verification.rs 41 KB

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