mod.rs 32 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849
  1. /* This file is part of DarkFi (https://dark.fi)
  2. *
  3. * Copyright (C) 2020-2026 Dyne.org foundation
  4. *
  5. * This program is free software: you can redistribute it and/or modify
  6. * it under the terms of the GNU Affero General Public License as
  7. * published by the Free Software Foundation, either version 3 of the
  8. * License, or (at your option) any later version.
  9. *
  10. * This program is distributed in the hope that it will be useful,
  11. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. * GNU Affero General Public License for more details.
  14. *
  15. * You should have received a copy of the GNU Affero General Public License
  16. * along with this program. If not, see <https://www.gnu.org/licenses/>.
  17. */
  18. use std::{collections::HashMap, sync::Arc};
  19. use darkfi_sdk::{crypto::MerkleTree, fee::minimum_fee};
  20. use kvdb_overlay::Database;
  21. use num_bigint::BigUint;
  22. use smol::lock::RwLock;
  23. use tracing::{debug, error, info, warn};
  24. use crate::{
  25. blockchain::{
  26. block_store::{BlockDifficulty, BlockInfo, BlockRanks},
  27. Blockchain, BlockchainOverlay, HeaderHash,
  28. },
  29. error::TxVerifyFailed,
  30. tx::Transaction,
  31. util::time::Timestamp,
  32. zk::VerifyingKey,
  33. Error, Result,
  34. };
  35. /// DarkFi consensus module
  36. pub mod consensus;
  37. use consensus::{Consensus, Fork, Proposal};
  38. /// DarkFi PoW module
  39. pub mod pow;
  40. use pow::PoWModule;
  41. /// RandomX infrastructure
  42. pub mod randomx_factory;
  43. pub use randomx_factory::RandomXFactory;
  44. /// Verification functions
  45. pub mod verification;
  46. use verification::{
  47. verify_block, verify_checkpoint_block, verify_genesis_block, verify_producer_transaction,
  48. verify_transaction, verify_transactions,
  49. };
  50. /// Fee calculation helpers
  51. pub mod fees;
  52. /// Helper utilities
  53. pub mod utils;
  54. use utils::{best_fork_index, block_rank, deploy_native_contracts};
  55. /// Configuration for initializing [`Validator`]
  56. #[derive(Clone)]
  57. pub struct ValidatorConfig {
  58. /// Currently configured confirmation security threshold
  59. pub confirmation_threshold: usize,
  60. /// Currently configured max in-memory forks to maintain.
  61. pub max_forks: usize,
  62. /// Currently configured PoW target
  63. pub pow_target: u32,
  64. /// Optional fixed difficulty, for testing purposes
  65. pub pow_fixed_difficulty: Option<BigUint>,
  66. /// Genesis block
  67. pub genesis_block: BlockInfo,
  68. /// Flag to enable tx fee verification
  69. pub verify_fees: bool,
  70. }
  71. /// Atomic pointer to validator.
  72. pub type ValidatorPtr = Arc<RwLock<Validator>>;
  73. /// This struct represents a DarkFi validator node.
  74. pub struct Validator {
  75. /// Canonical (confirmed) blockchain
  76. pub blockchain: Blockchain,
  77. /// Hot/Live data used by the consensus algorithm
  78. pub consensus: Consensus,
  79. /// Flag signalling if the node is synced
  80. pub synced: bool,
  81. /// Flag to enable tx fee verification
  82. pub verify_fees: bool,
  83. }
  84. impl Validator {
  85. pub async fn new(kvdb: &Database, config: &ValidatorConfig) -> Result<ValidatorPtr> {
  86. info!(target: "validator::new", "Initializing Validator");
  87. info!(target: "validator::new", "Initializing Blockchain");
  88. let blockchain = Blockchain::new(kvdb)?;
  89. // Create an overlay over whole blockchain so we can write
  90. // stuff.
  91. let overlay = BlockchainOverlay::new(&blockchain)?;
  92. // Deploy native wasm contracts
  93. deploy_native_contracts(&overlay, config.pow_target).await?;
  94. // Update the contracts states monotree in case native
  95. // contracts zkas has changed.
  96. let diff = overlay.lock().unwrap().overlay.lock().unwrap().diff(&[])?;
  97. overlay.lock().unwrap().contracts.update_state_monotree(&diff)?;
  98. // Add genesis block if blockchain is empty
  99. if blockchain.genesis().is_err() {
  100. info!(target: "validator::new", "Appending genesis block");
  101. verify_genesis_block(&overlay, &[diff], &config.genesis_block, config.pow_target)
  102. .await?;
  103. };
  104. // Write the changes to the actual chain db
  105. overlay.lock().unwrap().overlay.lock().unwrap().apply()?;
  106. info!(target: "validator::new", "Initializing Consensus");
  107. let consensus = Consensus::new(
  108. blockchain.clone(),
  109. config.confirmation_threshold,
  110. config.max_forks,
  111. config.pow_target,
  112. config.pow_fixed_difficulty.clone(),
  113. )?;
  114. // Create the actual state
  115. let state = Arc::new(RwLock::new(Self {
  116. blockchain,
  117. consensus,
  118. synced: false,
  119. verify_fees: config.verify_fees,
  120. }));
  121. info!(target: "validator::new", "Finished initializing validator");
  122. Ok(state)
  123. }
  124. /// Auxiliary function to compute provided transaction's required
  125. /// fee, against current best fork. The function takes a boolean
  126. /// called `verify_fee` to overwrite the nodes configured
  127. /// `verify_fees` flag.
  128. ///
  129. /// Note: Always remember to purge new trees from the database if
  130. /// not needed.
  131. pub async fn calculate_fee(&self, tx: &Transaction, verify_fee: bool) -> Result<u64> {
  132. // Grab the best fork to verify against
  133. let index = best_fork_index(&self.consensus.forks)?;
  134. let fork = self.consensus.forks[index].full_clone()?;
  135. // Map of ZK proof verifying keys for the transaction
  136. let mut vks: HashMap<[u8; 32], HashMap<String, VerifyingKey>> = HashMap::new();
  137. for call in &tx.calls {
  138. vks.insert(call.data.contract_id.to_bytes(), HashMap::new());
  139. }
  140. // Grab forks' next block height
  141. let next_block_height = fork.get_next_block_height()?;
  142. // Verify transaction to grab the gas used
  143. let verify_result = verify_transaction(
  144. &fork.overlay,
  145. next_block_height,
  146. self.consensus.module.target,
  147. tx,
  148. &mut MerkleTree::new(1),
  149. &mut vks,
  150. verify_fee,
  151. )
  152. .await?;
  153. Ok(minimum_fee(verify_result.total_gas_used())?)
  154. }
  155. /// The node retrieves a transaction, validates its state
  156. /// transition agains best fork, and appends it to the pending txs
  157. /// store if its valid.
  158. ///
  159. /// Note: Always remember to purge new trees from the database if
  160. /// not needed.
  161. pub async fn append_tx(&mut self, tx: &Transaction, write: bool) -> Result<()> {
  162. let tx_hash = tx.hash();
  163. // Check if we have already seen this tx in the pending store
  164. if self.blockchain.transactions.contains_pending(&tx_hash)? {
  165. debug!(target: "validator::append_tx", "We have already seen pending tx: {tx_hash}");
  166. return Err(TxVerifyFailed::AlreadySeenTx(tx_hash.as_string()).into())
  167. }
  168. // Grab the best fork to verify against
  169. let index = best_fork_index(&self.consensus.forks)?;
  170. let fork = self.consensus.forks[index].full_clone()?;
  171. // Check if we have already seen this tx. This checks both the
  172. // fork cache and the actual database.
  173. if fork.overlay.lock().unwrap().transactions.contains(&tx_hash)? {
  174. debug!(target: "validator::append_tx", "We have already seen tx: {tx_hash}");
  175. return Err(TxVerifyFailed::AlreadySeenTx(tx_hash.as_string()).into())
  176. }
  177. // Verify state transition
  178. info!(target: "validator::append_tx", "Starting state transition validation for tx: {tx_hash}");
  179. // Map of ZK proof verifying keys for the transaction
  180. let mut vks: HashMap<[u8; 32], HashMap<String, VerifyingKey>> = HashMap::new();
  181. for call in &tx.calls {
  182. vks.insert(call.data.contract_id.to_bytes(), HashMap::new());
  183. }
  184. // Grab forks' next block height
  185. let next_block_height = fork.get_next_block_height()?;
  186. // Verify transaction
  187. verify_transaction(
  188. &fork.overlay,
  189. next_block_height,
  190. self.consensus.module.target,
  191. tx,
  192. &mut MerkleTree::new(1),
  193. &mut vks,
  194. self.verify_fees,
  195. )
  196. .await?;
  197. // Add transaction to pending txs store
  198. if write {
  199. self.blockchain.add_pending_txs(std::slice::from_ref(tx))?;
  200. info!(target: "validator::append_tx", "Appended tx {tx_hash} to pending txs store");
  201. }
  202. Ok(())
  203. }
  204. /// The node tries to append provided proposal to its consensus
  205. /// state.
  206. pub async fn append_proposal(
  207. &mut self,
  208. proposal: &Proposal,
  209. timestamp_bound: Option<Timestamp>,
  210. ) -> Result<()> {
  211. self.consensus.append_proposal(proposal, timestamp_bound, self.verify_fees).await
  212. }
  213. /// The node checks if best fork can be confirmed.
  214. /// If proposals can be confirmed, node appends them to canonical,
  215. /// and resets the current forks.
  216. pub async fn confirmation(&mut self) -> Result<Vec<BlockInfo>> {
  217. info!(target: "validator::confirmation", "Performing confirmation check");
  218. // Grab best fork index that can be confirmed
  219. let confirmed_fork = self.consensus.confirmation().await?;
  220. if confirmed_fork.is_none() {
  221. info!(target: "validator::confirmation", "No proposals can be confirmed");
  222. return Ok(vec![])
  223. }
  224. // Grab the actual best fork
  225. let confirmed_fork = confirmed_fork.unwrap();
  226. let fork = &mut self.consensus.forks[confirmed_fork];
  227. // Find the excess over confirmation threshold
  228. let excess = (fork.proposals.len() - self.consensus.confirmation_threshold) + 1;
  229. // Grab confirmed proposals and update fork's sequences
  230. let rest_proposals = fork.proposals.split_off(excess);
  231. let rest_diffs = fork.diffs.split_off(excess);
  232. let confirmed_proposals = fork.proposals.clone();
  233. let diffs = fork.diffs.clone();
  234. fork.proposals = rest_proposals;
  235. fork.diffs = rest_diffs;
  236. // Grab confirmed proposals blocks
  237. let confirmed_blocks =
  238. fork.overlay.lock().unwrap().get_blocks_by_hash(&confirmed_proposals)?;
  239. // Apply confirmed proposals diffs and update PoW module
  240. let mut module = self.consensus.module.clone();
  241. let mut confirmed_txs = vec![];
  242. let mut state_inverse_diffs_heights = vec![];
  243. let mut state_inverse_diffs = vec![];
  244. info!(target: "validator::confirmation", "Confirming proposals:");
  245. for (index, proposal) in confirmed_proposals.iter().enumerate() {
  246. info!(target: "validator::confirmation", "\t{proposal} ({}) - {}", confirmed_blocks[index].header.pow_data, confirmed_blocks[index].header.height);
  247. fork.overlay.lock().unwrap().overlay.lock().unwrap().apply_diff(&diffs[index])?;
  248. let next_difficulty = module.next_difficulty()?;
  249. module.append(&confirmed_blocks[index].header, &next_difficulty)?;
  250. confirmed_txs.extend_from_slice(&confirmed_blocks[index].txs);
  251. state_inverse_diffs_heights.push(confirmed_blocks[index].header.height);
  252. state_inverse_diffs.push(diffs[index].inverse());
  253. }
  254. self.consensus.module = module;
  255. // Store the block inverse diffs
  256. self.blockchain
  257. .blocks
  258. .insert_state_inverse_diff(&state_inverse_diffs_heights, &state_inverse_diffs)?;
  259. // Reset forks starting with the confirmed blocks
  260. self.consensus.reset_forks(&confirmed_proposals, &confirmed_fork, &confirmed_txs).await?;
  261. info!(target: "validator::confirmation", "Confirmation completed!");
  262. Ok(confirmed_blocks)
  263. }
  264. /// Apply provided set of [`BlockInfo`] without doing formal
  265. /// verification. A set of [`HeaderHash`] is also provided, to
  266. /// verify that the provided block hash matches the expected header
  267. /// one.
  268. ///
  269. /// Note: this function should only be used for blocks received
  270. /// using a checkpoint, since in that case we enforce the node to
  271. /// follow the sequence, assuming all its blocks are valid.
  272. /// Additionally, it will update any forks to a single empty one,
  273. /// holding the updated module. Always remember to purge new trees
  274. /// from the database if not needed.
  275. pub async fn add_checkpoint_blocks(
  276. &mut self,
  277. blocks: &[BlockInfo],
  278. headers: &[HeaderHash],
  279. ) -> Result<()> {
  280. // Check provided sequences are the same length
  281. if blocks.len() != headers.len() {
  282. return Err(Error::InvalidInputLengths)
  283. }
  284. debug!(target: "validator::add_checkpoint_blocks", "Instantiating BlockchainOverlay");
  285. let overlay = BlockchainOverlay::new(&self.blockchain)?;
  286. // Retrieve last block difficulty to access current ranks
  287. let last_difficulty = self.blockchain.last_block_difficulty()?;
  288. let mut current_targets_rank = last_difficulty.ranks.targets_rank;
  289. let mut current_hashes_rank = last_difficulty.ranks.hashes_rank;
  290. // Grab current PoW module to validate each block
  291. let mut module = self.consensus.module.clone();
  292. // Keep track of all blocks transactions to remove them from
  293. // pending txs store.
  294. let mut removed_txs = vec![];
  295. // Keep track of all block database state diffs and their
  296. // inverse.
  297. let mut diffs_heights = vec![];
  298. let mut diffs = vec![];
  299. let mut inverse_diffs = vec![];
  300. // Validate and insert each block
  301. for (index, block) in blocks.iter().enumerate() {
  302. // Verify block
  303. match verify_checkpoint_block(&overlay, &diffs, block, &headers[index], module.target)
  304. .await
  305. {
  306. Ok(()) => { /* Do nothing */ }
  307. // Skip already existing block
  308. Err(Error::BlockAlreadyExists(_)) => continue,
  309. Err(e) => {
  310. error!(target: "validator::add_checkpoint_blocks", "Erroneous block found in set: {e}");
  311. return Err(Error::BlockIsInvalid(block.hash().as_string()))
  312. }
  313. };
  314. // Calculate block rank
  315. let (next_difficulty, target_distance_sq, hash_distance_sq) =
  316. block_rank(&mut module, block)?;
  317. // Update current ranks
  318. current_targets_rank += target_distance_sq.clone();
  319. current_hashes_rank += hash_distance_sq.clone();
  320. // Generate block difficulty and update PoW module
  321. let cumulative_difficulty =
  322. module.cumulative_difficulty.clone() + next_difficulty.clone();
  323. let ranks = BlockRanks::new(
  324. target_distance_sq,
  325. current_targets_rank.clone(),
  326. hash_distance_sq,
  327. current_hashes_rank.clone(),
  328. );
  329. let block_difficulty = BlockDifficulty::new(
  330. block.header.height,
  331. block.header.timestamp,
  332. next_difficulty,
  333. cumulative_difficulty,
  334. ranks,
  335. );
  336. module.append_difficulty(&overlay, &block.header, block_difficulty)?;
  337. // Store block transactions
  338. for tx in &block.txs {
  339. removed_txs.push(tx.clone());
  340. }
  341. // Store block database state diff and its inverse
  342. diffs_heights.push(block.header.height);
  343. let diff = overlay.lock().unwrap().overlay.lock().unwrap().diff(&diffs)?;
  344. inverse_diffs.push(diff.inverse());
  345. diffs.push(diff);
  346. }
  347. debug!(target: "validator::add_checkpoint_blocks", "Applying overlay changes");
  348. overlay.lock().unwrap().overlay.lock().unwrap().apply()?;
  349. // Store the block diffs
  350. self.blockchain.blocks.insert_state_inverse_diff(&diffs_heights, &inverse_diffs)?;
  351. // Remove blocks transactions from pending txs store
  352. self.blockchain.remove_pending_txs(&removed_txs)?;
  353. // Update PoW module
  354. self.consensus.module = module.clone();
  355. // Update forks
  356. self.consensus.forks = vec![Fork::new(self.blockchain.clone(), module).await?];
  357. Ok(())
  358. }
  359. /// Validate a set of [`BlockInfo`] in sequence and apply them if
  360. /// all are valid.
  361. ///
  362. /// Note: this function should only be used in tests when we don't
  363. /// want to perform consensus logic and always remember to purge
  364. /// new trees from the database if not needed.
  365. pub async fn add_test_blocks(&mut self, blocks: &[BlockInfo]) -> Result<()> {
  366. debug!(target: "validator::add_test_blocks", "Instantiating BlockchainOverlay");
  367. let overlay = BlockchainOverlay::new(&self.blockchain)?;
  368. // Retrieve last block
  369. let mut previous = &overlay.lock().unwrap().last_block()?;
  370. // Retrieve last block difficulty to access current ranks
  371. let last_difficulty = self.blockchain.last_block_difficulty()?;
  372. let mut current_targets_rank = last_difficulty.ranks.targets_rank;
  373. let mut current_hashes_rank = last_difficulty.ranks.hashes_rank;
  374. // Grab current PoW module to validate each block
  375. let mut module = self.consensus.module.clone();
  376. // Keep track of all blocks transactions to remove them from
  377. // pending txs store.
  378. let mut removed_txs = vec![];
  379. // Keep track of all block database state diffs and their
  380. // inverse.
  381. let mut diffs_heights = vec![];
  382. let mut diffs = vec![];
  383. let mut inverse_diffs = vec![];
  384. // All blocks must be before the future timestamp upper bound
  385. let timestamp_bound = Some(module.future_timestamp_upper_bound()?);
  386. // Validate and insert each block
  387. for block in blocks {
  388. // Verify block
  389. match verify_block(
  390. &overlay,
  391. &diffs,
  392. &mut module,
  393. block,
  394. previous,
  395. timestamp_bound,
  396. self.verify_fees,
  397. )
  398. .await
  399. {
  400. Ok(()) => { /* Do nothing */ }
  401. // Skip already existing block
  402. Err(Error::BlockAlreadyExists(_)) => {
  403. previous = block;
  404. continue
  405. }
  406. Err(e) => {
  407. error!(target: "validator::add_test_blocks", "Erroneous block found in set: {e}");
  408. return Err(Error::BlockIsInvalid(block.hash().as_string()))
  409. }
  410. };
  411. // Calculate block rank
  412. let (next_difficulty, target_distance_sq, hash_distance_sq) =
  413. block_rank(&mut module, block)?;
  414. // Update current ranks
  415. current_targets_rank += target_distance_sq.clone();
  416. current_hashes_rank += hash_distance_sq.clone();
  417. // Generate block difficulty and update PoW module
  418. let cumulative_difficulty =
  419. module.cumulative_difficulty.clone() + next_difficulty.clone();
  420. let ranks = BlockRanks::new(
  421. target_distance_sq,
  422. current_targets_rank.clone(),
  423. hash_distance_sq,
  424. current_hashes_rank.clone(),
  425. );
  426. let block_difficulty = BlockDifficulty::new(
  427. block.header.height,
  428. block.header.timestamp,
  429. next_difficulty,
  430. cumulative_difficulty,
  431. ranks,
  432. );
  433. module.append_difficulty(&overlay, &block.header, block_difficulty)?;
  434. // Store block transactions
  435. for tx in &block.txs {
  436. removed_txs.push(tx.clone());
  437. }
  438. // Store block database state diff and its inverse
  439. diffs_heights.push(block.header.height);
  440. let diff = overlay.lock().unwrap().overlay.lock().unwrap().diff(&diffs)?;
  441. inverse_diffs.push(diff.inverse());
  442. diffs.push(diff);
  443. // Use last inserted block as next iteration previous
  444. previous = block;
  445. }
  446. debug!(target: "validator::add_test_blocks", "Applying overlay changes");
  447. overlay.lock().unwrap().overlay.lock().unwrap().apply()?;
  448. // Store the block diffs
  449. self.blockchain.blocks.insert_state_inverse_diff(&diffs_heights, &inverse_diffs)?;
  450. // Remove blocks transactions from pending txs store
  451. self.blockchain.remove_pending_txs(&removed_txs)?;
  452. // Update PoW module
  453. self.consensus.module = module;
  454. Ok(())
  455. }
  456. /// Validate a set of [`Transaction`] in sequence and apply them if
  457. /// all are valid. In case any of the transactions fail, they will
  458. /// be returned to the caller. The function takes a boolean called
  459. /// `write` which tells it to actually write the state transitions
  460. /// to the database, and a boolean called `verify_fees` to
  461. /// overwrite the nodes configured `verify_fees` flag.
  462. ///
  463. /// Returns the total gas used and total paid fees for the given
  464. /// transactions.
  465. ///
  466. /// Note: This function should only be used in tests and always
  467. /// remember to purge new trees from the database if not needed.
  468. pub async fn add_test_transactions(
  469. &self,
  470. txs: &[Transaction],
  471. verifying_block_height: u32,
  472. block_target: u32,
  473. write: bool,
  474. verify_fees: bool,
  475. ) -> Result<(u64, u64)> {
  476. debug!(target: "validator::add_transactions", "Instantiating BlockchainOverlay");
  477. let overlay = BlockchainOverlay::new(&self.blockchain)?;
  478. // Verify all transactions and get erroneous ones
  479. let verify_result = verify_transactions(
  480. &overlay,
  481. verifying_block_height,
  482. block_target,
  483. txs,
  484. &mut MerkleTree::new(1),
  485. verify_fees,
  486. )
  487. .await;
  488. let lock = overlay.lock().unwrap();
  489. let mut overlay = lock.overlay.lock().unwrap();
  490. let gas_values = verify_result?;
  491. if !write {
  492. debug!(target: "validator::add_transactions", "Skipping apply of state updates because write=false");
  493. return Ok(gas_values)
  494. }
  495. debug!(target: "validator::add_transactions", "Applying overlay changes");
  496. overlay.apply()?;
  497. Ok(gas_values)
  498. }
  499. /// Validate a producer `Transaction` and apply it if valid. In
  500. /// case the transactions fail, ir will be returned to the caller.
  501. /// The function takes a boolean called `write` which tells it to
  502. /// actually write the state transitions to the database.
  503. ///
  504. /// Note: This function should only be used in tests and always
  505. /// remember to purge new trees from the database if not needed.
  506. pub async fn add_test_producer_transaction(
  507. &self,
  508. tx: &Transaction,
  509. verifying_block_height: u32,
  510. block_target: u32,
  511. write: bool,
  512. ) -> Result<()> {
  513. debug!(target: "validator::add_test_producer_transaction", "Instantiating BlockchainOverlay");
  514. let overlay = BlockchainOverlay::new(&self.blockchain)?;
  515. // Verify transaction
  516. let mut erroneous_txs = vec![];
  517. if let Err(e) = verify_producer_transaction(
  518. &overlay,
  519. verifying_block_height,
  520. block_target,
  521. tx,
  522. &mut MerkleTree::new(1),
  523. )
  524. .await
  525. {
  526. warn!(target: "validator::add_test_producer_transaction", "Transaction verification failed: {e}");
  527. erroneous_txs.push(tx.clone());
  528. }
  529. let lock = overlay.lock().unwrap();
  530. let mut overlay = lock.overlay.lock().unwrap();
  531. if !erroneous_txs.is_empty() {
  532. warn!(target: "validator::add_test_producer_transaction", "Erroneous transactions found in set");
  533. return Err(TxVerifyFailed::ErroneousTxs(erroneous_txs).into())
  534. }
  535. if !write {
  536. debug!(target: "validator::add_test_producer_transaction", "Skipping apply of state updates because write=false");
  537. return Ok(())
  538. }
  539. debug!(target: "validator::add_test_producer_transaction", "Applying overlay changes");
  540. overlay.apply()?;
  541. Ok(())
  542. }
  543. /// Retrieve all existing blocks and try to apply them
  544. /// to an in memory overlay to verify their correctness.
  545. /// Be careful as this will try to load everything in memory.
  546. ///
  547. /// Note: Always remember to purge new trees from the database if
  548. /// not needed.
  549. pub async fn validate_blockchain(
  550. &self,
  551. pow_target: u32,
  552. pow_fixed_difficulty: Option<BigUint>,
  553. ) -> Result<()> {
  554. // An empty blockchain is considered valid
  555. let mut blocks_count = self.blockchain.len()? as u32;
  556. info!(target: "validator::validate_blockchain", "Validating {blocks_count} blocks...");
  557. if blocks_count == 0 {
  558. info!(target: "validator::validate_blockchain", "Blockchain validated successfully!");
  559. return Ok(())
  560. }
  561. // Create an in memory blockchain overlay
  562. let (kvdb, _folder) = Database::open_temp()?;
  563. let blockchain = Blockchain::new(&kvdb)?;
  564. let overlay = BlockchainOverlay::new(&blockchain)?;
  565. // Set previous
  566. let mut previous = self.blockchain.genesis_block()?;
  567. // Deploy native wasm contracts
  568. deploy_native_contracts(&overlay, pow_target).await?;
  569. // Update the contracts states monotree
  570. let diff = overlay.lock().unwrap().overlay.lock().unwrap().diff(&[])?;
  571. overlay.lock().unwrap().contracts.update_state_monotree(&diff)?;
  572. // Validate genesis block
  573. verify_genesis_block(&overlay, &[diff], &previous, pow_target).await?;
  574. info!(target: "validator::validate_blockchain", "Genesis block validated successfully!");
  575. // Write the changes to the in memory db
  576. overlay.lock().unwrap().overlay.lock().unwrap().apply()?;
  577. // Create a PoW module to validate each block
  578. let mut module = PoWModule::new(blockchain, pow_target, pow_fixed_difficulty, Some(0))?;
  579. // Keep track of all block database state diffs
  580. let mut diffs = vec![];
  581. // All blocks must be before the future timestamp upper bound
  582. let timestamp_bound = Some(module.future_timestamp_upper_bound()?);
  583. // Validate and insert each block
  584. info!(target: "validator::validate_blockchain", "Validating rest blocks...");
  585. blocks_count -= 1;
  586. let mut index = 1;
  587. while index <= blocks_count {
  588. // Grab block
  589. let block = self.blockchain.get_blocks_by_heights(&[index])?[0].clone();
  590. // Verify block
  591. if let Err(e) = verify_block(
  592. &overlay,
  593. &diffs,
  594. &mut module,
  595. &block,
  596. &previous,
  597. timestamp_bound,
  598. self.verify_fees,
  599. )
  600. .await
  601. {
  602. error!(target: "validator::validate_blockchain", "Erroneous block found in set: {e}");
  603. return Err(Error::BlockIsInvalid(block.hash().as_string()))
  604. };
  605. // Update PoW module
  606. module.append(&block.header, &module.next_difficulty()?)?;
  607. // Store block database state diff
  608. let diff = overlay.lock().unwrap().overlay.lock().unwrap().diff(&diffs)?;
  609. diffs.push(diff);
  610. // Use last inserted block as next iteration previous
  611. previous = block;
  612. info!(target: "validator::validate_blockchain", "Block {index}/{blocks_count} validated successfully!");
  613. index += 1;
  614. }
  615. info!(target: "validator::validate_blockchain", "Blockchain validated successfully!");
  616. Ok(())
  617. }
  618. /// Auxiliary function to grab current mining RandomX key,
  619. /// based on next block height.
  620. /// If no forks exist, returns the canonical key.
  621. pub async fn current_mining_randomx_key(&self) -> Result<HeaderHash> {
  622. self.consensus.current_mining_randomx_key().await
  623. }
  624. /// Auxiliary function to grab best current fork full clone.
  625. pub async fn best_current_fork(&self) -> Result<Fork> {
  626. self.consensus.best_current_fork().await
  627. }
  628. /// Auxiliary function to retrieve current best fork next block
  629. /// height.
  630. pub async fn best_fork_next_block_height(&self) -> Result<u32> {
  631. let index = best_fork_index(&self.consensus.forks)?;
  632. let fork = &self.consensus.forks[index];
  633. let next_block_height = fork.get_next_block_height()?;
  634. Ok(next_block_height)
  635. }
  636. /// Auxiliary function to reset the validator blockchain and
  637. /// consensus states to the provided block height.
  638. pub async fn reset_to_height(&mut self, height: u32) -> Result<()> {
  639. info!(target: "validator::reset_to_height", "Resetting validator to height: {height}");
  640. // Reset our databasse to provided height
  641. self.blockchain.reset_to_height(height)?;
  642. // Reset consensus PoW module
  643. self.consensus.reset_pow_module().await?;
  644. // Purge current forks
  645. self.consensus.purge_forks().await?;
  646. info!(target: "validator::reset_to_height", "Validator reset successfully!");
  647. Ok(())
  648. }
  649. /// Auxiliary function to rebuild the block difficulties database
  650. /// based on current validator blockchain.
  651. /// Be careful as this will try to load everything in memory.
  652. pub async fn rebuild_block_difficulties(
  653. &self,
  654. pow_target: u32,
  655. pow_fixed_difficulty: Option<BigUint>,
  656. ) -> Result<()> {
  657. info!(target: "validator::rebuild_block_difficulties", "Rebuilding validator block difficulties...");
  658. // Clear the block difficulties tree
  659. self.blockchain.blocks.difficulty.clear()?;
  660. // An empty blockchain doesn't have difficulty records
  661. let mut blocks_count = self.blockchain.len()? as u32;
  662. info!(target: "validator::rebuild_block_difficulties", "Rebuilding {blocks_count} block difficulties...");
  663. if blocks_count == 0 {
  664. info!(target: "validator::rebuild_block_difficulties", "Validator block difficulties rebuilt successfully!");
  665. return Ok(())
  666. }
  667. // Create a PoW module and an in memory overlay to compute each
  668. // block difficulty.
  669. let mut module =
  670. PoWModule::new(self.blockchain.clone(), pow_target, pow_fixed_difficulty, Some(0))?;
  671. // Grab genesis block difficulty to access current ranks
  672. let genesis_block = self.blockchain.genesis_block()?;
  673. let last_difficulty = BlockDifficulty::genesis(genesis_block.header.timestamp);
  674. let mut targets_rank = last_difficulty.ranks.targets_rank;
  675. let mut hashes_rank = last_difficulty.ranks.hashes_rank;
  676. // Grab each block to compute its difficulty
  677. blocks_count -= 1;
  678. let mut index = 1;
  679. while index <= blocks_count {
  680. // Grab block
  681. let block = self.blockchain.get_blocks_by_heights(&[index])?[0].clone();
  682. // Calculate block rank
  683. let (next_difficulty, target_distance_sq, hash_distance_sq) =
  684. block_rank(&mut module, &block)?;
  685. // Update chain ranks
  686. targets_rank += target_distance_sq.clone();
  687. hashes_rank += hash_distance_sq.clone();
  688. // Generate block difficulty and update PoW module
  689. let cumulative_difficulty =
  690. module.cumulative_difficulty.clone() + next_difficulty.clone();
  691. let ranks = BlockRanks::new(
  692. target_distance_sq,
  693. targets_rank.clone(),
  694. hash_distance_sq,
  695. hashes_rank.clone(),
  696. );
  697. let block_difficulty = BlockDifficulty::new(
  698. block.header.height,
  699. block.header.timestamp,
  700. next_difficulty,
  701. cumulative_difficulty,
  702. ranks,
  703. );
  704. module.append(&block.header, &block_difficulty.difficulty)?;
  705. // Add difficulty to database
  706. self.blockchain.blocks.insert_difficulty(&[block_difficulty])?;
  707. info!(target: "validator::rebuild_block_difficulties", "Block {index}/{blocks_count} difficulty added successfully!");
  708. index += 1;
  709. }
  710. // Flush the database
  711. self.blockchain.kvdb.flush_default_mode()?;
  712. info!(target: "validator::rebuild_block_difficulties", "Validator block difficulties rebuilt successfully!");
  713. Ok(())
  714. }
  715. }