mirror of
https://github.com/logos-blockchain/logos-execution-zone.git
synced 2026-05-18 05:59:33 +00:00
Merge pull request #458 from logos-blockchain/arjentix/fix-clock-tx-in-indexer
Fix clock transaction validation in Indexer
This commit is contained in:
commit
cf3639d825
@ -3,7 +3,7 @@ use nssa::AccountId;
|
|||||||
use crate::{
|
use crate::{
|
||||||
HashType,
|
HashType,
|
||||||
block::{Block, HashableBlockData},
|
block::{Block, HashableBlockData},
|
||||||
transaction::NSSATransaction,
|
transaction::{NSSATransaction, clock_invocation},
|
||||||
};
|
};
|
||||||
|
|
||||||
// Helpers
|
// Helpers
|
||||||
@ -15,7 +15,7 @@ pub fn sequencer_sign_key_for_testing() -> nssa::PrivateKey {
|
|||||||
|
|
||||||
// Dummy producers
|
// Dummy producers
|
||||||
|
|
||||||
/// Produce dummy block with.
|
/// Produce dummy block with provided transactions + clock transaction an the end.
|
||||||
///
|
///
|
||||||
/// `id` - block id, provide zero for genesis.
|
/// `id` - block id, provide zero for genesis.
|
||||||
///
|
///
|
||||||
@ -26,8 +26,12 @@ pub fn sequencer_sign_key_for_testing() -> nssa::PrivateKey {
|
|||||||
pub fn produce_dummy_block(
|
pub fn produce_dummy_block(
|
||||||
id: u64,
|
id: u64,
|
||||||
prev_hash: Option<HashType>,
|
prev_hash: Option<HashType>,
|
||||||
transactions: Vec<NSSATransaction>,
|
mut transactions: Vec<NSSATransaction>,
|
||||||
) -> Block {
|
) -> Block {
|
||||||
|
transactions.push(NSSATransaction::Public(clock_invocation(
|
||||||
|
id.saturating_mul(100),
|
||||||
|
)));
|
||||||
|
|
||||||
let block_data = HashableBlockData {
|
let block_data = HashableBlockData {
|
||||||
block_id: id,
|
block_id: id,
|
||||||
prev_block_hash: prev_hash.unwrap_or_default(),
|
prev_block_hash: prev_hash.unwrap_or_default(),
|
||||||
|
|||||||
@ -243,14 +243,9 @@ mod tests {
|
|||||||
&sign_key,
|
&sign_key,
|
||||||
);
|
);
|
||||||
let block_id = u64::try_from(i).unwrap();
|
let block_id = u64::try_from(i).unwrap();
|
||||||
let block_timestamp = block_id.saturating_mul(100);
|
|
||||||
let clock_tx = NSSATransaction::Public(clock_invocation(block_timestamp));
|
|
||||||
|
|
||||||
let next_block = common::test_utils::produce_dummy_block(
|
let next_block =
|
||||||
block_id,
|
common::test_utils::produce_dummy_block(block_id, Some(prev_hash), vec![tx]);
|
||||||
Some(prev_hash),
|
|
||||||
vec![tx, clock_tx],
|
|
||||||
);
|
|
||||||
prev_hash = next_block.header.hash;
|
prev_hash = next_block.header.hash;
|
||||||
|
|
||||||
storage
|
storage
|
||||||
|
|||||||
@ -1,6 +1,9 @@
|
|||||||
use std::{path::Path, sync::Arc};
|
use std::{path::Path, sync::Arc};
|
||||||
|
|
||||||
use common::block::Block;
|
use common::{
|
||||||
|
block::Block,
|
||||||
|
transaction::{NSSATransaction, clock_invocation},
|
||||||
|
};
|
||||||
use nssa::V03State;
|
use nssa::V03State;
|
||||||
use rocksdb::{
|
use rocksdb::{
|
||||||
BoundColumnFamily, ColumnFamilyDescriptor, DBWithThreadMode, MultiThreaded, Options,
|
BoundColumnFamily, ColumnFamilyDescriptor, DBWithThreadMode, MultiThreaded, Options,
|
||||||
@ -169,22 +172,52 @@ impl RocksDBIO {
|
|||||||
for block in self.get_block_batch_seq(
|
for block in self.get_block_batch_seq(
|
||||||
start.checked_add(1).expect("Will be lesser that u64::MAX")..=block_id,
|
start.checked_add(1).expect("Will be lesser that u64::MAX")..=block_id,
|
||||||
)? {
|
)? {
|
||||||
for transaction in block.body.transactions {
|
let expected_clock =
|
||||||
transaction
|
NSSATransaction::Public(clock_invocation(block.header.timestamp));
|
||||||
.transaction_stateless_check()
|
|
||||||
.map_err(|err| {
|
if let Some((clock_tx, user_txs)) = block.body.transactions.split_last() {
|
||||||
DbError::db_interaction_error(format!(
|
if *clock_tx != expected_clock {
|
||||||
"transaction pre check failed with err {err:?}"
|
return Err(DbError::db_interaction_error(
|
||||||
))
|
"Last transaction in block must be the clock invocation for the block timestamp"
|
||||||
})?
|
.to_owned(),
|
||||||
.execute_check_on_state(
|
));
|
||||||
&mut breakpoint,
|
}
|
||||||
|
for transaction in user_txs {
|
||||||
|
transaction
|
||||||
|
.clone()
|
||||||
|
.transaction_stateless_check()
|
||||||
|
.map_err(|err| {
|
||||||
|
DbError::db_interaction_error(format!(
|
||||||
|
"transaction pre check failed with err {err:?}"
|
||||||
|
))
|
||||||
|
})?
|
||||||
|
.execute_check_on_state(
|
||||||
|
&mut breakpoint,
|
||||||
|
block.header.block_id,
|
||||||
|
block.header.timestamp,
|
||||||
|
)
|
||||||
|
.map_err(|err| {
|
||||||
|
DbError::db_interaction_error(format!(
|
||||||
|
"transaction execution failed with err {err:?}"
|
||||||
|
))
|
||||||
|
})?;
|
||||||
|
}
|
||||||
|
|
||||||
|
let NSSATransaction::Public(clock_public_tx) = clock_tx else {
|
||||||
|
return Err(DbError::db_interaction_error(
|
||||||
|
"Clock invocation must be a public transaction".to_owned(),
|
||||||
|
));
|
||||||
|
};
|
||||||
|
|
||||||
|
breakpoint
|
||||||
|
.transition_from_public_transaction(
|
||||||
|
clock_public_tx,
|
||||||
block.header.block_id,
|
block.header.block_id,
|
||||||
block.header.timestamp,
|
block.header.timestamp,
|
||||||
)
|
)
|
||||||
.map_err(|err| {
|
.map_err(|err| {
|
||||||
DbError::db_interaction_error(format!(
|
DbError::db_interaction_error(format!(
|
||||||
"transaction execution failed with err {err:?}"
|
"clock transaction execution failed with err {err:?}"
|
||||||
))
|
))
|
||||||
})?;
|
})?;
|
||||||
}
|
}
|
||||||
@ -213,6 +246,7 @@ fn closest_breakpoint_id(block_id: u64) -> u64 {
|
|||||||
#[expect(clippy::shadow_unrelated, reason = "Fine for tests")]
|
#[expect(clippy::shadow_unrelated, reason = "Fine for tests")]
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
|
use common::test_utils::produce_dummy_block;
|
||||||
use nssa::{AccountId, PublicKey};
|
use nssa::{AccountId, PublicKey};
|
||||||
use tempfile::tempdir;
|
use tempfile::tempdir;
|
||||||
|
|
||||||
@ -302,7 +336,7 @@ mod tests {
|
|||||||
|
|
||||||
let transfer_tx =
|
let transfer_tx =
|
||||||
common::test_utils::create_transaction_native_token_transfer(from, 0, to, 1, &sign_key);
|
common::test_utils::create_transaction_native_token_transfer(from, 0, to, 1, &sign_key);
|
||||||
let block = common::test_utils::produce_dummy_block(2, Some(prev_hash), vec![transfer_tx]);
|
let block = produce_dummy_block(2, Some(prev_hash), vec![transfer_tx]);
|
||||||
|
|
||||||
dbio.put_block(&block, [1; 32]).unwrap();
|
dbio.put_block(&block, [1; 32]).unwrap();
|
||||||
|
|
||||||
@ -369,11 +403,7 @@ mod tests {
|
|||||||
1,
|
1,
|
||||||
&sign_key,
|
&sign_key,
|
||||||
);
|
);
|
||||||
let block = common::test_utils::produce_dummy_block(
|
let block = produce_dummy_block((i + 1).into(), Some(prev_hash), vec![transfer_tx]);
|
||||||
(i + 1).into(),
|
|
||||||
Some(prev_hash),
|
|
||||||
vec![transfer_tx],
|
|
||||||
);
|
|
||||||
dbio.put_block(&block, [i; 32]).unwrap();
|
dbio.put_block(&block, [i; 32]).unwrap();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -439,7 +469,7 @@ mod tests {
|
|||||||
let prev_hash = last_block.header.hash;
|
let prev_hash = last_block.header.hash;
|
||||||
let transfer_tx =
|
let transfer_tx =
|
||||||
common::test_utils::create_transaction_native_token_transfer(from, 0, to, 1, &sign_key);
|
common::test_utils::create_transaction_native_token_transfer(from, 0, to, 1, &sign_key);
|
||||||
let block = common::test_utils::produce_dummy_block(2, Some(prev_hash), vec![transfer_tx]);
|
let block = produce_dummy_block(2, Some(prev_hash), vec![transfer_tx]);
|
||||||
|
|
||||||
let control_hash1 = block.header.hash;
|
let control_hash1 = block.header.hash;
|
||||||
|
|
||||||
@ -451,7 +481,7 @@ mod tests {
|
|||||||
let prev_hash = last_block.header.hash;
|
let prev_hash = last_block.header.hash;
|
||||||
let transfer_tx =
|
let transfer_tx =
|
||||||
common::test_utils::create_transaction_native_token_transfer(from, 1, to, 1, &sign_key);
|
common::test_utils::create_transaction_native_token_transfer(from, 1, to, 1, &sign_key);
|
||||||
let block = common::test_utils::produce_dummy_block(3, Some(prev_hash), vec![transfer_tx]);
|
let block = produce_dummy_block(3, Some(prev_hash), vec![transfer_tx]);
|
||||||
|
|
||||||
let control_hash2 = block.header.hash;
|
let control_hash2 = block.header.hash;
|
||||||
|
|
||||||
@ -466,7 +496,7 @@ mod tests {
|
|||||||
|
|
||||||
let control_tx_hash1 = transfer_tx.hash();
|
let control_tx_hash1 = transfer_tx.hash();
|
||||||
|
|
||||||
let block = common::test_utils::produce_dummy_block(4, Some(prev_hash), vec![transfer_tx]);
|
let block = produce_dummy_block(4, Some(prev_hash), vec![transfer_tx]);
|
||||||
dbio.put_block(&block, [3; 32]).unwrap();
|
dbio.put_block(&block, [3; 32]).unwrap();
|
||||||
|
|
||||||
let last_id = dbio.get_meta_last_block_in_db().unwrap();
|
let last_id = dbio.get_meta_last_block_in_db().unwrap();
|
||||||
@ -478,7 +508,7 @@ mod tests {
|
|||||||
|
|
||||||
let control_tx_hash2 = transfer_tx.hash();
|
let control_tx_hash2 = transfer_tx.hash();
|
||||||
|
|
||||||
let block = common::test_utils::produce_dummy_block(5, Some(prev_hash), vec![transfer_tx]);
|
let block = produce_dummy_block(5, Some(prev_hash), vec![transfer_tx]);
|
||||||
dbio.put_block(&block, [4; 32]).unwrap();
|
dbio.put_block(&block, [4; 32]).unwrap();
|
||||||
|
|
||||||
let control_block_id1 = dbio.get_block_id_by_hash(control_hash1.0).unwrap().unwrap();
|
let control_block_id1 = dbio.get_block_id_by_hash(control_hash1.0).unwrap().unwrap();
|
||||||
@ -526,7 +556,7 @@ mod tests {
|
|||||||
let prev_hash = last_block.header.hash;
|
let prev_hash = last_block.header.hash;
|
||||||
let transfer_tx =
|
let transfer_tx =
|
||||||
common::test_utils::create_transaction_native_token_transfer(from, 0, to, 1, &sign_key);
|
common::test_utils::create_transaction_native_token_transfer(from, 0, to, 1, &sign_key);
|
||||||
let block = common::test_utils::produce_dummy_block(2, Some(prev_hash), vec![transfer_tx]);
|
let block = produce_dummy_block(2, Some(prev_hash), vec![transfer_tx]);
|
||||||
|
|
||||||
block_res.push(block.clone());
|
block_res.push(block.clone());
|
||||||
dbio.put_block(&block, [1; 32]).unwrap();
|
dbio.put_block(&block, [1; 32]).unwrap();
|
||||||
@ -537,7 +567,7 @@ mod tests {
|
|||||||
let prev_hash = last_block.header.hash;
|
let prev_hash = last_block.header.hash;
|
||||||
let transfer_tx =
|
let transfer_tx =
|
||||||
common::test_utils::create_transaction_native_token_transfer(from, 1, to, 1, &sign_key);
|
common::test_utils::create_transaction_native_token_transfer(from, 1, to, 1, &sign_key);
|
||||||
let block = common::test_utils::produce_dummy_block(3, Some(prev_hash), vec![transfer_tx]);
|
let block = produce_dummy_block(3, Some(prev_hash), vec![transfer_tx]);
|
||||||
|
|
||||||
block_res.push(block.clone());
|
block_res.push(block.clone());
|
||||||
dbio.put_block(&block, [2; 32]).unwrap();
|
dbio.put_block(&block, [2; 32]).unwrap();
|
||||||
@ -549,7 +579,7 @@ mod tests {
|
|||||||
let transfer_tx =
|
let transfer_tx =
|
||||||
common::test_utils::create_transaction_native_token_transfer(from, 2, to, 1, &sign_key);
|
common::test_utils::create_transaction_native_token_transfer(from, 2, to, 1, &sign_key);
|
||||||
|
|
||||||
let block = common::test_utils::produce_dummy_block(4, Some(prev_hash), vec![transfer_tx]);
|
let block = produce_dummy_block(4, Some(prev_hash), vec![transfer_tx]);
|
||||||
block_res.push(block.clone());
|
block_res.push(block.clone());
|
||||||
dbio.put_block(&block, [3; 32]).unwrap();
|
dbio.put_block(&block, [3; 32]).unwrap();
|
||||||
|
|
||||||
@ -560,7 +590,7 @@ mod tests {
|
|||||||
let transfer_tx =
|
let transfer_tx =
|
||||||
common::test_utils::create_transaction_native_token_transfer(from, 3, to, 1, &sign_key);
|
common::test_utils::create_transaction_native_token_transfer(from, 3, to, 1, &sign_key);
|
||||||
|
|
||||||
let block = common::test_utils::produce_dummy_block(5, Some(prev_hash), vec![transfer_tx]);
|
let block = produce_dummy_block(5, Some(prev_hash), vec![transfer_tx]);
|
||||||
block_res.push(block.clone());
|
block_res.push(block.clone());
|
||||||
dbio.put_block(&block, [4; 32]).unwrap();
|
dbio.put_block(&block, [4; 32]).unwrap();
|
||||||
|
|
||||||
@ -633,11 +663,7 @@ mod tests {
|
|||||||
tx_hash_res.push(transfer_tx1.hash().0);
|
tx_hash_res.push(transfer_tx1.hash().0);
|
||||||
tx_hash_res.push(transfer_tx2.hash().0);
|
tx_hash_res.push(transfer_tx2.hash().0);
|
||||||
|
|
||||||
let block = common::test_utils::produce_dummy_block(
|
let block = produce_dummy_block(2, Some(prev_hash), vec![transfer_tx1, transfer_tx2]);
|
||||||
2,
|
|
||||||
Some(prev_hash),
|
|
||||||
vec![transfer_tx1, transfer_tx2],
|
|
||||||
);
|
|
||||||
|
|
||||||
dbio.put_block(&block, [1; 32]).unwrap();
|
dbio.put_block(&block, [1; 32]).unwrap();
|
||||||
|
|
||||||
@ -652,11 +678,7 @@ mod tests {
|
|||||||
tx_hash_res.push(transfer_tx1.hash().0);
|
tx_hash_res.push(transfer_tx1.hash().0);
|
||||||
tx_hash_res.push(transfer_tx2.hash().0);
|
tx_hash_res.push(transfer_tx2.hash().0);
|
||||||
|
|
||||||
let block = common::test_utils::produce_dummy_block(
|
let block = produce_dummy_block(3, Some(prev_hash), vec![transfer_tx1, transfer_tx2]);
|
||||||
3,
|
|
||||||
Some(prev_hash),
|
|
||||||
vec![transfer_tx1, transfer_tx2],
|
|
||||||
);
|
|
||||||
|
|
||||||
dbio.put_block(&block, [2; 32]).unwrap();
|
dbio.put_block(&block, [2; 32]).unwrap();
|
||||||
|
|
||||||
@ -671,11 +693,7 @@ mod tests {
|
|||||||
tx_hash_res.push(transfer_tx1.hash().0);
|
tx_hash_res.push(transfer_tx1.hash().0);
|
||||||
tx_hash_res.push(transfer_tx2.hash().0);
|
tx_hash_res.push(transfer_tx2.hash().0);
|
||||||
|
|
||||||
let block = common::test_utils::produce_dummy_block(
|
let block = produce_dummy_block(4, Some(prev_hash), vec![transfer_tx1, transfer_tx2]);
|
||||||
4,
|
|
||||||
Some(prev_hash),
|
|
||||||
vec![transfer_tx1, transfer_tx2],
|
|
||||||
);
|
|
||||||
|
|
||||||
dbio.put_block(&block, [3; 32]).unwrap();
|
dbio.put_block(&block, [3; 32]).unwrap();
|
||||||
|
|
||||||
@ -687,7 +705,7 @@ mod tests {
|
|||||||
common::test_utils::create_transaction_native_token_transfer(from, 6, to, 1, &sign_key);
|
common::test_utils::create_transaction_native_token_transfer(from, 6, to, 1, &sign_key);
|
||||||
tx_hash_res.push(transfer_tx.hash().0);
|
tx_hash_res.push(transfer_tx.hash().0);
|
||||||
|
|
||||||
let block = common::test_utils::produce_dummy_block(5, Some(prev_hash), vec![transfer_tx]);
|
let block = produce_dummy_block(5, Some(prev_hash), vec![transfer_tx]);
|
||||||
|
|
||||||
dbio.put_block(&block, [4; 32]).unwrap();
|
dbio.put_block(&block, [4; 32]).unwrap();
|
||||||
|
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user