diff --git a/miner/worker.go b/miner/worker.go index ed2324369a5b..2ec03305e360 100644 --- a/miner/worker.go +++ b/miner/worker.go @@ -1145,6 +1145,7 @@ loop: // However, after `ErrUnknown`, ccc might remain in an // inconsistent state, so we cannot pack more transactions. circuitCapacityReached = true + w.checkCurrentTxNumWithCCC(w.current.tcount) break loop case (errors.Is(err, circuitcapacitychecker.ErrUnknown) && !tx.IsL1MessageTx()): @@ -1164,6 +1165,7 @@ loop: // inconsistent state, so we cannot pack more transactions. w.eth.TxPool().RemoveTx(tx.Hash(), true) circuitCapacityReached = true + w.checkCurrentTxNumWithCCC(w.current.tcount) break loop default: @@ -1208,6 +1210,17 @@ loop: return false, circuitCapacityReached } +func (w *worker) checkCurrentTxNumWithCCC(expected int) { + match, got, err := w.circuitCapacityChecker.CheckTxNum(expected) + if err != nil { + log.Error("failed to CheckTxNum in ccc", "err", err) + return + } + if !match { + log.Error("tx count in miner is different with CCC", "w.current.tcount", w.current.tcount, "got", got) + } +} + func (w *worker) collectPendingL1Messages(startIndex uint64) []types.L1MessageTx { maxCount := w.chainConfig.Scroll.L1Config.NumL1MessagesPerBlock return rawdb.ReadL1MessagesFrom(w.eth.ChainDb(), startIndex, maxCount) diff --git a/params/version.go b/params/version.go index 0e507994badc..5c9d96b77f5b 100644 --- a/params/version.go +++ b/params/version.go @@ -24,7 +24,7 @@ import ( const ( VersionMajor = 4 // Major version component of the current release VersionMinor = 4 // Minor version component of the current release - VersionPatch = 2 // Patch version component of the current release + VersionPatch = 3 // Patch version component of the current release VersionMeta = "sepolia" // Version metadata to append to the version string ) diff --git a/rollup/circuitcapacitychecker/impl.go b/rollup/circuitcapacitychecker/impl.go index 081d70a4bb3d..55aab9e0fdc4 100644 --- a/rollup/circuitcapacitychecker/impl.go +++ b/rollup/circuitcapacitychecker/impl.go @@ -31,6 +31,7 @@ type CircuitCapacityChecker struct { ID uint64 } +// NewCircuitCapacityChecker creates a new CircuitCapacityChecker func NewCircuitCapacityChecker() *CircuitCapacityChecker { creationMu.Lock() defer creationMu.Unlock() @@ -39,6 +40,7 @@ func NewCircuitCapacityChecker() *CircuitCapacityChecker { return &CircuitCapacityChecker{ID: uint64(id)} } +// Reset resets a CircuitCapacityChecker func (ccc *CircuitCapacityChecker) Reset() { ccc.Lock() defer ccc.Unlock() @@ -46,6 +48,7 @@ func (ccc *CircuitCapacityChecker) Reset() { C.reset_circuit_capacity_checker(C.uint64_t(ccc.ID)) } +// ApplyTransaction appends a tx's wrapped BlockTrace into the ccc, and return the accumulated RowConsumption func (ccc *CircuitCapacityChecker) ApplyTransaction(traces *types.BlockTrace) (*types.RowConsumption, error) { ccc.Lock() defer ccc.Unlock() @@ -100,6 +103,7 @@ func (ccc *CircuitCapacityChecker) ApplyTransaction(traces *types.BlockTrace) (* return (*types.RowConsumption)(&result.AccRowUsage.RowUsageDetails), nil } +// ApplyBlock gets a block's RowConsumption func (ccc *CircuitCapacityChecker) ApplyBlock(traces *types.BlockTrace) (*types.RowConsumption, error) { ccc.Lock() defer ccc.Unlock() @@ -141,3 +145,28 @@ func (ccc *CircuitCapacityChecker) ApplyBlock(traces *types.BlockTrace) (*types. } return (*types.RowConsumption)(&result.AccRowUsage.RowUsageDetails), nil } + +// CheckTxNum compares whether the tx_count in ccc match the expected +func (ccc *CircuitCapacityChecker) CheckTxNum(expected int) (bool, unit64, error) { + ccc.Lock() + defer ccc.Unlock() + + log.Debug("ccc get_tx_num start", "id", ccc.ID) + rawResult := C.get_tx_num(C.uint64_t(ccc.ID)) + defer func() { + C.free(unsafe.Pointer(rawResult)) + }() + log.Debug("ccc get_tx_num end", "id", ccc.ID) + + result := &WrappedTxNum{} + if err = json.Unmarshal([]byte(C.GoString(rawResult)), result); err != nil { + log.Error("fail to json unmarshal get_tx_num result", "id", ccc.ID, "err", err) + return false, 0, ErrUnknown + } + if result.Error != "" { + log.Error("fail to get_tx_num in CircuitCapacityChecker", "id", ccc.ID, "err", result.Error) + return false, 0, ErrUnknown + } + + return result.TxNum == unit64(expected), result.TxNum, nil +} diff --git a/rollup/circuitcapacitychecker/libzkp/libzkp.h b/rollup/circuitcapacitychecker/libzkp/libzkp.h index 524c1ec2eb24..59213a0cee8b 100644 --- a/rollup/circuitcapacitychecker/libzkp/libzkp.h +++ b/rollup/circuitcapacitychecker/libzkp/libzkp.h @@ -4,3 +4,4 @@ uint64_t new_circuit_capacity_checker(); void reset_circuit_capacity_checker(uint64_t id); char* apply_tx(uint64_t id, char *tx_traces); char* apply_block(uint64_t id, char *block_trace); +char* get_tx_num(uint64_t id); diff --git a/rollup/circuitcapacitychecker/libzkp/src/lib.rs b/rollup/circuitcapacitychecker/libzkp/src/lib.rs index 14ea2cb6bd32..28a154bb76c8 100644 --- a/rollup/circuitcapacitychecker/libzkp/src/lib.rs +++ b/rollup/circuitcapacitychecker/libzkp/src/lib.rs @@ -20,6 +20,12 @@ pub mod checker { pub error: Option, } + #[derive(Debug, Clone, Deserialize, Serialize)] + pub struct TxNumResult { + pub tx_num: u64, + pub error: Option, + } + static mut CHECKERS: OnceCell> = OnceCell::new(); /// # Safety @@ -176,6 +182,50 @@ pub mod checker { } } } + + /// # Safety + #[no_mangle] + pub unsafe extern "C" fn get_tx_num(id: u64) -> *const c_char { + let result = get_tx_num_inner(id); + let r = match result { + Ok(tx_num) => { + log::debug!("id: {id}, tx_num: {tx_num}"); + TxNumResult { + tx_num, + error: None, + } + } + Err(e) => TxNumResult { + tx_num: 0, + error: Some(format!("{e:?}")), + }, + }; + serde_json::to_vec(&r).map_or(null(), vec_to_c_char) + } + + unsafe fn get_tx_num_inner(id: u64) -> Result { + log::debug!("ccc get_tx_num raw input, id: {id}"); + panic::catch_unwind(|| { + Ok(CHECKERS + .get_mut() + .ok_or(anyhow!( + "fail to get circuit capacity checkers map in get_tx_num" + ))? + .get_mut(&id) + .ok_or(anyhow!( + "fail to get circuit capacity checker (id: {id}) in get_tx_num" + ))? + .get_tx_num() as u64) + }) + .map_or_else( + |e| { + Err(anyhow!( + "circuit capacity checker (id: {id}) error in get_tx_num: {e:?}" + )) + }, + |result| result, + ) + } } pub(crate) mod utils { diff --git a/rollup/circuitcapacitychecker/mock.go b/rollup/circuitcapacitychecker/mock.go index 90e3430852af..6ec15dece2c3 100644 --- a/rollup/circuitcapacitychecker/mock.go +++ b/rollup/circuitcapacitychecker/mock.go @@ -14,13 +14,17 @@ type CircuitCapacityChecker struct { nextError *error } +// NewCircuitCapacityChecker creates a new CircuitCapacityChecker func NewCircuitCapacityChecker() *CircuitCapacityChecker { return &CircuitCapacityChecker{ID: rand.Uint64()} } +// Reset resets a ccc, but need to do nothing in mock_ccc. func (ccc *CircuitCapacityChecker) Reset() { } +// ApplyTransaction appends a tx's wrapped BlockTrace into the ccc, and return the accumulated RowConsumption. +// Will only return a dummy value in mock_ccc. func (ccc *CircuitCapacityChecker) ApplyTransaction(traces *types.BlockTrace) (*types.RowConsumption, error) { if ccc.nextError != nil { ccc.countdown-- @@ -36,6 +40,8 @@ func (ccc *CircuitCapacityChecker) ApplyTransaction(traces *types.BlockTrace) (* }}, nil } +// ApplyBlock gets a block's RowConsumption. +// Will only return a dummy value in mock_ccc. func (ccc *CircuitCapacityChecker) ApplyBlock(traces *types.BlockTrace) (*types.RowConsumption, error) { return &types.RowConsumption{types.SubCircuitRowUsage{ Name: "mock", @@ -43,6 +49,13 @@ func (ccc *CircuitCapacityChecker) ApplyBlock(traces *types.BlockTrace) (*types. }}, nil } +// CheckTxNum compares whether the tx_count in ccc match the expected. +// Will alway return true in mock_ccc. +func (ccc *CircuitCapacityChecker) CheckTxNum(expected int) (bool, uint64, error) { + return true, uint64(expected), nil +} + +// ScheduleError schedules an error for a tx (see `ApplyTransaction`), only used in tests. func (ccc *CircuitCapacityChecker) ScheduleError(cnt int, err error) { ccc.countdown = cnt ccc.nextError = &err diff --git a/rollup/circuitcapacitychecker/types.go b/rollup/circuitcapacitychecker/types.go index f57152745465..0cf75cf70224 100644 --- a/rollup/circuitcapacitychecker/types.go +++ b/rollup/circuitcapacitychecker/types.go @@ -15,3 +15,8 @@ type WrappedRowUsage struct { AccRowUsage *types.RowUsage `json:"acc_row_usage,omitempty"` Error string `json:"error,omitempty"` } + +type WrappedTxNum struct { + TxNum uint64 `json:"tx_num"` + Error string `json:"error,omitempty"` +}