1use crate::byron::{ByronAddress, ByronAddressError};
2use crate::genesis::network_info::NetworkInfo;
3use bech32::ToBase32;
4use cbor_event::{de::Deserializer, se::Serializer};
5use derivative::Derivative;
6use schemars::JsonSchema;
7use std::convert::{TryFrom, TryInto};
8use std::io::{BufRead, Write};
9
10#[cfg(not(feature = "used_from_wasm"))]
11use noop_proc_macro::wasm_bindgen;
12#[cfg(feature = "used_from_wasm")]
13use wasm_bindgen::prelude::wasm_bindgen;
14
15use cml_crypto::{Ed25519KeyHash, ScriptHash};
16
17use crate::certs::StakeCredential;
18
19use cml_core::{
20 error::{DeserializeError, DeserializeFailure},
21 serialization::{Deserialize, LenEncoding, Serialize, StringEncoding},
22 CertificateIndex, Slot, TransactionIndex,
23};
24
25fn variable_nat_decode(bytes: &[u8]) -> Option<(num_bigint::BigUint, usize)> {
28 let mut output = num_bigint::BigUint::from(0u64);
29 let mut bytes_read = 0;
30 for byte in bytes {
31 output = (output * 128u8) + (byte & 0x7F);
32 bytes_read += 1;
33 if (byte & 0x80) == 0 {
34 return Some((output, bytes_read));
35 }
36 }
37 None
38}
39
40fn variable_nat_encode(mut num: num_bigint::BigUint) -> Vec<u8> {
41 use num_integer::Integer;
42 let zero = num_bigint::BigUint::from(0u64);
43 let divider = num_bigint::BigUint::from(128u64);
44 let (next, chunk) = num.div_rem(÷r);
45 let chunk_byte: u8 = chunk.try_into().unwrap();
46 let mut output = vec![chunk_byte];
47 num = next;
48 while num > zero {
49 let (next, chunk) = num.div_rem(÷r);
50 let chunk_byte: u8 = chunk.try_into().unwrap();
51 num = next;
52 output.push(chunk_byte | 0x80);
53 }
54 output.reverse();
55 output
56}
57
58#[wasm_bindgen]
59#[derive(Clone, Copy, Debug, Eq, Ord, PartialEq, PartialOrd)]
60pub enum AddressKind {
61 Base,
62 Ptr,
63 Enterprise,
64 Reward,
65 Byron,
66}
67
68#[derive(Debug, thiserror::Error)]
69pub enum AddressError {
70 #[error("Bech32: {0}")]
71 Bech32(#[from] bech32::Error),
72 #[error("ByronError: {0}")]
73 Byron(#[from] ByronAddressError),
74 #[error("CBOR: {0}")]
75 CBOR(#[from] DeserializeError),
76 #[error("WrongKind: {:?}", 0)]
77 WrongKind(AddressKind),
78}
79
80#[derive(Debug, Clone, Eq, Ord, PartialEq, PartialOrd, Hash)]
81pub enum Address {
82 Base(BaseAddress),
83 Ptr(PointerAddress),
84 Enterprise(EnterpriseAddress),
85 Reward(RewardAddress),
86 Byron(ByronAddress),
87}
88
89impl serde::Serialize for Address {
90 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
91 where
92 S: serde::Serializer,
93 {
94 let bech32 = self
95 .to_bech32(None)
96 .map_err(|e| serde::ser::Error::custom(format!("to_bech32: {e:?}")))?;
97 serializer.serialize_str(&bech32)
98 }
99}
100
101impl<'de> serde::de::Deserialize<'de> for Address {
102 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
103 where
104 D: serde::de::Deserializer<'de>,
105 {
106 let bech32 = <String as serde::de::Deserialize>::deserialize(deserializer)?;
107 Address::from_bech32(&bech32).map_err(|_e| {
108 serde::de::Error::invalid_value(
109 serde::de::Unexpected::Str(&bech32),
110 &"bech32 address string",
111 )
112 })
113 }
114}
115
116impl JsonSchema for Address {
117 fn schema_name() -> String {
118 String::from("Address")
119 }
120 fn json_schema(gen: &mut schemars::gen::SchemaGenerator) -> schemars::schema::Schema {
121 String::json_schema(gen)
122 }
123 fn is_referenceable() -> bool {
124 String::is_referenceable()
125 }
126}
127
128#[wasm_bindgen]
132#[derive(Clone, Copy, Debug, Eq, Ord, PartialEq, PartialOrd)]
133#[repr(u8)]
134pub enum AddressHeaderKind {
135 BasePaymentKeyStakeKey = 0b0000,
137 BasePaymentScriptStakeKey = 0b0001,
138 BasePaymentKeyStakeScript = 0b0010,
139 BasePaymentScriptStakeScript = 0b0011,
140 PointerKey = 0b0100,
141 PointerScript = 0b0101,
142 EnterpriseKey = 0b0110,
143 EnterpriseScript = 0b0111,
144 Byron = 0b1000,
145 RewardKey = 0b1110,
146 RewardScript = 0b1111,
147}
148
149impl Address {
150 pub fn header(&self) -> u8 {
178 fn stake_cred_bit(cred: &StakeCredential) -> u8 {
179 match cred {
180 StakeCredential::PubKey { .. } => 0,
181 StakeCredential::Script { .. } => 1,
182 }
183 }
184 match self {
185 Self::Base(base) => {
186 (stake_cred_bit(&base.payment) << 4)
187 | (stake_cred_bit(&base.stake) << 5)
188 | (base.network & 0xF)
189 }
190 Self::Ptr(ptr) => {
191 0b0100_0000 | (stake_cred_bit(&ptr.payment) << 4) | (ptr.network & 0xF)
192 }
193 Self::Enterprise(enterprise) => {
194 0b0110_0000
195 | (stake_cred_bit(&enterprise.payment) << 4)
196 | (enterprise.network & 0xF)
197 }
198 Self::Byron(_) => 0b1000 << 4, Self::Reward(reward) => {
200 0b1110_0000 | (stake_cred_bit(&reward.payment) << 4) | (reward.network & 0xF)
201 }
202 }
203 }
204
205 pub fn header_matches_kind(header: u8, kind: AddressHeaderKind) -> bool {
206 (header >> 4) == kind as u8
207 }
208
209 pub fn to_hex(&self) -> String {
210 hex::encode(self.to_raw_bytes())
211 }
212
213 pub fn from_hex(hex: &str) -> Result<Address, DeserializeError> {
214 hex::decode(hex)
215 .map_err(|e| DeserializeFailure::InvalidStructure(Box::new(e)).into())
216 .and_then(|bytes| Self::from_raw_bytes(&bytes))
217 }
218
219 pub fn to_raw_bytes(&self) -> Vec<u8> {
221 let mut buf = Vec::new();
222 match self {
223 Self::Base(base) => {
224 buf.push(self.header());
225 buf.extend(base.payment.to_raw_bytes());
226 buf.extend(base.stake.to_raw_bytes());
227 }
228 Self::Ptr(ptr) => {
229 buf.push(self.header());
230 buf.extend(ptr.payment.to_raw_bytes());
231 buf.extend(variable_nat_encode(ptr.stake.slot.clone()));
232 buf.extend(variable_nat_encode(ptr.stake.tx_index.clone()));
233 buf.extend(variable_nat_encode(ptr.stake.cert_index.clone()));
234 }
235 Self::Enterprise(enterprise) => {
236 buf.push(self.header());
237 buf.extend(enterprise.payment.to_raw_bytes());
238 }
239 Self::Reward(reward) => {
240 buf.push(self.header());
241 buf.extend(reward.payment.to_raw_bytes());
242 }
243 Self::Byron(byron) => {
244 use cml_core::serialization::ToBytes;
245 buf.extend(byron.to_bytes())
246 }
247 }
248 if let Some(Some(trailing_bytes)) = self.encoding().map(|enc| &enc.trailing) {
249 buf.extend(trailing_bytes.iter());
250 }
251 buf
252 }
253
254 pub fn from_raw_bytes(data: &[u8]) -> Result<Address, DeserializeError> {
255 Self::from_bytes_impl(data, None)
256 }
257
258 pub(crate) fn from_bytes_impl(
259 data: &[u8],
260 bytes_encoding: Option<StringEncoding>,
261 ) -> Result<Address, DeserializeError> {
262 const TRAILING_WHITELIST: [&[u8]; 8] = [
263 &[
264 203, 87, 175, 176, 179, 95, 200, 156, 99, 6, 28, 153, 20, 224, 85, 0, 26, 81, 140,
265 117, 22,
266 ],
267 &[
268 19, 213, 244, 163, 254, 4, 120, 178, 36, 30, 1, 104, 227, 203, 165, 0, 26, 34, 193,
269 90, 17,
270 ],
271 &[0],
272 &[
273 106, 51, 48, 102, 53, 97, 109, 107, 119, 104, 119, 113, 97, 52, 119, 118, 102, 121,
274 106, 100, 101, 122, 121, 97, 101, 108, 109, 110, 110, 103, 100, 54, 100, 52, 101,
275 ],
276 &[
277 53, 97, 99, 121, 50, 114, 48, 101, 107, 114, 112, 113, 122, 113, 106, 108, 113,
278 100, 107, 56, 108, 122, 113, 110, 53, 114, 52, 53, 110,
279 ],
280 &[
281 6, 29, 7, 12, 13, 4, 27, 7, 2, 15, 11, 13, 11, 15, 2, 9, 18, 5, 29, 28, 16, 9, 17,
282 4, 14, 31, 7, 19, 17, 3, 1, 0, 11, 16, 22, 0,
283 ],
284 &[
285 18, 110, 119, 53, 51, 53, 103, 54, 118, 115, 112, 55, 120, 55, 102, 104, 120, 112,
286 113, 50, 112, 116, 115, 104, 57, 103, 107, 114,
287 ],
288 &[44],
289 ];
290 (|| -> Result<Self, DeserializeError> {
291 let header = data[0];
292 let network = header & 0x0F;
293 const HASH_LEN: usize = Ed25519KeyHash::BYTE_COUNT;
294 assert_eq!(ScriptHash::BYTE_COUNT, HASH_LEN);
296 let read_addr_cred = |bit: u8, pos: usize| {
298 let hash_bytes: [u8; HASH_LEN] = data[pos..pos + HASH_LEN].try_into().unwrap();
299 if header & (1 << bit) == 0 {
300 StakeCredential::new_pub_key(Ed25519KeyHash::from(hash_bytes))
301 } else {
302 StakeCredential::new_script(ScriptHash::from(hash_bytes))
303 }
304 };
305 fn make_encoding(
306 bytes_encoding: Option<StringEncoding>,
307 trailing: Option<Vec<u8>>,
308 ) -> Result<Option<AddressEncoding>, DeserializeError> {
309 if trailing.is_some() || bytes_encoding.is_some() {
310 if let Some(trailing) = &trailing {
311 let mut found = false;
312 for ending in TRAILING_WHITELIST.iter() {
313 if trailing.as_slice() == *ending {
314 found = true;
315 }
316 }
317 if !found {
318 return Err(cbor_event::Error::TrailingData.into());
319 }
320 }
321 Ok(Some(AddressEncoding {
322 trailing,
323 bytes_encoding: bytes_encoding.unwrap_or_default(),
324 }))
325 } else {
326 Ok(None)
327 }
328 }
329 fn len_check_trailing(
330 data: &[u8],
331 addr_size: usize,
332 ) -> Result<Option<Vec<u8>>, DeserializeFailure> {
333 match data.len().cmp(&addr_size) {
334 std::cmp::Ordering::Less => Err(DeserializeFailure::CBOR(
335 cbor_event::Error::NotEnough(data.len(), addr_size),
336 )),
337 std::cmp::Ordering::Greater => Ok(Some(data[addr_size..].to_vec())),
338 std::cmp::Ordering::Equal => Ok(None),
339 }
340 }
341 match (header & 0xF0) >> 4 {
342 #[allow(clippy::manual_range_patterns)]
344 0b0000 | 0b0001 | 0b0010 | 0b0011 => {
345 const BASE_ADDR_SIZE: usize = 1 + HASH_LEN * 2;
346 let trailing = len_check_trailing(data, BASE_ADDR_SIZE)?;
347 Ok(Address::Base(BaseAddress {
348 network,
349 payment: read_addr_cred(4, 1),
350 stake: read_addr_cred(5, 1 + HASH_LEN),
351 encoding: make_encoding(bytes_encoding, trailing)?,
352 }))
353 }
354 0b0100 | 0b0101 => {
356 const PTR_ADDR_MIN_SIZE: usize = 1 + HASH_LEN + 1 + 1 + 1;
358 if data.len() < PTR_ADDR_MIN_SIZE {
359 return Err(
361 cbor_event::Error::NotEnough(data.len(), PTR_ADDR_MIN_SIZE).into()
362 );
363 }
364 let mut byte_index = 1;
365 let payment_cred = read_addr_cred(4, 1);
366 byte_index += HASH_LEN;
367 let (slot, slot_bytes) =
368 variable_nat_decode(&data[byte_index..]).ok_or_else(|| {
369 DeserializeError::new(
370 "Address.Pointer.slot",
371 DeserializeFailure::VariableLenNatDecodeFailed,
372 )
373 })?;
374 byte_index += slot_bytes;
375 let (tx_index, tx_bytes) = variable_nat_decode(&data[byte_index..])
376 .ok_or_else(|| {
377 DeserializeError::new(
378 "Address.Pointer.tx_index",
379 DeserializeFailure::VariableLenNatDecodeFailed,
380 )
381 })?;
382 byte_index += tx_bytes;
383 let (cert_index, cert_bytes) = variable_nat_decode(&data[byte_index..])
384 .ok_or_else(|| {
385 DeserializeError::new(
386 "Address.Pointer.cert_index",
387 DeserializeFailure::VariableLenNatDecodeFailed,
388 )
389 })?;
390 byte_index += cert_bytes;
391 let trailing = if byte_index < data.len() {
392 Some(data[byte_index..].to_vec())
393 } else {
394 None
395 };
396 Ok(Address::Ptr(PointerAddress {
397 network,
398 payment: payment_cred,
399 stake: Pointer {
400 slot,
401 tx_index,
402 cert_index,
403 },
404 encoding: make_encoding(bytes_encoding, trailing)?,
405 }))
406 }
407 0b0110 | 0b0111 => {
409 const ENTERPRISE_ADDR_SIZE: usize = 1 + HASH_LEN;
410 let trailing = len_check_trailing(data, ENTERPRISE_ADDR_SIZE)?;
411 Ok(Address::Enterprise(EnterpriseAddress {
412 network,
413 payment: read_addr_cred(4, 1),
414 encoding: make_encoding(bytes_encoding, trailing)?,
415 }))
416 }
417 0b1110 | 0b1111 => {
419 const REWARD_ADDR_SIZE: usize = 1 + HASH_LEN;
420 let trailing = len_check_trailing(data, REWARD_ADDR_SIZE)?;
421 Ok(Address::Reward(RewardAddress {
422 network,
423 payment: read_addr_cred(4, 1),
424 encoding: make_encoding(bytes_encoding, trailing)?,
425 }))
426 }
427 0b1000 => {
429 ByronAddress::from_cbor_bytes(data)
432 .map(Address::Byron)
433 .map_err(|e| DeserializeFailure::InvalidStructure(Box::new(e)).into())
434 }
435 _ => Err(DeserializeFailure::BadAddressType(header).into()),
436 }
437 })()
438 .map_err(|e| e.annotate("Address"))
439 }
440
441 pub fn to_bech32(&self, prefix: Option<String>) -> Result<String, AddressError> {
442 let final_prefix = match prefix {
443 Some(prefix) => prefix,
444 None => {
445 let prefix_header = match self {
447 Self::Reward(_) => "stake",
448 _ => "addr",
449 };
450 let prefix_tail = match self.network_id()? {
451 id if id == NetworkInfo::testnet().network_id() => "_test",
452 _ => "",
453 };
454 format!("{prefix_header}{prefix_tail}")
455 }
456 };
457 bech32::encode(&final_prefix, self.to_raw_bytes().to_base32()).map_err(|e| e.into())
458 }
459
460 pub fn from_bech32(bech_str: &str) -> Result<Address, AddressError> {
461 let (_hrp, u5data) = bech32::decode(bech_str)?;
462 let data: Vec<u8> = bech32::FromBase32::from_base32(&u5data).unwrap();
463 Ok(Self::from_bytes_impl(data.as_ref(), None)?)
464 }
465
466 pub fn is_valid_bech32(bech_str: &str) -> bool {
470 match Self::from_bech32(bech_str) {
471 Ok(_v) => true,
472 Err(_err) => false,
473 }
474 }
475
476 pub fn is_valid_byron(base58: &str) -> bool {
477 ByronAddress::is_valid(base58)
478 }
479
480 pub fn is_valid(bech_str: &str) -> bool {
481 Self::is_valid_bech32(bech_str) || Self::is_valid_byron(bech_str)
482 }
483
484 pub fn kind(&self) -> AddressKind {
485 match self {
486 Self::Base(_) => AddressKind::Base,
487 Self::Byron(_) => AddressKind::Byron,
488 Self::Enterprise(_) => AddressKind::Enterprise,
489 Self::Ptr(_) => AddressKind::Ptr,
490 Self::Reward(_) => AddressKind::Reward,
491 }
492 }
493
494 pub fn network_id(&self) -> Result<u8, AddressError> {
495 match self {
496 Self::Base(a) => Ok(a.network),
497 Self::Enterprise(a) => Ok(a.network),
498 Self::Ptr(a) => Ok(a.network),
499 Self::Reward(a) => Ok(a.network),
500 Self::Byron(a) => a.content.network_id().map_err(Into::into),
501 }
502 }
503
504 pub fn payment_cred(&self) -> Option<&StakeCredential> {
506 match self {
507 Self::Base(a) => Some(&a.payment),
508 Self::Enterprise(a) => Some(&a.payment),
509 Self::Ptr(a) => Some(&a.payment),
510 Self::Reward(a) => Some(&a.payment),
511 Self::Byron(_) => None,
512 }
513 }
514
515 pub fn staking_cred(&self) -> Option<&StakeCredential> {
518 match self {
519 Self::Base(a) => Some(&a.stake),
520 Self::Enterprise(_) => None,
521 Self::Ptr(_) => None,
522 Self::Reward(_) => None,
523 Self::Byron(_) => None,
524 }
525 }
526
527 pub(crate) fn encoding(&self) -> Option<&AddressEncoding> {
528 match self {
529 Self::Base(a) => a.encoding.as_ref(),
530 Self::Enterprise(a) => a.encoding.as_ref(),
531 Self::Ptr(a) => a.encoding.as_ref(),
532 Self::Reward(a) => a.encoding.as_ref(),
533 Self::Byron(_a) => None,
535 }
536 }
537}
538
539#[derive(Debug, Clone, Derivative)]
540#[derivative(Eq, PartialEq, Ord, PartialOrd, Hash)]
541pub struct BaseAddress {
542 pub network: u8,
543 pub payment: StakeCredential,
544 pub stake: StakeCredential,
545 #[derivative(
546 PartialEq = "ignore",
547 Ord = "ignore",
548 PartialOrd = "ignore",
549 Hash = "ignore"
550 )]
551 pub(crate) encoding: Option<AddressEncoding>,
552}
553
554impl BaseAddress {
555 pub fn new(network: u8, payment: StakeCredential, stake: StakeCredential) -> Self {
556 Self {
557 network,
558 payment,
559 stake,
560 encoding: None,
561 }
562 }
563
564 pub fn to_address(self) -> Address {
565 self.into()
566 }
567
568 pub fn from_address(addr: &Address) -> Option<Self> {
569 match addr {
570 Address::Base(base) => Some(base.clone()),
571 _ => None,
572 }
573 }
574}
575
576impl TryFrom<Address> for BaseAddress {
577 type Error = AddressError;
578
579 fn try_from(addr: Address) -> Result<Self, Self::Error> {
580 match addr {
581 Address::Base(base) => Ok(base),
582 _ => Err(AddressError::WrongKind(addr.kind())),
583 }
584 }
585}
586
587impl From<BaseAddress> for Address {
588 fn from(enterprise: BaseAddress) -> Self {
589 Self::Base(enterprise)
590 }
591}
592
593#[derive(Debug, Clone, Derivative)]
594#[derivative(Eq, PartialEq, Ord, PartialOrd, Hash)]
595pub struct EnterpriseAddress {
596 pub network: u8,
597 pub payment: StakeCredential,
598 #[derivative(
599 PartialEq = "ignore",
600 Ord = "ignore",
601 PartialOrd = "ignore",
602 Hash = "ignore"
603 )]
604 pub(crate) encoding: Option<AddressEncoding>,
605}
606
607impl EnterpriseAddress {
608 pub fn new(network: u8, payment: StakeCredential) -> Self {
609 Self {
610 network,
611 payment,
612 encoding: None,
613 }
614 }
615
616 pub fn to_address(self) -> Address {
617 self.into()
618 }
619
620 pub fn from_address(addr: &Address) -> Option<Self> {
621 match addr {
622 Address::Enterprise(enterprise) => Some(enterprise.clone()),
623 _ => None,
624 }
625 }
626}
627
628impl TryFrom<Address> for EnterpriseAddress {
629 type Error = AddressError;
630
631 fn try_from(addr: Address) -> Result<Self, Self::Error> {
632 match addr {
633 Address::Enterprise(enterprise) => Ok(enterprise),
634 _ => Err(AddressError::WrongKind(addr.kind())),
635 }
636 }
637}
638
639impl From<EnterpriseAddress> for Address {
640 fn from(enterprise: EnterpriseAddress) -> Self {
641 Self::Enterprise(enterprise)
642 }
643}
644
645pub type RewardAccount = RewardAddress;
646
647#[derive(Debug, Clone, Derivative)]
648#[derivative(Eq, PartialEq, Ord, PartialOrd, Hash)]
649pub struct RewardAddress {
650 pub network: u8,
651 pub payment: StakeCredential,
652 #[derivative(
653 PartialEq = "ignore",
654 Ord = "ignore",
655 PartialOrd = "ignore",
656 Hash = "ignore"
657 )]
658 pub(crate) encoding: Option<AddressEncoding>,
659}
660
661impl RewardAddress {
662 pub fn new(network: u8, payment: StakeCredential) -> Self {
663 Self {
664 network,
665 payment,
666 encoding: None,
667 }
668 }
669
670 pub fn to_address(self) -> Address {
671 self.into()
672 }
673
674 pub fn from_address(addr: &Address) -> Option<Self> {
675 match addr {
676 Address::Reward(reward) => Some(reward.clone()),
677 _ => None,
678 }
679 }
680}
681
682impl TryFrom<Address> for RewardAddress {
683 type Error = AddressError;
684
685 fn try_from(addr: Address) -> Result<Self, Self::Error> {
686 match addr {
687 Address::Reward(reward) => Ok(reward),
688 _ => Err(AddressError::WrongKind(addr.kind())),
689 }
690 }
691}
692
693impl From<RewardAddress> for Address {
694 fn from(reward: RewardAddress) -> Self {
695 Self::Reward(reward)
696 }
697}
698
699impl serde::Serialize for RewardAddress {
700 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
701 where
702 S: serde::Serializer,
703 {
704 let bech32 = self
705 .clone()
706 .to_address()
707 .to_bech32(None)
708 .map_err(|e| serde::ser::Error::custom(format!("to_bech32: {e:?}")))?;
709 serializer.serialize_str(&bech32)
710 }
711}
712
713impl<'de> serde::de::Deserialize<'de> for RewardAddress {
714 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
715 where
716 D: serde::de::Deserializer<'de>,
717 {
718 let bech32 = <String as serde::de::Deserialize>::deserialize(deserializer)?;
719 match Address::from_bech32(&bech32)
720 .ok()
721 .map(|addr| RewardAddress::from_address(&addr))
722 {
723 Some(Some(ra)) => Ok(ra),
724 _ => Err(serde::de::Error::invalid_value(
725 serde::de::Unexpected::Str(&bech32),
726 &"bech32 reward address string",
727 )),
728 }
729 }
730}
731
732impl JsonSchema for RewardAddress {
733 fn schema_name() -> String {
734 String::from("RewardAddress")
735 }
736 fn json_schema(gen: &mut schemars::gen::SchemaGenerator) -> schemars::schema::Schema {
737 String::json_schema(gen)
738 }
739 fn is_referenceable() -> bool {
740 String::is_referenceable()
741 }
742}
743
744#[derive(Debug, Clone, Eq, Ord, PartialEq, PartialOrd, Hash)]
745pub struct Pointer {
746 slot: num_bigint::BigUint,
747 tx_index: num_bigint::BigUint,
748 cert_index: num_bigint::BigUint,
749}
750
751impl Pointer {
752 pub fn new(slot: Slot, tx_index: TransactionIndex, cert_index: CertificateIndex) -> Self {
753 Self {
754 slot: num_bigint::BigUint::from(slot),
755 tx_index: num_bigint::BigUint::from(tx_index),
756 cert_index: num_bigint::BigUint::from(cert_index),
757 }
758 }
759
760 pub fn slot(&self) -> Slot {
762 self.slot.clone().try_into().unwrap_or(u64::MAX)
763 }
764
765 pub fn tx_index(&self) -> Slot {
767 self.tx_index.clone().try_into().unwrap_or(u64::MAX)
768 }
769
770 pub fn cert_index(&self) -> Slot {
772 self.cert_index.clone().try_into().unwrap_or(u64::MAX)
773 }
774}
775
776#[derive(Debug, Clone, Derivative)]
777#[derivative(Eq, PartialEq, Ord, PartialOrd, Hash)]
778pub struct PointerAddress {
779 pub network: u8,
780 pub payment: StakeCredential,
781 pub stake: Pointer,
782 #[derivative(
783 PartialEq = "ignore",
784 Ord = "ignore",
785 PartialOrd = "ignore",
786 Hash = "ignore"
787 )]
788 pub(crate) encoding: Option<AddressEncoding>,
789}
790
791impl PointerAddress {
792 pub fn new(network: u8, payment: StakeCredential, stake: Pointer) -> Self {
793 Self {
794 network,
795 payment,
796 stake,
797 encoding: None,
798 }
799 }
800
801 pub fn to_address(self) -> Address {
802 self.into()
803 }
804
805 pub fn from_address(addr: &Address) -> Option<Self> {
806 match addr {
807 Address::Ptr(pointer) => Some(pointer.clone()),
808 _ => None,
809 }
810 }
811}
812
813impl TryFrom<Address> for PointerAddress {
814 type Error = AddressError;
815
816 fn try_from(addr: Address) -> Result<Self, Self::Error> {
817 match addr {
818 Address::Ptr(pointer) => Ok(pointer),
819 _ => Err(AddressError::WrongKind(addr.kind())),
820 }
821 }
822}
823
824impl From<PointerAddress> for Address {
825 fn from(pointer: PointerAddress) -> Self {
826 Self::Ptr(pointer)
827 }
828}
829
830#[derive(Clone, Debug)]
832pub struct AddressEncoding {
833 pub(crate) trailing: Option<Vec<u8>>,
835 pub(crate) bytes_encoding: StringEncoding,
836}
837
838#[derive(Clone, Debug, Default)]
839pub struct StakeCredentialEncoding {
840 pub len_encoding: LenEncoding,
841 pub index_0_encoding: Option<cbor_event::Sz>,
842}
843
844impl Serialize for Address {
845 fn serialize<'se, W: Write>(
846 &self,
847 serializer: &'se mut Serializer<W>,
848 force_canonical: bool,
849 ) -> cbor_event::Result<&'se mut Serializer<W>> {
850 let raw_bytes = self.to_raw_bytes();
851 serializer.write_bytes_sz(
852 &raw_bytes,
853 self.encoding()
854 .map(|encs| encs.bytes_encoding.clone())
855 .unwrap_or_default()
856 .to_str_len_sz(raw_bytes.len() as u64, force_canonical),
857 )
858 }
859}
860
861impl Deserialize for Address {
862 fn deserialize<R: BufRead>(raw: &mut Deserializer<R>) -> Result<Self, DeserializeError> {
863 let (raw_bytes, encoding) = raw.bytes_sz()?;
864 Self::from_bytes_impl(raw_bytes.as_ref(), Some(encoding.into()))
865 }
866}
867
868impl Serialize for RewardAccount {
869 fn serialize<'se, W: Write>(
870 &self,
871 serializer: &'se mut Serializer<W>,
872 force_canonical: bool,
873 ) -> cbor_event::Result<&'se mut Serializer<W>> {
874 Address::from(self.clone()).serialize(serializer, force_canonical)
875 }
876}
877
878impl Deserialize for RewardAccount {
879 fn deserialize<R: BufRead>(raw: &mut Deserializer<R>) -> Result<Self, DeserializeError> {
880 let (raw_bytes, encoding) = raw.bytes_sz()?;
881 match Address::from_bytes_impl(raw_bytes.as_ref(), Some(encoding.into()))? {
882 Address::Reward(reward_address) => Ok(reward_address),
883 _ => Err(DeserializeFailure::BadAddressType(raw_bytes[0]).into()),
885 }
886 }
887}
888
889#[cfg(test)]
890mod tests {
891 use crate::{byron::AddressContent, transaction::NativeScript};
892
893 use super::*;
894 use cml_core::serialization::ToBytes;
895 use cml_crypto::*;
896
897 #[test]
898 fn variable_nat_encoding() {
899 let cases = [0u64, 127u64, 128u64, 255u64, 256275757658493284u64];
900 for case in cases.iter() {
901 let case_biguint = num_bigint::BigUint::from(*case);
902 let encoded = variable_nat_encode(case_biguint.clone());
903 let decoded = variable_nat_decode(&encoded).unwrap().0;
904 assert_eq!(case_biguint, decoded);
905 }
906 }
907
908 #[test]
909 fn base_serialize_consistency() {
910 let base = BaseAddress::new(
911 5,
912 StakeCredential::new_pub_key(Ed25519KeyHash::from([23; Ed25519KeyHash::BYTE_COUNT])),
913 StakeCredential::new_script(ScriptHash::from([42; ScriptHash::BYTE_COUNT])),
914 );
915 let addr = base.to_address();
916 let addr2 = Address::from_cbor_bytes(&addr.to_cbor_bytes()).unwrap();
917 assert_eq!(addr.to_cbor_bytes(), addr2.to_cbor_bytes());
918 }
919
920 #[test]
921 fn ptr_serialize_consistency() {
922 let ptr = PointerAddress::new(
923 25,
924 StakeCredential::new_pub_key(Ed25519KeyHash::from([23; Ed25519KeyHash::BYTE_COUNT])),
925 Pointer::new(2354556573, 127, 0),
926 );
927 let addr = ptr.to_address();
928 let addr2 = Address::from_cbor_bytes(&addr.to_cbor_bytes()).unwrap();
929 assert_eq!(addr.to_cbor_bytes(), addr2.to_cbor_bytes());
930 }
931
932 #[test]
933 fn enterprise_serialize_consistency() {
934 let enterprise = EnterpriseAddress::new(
935 64,
936 StakeCredential::new_pub_key(Ed25519KeyHash::from([23; Ed25519KeyHash::BYTE_COUNT])),
937 );
938 let addr = enterprise.to_address();
939 let addr2 = Address::from_cbor_bytes(&addr.to_cbor_bytes()).unwrap();
940 assert_eq!(addr.to_cbor_bytes(), addr2.to_cbor_bytes());
941 }
942
943 #[test]
944 fn reward_serialize_consistency() {
945 let reward = RewardAddress::new(
946 9,
947 StakeCredential::new_script(ScriptHash::from([127; Ed25519KeyHash::BYTE_COUNT])),
948 );
949 let addr = reward.to_address();
950 let addr2 = Address::from_cbor_bytes(&addr.to_cbor_bytes()).unwrap();
951 assert_eq!(addr.to_cbor_bytes(), addr2.to_cbor_bytes());
952 }
953
954 #[test]
955 fn address_header_matching() {
956 let reward = RewardAddress::new(
957 0b1001,
958 StakeCredential::new_script(ScriptHash::from([127; Ed25519KeyHash::BYTE_COUNT])),
959 )
960 .to_address();
961 assert_eq!(reward.header(), 0b1111_1001);
962 assert!(Address::header_matches_kind(
963 reward.header(),
964 AddressHeaderKind::RewardScript
965 ))
966 }
967
968 fn root_key_12() -> Bip32PrivateKey {
969 let entropy = [
971 0xdf, 0x9e, 0xd2, 0x5e, 0xd1, 0x46, 0xbf, 0x43, 0x33, 0x6a, 0x5d, 0x7c, 0xf7, 0x39,
972 0x59, 0x94,
973 ];
974 Bip32PrivateKey::from_bip39_entropy(&entropy, &[])
975 }
976
977 fn root_key_15() -> Bip32PrivateKey {
978 let entropy = [
980 0x0c, 0xcb, 0x74, 0xf3, 0x6b, 0x7d, 0xa1, 0x64, 0x9a, 0x81, 0x44, 0x67, 0x55, 0x22,
981 0xd4, 0xd8, 0x09, 0x7c, 0x64, 0x12,
982 ];
983 Bip32PrivateKey::from_bip39_entropy(&entropy, &[])
984 }
985
986 fn root_key_24() -> Bip32PrivateKey {
987 let entropy = [
988 0x4e, 0x82, 0x8f, 0x9a, 0x67, 0xdd, 0xcf, 0xf0, 0xe6, 0x39, 0x1a, 0xd4, 0xf2, 0x6d,
989 0xdb, 0x75, 0x79, 0xf5, 0x9b, 0xa1, 0x4b, 0x6d, 0xd4, 0xba, 0xf6, 0x3d, 0xcf, 0xdb,
990 0x9d, 0x24, 0x20, 0xda,
991 ];
992 Bip32PrivateKey::from_bip39_entropy(&entropy, &[])
993 }
994
995 fn harden(index: u32) -> u32 {
996 index | 0x80_00_00_00
997 }
998
999 #[test]
1000 fn bech32_parsing() {
1001 let addr =
1002 Address::from_bech32("addr1u8pcjgmx7962w6hey5hhsd502araxp26kdtgagakhaqtq8sxy9w7g")
1003 .unwrap();
1004 assert_eq!(
1005 addr.to_bech32(Some("foobar".to_string())).unwrap(),
1006 "foobar1u8pcjgmx7962w6hey5hhsd502araxp26kdtgagakhaqtq8s92n4tm"
1007 );
1008 }
1009
1010 #[test]
1011 fn bip32_12_base() {
1012 let spend = root_key_12()
1013 .derive(harden(1852))
1014 .derive(harden(1815))
1015 .derive(harden(0))
1016 .derive(0)
1017 .derive(0)
1018 .to_public();
1019 let stake = root_key_12()
1020 .derive(harden(1852))
1021 .derive(harden(1815))
1022 .derive(harden(0))
1023 .derive(2)
1024 .derive(0)
1025 .to_public();
1026 let spend_cred = StakeCredential::new_pub_key(spend.to_raw_key().hash());
1027 let stake_cred = StakeCredential::new_pub_key(stake.to_raw_key().hash());
1028 let addr_net_0 = BaseAddress::new(
1029 NetworkInfo::testnet().network_id(),
1030 spend_cred.clone(),
1031 stake_cred.clone(),
1032 )
1033 .to_address();
1034 assert_eq!(addr_net_0.to_bech32(None).unwrap(), "addr_test1qz2fxv2umyhttkxyxp8x0dlpdt3k6cwng5pxj3jhsydzer3jcu5d8ps7zex2k2xt3uqxgjqnnj83ws8lhrn648jjxtwq2ytjqp");
1035 let addr_net_3 =
1036 BaseAddress::new(NetworkInfo::mainnet().network_id(), spend_cred, stake_cred)
1037 .to_address();
1038 assert_eq!(addr_net_3.to_bech32(None).unwrap(), "addr1qx2fxv2umyhttkxyxp8x0dlpdt3k6cwng5pxj3jhsydzer3jcu5d8ps7zex2k2xt3uqxgjqnnj83ws8lhrn648jjxtwqfjkjv7");
1039 }
1040
1041 #[test]
1042 fn bip32_12_enterprise() {
1043 let spend = root_key_12()
1044 .derive(harden(1852))
1045 .derive(harden(1815))
1046 .derive(harden(0))
1047 .derive(0)
1048 .derive(0)
1049 .to_public();
1050 let spend_cred = StakeCredential::new_pub_key(spend.to_raw_key().hash());
1051 let addr_net_0 =
1052 EnterpriseAddress::new(NetworkInfo::testnet().network_id(), spend_cred.clone())
1053 .to_address();
1054 assert_eq!(
1055 addr_net_0.to_bech32(None).unwrap(),
1056 "addr_test1vz2fxv2umyhttkxyxp8x0dlpdt3k6cwng5pxj3jhsydzerspjrlsz"
1057 );
1058 let addr_net_3 =
1059 EnterpriseAddress::new(NetworkInfo::mainnet().network_id(), spend_cred).to_address();
1060 assert_eq!(
1061 addr_net_3.to_bech32(None).unwrap(),
1062 "addr1vx2fxv2umyhttkxyxp8x0dlpdt3k6cwng5pxj3jhsydzers66hrl8"
1063 );
1064 }
1065
1066 #[test]
1067 fn bip32_12_pointer() {
1068 let spend = root_key_12()
1069 .derive(harden(1852))
1070 .derive(harden(1815))
1071 .derive(harden(0))
1072 .derive(0)
1073 .derive(0)
1074 .to_public();
1075 let spend_cred = StakeCredential::new_pub_key(spend.to_raw_key().hash());
1076 let addr_net_0 = PointerAddress::new(
1077 NetworkInfo::testnet().network_id(),
1078 spend_cred.clone(),
1079 Pointer::new(1, 2, 3),
1080 )
1081 .to_address();
1082 assert_eq!(
1083 addr_net_0.to_bech32(None).unwrap(),
1084 "addr_test1gz2fxv2umyhttkxyxp8x0dlpdt3k6cwng5pxj3jhsydzerspqgpsqe70et"
1085 );
1086 let addr_net_3 = PointerAddress::new(
1087 NetworkInfo::mainnet().network_id(),
1088 spend_cred,
1089 Pointer::new(24157, 177, 42),
1090 )
1091 .to_address();
1092 assert_eq!(
1093 addr_net_3.to_bech32(None).unwrap(),
1094 "addr1gx2fxv2umyhttkxyxp8x0dlpdt3k6cwng5pxj3jhsydzer5ph3wczvf2w8lunk"
1095 );
1096 }
1097
1098 #[test]
1099 fn bip32_15_base() {
1100 let spend = root_key_15()
1101 .derive(harden(1852))
1102 .derive(harden(1815))
1103 .derive(harden(0))
1104 .derive(0)
1105 .derive(0)
1106 .to_public();
1107 let stake = root_key_15()
1108 .derive(harden(1852))
1109 .derive(harden(1815))
1110 .derive(harden(0))
1111 .derive(2)
1112 .derive(0)
1113 .to_public();
1114 let spend_cred = StakeCredential::new_pub_key(spend.to_raw_key().hash());
1115 let stake_cred = StakeCredential::new_pub_key(stake.to_raw_key().hash());
1116 let addr_net_0 = BaseAddress::new(
1117 NetworkInfo::testnet().network_id(),
1118 spend_cred.clone(),
1119 stake_cred.clone(),
1120 )
1121 .to_address();
1122 assert_eq!(addr_net_0.to_bech32(None).unwrap(), "addr_test1qpu5vlrf4xkxv2qpwngf6cjhtw542ayty80v8dyr49rf5ewvxwdrt70qlcpeeagscasafhffqsxy36t90ldv06wqrk2qum8x5w");
1123 let addr_net_3 =
1124 BaseAddress::new(NetworkInfo::mainnet().network_id(), spend_cred, stake_cred)
1125 .to_address();
1126 assert_eq!(addr_net_3.to_bech32(None).unwrap(), "addr1q9u5vlrf4xkxv2qpwngf6cjhtw542ayty80v8dyr49rf5ewvxwdrt70qlcpeeagscasafhffqsxy36t90ldv06wqrk2qld6xc3");
1127 }
1128
1129 #[test]
1130 fn bip32_15_enterprise() {
1131 let spend = root_key_15()
1132 .derive(harden(1852))
1133 .derive(harden(1815))
1134 .derive(harden(0))
1135 .derive(0)
1136 .derive(0)
1137 .to_public();
1138 let spend_cred = StakeCredential::new_pub_key(spend.to_raw_key().hash());
1139 let addr_net_0 =
1140 EnterpriseAddress::new(NetworkInfo::testnet().network_id(), spend_cred.clone())
1141 .to_address();
1142 assert_eq!(
1143 addr_net_0.to_bech32(None).unwrap(),
1144 "addr_test1vpu5vlrf4xkxv2qpwngf6cjhtw542ayty80v8dyr49rf5eg57c2qv"
1145 );
1146 let addr_net_3 =
1147 EnterpriseAddress::new(NetworkInfo::mainnet().network_id(), spend_cred).to_address();
1148 assert_eq!(
1149 addr_net_3.to_bech32(None).unwrap(),
1150 "addr1v9u5vlrf4xkxv2qpwngf6cjhtw542ayty80v8dyr49rf5eg0kvk0f"
1151 );
1152 }
1153
1154 #[test]
1155 fn bip32_15_pointer() {
1156 let spend = root_key_15()
1157 .derive(harden(1852))
1158 .derive(harden(1815))
1159 .derive(harden(0))
1160 .derive(0)
1161 .derive(0)
1162 .to_public();
1163 let spend_cred = StakeCredential::new_pub_key(spend.to_raw_key().hash());
1164 let addr_net_0 = PointerAddress::new(
1165 NetworkInfo::testnet().network_id(),
1166 spend_cred.clone(),
1167 Pointer::new(1, 2, 3),
1168 )
1169 .to_address();
1170 assert_eq!(
1171 addr_net_0.to_bech32(None).unwrap(),
1172 "addr_test1gpu5vlrf4xkxv2qpwngf6cjhtw542ayty80v8dyr49rf5egpqgpsdhdyc0"
1173 );
1174 let addr_net_3 = PointerAddress::new(
1175 NetworkInfo::mainnet().network_id(),
1176 spend_cred,
1177 Pointer::new(24157, 177, 42),
1178 )
1179 .to_address();
1180 assert_eq!(
1181 addr_net_3.to_bech32(None).unwrap(),
1182 "addr1g9u5vlrf4xkxv2qpwngf6cjhtw542ayty80v8dyr49rf5evph3wczvf2kd5vam"
1183 );
1184 }
1185
1186 #[test]
1187 fn bip32_15_byron() {
1188 let byron_key = root_key_15()
1189 .derive(harden(44))
1190 .derive(harden(1815))
1191 .derive(harden(0))
1192 .derive(0)
1193 .derive(0)
1194 .to_public();
1195 let byron_addr =
1196 AddressContent::icarus_from_key(byron_key, NetworkInfo::mainnet().protocol_magic());
1197 assert_eq!(
1198 byron_addr.to_address().to_base58(),
1199 "Ae2tdPwUPEZHtBmjZBF4YpMkK9tMSPTE2ADEZTPN97saNkhG78TvXdp3GDk"
1200 );
1201 assert!(ByronAddress::is_valid(
1202 "Ae2tdPwUPEZHtBmjZBF4YpMkK9tMSPTE2ADEZTPN97saNkhG78TvXdp3GDk"
1203 ));
1204 assert_eq!(byron_addr.network_id().unwrap(), 0b0001);
1205
1206 let generic_addr = Address::from_raw_bytes(&byron_addr.to_address().to_bytes()).unwrap();
1208 let byron_addr_2 = ByronAddress::from_address(&generic_addr).unwrap();
1209 assert_eq!(
1210 byron_addr.to_address().to_base58(),
1211 byron_addr_2.to_base58()
1212 );
1213 }
1214
1215 #[test]
1216 fn bip32_24_base() {
1217 let spend = root_key_24()
1218 .derive(harden(1852))
1219 .derive(harden(1815))
1220 .derive(harden(0))
1221 .derive(0)
1222 .derive(0)
1223 .to_public();
1224 let stake = root_key_24()
1225 .derive(harden(1852))
1226 .derive(harden(1815))
1227 .derive(harden(0))
1228 .derive(2)
1229 .derive(0)
1230 .to_public();
1231 let spend_cred = StakeCredential::new_pub_key(spend.to_raw_key().hash());
1232 let stake_cred = StakeCredential::new_pub_key(stake.to_raw_key().hash());
1233 let addr_net_0 = BaseAddress::new(
1234 NetworkInfo::testnet().network_id(),
1235 spend_cred.clone(),
1236 stake_cred.clone(),
1237 )
1238 .to_address();
1239 assert_eq!(addr_net_0.to_bech32(None).unwrap(), "addr_test1qqy6nhfyks7wdu3dudslys37v252w2nwhv0fw2nfawemmn8k8ttq8f3gag0h89aepvx3xf69g0l9pf80tqv7cve0l33sw96paj");
1240 let addr_net_3 =
1241 BaseAddress::new(NetworkInfo::mainnet().network_id(), spend_cred, stake_cred)
1242 .to_address();
1243 assert_eq!(addr_net_3.to_bech32(None).unwrap(), "addr1qyy6nhfyks7wdu3dudslys37v252w2nwhv0fw2nfawemmn8k8ttq8f3gag0h89aepvx3xf69g0l9pf80tqv7cve0l33sdn8p3d");
1244 }
1245
1246 #[test]
1247 fn bip32_24_enterprise() {
1248 let spend = root_key_24()
1249 .derive(harden(1852))
1250 .derive(harden(1815))
1251 .derive(harden(0))
1252 .derive(0)
1253 .derive(0)
1254 .to_public();
1255 let spend_cred = StakeCredential::new_pub_key(spend.to_raw_key().hash());
1256 let addr_net_0 =
1257 EnterpriseAddress::new(NetworkInfo::testnet().network_id(), spend_cred.clone())
1258 .to_address();
1259 assert_eq!(
1260 addr_net_0.to_bech32(None).unwrap(),
1261 "addr_test1vqy6nhfyks7wdu3dudslys37v252w2nwhv0fw2nfawemmnqtjtf68"
1262 );
1263 let addr_net_3 =
1264 EnterpriseAddress::new(NetworkInfo::mainnet().network_id(), spend_cred).to_address();
1265 assert_eq!(
1266 addr_net_3.to_bech32(None).unwrap(),
1267 "addr1vyy6nhfyks7wdu3dudslys37v252w2nwhv0fw2nfawemmnqs6l44z"
1268 );
1269 }
1270
1271 #[test]
1272 fn bip32_24_pointer() {
1273 let spend = root_key_24()
1274 .derive(harden(1852))
1275 .derive(harden(1815))
1276 .derive(harden(0))
1277 .derive(0)
1278 .derive(0)
1279 .to_public();
1280 let spend_cred = StakeCredential::new_pub_key(spend.to_raw_key().hash());
1281 let addr_net_0 = PointerAddress::new(
1282 NetworkInfo::testnet().network_id(),
1283 spend_cred.clone(),
1284 Pointer::new(1, 2, 3),
1285 )
1286 .to_address();
1287 assert_eq!(
1288 addr_net_0.to_bech32(None).unwrap(),
1289 "addr_test1gqy6nhfyks7wdu3dudslys37v252w2nwhv0fw2nfawemmnqpqgps5mee0p"
1290 );
1291 let addr_net_3 = PointerAddress::new(
1292 NetworkInfo::mainnet().network_id(),
1293 spend_cred,
1294 Pointer::new(24157, 177, 42),
1295 )
1296 .to_address();
1297 assert_eq!(
1298 addr_net_3.to_bech32(None).unwrap(),
1299 "addr1gyy6nhfyks7wdu3dudslys37v252w2nwhv0fw2nfawemmnyph3wczvf2dqflgt"
1300 );
1301 }
1302
1303 #[test]
1304 fn bip32_12_reward() {
1305 let staking_key = root_key_12()
1306 .derive(harden(1852))
1307 .derive(harden(1815))
1308 .derive(harden(0))
1309 .derive(2)
1310 .derive(0)
1311 .to_public();
1312 let staking_cred = StakeCredential::new_pub_key(staking_key.to_raw_key().hash());
1313 let addr_net_0 =
1314 RewardAddress::new(NetworkInfo::testnet().network_id(), staking_cred.clone())
1315 .to_address();
1316 assert_eq!(
1317 addr_net_0.to_bech32(None).unwrap(),
1318 "stake_test1uqevw2xnsc0pvn9t9r9c7qryfqfeerchgrlm3ea2nefr9hqp8n5xl"
1319 );
1320 let addr_net_3 =
1321 RewardAddress::new(NetworkInfo::mainnet().network_id(), staking_cred).to_address();
1322 assert_eq!(
1323 addr_net_3.to_bech32(None).unwrap(),
1324 "stake1uyevw2xnsc0pvn9t9r9c7qryfqfeerchgrlm3ea2nefr9hqxdekzz"
1325 );
1326 }
1327
1328 #[test]
1329 fn bip32_24_base_multisig_hd_derivation() {
1330 let spend = root_key_24()
1331 .derive(harden(1854))
1332 .derive(harden(1815))
1333 .derive(harden(0))
1334 .derive(0)
1335 .derive(0)
1336 .to_public();
1337 let stake = root_key_24()
1338 .derive(harden(1854))
1339 .derive(harden(1815))
1340 .derive(harden(0))
1341 .derive(2)
1342 .derive(0)
1343 .to_public();
1344 let spend_cred = StakeCredential::new_pub_key(spend.to_raw_key().hash());
1345 let stake_cred = StakeCredential::new_pub_key(stake.to_raw_key().hash());
1346 let addr_net_0 = BaseAddress::new(
1347 NetworkInfo::testnet().network_id(),
1348 spend_cred.clone(),
1349 stake_cred.clone(),
1350 )
1351 .to_address();
1352 assert_eq!(addr_net_0.to_bech32(None).unwrap(), "addr_test1qz8fg2e9yn0ga6sav0760cxmx0antql96mfuhqgzcc5swugw2jqqlugnx9qjep9xvcx40z0zfyep55r2t3lav5smyjrs96cusg");
1353 let addr_net_3 =
1354 BaseAddress::new(NetworkInfo::mainnet().network_id(), spend_cred, stake_cred)
1355 .to_address();
1356 assert_eq!(addr_net_3.to_bech32(None).unwrap(), "addr1qx8fg2e9yn0ga6sav0760cxmx0antql96mfuhqgzcc5swugw2jqqlugnx9qjep9xvcx40z0zfyep55r2t3lav5smyjrsxv9uuh");
1357 }
1358
1359 #[test]
1360 fn multisig_from_script() {
1361 let spend = root_key_24()
1362 .derive(harden(1852))
1363 .derive(harden(1815))
1364 .derive(harden(0))
1365 .derive(0)
1366 .derive(0)
1367 .to_public();
1368
1369 let mut pubkey_native_scripts = Vec::new();
1370
1371 let spending_hash = spend.to_raw_key().hash();
1372 pubkey_native_scripts.push(NativeScript::new_script_pubkey(spending_hash));
1373 let oneof_native_script = NativeScript::new_script_n_of_k(1, pubkey_native_scripts);
1374
1375 let script_hash =
1376 ScriptHash::from_raw_bytes(oneof_native_script.hash().to_raw_bytes()).unwrap();
1377
1378 let spend_cred = StakeCredential::new_script(script_hash);
1379 let stake_cred = StakeCredential::new_script(script_hash);
1380 let addr_net_0 = BaseAddress::new(
1381 NetworkInfo::testnet().network_id(),
1382 spend_cred.clone(),
1383 stake_cred.clone(),
1384 )
1385 .to_address();
1386 assert_eq!(addr_net_0.to_bech32(None).unwrap(), "addr_test1xr0de0mz3m9xmgtlmqqzu06s0uvfsczskdec8k7v4jhr7077mjlk9rk2dkshlkqq9cl4qlccnps9pvmns0duet9w8uls8flvxc");
1387 let addr_net_3 =
1388 BaseAddress::new(NetworkInfo::mainnet().network_id(), spend_cred, stake_cred)
1389 .to_address();
1390 assert_eq!(addr_net_3.to_bech32(None).unwrap(), "addr1x80de0mz3m9xmgtlmqqzu06s0uvfsczskdec8k7v4jhr7077mjlk9rk2dkshlkqq9cl4qlccnps9pvmns0duet9w8ulsylzv28");
1391 }
1392
1393 #[test]
1394 fn pointer_address_big() {
1395 let addr = Address::from_bech32("addr_test1grqe6lg9ay8wkcu5k5e38lne63c80h3nq6xxhqfmhewf645pllllllllllll7lupllllllllllll7lupllllllllllll7lc9wayvj").unwrap();
1396 let ptr = PointerAddress::from_address(&addr).unwrap().stake;
1397 let u64_max = num_bigint::BigUint::from(u64::MAX);
1398 assert_eq!(u64_max, ptr.slot);
1399 assert_eq!(u64_max, ptr.tx_index);
1400 assert_eq!(u64_max, ptr.cert_index);
1401 }
1402
1403 #[test]
1404 fn long_address() {
1405 let long = Address::from_bech32("addr1q9d66zzs27kppmx8qc8h43q7m4hkxp5d39377lvxefvxd8j7eukjsdqc5c97t2zg5guqadepqqx6rc9m7wtnxy6tajjvk4a0kze4ljyuvvrpexg5up2sqxj33363v35gtew").unwrap();
1406 let long_trimmed = Address::from_bech32("addr1q9d66zzs27kppmx8qc8h43q7m4hkxp5d39377lvxefvxd8j7eukjsdqc5c97t2zg5guqadepqqx6rc9m7wtnxy6tajjq6r54x9").unwrap();
1407 assert_eq!(long, long_trimmed);
1408 assert_eq!(
1409 long.encoding().unwrap().trailing,
1410 Some(vec![
1411 203u8, 87, 175, 176, 179, 95, 200, 156, 99, 6, 28, 153, 20, 224, 85, 0, 26, 81,
1412 140, 117, 22
1413 ])
1414 );
1415 assert_eq!(
1416 long_trimmed.encoding().and_then(|enc| enc.trailing.clone()),
1417 None
1418 );
1419 assert_eq!(
1420 hex::encode(long.to_raw_bytes()),
1421 "015bad085057ac10ecc7060f7ac41edd6f63068d8963ef7d86ca58669e5ecf2d283418a60be5a848a2380eb721000da1e0bbf39733134beca4cb57afb0b35fc89c63061c9914e055001a518c7516"
1422 );
1423 let long_not_whitelisted = Address::from_bech32(
1424 "addr_test1vqt3w9chzut3w9chzut3w9chzut3w9chzut3w9chzut3w9cqqspqvqcqsmxqdssg97",
1425 );
1426 assert!(long_not_whitelisted.is_err());
1427 }
1428
1429 #[test]
1430 fn ptr_addr_huge_slot() {
1431 let addr_bytes: Vec<u8> = vec![
1432 64, 193, 157, 125, 5, 233, 14, 235, 99, 148, 181, 51, 19, 254, 121, 212, 112, 119, 222,
1433 51, 6, 140, 107, 129, 59, 190, 92, 157, 86, 129, 255, 255, 255, 255, 255, 255, 255,
1434 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
1435 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
1436 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
1437 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
1438 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
1439 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
1440 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
1441 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
1442 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
1443 255, 255, 255, 255, 255, 255, 255, 255, 127, 129, 255, 255, 255, 255, 255, 255, 255,
1444 255, 127, 129, 255, 255, 255, 255, 255, 255, 255, 255, 127,
1445 ];
1446 let addr = Address::from_raw_bytes(&addr_bytes).unwrap();
1447 assert_eq!(addr_bytes, addr.to_raw_bytes());
1448 }
1449}