|
@@ -43,7 +43,7 @@ pub async fn verify_genesis_block(
|
|
|
genesis_txs_total: u64,
|
|
genesis_txs_total: u64,
|
|
|
) -> Result<()> {
|
|
) -> Result<()> {
|
|
|
let block_hash = block.blockhash().to_string();
|
|
let block_hash = block.blockhash().to_string();
|
|
|
- debug!(target: "validator", "Validating genesis block {}", block_hash);
|
|
|
|
|
|
|
+ debug!(target: "validator::verification::verify_genesis_block", "Validating genesis block {}", block_hash);
|
|
|
|
|
|
|
|
// Check if block already exists
|
|
// Check if block already exists
|
|
|
if overlay.lock().unwrap().has_block(block)? {
|
|
if overlay.lock().unwrap().has_block(block)? {
|
|
@@ -76,14 +76,14 @@ pub async fn verify_genesis_block(
|
|
|
|
|
|
|
|
// Genesis transaction must be the Transaction::default() one (empty)
|
|
// Genesis transaction must be the Transaction::default() one (empty)
|
|
|
if block.producer.proposal != Transaction::default() {
|
|
if block.producer.proposal != Transaction::default() {
|
|
|
- error!(target: "validator", "Genesis proposal transaction is not default one");
|
|
|
|
|
|
|
+ error!(target: "validator::verification::verify_genesis_block", "Genesis proposal transaction is not default one");
|
|
|
return Err(TxVerifyFailed::ErroneousTxs(vec![block.producer.proposal.clone()]).into())
|
|
return Err(TxVerifyFailed::ErroneousTxs(vec![block.producer.proposal.clone()]).into())
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
// Verify transactions
|
|
// Verify transactions
|
|
|
let erroneous_txs = verify_transactions(overlay, time_keeper, &block.txs).await?;
|
|
let erroneous_txs = verify_transactions(overlay, time_keeper, &block.txs).await?;
|
|
|
if !erroneous_txs.is_empty() {
|
|
if !erroneous_txs.is_empty() {
|
|
|
- warn!(target: "validator", "Erroneous transactions found in set");
|
|
|
|
|
|
|
+ warn!(target: "validator::verification::verify_genesis_block", "Erroneous transactions found in set");
|
|
|
overlay.lock().unwrap().overlay.lock().unwrap().purge_new_trees()?;
|
|
overlay.lock().unwrap().overlay.lock().unwrap().purge_new_trees()?;
|
|
|
return Err(TxVerifyFailed::ErroneousTxs(erroneous_txs).into())
|
|
return Err(TxVerifyFailed::ErroneousTxs(erroneous_txs).into())
|
|
|
}
|
|
}
|
|
@@ -91,7 +91,7 @@ pub async fn verify_genesis_block(
|
|
|
// Insert block
|
|
// Insert block
|
|
|
overlay.lock().unwrap().add_block(block)?;
|
|
overlay.lock().unwrap().add_block(block)?;
|
|
|
|
|
|
|
|
- debug!(target: "validator", "Genesis block {} verified successfully", block_hash);
|
|
|
|
|
|
|
+ debug!(target: "validator::verification::verify_genesis_block", "Genesis block {} verified successfully", block_hash);
|
|
|
Ok(())
|
|
Ok(())
|
|
|
}
|
|
}
|
|
|
|
|
|
|
@@ -105,7 +105,7 @@ pub async fn verify_block(
|
|
|
testing_mode: bool,
|
|
testing_mode: bool,
|
|
|
) -> Result<()> {
|
|
) -> Result<()> {
|
|
|
let block_hash = block.blockhash().to_string();
|
|
let block_hash = block.blockhash().to_string();
|
|
|
- debug!(target: "validator", "Validating block {}", block_hash);
|
|
|
|
|
|
|
+ debug!(target: "validator::verification::verify_block", "Validating block {}", block_hash);
|
|
|
|
|
|
|
|
// Check if block already exists
|
|
// Check if block already exists
|
|
|
if overlay.lock().unwrap().has_block(block)? {
|
|
if overlay.lock().unwrap().has_block(block)? {
|
|
@@ -128,7 +128,7 @@ pub async fn verify_block(
|
|
|
// Verify transactions
|
|
// Verify transactions
|
|
|
let erroneous_txs = verify_transactions(overlay, time_keeper, &block.txs).await?;
|
|
let erroneous_txs = verify_transactions(overlay, time_keeper, &block.txs).await?;
|
|
|
if !erroneous_txs.is_empty() {
|
|
if !erroneous_txs.is_empty() {
|
|
|
- warn!(target: "validator", "Erroneous transactions found in set");
|
|
|
|
|
|
|
+ warn!(target: "validator::verification::verify_block", "Erroneous transactions found in set");
|
|
|
overlay.lock().unwrap().overlay.lock().unwrap().purge_new_trees()?;
|
|
overlay.lock().unwrap().overlay.lock().unwrap().purge_new_trees()?;
|
|
|
return Err(TxVerifyFailed::ErroneousTxs(erroneous_txs).into())
|
|
return Err(TxVerifyFailed::ErroneousTxs(erroneous_txs).into())
|
|
|
}
|
|
}
|
|
@@ -136,7 +136,7 @@ pub async fn verify_block(
|
|
|
// Insert block
|
|
// Insert block
|
|
|
overlay.lock().unwrap().add_block(block)?;
|
|
overlay.lock().unwrap().add_block(block)?;
|
|
|
|
|
|
|
|
- debug!(target: "validator", "Block {} verified successfully", block_hash);
|
|
|
|
|
|
|
+ debug!(target: "validator::verification::verify_block", "Block {} verified successfully", block_hash);
|
|
|
Ok(())
|
|
Ok(())
|
|
|
}
|
|
}
|
|
|
|
|
|
|
@@ -148,13 +148,13 @@ pub async fn verify_proposal_transaction(
|
|
|
tx: &Transaction,
|
|
tx: &Transaction,
|
|
|
) -> Result<()> {
|
|
) -> Result<()> {
|
|
|
let tx_hash = tx.hash();
|
|
let tx_hash = tx.hash();
|
|
|
- debug!(target: "validator", "Validating proposal transaction {}", tx_hash);
|
|
|
|
|
|
|
+ debug!(target: "validator::verification::verify_proposal_transaction", "Validating proposal transaction {}", tx_hash);
|
|
|
|
|
|
|
|
// Transaction must contain a single Consensus::Proposal (0x02) call
|
|
// Transaction must contain a single Consensus::Proposal (0x02) call
|
|
|
if tx.calls.len() != 1 ||
|
|
if tx.calls.len() != 1 ||
|
|
|
(tx.calls[0].contract_id != *CONSENSUS_CONTRACT_ID && tx.calls[0].data[0] != 0x02)
|
|
(tx.calls[0].contract_id != *CONSENSUS_CONTRACT_ID && tx.calls[0].data[0] != 0x02)
|
|
|
{
|
|
{
|
|
|
- error!(target: "validator", "Proposal transaction is malformed");
|
|
|
|
|
|
|
+ error!(target: "validator::verification::verify_proposal_transaction", "Proposal transaction is malformed");
|
|
|
return Err(TxVerifyFailed::ErroneousTxs(vec![tx.clone()]).into())
|
|
return Err(TxVerifyFailed::ErroneousTxs(vec![tx.clone()]).into())
|
|
|
}
|
|
}
|
|
|
|
|
|
|
@@ -168,7 +168,7 @@ pub async fn verify_proposal_transaction(
|
|
|
// won't have fee
|
|
// won't have fee
|
|
|
verify_transaction(overlay, time_keeper, tx, &mut vks).await?;
|
|
verify_transaction(overlay, time_keeper, tx, &mut vks).await?;
|
|
|
|
|
|
|
|
- debug!(target: "validator", "Proposal transaction {} verified successfully", tx_hash);
|
|
|
|
|
|
|
+ debug!(target: "validator::verification::verify_proposal_transaction", "Proposal transaction {} verified successfully", tx_hash);
|
|
|
|
|
|
|
|
Ok(())
|
|
Ok(())
|
|
|
}
|
|
}
|
|
@@ -182,7 +182,7 @@ pub async fn verify_transaction(
|
|
|
verifying_keys: &mut HashMap<[u8; 32], HashMap<String, VerifyingKey>>,
|
|
verifying_keys: &mut HashMap<[u8; 32], HashMap<String, VerifyingKey>>,
|
|
|
) -> Result<()> {
|
|
) -> Result<()> {
|
|
|
let tx_hash = tx.hash();
|
|
let tx_hash = tx.hash();
|
|
|
- debug!(target: "validator", "Validating transaction {}", tx_hash);
|
|
|
|
|
|
|
+ debug!(target: "validator::verification::verify_transaction", "Validating transaction {}", tx_hash);
|
|
|
|
|
|
|
|
// Table of public inputs used for ZK proof verification
|
|
// Table of public inputs used for ZK proof verification
|
|
|
let mut zkp_table = vec![];
|
|
let mut zkp_table = vec![];
|
|
@@ -191,20 +191,20 @@ pub async fn verify_transaction(
|
|
|
|
|
|
|
|
// Iterate over all calls to get the metadata
|
|
// Iterate over all calls to get the metadata
|
|
|
for (idx, call) in tx.calls.iter().enumerate() {
|
|
for (idx, call) in tx.calls.iter().enumerate() {
|
|
|
- debug!(target: "validator", "Executing contract call {}", idx);
|
|
|
|
|
|
|
+ debug!(target: "validator::verification::verify_transaction", "Executing contract call {}", idx);
|
|
|
|
|
|
|
|
// Write the actual payload data
|
|
// Write the actual payload data
|
|
|
let mut payload = vec![];
|
|
let mut payload = vec![];
|
|
|
payload.write_u32(idx as u32)?; // Call index
|
|
payload.write_u32(idx as u32)?; // Call index
|
|
|
tx.calls.encode(&mut payload)?; // Actual call data
|
|
tx.calls.encode(&mut payload)?; // Actual call data
|
|
|
|
|
|
|
|
- debug!(target: "validator", "Instantiating WASM runtime");
|
|
|
|
|
|
|
+ debug!(target: "validator::verification::verify_transaction", "Instantiating WASM runtime");
|
|
|
let wasm = overlay.lock().unwrap().wasm_bincode.get(call.contract_id)?;
|
|
let wasm = overlay.lock().unwrap().wasm_bincode.get(call.contract_id)?;
|
|
|
|
|
|
|
|
let mut runtime =
|
|
let mut runtime =
|
|
|
Runtime::new(&wasm, overlay.clone(), call.contract_id, time_keeper.clone())?;
|
|
Runtime::new(&wasm, overlay.clone(), call.contract_id, time_keeper.clone())?;
|
|
|
|
|
|
|
|
- debug!(target: "validator", "Executing \"metadata\" call");
|
|
|
|
|
|
|
+ debug!(target: "validator::verification::verify_transaction", "Executing \"metadata\" call");
|
|
|
let metadata = runtime.metadata(&payload)?;
|
|
let metadata = runtime.metadata(&payload)?;
|
|
|
|
|
|
|
|
// Decode the metadata retrieved from the execution
|
|
// Decode the metadata retrieved from the execution
|
|
@@ -214,10 +214,10 @@ pub async fn verify_transaction(
|
|
|
let zkp_pub: Vec<(String, Vec<pallas::Base>)> = Decodable::decode(&mut decoder)?;
|
|
let zkp_pub: Vec<(String, Vec<pallas::Base>)> = Decodable::decode(&mut decoder)?;
|
|
|
let sig_pub: Vec<PublicKey> = Decodable::decode(&mut decoder)?;
|
|
let sig_pub: Vec<PublicKey> = Decodable::decode(&mut decoder)?;
|
|
|
// TODO: Make sure we've read all the bytes above.
|
|
// TODO: Make sure we've read all the bytes above.
|
|
|
- debug!(target: "validator", "Successfully executed \"metadata\" call");
|
|
|
|
|
|
|
+ debug!(target: "validator::verification::verify_transaction", "Successfully executed \"metadata\" call");
|
|
|
|
|
|
|
|
// Here we'll look up verifying keys and insert them into the per-contract map.
|
|
// Here we'll look up verifying keys and insert them into the per-contract map.
|
|
|
- debug!(target: "validator", "Performing VerifyingKey lookups from the sled db");
|
|
|
|
|
|
|
+ debug!(target: "validator::verification::verify_transaction", "Performing VerifyingKey lookups from the sled db");
|
|
|
for (zkas_ns, _) in &zkp_pub {
|
|
for (zkas_ns, _) in &zkp_pub {
|
|
|
let inner_vk_map = verifying_keys.get_mut(&call.contract_id.to_bytes()).unwrap();
|
|
let inner_vk_map = verifying_keys.get_mut(&call.contract_id.to_bytes()).unwrap();
|
|
|
|
|
|
|
@@ -238,14 +238,14 @@ pub async fn verify_transaction(
|
|
|
|
|
|
|
|
// After getting the metadata, we run the "exec" function with the same runtime
|
|
// After getting the metadata, we run the "exec" function with the same runtime
|
|
|
// and the same payload.
|
|
// and the same payload.
|
|
|
- debug!(target: "validator", "Executing \"exec\" call");
|
|
|
|
|
|
|
+ debug!(target: "validator::verification::verify_transaction", "Executing \"exec\" call");
|
|
|
let state_update = runtime.exec(&payload)?;
|
|
let state_update = runtime.exec(&payload)?;
|
|
|
- debug!(target: "validator", "Successfully executed \"exec\" call");
|
|
|
|
|
|
|
+ debug!(target: "validator::verification::verify_transaction", "Successfully executed \"exec\" call");
|
|
|
|
|
|
|
|
// If that was successful, we apply the state update in the ephemeral overlay.
|
|
// If that was successful, we apply the state update in the ephemeral overlay.
|
|
|
- debug!(target: "validator", "Executing \"apply\" call");
|
|
|
|
|
|
|
+ debug!(target: "validator::verification::verify_transaction", "Executing \"apply\" call");
|
|
|
runtime.apply(&state_update)?;
|
|
runtime.apply(&state_update)?;
|
|
|
- debug!(target: "validator", "Successfully executed \"apply\" call");
|
|
|
|
|
|
|
+ debug!(target: "validator::verification::verify_transaction", "Successfully executed \"apply\" call");
|
|
|
|
|
|
|
|
// At this point we're done with the call and move on to the next one.
|
|
// At this point we're done with the call and move on to the next one.
|
|
|
}
|
|
}
|
|
@@ -253,29 +253,29 @@ pub async fn verify_transaction(
|
|
|
// When we're done looping and executing over the tx's contract calls, we now
|
|
// When we're done looping and executing over the tx's contract calls, we now
|
|
|
// move on with verification. First we verify the signatures as that's cheaper,
|
|
// move on with verification. First we verify the signatures as that's cheaper,
|
|
|
// and then finally we verify the ZK proofs.
|
|
// and then finally we verify the ZK proofs.
|
|
|
- debug!(target: "validator", "Verifying signatures for transaction {}", tx_hash);
|
|
|
|
|
|
|
+ debug!(target: "validator::verification::verify_transaction", "Verifying signatures for transaction {}", tx_hash);
|
|
|
if sig_table.len() != tx.signatures.len() {
|
|
if sig_table.len() != tx.signatures.len() {
|
|
|
- error!(target: "validator", "Incorrect number of signatures in tx {}", tx_hash);
|
|
|
|
|
|
|
+ error!(target: "validator::verification::verify_transaction", "Incorrect number of signatures in tx {}", tx_hash);
|
|
|
return Err(TxVerifyFailed::MissingSignatures.into())
|
|
return Err(TxVerifyFailed::MissingSignatures.into())
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
// TODO: Go through the ZK circuits that have to be verified and account for the opcodes.
|
|
// TODO: Go through the ZK circuits that have to be verified and account for the opcodes.
|
|
|
|
|
|
|
|
if let Err(e) = tx.verify_sigs(sig_table) {
|
|
if let Err(e) = tx.verify_sigs(sig_table) {
|
|
|
- error!(target: "validator", "Signature verification for tx {} failed: {}", tx_hash, e);
|
|
|
|
|
|
|
+ error!(target: "validator::verification::verify_transaction", "Signature verification for tx {} failed: {}", tx_hash, e);
|
|
|
return Err(TxVerifyFailed::InvalidSignature.into())
|
|
return Err(TxVerifyFailed::InvalidSignature.into())
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- debug!(target: "validator", "Signature verification successful");
|
|
|
|
|
|
|
+ debug!(target: "validator::verification::verify_transaction", "Signature verification successful");
|
|
|
|
|
|
|
|
- debug!(target: "validator", "Verifying ZK proofs for transaction {}", tx_hash);
|
|
|
|
|
|
|
+ debug!(target: "validator::verification::verify_transaction", "Verifying ZK proofs for transaction {}", tx_hash);
|
|
|
if let Err(e) = tx.verify_zkps(verifying_keys, zkp_table).await {
|
|
if let Err(e) = tx.verify_zkps(verifying_keys, zkp_table).await {
|
|
|
- error!(target: "validator", "ZK proof verification for tx {} failed: {}", tx_hash, e);
|
|
|
|
|
|
|
+ error!(target: "validator::verification::verify_transaction", "ZK proof verification for tx {} failed: {}", tx_hash, e);
|
|
|
return Err(TxVerifyFailed::InvalidZkProof.into())
|
|
return Err(TxVerifyFailed::InvalidZkProof.into())
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- debug!(target: "validator", "ZK proof verification successful");
|
|
|
|
|
- debug!(target: "validator", "Transaction {} verified successfully", tx_hash);
|
|
|
|
|
|
|
+ debug!(target: "validator::verification::verify_transaction", "ZK proof verification successful");
|
|
|
|
|
+ debug!(target: "validator::verification::verify_transaction", "Transaction {} verified successfully", tx_hash);
|
|
|
|
|
|
|
|
Ok(())
|
|
Ok(())
|
|
|
}
|
|
}
|
|
@@ -289,7 +289,7 @@ pub async fn verify_transactions(
|
|
|
time_keeper: &TimeKeeper,
|
|
time_keeper: &TimeKeeper,
|
|
|
txs: &[Transaction],
|
|
txs: &[Transaction],
|
|
|
) -> Result<Vec<Transaction>> {
|
|
) -> Result<Vec<Transaction>> {
|
|
|
- debug!(target: "validator", "Verifying {} transactions", txs.len());
|
|
|
|
|
|
|
+ debug!(target: "validator::verification::verify_transactions", "Verifying {} transactions", txs.len());
|
|
|
|
|
|
|
|
// Tracker for failed txs
|
|
// Tracker for failed txs
|
|
|
let mut erroneous_txs = vec![];
|
|
let mut erroneous_txs = vec![];
|
|
@@ -308,7 +308,7 @@ pub async fn verify_transactions(
|
|
|
for tx in txs {
|
|
for tx in txs {
|
|
|
overlay.lock().unwrap().checkpoint();
|
|
overlay.lock().unwrap().checkpoint();
|
|
|
if let Err(e) = verify_transaction(overlay, time_keeper, tx, &mut vks).await {
|
|
if let Err(e) = verify_transaction(overlay, time_keeper, tx, &mut vks).await {
|
|
|
- warn!(target: "validator", "Transaction verification failed: {}", e);
|
|
|
|
|
|
|
+ warn!(target: "validator::verification::verify_transactions", "Transaction verification failed: {}", e);
|
|
|
erroneous_txs.push(tx.clone());
|
|
erroneous_txs.push(tx.clone());
|
|
|
// TODO: verify this works as expected
|
|
// TODO: verify this works as expected
|
|
|
overlay.lock().unwrap().revert_to_checkpoint()?;
|
|
overlay.lock().unwrap().revert_to_checkpoint()?;
|