Skip to content
Open
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
34 commits
Select commit Hold shift + click to select a range
f744932
1, add benchmark for testing vm2 transaction execution
jackzhhuang Oct 20, 2025
17a0b49
add benchmark code
jackzhhuang Oct 22, 2025
9a94ccf
Update test
sanlee42 Oct 22, 2025
09b00bc
use 2000 receiver
jackzhhuang Oct 22, 2025
df4ee52
use 1280000 as max sender
jackzhhuang Oct 22, 2025
ceabaf8
add more 128 G as default max memory size
jackzhhuang Oct 22, 2025
be6965f
watch the tranaction
jackzhhuang Oct 24, 2025
a1f2920
fix fmt
jackzhhuang Oct 24, 2025
42462b7
add draw svg
jackzhhuang Nov 7, 2025
e5954a9
update cargo.lock
jackzhhuang Nov 7, 2025
19b0b3b
add get balance2
jackzhhuang Nov 7, 2025
25fdca4
1, update rpc schema
jackzhhuang Nov 7, 2025
95a8ae1
fix fmt and the advice from the coderabbit
jackzhhuang Nov 10, 2025
850b7dc
add bench code
jackzhhuang Nov 10, 2025
65115e1
fix fmt
jackzhhuang Nov 11, 2025
b0829ee
fix query balance2
jackzhhuang Nov 21, 2025
4b708ad
update Cargo.lock
jackzhhuang Nov 25, 2025
8b29ac3
1, add benchmark for testing vm2 transaction execution
jackzhhuang Oct 20, 2025
cb2be65
add benchmark code
jackzhhuang Oct 22, 2025
899567c
Update test
sanlee42 Oct 22, 2025
2484459
use 2000 receiver
jackzhhuang Oct 22, 2025
9ae0965
add more 128 G as default max memory size
jackzhhuang Oct 22, 2025
2fd837d
watch the tranaction
jackzhhuang Oct 24, 2025
c4a6748
watch the tranaction
jackzhhuang Oct 24, 2025
629aa50
fix fmt
jackzhhuang Oct 24, 2025
8e0bfd2
add draw svg
jackzhhuang Nov 7, 2025
3fc47c4
update cargo.lock
jackzhhuang Nov 7, 2025
0d55222
add get balance2
jackzhhuang Nov 7, 2025
ec72123
1, update rpc schema
jackzhhuang Nov 7, 2025
fe813e1
fix fmt and the advice from the coderabbit
jackzhhuang Nov 10, 2025
4fa3d7d
add bench code
jackzhhuang Nov 10, 2025
dd8c66e
fix fmt
jackzhhuang Nov 11, 2025
dfe4132
fix query balance2
jackzhhuang Nov 21, 2025
47803f0
rebase dual-verse-dag
jackzhhuang Nov 27, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
1, add benchmark for testing vm2 transaction execution
2, cache the vm2 config from shengguo lu
3, add batch operations for the transaction interface
  • Loading branch information
jackzhhuang committed Nov 27, 2025
commit 8b29ac3c5f9eb03af252b123adc642dc3315cd9e
1 change: 1 addition & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

