Skip to content
This repository has been archived by the owner on Nov 9, 2022. It is now read-only.

feat: remove verification for state_checkpoint_list #130

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
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
115 changes: 0 additions & 115 deletions c/validator_utils.h
Original file line number Diff line number Diff line change
Expand Up @@ -88,10 +88,6 @@ typedef struct gw_context_t {
/* sender's original nonce */
uint32_t original_sender_nonce;

/* tx check point */
uint8_t prev_tx_checkpoint[32];
uint8_t post_tx_checkpoint[32];

/* kv state */
smt_state_t kv_state;
smt_pair_t kv_pairs[GW_MAX_KV_PAIRS];
Expand Down Expand Up @@ -1011,59 +1007,6 @@ int _gw_verify_cbmt_tx_proof(mol_seg_t *proof_seg, mol_seg_t *root_seg,
return memcmp(root_seg->ptr, leaf_hash, 32);
}

/*
* Load transaction checkpoints
*/
int _load_tx_checkpoint(mol_seg_t *raw_l2block_seg, uint32_t tx_index,
uint8_t prev_tx_checkpoint[32],
uint8_t post_tx_checkpoint[32]) {
mol_seg_t submit_withdrawals_seg =
MolReader_RawL2Block_get_submit_withdrawals(raw_l2block_seg);
mol_seg_t withdrawals_count_seg =
MolReader_SubmitWithdrawals_get_withdrawal_count(&submit_withdrawals_seg);
uint32_t withdrawals_count = 0;
_gw_fast_memcpy((uint8_t *)(&withdrawals_count), withdrawals_count_seg.ptr,
sizeof(uint32_t));

mol_seg_t checkpoint_list_seg =
MolReader_RawL2Block_get_state_checkpoint_list(raw_l2block_seg);

// load prev tx checkpoint
if (0 == tx_index) {
mol_seg_t submit_txs_seg =
MolReader_RawL2Block_get_submit_transactions(raw_l2block_seg);
mol_seg_t prev_state_checkpoint_seg =
MolReader_SubmitTransactions_get_prev_state_checkpoint(&submit_txs_seg);
if (32 != prev_state_checkpoint_seg.size) {
printf("invalid prev state checkpoint");
return GW_FATAL_INVALID_DATA;
}
_gw_fast_memcpy(prev_tx_checkpoint, prev_state_checkpoint_seg.ptr, 32);
} else {
uint32_t prev_tx_checkpoint_index = withdrawals_count + tx_index - 1;

mol_seg_res_t checkpoint_res =
MolReader_Byte32Vec_get(&checkpoint_list_seg, prev_tx_checkpoint_index);
if (MOL_OK != checkpoint_res.errno || 32 != checkpoint_res.seg.size) {
printf("invalid prev tx checkpoint");
return GW_FATAL_INVALID_DATA;
}
_gw_fast_memcpy(prev_tx_checkpoint, checkpoint_res.seg.ptr, 32);
}

// load post tx checkpoint
uint32_t post_tx_checkpoint_index = withdrawals_count + tx_index;

mol_seg_res_t checkpoint_res =
MolReader_Byte32Vec_get(&checkpoint_list_seg, post_tx_checkpoint_index);
if (MOL_OK != checkpoint_res.errno || 32 != checkpoint_res.seg.size) {
printf("invalid post tx checkpoint");
return GW_FATAL_INVALID_DATA;
}
_gw_fast_memcpy(post_tx_checkpoint, checkpoint_res.seg.ptr, 32);
return 0;
}

/* Load verify transaction witness
*/
int _load_verify_transaction_witness(uint8_t rollup_script_hash[32],
Expand Down Expand Up @@ -1260,13 +1203,6 @@ int _load_verify_transaction_witness(uint8_t rollup_script_hash[32],
kv_state_proof_bytes_seg.size);
ctx->kv_state_proof_size = kv_state_proof_bytes_seg.size;

/* load tx checkpoint */
ret = _load_tx_checkpoint(&raw_l2block_seg, tx_index, ctx->prev_tx_checkpoint,
ctx->post_tx_checkpoint);
if (ret != 0) {
return ret;
}

mol_seg_t account_count_seg =
MolReader_CCTransactionWitness_get_account_count(&cc_tx_witness_seg);
_gw_fast_memcpy((uint8_t *)(&ctx->account_count), account_count_seg.ptr,
Expand Down Expand Up @@ -1537,43 +1473,6 @@ int _check_owner_lock_hash() {
return GW_ERROR_NOT_FOUND;
}

int _gw_calculate_state_checkpoint(uint8_t buffer[32], const smt_state_t *state,
const uint8_t *proof, uint32_t proof_length,
uint32_t account_count) {
uint8_t root[32];
int ret = smt_calculate_root(root, state, proof, proof_length);
if (0 != ret) {
printf(
"_gw_calculate_state_check_point: failed to calculate kv state "
"root ret: %d",
ret);
return GW_FATAL_SMT_CALCULATE_ROOT;
}

blake2b_state blake2b_ctx;
blake2b_init(&blake2b_ctx, 32);
blake2b_update(&blake2b_ctx, root, 32);
blake2b_update(&blake2b_ctx, &account_count, sizeof(uint32_t));
blake2b_final(&blake2b_ctx, buffer, 32);

return 0;
}

int _gw_verify_checkpoint(const uint8_t checkpoint[32],
const smt_state_t *state, const uint8_t *proof,
uint32_t proof_length, uint32_t account_count) {
uint8_t proof_checkpoint[32];
int ret = _gw_calculate_state_checkpoint(proof_checkpoint, state, proof,
proof_length, account_count);
if (0 != ret) {
return ret;
}
if (0 != memcmp(proof_checkpoint, checkpoint, 32)) {
return GW_FATAL_INVALID_CHECK_POINT;
}
return 0;
}

int gw_context_init(gw_context_t *ctx) {
/* check owner lock */
int ret = _check_owner_lock_hash();
Expand Down Expand Up @@ -1650,13 +1549,6 @@ int gw_context_init(gw_context_t *ctx) {

/* verify kv_state merkle proof */
smt_state_normalize(&ctx->kv_state);
ret = _gw_verify_checkpoint(ctx->prev_tx_checkpoint, &ctx->kv_state,
ctx->kv_state_proof, ctx->kv_state_proof_size,
ctx->account_count);
if (ret != 0) {
printf("failed to merkle verify prev tx checkpoint");
return ret;
}

/* init original sender nonce */
ret = _load_sender_nonce(ctx, &ctx->original_sender_nonce);
Expand Down Expand Up @@ -1688,13 +1580,6 @@ int gw_finalize(gw_context_t *ctx) {
}

smt_state_normalize(&ctx->kv_state);
ret = _gw_verify_checkpoint(ctx->post_tx_checkpoint, &ctx->kv_state,
ctx->kv_state_proof, ctx->kv_state_proof_size,
ctx->account_count);
if (ret != 0) {
printf("failed to merkle verify post tx checkpoint");
return ret;
}
return 0;
}

Expand Down
33 changes: 1 addition & 32 deletions contracts/challenge-lock/src/verifications/context.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
use core::result::Result;
use gw_common::{
builtins::ETH_REGISTRY_ACCOUNT_ID, merkle_utils::calculate_state_checkpoint,
registry_address::RegistryAddress, state::State, H256,
builtins::ETH_REGISTRY_ACCOUNT_ID, registry_address::RegistryAddress, state::State, H256,
};
use gw_state::kv_state::KVState;
use gw_types::{
Expand Down Expand Up @@ -137,36 +136,6 @@ pub fn verify_tx_context(input: TxContextInput) -> Result<TxContext, Error> {
return Err(Error::MerkleProof);
}

// verify kv-state merkle proof (prev state root)
let prev_state_checkpoint: H256 = match tx_index.checked_sub(1) {
Some(tx_prev_state_checkpoint_index) => {
// skip withdrawal state checkpoints
let offset: u32 = raw_block.submit_withdrawals().withdrawal_count().unpack();
raw_block
.state_checkpoint_list()
.get((offset + tx_prev_state_checkpoint_index) as usize)
.ok_or(Error::InvalidStateCheckpoint)?
.unpack()
}
None => raw_block
.submit_transactions()
.prev_state_checkpoint()
.unpack(),
};
let state_root = kv_state.calculate_root().map_err(|_err| {
debug!("verify_tx_context, calculate merkle root error: {:?}", _err);
Error::MerkleProof
})?;
let account_count = kv_state.get_account_count()?;
let calculated_state_checkpoint: H256 = calculate_state_checkpoint(&state_root, account_count);
if prev_state_checkpoint != calculated_state_checkpoint {
debug!(
"TxContext mismatch prev_state_checkpoint: {:?}, calculated_state_checkpoint: {:?}",
prev_state_checkpoint, calculated_state_checkpoint
);
return Err(Error::MerkleProof);
}

let sender_address = kv_state
.get_registry_address_by_script_hash(ETH_REGISTRY_ACCOUNT_ID, &sender_script_hash)?
.ok_or(Error::RegistryAddressNotFound)?;
Expand Down
2 changes: 1 addition & 1 deletion contracts/gw-utils/src/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ pub enum Error {
InsufficientInputFinalizedAssets,
InsufficientOutputFinalizedAssets,
SMTKeyMissing,
InvalidStateCheckpoint,
_InvalidStateCheckpoint, // deprecated
InvalidBlock,
InvalidStatus,
InvalidStakeCellUnlock,
Expand Down
87 changes: 4 additions & 83 deletions contracts/state-validator/src/verifications/submit_block.rs
Original file line number Diff line number Diff line change
Expand Up @@ -36,14 +36,14 @@ use gw_common::{
builtins::CKB_SUDT_ACCOUNT_ID,
error::Error as StateError,
h256_ext::H256Ext,
merkle_utils::{calculate_ckb_merkle_root, calculate_state_checkpoint, ckb_merkle_leaf_hash},
merkle_utils::{calculate_ckb_merkle_root, ckb_merkle_leaf_hash},
state::State,
CKB_SUDT_SCRIPT_ARGS, H256,
};
use gw_types::{
bytes::Bytes,
core::{ScriptHashType, Status},
packed::{Byte32, GlobalState, RawL2Block, RollupConfig},
packed::{GlobalState, RawL2Block, RollupConfig},
prelude::*,
};

Expand Down Expand Up @@ -530,53 +530,7 @@ fn verify_block_producer(
Ok(())
}

fn check_state_checkpoints(block: &L2BlockReader) -> Result<(), Error> {
let raw_block = block.raw();
let checkpoint_list = raw_block.state_checkpoint_list();

let transactions = block.transactions();
let withdrawals = block.withdrawals();

if checkpoint_list.len() != withdrawals.len() + transactions.len() {
debug!(
"Wrong checkpoint length, checkpoints_list: {}, withdrawals: {} transactions: {}",
checkpoint_list.len(),
withdrawals.len(),
transactions.len()
);
return Err(Error::InvalidStateCheckpoint);
}

// check post state
let last_state_checkpoint = if transactions.is_empty() {
raw_block.submit_transactions().prev_state_checkpoint()
} else {
// return last transaction state checkpoint
checkpoint_list
.iter()
.last()
.ok_or(Error::InvalidStateCheckpoint)?
};
let block_state_checkpoint: Byte32 = {
let post_account_state = raw_block.post_account();
calculate_state_checkpoint(
&post_account_state.merkle_root().unpack(),
post_account_state.count().unpack(),
)
.pack()
};
if last_state_checkpoint.as_slice() != block_state_checkpoint.as_slice() {
debug!(
"Mismatch last_state_checkpoint: {:?}, block_state_checkpoint: {:?}",
last_state_checkpoint, block_state_checkpoint
);
return Err(Error::InvalidStateCheckpoint);
}

Ok(())
}

fn check_block_transactions(block: &L2BlockReader, kv_state: &KVState) -> Result<(), Error> {
fn check_block_transactions(block: &L2BlockReader) -> Result<(), Error> {
// check tx_witness_root
let raw_block = block.raw();

Expand Down Expand Up @@ -605,36 +559,6 @@ fn check_block_transactions(block: &L2BlockReader, kv_state: &KVState) -> Result
return Err(Error::MerkleProof);
}

// check current account tree state
let prev_state_checkpoint: H256 = submit_transactions.prev_state_checkpoint().unpack();
if kv_state.calculate_state_checkpoint()? != prev_state_checkpoint {
debug!("submit_transactions.prev_state_checkpoint isn't equals to the state checkpoint calculated from context");
return Err(Error::InvalidStateCheckpoint);
}

// check post account tree state
let last_checkpoint_root = if block.transactions().is_empty() {
prev_state_checkpoint
} else {
raw_block
.state_checkpoint_list()
.iter()
.last()
.map(|checkpoint| checkpoint.unpack())
.ok_or(Error::InvalidStateCheckpoint)?
};
let block_post_state_root = {
let account = raw_block.post_account();
calculate_state_checkpoint(&account.merkle_root().unpack(), account.count().unpack())
};
if last_checkpoint_root != block_post_state_root {
debug!(
"Invalid post state, last_checkpoint_root: {:?}, block_post_state_root: {:?}",
last_checkpoint_root, block_post_state_root
);
return Err(Error::InvalidStateCheckpoint);
}

Ok(())
}

Expand Down Expand Up @@ -738,9 +662,6 @@ pub fn verify(
) -> Result<(), Error> {
check_status(prev_global_state, Status::Running)?;

// check checkpoints
check_state_checkpoints(block)?;

// Check withdrawals root
check_block_withdrawals(block)?;

Expand Down Expand Up @@ -786,7 +707,7 @@ pub fn verify(
// Mint token: deposit requests -> layer2 SUDT
check_layer2_deposit(&rollup_type_hash, config, &mut kv_state, &deposit_cells)?;
// Check transactions
check_block_transactions(block, &kv_state)?;
check_block_transactions(block)?;

// Verify Post state
let actual_post_global_state = {
Expand Down