Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Refactor genesis transaction #4364

Merged
merged 3 commits into from
Dec 30, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
23 changes: 15 additions & 8 deletions chain/src/chain.rs
Original file line number Diff line number Diff line change
Expand Up @@ -697,10 +697,10 @@ impl BlockChain {
txn_accumulator,
block_accumulator,
&genesis_epoch,
None,
None, /*parent status*/
genesis_block,
&chain_id,
None,
None, /*VM metrics*/
)?;
dag = Self::init_dag(dag, genesis_header)?;
Self::new(time_service, executed_block.block.id(), storage, None, dag)
Expand Down Expand Up @@ -1269,12 +1269,19 @@ impl BlockChain {
};

watch(CHAIN_WATCH_NAME, "n21");
let executed_data = starcoin_executor::block_execute(
&statedb,
transactions.clone(),
epoch.block_gas_limit(),
vm_metrics,
)?;
let executed_data = if header.is_genesis() {
starcoin_executor::execute_genesis_transaction(
&statedb,
transactions.first().unwrap().clone(),
)?
} else {
starcoin_executor::block_execute(
&statedb,
transactions.clone(),
epoch.block_gas_limit(),
vm_metrics,
)?
};
watch(CHAIN_WATCH_NAME, "n22");
let state_root = executed_data.state_root;
let vec_transaction_info = &executed_data.txn_infos;
Expand Down
77 changes: 70 additions & 7 deletions executor/src/block_executor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,18 @@ use crate::execute_block_transactions;
use serde::{Deserialize, Serialize};
use starcoin_crypto::HashValue;
use starcoin_state_api::{ChainStateReader, ChainStateWriter};
use starcoin_types::error::BlockExecutorError;
use starcoin_types::error::ExecutorResult;
use starcoin_types::transaction::TransactionStatus;
use starcoin_types::transaction::{Transaction, TransactionInfo};
use starcoin_types::{
error::{BlockExecutorError, ExecutorResult},
transaction::{Transaction, TransactionInfo, TransactionStatus},
vm_error::KeptVMStatus,
};
use starcoin_vm_runtime::metrics::VMMetrics;
use starcoin_vm_types::contract_event::ContractEvent;
use starcoin_vm_types::state_store::table::{TableHandle, TableInfo};
use starcoin_vm_types::write_set::WriteSet;
use starcoin_vm_types::{
contract_event::ContractEvent,
state_store::table::{TableHandle, TableInfo},
write_set::WriteSet,
StateView,
};
use std::collections::BTreeMap;

#[cfg(feature = "force-deploy")]
Expand Down Expand Up @@ -64,6 +68,61 @@ impl Default for BlockExecutedData {
}
}

pub fn execute_genesis_transaction<S: StateView + ChainStateWriter + Sync>(
chain_state: &S,
genesis_txn: Transaction,
) -> ExecutorResult<BlockExecutedData> {
let txn_hash = genesis_txn.id();
let txn_outputs = execute_block_transactions(chain_state, vec![genesis_txn], u64::MAX, None)
.map_err(BlockExecutorError::BlockTransactionExecuteErr)?;
assert_eq!(
txn_outputs.len(),
1,
"genesis txn output count must be 1, but got {}",
txn_outputs.len()
);
let mut executed_data = BlockExecutedData::default();
// this expect will never fail, as we have checked the output count is 1.
let (write_set, events, gas_used, status, _) = txn_outputs
.first()
.expect("genesis txn must have one output")
.clone()
.into_inner();
let extra_write_set =
extract_extra_writeset(chain_state).expect("extract extra write set failed");
let write_set = write_set
.into_mut()
.squash(extra_write_set.into_mut())
.expect("failed to squash write set")
.freeze()
.expect("failed to freeze write set");
match status {
TransactionStatus::Keep(status) => {
assert_eq!(status, KeptVMStatus::Executed);
chain_state
.apply_write_set(write_set.clone())
.map_err(BlockExecutorError::BlockChainStateErr)?;

let txn_state_root = chain_state
.commit()
.map_err(BlockExecutorError::BlockChainStateErr)?;
executed_data.state_root = txn_state_root;
executed_data.txn_infos.push(TransactionInfo::new(
txn_hash,
txn_state_root,
events.as_slice(),
gas_used,
status,
));
executed_data.txn_events.push(events);
executed_data.write_sets.push(write_set);
}
_ => unreachable!("genesis txn output must be keep"),
}

Ok(executed_data)
}

