verification.rs 42 KB

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