mod.rs 30 KB

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