pub fn block_execute<S: ChainStateReader + ChainStateWriter + Sync>(
chain_state: &S,
txns: Vec<Transaction>,
Expand Down Expand Up @@ -170,6 +229,10 @@ fn create_force_upgrade_extra_txn<S: ChainStateReader + ChainStateWriter>(
)
}

fn extract_extra_writeset<S: StateView>(_chain_state: &S) -> anyhow::Result<WriteSet> {
Ok(WriteSet::default())
}

// todo: check the execute_extra_txn in OpenedBlock, and merge with it
#[cfg(feature = "force-deploy")]
fn execute_extra_txn<S: ChainStateReader + ChainStateWriter>(
Expand Down
2 changes: 1 addition & 1 deletion executor/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
#[macro_use]
extern crate log;

pub use block_executor::{block_execute, BlockExecutedData};
pub use block_executor::{block_execute, execute_genesis_transaction, BlockExecutedData};
pub use executor::*;
// pub use starcoin_transaction_builder::{
// build_accept_token_txn, build_batch_transfer_txn, build_transfer_from_association,
Expand Down
29 changes: 5 additions & 24 deletions genesis/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@

mod errors;

use anyhow::{bail, ensure, format_err, Result};
use anyhow::{bail, format_err, Result};
pub use errors::GenesisError;
use include_dir::include_dir;
use include_dir::Dir;
Expand Down Expand Up @@ -32,7 +32,6 @@ use starcoin_vm_types::{
account_config::CORE_CODE_ADDRESS,
state_store::StateView,
transaction::{RawUserTransaction, SignedUserTransaction, TransactionPayload},
vm_status::KeptVMStatus,
};
use std::{
fmt::Display,
Expand Down Expand Up @@ -186,31 +185,13 @@ impl Genesis {
txn: SignedUserTransaction,
) -> Result<TransactionInfo> {
let txn = Transaction::UserTransaction(txn);
let txn_hash = txn.id();

let output = starcoin_executor::execute_transactions(chain_state, vec![txn], None)?
let output = starcoin_executor::execute_genesis_transaction(chain_state, txn)?
.txn_infos
.pop()
.expect("Execute output must exist.");
let (write_set, events, gas_used, status, _) = output.into_inner();
assert_eq!(gas_used, 0, "Genesis txn output's gas_used must be zero");
let keep_status = status
.status()
.map_err(|e| format_err!("Genesis txn is discard by: {:?}", e))?;
ensure!(
keep_status == KeptVMStatus::Executed,
"Genesis txn execute fail for: {:?}",
keep_status
);
chain_state.apply_write_set(write_set)?;
let state_root = chain_state.commit()?;
chain_state.flush()?;
Ok(TransactionInfo::new(
txn_hash,
state_root,
events.as_slice(),
gas_used,
keep_status,
))

Ok(output)
}

pub fn block(&self) -> &Block {
Expand Down
2 changes: 1 addition & 1 deletion vm/starcoin-transactional-test-harness/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1504,7 +1504,7 @@ pub fn print_help(task_name: Option<String>) -> Result<()> {
//TODO(simon): construct PackagePaths properly
pub static G_PRECOMPILED_STARCOIN_FRAMEWORK: Lazy<(FullyCompiledProgram, Vec<PackagePaths>)> =
Lazy::new(|| {
let sources = starcoin_framework::testnet_release_bundle()
let sources = starcoin_cached_packages::head_release_bundle()
.files()
.unwrap();
let package_paths = vec![PackagePaths {
Expand Down
3 changes: 2 additions & 1 deletion vm/vm-runtime/tests/test_native_functions.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,11 @@ use starcoin_gas_schedule::LATEST_GAS_FEATURE_VERSION;
use starcoin_vm_types::access::ModuleAccess;
use starcoin_vm_types::normalized::Function;
use std::collections::{HashMap, HashSet};
use stdlib::StdLibOptions;

#[test]
pub fn test_native_function_matches() -> Result<()> {
let modules = starcoin_framework::testnet_release_bundle().compiled_modules();
let modules = stdlib::stdlib_compiled_modules(StdLibOptions::Fresh);
let runtime_metadata = modules
.iter()
.filter_map(|m| {
Expand Down
Loading