93 changes: 39 additions & 54 deletions chain/src/chain.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1254,9 +1254,9 @@ impl ChainReader for BlockChain {

fn get_transaction_info(&self, txn_hash: HashValue) -> Result<Option<StcRichTransactionInfo>> {
let (storage, _storage2) = &self.storage;
let txn_info_ids = storage.get_rich_transaction_info_ids_by_txn_hash(txn_hash)?;
let txn_info_ids = storage.get_transaction_info_ids_by_txn_hash(txn_hash)?;
for txn_info_id in txn_info_ids {
let txn_info = storage.get_transaction_info_by_rich_info_id(txn_info_id)?;
let txn_info = storage.get_transaction_info(txn_info_id)?;
if let Some(txn_info) = txn_info {
if self.exist_block(txn_info.block_id())? {
return Ok(Some(txn_info));
Expand All @@ -1266,6 +1266,17 @@ impl ChainReader for BlockChain {
Ok(None)
}

fn get_transaction_info_by_global_index(
&self,
transaction_global_index: u64,
) -> Result<Option<StcRichTransactionInfo>> {
let (storage, _storage2) = &self.storage;
match self.txn_accumulator.get_leaf(transaction_global_index)? {
None => Ok(None),
Some(hash) => storage.get_transaction_info(hash),
}
}

fn chain_state_reader(&self) -> &dyn ChainStateReader {
&self.statedb.0
}
Expand Down Expand Up @@ -1416,8 +1427,7 @@ impl ChainReader for BlockChain {
.txn_accumulator
.get_leaves(start_index, reverse, max_size)?;
let mut infos = vec![];
let txn_infos =
storage.get_transaction_infos_by_info_ids(hashes.clone(), chain_header.id())?;
let txn_infos = storage.get_transaction_infos(hashes.clone())?;
for (i, info) in txn_infos.into_iter().enumerate() {
match info {
Some(info) => infos.push(info),
Expand Down Expand Up @@ -1496,45 +1506,20 @@ impl ChainReader for BlockChain {
)
})?;

let get_transaction_info_in_this_chain =
|id: HashValue| -> Result<Option<StcRichTransactionInfo>> {
// vm1's TransactionInfo's id and StcRichTransactionInfo's id are same,
// vm2's TransactionInfo's id and StcRichTransactionInfo's id are different
// we are not sure whether the id is from vm1 or vm2, so we need to check both.
let mut rich_ids = storage.get_rich_ids_by_info_id(id).unwrap_or(vec![]);
rich_ids.push(id);
let rich_infos = storage.get_transaction_infos_by_rich_ids(rich_ids)?;
for rich_info in rich_infos {
if rich_info.is_none() {
continue;
}
let rich_info = rich_info.unwrap();
if self.check_exist_block(rich_info.block_id(), rich_info.block_number)? {
return Ok(Some(rich_info));
}
}
Ok(None)
};

let proof_rich_transaction_info =
get_transaction_info_in_this_chain(proof_transaction_info_id)?.ok_or_else(|| {
let proof_rich_transaction_info = storage
.get_transaction_info(proof_transaction_info_id)?
.ok_or_else(|| {
format_err!(
"failed to get proof txn info by hash:{}, block id:{}",
proof_transaction_info_id,
block_id
"failed to get proof txn info by hash:{}",
proof_transaction_info_id
)
})?;

let proof_transaction_info = proof_rich_transaction_info.transaction_info;

let input_rich_transaction_info = get_transaction_info_in_this_chain(transaction_info_id)?
.ok_or_else(|| {
format_err!(
"failed to get txn info by hash:{}, block id:{}",
transaction_info_id,
block_id
)
})?;
let input_rich_transaction_info = storage
.get_transaction_info(transaction_info_id)?
.ok_or_else(|| format_err!("failed to get txn info by hash:{}", transaction_info_id))?;

let final_raw_transaction = storage
.get_transaction(proof_transaction_info.transaction_hash())?
Expand All @@ -1551,14 +1536,9 @@ impl ChainReader for BlockChain {
.ok_or_else(|| format_err!("Cannot get state root hash"))?;
let final_access_path = final_raw_transaction.access_path();

let transaction_info = get_transaction_info_in_this_chain(transaction_info_id)?
.ok_or_else(|| {
format_err!(
"failed to get txn info by hash:{}, block id:{}",
transaction_info_id,
block_id
)
})?;
let transaction_info = storage
.get_transaction_info(transaction_info_id)?
.ok_or_else(|| format_err!("failed to get txn info by hash:{}", transaction_info_id))?;

let event_proof = match input_rich_transaction_info.transaction_info {
StcTransactionInfo::V1(_) => {
Expand Down Expand Up @@ -1840,15 +1820,13 @@ impl BlockChain {
continue;
}

let txn_info = storage
.get_transaction_info_by_info_id(*id, block_id)?
.ok_or_else(|| {
anyhow::anyhow!(format!(
"cannot find txn info with txn_info_id {} on main chain(head: {})",
id,
chain_header.id()
))
})?;
let txn_info = storage.get_transaction_info(*id)?.ok_or_else(|| {
anyhow::anyhow!(format!(
"cannot find txn info with txn_info_id {} on main chain(head: {})",
id,
chain_header.id()
))
})?;

let filtered_event_with_info =
filtered_events.map(|(idx, evt)| StcContractEventInfo {
Expand Down Expand Up @@ -2218,6 +2196,13 @@ impl BlockChain {
format_err!("Can not find block info for parent {:?}", selected_parent)
})?;

// let multi_state = self.storage.0.get_vm_multi_state(selected_parent)?;

// let statedb = self.statedb.0.fork_at(multi_state.state_root1());
// let statedb2 = self.statedb.1.fork_at(multi_state.state_root2());

// Get epoch from forked statedb (read from VM2's statedb)

// Execute VM1 transactions
let executed_data = if !transactions.is_empty() {
starcoin_executor::block_execute(
Expand Down
2 changes: 1 addition & 1 deletion cmd/tx-factory/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -269,4 +269,4 @@ fn main() {

handle.join().unwrap();
info!("txfactory: stop now");
}
}
6 changes: 3 additions & 3 deletions cmd/tx-factory/src/mocker.rs
Original file line number Diff line number Diff line change
Expand Up @@ -132,7 +132,7 @@ impl TxnMocker {
.generate_mock_txn2(self.next_sequence_number, expiration_timestamp)?;
info!("prepare to sign txn, sender: {}", raw_txn.sender());

self.unlock_account2()?;
self.unlock_account()?;

let user_txn = match self.client.account_sign_txn2(raw_txn) {
Err(e) => {
Expand Down Expand Up @@ -585,8 +585,8 @@ impl TxnMocker {
}

if !addr_vec.is_empty() {
self.recheck_sequence_number2()?;
self.unlock_account2()?;
self.recheck_sequence_number()?;
self.unlock_account()?;
let txn = self.generator.generate_account_txn2(
self.next_sequence_number,
self.account_address2,
Expand Down
4 changes: 2 additions & 2 deletions cmd/tx-factory/src/pressure_vm2.rs
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ pub fn start_vm2_pressure_test(
if let Err(e) = success {
error!("fail to run stress test, err: {:?}", &e);
// if txn is rejected, recheck sequence number, and start over
if let Err(e) = tx_mocker.recheck_sequence_number2() {
if let Err(e) = tx_mocker.recheck_sequence_number() {
error!("fail to start over, err: {:?}", e);
}
}
Expand All @@ -46,7 +46,7 @@ pub fn start_vm2_pressure_test(
if let Err(e) = success {
error!("fail to generate/submit mock txn, err: {:?}", &e);
// if txn is rejected, recheck sequence number, and start over
if let Err(e) = tx_mocker.recheck_sequence_number2() {
if let Err(e) = tx_mocker.recheck_sequence_number() {
error!("fail to start over, err: {:?}", e);
}
}
Expand Down
65 changes: 65 additions & 0 deletions commons/parallel-executor/src/executor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ use crate::{
use num_cpus;
use once_cell::sync::Lazy;
use starcoin_infallible::Mutex;
use starcoin_logger::prelude::error;
use starcoin_mvhashmap::MVHashMap;
use std::{collections::HashSet, hash::Hash, marker::PhantomData, sync::Arc, thread::spawn};

Expand Down Expand Up @@ -285,6 +286,60 @@ where
}
}

fn execute_block_meta_data_txn(
&self,
executor_arguments: &E::Argument,
block: &[T],
last_input_output: &TxnLastInputOutput<
<T as Transaction>::Key,
<E as ExecutorTask>::Output,
<E as ExecutorTask>::Error,
>,
versioned_data_cache: &MVHashMap<<T as Transaction>::Key, <T as Transaction>::Value>,
scheduler: &Scheduler,
) {
if block.is_empty() || !block[0].is_block_meta_data() {
return;
}

let executor = E::init(*executor_arguments);
match scheduler.next_task() {
SchedulerTask::ExecutionTask(version, None, guard) => {
let (idx_to_execute, incarnation) = version;
assert!(idx_to_execute == 0 && incarnation == 0);
self.execute(
version,
guard,
block,
last_input_output,
versioned_data_cache,
scheduler,
&executor,
);
}
_ => {
unreachable!()
}
};

match scheduler.next_task() {
SchedulerTask::ValidationTask(version, guard) => {
let (idx_to_execute, incarnation) = version;
assert!(idx_to_execute == 0 && incarnation == 0);
self.validate(
version,
guard,
last_input_output,
versioned_data_cache,
scheduler,
);
}
_ => {
error!("second task from scheduler should be validation of block metadata txn, maybe execute block meta txn failed?");
}
};
}

pub fn execute_transactions_parallel(
&self,
executor_initial_arguments: E::Argument,
Expand All @@ -299,6 +354,16 @@ where
let last_input_output = TxnLastInputOutput::new(num_txns);
let scheduler = Scheduler::new(num_txns);

// BlockMetadata is always the first txn of block that modifies fundamental info of block
// other txns depends on this execution result, execute it first to avoid unnecessary contention
self.execute_block_meta_data_txn(
&executor_initial_arguments,
&signature_verified_block,
&last_input_output,
&versioned_data_cache,
&scheduler,
);

RAYON_EXEC_POOL.scope(|s| {
for _ in 0..self.concurrency_level {
s.spawn(|_| {
Expand Down
6 changes: 6 additions & 0 deletions commons/parallel-executor/src/task.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,12 @@ pub enum ExecutionStatus<T, E> {
pub trait Transaction: Sync + Send + 'static {
type Key: PartialOrd + Send + Sync + Clone + Hash + Eq;
type Value: Send + Sync;

/// Returns true if this transaction is block metadata.
/// Default false to preserve backward compatibility for existing implementors.
fn is_block_meta_data(&self) -> bool {
false
}
}

/// Inference result of a transaction.
Expand Down
2 changes: 1 addition & 1 deletion kube/manifest/starcoin-halley.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ spec:
starcoin/node-pool: seed-pool
containers:
- name: starcoin
image: starcoin/starcoin:sha-718e01a
image: starcoin/starcoin:sha-6a5e4e8
imagePullPolicy: Always
command:
- bash
Expand Down
43 changes: 11 additions & 32 deletions rpc/client/src/remote_state_reader2/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,13 +10,9 @@ use starcoin_vm2_crypto::HashValue;
use starcoin_vm2_state_api::{
AccountStateSetIterator, ChainStateReader, StateWithProof, StateWithTableItemProof,
};
use starcoin_vm2_types::{
account_address::AccountAddress as AccountAddress2,
account_config::{stc_struct_tag, CoinStoreResource},
view::StrView,
};
use starcoin_vm2_types::{
account_address::AccountAddress,
account_config::BalanceResource,
account_state::AccountState,
state_set::{AccountStateSet, ChainStateSet},
};
Expand Down Expand Up @@ -64,33 +60,16 @@ impl<'a> RemoteStateReader<'a> {
Self { client, state_root }
}

pub fn get_balance2(&self, address: AccountAddress2) -> Result<Option<u128>> {
let stc = stc_struct_tag();
let resources = self.client.state_list_resource2(
address,
false,
Some(self.state_root),
0,
usize::MAX,
Some(vec![StrView::from(stc.clone())]),
None,
)?;
for (key, resource) in resources.resources {
if key.0 != stc {
continue;
}
if let Some(_token_code) = CoinStoreResource::token_code(&key.0) {
let balance = resource
.decode::<CoinStoreResource>()
.ok()
.map(|balance| balance.coin() as u128);
return Ok(balance);
} else {
return Ok(None);
}
}

Ok(None)
pub fn get_balance2(&self, address: AccountAddress) -> Result<Option<u128>> {
let state_key = StateKey::resource_typed::<BalanceResource>(&address)?;
self.client
.state_get_with_proof2(state_key)?
.state
.map_or(Ok(None), |state| {
Ok(Some(
bcs_ext::from_bytes::<BalanceResource>(state.0.as_slice())?.token(),
))
})
}
}

Expand Down
4 changes: 0 additions & 4 deletions sync/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -77,10 +77,6 @@ starcoin-account-service = { workspace = true }
starcoin-vm2-account-service = { workspace = true }
starcoin-vm2-statedb = { workspace = true }
starcoin-vm2-vm-runtime = { workspace = true }
starcoin-rpc-client = { workspace = true }
chrono = { workspace = true }
plotters = "0.3"
tempfile = { workspace = true }

[package]
authors = { workspace = true }
Expand Down
Binary file added sync/starcoin-execute-bench/.test.log.swp
Binary file not shown.
Loading