mod.rs 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569
  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_serial::serialize_async;
  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},
  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::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 = blake3::hash(&serialize_async(tx).await);
  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.pending_txs.contains(&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.to_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(crate::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(crate::Error::TxVerifyFailed(TxVerifyFailed::ErroneousTxs(etx))) => {
  168. erroneous_txs = etx
  169. }
  170. Err(e) => return Err(e),
  171. }
  172. // Drop forks lock
  173. drop(forks);
  174. // Return error if transaction is not valid for canonical or any fork
  175. if !valid {
  176. return Err(TxVerifyFailed::ErroneousTxs(erroneous_txs).into())
  177. }
  178. // Add transaction to pending txs store
  179. if write {
  180. self.blockchain.add_pending_txs(&tx_vec)?;
  181. info!(target: "validator::append_tx", "Appended tx to pending txs store");
  182. }
  183. Ok(())
  184. }
  185. /// The node removes invalid transactions from the pending txs store.
  186. pub async fn purge_pending_txs(&self) -> Result<()> {
  187. info!(target: "validator::purge_pending_txs", "Removing invalid transactions from pending transactions store...");
  188. // Check if any pending transactions exist
  189. let pending_txs = self.blockchain.get_pending_txs()?;
  190. if pending_txs.is_empty() {
  191. info!(target: "validator::purge_pending_txs", "No pending transactions found");
  192. return Ok(())
  193. }
  194. // Grab a lock over current consensus forks state
  195. let mut forks = self.consensus.forks.write().await;
  196. let mut removed_txs = vec![];
  197. for tx in pending_txs {
  198. let tx_hash = &blake3::hash(&serialize_async(&tx).await);
  199. let tx_vec = [tx.clone()];
  200. let mut valid = false;
  201. // If node participates in consensus and holds any forks, iterate over them
  202. // to verify transaction validity in their overlays
  203. for fork in forks.iter_mut() {
  204. // Clone forks' overlay
  205. let overlay = fork.overlay.lock().unwrap().full_clone()?;
  206. // Grab forks' next block height
  207. let next_block_height = fork.get_next_block_height()?;
  208. // Verify transaction
  209. match verify_transactions(
  210. &overlay,
  211. next_block_height,
  212. &tx_vec,
  213. &mut MerkleTree::new(1),
  214. false,
  215. )
  216. .await
  217. {
  218. Ok(_) => {
  219. valid = true;
  220. continue
  221. }
  222. Err(crate::Error::TxVerifyFailed(TxVerifyFailed::ErroneousTxs(_))) => {}
  223. Err(e) => return Err(e),
  224. }
  225. // Remove erroneous transaction from forks' mempool
  226. fork.mempool.retain(|x| x != tx_hash);
  227. }
  228. // Verify transaction against canonical state
  229. let overlay = BlockchainOverlay::new(&self.blockchain)?;
  230. let next_block_height = self.blockchain.last_block()?.header.height + 1;
  231. match verify_transactions(
  232. &overlay,
  233. next_block_height,
  234. &tx_vec,
  235. &mut MerkleTree::new(1),
  236. false,
  237. )
  238. .await
  239. {
  240. Ok(_) => valid = true,
  241. Err(crate::Error::TxVerifyFailed(TxVerifyFailed::ErroneousTxs(_))) => {}
  242. Err(e) => return Err(e),
  243. }
  244. // Remove pending transaction if it's not valid for canonical or any fork
  245. if !valid {
  246. removed_txs.push(tx)
  247. }
  248. }
  249. // Drop forks lock
  250. drop(forks);
  251. if removed_txs.is_empty() {
  252. info!(target: "validator::purge_pending_txs", "No erroneous transactions found");
  253. return Ok(())
  254. }
  255. info!(target: "validator::purge_pending_txs", "Removing {} erroneous transactions...", removed_txs.len());
  256. self.blockchain.remove_pending_txs(&removed_txs)?;
  257. Ok(())
  258. }
  259. /// The node retrieves a block and tries to add it if it doesn't
  260. /// already exists.
  261. pub async fn append_block(&self, block: &BlockInfo) -> Result<()> {
  262. let block_hash = block.hash()?.to_string();
  263. // Check if block already exists
  264. if self.blockchain.has_block(block)? {
  265. debug!(target: "validator::append_block", "We have already seen this block");
  266. return Err(Error::BlockAlreadyExists(block_hash))
  267. }
  268. self.add_blocks(&[block.clone()]).await?;
  269. info!(target: "validator::append_block", "Block added: {}", block_hash);
  270. Ok(())
  271. }
  272. /// The node checks if proposals can be finalized.
  273. /// If proposals are found, node appends them to canonical, excluding the
  274. /// last one, and rebuild the finalized fork to contain the last one.
  275. pub async fn finalization(&self) -> Result<Vec<BlockInfo>> {
  276. info!(target: "validator::finalization", "Performing finalization check");
  277. // Grab blocks that can be finalized
  278. let mut finalized = self.consensus.finalization().await?;
  279. if finalized.is_empty() {
  280. info!(target: "validator::finalization", "No proposals can be finalized");
  281. return Ok(vec![])
  282. }
  283. // Exclude last proposal
  284. let last = finalized.pop().unwrap();
  285. // Append finalized blocks
  286. info!(target: "validator::finalization", "Finalizing {} proposals:", finalized.len());
  287. for block in &finalized {
  288. info!(target: "validator::finalization", "\t{}", block.hash()?);
  289. }
  290. self.add_blocks(&finalized).await?;
  291. // Rebuild best fork using last proposal
  292. *self.consensus.forks.write().await = vec![];
  293. self.consensus.append_proposal(&Proposal::new(last)?).await?;
  294. info!(target: "validator::finalization", "Finalization completed!");
  295. Ok(finalized)
  296. }
  297. // ==========================
  298. // State transition functions
  299. // ==========================
  300. // TODO TESTNET: Write down all cases below
  301. // State transition checks should be happening in the following cases for a sync node:
  302. // 1) When a finalized block is received
  303. // 2) When a transaction is being broadcasted to us
  304. // State transition checks should be happening in the following cases for a consensus participating node:
  305. // 1) When a finalized block is received
  306. // 2) When a transaction is being broadcasted to us
  307. // ==========================
  308. /// Validate a set of [`BlockInfo`] in sequence and apply them if all are valid.
  309. pub async fn add_blocks(&self, blocks: &[BlockInfo]) -> Result<()> {
  310. debug!(target: "validator::add_blocks", "Instantiating BlockchainOverlay");
  311. let overlay = BlockchainOverlay::new(&self.blockchain)?;
  312. // Retrieve last block
  313. let mut previous = &overlay.lock().unwrap().last_block()?;
  314. // Grab current PoW module to validate each block
  315. let mut module = self.consensus.module.read().await.clone();
  316. // Keep track of all blocks transactions to remove them from pending txs store
  317. let mut removed_txs = vec![];
  318. // Validate and insert each block
  319. for block in blocks {
  320. // Verify block
  321. if verify_block(&overlay, &module, block, previous).await.is_err() {
  322. error!(target: "validator::add_blocks", "Erroneous block found in set");
  323. overlay.lock().unwrap().overlay.lock().unwrap().purge_new_trees()?;
  324. return Err(Error::BlockIsInvalid(block.hash()?.to_string()))
  325. };
  326. // Generate block difficulty
  327. let difficulty = module.next_difficulty()?;
  328. let cummulative_difficulty = module.cummulative_difficulty.clone() + difficulty.clone();
  329. let block_difficulty = BlockDifficulty::new(
  330. block.header.height,
  331. block.header.timestamp.0,
  332. difficulty,
  333. cummulative_difficulty,
  334. );
  335. module.append_difficulty(&overlay, block_difficulty)?;
  336. // Store block transactions
  337. for tx in &block.txs {
  338. removed_txs.push(tx.clone());
  339. }
  340. // Use last inserted block as next iteration previous
  341. previous = block;
  342. }
  343. debug!(target: "validator::add_blocks", "Applying overlay changes");
  344. overlay.lock().unwrap().overlay.lock().unwrap().apply()?;
  345. // Purge pending erroneous txs since canonical state has been changed
  346. self.blockchain.remove_pending_txs(&removed_txs)?;
  347. self.purge_pending_txs().await?;
  348. // Update PoW module
  349. *self.consensus.module.write().await = module;
  350. Ok(())
  351. }
  352. /// Validate a set of [`Transaction`] in sequence and apply them if all are valid.
  353. /// In case any of the transactions fail, they will be returned to the caller.
  354. /// The function takes a boolean called `write` which tells it to actually write
  355. /// the state transitions to the database.
  356. ///
  357. /// Returns the total gas used for the given transactions.
  358. pub async fn add_transactions(
  359. &self,
  360. txs: &[Transaction],
  361. verifying_block_height: u64,
  362. write: bool,
  363. verify_fees: bool,
  364. ) -> Result<u64> {
  365. debug!(target: "validator::add_transactions", "Instantiating BlockchainOverlay");
  366. let overlay = BlockchainOverlay::new(&self.blockchain)?;
  367. // Verify all transactions and get erroneous ones
  368. let verify_result = verify_transactions(
  369. &overlay,
  370. verifying_block_height,
  371. txs,
  372. &mut MerkleTree::new(1),
  373. verify_fees,
  374. )
  375. .await;
  376. let lock = overlay.lock().unwrap();
  377. let mut overlay = lock.overlay.lock().unwrap();
  378. if let Err(e) = verify_result {
  379. overlay.purge_new_trees()?;
  380. return Err(e)
  381. }
  382. let gas_used = verify_result.unwrap();
  383. if !write {
  384. debug!(target: "validator::add_transactions", "Skipping apply of state updates because write=false");
  385. overlay.purge_new_trees()?;
  386. return Ok(gas_used)
  387. }
  388. debug!(target: "validator::add_transactions", "Applying overlay changes");
  389. overlay.apply()?;
  390. Ok(gas_used)
  391. }
  392. /// Validate a producer `Transaction` and apply it if valid.
  393. /// In case the transactions fail, ir will be returned to the caller.
  394. /// The function takes a boolean called `write` which tells it to actually write
  395. /// the state transitions to the database.
  396. /// This should be only used for test purposes.
  397. pub async fn add_test_producer_transaction(
  398. &self,
  399. tx: &Transaction,
  400. verifying_block_height: u64,
  401. write: bool,
  402. ) -> Result<()> {
  403. debug!(target: "validator::add_test_producer_transaction", "Instantiating BlockchainOverlay");
  404. let overlay = BlockchainOverlay::new(&self.blockchain)?;
  405. // Verify transaction
  406. let mut erroneous_txs = vec![];
  407. if let Err(e) = verify_producer_transaction(
  408. &overlay,
  409. verifying_block_height,
  410. tx,
  411. &mut MerkleTree::new(1),
  412. )
  413. .await
  414. {
  415. warn!(target: "validator::add_test_producer_transaction", "Transaction verification failed: {}", e);
  416. erroneous_txs.push(tx.clone());
  417. }
  418. let lock = overlay.lock().unwrap();
  419. let mut overlay = lock.overlay.lock().unwrap();
  420. if !erroneous_txs.is_empty() {
  421. warn!(target: "validator::add_test_producer_transaction", "Erroneous transactions found in set");
  422. overlay.purge_new_trees()?;
  423. return Err(TxVerifyFailed::ErroneousTxs(erroneous_txs).into())
  424. }
  425. if !write {
  426. debug!(target: "validator::add_test_producer_transaction", "Skipping apply of state updates because write=false");
  427. overlay.purge_new_trees()?;
  428. return Ok(())
  429. }
  430. debug!(target: "validator::add_test_producer_transaction", "Applying overlay changes");
  431. overlay.apply()?;
  432. Ok(())
  433. }
  434. /// Retrieve all existing blocks and try to apply them
  435. /// to an in memory overlay to verify their correctness.
  436. /// Be careful as this will try to load everything in memory.
  437. pub async fn validate_blockchain(
  438. &self,
  439. pow_target: usize,
  440. pow_fixed_difficulty: Option<BigUint>,
  441. ) -> Result<()> {
  442. let blocks = self.blockchain.get_all()?;
  443. // An empty blockchain is considered valid
  444. if blocks.is_empty() {
  445. return Ok(())
  446. }
  447. // Create an in memory blockchain overlay
  448. let sled_db = sled::Config::new().temporary(true).open()?;
  449. let blockchain = Blockchain::new(&sled_db)?;
  450. let overlay = BlockchainOverlay::new(&blockchain)?;
  451. // Set previous
  452. let mut previous = &blocks[0];
  453. // Create a time keeper and a PoW module to validate each block
  454. let mut module = PoWModule::new(blockchain.clone(), pow_target, pow_fixed_difficulty)?;
  455. // Deploy native wasm contracts
  456. deploy_native_contracts(&overlay).await?;
  457. // Validate genesis block
  458. verify_genesis_block(&overlay, previous).await?;
  459. // Validate and insert each block
  460. for block in &blocks[1..] {
  461. // Verify block
  462. if verify_block(&overlay, &module, block, previous).await.is_err() {
  463. error!(target: "validator::validate_blockchain", "Erroneous block found in set");
  464. overlay.lock().unwrap().overlay.lock().unwrap().purge_new_trees()?;
  465. return Err(Error::BlockIsInvalid(block.hash()?.to_string()))
  466. };
  467. // Update PoW module
  468. if block.header.version == 1 {
  469. module.append(block.header.timestamp.0, &module.next_difficulty()?);
  470. }
  471. // Use last inserted block as next iteration previous
  472. previous = block;
  473. }
  474. Ok(())
  475. }
  476. }