mod.rs 22 KB

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