mod.rs 35 KB

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