1use std::{collections::HashMap, sync::Arc};
20
21use darkfi_sdk::{
22 blockchain::{block_version, compute_fee},
23 crypto::{
24 schnorr::{SchnorrPublic, Signature},
25 ContractId, MerkleTree, PublicKey,
26 },
27 dark_tree::dark_forest_leaf_vec_integrity_check,
28 deploy::DeployParamsV1,
29 pasta::pallas,
30};
31use darkfi_serial::{deserialize_async, serialize_async, AsyncDecodable, AsyncEncodable};
32use num_bigint::BigUint;
33use parking_lot::Mutex;
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, TxLocalState},
45 tx::{Transaction, MAX_TX_CALLS, MIN_TX_CALLS},
46 validator::{
47 consensus::{Consensus, Fork, Proposal, BLOCK_GAS_LIMIT},
48 fees::{circuit_gas_use, GasData, PALLAS_SCHNORR_SIGNATURE_FEE},
49 pow::PoWModule,
50 },
51 zk::VerifyingKey,
52 Error, Result,
53};
54
55pub async fn verify_genesis_block(
61 overlay: &BlockchainOverlayPtr,
62 diffs: &[SledDbOverlayStateDiff],
63 block: &BlockInfo,
64 block_target: u32,
65) -> Result<()> {
66 let block_hash = block.hash().as_string();
67 debug!(target: "validator::verification::verify_genesis_block", "Validating genesis block {block_hash}");
68
69 if overlay.lock().unwrap().has_block(block)? {
71 return Err(Error::BlockAlreadyExists(block_hash))
72 }
73
74 if block.header.height != 0 {
76 return Err(Error::BlockIsInvalid(block_hash))
77 }
78
79 if block.header.version != block_version(block.header.height) {
81 return Err(Error::BlockIsInvalid(block_hash))
82 }
83
84 match block.header.pow_data {
86 DarkFi => { }
87 _ => return Err(Error::BlockIsInvalid(block_hash)),
88 }
89
90 if block.txs.is_empty() {
93 return Err(Error::BlockContainsNoTransactions(block_hash))
94 }
95
96 let producer_tx = block.txs.last().unwrap();
99 if producer_tx != &Transaction::default() {
100 error!(target: "validator::verification::verify_genesis_block", "Genesis producer transaction is not default one");
101 return Err(TxVerifyFailed::ErroneousTxs(vec![producer_tx.clone()]).into())
102 }
103
104 let mut tree = MerkleTree::new(1);
107 let txs = &block.txs[..block.txs.len() - 1];
108 if let Err(e) =
109 verify_transactions(overlay, block.header.height, block_target, txs, &mut tree, false).await
110 {
111 warn!(
112 target: "validator::verification::verify_genesis_block",
113 "[VALIDATOR] Erroneous transactions found in set",
114 );
115 return Err(e)
116 }
117
118 append_tx_to_merkle_tree(&mut tree, producer_tx);
121 if tree.root(0).unwrap() != block.header.transactions_root {
122 error!(target: "validator::verification::verify_genesis_block", "Genesis Merkle tree is invalid");
123 return Err(Error::BlockIsInvalid(block_hash))
124 }
125
126 let diff = overlay.lock().unwrap().overlay.lock().unwrap().diff(diffs)?;
129 let state_root = overlay.lock().unwrap().contracts.update_state_monotree(&diff)?;
130 if state_root != block.header.state_root {
131 return Err(Error::ContractsStatesRootError(
132 blake3::Hash::from_bytes(state_root).to_string(),
133 blake3::Hash::from_bytes(block.header.state_root).to_string(),
134 ));
135 }
136
137 if block.signature != Signature::dummy() {
140 error!(target: "validator::verification::verify_genesis_block", "Genesis producer signature is not dummy one");
141 return Err(Error::InvalidSignature)
142 }
143
144 overlay.lock().unwrap().add_block(block)?;
146
147 debug!(target: "validator::verification::verify_genesis_block", "Genesis block {block_hash} verified successfully");
148 Ok(())
149}
150
151pub fn validate_block(
163 block: &BlockInfo,
164 previous: &BlockInfo,
165 module: &mut PoWModule,
166 is_new: bool,
167) -> Result<()> {
168 if block.header.version != block_version(block.header.height) {
170 return Err(Error::BlockIsInvalid(block.hash().as_string()))
171 }
172
173 if block.header.previous != previous.hash() {
175 return Err(Error::BlockIsInvalid(block.hash().as_string()))
176 }
177
178 if block.header.height != previous.header.height + 1 {
180 return Err(Error::BlockIsInvalid(block.hash().as_string()))
181 }
182
183 let valid = if is_new {
185 module.verify_current_timestamp(block.header.timestamp)?
186 } else {
187 module.verify_timestamp_by_median(block.header.timestamp)
188 };
189 if !valid {
190 return Err(Error::BlockIsInvalid(block.hash().as_string()))
191 }
192
193 if !block.header.validate_powdata() {
195 return Err(Error::BlockIsInvalid(block.hash().as_string()))
196 }
197
198 module.verify_block_hash(&block.header)?;
200
201 Ok(())
202}
203
204pub fn validate_blockchain(
208 blockchain: &Blockchain,
209 pow_target: u32,
210 pow_fixed_difficulty: Option<BigUint>,
211) -> Result<()> {
212 let mut module = PoWModule::new(blockchain.clone(), pow_target, pow_fixed_difficulty, Some(0))?;
214
215 let blocks = blockchain.blocks.get_all_order()?;
217 for (index, block) in blocks[1..].iter().enumerate() {
218 let full_blocks = blockchain.get_blocks_by_hash(&[blocks[index].1, block.1])?;
219 let full_block = &full_blocks[1];
220 validate_block(full_block, &full_blocks[0], &mut module, false)?;
221 module.append(&full_block.header, &module.next_difficulty()?)?;
223 }
224
225 Ok(())
226}
227
228pub async fn verify_block(
233 overlay: &BlockchainOverlayPtr,
234 diffs: &[SledDbOverlayStateDiff],
235 module: &mut PoWModule,
236 block: &BlockInfo,
237 previous: &BlockInfo,
238 is_new: bool,
239 verify_fees: bool,
240) -> Result<()> {
241 let block_hash = block.hash();
242 debug!(target: "validator::verification::verify_block", "Validating block {block_hash}");
243
244 if overlay.lock().unwrap().has_block(block)? {
246 return Err(Error::BlockAlreadyExists(block_hash.as_string()))
247 }
248
249 validate_block(block, previous, module, is_new)?;
251
252 if block.txs.is_empty() {
255 return Err(Error::BlockContainsNoTransactions(block_hash.as_string()))
256 }
257
258 let mut tree = MerkleTree::new(1);
260 let txs = &block.txs[..block.txs.len() - 1];
261 if let Err(e) = verify_transactions(
262 overlay,
263 block.header.height,
264 module.target,
265 txs,
266 &mut tree,
267 verify_fees,
268 )
269 .await
270 {
271 warn!(
272 target: "validator::verification::verify_block",
273 "[VALIDATOR] Erroneous transactions found in set",
274 );
275 return Err(e)
276 }
277
278 let public_key = verify_producer_transaction(
280 overlay,
281 block.header.height,
282 module.target,
283 block.txs.last().unwrap(),
284 &mut tree,
285 )
286 .await?;
287
288 if tree.root(0).unwrap() != block.header.transactions_root {
290 error!(target: "validator::verification::verify_block", "Block Merkle tree root is invalid");
291 return Err(Error::BlockIsInvalid(block_hash.as_string()))
292 }
293
294 let diff = overlay.lock().unwrap().overlay.lock().unwrap().diff(diffs)?;
297 let state_root = overlay.lock().unwrap().contracts.update_state_monotree(&diff)?;
298 if state_root != block.header.state_root {
299 return Err(Error::ContractsStatesRootError(
300 blake3::Hash::from_bytes(state_root).to_string(),
301 blake3::Hash::from_bytes(block.header.state_root).to_string(),
302 ));
303 }
304
305 verify_producer_signature(block, &public_key)?;
307
308 overlay.lock().unwrap().add_block(block)?;
310
311 debug!(target: "validator::verification::verify_block", "Block {block_hash} verified successfully");
312 Ok(())
313}
314
315pub async fn verify_checkpoint_block(
321 overlay: &BlockchainOverlayPtr,
322 diffs: &[SledDbOverlayStateDiff],
323 block: &BlockInfo,
324 header: &HeaderHash,
325 block_target: u32,
326) -> Result<()> {
327 let block_hash = block.hash();
328 debug!(target: "validator::verification::verify_checkpoint_block", "Validating block {block_hash}");
329
330 if overlay.lock().unwrap().has_block(block)? {
332 return Err(Error::BlockAlreadyExists(block_hash.as_string()))
333 }
334
335 if block_hash != *header {
337 error!(target: "validator::verification::verify_checkpoint_block", "Block hash doesn't match the expected one");
338 return Err(Error::BlockIsInvalid(block_hash.as_string()))
339 }
340
341 if block.txs.is_empty() {
344 return Err(Error::BlockContainsNoTransactions(block_hash.as_string()))
345 }
346
347 let mut tree = MerkleTree::new(1);
349 let txs = &block.txs[..block.txs.len() - 1];
350 if let Err(e) =
351 apply_transactions(overlay, block.header.height, block_target, txs, &mut tree).await
352 {
353 warn!(
354 target: "validator::verification::verify_checkpoint_block",
355 "[VALIDATOR] Erroneous transactions found in set",
356 );
357 return Err(e)
358 }
359
360 let public_key = apply_producer_transaction(
362 overlay,
363 block.header.height,
364 block_target,
365 block.txs.last().unwrap(),
366 &mut tree,
367 )
368 .await?;
369
370 if tree.root(0).unwrap() != block.header.transactions_root {
372 error!(target: "validator::verification::verify_checkpoint_block", "Block Merkle tree root is invalid");
373 return Err(Error::BlockIsInvalid(block_hash.as_string()))
374 }
375
376 let diff = overlay.lock().unwrap().overlay.lock().unwrap().diff(diffs)?;
379 let state_root = overlay.lock().unwrap().contracts.update_state_monotree(&diff)?;
380 if state_root != block.header.state_root {
381 return Err(Error::ContractsStatesRootError(
382 blake3::Hash::from_bytes(state_root).to_string(),
383 blake3::Hash::from_bytes(block.header.state_root).to_string(),
384 ));
385 }
386
387 verify_producer_signature(block, &public_key)?;
389
390 overlay.lock().unwrap().add_block(block)?;
392
393 debug!(target: "validator::verification::verify_checkpoint_block", "Block {block_hash} verified successfully");
394 Ok(())
395}
396
397pub fn verify_producer_signature(block: &BlockInfo, public_key: &PublicKey) -> Result<()> {
400 if !public_key.verify(block.header.hash().inner(), &block.signature) {
401 warn!(target: "validator::verification::verify_producer_signature", "Proposer {public_key} signature could not be verified");
402 return Err(Error::InvalidSignature)
403 }
404
405 Ok(())
406}
407
408pub async fn verify_producer_transaction(
414 overlay: &BlockchainOverlayPtr,
415 verifying_block_height: u32,
416 block_target: u32,
417 tx: &Transaction,
418 tree: &mut MerkleTree,
419) -> Result<PublicKey> {
420 let tx_hash = tx.hash();
421 debug!(target: "validator::verification::verify_producer_transaction", "Validating producer transaction {tx_hash}");
422
423 if !tx.is_pow_reward() {
425 return Err(TxVerifyFailed::ErroneousTxs(vec![tx.clone()]).into())
426 }
427
428 let call = &tx.calls[0];
430
431 let mut verifying_keys: HashMap<[u8; 32], HashMap<String, VerifyingKey>> = HashMap::new();
433
434 verifying_keys.insert(call.data.contract_id.to_bytes(), HashMap::new());
436
437 let mut zkp_table = vec![];
439 let mut sig_table = vec![];
441
442 debug!(target: "validator::verification::verify_producer_transaction", "Executing contract call");
443
444 let mut payload = vec![];
446 tx.calls.encode_async(&mut payload).await?; debug!(target: "validator::verification::verify_producer_transaction", "Instantiating WASM runtime");
449 let wasm = overlay.lock().unwrap().contracts.get(call.data.contract_id)?;
450
451 let tx_local_state = Arc::new(Mutex::new(TxLocalState::new()));
453
454 let mut runtime = Runtime::new(
455 &wasm,
456 overlay.clone(),
457 tx_local_state,
458 call.data.contract_id,
459 verifying_block_height,
460 block_target,
461 tx_hash,
462 0,
464 )?;
465
466 debug!(target: "validator::verification::verify_producer_transaction", "Executing \"metadata\" call");
467 let metadata = runtime.metadata(&payload)?;
468
469 let mut decoder = Cursor::new(&metadata);
471
472 let zkp_pub: Vec<(String, Vec<pallas::Base>)> =
474 AsyncDecodable::decode_async(&mut decoder).await?;
475 let sig_pub: Vec<PublicKey> = AsyncDecodable::decode_async(&mut decoder).await?;
476
477 if zkp_pub.len() != 1 || sig_pub.len() != 1 {
479 error!(target: "validator::verification::verify_producer_transaction", "Producer transaction contains multiple ZK proofs or signature public keys");
480 return Err(TxVerifyFailed::ErroneousTxs(vec![tx.clone()]).into())
481 }
482
483 debug!(target: "validator::verification::verify_producer_transaction", "Successfully executed \"metadata\" call");
485
486 debug!(target: "validator::verification::verify_producer_transaction", "Performing VerifyingKey lookups from the sled db");
488 for (zkas_ns, _) in &zkp_pub {
489 let inner_vk_map = verifying_keys.get_mut(&call.data.contract_id.to_bytes()).unwrap();
491 if inner_vk_map.contains_key(zkas_ns.as_str()) {
492 continue
493 }
494
495 let (_zkbin, vk) =
496 overlay.lock().unwrap().contracts.get_zkas(&call.data.contract_id, zkas_ns)?;
497
498 inner_vk_map.insert(zkas_ns.to_string(), vk);
499 }
500
501 zkp_table.push(zkp_pub);
502 let signature_public_key = *sig_pub.last().unwrap();
503 sig_table.push(sig_pub);
504
505 debug!(target: "validator::verification::verify_producer_transaction", "Executing \"exec\" call");
510 let mut state_update = vec![call.data.data[0]];
511 state_update.append(&mut runtime.exec(&payload)?);
512 debug!(target: "validator::verification::verify_producer_transaction", "Successfully executed \"exec\" call");
513
514 debug!(target: "validator::verification::verify_producer_transaction", "Executing \"apply\" call");
517 runtime.apply(&state_update)?;
518 debug!(target: "validator::verification::verify_producer_transaction", "Successfully executed \"apply\" call");
519
520 debug!(target: "validator::verification::verify_producer_transaction", "Verifying signatures for transaction {tx_hash}");
524 if sig_table.len() != tx.signatures.len() {
525 error!(target: "validator::verification::verify_producer_transaction", "Incorrect number of signatures in tx {tx_hash}");
526 return Err(TxVerifyFailed::MissingSignatures.into())
527 }
528
529 if let Err(e) = tx.verify_sigs(sig_table) {
533 error!(target: "validator::verification::verify_producer_transaction", "Signature verification for tx {tx_hash} failed: {e}");
534 return Err(TxVerifyFailed::InvalidSignature.into())
535 }
536
537 debug!(target: "validator::verification::verify_producer_transaction", "Signature verification successful");
538
539 debug!(target: "validator::verification::verify_producer_transaction", "Verifying ZK proofs for transaction {tx_hash}");
540 if let Err(e) = tx.verify_zkps(&verifying_keys, zkp_table).await {
541 error!(target: "validator::verification::verify_producer_transaction", "ZK proof verification for tx {tx_hash} failed: {e}");
542 return Err(TxVerifyFailed::InvalidZkProof.into())
543 }
544 debug!(target: "validator::verification::verify_producer_transaction", "ZK proof verification successful");
545
546 append_tx_to_merkle_tree(tree, tx);
548
549 debug!(target: "validator::verification::verify_producer_transaction", "Producer transaction {tx_hash} verified successfully");
550
551 Ok(signature_public_key)
552}
553
554pub async fn apply_producer_transaction(
558 overlay: &BlockchainOverlayPtr,
559 verifying_block_height: u32,
560 block_target: u32,
561 tx: &Transaction,
562 tree: &mut MerkleTree,
563) -> Result<PublicKey> {
564 let tx_hash = tx.hash();
565 debug!(target: "validator::verification::apply_producer_transaction", "Applying producer transaction {tx_hash}");
566
567 if !tx.is_single_call() {
569 return Err(TxVerifyFailed::ErroneousTxs(vec![tx.clone()]).into())
570 }
571
572 debug!(target: "validator::verification::apply_producer_transaction", "Executing contract call");
573
574 let mut payload = vec![];
576 tx.calls.encode_async(&mut payload).await?; debug!(target: "validator::verification::apply_producer_transaction", "Instantiating WASM runtime");
579 let call = &tx.calls[0];
580 let wasm = overlay.lock().unwrap().contracts.get(call.data.contract_id)?;
581
582 let tx_local_state = Arc::new(Mutex::new(TxLocalState::new()));
584
585 let mut runtime = Runtime::new(
586 &wasm,
587 overlay.clone(),
588 tx_local_state,
589 call.data.contract_id,
590 verifying_block_height,
591 block_target,
592 tx_hash,
593 0,
595 )?;
596
597 debug!(target: "validator::verification::apply_producer_transaction", "Executing \"metadata\" call");
598 let metadata = runtime.metadata(&payload)?;
599
600 let mut decoder = Cursor::new(&metadata);
602
603 let _: Vec<(String, Vec<pallas::Base>)> = AsyncDecodable::decode_async(&mut decoder).await?;
605 let sig_pub: Vec<PublicKey> = AsyncDecodable::decode_async(&mut decoder).await?;
606
607 if sig_pub.len() != 1 {
609 error!(target: "validator::verification::apply_producer_transaction", "Producer transaction contains multiple ZK proofs or signature public keys");
610 return Err(TxVerifyFailed::ErroneousTxs(vec![tx.clone()]).into())
611 }
612
613 let signature_public_key = *sig_pub.last().unwrap();
614
615 debug!(target: "validator::verification::apply_producer_transaction", "Executing \"exec\" call");
620 let mut state_update = vec![call.data.data[0]];
621 state_update.append(&mut runtime.exec(&payload)?);
622 debug!(target: "validator::verification::apply_producer_transaction", "Successfully executed \"exec\" call");
623
624 debug!(target: "validator::verification::apply_producer_transaction", "Executing \"apply\" call");
627 runtime.apply(&state_update)?;
628 debug!(target: "validator::verification::apply_producer_transaction", "Successfully executed \"apply\" call");
629
630 append_tx_to_merkle_tree(tree, tx);
632
633 debug!(target: "validator::verification::apply_producer_transaction", "Producer transaction {tx_hash} executed successfully");
634
635 Ok(signature_public_key)
636}
637
638pub async fn verify_transaction(
642 overlay: &BlockchainOverlayPtr,
643 verifying_block_height: u32,
644 block_target: u32,
645 tx: &Transaction,
646 tree: &mut MerkleTree,
647 verifying_keys: &mut HashMap<[u8; 32], HashMap<String, VerifyingKey>>,
648 verify_fee: bool,
649) -> Result<GasData> {
650 let tx_hash = tx.hash();
651 debug!(target: "validator::verification::verify_transaction", "Validating transaction {tx_hash}");
652
653 let mut gas_data = GasData::default();
655
656 if verify_fee {
658 dark_forest_leaf_vec_integrity_check(
659 &tx.calls,
660 Some(MIN_TX_CALLS + 1),
661 Some(MAX_TX_CALLS),
662 )?;
663 } else {
664 dark_forest_leaf_vec_integrity_check(&tx.calls, Some(MIN_TX_CALLS), Some(MAX_TX_CALLS))?;
665 }
666
667 let mut zkp_table = vec![];
669 let mut sig_table = vec![];
671
672 let mut fee_call_idx = 0;
674
675 if verify_fee {
676 let mut found_fee = false;
679 for (call_idx, call) in tx.calls.iter().enumerate() {
680 if !call.data.is_money_fee() {
681 continue
682 }
683
684 if found_fee {
685 error!(
686 target: "validator::verification::verify_transcation",
687 "[VALIDATOR] Transaction {tx_hash} contains multiple fee payment calls"
688 );
689 return Err(TxVerifyFailed::InvalidFee.into())
690 }
691
692 found_fee = true;
693 fee_call_idx = call_idx;
694 }
695
696 if !found_fee {
697 error!(
698 target: "validator::verification::verify_transcation",
699 "[VALIDATOR] Transaction {tx_hash} does not contain fee payment call"
700 );
701 return Err(TxVerifyFailed::InvalidFee.into())
702 }
703 }
704
705 let mut payload = vec![];
707 tx.calls.encode_async(&mut payload).await?;
708
709 let mut _call_payload = vec![];
712
713 let mut circuits_to_verify = vec![];
716
717 let tx_local_state = Arc::new(Mutex::new(TxLocalState::new()));
720
721 for (idx, call) in tx.calls.iter().enumerate() {
723 debug!(target: "validator::verification::verify_transaction", "Executing contract call {idx}");
724
725 if call.data.is_money_pow_reward() {
727 error!(target: "validator::verification::verify_transaction", "Reward transaction detected");
728 return Err(TxVerifyFailed::ErroneousTxs(vec![tx.clone()]).into())
729 }
730
731 let (call_idx, call_payload) = if call.data.is_money_fee() {
733 _call_payload = vec![];
734 vec![call.clone()].encode_async(&mut _call_payload).await?;
735 (0_u8, &_call_payload)
736 } else {
737 (idx as u8, &payload)
738 };
739
740 debug!(target: "validator::verification::verify_transaction", "Instantiating WASM runtime");
741 let wasm = overlay.lock().unwrap().contracts.get(call.data.contract_id)?;
742
743 let mut runtime = Runtime::new(
744 &wasm,
745 overlay.clone(),
746 tx_local_state.clone(),
747 call.data.contract_id,
748 verifying_block_height,
749 block_target,
750 tx_hash,
751 call_idx,
752 )?;
753
754 debug!(target: "validator::verification::verify_transaction", "Executing \"metadata\" call");
755 let metadata = runtime.metadata(call_payload)?;
756
757 let mut decoder = Cursor::new(&metadata);
759
760 let zkp_pub: Vec<(String, Vec<pallas::Base>)> =
762 AsyncDecodable::decode_async(&mut decoder).await?;
763 let sig_pub: Vec<PublicKey> = AsyncDecodable::decode_async(&mut decoder).await?;
764
765 if decoder.position() != metadata.len() as u64 {
766 error!(
767 target: "validator::verification::verify_transaction",
768 "[VALIDATOR] Failed decoding entire metadata buffer for {tx_hash}:{idx}"
769 );
770 return Err(TxVerifyFailed::ErroneousTxs(vec![tx.clone()]).into())
771 }
772
773 debug!(target: "validator::verification::verify_transaction", "Successfully executed \"metadata\" call");
774
775 debug!(target: "validator::verification::verify_transaction", "Performing VerifyingKey lookups from the sled db");
780 for (zkas_ns, _) in &zkp_pub {
781 let inner_vk_map = verifying_keys.get_mut(&call.data.contract_id.to_bytes()).unwrap();
782
783 if inner_vk_map.contains_key(zkas_ns.as_str()) {
789 continue
790 }
791
792 let (zkbin, vk) =
793 overlay.lock().unwrap().contracts.get_zkas(&call.data.contract_id, zkas_ns)?;
794
795 inner_vk_map.insert(zkas_ns.to_string(), vk);
796 circuits_to_verify.push(zkbin);
797 }
798
799 zkp_table.push(zkp_pub);
800 sig_table.push(sig_pub);
801
802 debug!(target: "validator::verification::verify_transaction", "Executing \"exec\" call");
807 let mut state_update = vec![call.data.data[0]];
808 state_update.append(&mut runtime.exec(call_payload)?);
809 debug!(target: "validator::verification::verify_transaction", "Successfully executed \"exec\" call");
810
811 debug!(target: "validator::verification::verify_transaction", "Executing \"apply\" call");
814 runtime.apply(&state_update)?;
815 debug!(target: "validator::verification::verify_transaction", "Successfully executed \"apply\" call");
816
817 if call.data.is_deployment()
820 {
822 debug!(target: "validator::verification::verify_transaction", "Deploying new contract");
823 let deploy_params: DeployParamsV1 = deserialize_async(&call.data.data[1..]).await?;
825 let deploy_cid = ContractId::derive_public(deploy_params.public_key);
826
827 let mut deploy_runtime = Runtime::new(
829 &deploy_params.wasm_bincode,
830 overlay.clone(),
831 tx_local_state.clone(),
832 deploy_cid,
833 verifying_block_height,
834 block_target,
835 tx_hash,
836 call_idx,
837 )?;
838
839 deploy_runtime.deploy(&deploy_params.ix)?;
840
841 let deploy_gas_used = deploy_runtime.gas_used();
842 debug!(target: "validator::verification::verify_transaction", "The gas used for deployment call {call:?} of transaction {tx_hash}: {deploy_gas_used}");
843 gas_data.deployments = gas_data.deployments.saturating_add(deploy_gas_used);
844 }
845
846 let wasm_gas_used = runtime.gas_used();
849 debug!(target: "validator::verification::verify_transaction", "The gas used for WASM call {call:?} of transaction {tx_hash}: {wasm_gas_used}");
850
851 gas_data.wasm = gas_data.wasm.saturating_add(wasm_gas_used);
853 }
854
855 gas_data.signatures = PALLAS_SCHNORR_SIGNATURE_FEE
857 .saturating_mul(tx.signatures.len() as u64)
858 .saturating_add(serialize_async(tx).await.len() as u64);
859 debug!(target: "validator::verification::verify_transaction", "The gas used for signature of transaction {tx_hash}: {}", gas_data.signatures);
860
861 for zkbin in circuits_to_verify.iter() {
864 let zk_circuit_gas_used = circuit_gas_use(zkbin);
865 debug!(target: "validator::verification::verify_transaction", "The gas used for ZK circuit in namespace {} of transaction {tx_hash}: {zk_circuit_gas_used}", zkbin.namespace);
866
867 gas_data.zk_circuits = gas_data.zk_circuits.saturating_add(zk_circuit_gas_used);
869 }
870
871 let total_gas_used = gas_data.total_gas_used();
874
875 if verify_fee {
876 let fee: u64 = match deserialize_async(&tx.calls[fee_call_idx].data.data[1..9]).await {
878 Ok(v) => v,
879 Err(e) => {
880 error!(
881 target: "validator::verification::verify_transaction",
882 "[VALIDATOR] Failed deserializing tx {tx_hash} fee call: {e}"
883 );
884 return Err(TxVerifyFailed::InvalidFee.into())
885 }
886 };
887
888 let required_fee = compute_fee(&total_gas_used);
890
891 if required_fee > fee {
894 error!(
895 target: "validator::verification::verify_transaction",
896 "[VALIDATOR] Transaction {tx_hash} has insufficient fee. Required: {required_fee}, Paid: {fee}"
897 );
898 return Err(TxVerifyFailed::InsufficientFee.into())
899 }
900 debug!(target: "validator::verification::verify_transaction", "The gas paid for transaction {tx_hash}: {}", gas_data.paid);
901
902 gas_data.paid = fee;
904 }
905
906 debug!(target: "validator::verification::verify_transaction", "Verifying signatures for transaction {tx_hash}");
911 if sig_table.len() != tx.signatures.len() {
912 error!(
913 target: "validator::verification::verify_transaction",
914 "[VALIDATOR] Incorrect number of signatures in tx {tx_hash}"
915 );
916 return Err(TxVerifyFailed::MissingSignatures.into())
917 }
918
919 if let Err(e) = tx.verify_sigs(sig_table) {
920 error!(
921 target: "validator::verification::verify_transaction",
922 "[VALIDATOR] Signature verification for tx {tx_hash} failed: {e}"
923 );
924 return Err(TxVerifyFailed::InvalidSignature.into())
925 }
926 debug!(target: "validator::verification::verify_transaction", "Signature verification successful");
927
928 debug!(target: "validator::verification::verify_transaction", "Verifying ZK proofs for transaction {tx_hash}");
929 if let Err(e) = tx.verify_zkps(verifying_keys, zkp_table).await {
930 error!(
931 target: "validator::verification::verify_transaction",
932 "[VALIDATOR] ZK proof verification for tx {tx_hash} failed: {e}"
933 );
934 return Err(TxVerifyFailed::InvalidZkProof.into())
935 }
936 debug!(target: "validator::verification::verify_transaction", "ZK proof verification successful");
937
938 append_tx_to_merkle_tree(tree, tx);
940
941 debug!(target: "validator::verification::verify_transaction", "The total gas used for transaction {tx_hash}: {total_gas_used}");
942 debug!(target: "validator::verification::verify_transaction", "Transaction {tx_hash} verified successfully");
943 Ok(gas_data)
944}
945
946pub async fn apply_transaction(
949 overlay: &BlockchainOverlayPtr,
950 verifying_block_height: u32,
951 block_target: u32,
952 tx: &Transaction,
953 tree: &mut MerkleTree,
954) -> Result<()> {
955 let tx_hash = tx.hash();
956 debug!(target: "validator::verification::apply_transaction", "Applying transaction {tx_hash}");
957
958 let mut payload = vec![];
960 tx.calls.encode_async(&mut payload).await?;
961
962 let tx_local_state = Arc::new(Mutex::new(TxLocalState::new()));
964
965 for (idx, call) in tx.calls.iter().enumerate() {
967 debug!(target: "validator::verification::apply_transaction", "Executing contract call {idx}");
968
969 debug!(target: "validator::verification::apply_transaction", "Instantiating WASM runtime");
970 let wasm = overlay.lock().unwrap().contracts.get(call.data.contract_id)?;
971
972 let mut runtime = Runtime::new(
973 &wasm,
974 overlay.clone(),
975 tx_local_state.clone(),
976 call.data.contract_id,
977 verifying_block_height,
978 block_target,
979 tx_hash,
980 idx as u8,
981 )?;
982
983 debug!(target: "validator::verification::apply_transaction", "Executing \"exec\" call");
987 let mut state_update = vec![call.data.data[0]];
988 state_update.append(&mut runtime.exec(&payload)?);
989 debug!(target: "validator::verification::apply_transaction", "Successfully executed \"exec\" call");
990
991 debug!(target: "validator::verification::apply_transaction", "Executing \"apply\" call");
994 runtime.apply(&state_update)?;
995 debug!(target: "validator::verification::apply_transaction", "Successfully executed \"apply\" call");
996
997 if call.data.is_deployment()
1000 {
1002 debug!(target: "validator::verification::apply_transaction", "Deploying new contract");
1003 let deploy_params: DeployParamsV1 = deserialize_async(&call.data.data[1..]).await?;
1005 let deploy_cid = ContractId::derive_public(deploy_params.public_key);
1006
1007 let mut deploy_runtime = Runtime::new(
1009 &deploy_params.wasm_bincode,
1010 overlay.clone(),
1011 tx_local_state.clone(),
1012 deploy_cid,
1013 verifying_block_height,
1014 block_target,
1015 tx_hash,
1016 idx as u8,
1017 )?;
1018
1019 deploy_runtime.deploy(&deploy_params.ix)?;
1020 }
1021 }
1022
1023 append_tx_to_merkle_tree(tree, tx);
1025
1026 debug!(target: "validator::verification::apply_transaction", "Transaction {tx_hash} applied successfully");
1027 Ok(())
1028}
1029
1030pub async fn verify_transactions(
1040 overlay: &BlockchainOverlayPtr,
1041 verifying_block_height: u32,
1042 block_target: u32,
1043 txs: &[Transaction],
1044 tree: &mut MerkleTree,
1045 verify_fees: bool,
1046) -> Result<(u64, u64)> {
1047 debug!(target: "validator::verification::verify_transactions", "Verifying {} transactions", txs.len());
1048 if txs.is_empty() {
1049 return Ok((0, 0))
1050 }
1051
1052 let mut erroneous_txs = vec![];
1054
1055 let mut total_gas_used = 0_u64;
1057 let mut total_gas_paid = 0_u64;
1058
1059 let mut vks: HashMap<[u8; 32], HashMap<String, VerifyingKey>> = HashMap::new();
1061
1062 for tx in txs {
1064 for call in &tx.calls {
1065 vks.insert(call.data.contract_id.to_bytes(), HashMap::new());
1066 }
1067 }
1068
1069 for tx in txs {
1071 overlay.lock().unwrap().checkpoint();
1072 let gas_data = match verify_transaction(
1073 overlay,
1074 verifying_block_height,
1075 block_target,
1076 tx,
1077 tree,
1078 &mut vks,
1079 verify_fees,
1080 )
1081 .await
1082 {
1083 Ok(gas_values) => gas_values,
1084 Err(e) => {
1085 warn!(target: "validator::verification::verify_transactions", "Transaction verification failed: {e}");
1086 erroneous_txs.push(tx.clone());
1087 overlay.lock().unwrap().revert_to_checkpoint();
1088 continue
1089 }
1090 };
1091
1092 let tx_gas_used = gas_data.total_gas_used();
1094
1095 let accumulated_gas_usage = total_gas_used.saturating_add(tx_gas_used);
1097
1098 if accumulated_gas_usage > BLOCK_GAS_LIMIT {
1101 warn!(
1102 target: "validator::verification::verify_transactions",
1103 "Transaction {} exceeds configured transaction gas limit: {accumulated_gas_usage} - {BLOCK_GAS_LIMIT}",
1104 tx.hash()
1105 );
1106 erroneous_txs.push(tx.clone());
1107 overlay.lock().unwrap().revert_to_checkpoint();
1108 break
1109 }
1110
1111 total_gas_used = total_gas_used.saturating_add(tx_gas_used);
1113 total_gas_paid = total_gas_paid.saturating_add(gas_data.paid);
1114 }
1115
1116 if !erroneous_txs.is_empty() {
1117 return Err(TxVerifyFailed::ErroneousTxs(erroneous_txs).into())
1118 }
1119
1120 Ok((total_gas_used, total_gas_paid))
1121}
1122
1123async fn apply_transactions(
1128 overlay: &BlockchainOverlayPtr,
1129 verifying_block_height: u32,
1130 block_target: u32,
1131 txs: &[Transaction],
1132 tree: &mut MerkleTree,
1133) -> Result<()> {
1134 debug!(target: "validator::verification::apply_transactions", "Applying {} transactions", txs.len());
1135 if txs.is_empty() {
1136 return Ok(())
1137 }
1138
1139 let mut erroneous_txs = vec![];
1141
1142 for tx in txs {
1144 overlay.lock().unwrap().checkpoint();
1145 if let Err(e) =
1146 apply_transaction(overlay, verifying_block_height, block_target, tx, tree).await
1147 {
1148 warn!(target: "validator::verification::apply_transactions", "Transaction apply failed: {e}");
1149 erroneous_txs.push(tx.clone());
1150 overlay.lock().unwrap().revert_to_checkpoint();
1151 };
1152 }
1153
1154 if !erroneous_txs.is_empty() {
1155 return Err(TxVerifyFailed::ErroneousTxs(erroneous_txs).into())
1156 }
1157
1158 Ok(())
1159}
1160
1161pub async fn verify_proposal(
1171 consensus: &Consensus,
1172 proposal: &Proposal,
1173 is_new: bool,
1174 verify_fees: bool,
1175) -> Result<(Fork, Option<usize>)> {
1176 let proposal_hash = proposal.block.hash();
1178 if proposal.hash != proposal_hash {
1179 warn!(
1180 target: "validator::verification::verify_proposal", "Received proposal contains mismatched hashes: {} - {proposal_hash}",
1181 proposal.hash
1182 );
1183 return Err(Error::ProposalHashesMissmatchError)
1184 }
1185
1186 let (mut fork, index) = consensus.find_extended_fork(proposal).await?;
1188
1189 let previous = fork.overlay.lock().unwrap().last_block()?;
1191
1192 if let Err(e) = verify_block(
1194 &fork.overlay,
1195 &fork.diffs,
1196 &mut fork.module,
1197 &proposal.block,
1198 &previous,
1199 is_new,
1200 verify_fees,
1201 )
1202 .await
1203 {
1204 error!(target: "validator::verification::verify_proposal", "Erroneous proposal block found: {e}");
1205 return Err(Error::BlockIsInvalid(proposal.hash.as_string()))
1206 };
1207
1208 Ok((fork, index))
1209}
1210
1211pub async fn verify_fork_proposal(
1221 fork: &mut Fork,
1222 proposal: &Proposal,
1223 verify_fees: bool,
1224) -> Result<()> {
1225 let proposal_hash = proposal.block.hash();
1227 if proposal.hash != proposal_hash {
1228 warn!(
1229 target: "validator::verification::verify_fork_proposal", "Received proposal contains mismatched hashes: {} - {proposal_hash}",
1230 proposal.hash
1231 );
1232 return Err(Error::ProposalHashesMissmatchError)
1233 }
1234
1235 let previous = fork.overlay.lock().unwrap().last_block()?;
1237
1238 if let Err(e) = verify_block(
1240 &fork.overlay,
1241 &fork.diffs,
1242 &mut fork.module,
1243 &proposal.block,
1244 &previous,
1245 false,
1246 verify_fees,
1247 )
1248 .await
1249 {
1250 error!(target: "validator::verification::verify_fork_proposal", "Erroneous proposal block found: {e}");
1251 return Err(Error::BlockIsInvalid(proposal.hash.as_string()))
1252 };
1253
1254 Ok(())
1255}