mod.rs 28 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748
  1. /* This file is part of DarkFi (https://dark.fi)
  2. *
  3. * Copyright (C) 2020-2024 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 log::{debug, error, info, warn};
  21. use num_bigint::BigUint;
  22. use sled_overlay::sled;
  23. use smol::lock::RwLock;
  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. /// Verification functions
  41. pub mod verification;
  42. use verification::{
  43. verify_block, verify_checkpoint_block, verify_genesis_block, verify_producer_transaction,
  44. verify_transaction, verify_transactions,
  45. };
  46. /// Fee calculation helpers
  47. pub mod fees;
  48. /// Helper utilities
  49. pub mod utils;
  50. use utils::{best_fork_index, block_rank, deploy_native_contracts};
  51. /// Configuration for initializing [`Validator`]
  52. #[derive(Clone)]
  53. pub struct ValidatorConfig {
  54. /// Currently configured finalization security threshold
  55. pub finalization_threshold: usize,
  56. /// Currently configured PoW target
  57. pub pow_target: u32,
  58. /// Optional fixed difficulty, for testing purposes
  59. pub pow_fixed_difficulty: Option<BigUint>,
  60. /// Genesis block
  61. pub genesis_block: BlockInfo,
  62. /// Flag to enable tx fee verification
  63. pub verify_fees: bool,
  64. }
  65. /// Atomic pointer to validator.
  66. pub type ValidatorPtr = Arc<Validator>;
  67. /// This struct represents a DarkFi validator node.
  68. pub struct Validator {
  69. /// Canonical (finalized) blockchain
  70. pub blockchain: Blockchain,
  71. /// Hot/Live data used by the consensus algorithm
  72. pub consensus: Consensus,
  73. /// Flag signalling node has finished initial sync
  74. pub synced: RwLock<bool>,
  75. /// Flag to enable tx fee verification
  76. pub verify_fees: bool,
  77. }
  78. impl Validator {
  79. pub async fn new(db: &sled::Db, config: &ValidatorConfig) -> Result<ValidatorPtr> {
  80. info!(target: "validator::new", "Initializing Validator");
  81. info!(target: "validator::new", "Initializing Blockchain");
  82. let blockchain = Blockchain::new(db)?;
  83. // Create an overlay over whole blockchain so we can write stuff
  84. let overlay = BlockchainOverlay::new(&blockchain)?;
  85. // Deploy native wasm contracts
  86. deploy_native_contracts(&overlay, config.pow_target).await?;
  87. // Add genesis block if blockchain is empty
  88. if blockchain.genesis().is_err() {
  89. info!(target: "validator::new", "Appending genesis block");
  90. verify_genesis_block(&overlay, &config.genesis_block, config.pow_target).await?;
  91. };
  92. // Write the changes to the actual chain db
  93. overlay.lock().unwrap().overlay.lock().unwrap().apply()?;
  94. info!(target: "validator::new", "Initializing Consensus");
  95. let consensus = Consensus::new(
  96. blockchain.clone(),
  97. config.finalization_threshold,
  98. config.pow_target,
  99. config.pow_fixed_difficulty.clone(),
  100. )?;
  101. // Create the actual state
  102. let state = Arc::new(Self {
  103. blockchain,
  104. consensus,
  105. synced: RwLock::new(false),
  106. verify_fees: config.verify_fees,
  107. });
  108. info!(target: "validator::new", "Finished initializing validator");
  109. Ok(state)
  110. }
  111. /// Auxiliary function to compute provided transaction's total gas,
  112. /// against current best fork.
  113. /// The function takes a boolean called `verify_fee` to overwrite
  114. /// the nodes configured `verify_fees` flag.
  115. pub async fn calculate_gas(&self, tx: &Transaction, verify_fee: bool) -> Result<u64> {
  116. // Grab the best fork to verify against
  117. let forks = self.consensus.forks.read().await;
  118. let fork = forks[best_fork_index(&forks)?].full_clone()?;
  119. drop(forks);
  120. // Map of ZK proof verifying keys for the transaction
  121. let mut vks: HashMap<[u8; 32], HashMap<String, VerifyingKey>> = HashMap::new();
  122. for call in &tx.calls {
  123. vks.insert(call.data.contract_id.to_bytes(), HashMap::new());
  124. }
  125. // Grab forks' next block height
  126. let next_block_height = fork.get_next_block_height()?;
  127. // Verify transaction to grab the gas used
  128. let verify_result = verify_transaction(
  129. &fork.overlay,
  130. next_block_height,
  131. self.consensus.module.read().await.target,
  132. tx,
  133. &mut MerkleTree::new(1),
  134. &mut vks,
  135. verify_fee,
  136. )
  137. .await;
  138. // Purge new trees
  139. fork.overlay.lock().unwrap().overlay.lock().unwrap().purge_new_trees()?;
  140. Ok(verify_result?.0)
  141. }
  142. /// The node retrieves a transaction, validates its state transition,
  143. /// and appends it to the pending txs store.
  144. pub async fn append_tx(&self, tx: &Transaction, write: bool) -> Result<()> {
  145. let tx_hash = tx.hash();
  146. // Check if we have already seen this tx
  147. let tx_in_txstore = self.blockchain.transactions.contains(&tx_hash)?;
  148. let tx_in_pending_txs_store = self.blockchain.transactions.contains_pending(&tx_hash)?;
  149. if tx_in_txstore || tx_in_pending_txs_store {
  150. info!(target: "validator::append_tx", "We have already seen this tx");
  151. return Err(TxVerifyFailed::AlreadySeenTx(tx_hash.as_string()).into())
  152. }
  153. // Verify state transition
  154. info!(target: "validator::append_tx", "Starting state transition validation");
  155. let tx_vec = [tx.clone()];
  156. let mut valid = false;
  157. // Grab a lock over current consensus forks state
  158. let mut forks = self.consensus.forks.write().await;
  159. // Iterate over node forks to verify transaction validity in their overlays
  160. for fork in forks.iter_mut() {
  161. // Clone fork state
  162. let fork_clone = fork.full_clone()?;
  163. // Grab forks' next block height
  164. let next_block_height = fork_clone.get_next_block_height()?;
  165. // Verify transaction
  166. let verify_result = verify_transactions(
  167. &fork_clone.overlay,
  168. next_block_height,
  169. self.consensus.module.read().await.target,
  170. &tx_vec,
  171. &mut MerkleTree::new(1),
  172. self.verify_fees,
  173. )
  174. .await;
  175. // Purge new trees
  176. fork_clone.overlay.lock().unwrap().overlay.lock().unwrap().purge_new_trees()?;
  177. // Handle response
  178. match verify_result {
  179. Ok(_) => {}
  180. Err(Error::TxVerifyFailed(TxVerifyFailed::ErroneousTxs(_))) => continue,
  181. Err(e) => return Err(e),
  182. }
  183. valid = true;
  184. // Store transaction hash in forks' mempool
  185. if write {
  186. fork.mempool.push(tx_hash);
  187. }
  188. }
  189. // Drop forks lock
  190. drop(forks);
  191. // Return error if transaction is not valid for any fork
  192. if !valid {
  193. return Err(TxVerifyFailed::ErroneousTxs(tx_vec.to_vec()).into())
  194. }
  195. // Add transaction to pending txs store
  196. if write {
  197. self.blockchain.add_pending_txs(&tx_vec)?;
  198. info!(target: "validator::append_tx", "Appended tx to pending txs store");
  199. }
  200. Ok(())
  201. }
  202. /// The node removes invalid transactions from the pending txs store.
  203. pub async fn purge_pending_txs(&self) -> Result<()> {
  204. info!(target: "validator::purge_pending_txs", "Removing invalid transactions from pending transactions store...");
  205. // Check if any pending transactions exist
  206. let pending_txs = self.blockchain.get_pending_txs()?;
  207. if pending_txs.is_empty() {
  208. info!(target: "validator::purge_pending_txs", "No pending transactions found");
  209. return Ok(())
  210. }
  211. // Grab a lock over current consensus forks state
  212. let mut forks = self.consensus.forks.write().await;
  213. let mut removed_txs = vec![];
  214. for tx in pending_txs {
  215. let tx_hash = tx.hash();
  216. let tx_vec = [tx.clone()];
  217. let mut valid = false;
  218. // Iterate over node forks to verify transaction validity in their overlays
  219. for fork in forks.iter_mut() {
  220. // Clone fork state
  221. let fork_clone = fork.full_clone()?;
  222. // Grab forks' next block height
  223. let next_block_height = fork_clone.get_next_block_height()?;
  224. // Verify transaction
  225. let verify_result = verify_transactions(
  226. &fork_clone.overlay,
  227. next_block_height,
  228. self.consensus.module.read().await.target,
  229. &tx_vec,
  230. &mut MerkleTree::new(1),
  231. self.verify_fees,
  232. )
  233. .await;
  234. // Purge new trees
  235. fork_clone.overlay.lock().unwrap().overlay.lock().unwrap().purge_new_trees()?;
  236. // Handle response
  237. match verify_result {
  238. Ok(_) => {
  239. valid = true;
  240. continue
  241. }
  242. Err(Error::TxVerifyFailed(TxVerifyFailed::ErroneousTxs(_))) => {}
  243. Err(e) => return Err(e),
  244. }
  245. // Remove erroneous transaction from forks' mempool
  246. fork.mempool.retain(|x| *x != tx_hash);
  247. }
  248. // Remove pending transaction if it's not valid for canonical or any fork
  249. if !valid {
  250. removed_txs.push(tx)
  251. }
  252. }
  253. // Drop forks lock
  254. drop(forks);
  255. if removed_txs.is_empty() {
  256. info!(target: "validator::purge_pending_txs", "No erroneous transactions found");
  257. return Ok(())
  258. }
  259. info!(target: "validator::purge_pending_txs", "Removing {} erroneous transactions...", removed_txs.len());
  260. self.blockchain.remove_pending_txs(&removed_txs)?;
  261. Ok(())
  262. }
  263. /// The node locks its consensus state and tries to append provided proposal.
  264. pub async fn append_proposal(&self, proposal: &Proposal) -> Result<()> {
  265. // Grab append lock so we restrict concurrent calls of this function
  266. let append_lock = self.consensus.append_lock.write().await;
  267. // Execute append
  268. let result = self.consensus.append_proposal(proposal, self.verify_fees).await;
  269. // Release append lock
  270. drop(append_lock);
  271. result
  272. }
  273. /// The node checks if best fork can be finalized.
  274. /// If proposals can be finalized, node appends them to canonical,
  275. /// and resets the current forks.
  276. pub async fn finalization(&self) -> Result<Vec<BlockInfo>> {
  277. // Grab append lock so no new proposals can be appended while
  278. // we execute finalization
  279. let append_lock = self.consensus.append_lock.write().await;
  280. info!(target: "validator::finalization", "Performing finalization check");
  281. // Grab best fork index that can be finalized
  282. let finalized_fork = match self.consensus.finalization().await {
  283. Ok(f) => f,
  284. Err(e) => {
  285. drop(append_lock);
  286. return Err(e)
  287. }
  288. };
  289. if finalized_fork.is_none() {
  290. info!(target: "validator::finalization", "No proposals can be finalized");
  291. drop(append_lock);
  292. return Ok(vec![])
  293. }
  294. // Grab the actual best fork
  295. let finalized_fork = finalized_fork.unwrap();
  296. let mut forks = self.consensus.forks.write().await;
  297. let fork = &mut forks[finalized_fork];
  298. // Find the excess over finalization threshold
  299. let excess = (fork.proposals.len() - self.consensus.finalization_threshold) + 1;
  300. // Grab finalized proposals and update fork's sequences
  301. let rest_proposals = fork.proposals.split_off(excess);
  302. let rest_diffs = fork.diffs.split_off(excess);
  303. let finalized_proposals = fork.proposals.clone();
  304. let diffs = fork.diffs.clone();
  305. fork.proposals = rest_proposals;
  306. fork.diffs = rest_diffs;
  307. // Grab finalized proposals blocks
  308. let finalized_blocks =
  309. fork.overlay.lock().unwrap().get_blocks_by_hash(&finalized_proposals)?;
  310. // Apply finalized proposals diffs and update PoW module
  311. let mut module = self.consensus.module.write().await;
  312. let mut finalized_txs = vec![];
  313. info!(target: "validator::finalization", "Finalizing proposals:");
  314. for (index, proposal) in finalized_proposals.iter().enumerate() {
  315. info!(target: "validator::finalization", "\t{} - {}", proposal, finalized_blocks[index].header.height);
  316. fork.overlay.lock().unwrap().overlay.lock().unwrap().apply_diff(&diffs[index])?;
  317. let next_difficulty = module.next_difficulty()?;
  318. module.append(finalized_blocks[index].header.timestamp, &next_difficulty);
  319. finalized_txs.extend_from_slice(&finalized_blocks[index].txs);
  320. }
  321. drop(module);
  322. drop(forks);
  323. // Reset forks starting with the finalized blocks
  324. self.consensus.reset_forks(&finalized_proposals, &finalized_fork, &finalized_txs).await?;
  325. info!(target: "validator::finalization", "Finalization completed!");
  326. // Release append lock
  327. drop(append_lock);
  328. Ok(finalized_blocks)
  329. }
  330. /// Apply provided set of [`BlockInfo`] without doing formal verification.
  331. /// A set of ['HeaderHash`] is also provided, to verify that the provided
  332. /// block hash matches the expected header one.
  333. /// Note: this function should only be used for blocks received using a
  334. /// checkpoint, since in that case we enforce the node to follow the sequence,
  335. /// assuming they all its blocks are valid. Additionally, it will update
  336. /// any forks to a single empty one, holding the updated module.
  337. pub async fn add_checkpoint_blocks(
  338. &self,
  339. blocks: &[BlockInfo],
  340. headers: &[HeaderHash],
  341. ) -> Result<()> {
  342. // Check provided sequences are the same length
  343. if blocks.len() != headers.len() {
  344. return Err(Error::InvalidInputLengths)
  345. }
  346. debug!(target: "validator::add_checkpoint_blocks", "Instantiating BlockchainOverlay");
  347. let overlay = BlockchainOverlay::new(&self.blockchain)?;
  348. // Retrieve last block difficulty to access current ranks
  349. let last_difficulty = self.blockchain.last_block_difficulty()?;
  350. let mut current_targets_rank = last_difficulty.ranks.targets_rank;
  351. let mut current_hashes_rank = last_difficulty.ranks.hashes_rank;
  352. // Grab current PoW module to validate each block
  353. let mut module = self.consensus.module.read().await.clone();
  354. // Keep track of all blocks transactions to remove them from pending txs store
  355. let mut removed_txs = vec![];
  356. // Validate and insert each block
  357. for (index, block) in blocks.iter().enumerate() {
  358. // Verify block
  359. match verify_checkpoint_block(&overlay, block, &headers[index], module.target).await {
  360. Ok(()) => { /* Do nothing */ }
  361. // Skip already existing block
  362. Err(Error::BlockAlreadyExists(_)) => continue,
  363. Err(e) => {
  364. error!(target: "validator::add_checkpoint_blocks", "Erroneous block found in set: {}", e);
  365. overlay.lock().unwrap().overlay.lock().unwrap().purge_new_trees()?;
  366. return Err(Error::BlockIsInvalid(block.hash().as_string()))
  367. }
  368. };
  369. // Grab next mine target and difficulty
  370. let (next_target, next_difficulty) = module.next_mine_target_and_difficulty()?;
  371. // Calculate block rank
  372. let (target_distance_sq, hash_distance_sq) = block_rank(block, &next_target);
  373. // Update current ranks
  374. current_targets_rank += target_distance_sq.clone();
  375. current_hashes_rank += hash_distance_sq.clone();
  376. // Generate block difficulty and update PoW module
  377. let cummulative_difficulty =
  378. module.cummulative_difficulty.clone() + next_difficulty.clone();
  379. let ranks = BlockRanks::new(
  380. target_distance_sq,
  381. current_targets_rank.clone(),
  382. hash_distance_sq,
  383. current_hashes_rank.clone(),
  384. );
  385. let block_difficulty = BlockDifficulty::new(
  386. block.header.height,
  387. block.header.timestamp,
  388. next_difficulty,
  389. cummulative_difficulty,
  390. ranks,
  391. );
  392. module.append_difficulty(&overlay, block_difficulty)?;
  393. // Store block transactions
  394. for tx in &block.txs {
  395. removed_txs.push(tx.clone());
  396. }
  397. }
  398. debug!(target: "validator::add_checkpoint_blocks", "Applying overlay changes");
  399. overlay.lock().unwrap().overlay.lock().unwrap().apply()?;
  400. // Remove blocks transactions from pending txs store
  401. self.blockchain.remove_pending_txs(&removed_txs)?;
  402. // Update PoW module
  403. *self.consensus.module.write().await = module.clone();
  404. // Update forks
  405. *self.consensus.forks.write().await =
  406. vec![Fork::new(self.blockchain.clone(), module).await?];
  407. Ok(())
  408. }
  409. /// Validate a set of [`BlockInfo`] in sequence and apply them if all are valid.
  410. /// Note: this function should only be used in tests when we don't want to
  411. /// perform consensus logic.
  412. pub async fn add_test_blocks(&self, blocks: &[BlockInfo]) -> Result<()> {
  413. debug!(target: "validator::add_test_blocks", "Instantiating BlockchainOverlay");
  414. let overlay = BlockchainOverlay::new(&self.blockchain)?;
  415. // Retrieve last block
  416. let mut previous = &overlay.lock().unwrap().last_block()?;
  417. // Retrieve last block difficulty to access current ranks
  418. let last_difficulty = self.blockchain.last_block_difficulty()?;
  419. let mut current_targets_rank = last_difficulty.ranks.targets_rank;
  420. let mut current_hashes_rank = last_difficulty.ranks.hashes_rank;
  421. // Grab current PoW module to validate each block
  422. let mut module = self.consensus.module.read().await.clone();
  423. // Keep track of all blocks transactions to remove them from pending txs store
  424. let mut removed_txs = vec![];
  425. // Validate and insert each block
  426. for block in blocks {
  427. // Verify block
  428. match verify_block(&overlay, &module, block, previous, self.verify_fees).await {
  429. Ok(()) => { /* Do nothing */ }
  430. // Skip already existing block
  431. Err(Error::BlockAlreadyExists(_)) => {
  432. previous = block;
  433. continue
  434. }
  435. Err(e) => {
  436. error!(target: "validator::add_test_blocks", "Erroneous block found in set: {}", e);
  437. overlay.lock().unwrap().overlay.lock().unwrap().purge_new_trees()?;
  438. return Err(Error::BlockIsInvalid(block.hash().as_string()))
  439. }
  440. };
  441. // Grab next mine target and difficulty
  442. let (next_target, next_difficulty) = module.next_mine_target_and_difficulty()?;
  443. // Calculate block rank
  444. let (target_distance_sq, hash_distance_sq) = block_rank(block, &next_target);
  445. // Update current ranks
  446. current_targets_rank += target_distance_sq.clone();
  447. current_hashes_rank += hash_distance_sq.clone();
  448. // Generate block difficulty and update PoW module
  449. let cummulative_difficulty =
  450. module.cummulative_difficulty.clone() + next_difficulty.clone();
  451. let ranks = BlockRanks::new(
  452. target_distance_sq,
  453. current_targets_rank.clone(),
  454. hash_distance_sq,
  455. current_hashes_rank.clone(),
  456. );
  457. let block_difficulty = BlockDifficulty::new(
  458. block.header.height,
  459. block.header.timestamp,
  460. next_difficulty,
  461. cummulative_difficulty,
  462. ranks,
  463. );
  464. module.append_difficulty(&overlay, block_difficulty)?;
  465. // Store block transactions
  466. for tx in &block.txs {
  467. removed_txs.push(tx.clone());
  468. }
  469. // Use last inserted block as next iteration previous
  470. previous = block;
  471. }
  472. debug!(target: "validator::add_test_blocks", "Applying overlay changes");
  473. overlay.lock().unwrap().overlay.lock().unwrap().apply()?;
  474. // Purge pending erroneous txs since canonical state has been changed
  475. self.blockchain.remove_pending_txs(&removed_txs)?;
  476. self.purge_pending_txs().await?;
  477. // Update PoW module
  478. *self.consensus.module.write().await = module;
  479. Ok(())
  480. }
  481. /// Validate a set of [`Transaction`] in sequence and apply them if all are valid.
  482. /// In case any of the transactions fail, they will be returned to the caller.
  483. /// The function takes a boolean called `write` which tells it to actually write
  484. /// the state transitions to the database, and a boolean called `verify_fees` to
  485. /// overwrite the nodes configured `verify_fees` flag.
  486. ///
  487. /// Returns the total gas used and total paid fees for the given transactions.
  488. /// Note: this function should only be used in tests.
  489. pub async fn add_test_transactions(
  490. &self,
  491. txs: &[Transaction],
  492. verifying_block_height: u32,
  493. block_target: u32,
  494. write: bool,
  495. verify_fees: bool,
  496. ) -> Result<(u64, u64)> {
  497. debug!(target: "validator::add_transactions", "Instantiating BlockchainOverlay");
  498. let overlay = BlockchainOverlay::new(&self.blockchain)?;
  499. // Verify all transactions and get erroneous ones
  500. let verify_result = verify_transactions(
  501. &overlay,
  502. verifying_block_height,
  503. block_target,
  504. txs,
  505. &mut MerkleTree::new(1),
  506. verify_fees,
  507. )
  508. .await;
  509. let lock = overlay.lock().unwrap();
  510. let mut overlay = lock.overlay.lock().unwrap();
  511. if let Err(e) = verify_result {
  512. overlay.purge_new_trees()?;
  513. return Err(e)
  514. }
  515. let gas_values = verify_result.unwrap();
  516. if !write {
  517. debug!(target: "validator::add_transactions", "Skipping apply of state updates because write=false");
  518. overlay.purge_new_trees()?;
  519. return Ok(gas_values)
  520. }
  521. debug!(target: "validator::add_transactions", "Applying overlay changes");
  522. overlay.apply()?;
  523. Ok(gas_values)
  524. }
  525. /// Validate a producer `Transaction` and apply it if valid.
  526. /// In case the transactions fail, ir will be returned to the caller.
  527. /// The function takes a boolean called `write` which tells it to actually write
  528. /// the state transitions to the database.
  529. /// This should be only used for test purposes.
  530. pub async fn add_test_producer_transaction(
  531. &self,
  532. tx: &Transaction,
  533. verifying_block_height: u32,
  534. block_target: u32,
  535. write: bool,
  536. ) -> Result<()> {
  537. debug!(target: "validator::add_test_producer_transaction", "Instantiating BlockchainOverlay");
  538. let overlay = BlockchainOverlay::new(&self.blockchain)?;
  539. // Verify transaction
  540. let mut erroneous_txs = vec![];
  541. if let Err(e) = verify_producer_transaction(
  542. &overlay,
  543. verifying_block_height,
  544. block_target,
  545. tx,
  546. &mut MerkleTree::new(1),
  547. )
  548. .await
  549. {
  550. warn!(target: "validator::add_test_producer_transaction", "Transaction verification failed: {}", e);
  551. erroneous_txs.push(tx.clone());
  552. }
  553. let lock = overlay.lock().unwrap();
  554. let mut overlay = lock.overlay.lock().unwrap();
  555. if !erroneous_txs.is_empty() {
  556. warn!(target: "validator::add_test_producer_transaction", "Erroneous transactions found in set");
  557. overlay.purge_new_trees()?;
  558. return Err(TxVerifyFailed::ErroneousTxs(erroneous_txs).into())
  559. }
  560. if !write {
  561. debug!(target: "validator::add_test_producer_transaction", "Skipping apply of state updates because write=false");
  562. overlay.purge_new_trees()?;
  563. return Ok(())
  564. }
  565. debug!(target: "validator::add_test_producer_transaction", "Applying overlay changes");
  566. overlay.apply()?;
  567. Ok(())
  568. }
  569. /// Retrieve all existing blocks and try to apply them
  570. /// to an in memory overlay to verify their correctness.
  571. /// Be careful as this will try to load everything in memory.
  572. pub async fn validate_blockchain(
  573. &self,
  574. pow_target: u32,
  575. pow_fixed_difficulty: Option<BigUint>,
  576. ) -> Result<()> {
  577. let blocks = self.blockchain.get_all()?;
  578. // An empty blockchain is considered valid
  579. if blocks.is_empty() {
  580. return Ok(())
  581. }
  582. // Create an in memory blockchain overlay
  583. let sled_db = sled::Config::new().temporary(true).open()?;
  584. let blockchain = Blockchain::new(&sled_db)?;
  585. let overlay = BlockchainOverlay::new(&blockchain)?;
  586. // Set previous
  587. let mut previous = &blocks[0];
  588. // Deploy native wasm contracts
  589. deploy_native_contracts(&overlay, pow_target).await?;
  590. // Validate genesis block
  591. verify_genesis_block(&overlay, previous, pow_target).await?;
  592. // Write the changes to the in memory db
  593. overlay.lock().unwrap().overlay.lock().unwrap().apply()?;
  594. // Create a PoW module to validate each block
  595. let mut module = PoWModule::new(blockchain, pow_target, pow_fixed_difficulty)?;
  596. // Validate and insert each block
  597. for block in &blocks[1..] {
  598. // Verify block
  599. if verify_block(&overlay, &module, block, previous, self.verify_fees).await.is_err() {
  600. error!(target: "validator::validate_blockchain", "Erroneous block found in set");
  601. overlay.lock().unwrap().overlay.lock().unwrap().purge_new_trees()?;
  602. return Err(Error::BlockIsInvalid(block.hash().as_string()))
  603. };
  604. // Update PoW module
  605. module.append(block.header.timestamp, &module.next_difficulty()?);
  606. // Use last inserted block as next iteration previous
  607. previous = block;
  608. }
  609. Ok(())
  610. }
  611. /// Auxiliary function to retrieve current best fork next block height.
  612. pub async fn best_fork_next_block_height(&self) -> Result<u32> {
  613. let forks = self.consensus.forks.read().await;
  614. let fork = &forks[best_fork_index(&forks)?];
  615. let next_block_height = fork.get_next_block_height()?;
  616. drop(forks);
  617. Ok(next_block_height)
  618. }
  619. }