cfx_parity_trace_types/
address_pocket.rs

1use cfx_types::{Address, AddressSpaceUtil, AddressWithSpace, Space};
2use rlp::{Decodable, DecoderError, Encodable, Rlp, RlpStream};
3
4#[derive(Debug, Clone, Copy, PartialEq)]
5pub enum AddressPocket {
6    Balance(AddressWithSpace),
7    StakingBalance(Address),
8    StorageCollateral(Address),
9    SponsorBalanceForGas(Address),
10    SponsorBalanceForStorage(Address),
11    MintBurn,
12    GasPayment,
13}
14
15impl AddressPocket {
16    pub fn inner_address(&self) -> Option<&Address> {
17        use AddressPocket::*;
18        match self {
19            Balance(AddressWithSpace { address: addr, .. })
20            | StakingBalance(addr)
21            | StorageCollateral(addr)
22            | SponsorBalanceForGas(addr)
23            | SponsorBalanceForStorage(addr) => Some(addr),
24            MintBurn | GasPayment => None,
25        }
26    }
27
28    pub fn inner_address_or_default(&self) -> Address {
29        self.inner_address().cloned().unwrap_or(Address::zero())
30    }
31
32    pub fn pocket(&self) -> &'static str {
33        use AddressPocket::*;
34        match self {
35            Balance(_) => "balance",
36            StakingBalance(_) => "staking_balance",
37            StorageCollateral(_) => "storage_collateral",
38            SponsorBalanceForGas(_) => "sponsor_balance_for_gas",
39            SponsorBalanceForStorage(_) => "sponsor_balance_for_collateral",
40            MintBurn => "mint_or_burn",
41            GasPayment => "gas_payment",
42        }
43    }
44
45    pub fn space(&self) -> &'static str {
46        use AddressPocket::*;
47        match self {
48            Balance(AddressWithSpace { space, .. }) => space.clone().into(),
49            MintBurn | GasPayment => "none",
50            _ => Space::Native.into(),
51        }
52    }
53
54    fn type_number(&self) -> u8 {
55        use AddressPocket::*;
56        match self {
57            Balance(AddressWithSpace {
58                space: Space::Native,
59                ..
60            }) => 0,
61            StakingBalance(_) => 1,
62            StorageCollateral(_) => 2,
63            SponsorBalanceForGas(_) => 3,
64            SponsorBalanceForStorage(_) => 4,
65            MintBurn => 5,
66            GasPayment => 6,
67            Balance(AddressWithSpace {
68                space: Space::Ethereum,
69                ..
70            }) => 7,
71        }
72    }
73}
74
75impl Encodable for AddressPocket {
76    fn rlp_append(&self, s: &mut RlpStream) {
77        let maybe_address = self.inner_address();
78        let type_number = self.type_number();
79        if let Some(address) = maybe_address {
80            s.begin_list(2);
81            s.append(&type_number);
82            s.append(address);
83        } else {
84            s.begin_list(1);
85            s.append(&type_number);
86        }
87    }
88}
89
90impl Decodable for AddressPocket {
91    fn decode(rlp: &Rlp) -> Result<Self, DecoderError> {
92        use AddressPocket::*;
93
94        let type_number: u8 = rlp.val_at(0)?;
95        match type_number {
96            0 => rlp
97                .val_at(1)
98                .map(|addr: Address| Balance(addr.with_native_space())),
99            1 => rlp.val_at(1).map(StakingBalance),
100            2 => rlp.val_at(1).map(StorageCollateral),
101            3 => rlp.val_at(1).map(SponsorBalanceForGas),
102            4 => rlp.val_at(1).map(SponsorBalanceForStorage),
103            5 => Ok(MintBurn),
104            6 => Ok(GasPayment),
105            7 => rlp
106                .val_at(1)
107                .map(|addr: Address| Balance(addr.with_evm_space())),
108            _ => {
109                Err(DecoderError::Custom("Invalid internal transfer address."))
110            }
111        }
112    }
113}