1use std::collections::HashMap;
20
21use darkfi_sdk::{
22 blockchain::block_version,
23 crypto::{
24 schnorr::{SchnorrPublic, Signature},
25 ContractId, MerkleTree, PublicKey,
26 },
27 dark_tree::dark_forest_leaf_vec_integrity_check,
28 deploy::DeployParamsV1,
29 monotree::{self, Monotree},
30 pasta::pallas,
31};
32use darkfi_serial::{deserialize_async, serialize_async, AsyncDecodable, AsyncEncodable};
33use num_bigint::BigUint;
34use sled_overlay::SledDbOverlayStateDiff;
35use smol::io::Cursor;
36use tracing::{debug, error, warn};
37
38use crate::{
39 blockchain::{
40 block_store::append_tx_to_merkle_tree, header_store::PowData::DarkFi, BlockInfo,
41 Blockchain, BlockchainOverlayPtr, HeaderHash,
42 },
43 error::TxVerifyFailed,
44 runtime::vm_runtime::Runtime,
45 tx::{Transaction, MAX_TX_CALLS, MIN_TX_CALLS},
46 validator::{
47 consensus::{Consensus, Fork, Proposal, BLOCK_GAS_LIMIT},
48 fees::{circuit_gas_use, compute_fee, GasData, PALLAS_SCHNORR_SIGNATURE_FEE},
49 pow::PoWModule,
50 },
51 zk::VerifyingKey,
52 Error, Result,
53};
54
55pub async fn verify_genesis_block(
57 overlay: &BlockchainOverlayPtr,
58 block: &BlockInfo,
59 block_target: u32,
60) -> Result<()> {
61 let block_hash = block.hash().as_string();
62 debug!(target: "validator::verification::verify_genesis_block", "Validating genesis block {block_hash}");
63
64 if overlay.lock().unwrap().has_block(block)? {
66 return Err(Error::BlockAlreadyExists(block_hash))
67 }
68
69 if block.header.height != 0 {
71 return Err(Error::BlockIsInvalid(block_hash))
72 }
73
74 if block.header.version != block_version(block.header.height) {
76 return Err(Error::BlockIsInvalid(block_hash))
77 }
78
79 match block.header.pow_data {
81 DarkFi => { }
82 _ => return Err(Error::BlockIsInvalid(block_hash)),
83 }
84
85 if block.txs.is_empty() {
87 return Err(Error::BlockContainsNoTransactions(block_hash))
88 }
89
90 let producer_tx = block.txs.last().unwrap();
92 if producer_tx != &Transaction::default() {
93 error!(target: "validator::verification::verify_genesis_block", "Genesis producer transaction is not default one");
94 return Err(TxVerifyFailed::ErroneousTxs(vec![producer_tx.clone()]).into())
95 }
96
97 let mut tree = MerkleTree::new(1);
100 let txs = &block.txs[..block.txs.len() - 1];
101 if let Err(e) =
102 verify_transactions(overlay, block.header.height, block_target, txs, &mut tree, false).await
103 {
104 warn!(
105 target: "validator::verification::verify_genesis_block",
106 "[VALIDATOR] Erroneous transactions found in set",
107 );
108 overlay.lock().unwrap().overlay.lock().unwrap().purge_new_trees()?;
109 return Err(e)
110 }
111
112 append_tx_to_merkle_tree(&mut tree, producer_tx);
114 if tree.root(0).unwrap() != block.header.transactions_root {
115 error!(target: "validator::verification::verify_genesis_block", "Genesis Merkle tree is invalid");
116 return Err(Error::BlockIsInvalid(block_hash))
117 }
118
119 let state_monotree = overlay.lock().unwrap().contracts.get_state_monotree()?;
121 let Some(state_root) = state_monotree.get_headroot()? else {
122 return Err(Error::ContractsStatesRootNotFoundError);
123 };
124 if state_root != block.header.state_root {
125 return Err(Error::ContractsStatesRootError(
126 blake3::Hash::from_bytes(state_root).to_string(),
127 blake3::Hash::from_bytes(block.header.state_root).to_string(),
128 ));
129 }
130
131 if block.signature != Signature::dummy() {
133 error!(target: "validator::verification::verify_genesis_block", "Genesis producer signature is not dummy one");
134 return Err(Error::InvalidSignature)
135 }
136
137 overlay.lock().unwrap().add_block(block)?;
139
140 debug!(target: "validator::verification::verify_genesis_block", "Genesis block {block_hash} verified successfully");
141 Ok(())
142}
143
144pub fn validate_block(block: &BlockInfo, previous: &BlockInfo, module: &PoWModule) -> Result<()> {
155 if block.header.version != block_version(block.header.height) {
157 return Err(Error::BlockIsInvalid(block.hash().as_string()))
158 }
159
160 if block.header.previous != previous.hash() {
162 return Err(Error::BlockIsInvalid(block.hash().as_string()))
163 }
164
165 if block.header.height != previous.header.height + 1 {
167 return Err(Error::BlockIsInvalid(block.hash().as_string()))
168 }
169
170 if !module.verify_timestamp_by_median(block.header.timestamp) {
172 return Err(Error::BlockIsInvalid(block.hash().as_string()))
173 }
174
175 if !block.header.validate_powdata() {
177 return Err(Error::BlockIsInvalid(block.hash().as_string()))
178 }
179
180 module.verify_block_hash(&block.header)?;
182
183 Ok(())
184}
185
186pub fn validate_blockchain(
190 blockchain: &Blockchain,
191 pow_target: u32,
192 pow_fixed_difficulty: Option<BigUint>,
193) -> Result<()> {
194 let mut module = PoWModule::new(blockchain.clone(), pow_target, pow_fixed_difficulty, Some(0))?;
196
197 let blocks = blockchain.blocks.get_all_order()?;
199 for (index, block) in blocks[1..].iter().enumerate() {
200 let full_blocks = blockchain.get_blocks_by_hash(&[blocks[index].1, block.1])?;
201 let full_block = &full_blocks[1];
202 validate_block(full_block, &full_blocks[0], &module)?;
203 module.append(&full_block.header, &module.next_difficulty()?)?;
205 }
206
207 Ok(())
208}
209
210pub async fn verify_block(
212 overlay: &BlockchainOverlayPtr,
213 diffs: &[SledDbOverlayStateDiff],
214 module: &PoWModule,
215 state_monotree: &mut Monotree<monotree::MemoryDb>,
216 block: &BlockInfo,
217 previous: &BlockInfo,
218 verify_fees: bool,
219) -> Result<()> {
220 let block_hash = block.hash();
221 debug!(target: "validator::verification::verify_block", "Validating block {block_hash}");
222
223 if overlay.lock().unwrap().has_block(block)? {
225 return Err(Error::BlockAlreadyExists(block_hash.as_string()))
226 }
227
228 validate_block(block, previous, module)?;
230
231 if block.txs.is_empty() {
233 return Err(Error::BlockContainsNoTransactions(block_hash.as_string()))
234 }
235
236 let mut tree = MerkleTree::new(1);
238 let txs = &block.txs[..block.txs.len() - 1];
239 let e = verify_transactions(
240 overlay,
241 block.header.height,
242 module.target,
243 txs,
244 &mut tree,
245 verify_fees,
246 )
247 .await;
248 if let Err(e) = e {
249 warn!(
250 target: "validator::verification::verify_block",
251 "[VALIDATOR] Erroneous transactions found in set",
252 );
253 overlay.lock().unwrap().overlay.lock().unwrap().purge_new_trees()?;
254 return Err(e)
255 }
256
257 let public_key = verify_producer_transaction(
259 overlay,
260 block.header.height,
261 module.target,
262 block.txs.last().unwrap(),
263 &mut tree,
264 )
265 .await?;
266
267 if tree.root(0).unwrap() != block.header.transactions_root {
269 error!(target: "validator::verification::verify_block", "Block Merkle tree root is invalid");
270 return Err(Error::BlockIsInvalid(block_hash.as_string()))
271 }
272
273 let diff = overlay.lock().unwrap().overlay.lock().unwrap().diff(diffs)?;
275 overlay.lock().unwrap().contracts.update_state_monotree(&diff, state_monotree)?;
276 let Some(state_root) = state_monotree.get_headroot()? else {
277 return Err(Error::ContractsStatesRootNotFoundError);
278 };
279 if state_root != block.header.state_root {
280 return Err(Error::ContractsStatesRootError(
281 blake3::Hash::from_bytes(state_root).to_string(),
282 blake3::Hash::from_bytes(block.header.state_root).to_string(),
283 ));
284 }
285
286 verify_producer_signature(block, &public_key)?;
288
289 overlay.lock().unwrap().add_block(block)?;
291
292 debug!(target: "validator::verification::verify_block", "Block {block_hash} verified successfully");
293 Ok(())
294}
295
296pub async fn verify_checkpoint_block(
298 overlay: &BlockchainOverlayPtr,
299 diffs: &[SledDbOverlayStateDiff],
300 state_monotree: &mut Monotree<monotree::MemoryDb>,
301 block: &BlockInfo,
302 header: &HeaderHash,
303 block_target: u32,
304) -> Result<()> {
305 let block_hash = block.hash();
306 debug!(target: "validator::verification::verify_checkpoint_block", "Validating block {block_hash}");
307
308 if overlay.lock().unwrap().has_block(block)? {
310 return Err(Error::BlockAlreadyExists(block_hash.as_string()))
311 }
312
313 if block_hash != *header {
315 error!(target: "validator::verification::verify_checkpoint_block", "Block hash doesn't match the expected one");
316 return Err(Error::BlockIsInvalid(block_hash.as_string()))
317 }
318
319 if block.txs.is_empty() {
321 return Err(Error::BlockContainsNoTransactions(block_hash.as_string()))
322 }
323
324 let mut tree = MerkleTree::new(1);
326 let txs = &block.txs[..block.txs.len() - 1];
327 let e = apply_transactions(overlay, block.header.height, block_target, txs, &mut tree).await;
328 if let Err(e) = e {
329 warn!(
330 target: "validator::verification::verify_checkpoint_block",
331 "[VALIDATOR] Erroneous transactions found in set",
332 );
333 overlay.lock().unwrap().overlay.lock().unwrap().purge_new_trees()?;
334 return Err(e)
335 }
336
337 let public_key = apply_producer_transaction(
339 overlay,
340 block.header.height,
341 block_target,
342 block.txs.last().unwrap(),
343 &mut tree,
344 )
345 .await?;
346
347 if tree.root(0).unwrap() != block.header.transactions_root {
349 error!(target: "validator::verification::verify_checkpoint_block", "Block Merkle tree root is invalid");
350 return Err(Error::BlockIsInvalid(block_hash.as_string()))
351 }
352
353 let diff = overlay.lock().unwrap().overlay.lock().unwrap().diff(diffs)?;
355 overlay.lock().unwrap().contracts.update_state_monotree(&diff, state_monotree)?;
356 let Some(state_root) = state_monotree.get_headroot()? else {
357 return Err(Error::ContractsStatesRootNotFoundError);
358 };
359 if state_root != block.header.state_root {
360 return Err(Error::ContractsStatesRootError(
361 blake3::Hash::from_bytes(state_root).to_string(),
362 blake3::Hash::from_bytes(block.header.state_root).to_string(),
363 ));
364 }
365
366 verify_producer_signature(block, &public_key)?;
368
369 overlay.lock().unwrap().add_block(block)?;
371
372 debug!(target: "validator::verification::verify_checkpoint_block", "Block {block_hash} verified successfully");
373 Ok(())
374}
375
376pub fn verify_producer_signature(block: &BlockInfo, public_key: &PublicKey) -> Result<()> {
379 if !public_key.verify(block.header.hash().inner(), &block.signature) {
380 warn!(target: "validator::verification::verify_producer_signature", "Proposer {public_key} signature could not be verified");
381 return Err(Error::InvalidSignature)
382 }
383
384 Ok(())
385}
386
387pub async fn verify_producer_transaction(
393 overlay: &BlockchainOverlayPtr,
394 verifying_block_height: u32,
395 block_target: u32,
396 tx: &Transaction,
397 tree: &mut MerkleTree,
398) -> Result<PublicKey> {
399 let tx_hash = tx.hash();
400 debug!(target: "validator::verification::verify_producer_transaction", "Validating producer transaction {tx_hash}");
401
402 if !tx.is_pow_reward() {
404 return Err(TxVerifyFailed::ErroneousTxs(vec![tx.clone()]).into())
405 }
406
407 let call = &tx.calls[0];
409
410 let mut verifying_keys: HashMap<[u8; 32], HashMap<String, VerifyingKey>> = HashMap::new();
412
413 verifying_keys.insert(call.data.contract_id.to_bytes(), HashMap::new());
415
416 let mut zkp_table = vec![];
418 let mut sig_table = vec![];
420
421 debug!(target: "validator::verification::verify_producer_transaction", "Executing contract call");
422
423 let mut payload = vec![];
425 tx.calls.encode_async(&mut payload).await?; debug!(target: "validator::verification::verify_producer_transaction", "Instantiating WASM runtime");
428 let wasm = overlay.lock().unwrap().contracts.get(call.data.contract_id)?;
429
430 let mut runtime = Runtime::new(
431 &wasm,
432 overlay.clone(),
433 call.data.contract_id,
434 verifying_block_height,
435 block_target,
436 tx_hash,
437 0,
439 )?;
440
441 debug!(target: "validator::verification::verify_producer_transaction", "Executing \"metadata\" call");
442 let metadata = runtime.metadata(&payload)?;
443
444 let mut decoder = Cursor::new(&metadata);
446
447 let zkp_pub: Vec<(String, Vec<pallas::Base>)> =
449 AsyncDecodable::decode_async(&mut decoder).await?;
450 let sig_pub: Vec<PublicKey> = AsyncDecodable::decode_async(&mut decoder).await?;
451
452 if zkp_pub.len() != 1 || sig_pub.len() != 1 {
454 error!(target: "validator::verification::verify_producer_transaction", "Producer transaction contains multiple ZK proofs or signature public keys");
455 return Err(TxVerifyFailed::ErroneousTxs(vec![tx.clone()]).into())
456 }
457
458 debug!(target: "validator::verification::verify_producer_transaction", "Successfully executed \"metadata\" call");
460
461 debug!(target: "validator::verification::verify_producer_transaction", "Performing VerifyingKey lookups from the sled db");
463 for (zkas_ns, _) in &zkp_pub {
464 let inner_vk_map = verifying_keys.get_mut(&call.data.contract_id.to_bytes()).unwrap();
466 if inner_vk_map.contains_key(zkas_ns.as_str()) {
467 continue
468 }
469
470 let (_zkbin, vk) =
471 overlay.lock().unwrap().contracts.get_zkas(&call.data.contract_id, zkas_ns)?;
472
473 inner_vk_map.insert(zkas_ns.to_string(), vk);
474 }
475
476 zkp_table.push(zkp_pub);
477 let signature_public_key = *sig_pub.last().unwrap();
478 sig_table.push(sig_pub);
479
480 debug!(target: "validator::verification::verify_producer_transaction", "Executing \"exec\" call");
484 let mut state_update = vec![call.data.data[0]];
485 state_update.append(&mut runtime.exec(&payload)?);
486 debug!(target: "validator::verification::verify_producer_transaction", "Successfully executed \"exec\" call");
487
488 debug!(target: "validator::verification::verify_producer_transaction", "Executing \"apply\" call");
490 runtime.apply(&state_update)?;
491 debug!(target: "validator::verification::verify_producer_transaction", "Successfully executed \"apply\" call");
492
493 debug!(target: "validator::verification::verify_producer_transaction", "Verifying signatures for transaction {tx_hash}");
496 if sig_table.len() != tx.signatures.len() {
497 error!(target: "validator::verification::verify_producer_transaction", "Incorrect number of signatures in tx {tx_hash}");
498 return Err(TxVerifyFailed::MissingSignatures.into())
499 }
500
501 if let Err(e) = tx.verify_sigs(sig_table) {
504 error!(target: "validator::verification::verify_producer_transaction", "Signature verification for tx {tx_hash} failed: {e}");
505 return Err(TxVerifyFailed::InvalidSignature.into())
506 }
507
508 debug!(target: "validator::verification::verify_producer_transaction", "Signature verification successful");
509
510 debug!(target: "validator::verification::verify_producer_transaction", "Verifying ZK proofs for transaction {tx_hash}");
511 if let Err(e) = tx.verify_zkps(&verifying_keys, zkp_table).await {
512 error!(target: "validator::verification::verify_producer_transaction", "ZK proof verification for tx {tx_hash} failed: {e}");
513 return Err(TxVerifyFailed::InvalidZkProof.into())
514 }
515 debug!(target: "validator::verification::verify_producer_transaction", "ZK proof verification successful");
516
517 append_tx_to_merkle_tree(tree, tx);
519
520 debug!(target: "validator::verification::verify_producer_transaction", "Producer transaction {tx_hash} verified successfully");
521
522 Ok(signature_public_key)
523}
524
525pub async fn apply_producer_transaction(
528 overlay: &BlockchainOverlayPtr,
529 verifying_block_height: u32,
530 block_target: u32,
531 tx: &Transaction,
532 tree: &mut MerkleTree,
533) -> Result<PublicKey> {
534 let tx_hash = tx.hash();
535 debug!(target: "validator::verification::apply_producer_transaction", "Applying producer transaction {tx_hash}");
536
537 if !tx.is_single_call() {
539 return Err(TxVerifyFailed::ErroneousTxs(vec![tx.clone()]).into())
540 }
541
542 debug!(target: "validator::verification::apply_producer_transaction", "Executing contract call");
543
544 let mut payload = vec![];
546 tx.calls.encode_async(&mut payload).await?; debug!(target: "validator::verification::apply_producer_transaction", "Instantiating WASM runtime");
549 let call = &tx.calls[0];
550 let wasm = overlay.lock().unwrap().contracts.get(call.data.contract_id)?;
551
552 let mut runtime = Runtime::new(
553 &wasm,
554 overlay.clone(),
555 call.data.contract_id,
556 verifying_block_height,
557 block_target,
558 tx_hash,
559 0,
561 )?;
562
563 debug!(target: "validator::verification::apply_producer_transaction", "Executing \"metadata\" call");
564 let metadata = runtime.metadata(&payload)?;
565
566 let mut decoder = Cursor::new(&metadata);
568
569 let _: Vec<(String, Vec<pallas::Base>)> = AsyncDecodable::decode_async(&mut decoder).await?;
571 let sig_pub: Vec<PublicKey> = AsyncDecodable::decode_async(&mut decoder).await?;
572
573 if sig_pub.len() != 1 {
575 error!(target: "validator::verification::apply_producer_transaction", "Producer transaction contains multiple ZK proofs or signature public keys");
576 return Err(TxVerifyFailed::ErroneousTxs(vec![tx.clone()]).into())
577 }
578
579 let signature_public_key = *sig_pub.last().unwrap();
580
581 debug!(target: "validator::verification::apply_producer_transaction", "Executing \"exec\" call");
585 let mut state_update = vec![call.data.data[0]];
586 state_update.append(&mut runtime.exec(&payload)?);
587 debug!(target: "validator::verification::apply_producer_transaction", "Successfully executed \"exec\" call");
588
589 debug!(target: "validator::verification::apply_producer_transaction", "Executing \"apply\" call");
591 runtime.apply(&state_update)?;
592 debug!(target: "validator::verification::apply_producer_transaction", "Successfully executed \"apply\" call");
593
594 append_tx_to_merkle_tree(tree, tx);
596
597 debug!(target: "validator::verification::apply_producer_transaction", "Producer transaction {tx_hash} executed successfully");
598
599 Ok(signature_public_key)
600}
601
602pub async fn verify_transaction(
606 overlay: &BlockchainOverlayPtr,
607 verifying_block_height: u32,
608 block_target: u32,
609 tx: &Transaction,
610 tree: &mut MerkleTree,
611 verifying_keys: &mut HashMap<[u8; 32], HashMap<String, VerifyingKey>>,
612 verify_fee: bool,
613) -> Result<GasData> {
614 let tx_hash = tx.hash();
615 debug!(target: "validator::verification::verify_transaction", "Validating transaction {tx_hash}");
616
617 let mut gas_data = GasData::default();
619
620 if verify_fee {
622 dark_forest_leaf_vec_integrity_check(
623 &tx.calls,
624 Some(MIN_TX_CALLS + 1),
625 Some(MAX_TX_CALLS),
626 )?;
627 } else {
628 dark_forest_leaf_vec_integrity_check(&tx.calls, Some(MIN_TX_CALLS), Some(MAX_TX_CALLS))?;
629 }
630
631 let mut zkp_table = vec![];
633 let mut sig_table = vec![];
635
636 let mut fee_call_idx = 0;
638
639 if verify_fee {
640 let mut found_fee = false;
642 for (call_idx, call) in tx.calls.iter().enumerate() {
643 if !call.data.is_money_fee() {
644 continue
645 }
646
647 if found_fee {
648 error!(
649 target: "validator::verification::verify_transcation",
650 "[VALIDATOR] Transaction {tx_hash} contains multiple fee payment calls"
651 );
652 return Err(TxVerifyFailed::InvalidFee.into())
653 }
654
655 found_fee = true;
656 fee_call_idx = call_idx;
657 }
658
659 if !found_fee {
660 error!(
661 target: "validator::verification::verify_transcation",
662 "[VALIDATOR] Transaction {tx_hash} does not contain fee payment call"
663 );
664 return Err(TxVerifyFailed::InvalidFee.into())
665 }
666 }
667
668 let mut payload = vec![];
670 tx.calls.encode_async(&mut payload).await?;
671
672 let mut _call_payload = vec![];
674
675 let mut circuits_to_verify = vec![];
677
678 for (idx, call) in tx.calls.iter().enumerate() {
680 debug!(target: "validator::verification::verify_transaction", "Executing contract call {idx}");
681
682 if call.data.is_money_pow_reward() {
684 error!(target: "validator::verification::verify_transaction", "Reward transaction detected");
685 return Err(TxVerifyFailed::ErroneousTxs(vec![tx.clone()]).into())
686 }
687
688 let (call_idx, call_payload) = if call.data.is_money_fee() {
690 _call_payload = vec![];
691 vec![call.clone()].encode_async(&mut _call_payload).await?;
692 (0_u8, &_call_payload)
693 } else {
694 (idx as u8, &payload)
695 };
696
697 debug!(target: "validator::verification::verify_transaction", "Instantiating WASM runtime");
698 let wasm = overlay.lock().unwrap().contracts.get(call.data.contract_id)?;
699 let mut runtime = Runtime::new(
700 &wasm,
701 overlay.clone(),
702 call.data.contract_id,
703 verifying_block_height,
704 block_target,
705 tx_hash,
706 call_idx,
707 )?;
708
709 debug!(target: "validator::verification::verify_transaction", "Executing \"metadata\" call");
710 let metadata = runtime.metadata(call_payload)?;
711
712 let mut decoder = Cursor::new(&metadata);
714
715 let zkp_pub: Vec<(String, Vec<pallas::Base>)> =
717 AsyncDecodable::decode_async(&mut decoder).await?;
718 let sig_pub: Vec<PublicKey> = AsyncDecodable::decode_async(&mut decoder).await?;
719
720 if decoder.position() != metadata.len() as u64 {
721 error!(
722 target: "validator::verification::verify_transaction",
723 "[VALIDATOR] Failed decoding entire metadata buffer for {tx_hash}:{idx}"
724 );
725 return Err(TxVerifyFailed::ErroneousTxs(vec![tx.clone()]).into())
726 }
727
728 debug!(target: "validator::verification::verify_transaction", "Successfully executed \"metadata\" call");
729
730 debug!(target: "validator::verification::verify_transaction", "Performing VerifyingKey lookups from the sled db");
733 for (zkas_ns, _) in &zkp_pub {
734 let inner_vk_map = verifying_keys.get_mut(&call.data.contract_id.to_bytes()).unwrap();
735
736 if inner_vk_map.contains_key(zkas_ns.as_str()) {
740 continue
741 }
742
743 let (zkbin, vk) =
744 overlay.lock().unwrap().contracts.get_zkas(&call.data.contract_id, zkas_ns)?;
745
746 inner_vk_map.insert(zkas_ns.to_string(), vk);
747 circuits_to_verify.push(zkbin);
748 }
749
750 zkp_table.push(zkp_pub);
751 sig_table.push(sig_pub);
752
753 debug!(target: "validator::verification::verify_transaction", "Executing \"exec\" call");
757 let mut state_update = vec![call.data.data[0]];
758 state_update.append(&mut runtime.exec(call_payload)?);
759 debug!(target: "validator::verification::verify_transaction", "Successfully executed \"exec\" call");
760
761 debug!(target: "validator::verification::verify_transaction", "Executing \"apply\" call");
763 runtime.apply(&state_update)?;
764 debug!(target: "validator::verification::verify_transaction", "Successfully executed \"apply\" call");
765
766 if call.data.is_deployment()
769 {
771 debug!(target: "validator::verification::verify_transaction", "Deploying new contract");
772 let deploy_params: DeployParamsV1 = deserialize_async(&call.data.data[1..]).await?;
774 let deploy_cid = ContractId::derive_public(deploy_params.public_key);
775
776 let mut deploy_runtime = Runtime::new(
778 &deploy_params.wasm_bincode,
779 overlay.clone(),
780 deploy_cid,
781 verifying_block_height,
782 block_target,
783 tx_hash,
784 call_idx,
785 )?;
786
787 deploy_runtime.deploy(&deploy_params.ix)?;
788
789 let deploy_gas_used = deploy_runtime.gas_used();
790 debug!(target: "validator::verification::verify_transaction", "The gas used for deployment call {call:?} of transaction {tx_hash}: {deploy_gas_used}");
791 gas_data.deployments += deploy_gas_used;
792 }
793
794 let wasm_gas_used = runtime.gas_used();
797 debug!(target: "validator::verification::verify_transaction", "The gas used for WASM call {call:?} of transaction {tx_hash}: {wasm_gas_used}");
798
799 gas_data.wasm += wasm_gas_used;
801 }
802
803 gas_data.signatures = (PALLAS_SCHNORR_SIGNATURE_FEE * tx.signatures.len() as u64) +
805 serialize_async(tx).await.len() as u64;
806 debug!(target: "validator::verification::verify_transaction", "The gas used for signature of transaction {tx_hash}: {}", gas_data.signatures);
807
808 for zkbin in circuits_to_verify.iter() {
810 let zk_circuit_gas_used = circuit_gas_use(zkbin);
811 debug!(target: "validator::verification::verify_transaction", "The gas used for ZK circuit in namespace {} of transaction {tx_hash}: {zk_circuit_gas_used}", zkbin.namespace);
812
813 gas_data.zk_circuits += zk_circuit_gas_used;
815 }
816
817 let total_gas_used = gas_data.total_gas_used();
819
820 if verify_fee {
821 let fee: u64 = match deserialize_async(&tx.calls[fee_call_idx].data.data[1..9]).await {
823 Ok(v) => v,
824 Err(e) => {
825 error!(
826 target: "validator::verification::verify_transaction",
827 "[VALIDATOR] Failed deserializing tx {tx_hash} fee call: {e}"
828 );
829 return Err(TxVerifyFailed::InvalidFee.into())
830 }
831 };
832
833 let required_fee = compute_fee(&total_gas_used);
835
836 if required_fee > fee {
838 error!(
839 target: "validator::verification::verify_transaction",
840 "[VALIDATOR] Transaction {tx_hash} has insufficient fee. Required: {required_fee}, Paid: {fee}"
841 );
842 return Err(TxVerifyFailed::InsufficientFee.into())
843 }
844 debug!(target: "validator::verification::verify_transaction", "The gas paid for transaction {tx_hash}: {}", gas_data.paid);
845
846 gas_data.paid = fee;
848 }
849
850 debug!(target: "validator::verification::verify_transaction", "Verifying signatures for transaction {tx_hash}");
855 if sig_table.len() != tx.signatures.len() {
856 error!(
857 target: "validator::verification::verify_transaction",
858 "[VALIDATOR] Incorrect number of signatures in tx {tx_hash}"
859 );
860 return Err(TxVerifyFailed::MissingSignatures.into())
861 }
862
863 if let Err(e) = tx.verify_sigs(sig_table) {
864 error!(
865 target: "validator::verification::verify_transaction",
866 "[VALIDATOR] Signature verification for tx {tx_hash} failed: {e}"
867 );
868 return Err(TxVerifyFailed::InvalidSignature.into())
869 }
870 debug!(target: "validator::verification::verify_transaction", "Signature verification successful");
871
872 debug!(target: "validator::verification::verify_transaction", "Verifying ZK proofs for transaction {tx_hash}");
873 if let Err(e) = tx.verify_zkps(verifying_keys, zkp_table).await {
874 error!(
875 target: "validator::verification::verify_transaction",
876 "[VALIDATOR] ZK proof verification for tx {tx_hash} failed: {e}"
877 );
878 return Err(TxVerifyFailed::InvalidZkProof.into())
879 }
880 debug!(target: "validator::verification::verify_transaction", "ZK proof verification successful");
881
882 append_tx_to_merkle_tree(tree, tx);
884
885 debug!(target: "validator::verification::verify_transaction", "The total gas used for transaction {tx_hash}: {total_gas_used}");
886 debug!(target: "validator::verification::verify_transaction", "Transaction {tx_hash} verified successfully");
887 Ok(gas_data)
888}
889
890pub async fn apply_transaction(
893 overlay: &BlockchainOverlayPtr,
894 verifying_block_height: u32,
895 block_target: u32,
896 tx: &Transaction,
897 tree: &mut MerkleTree,
898) -> Result<()> {
899 let tx_hash = tx.hash();
900 debug!(target: "validator::verification::apply_transaction", "Applying transaction {tx_hash}");
901
902 let mut payload = vec![];
904 tx.calls.encode_async(&mut payload).await?;
905
906 for (idx, call) in tx.calls.iter().enumerate() {
908 debug!(target: "validator::verification::apply_transaction", "Executing contract call {idx}");
909
910 debug!(target: "validator::verification::apply_transaction", "Instantiating WASM runtime");
911 let wasm = overlay.lock().unwrap().contracts.get(call.data.contract_id)?;
912 let mut runtime = Runtime::new(
913 &wasm,
914 overlay.clone(),
915 call.data.contract_id,
916 verifying_block_height,
917 block_target,
918 tx_hash,
919 idx as u8,
920 )?;
921
922 debug!(target: "validator::verification::apply_transaction", "Executing \"exec\" call");
925 let mut state_update = vec![call.data.data[0]];
926 state_update.append(&mut runtime.exec(&payload)?);
927 debug!(target: "validator::verification::apply_transaction", "Successfully executed \"exec\" call");
928
929 debug!(target: "validator::verification::apply_transaction", "Executing \"apply\" call");
931 runtime.apply(&state_update)?;
932 debug!(target: "validator::verification::apply_transaction", "Successfully executed \"apply\" call");
933
934 if call.data.is_deployment()
937 {
939 debug!(target: "validator::verification::apply_transaction", "Deploying new contract");
940 let deploy_params: DeployParamsV1 = deserialize_async(&call.data.data[1..]).await?;
942 let deploy_cid = ContractId::derive_public(deploy_params.public_key);
943
944 let mut deploy_runtime = Runtime::new(
946 &deploy_params.wasm_bincode,
947 overlay.clone(),
948 deploy_cid,
949 verifying_block_height,
950 block_target,
951 tx_hash,
952 idx as u8,
953 )?;
954
955 deploy_runtime.deploy(&deploy_params.ix)?;
956 }
957 }
958
959 append_tx_to_merkle_tree(tree, tx);
961
962 debug!(target: "validator::verification::apply_transaction", "Transaction {tx_hash} applied successfully");
963 Ok(())
964}
965
966pub async fn verify_transactions(
973 overlay: &BlockchainOverlayPtr,
974 verifying_block_height: u32,
975 block_target: u32,
976 txs: &[Transaction],
977 tree: &mut MerkleTree,
978 verify_fees: bool,
979) -> Result<(u64, u64)> {
980 debug!(target: "validator::verification::verify_transactions", "Verifying {} transactions", txs.len());
981 if txs.is_empty() {
982 return Ok((0, 0))
983 }
984
985 let mut erroneous_txs = vec![];
987
988 let mut total_gas_used = 0;
990 let mut total_gas_paid = 0;
991
992 let mut vks: HashMap<[u8; 32], HashMap<String, VerifyingKey>> = HashMap::new();
994
995 for tx in txs {
997 for call in &tx.calls {
998 vks.insert(call.data.contract_id.to_bytes(), HashMap::new());
999 }
1000 }
1001
1002 for tx in txs {
1004 overlay.lock().unwrap().checkpoint();
1005 let gas_data = match verify_transaction(
1006 overlay,
1007 verifying_block_height,
1008 block_target,
1009 tx,
1010 tree,
1011 &mut vks,
1012 verify_fees,
1013 )
1014 .await
1015 {
1016 Ok(gas_values) => gas_values,
1017 Err(e) => {
1018 warn!(target: "validator::verification::verify_transactions", "Transaction verification failed: {e}");
1019 erroneous_txs.push(tx.clone());
1020 overlay.lock().unwrap().overlay.lock().unwrap().purge_new_trees()?;
1021 overlay.lock().unwrap().revert_to_checkpoint()?;
1022 continue
1023 }
1024 };
1025
1026 let tx_gas_used = gas_data.total_gas_used();
1028
1029 let accumulated_gas_usage = total_gas_used + tx_gas_used;
1031
1032 if accumulated_gas_usage > BLOCK_GAS_LIMIT {
1034 warn!(
1035 target: "validator::verification::verify_transactions",
1036 "Transaction {} exceeds configured transaction gas limit: {accumulated_gas_usage} - {BLOCK_GAS_LIMIT}",
1037 tx.hash()
1038 );
1039 erroneous_txs.push(tx.clone());
1040 overlay.lock().unwrap().overlay.lock().unwrap().purge_new_trees()?;
1041 overlay.lock().unwrap().revert_to_checkpoint()?;
1042 break
1043 }
1044
1045 total_gas_used += tx_gas_used;
1047 total_gas_paid += gas_data.paid;
1048 }
1049
1050 if !erroneous_txs.is_empty() {
1051 return Err(TxVerifyFailed::ErroneousTxs(erroneous_txs).into())
1052 }
1053
1054 Ok((total_gas_used, total_gas_paid))
1055}
1056
1057async fn apply_transactions(
1061 overlay: &BlockchainOverlayPtr,
1062 verifying_block_height: u32,
1063 block_target: u32,
1064 txs: &[Transaction],
1065 tree: &mut MerkleTree,
1066) -> Result<()> {
1067 debug!(target: "validator::verification::apply_transactions", "Applying {} transactions", txs.len());
1068 if txs.is_empty() {
1069 return Ok(())
1070 }
1071
1072 let mut erroneous_txs = vec![];
1074
1075 for tx in txs {
1077 overlay.lock().unwrap().checkpoint();
1078 if let Err(e) =
1079 apply_transaction(overlay, verifying_block_height, block_target, tx, tree).await
1080 {
1081 warn!(target: "validator::verification::apply_transactions", "Transaction apply failed: {e}");
1082 erroneous_txs.push(tx.clone());
1083 overlay.lock().unwrap().revert_to_checkpoint()?;
1084 };
1085 }
1086
1087 if !erroneous_txs.is_empty() {
1088 return Err(TxVerifyFailed::ErroneousTxs(erroneous_txs).into())
1089 }
1090
1091 Ok(())
1092}
1093
1094pub async fn verify_proposal(
1101 consensus: &Consensus,
1102 proposal: &Proposal,
1103 verify_fees: bool,
1104) -> Result<(Fork, Option<usize>)> {
1105 let proposal_hash = proposal.block.hash();
1107 if proposal.hash != proposal_hash {
1108 warn!(
1109 target: "validator::verification::verify_proposal", "Received proposal contains mismatched hashes: {} - {proposal_hash}",
1110 proposal.hash
1111 );
1112 return Err(Error::ProposalHashesMissmatchError)
1113 }
1114
1115 let (mut fork, index) = consensus.find_extended_fork(proposal).await?;
1117
1118 let previous = fork.overlay.lock().unwrap().last_block()?;
1120
1121 if let Err(e) = verify_block(
1123 &fork.overlay,
1124 &fork.diffs,
1125 &fork.module,
1126 &mut fork.state_monotree,
1127 &proposal.block,
1128 &previous,
1129 verify_fees,
1130 )
1131 .await
1132 {
1133 error!(target: "validator::verification::verify_proposal", "Erroneous proposal block found: {e}");
1134 fork.overlay.lock().unwrap().overlay.lock().unwrap().purge_new_trees()?;
1135 return Err(Error::BlockIsInvalid(proposal.hash.as_string()))
1136 };
1137
1138 Ok((fork, index))
1139}
1140
1141pub async fn verify_fork_proposal(
1148 fork: &mut Fork,
1149 proposal: &Proposal,
1150 verify_fees: bool,
1151) -> Result<()> {
1152 let proposal_hash = proposal.block.hash();
1154 if proposal.hash != proposal_hash {
1155 warn!(
1156 target: "validator::verification::verify_fork_proposal", "Received proposal contains mismatched hashes: {} - {proposal_hash}",
1157 proposal.hash
1158 );
1159 return Err(Error::ProposalHashesMissmatchError)
1160 }
1161
1162 let previous = fork.overlay.lock().unwrap().last_block()?;
1164
1165 if let Err(e) = verify_block(
1167 &fork.overlay,
1168 &fork.diffs,
1169 &fork.module,
1170 &mut fork.state_monotree,
1171 &proposal.block,
1172 &previous,
1173 verify_fees,
1174 )
1175 .await
1176 {
1177 error!(target: "validator::verification::verify_fork_proposal", "Erroneous proposal block found: {e}");
1178 fork.overlay.lock().unwrap().overlay.lock().unwrap().purge_new_trees()?;
1179 return Err(Error::BlockIsInvalid(proposal.hash.as_string()))
1180 };
1181
1182 Ok(())
1183}