mod.rs 36 KB

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