Create new state instance.
(
store: &BS,
network_name: String,
// Accounts from the Genesis file.
accounts: &[Actor],
// Pre-defined IDs for top-level EVM contracts.
eth_builtin_i
| 52 | impl State { |
| 53 | /// Create new state instance. |
| 54 | pub fn new<BS: Blockstore>( |
| 55 | store: &BS, |
| 56 | network_name: String, |
| 57 | // Accounts from the Genesis file. |
| 58 | accounts: &[Actor], |
| 59 | // Pre-defined IDs for top-level EVM contracts. |
| 60 | eth_builtin_ids: &BTreeSet<ActorID>, |
| 61 | // Number of dynamically deployed EVM library contracts. |
| 62 | eth_library_count: u64, |
| 63 | ) -> anyhow::Result<(Self, AddressMap)> { |
| 64 | // Returning only the addreses that belong to user accounts. |
| 65 | let mut allocated_ids = AddressMap::new(); |
| 66 | // Inserting both user accounts and built-in EVM actors. |
| 67 | let mut address_map = Hamt::<&BS, ActorID>::new_with_bit_width(store, HAMT_BIT_WIDTH); |
| 68 | |
| 69 | let mut set_address = |addr: Address, id: ActorID| { |
| 70 | tracing::debug!( |
| 71 | addr = addr.to_string(), |
| 72 | actor_id = id, |
| 73 | "setting init address" |
| 74 | ); |
| 75 | address_map.set(addr.to_bytes().into(), id) |
| 76 | }; |
| 77 | |
| 78 | let addresses = accounts.iter().flat_map(|a| match &a.meta { |
| 79 | ActorMeta::Account(acc) => { |
| 80 | vec![acc.owner.0] |
| 81 | } |
| 82 | ActorMeta::Multisig(ms) => ms.signers.iter().map(|a| a.0).collect(), |
| 83 | }); |
| 84 | |
| 85 | let mut next_id = FIRST_NON_SINGLETON_ADDR; |
| 86 | |
| 87 | for addr in addresses { |
| 88 | if allocated_ids.contains_key(&addr) { |
| 89 | continue; |
| 90 | } |
| 91 | allocated_ids.insert(addr, next_id); |
| 92 | set_address(addr, next_id).context("cannot set ID of account address")?; |
| 93 | next_id += 1; |
| 94 | } |
| 95 | |
| 96 | // We will need to allocate an ID for each multisig account, however, |
| 97 | // these do not have to be recorded in the map, because their addr->ID |
| 98 | // mapping is trivial (it's an ID type address). To avoid the init actor |
| 99 | // using the same ID for something else, give it a higher ID to use next. |
| 100 | for a in accounts.iter() { |
| 101 | if let ActorMeta::Multisig { .. } = a.meta { |
| 102 | next_id += 1; |
| 103 | } |
| 104 | } |
| 105 | |
| 106 | // Insert top-level EVM contracts which have fixed IDs. |
| 107 | for id in eth_builtin_ids { |
| 108 | let addr = Address::from(builtin_actor_eth_addr(*id)); |
| 109 | set_address(addr, *id).context("cannot set ID of eth contract address")?; |
| 110 | } |
| 111 |