mod.rs 20 KB

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