verification.rs 48 KB

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