node_lifecycle.rs (6798B)
1 use std::collections::{BTreeMap, BTreeSet}; 2 3 use anyhow::Result; 4 5 use crate::{ 6 adapters::config_store::{DEFAULT_POW_MINING_WORKERS, clamp_pow_mining_workers}, 7 domain::{ 8 AddressNetwork, Amount, BurnBundle, DEFAULT_FEE_PER_BYTE, Ledger, VersionedAddress, Wallet, 9 decode_address, decode_versioned_address, encode_address, transaction_v2_is_active, 10 }, 11 }; 12 13 use super::{GossipEnvelope, NodeConfig, NodeCore, NodeWallet}; 14 15 impl NodeCore { 16 pub fn new(config: NodeConfig) -> Self { 17 let ledger = Ledger::new(config.genesis_allocations, config.vdf_rounds); 18 let mut node = Self::from_ledger_with_burn_fee( 19 config.wallet, 20 ledger, 21 config.burn_per_block, 22 config.burn_fee, 23 ); 24 node.set_pow_mining_workers(config.pow_mining_workers); 25 node.set_recovery_vdf_top_rank_percent(config.recovery_vdf_top_rank_percent); 26 node 27 } 28 29 pub fn from_ledger(wallet: Wallet, ledger: Ledger, burn_per_block: Amount) -> Self { 30 Self::from_ledger_with_burn_fee(wallet, ledger, burn_per_block, DEFAULT_FEE_PER_BYTE) 31 } 32 33 pub fn from_locked_wallet_address( 34 address: impl Into<String>, 35 ledger: Ledger, 36 automatic_mining_enabled: bool, 37 burn_per_block: Amount, 38 burn_fee: Amount, 39 ) -> Self { 40 Self::from_node_wallet_with_burn_fee_and_enabled( 41 NodeWallet::Locked { 42 address: address.into(), 43 }, 44 ledger, 45 automatic_mining_enabled, 46 burn_per_block, 47 burn_fee, 48 DEFAULT_POW_MINING_WORKERS, 49 100, 50 ) 51 } 52 53 pub fn from_ledger_with_burn_fee( 54 wallet: Wallet, 55 ledger: Ledger, 56 burn_per_block: Amount, 57 burn_fee: Amount, 58 ) -> Self { 59 Self::from_ledger_with_burn_fee_and_enabled( 60 wallet, 61 ledger, 62 burn_per_block > 0, 63 burn_per_block, 64 burn_fee, 65 ) 66 } 67 68 pub fn from_ledger_with_burn_fee_and_enabled( 69 wallet: Wallet, 70 ledger: Ledger, 71 automatic_mining_enabled: bool, 72 burn_per_block: Amount, 73 burn_fee: Amount, 74 ) -> Self { 75 Self::from_node_wallet_with_burn_fee_and_enabled( 76 NodeWallet::Unlocked(wallet), 77 ledger, 78 automatic_mining_enabled, 79 burn_per_block, 80 burn_fee, 81 DEFAULT_POW_MINING_WORKERS, 82 100, 83 ) 84 } 85 86 fn from_node_wallet_with_burn_fee_and_enabled( 87 wallet: NodeWallet, 88 ledger: Ledger, 89 automatic_mining_enabled: bool, 90 burn_per_block: Amount, 91 burn_fee: Amount, 92 pow_mining_workers: u8, 93 recovery_vdf_top_rank_percent: u8, 94 ) -> Self { 95 Self { 96 wallet, 97 ledger, 98 automatic_mining_enabled, 99 pow_mining_enabled: false, 100 pow_mining_workers: clamp_pow_mining_workers(pow_mining_workers), 101 burn_per_block, 102 burn_fee, 103 recovery_vdf_top_rank_percent: recovery_vdf_top_rank_percent.min(100), 104 last_auto_burn_height: None, 105 last_auto_anchor_burn_height: None, 106 last_auto_finalization_status: None, 107 last_auto_pow_mine_anchor: None, 108 last_auto_pow_mine_status: None, 109 auto_pow_mine_cursor: None, 110 burn_bundles: BTreeMap::<(u64, u8, String), BurnBundle>::new(), 111 equivocated_burn_bundle_slots: BTreeSet::new(), 112 burn_bundle_collection_started: None, 113 local_block_anchor_burn: None, 114 outbox: Vec::<GossipEnvelope>::new(), 115 network_migration_from: None, 116 } 117 } 118 119 pub fn require_network_migration(&mut self, from_network: impl Into<String>) { 120 self.network_migration_from = Some(from_network.into()); 121 } 122 123 pub fn network_migration_from(&self) -> Option<&str> { 124 self.network_migration_from.as_deref() 125 } 126 127 pub fn complete_network_migration(&mut self) { 128 self.network_migration_from = None; 129 } 130 131 pub fn wallet_address(&self) -> &str { 132 self.wallet.address() 133 } 134 135 pub fn wallet_receive_address(&self) -> Result<String> { 136 if transaction_v2_is_active(self.ledger.height()) { 137 if let Ok(wallet) = self.wallet.unlocked() { 138 return self.ledger.wallet_receive_address(wallet); 139 } 140 } 141 encode_address(self.wallet.address(), self.address_network()) 142 } 143 144 pub fn wallet_owned_addresses(&self) -> Result<Vec<String>> { 145 let mut addresses = vec![self.wallet.address().to_string()]; 146 if let Ok(wallet) = self.wallet.unlocked() { 147 addresses.extend(self.ledger.wallet_owned_hybrid_encoded_addresses(wallet)?); 148 } 149 addresses.sort(); 150 addresses.dedup(); 151 Ok(addresses) 152 } 153 154 pub fn normalize_user_address(&self, address: &str) -> Result<String> { 155 decode_address(address, self.address_network()) 156 } 157 158 pub fn decode_user_address(&self, address: &str) -> Result<VersionedAddress> { 159 decode_versioned_address(address, self.address_network()) 160 } 161 162 fn address_network(&self) -> AddressNetwork { 163 AddressNetwork::from_profile_id(&self.ledger.launch_profile().profile_id) 164 } 165 166 pub fn wallet_is_locked(&self) -> bool { 167 self.wallet.is_locked() 168 } 169 170 pub fn replace_wallet(&mut self, wallet: Wallet) { 171 self.wallet = NodeWallet::Unlocked(wallet); 172 self.reset_automatic_mining_progress(); 173 self.burn_bundles.clear(); 174 self.equivocated_burn_bundle_slots.clear(); 175 self.burn_bundle_collection_started = None; 176 self.local_block_anchor_burn = None; 177 } 178 179 pub fn reset_chain_to_setup_placeholder(&mut self) { 180 let launch_profile = self.ledger.launch_profile().clone(); 181 self.ledger = Ledger::new_with_genesis_burns_and_profile( 182 BTreeMap::new(), 183 Vec::new(), 184 1, 185 launch_profile, 186 ) 187 .expect("empty setup ledger is valid"); 188 self.reset_automatic_mining_progress(); 189 self.burn_bundles.clear(); 190 self.equivocated_burn_bundle_slots.clear(); 191 self.burn_bundle_collection_started = None; 192 self.local_block_anchor_burn = None; 193 self.outbox.clear(); 194 } 195 196 pub(super) fn reset_automatic_mining_progress(&mut self) { 197 self.last_auto_burn_height = None; 198 self.last_auto_anchor_burn_height = None; 199 self.last_auto_finalization_status = None; 200 self.last_auto_pow_mine_anchor = None; 201 self.last_auto_pow_mine_status = None; 202 self.auto_pow_mine_cursor = None; 203 self.burn_bundle_collection_started = None; 204 } 205 }