verification.rs 45 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139
  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;
  19. use darkfi_sdk::{
  20. blockchain::block_version,
  21. crypto::{
  22. schnorr::{SchnorrPublic, Signature},
  23. ContractId, MerkleTree, PublicKey,
  24. },
  25. dark_tree::dark_forest_leaf_vec_integrity_check,
  26. deploy::DeployParamsV1,
  27. monotree::Monotree,
  28. pasta::pallas,
  29. };
  30. use darkfi_serial::{deserialize_async, serialize_async, AsyncDecodable, AsyncEncodable};
  31. use log::{debug, error, warn};
  32. use num_bigint::BigUint;
  33. use smol::io::Cursor;
  34. use crate::{
  35. blockchain::{
  36. block_store::append_tx_to_merkle_tree, BlockInfo, Blockchain, BlockchainOverlayPtr,
  37. HeaderHash,
  38. },
  39. error::TxVerifyFailed,
  40. runtime::vm_runtime::Runtime,
  41. tx::{Transaction, MAX_TX_CALLS, MIN_TX_CALLS},
  42. validator::{
  43. consensus::{Consensus, Fork, Proposal, GAS_LIMIT_UNPROPOSED_TXS},
  44. fees::{circuit_gas_use, compute_fee, GasData, PALLAS_SCHNORR_SIGNATURE_FEE},
  45. pow::PoWModule,
  46. },
  47. zk::VerifyingKey,
  48. Error, Result,
  49. };
  50. /// Verify given genesis [`BlockInfo`], and apply it to the provided overlay.
  51. pub async fn verify_genesis_block(
  52. overlay: &BlockchainOverlayPtr,
  53. block: &BlockInfo,
  54. block_target: u32,
  55. ) -> Result<()> {
  56. let block_hash = block.hash().as_string();
  57. debug!(target: "validator::verification::verify_genesis_block", "Validating genesis block {}", block_hash);
  58. // Check if block already exists
  59. if overlay.lock().unwrap().has_block(block)? {
  60. return Err(Error::BlockAlreadyExists(block_hash))
  61. }
  62. // Block height must be 0
  63. if block.header.height != 0 {
  64. return Err(Error::BlockIsInvalid(block_hash))
  65. }
  66. // Block version must be correct
  67. if block.header.version != block_version(block.header.height) {
  68. return Err(Error::BlockIsInvalid(block_hash))
  69. }
  70. // Verify transactions vector contains at least one(producers) transaction
  71. if block.txs.is_empty() {
  72. return Err(Error::BlockContainsNoTransactions(block_hash))
  73. }
  74. // Genesis producer transaction must be the Transaction::default() one(empty)
  75. let producer_tx = block.txs.last().unwrap();
  76. if producer_tx != &Transaction::default() {
  77. error!(target: "validator::verification::verify_genesis_block", "Genesis producer transaction is not default one");
  78. return Err(TxVerifyFailed::ErroneousTxs(vec![producer_tx.clone()]).into())
  79. }
  80. // Verify transactions, exluding producer(last) one/
  81. // Genesis block doesn't check for fees
  82. let mut tree = MerkleTree::new(1);
  83. let txs = &block.txs[..block.txs.len() - 1];
  84. if let Err(e) =
  85. verify_transactions(overlay, block.header.height, block_target, txs, &mut tree, false).await
  86. {
  87. warn!(
  88. target: "validator::verification::verify_genesis_block",
  89. "[VALIDATOR] Erroneous transactions found in set",
  90. );
  91. overlay.lock().unwrap().overlay.lock().unwrap().purge_new_trees()?;
  92. return Err(e)
  93. }
  94. // Append producer transaction to the tree and check tree matches header one
  95. append_tx_to_merkle_tree(&mut tree, producer_tx);
  96. if tree.root(0).unwrap() != block.header.transactions_root {
  97. error!(target: "validator::verification::verify_genesis_block", "Genesis Merkle tree is invalid");
  98. return Err(Error::BlockIsInvalid(block_hash))
  99. }
  100. // Verify header contracts states root
  101. let state_monotree = overlay.lock().unwrap().get_state_monotree()?;
  102. let Some(state_root) = state_monotree.get_headroot()? else {
  103. return Err(Error::ContractsStatesRootNotFoundError);
  104. };
  105. if state_root != block.header.state_root {
  106. return Err(Error::ContractsStatesRootError(
  107. blake3::Hash::from_bytes(state_root).to_string(),
  108. blake3::Hash::from_bytes(block.header.state_root).to_string(),
  109. ));
  110. }
  111. // Genesis producer signature must be the Signature::dummy() one(empty)
  112. if block.signature != Signature::dummy() {
  113. error!(target: "validator::verification::verify_genesis_block", "Genesis producer signature is not dummy one");
  114. return Err(Error::InvalidSignature)
  115. }
  116. // Insert block
  117. overlay.lock().unwrap().add_block(block)?;
  118. debug!(target: "validator::verification::verify_genesis_block", "Genesis block {} verified successfully", block_hash);
  119. Ok(())
  120. }
  121. /// Validate provided block according to set rules.
  122. ///
  123. /// A block is considered valid when the following rules apply:
  124. /// 1. Block version is correct for its height
  125. /// 2. Parent hash is equal to the hash of the previous block
  126. /// 3. Block height increments previous block height by 1
  127. /// 4. Timestamp is valid based on PoWModule validation
  128. /// 5. Block hash is valid based on PoWModule validation
  129. /// Additional validity rules can be applied.
  130. pub fn validate_block(block: &BlockInfo, previous: &BlockInfo, module: &PoWModule) -> Result<()> {
  131. // Check block version (1)
  132. if block.header.version != block_version(block.header.height) {
  133. return Err(Error::BlockIsInvalid(block.hash().as_string()))
  134. }
  135. // Check previous hash (2)
  136. if block.header.previous != previous.hash() {
  137. return Err(Error::BlockIsInvalid(block.hash().as_string()))
  138. }
  139. // Check heights are incremental (3)
  140. if block.header.height != previous.header.height + 1 {
  141. return Err(Error::BlockIsInvalid(block.hash().as_string()))
  142. }
  143. // Check timestamp validity (4)
  144. if !module.verify_timestamp_by_median(block.header.timestamp) {
  145. return Err(Error::BlockIsInvalid(block.hash().as_string()))
  146. }
  147. // Check block hash corresponds to next one (5)
  148. module.verify_block_hash(block)?;
  149. Ok(())
  150. }
  151. /// A blockchain is considered valid, when every block is valid,
  152. /// based on validate_block checks.
  153. /// Be careful as this will try to load everything in memory.
  154. pub fn validate_blockchain(
  155. blockchain: &Blockchain,
  156. pow_target: u32,
  157. pow_fixed_difficulty: Option<BigUint>,
  158. ) -> Result<()> {
  159. // Generate a PoW module
  160. let mut module = PoWModule::new(blockchain.clone(), pow_target, pow_fixed_difficulty, None)?;
  161. // We use block order store here so we have all blocks in order
  162. let blocks = blockchain.blocks.get_all_order()?;
  163. for (index, block) in blocks[1..].iter().enumerate() {
  164. let full_blocks = blockchain.get_blocks_by_hash(&[blocks[index].1, block.1])?;
  165. let full_block = &full_blocks[1];
  166. validate_block(full_block, &full_blocks[0], &module)?;
  167. // Update PoW module
  168. module.append(full_block.header.timestamp, &module.next_difficulty()?);
  169. }
  170. Ok(())
  171. }
  172. /// Verify given [`BlockInfo`], and apply it to the provided overlay.
  173. pub async fn verify_block(
  174. overlay: &BlockchainOverlayPtr,
  175. module: &PoWModule,
  176. state_monotree: &mut Monotree,
  177. block: &BlockInfo,
  178. previous: &BlockInfo,
  179. verify_fees: bool,
  180. ) -> Result<()> {
  181. let block_hash = block.hash();
  182. debug!(target: "validator::verification::verify_block", "Validating block {}", block_hash);
  183. // Check if block already exists
  184. if overlay.lock().unwrap().has_block(block)? {
  185. return Err(Error::BlockAlreadyExists(block_hash.as_string()))
  186. }
  187. // Validate block, using its previous
  188. validate_block(block, previous, module)?;
  189. // Verify transactions vector contains at least one(producers) transaction
  190. if block.txs.is_empty() {
  191. return Err(Error::BlockContainsNoTransactions(block_hash.as_string()))
  192. }
  193. // Verify transactions, exluding producer(last) one
  194. let mut tree = MerkleTree::new(1);
  195. let txs = &block.txs[..block.txs.len() - 1];
  196. let e = verify_transactions(
  197. overlay,
  198. block.header.height,
  199. module.target,
  200. txs,
  201. &mut tree,
  202. verify_fees,
  203. )
  204. .await;
  205. if let Err(e) = e {
  206. warn!(
  207. target: "validator::verification::verify_block",
  208. "[VALIDATOR] Erroneous transactions found in set",
  209. );
  210. overlay.lock().unwrap().overlay.lock().unwrap().purge_new_trees()?;
  211. return Err(e)
  212. }
  213. // Verify producer transaction
  214. let public_key = verify_producer_transaction(
  215. overlay,
  216. block.header.height,
  217. module.target,
  218. block.txs.last().unwrap(),
  219. &mut tree,
  220. )
  221. .await?;
  222. // Verify transactions merkle tree root matches header one
  223. if tree.root(0).unwrap() != block.header.transactions_root {
  224. error!(target: "validator::verification::verify_block", "Block Merkle tree root is invalid");
  225. return Err(Error::BlockIsInvalid(block_hash.as_string()))
  226. }
  227. // Update the provided contracts states monotree and verify header contracts states root
  228. overlay.lock().unwrap().contracts.update_state_monotree(state_monotree)?;
  229. let Some(state_root) = state_monotree.get_headroot()? else {
  230. return Err(Error::ContractsStatesRootNotFoundError);
  231. };
  232. if state_root != block.header.state_root {
  233. return Err(Error::ContractsStatesRootError(
  234. blake3::Hash::from_bytes(state_root).to_string(),
  235. blake3::Hash::from_bytes(block.header.state_root).to_string(),
  236. ));
  237. }
  238. // Verify producer signature
  239. verify_producer_signature(block, &public_key)?;
  240. // Insert block
  241. overlay.lock().unwrap().add_block(block)?;
  242. debug!(target: "validator::verification::verify_block", "Block {} verified successfully", block_hash);
  243. Ok(())
  244. }
  245. /// Verify given checkpoint [`BlockInfo`], and apply it to the provided overlay.
  246. pub async fn verify_checkpoint_block(
  247. overlay: &BlockchainOverlayPtr,
  248. state_monotree: &mut Monotree,
  249. block: &BlockInfo,
  250. header: &HeaderHash,
  251. block_target: u32,
  252. ) -> Result<()> {
  253. let block_hash = block.hash();
  254. debug!(target: "validator::verification::verify_checkpoint_block", "Validating block {}", block_hash);
  255. // Check if block already exists
  256. if overlay.lock().unwrap().has_block(block)? {
  257. return Err(Error::BlockAlreadyExists(block_hash.as_string()))
  258. }
  259. // Check if block hash matches the expected(provided) one
  260. if block_hash != *header {
  261. error!(target: "validator::verification::verify_checkpoint_block", "Block hash doesn't match the expected one");
  262. return Err(Error::BlockIsInvalid(block_hash.as_string()))
  263. }
  264. // Verify transactions vector contains at least one(producers) transaction
  265. if block.txs.is_empty() {
  266. return Err(Error::BlockContainsNoTransactions(block_hash.as_string()))
  267. }
  268. // Apply transactions, excluding producer(last) one
  269. let mut tree = MerkleTree::new(1);
  270. let txs = &block.txs[..block.txs.len() - 1];
  271. let e = apply_transactions(overlay, block.header.height, block_target, txs, &mut tree).await;
  272. if let Err(e) = e {
  273. warn!(
  274. target: "validator::verification::verify_checkpoint_block",
  275. "[VALIDATOR] Erroneous transactions found in set",
  276. );
  277. overlay.lock().unwrap().overlay.lock().unwrap().purge_new_trees()?;
  278. return Err(e)
  279. }
  280. // Apply producer transaction
  281. let public_key = apply_producer_transaction(
  282. overlay,
  283. block.header.height,
  284. block_target,
  285. block.txs.last().unwrap(),
  286. &mut tree,
  287. )
  288. .await?;
  289. // Verify transactions merkle tree root matches header one
  290. if tree.root(0).unwrap() != block.header.transactions_root {
  291. error!(target: "validator::verification::verify_checkpoint_block", "Block Merkle tree root is invalid");
  292. return Err(Error::BlockIsInvalid(block_hash.as_string()))
  293. }
  294. // Update the provided contracts states monotree and verify header contracts states root
  295. overlay.lock().unwrap().contracts.update_state_monotree(state_monotree)?;
  296. let Some(state_root) = state_monotree.get_headroot()? else {
  297. return Err(Error::ContractsStatesRootNotFoundError);
  298. };
  299. if state_root != block.header.state_root {
  300. return Err(Error::ContractsStatesRootError(
  301. blake3::Hash::from_bytes(state_root).to_string(),
  302. blake3::Hash::from_bytes(block.header.state_root).to_string(),
  303. ));
  304. }
  305. // Verify producer signature
  306. verify_producer_signature(block, &public_key)?;
  307. // Insert block
  308. overlay.lock().unwrap().add_block(block)?;
  309. debug!(target: "validator::verification::verify_checkpoint_block", "Block {} verified successfully", block_hash);
  310. Ok(())
  311. }
  312. /// Verify block proposer signature, using the producer transaction signature as signing key
  313. /// over blocks header hash.
  314. pub fn verify_producer_signature(block: &BlockInfo, public_key: &PublicKey) -> Result<()> {
  315. if !public_key.verify(block.header.hash().inner(), &block.signature) {
  316. warn!(target: "validator::verification::verify_producer_signature", "Proposer {} signature could not be verified", public_key);
  317. return Err(Error::InvalidSignature)
  318. }
  319. Ok(())
  320. }
  321. /// Verify provided producer [`Transaction`].
  322. ///
  323. /// Verify WASM execution, signatures, and ZK proofs and apply it to the provided,
  324. /// provided overlay. Returns transaction signature public key. Additionally,
  325. /// append its hash to the provided Merkle tree.
  326. pub async fn verify_producer_transaction(
  327. overlay: &BlockchainOverlayPtr,
  328. verifying_block_height: u32,
  329. block_target: u32,
  330. tx: &Transaction,
  331. tree: &mut MerkleTree,
  332. ) -> Result<PublicKey> {
  333. let tx_hash = tx.hash();
  334. debug!(target: "validator::verification::verify_producer_transaction", "Validating producer transaction {}", tx_hash);
  335. // Transaction must be a PoW reward one
  336. if !tx.is_pow_reward() {
  337. return Err(TxVerifyFailed::ErroneousTxs(vec![tx.clone()]).into())
  338. }
  339. // Retrieve first call from the transaction for further processing
  340. let call = &tx.calls[0];
  341. // Map of ZK proof verifying keys for the current transaction
  342. let mut verifying_keys: HashMap<[u8; 32], HashMap<String, VerifyingKey>> = HashMap::new();
  343. // Initialize the map
  344. verifying_keys.insert(call.data.contract_id.to_bytes(), HashMap::new());
  345. // Table of public inputs used for ZK proof verification
  346. let mut zkp_table = vec![];
  347. // Table of public keys used for signature verification
  348. let mut sig_table = vec![];
  349. debug!(target: "validator::verification::verify_producer_transaction", "Executing contract call");
  350. // Write the actual payload data
  351. let mut payload = vec![];
  352. tx.calls.encode_async(&mut payload).await?; // Actual call data
  353. debug!(target: "validator::verification::verify_producer_transaction", "Instantiating WASM runtime");
  354. let wasm = overlay.lock().unwrap().contracts.get(call.data.contract_id)?;
  355. let mut runtime = Runtime::new(
  356. &wasm,
  357. overlay.clone(),
  358. call.data.contract_id,
  359. verifying_block_height,
  360. block_target,
  361. tx_hash,
  362. // Call index in producer tx is 0
  363. 0,
  364. )?;
  365. debug!(target: "validator::verification::verify_producer_transaction", "Executing \"metadata\" call");
  366. let metadata = runtime.metadata(&payload)?;
  367. // Decode the metadata retrieved from the execution
  368. let mut decoder = Cursor::new(&metadata);
  369. // The tuple is (zkas_ns, public_inputs)
  370. let zkp_pub: Vec<(String, Vec<pallas::Base>)> =
  371. AsyncDecodable::decode_async(&mut decoder).await?;
  372. let sig_pub: Vec<PublicKey> = AsyncDecodable::decode_async(&mut decoder).await?;
  373. // Check that only one ZK proof and signature public key exist
  374. if zkp_pub.len() != 1 || sig_pub.len() != 1 {
  375. error!(target: "validator::verification::verify_producer_transaction", "Producer transaction contains multiple ZK proofs or signature public keys");
  376. return Err(TxVerifyFailed::ErroneousTxs(vec![tx.clone()]).into())
  377. }
  378. // TODO: Make sure we've read all the bytes above.
  379. debug!(target: "validator::verification::verify_producer_transaction", "Successfully executed \"metadata\" call");
  380. // Here we'll look up verifying keys and insert them into the map.
  381. debug!(target: "validator::verification::verify_producer_transaction", "Performing VerifyingKey lookups from the sled db");
  382. for (zkas_ns, _) in &zkp_pub {
  383. // TODO: verify this is correct behavior
  384. let inner_vk_map = verifying_keys.get_mut(&call.data.contract_id.to_bytes()).unwrap();
  385. if inner_vk_map.contains_key(zkas_ns.as_str()) {
  386. continue
  387. }
  388. let (_zkbin, vk) =
  389. overlay.lock().unwrap().contracts.get_zkas(&call.data.contract_id, zkas_ns)?;
  390. inner_vk_map.insert(zkas_ns.to_string(), vk);
  391. }
  392. zkp_table.push(zkp_pub);
  393. let signature_public_key = *sig_pub.last().unwrap();
  394. sig_table.push(sig_pub);
  395. // After getting the metadata, we run the "exec" function with the same runtime
  396. // and the same payload. We keep the returned state update in a buffer, prefixed
  397. // by the call function ID, enforcing the state update function in the contract.
  398. debug!(target: "validator::verification::verify_producer_transaction", "Executing \"exec\" call");
  399. let mut state_update = vec![call.data.data[0]];
  400. state_update.append(&mut runtime.exec(&payload)?);
  401. debug!(target: "validator::verification::verify_producer_transaction", "Successfully executed \"exec\" call");
  402. // If that was successful, we apply the state update in the ephemeral overlay.
  403. debug!(target: "validator::verification::verify_producer_transaction", "Executing \"apply\" call");
  404. runtime.apply(&state_update)?;
  405. debug!(target: "validator::verification::verify_producer_transaction", "Successfully executed \"apply\" call");
  406. // When we're done executing over the tx's contract call, we now move on with verification.
  407. // First we verify the signatures as that's cheaper, and then finally we verify the ZK proofs.
  408. debug!(target: "validator::verification::verify_producer_transaction", "Verifying signatures for transaction {}", tx_hash);
  409. if sig_table.len() != tx.signatures.len() {
  410. error!(target: "validator::verification::verify_producer_transaction", "Incorrect number of signatures in tx {}", tx_hash);
  411. return Err(TxVerifyFailed::MissingSignatures.into())
  412. }
  413. // TODO: Go through the ZK circuits that have to be verified and account for the opcodes.
  414. if let Err(e) = tx.verify_sigs(sig_table) {
  415. error!(target: "validator::verification::verify_producer_transaction", "Signature verification for tx {} failed: {}", tx_hash, e);
  416. return Err(TxVerifyFailed::InvalidSignature.into())
  417. }
  418. debug!(target: "validator::verification::verify_producer_transaction", "Signature verification successful");
  419. debug!(target: "validator::verification::verify_producer_transaction", "Verifying ZK proofs for transaction {}", tx_hash);
  420. if let Err(e) = tx.verify_zkps(&verifying_keys, zkp_table).await {
  421. error!(target: "validator::verification::verify_producer_transaction", "ZK proof verification for tx {} failed: {}", tx_hash, e);
  422. return Err(TxVerifyFailed::InvalidZkProof.into())
  423. }
  424. debug!(target: "validator::verification::verify_producer_transaction", "ZK proof verification successful");
  425. // Append hash to merkle tree
  426. append_tx_to_merkle_tree(tree, tx);
  427. debug!(target: "validator::verification::verify_producer_transaction", "Producer transaction {} verified successfully", tx_hash);
  428. Ok(signature_public_key)
  429. }
  430. /// Apply given producer [`Transaction`] to the provided overlay, without formal verification.
  431. /// Returns transaction signature public key. Additionally, append its hash to the provided Merkle tree.
  432. pub async fn apply_producer_transaction(
  433. overlay: &BlockchainOverlayPtr,
  434. verifying_block_height: u32,
  435. block_target: u32,
  436. tx: &Transaction,
  437. tree: &mut MerkleTree,
  438. ) -> Result<PublicKey> {
  439. let tx_hash = tx.hash();
  440. debug!(target: "validator::verification::apply_producer_transaction", "Applying producer transaction {}", tx_hash);
  441. // Producer transactions must contain a single, non-empty call
  442. if !tx.is_single_call() {
  443. return Err(TxVerifyFailed::ErroneousTxs(vec![tx.clone()]).into())
  444. }
  445. debug!(target: "validator::verification::apply_producer_transaction", "Executing contract call");
  446. // Write the actual payload data
  447. let mut payload = vec![];
  448. tx.calls.encode_async(&mut payload).await?; // Actual call data
  449. debug!(target: "validator::verification::apply_producer_transaction", "Instantiating WASM runtime");
  450. let call = &tx.calls[0];
  451. let wasm = overlay.lock().unwrap().contracts.get(call.data.contract_id)?;
  452. let mut runtime = Runtime::new(
  453. &wasm,
  454. overlay.clone(),
  455. call.data.contract_id,
  456. verifying_block_height,
  457. block_target,
  458. tx_hash,
  459. // Call index in producer tx is 0
  460. 0,
  461. )?;
  462. debug!(target: "validator::verification::apply_producer_transaction", "Executing \"metadata\" call");
  463. let metadata = runtime.metadata(&payload)?;
  464. // Decode the metadata retrieved from the execution
  465. let mut decoder = Cursor::new(&metadata);
  466. // The tuple is (zkas_ns, public_inputs)
  467. let _: Vec<(String, Vec<pallas::Base>)> = AsyncDecodable::decode_async(&mut decoder).await?;
  468. let sig_pub: Vec<PublicKey> = AsyncDecodable::decode_async(&mut decoder).await?;
  469. // Check that only one ZK proof and signature public key exist
  470. if sig_pub.len() != 1 {
  471. error!(target: "validator::verification::apply_producer_transaction", "Producer transaction contains multiple ZK proofs or signature public keys");
  472. return Err(TxVerifyFailed::ErroneousTxs(vec![tx.clone()]).into())
  473. }
  474. let signature_public_key = *sig_pub.last().unwrap();
  475. // After getting the metadata, we run the "exec" function with the same runtime
  476. // and the same payload. We keep the returned state update in a buffer, prefixed
  477. // by the call function ID, enforcing the state update function in the contract.
  478. debug!(target: "validator::verification::apply_producer_transaction", "Executing \"exec\" call");
  479. let mut state_update = vec![call.data.data[0]];
  480. state_update.append(&mut runtime.exec(&payload)?);
  481. debug!(target: "validator::verification::apply_producer_transaction", "Successfully executed \"exec\" call");
  482. // If that was successful, we apply the state update in the ephemeral overlay.
  483. debug!(target: "validator::verification::apply_producer_transaction", "Executing \"apply\" call");
  484. runtime.apply(&state_update)?;
  485. debug!(target: "validator::verification::apply_producer_transaction", "Successfully executed \"apply\" call");
  486. // Append hash to merkle tree
  487. append_tx_to_merkle_tree(tree, tx);
  488. debug!(target: "validator::verification::apply_producer_transaction", "Producer transaction {} executed successfully", tx_hash);
  489. Ok(signature_public_key)
  490. }
  491. /// Verify WASM execution, signatures, and ZK proofs for a given [`Transaction`],
  492. /// and apply it to the provided overlay. Additionally, append its hash to the
  493. /// provided Merkle tree.
  494. pub async fn verify_transaction(
  495. overlay: &BlockchainOverlayPtr,
  496. verifying_block_height: u32,
  497. block_target: u32,
  498. tx: &Transaction,
  499. tree: &mut MerkleTree,
  500. verifying_keys: &mut HashMap<[u8; 32], HashMap<String, VerifyingKey>>,
  501. verify_fee: bool,
  502. ) -> Result<GasData> {
  503. let tx_hash = tx.hash();
  504. debug!(target: "validator::verification::verify_transaction", "Validating transaction {}", tx_hash);
  505. // Create a FeeData instance to hold the calculated fee data
  506. let mut gas_data = GasData::default();
  507. // Verify calls indexes integrity
  508. if verify_fee {
  509. dark_forest_leaf_vec_integrity_check(
  510. &tx.calls,
  511. Some(MIN_TX_CALLS + 1),
  512. Some(MAX_TX_CALLS),
  513. )?;
  514. } else {
  515. dark_forest_leaf_vec_integrity_check(&tx.calls, Some(MIN_TX_CALLS), Some(MAX_TX_CALLS))?;
  516. }
  517. // Table of public inputs used for ZK proof verification
  518. let mut zkp_table = vec![];
  519. // Table of public keys used for signature verification
  520. let mut sig_table = vec![];
  521. // Index of the Fee-paying call
  522. let mut fee_call_idx = 0;
  523. if verify_fee {
  524. let mut found_fee = false;
  525. // Verify that there is a money fee call in the transaction
  526. for (call_idx, call) in tx.calls.iter().enumerate() {
  527. if call.data.is_money_fee() {
  528. found_fee = true;
  529. fee_call_idx = call_idx;
  530. break
  531. }
  532. }
  533. if !found_fee {
  534. error!(
  535. target: "validator::verification::verify_transcation",
  536. "[VALIDATOR] Transaction {} does not contain fee payment call", tx_hash,
  537. );
  538. return Err(TxVerifyFailed::InvalidFee.into())
  539. }
  540. }
  541. // Write the transaction calls payload data
  542. let mut payload = vec![];
  543. tx.calls.encode_async(&mut payload).await?;
  544. // We'll also take note of all the circuits in a Vec so we can calculate their verification cost.
  545. let mut circuits_to_verify = vec![];
  546. // Iterate over all calls to get the metadata
  547. for (idx, call) in tx.calls.iter().enumerate() {
  548. debug!(target: "validator::verification::verify_transaction", "Executing contract call {}", idx);
  549. // Transaction must not contain a Pow reward call
  550. if call.data.is_money_pow_reward() {
  551. error!(target: "validator::verification::verify_transaction", "Reward transaction detected");
  552. return Err(TxVerifyFailed::ErroneousTxs(vec![tx.clone()]).into())
  553. }
  554. debug!(target: "validator::verification::verify_transaction", "Instantiating WASM runtime");
  555. let wasm = overlay.lock().unwrap().contracts.get(call.data.contract_id)?;
  556. let mut runtime = Runtime::new(
  557. &wasm,
  558. overlay.clone(),
  559. call.data.contract_id,
  560. verifying_block_height,
  561. block_target,
  562. tx_hash,
  563. idx as u8,
  564. )?;
  565. debug!(target: "validator::verification::verify_transaction", "Executing \"metadata\" call");
  566. let metadata = runtime.metadata(&payload)?;
  567. // Decode the metadata retrieved from the execution
  568. let mut decoder = Cursor::new(&metadata);
  569. // The tuple is (zkas_ns, public_inputs)
  570. let zkp_pub: Vec<(String, Vec<pallas::Base>)> =
  571. AsyncDecodable::decode_async(&mut decoder).await?;
  572. let sig_pub: Vec<PublicKey> = AsyncDecodable::decode_async(&mut decoder).await?;
  573. if decoder.position() != metadata.len() as u64 {
  574. error!(
  575. target: "validator::verification::verify_transaction",
  576. "[VALIDATOR] Failed decoding entire metadata buffer for {}:{}", tx_hash, idx,
  577. );
  578. return Err(TxVerifyFailed::ErroneousTxs(vec![tx.clone()]).into())
  579. }
  580. debug!(target: "validator::verification::verify_transaction", "Successfully executed \"metadata\" call");
  581. // Here we'll look up verifying keys and insert them into the per-contract map.
  582. // TODO: This vk map can potentially use a lot of RAM. Perhaps load keys on-demand at verification time?
  583. debug!(target: "validator::verification::verify_transaction", "Performing VerifyingKey lookups from the sled db");
  584. for (zkas_ns, _) in &zkp_pub {
  585. let inner_vk_map = verifying_keys.get_mut(&call.data.contract_id.to_bytes()).unwrap();
  586. // TODO: This will be a problem in case of ::deploy, unless we force a different
  587. // namespace and disable updating existing circuit. Might be a smart idea to do
  588. // so in order to have to care less about being able to verify historical txs.
  589. if inner_vk_map.contains_key(zkas_ns.as_str()) {
  590. continue
  591. }
  592. let (zkbin, vk) =
  593. overlay.lock().unwrap().contracts.get_zkas(&call.data.contract_id, zkas_ns)?;
  594. inner_vk_map.insert(zkas_ns.to_string(), vk);
  595. circuits_to_verify.push(zkbin);
  596. }
  597. zkp_table.push(zkp_pub);
  598. sig_table.push(sig_pub);
  599. // After getting the metadata, we run the "exec" function with the same runtime
  600. // and the same payload. We keep the returned state update in a buffer, prefixed
  601. // by the call function ID, enforcing the state update function in the contract.
  602. debug!(target: "validator::verification::verify_transaction", "Executing \"exec\" call");
  603. let mut state_update = vec![call.data.data[0]];
  604. state_update.append(&mut runtime.exec(&payload)?);
  605. debug!(target: "validator::verification::verify_transaction", "Successfully executed \"exec\" call");
  606. // If that was successful, we apply the state update in the ephemeral overlay.
  607. debug!(target: "validator::verification::verify_transaction", "Executing \"apply\" call");
  608. runtime.apply(&state_update)?;
  609. debug!(target: "validator::verification::verify_transaction", "Successfully executed \"apply\" call");
  610. // If this call is supposed to deploy a new contract, we have to instantiate
  611. // a new `Runtime` and run its deploy function.
  612. if call.data.is_deployment()
  613. /* DeployV1 */
  614. {
  615. debug!(target: "validator::verification::verify_transaction", "Deploying new contract");
  616. // Deserialize the deployment parameters
  617. let deploy_params: DeployParamsV1 = deserialize_async(&call.data.data[1..]).await?;
  618. let deploy_cid = ContractId::derive_public(deploy_params.public_key);
  619. // Instantiate the new deployment runtime
  620. let mut deploy_runtime = Runtime::new(
  621. &deploy_params.wasm_bincode,
  622. overlay.clone(),
  623. deploy_cid,
  624. verifying_block_height,
  625. block_target,
  626. tx_hash,
  627. idx as u8,
  628. )?;
  629. deploy_runtime.deploy(&deploy_params.ix)?;
  630. let deploy_gas_used = deploy_runtime.gas_used();
  631. debug!(target: "validator::verification::verify_transaction", "The gas used for deployment call {:?} of transaction {}: {}", call, tx_hash, deploy_gas_used);
  632. gas_data.deployments += deploy_gas_used;
  633. }
  634. // At this point we're done with the call and move on to the next one.
  635. // Accumulate the WASM gas used.
  636. let wasm_gas_used = runtime.gas_used();
  637. debug!(target: "validator::verification::verify_transaction", "The gas used for WASM call {:?} of transaction {}: {}", call, tx_hash, wasm_gas_used);
  638. // Append the used wasm gas
  639. gas_data.wasm += wasm_gas_used;
  640. }
  641. // The signature fee is tx_size + fixed_sig_fee * n_signatures
  642. gas_data.signatures = (PALLAS_SCHNORR_SIGNATURE_FEE * tx.signatures.len() as u64) +
  643. serialize_async(tx).await.len() as u64;
  644. debug!(target: "validator::verification::verify_transaction", "The gas used for signature of transaction {}: {}", tx_hash, gas_data.signatures);
  645. // The ZK circuit fee is calculated using a function in validator/fees.rs
  646. for zkbin in circuits_to_verify.iter() {
  647. let zk_circuit_gas_used = circuit_gas_use(zkbin);
  648. debug!(target: "validator::verification::verify_transaction", "The gas used for ZK circuit in namespace {} of transaction {}: {}", zkbin.namespace, tx_hash, zk_circuit_gas_used);
  649. // Append the used zk circuit gas
  650. gas_data.zk_circuits += zk_circuit_gas_used;
  651. }
  652. // Store the calculated total gas used to avoid recalculating it for subsequent uses
  653. let total_gas_used = gas_data.total_gas_used();
  654. if verify_fee {
  655. // Deserialize the fee call to find the paid fee
  656. let fee: u64 = match deserialize_async(&tx.calls[fee_call_idx].data.data[1..9]).await {
  657. Ok(v) => v,
  658. Err(e) => {
  659. error!(
  660. target: "validator::verification::verify_transaction",
  661. "[VALIDATOR] Failed deserializing tx {} fee call: {}", tx_hash, e,
  662. );
  663. return Err(TxVerifyFailed::InvalidFee.into())
  664. }
  665. };
  666. // Compute the required fee for this transaction
  667. let required_fee = compute_fee(&total_gas_used);
  668. // Check that enough fee has been paid for the used gas in this transaction
  669. if required_fee > fee {
  670. error!(
  671. target: "validator::verification::verify_transaction",
  672. "[VALIDATOR] Transaction {} has insufficient fee. Required: {}, Paid: {}",
  673. tx_hash, required_fee, fee,
  674. );
  675. return Err(TxVerifyFailed::InsufficientFee.into())
  676. }
  677. debug!(target: "validator::verification::verify_transaction", "The gas paid for transaction {}: {}", tx_hash, gas_data.paid);
  678. // Store paid fee
  679. gas_data.paid = fee;
  680. }
  681. // When we're done looping and executing over the tx's contract calls and
  682. // (optionally) made sure that enough fee was paid, we now move on with
  683. // verification. First we verify the transaction signatures and then we
  684. // verify any accompanying ZK proofs.
  685. debug!(target: "validator::verification::verify_transaction", "Verifying signatures for transaction {}", tx_hash);
  686. if sig_table.len() != tx.signatures.len() {
  687. error!(
  688. target: "validator::verification::verify_transaction",
  689. "[VALIDATOR] Incorrect number of signatures in tx {}", tx_hash,
  690. );
  691. return Err(TxVerifyFailed::MissingSignatures.into())
  692. }
  693. if let Err(e) = tx.verify_sigs(sig_table) {
  694. error!(
  695. target: "validator::verification::verify_transaction",
  696. "[VALIDATOR] Signature verification for tx {} failed: {}", tx_hash, e,
  697. );
  698. return Err(TxVerifyFailed::InvalidSignature.into())
  699. }
  700. debug!(target: "validator::verification::verify_transaction", "Signature verification successful");
  701. debug!(target: "validator::verification::verify_transaction", "Verifying ZK proofs for transaction {}", tx_hash);
  702. if let Err(e) = tx.verify_zkps(verifying_keys, zkp_table).await {
  703. error!(
  704. target: "validator::verification::verify_transaction",
  705. "[VALIDATOR] ZK proof verification for tx {} failed: {}", tx_hash, e,
  706. );
  707. return Err(TxVerifyFailed::InvalidZkProof.into())
  708. }
  709. debug!(target: "validator::verification::verify_transaction", "ZK proof verification successful");
  710. // Append hash to merkle tree
  711. append_tx_to_merkle_tree(tree, tx);
  712. debug!(target: "validator::verification::verify_transaction", "The total gas used for transaction {}: {}", tx_hash, total_gas_used);
  713. debug!(target: "validator::verification::verify_transaction", "Transaction {} verified successfully", tx_hash);
  714. Ok(gas_data)
  715. }
  716. /// Apply given [`Transaction`] to the provided overlay.
  717. /// Additionally, append its hash to the provided Merkle tree.
  718. pub async fn apply_transaction(
  719. overlay: &BlockchainOverlayPtr,
  720. verifying_block_height: u32,
  721. block_target: u32,
  722. tx: &Transaction,
  723. tree: &mut MerkleTree,
  724. ) -> Result<()> {
  725. let tx_hash = tx.hash();
  726. debug!(target: "validator::verification::apply_transaction", "Applying transaction {}", tx_hash);
  727. // Write the transaction calls payload data
  728. let mut payload = vec![];
  729. tx.calls.encode_async(&mut payload).await?;
  730. // Iterate over all calls to get the metadata
  731. for (idx, call) in tx.calls.iter().enumerate() {
  732. debug!(target: "validator::verification::apply_transaction", "Executing contract call {}", idx);
  733. debug!(target: "validator::verification::apply_transaction", "Instantiating WASM runtime");
  734. let wasm = overlay.lock().unwrap().contracts.get(call.data.contract_id)?;
  735. let mut runtime = Runtime::new(
  736. &wasm,
  737. overlay.clone(),
  738. call.data.contract_id,
  739. verifying_block_height,
  740. block_target,
  741. tx_hash,
  742. idx as u8,
  743. )?;
  744. // Run the "exec" function. We keep the returned state update in a buffer, prefixed
  745. // by the call function ID, enforcing the state update function in the contract.
  746. debug!(target: "validator::verification::apply_transaction", "Executing \"exec\" call");
  747. let mut state_update = vec![call.data.data[0]];
  748. state_update.append(&mut runtime.exec(&payload)?);
  749. debug!(target: "validator::verification::apply_transaction", "Successfully executed \"exec\" call");
  750. // If that was successful, we apply the state update in the ephemeral overlay
  751. debug!(target: "validator::verification::apply_transaction", "Executing \"apply\" call");
  752. runtime.apply(&state_update)?;
  753. debug!(target: "validator::verification::apply_transaction", "Successfully executed \"apply\" call");
  754. // If this call is supposed to deploy a new contract, we have to instantiate
  755. // a new `Runtime` and run its deploy function.
  756. if call.data.is_deployment()
  757. /* DeployV1 */
  758. {
  759. debug!(target: "validator::verification::apply_transaction", "Deploying new contract");
  760. // Deserialize the deployment parameters
  761. let deploy_params: DeployParamsV1 = deserialize_async(&call.data.data[1..]).await?;
  762. let deploy_cid = ContractId::derive_public(deploy_params.public_key);
  763. // Instantiate the new deployment runtime
  764. let mut deploy_runtime = Runtime::new(
  765. &deploy_params.wasm_bincode,
  766. overlay.clone(),
  767. deploy_cid,
  768. verifying_block_height,
  769. block_target,
  770. tx_hash,
  771. idx as u8,
  772. )?;
  773. deploy_runtime.deploy(&deploy_params.ix)?;
  774. }
  775. }
  776. // Append hash to merkle tree
  777. append_tx_to_merkle_tree(tree, tx);
  778. debug!(target: "validator::verification::apply_transaction", "Transaction {} applied successfully", tx_hash);
  779. Ok(())
  780. }
  781. /// Verify a set of [`Transaction`] in sequence and apply them if all are valid.
  782. ///
  783. /// In case any of the transactions fail, they will be returned to the caller as an error.
  784. /// If all transactions are valid, the function will return the total gas used and total
  785. /// paid fees from all the transactions. Additionally, their hash is appended to the provided
  786. /// Merkle tree.
  787. pub async fn verify_transactions(
  788. overlay: &BlockchainOverlayPtr,
  789. verifying_block_height: u32,
  790. block_target: u32,
  791. txs: &[Transaction],
  792. tree: &mut MerkleTree,
  793. verify_fees: bool,
  794. ) -> Result<(u64, u64)> {
  795. debug!(target: "validator::verification::verify_transactions", "Verifying {} transactions", txs.len());
  796. if txs.is_empty() {
  797. return Ok((0, 0))
  798. }
  799. // Tracker for failed txs
  800. let mut erroneous_txs = vec![];
  801. // Total gas accumulators
  802. let mut total_gas_used = 0;
  803. let mut total_gas_paid = 0;
  804. // Map of ZK proof verifying keys for the current transaction batch
  805. let mut vks: HashMap<[u8; 32], HashMap<String, VerifyingKey>> = HashMap::new();
  806. // Initialize the map
  807. for tx in txs {
  808. for call in &tx.calls {
  809. vks.insert(call.data.contract_id.to_bytes(), HashMap::new());
  810. }
  811. }
  812. // Iterate over transactions and attempt to verify them
  813. for tx in txs {
  814. overlay.lock().unwrap().checkpoint();
  815. let gas_data = match verify_transaction(
  816. overlay,
  817. verifying_block_height,
  818. block_target,
  819. tx,
  820. tree,
  821. &mut vks,
  822. verify_fees,
  823. )
  824. .await
  825. {
  826. Ok(gas_values) => gas_values,
  827. Err(e) => {
  828. warn!(target: "validator::verification::verify_transactions", "Transaction verification failed: {}", e);
  829. erroneous_txs.push(tx.clone());
  830. overlay.lock().unwrap().revert_to_checkpoint()?;
  831. continue
  832. }
  833. };
  834. // Store the gas used by the verified transaction
  835. let tx_gas_used = gas_data.total_gas_used();
  836. // Calculate current accumulated gas usage
  837. let accumulated_gas_usage = total_gas_used + tx_gas_used;
  838. // Check gas limit - if accumulated gas used exceeds it, break out of loop
  839. if accumulated_gas_usage > GAS_LIMIT_UNPROPOSED_TXS {
  840. warn!(target: "validator::verification::verify_transactions", "Transaction {} exceeds configured transaction gas limit: {} - {}", tx.hash(), accumulated_gas_usage, GAS_LIMIT_UNPROPOSED_TXS);
  841. erroneous_txs.push(tx.clone());
  842. overlay.lock().unwrap().revert_to_checkpoint()?;
  843. break
  844. }
  845. // Update accumulated total gas
  846. total_gas_used += tx_gas_used;
  847. total_gas_paid += gas_data.paid;
  848. }
  849. if !erroneous_txs.is_empty() {
  850. return Err(TxVerifyFailed::ErroneousTxs(erroneous_txs).into())
  851. }
  852. Ok((total_gas_used, total_gas_paid))
  853. }
  854. /// Apply given set of [`Transaction`] in sequence, without formal verification.
  855. /// In case any of the transactions fail, they will be returned to the caller as an error.
  856. /// Additionally, their hash is appended to the provided Merkle tree.
  857. async fn apply_transactions(
  858. overlay: &BlockchainOverlayPtr,
  859. verifying_block_height: u32,
  860. block_target: u32,
  861. txs: &[Transaction],
  862. tree: &mut MerkleTree,
  863. ) -> Result<()> {
  864. debug!(target: "validator::verification::apply_transactions", "Applying {} transactions", txs.len());
  865. if txs.is_empty() {
  866. return Ok(())
  867. }
  868. // Tracker for failed txs
  869. let mut erroneous_txs = vec![];
  870. // Iterate over transactions and attempt to apply them
  871. for tx in txs {
  872. overlay.lock().unwrap().checkpoint();
  873. if let Err(e) =
  874. apply_transaction(overlay, verifying_block_height, block_target, tx, tree).await
  875. {
  876. warn!(target: "validator::verification::apply_transactions", "Transaction apply failed: {}", e);
  877. erroneous_txs.push(tx.clone());
  878. overlay.lock().unwrap().revert_to_checkpoint()?;
  879. };
  880. }
  881. if !erroneous_txs.is_empty() {
  882. return Err(TxVerifyFailed::ErroneousTxs(erroneous_txs).into())
  883. }
  884. Ok(())
  885. }
  886. /// Verify given [`Proposal`] against provided consensus state.
  887. ///
  888. /// A proposal is considered valid when the following rules apply:
  889. /// 1. Proposal hash matches the actual block one
  890. /// 2. Block is valid
  891. /// Additional validity rules can be applied.
  892. pub async fn verify_proposal(
  893. consensus: &Consensus,
  894. proposal: &Proposal,
  895. verify_fees: bool,
  896. ) -> Result<(Fork, Option<usize>)> {
  897. // Check if proposal hash matches actual one (1)
  898. let proposal_hash = proposal.block.hash();
  899. if proposal.hash != proposal_hash {
  900. warn!(
  901. target: "validator::verification::verify_proposal", "Received proposal contains mismatched hashes: {} - {}",
  902. proposal.hash, proposal_hash
  903. );
  904. return Err(Error::ProposalHashesMissmatchError)
  905. }
  906. // Check if proposal extends any existing forks
  907. let (mut fork, index) = consensus.find_extended_fork(proposal).await?;
  908. // Grab overlay last block
  909. let previous = fork.overlay.lock().unwrap().last_block()?;
  910. // Verify proposal block (2)
  911. if verify_block(
  912. &fork.overlay,
  913. &fork.module,
  914. &mut fork.state_monotree,
  915. &proposal.block,
  916. &previous,
  917. verify_fees,
  918. )
  919. .await
  920. .is_err()
  921. {
  922. error!(target: "validator::verification::verify_proposal", "Erroneous proposal block found");
  923. fork.overlay.lock().unwrap().overlay.lock().unwrap().purge_new_trees()?;
  924. return Err(Error::BlockIsInvalid(proposal.hash.as_string()))
  925. };
  926. Ok((fork, index))
  927. }
  928. /// Verify given [`Proposal`] against provided fork state.
  929. ///
  930. /// A proposal is considered valid when the following rules apply:
  931. /// 1. Proposal hash matches the actual block one
  932. /// 2. Block is valid
  933. /// Additional validity rules can be applied.
  934. pub async fn verify_fork_proposal(
  935. fork: &mut Fork,
  936. proposal: &Proposal,
  937. verify_fees: bool,
  938. ) -> Result<()> {
  939. // Check if proposal hash matches actual one (1)
  940. let proposal_hash = proposal.block.hash();
  941. if proposal.hash != proposal_hash {
  942. warn!(
  943. target: "validator::verification::verify_fork_proposal", "Received proposal contains mismatched hashes: {} - {}",
  944. proposal.hash, proposal_hash
  945. );
  946. return Err(Error::ProposalHashesMissmatchError)
  947. }
  948. // Grab overlay last block
  949. let previous = fork.overlay.lock().unwrap().last_block()?;
  950. // Verify proposal block (2)
  951. if verify_block(
  952. &fork.overlay,
  953. &fork.module,
  954. &mut fork.state_monotree,
  955. &proposal.block,
  956. &previous,
  957. verify_fees,
  958. )
  959. .await
  960. .is_err()
  961. {
  962. error!(target: "validator::verification::verify_fork_proposal", "Erroneous proposal block found");
  963. fork.overlay.lock().unwrap().overlay.lock().unwrap().purge_new_trees()?;
  964. return Err(Error::BlockIsInvalid(proposal.hash.as_string()))
  965. };
  966. Ok(())
  967. }