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

Support revert inner state and add syscalls #835

Merged
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
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.

15 changes: 8 additions & 7 deletions crates/benches/benches/benchmarks/fee_queue.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,9 @@ use gw_mem_pool::fee::{
types::{FeeEntry, FeeItem, FeeItemSender},
};
use gw_store::{
mem_pool_state::MemStore, state::state_db::StateContext, traits::chain_store::ChainStore, Store,
state::{history::history_state::RWConfig, BlockStateDB, MemStateDB},
traits::chain_store::ChainStore,
Store,
};
use gw_types::{
bytes::Bytes,
Expand All @@ -23,10 +25,10 @@ fn bench_add_full(b: &mut Bencher) {
let store = Store::open_tmp().expect("open store");
setup_genesis(&store);
{
let db = store.begin_transaction();
let db = &store.begin_transaction();
let genesis = db.get_tip_block().expect("tip");
assert_eq!(genesis.raw().number().unpack(), 0);
let mut state = db.state_tree(StateContext::AttachBlock(1)).expect("state");
let mut state = BlockStateDB::from_store(db, RWConfig::attach_block(1)).unwrap();

// create accounts
for i in 0..4 {
Expand Down Expand Up @@ -79,10 +81,10 @@ fn bench_add_fetch_20(b: &mut Bencher) {
let store = Store::open_tmp().expect("open store");
setup_genesis(&store);
{
let db = store.begin_transaction();
let db = &store.begin_transaction();
let genesis = db.get_tip_block().expect("tip");
assert_eq!(genesis.raw().number().unpack(), 0);
let mut state = db.state_tree(StateContext::AttachBlock(1)).expect("state");
let mut state = BlockStateDB::from_store(db, RWConfig::attach_block(1)).unwrap();

// create accounts
for i in 0..4 {
Expand All @@ -108,8 +110,7 @@ fn bench_add_fetch_20(b: &mut Bencher) {
queue.add(entry1, ());
}

let mem_store = MemStore::new(snap);
let tree = mem_store.state().unwrap();
let tree = MemStateDB::from_store(snap).unwrap();

b.iter(|| {
for i in 0..20 {
Expand Down
39 changes: 23 additions & 16 deletions crates/benches/benches/benchmarks/smt.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
use std::sync::Arc;

use criterion::{criterion_group, BenchmarkId, Criterion, Throughput};
use gw_common::{
blake2b::new_blake2b,
Expand All @@ -19,8 +17,13 @@ use gw_generator::{
Generator,
};
use gw_store::{
mem_pool_state::{MemPoolState, MemStore},
state::state_db::{StateContext, StateTree},
mem_pool_state::MemPoolState,
state::{
history::history_state::{HistoryState, RWConfig},
state_db::StateDB,
traits::JournalDB,
MemStateDB,
},
traits::chain_store::ChainStore,
Store,
};
Expand Down Expand Up @@ -182,7 +185,10 @@ impl BenchExecutionEnvironment {
);

Self::init_genesis(&store, &genesis_config, accounts);
let mem_pool_state = MemPoolState::new(Arc::new(MemStore::new(store.get_snapshot())), true);
let mem_pool_state = MemPoolState::new(
MemStateDB::from_store(store.get_snapshot()).expect("mem state db"),
true,
);

BenchExecutionEnvironment {
generator,
Expand All @@ -192,8 +198,7 @@ impl BenchExecutionEnvironment {
}

fn accounts_transfer(&self, accounts: u32, count: usize) {
let snap = self.mem_pool_state.load();
let mut state = snap.state().unwrap();
let mut state = self.mem_pool_state.load_state_db();

let (block_producer_script, block_producer) = Account::build_script(0);
let block_info = BlockInfo::new_builder()
Expand Down Expand Up @@ -251,30 +256,28 @@ impl BenchExecutionEnvironment {
.args(args.as_bytes().pack())
.build();

let run_result = self
.generator
self.generator
.execute_transaction(
&self.chain,
&state,
&mut state,
&block_info,
&raw_tx,
L2TX_MAX_CYCLES,
None,
)
.unwrap();

state.apply_run_result(&run_result.write).unwrap();
state.finalise().unwrap();

from_id += 1;
if from_id > end_account_id {
from_id = start_account_id;
}
transfer_count -= 1;
}
self.mem_pool_state.store(snap.into());
self.mem_pool_state.store_state_db(state);

let snap = self.mem_pool_state.load();
let state = snap.state().unwrap();
let state = self.mem_pool_state.load_state_db();
let post_block_producer_balance = state
.get_sudt_balance(CKB_SUDT_ACCOUNT_ID, &block_producer)
.unwrap();
Expand Down Expand Up @@ -322,12 +325,16 @@ impl BenchExecutionEnvironment {
let (db, genesis_state) = build_genesis_from_store(db, config, Default::default()).unwrap();

let smt = db
.account_smt_with_merkle_state(genesis_state.genesis.raw().post_account())
.state_smt_with_merkle_state(genesis_state.genesis.raw().post_account())
.unwrap();
let account_count = genesis_state.genesis.raw().post_account().count().unpack();
let mut state = { StateTree::new(smt, account_count, StateContext::AttachBlock(0)) };
let mut state = {
let history_state = HistoryState::new(smt, account_count, RWConfig::attach_block(0));
StateDB::new(history_state)
};

Self::generate_accounts(&mut state, accounts + 1); // Plus block producer
state.finalise().unwrap();

let (genesis, global_state) = {
let prev_state_checkpoint: [u8; 32] =
Expand Down
32 changes: 24 additions & 8 deletions crates/benches/benches/benchmarks/sudt.rs
Original file line number Diff line number Diff line change
@@ -1,12 +1,22 @@
use criterion::*;
use gw_common::{
builtins::ETH_REGISTRY_ACCOUNT_ID, registry_address::RegistryAddress, state::State, H256,
builtins::ETH_REGISTRY_ACCOUNT_ID, registry_address::RegistryAddress, smt::SMT, state::State,
H256,
};
use gw_config::{BackendConfig, BackendSwitchConfig};
use gw_generator::{
account_lock_manage::AccountLockManage, backend_manage::BackendManage,
constants::L2TX_MAX_CYCLES, dummy_state::DummyState, error::TransactionError, traits::StateExt,
Generator,
constants::L2TX_MAX_CYCLES, error::TransactionError, traits::StateExt, Generator,
};
use gw_store::{
smt::smt_store::SMTStateStore,
snapshot::StoreSnapshot,
state::{
overlay::{mem_state::MemStateTree, mem_store::MemStore},
traits::JournalDB,
MemStateDB,
},
Store,
};
use gw_traits::{ChainView, CodeStore};
use gw_types::{
Expand Down Expand Up @@ -62,6 +72,12 @@ impl ChainView for DummyChainStore {
}
}

fn new_state(store: StoreSnapshot) -> MemStateDB {
let smt = SMT::new(H256::zero(), SMTStateStore::new(MemStore::new(store)));
let inner = MemStateTree::new(smt, 0);
MemStateDB::new(inner)
}

fn new_block_info(block_producer: &RegistryAddress, number: u64, timestamp: u64) -> BlockInfo {
BlockInfo::new_builder()
.block_producer(Bytes::from(block_producer.to_bytes()).pack())
Expand All @@ -70,7 +86,7 @@ fn new_block_info(block_producer: &RegistryAddress, number: u64, timestamp: u64)
.build()
}

fn run_contract_get_result<S: State + CodeStore>(
fn run_contract_get_result<S: State + CodeStore + JournalDB>(
rollup_config: &RollupConfig,
tree: &mut S,
from_id: u32,
Expand Down Expand Up @@ -104,12 +120,11 @@ fn run_contract_get_result<S: State + CodeStore>(
L2TX_MAX_CYCLES,
None,
)?;
tree.apply_run_result(&run_result.write)
.expect("update state");
tree.finalise()?;
Ok(run_result)
}

fn run_contract<S: State + CodeStore>(
fn run_contract<S: State + CodeStore + JournalDB>(
rollup_config: &RollupConfig,
tree: &mut S,
from_id: u32,
Expand All @@ -128,7 +143,8 @@ pub fn bench(c: &mut Criterion) {
group.bench_function("sudt", move |b| {
b.iter_batched(
|| {
let mut tree = DummyState::default();
let db = Store::open_tmp().unwrap();
let mut tree = new_state(db.get_snapshot());

let always_success_lock_hash = [255u8; 32];
let rollup_config = RollupConfig::new_builder()
Expand Down
4 changes: 2 additions & 2 deletions crates/block-producer/src/block_sync_client.rs
Original file line number Diff line number Diff line change
Expand Up @@ -326,12 +326,12 @@ async fn handle_local_block(
"received block {block_number} {}",
ckb_types::H256::from(block_hash),
);
let store_tx = client.store.begin_transaction();
let store_tx = &client.store.begin_transaction();
let store_block_hash = store_tx.get_block_hash_by_number(block_number)?;
if let Some(store_block_hash) = store_block_hash {
if store_block_hash != block_hash.into() {
log::info!("revert to {}", block_number - 1);
revert(client, &store_tx, block_number - 1).await?;
revert(client, store_tx, block_number - 1).await?;
store_tx.commit()?;
} else {
log::info!("block already known");
Expand Down
14 changes: 8 additions & 6 deletions crates/block-producer/src/produce_block.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,9 @@ use gw_common::{
use gw_generator::Generator;
use gw_mem_pool::mem_block::MemBlock;
use gw_store::{
state::state_db::StateContext, traits::chain_store::ChainStore, transaction::StoreTransaction,
state::{history::history_state::RWConfig, BlockStateDB},
traits::chain_store::ChainStore,
transaction::StoreTransaction,
Store,
};
use gw_types::{
Expand Down Expand Up @@ -184,15 +186,15 @@ pub fn generate_produce_block_param(
mem_block: MemBlock,
post_merkle_state: AccountMerkleState,
) -> Result<BlockParam> {
let db = store.begin_transaction();
let db = &store.begin_transaction();
let tip_block_number = mem_block.block_info().number().unpack().saturating_sub(1);
let tip_block_hash = {
let opt = db.get_block_hash_by_number(tip_block_number)?;
opt.ok_or_else(|| anyhow!("[produce block] tip block {} not found", tip_block_number))?
};

// generate kv state & merkle proof from tip state
let chain_state = db.state_tree(StateContext::ReadOnly)?;
let chain_state = BlockStateDB::from_store(db, RWConfig::readonly())?;

let kv_state: Vec<(H256, H256)> = mem_block
.touched_keys()
Expand All @@ -208,9 +210,9 @@ pub fn generate_produce_block_param(
// nothing need to prove
Vec::new()
} else {
let account_smt = db.account_smt()?;
let state_smt = db.state_smt()?;

account_smt
state_smt
.merkle_proof(kv_state.iter().map(|(k, _v)| *k).collect())
.map_err(|err| anyhow!("merkle proof error: {:?}", err))?
.compile(kv_state.clone())?
Expand Down Expand Up @@ -263,7 +265,7 @@ pub fn generate_produce_block_param(

// check smt root
let expected_kv_state_root: H256 = prev_merkle_state.merkle_root().unpack();
let smt = db.account_smt()?;
let smt = db.state_smt()?;
assert_eq!(
smt.root(),
&expected_kv_state_root,
Expand Down
16 changes: 8 additions & 8 deletions crates/block-producer/src/replay_block.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,8 @@ use gw_generator::constants::L2TX_MAX_CYCLES;
use gw_generator::traits::StateExt;
use gw_generator::Generator;
use gw_store::chain_view::ChainView;
use gw_store::mem_pool_state::MemStore;
use gw_store::state::traits::JournalDB;
use gw_store::state::MemStateDB;
use gw_store::traits::chain_store::ChainStore;
use gw_store::Store;
use gw_types::packed::{BlockInfo, DepositRequest, L2Block, RawL2Block, WithdrawalRequestExtra};
Expand All @@ -35,13 +36,12 @@ impl ReplayBlock {
.get_block(&parent_block_hash)?
.ok_or_else(|| anyhow!("replay parent block not found"))?;

let mem_store = MemStore::new(snap);
let mut state = mem_store.state()?;
let mut state = MemStateDB::from_store(snap)?;
{
let parent_post_state = parent_block.raw().post_account();
assert_eq!(
parent_post_state,
state.merkle_state()?,
state.calculate_merkle_state()?,
"merkle state should equals to parent block"
);
};
Expand Down Expand Up @@ -88,7 +88,7 @@ impl ReplayBlock {
}

// handle transactions
let db = store.begin_transaction();
let db = &store.begin_transaction();
let chain_view = ChainView::new(&db, parent_block_hash);
for (tx_index, tx) in block.transactions().into_iter().enumerate() {
generator.check_transaction_signature(&state, &tx)?;
Expand All @@ -108,16 +108,16 @@ impl ReplayBlock {

// build call context
// NOTICE users only allowed to send HandleMessage CallType txs
let run_result = generator.execute_transaction(
generator.execute_transaction(
&chain_view,
&state,
&mut state,
&block_info,
&raw_tx,
L2TX_MAX_CYCLES,
None,
)?;

state.apply_run_result(&run_result.write)?;
state.finalise()?;
let expected_checkpoint = state.calculate_state_checkpoint()?;
let checkpoint_index = withdrawals.len() + tx_index;
let block_checkpoint: H256 = match state_checkpoint_list.get(checkpoint_index) {
Expand Down
6 changes: 3 additions & 3 deletions crates/block-producer/src/sync_l1.rs
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ pub async fn sync_l1(ctx: &(dyn SyncL1Context + Sync + Send)) -> Result<()> {

async fn sync_l1_impl(ctx: &(dyn SyncL1Context + Sync + Send)) -> Result<()> {
log::info!("syncing with L1");
let store_tx = ctx.store().begin_transaction();
let store_tx = &ctx.store().begin_transaction();
let last_confirmed_local = store_tx
.get_last_confirmed_block_number_hash()
.context("get last confirmed")?;
Expand Down Expand Up @@ -86,7 +86,7 @@ async fn sync_l1_impl(ctx: &(dyn SyncL1Context + Sync + Send)) -> Result<()> {
// accidentally running two godwoken full nodes.
async fn sync_l1_unknown(
ctx: &(dyn SyncL1Context + Send + Sync),
store_tx: StoreTransaction,
store_tx: &StoreTransaction,
mut last_confirmed: u64,
) -> Result<()> {
log::info!("syncing unknown L2 blocks from L1");
Expand Down Expand Up @@ -150,7 +150,7 @@ async fn sync_l1_unknown(
}

log::info!("L2 fork detected, reverting to L2 block {last_confirmed}");
revert(ctx, &store_tx, last_confirmed).await?;
revert(ctx, store_tx, last_confirmed).await?;
// Commit transaction because chain_updater.update_single will open and commit new transactions.
store_tx.commit()?;
reverted = true;
Expand Down
2 changes: 1 addition & 1 deletion crates/block-producer/src/test_mode_control.rs
Original file line number Diff line number Diff line change
Expand Up @@ -251,7 +251,7 @@ impl TestModeControl {
(block_number, target_index, target_type)
};

let db = self.store.begin_transaction();
let db = &self.store.begin_transaction();
let block_hash = db.get_block_hash_by_number(block_number)?;
let block =
db.get_block(&block_hash.ok_or_else(|| anyhow!("block {} not found", block_number))?)?;
Expand Down
Loading