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

executor v3 #3517

Merged
merged 4 commits into from
Apr 17, 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
26 changes: 1 addition & 25 deletions event/eventlog.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ func (e *EventLog) LogEvent(ctx context.Context, event *Event) error {
}

// LogExecutorError is used to store Executor error for runtime debugging
func (e *EventLog) LogExecutorError(ctx context.Context, responseError executor.ExecutorError, processBatchRequest *executor.ProcessBatchRequest) {
func (e *EventLog) LogExecutorError(ctx context.Context, responseError executor.ExecutorError, processBatchRequest interface{}) {
timestamp := time.Now()

// if it's a user related error, ignore it
Expand Down Expand Up @@ -64,27 +64,3 @@ func (e *EventLog) LogExecutorError(ctx context.Context, responseError executor.
}
}
}

// LogExecutorErrorV2 is used to store Executor error for runtime debugging
func (e *EventLog) LogExecutorErrorV2(ctx context.Context, responseError executor.ExecutorError, processBatchRequest *executor.ProcessBatchRequestV2) {
timestamp := time.Now()
log.Errorf("error found in the executor: %v at %v", responseError, timestamp)
payload, err := json.Marshal(processBatchRequest)
if err != nil {
log.Errorf("error marshaling payload: %v", err)
} else {
event := &Event{
ReceivedAt: timestamp,
Source: Source_Node,
Component: Component_Executor,
Level: Level_Error,
EventID: EventID_ExecutorError,
Description: responseError.String(),
Json: string(payload),
}
err = e.storage.LogEvent(ctx, event)
if err != nil {
log.Errorf("error storing event: %v", err)
}
}
}
234 changes: 233 additions & 1 deletion proto/src/proto/executor/v1/executor.proto
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,9 @@ service ExecutorService {
/// Processes a batch
rpc ProcessBatch(ProcessBatchRequest) returns (ProcessBatchResponse) {}
rpc ProcessBatchV2(ProcessBatchRequestV2) returns (ProcessBatchResponseV2) {}
rpc ProcessBatchV3(ProcessBatchRequestV3) returns (ProcessBatchResponseV3) {}
rpc ProcessBlobInnerV3(ProcessBlobInnerRequestV3) returns (ProcessBlobInnerResponseV3) {}
rpc ProcessStatelessBatchV2(ProcessStatelessBatchRequestV2) returns (ProcessBatchResponseV2) {}
rpc GetFlushStatus (google.protobuf.Empty) returns (GetFlushStatusResponse) {}
}

Expand Down Expand Up @@ -294,6 +297,24 @@ message ProcessBatchRequestV2 {
DebugV2 debug = 24;
}

message ProcessStatelessBatchRequestV2 {
// Batch data
bytes witness = 1; // SMT partial tree, SCs, (indirectly) old state root
bytes data_stream = 2; // txs, old batch num, chain id, fork id, effective gas price, block header, index of L1 info tree (global exit root, min timestamp, ...)

string coinbase = 3; // sequencer address
bytes old_acc_input_hash = 4; // 0 for executor, required for the prover

// Used by injected/first batches (do not use it for regular batches)
bytes l1_info_root = 5; // 0 for executor, required for the prover
uint64 timestamp_limit = 6; // if 0, replace by now + 10 min internally
bytes forced_blockhash_l1 = 7; // we need it, 0 in regular batches, hash in forced batches, also used in injected/first batches, 0 by now

// Debug
string context_id = 8; // batch ID to be shown in the executor traces, for your convenience: "Erigon_candidate_batch_N"
TraceConfigV2 trace_config = 9;
}

message L1DataV2 {
bytes global_exit_root = 1;
bytes block_hash_l1 = 2;
Expand All @@ -303,7 +324,7 @@ message L1DataV2 {

message DebugV2 {
uint64 gas_limit = 1;
bytes new_state_root = 2;
bytes new_state_root = 2;
bytes new_acc_input_hash = 3;
bytes new_local_exit_root = 4;
uint64 new_batch_num = 5;
Expand Down Expand Up @@ -342,6 +363,12 @@ message ProcessBatchResponseV2 {
uint32 cnt_reserve_binaries = 30;
uint32 cnt_reserve_steps = 31;
uint32 cnt_reserve_sha256_hashes = 32;
bytes old_state_root = 33;
ResponseDebug debug = 34;
}

message ResponseDebug {
string error_log = 1;
}

// Trace configuration request params
Expand Down Expand Up @@ -382,6 +409,12 @@ message InfoReadWriteV2 {
string nonce = 1;
// If balance="" then it has not been set; if set, string is in decimal (base 10)
string balance = 2;
// If sc_code="" then it has not been set; if set, string is in hexa (base 16)
string sc_code = 3;
// Both sc_storage first (key) and second (value) map elements are set in hexa (base 16)
map<string, string> sc_storage = 4;
// If sc_length="" then it has not been set; if set, string is in decimal (base 10)
string sc_length = 5;
}

message FullTraceV2 {
Expand Down Expand Up @@ -635,6 +668,8 @@ enum RomError {
ROM_ERROR_INVALID_TX_CHANGE_L2_BLOCK_LIMIT_TIMESTAMP = 33;
// ROM_ERROR_INVALID_TX_CHANGE_L2_BLOCK_MIN_TIMESTAMP indicates that the change l2 block transaction has trigger an error during while executing
ROM_ERROR_INVALID_TX_CHANGE_L2_BLOCK_MIN_TIMESTAMP = 34;
// ROM_ERROR_INVALID_L1_INFO_TREE_INDEX indicates that the l1 info tree index added is not valid since its value is 0
ROM_ERROR_INVALID_L1_INFO_TREE_INDEX = 35;
}

enum ExecutorError {
Expand Down Expand Up @@ -874,4 +909,201 @@ enum ExecutorError {
EXECUTOR_ERROR_INVALID_UPDATE_MERKLE_TREE = 116;
// EXECUTOR_ERROR_SM_MAIN_INVALID_TX_STATUS_ERROR indicates that a TX has an invalid status-error combination
EXECUTOR_ERROR_SM_MAIN_INVALID_TX_STATUS_ERROR = 117;
// EXECUTOR_ERROR_INVALID_PREVIOUS_L1_INFO_TREE_ROOT indicates that the input parameter previous_l1_info_tree_root is invalid
EXECUTOR_ERROR_INVALID_PREVIOUS_L1_INFO_TREE_ROOT = 118;
// EXECUTOR_ERROR_INVALID_FORCED_HASH_DATA indicates that the input parameter forced_hash_data is invalid
EXECUTOR_ERROR_INVALID_FORCED_HASH_DATA = 119;
// EXECUTOR_ERROR_INVALID_FORCED_DATA_GLOBAL_EXIT_ROOT indicates that the input parameter forced_data.global_exit_root is invalid
EXECUTOR_ERROR_INVALID_FORCED_DATA_GLOBAL_EXIT_ROOT = 120;
// EXECUTOR_ERROR_INVALID_FORCED_DATA_BLOCK_HASH_L1 indicates that the input parameter forced_data.block_hash_l1 is invalid
EXECUTOR_ERROR_INVALID_FORCED_DATA_BLOCK_HASH_L1 = 121;
// EXECUTOR_ERROR_INVALID_L1_DATA_V3_INITIAL_HISTORIC_ROOT indicates that the input parameter L1 Data initiali_historic_root is invalid
EXECUTOR_ERROR_INVALID_L1_DATA_V3_INITIAL_HISTORIC_ROOT = 122;
// EXECUTOR_ERROR_INVALID_OLD_BLOB_STATE_ROOT indicates that the input parameter old_blob_state_root is invalid
EXECUTOR_ERROR_INVALID_OLD_BLOB_STATE_ROOT = 123;
// EXECUTOR_ERROR_INVALID_OLD_BLOB_ACC_INPUT_HASH indicates that the input parameter old_blob_acc_input_hash is invalid
EXECUTOR_ERROR_INVALID_OLD_BLOB_ACC_INPUT_HASH = 124;
// EXECUTOR_ERROR_INVALID_LAST_L1_INFO_TREE_ROOT indicates that the input parameter last_l1_info_tree_root is invalid
EXECUTOR_ERROR_INVALID_LAST_L1_INFO_TREE_ROOT = 125;
// EXECUTOR_ERROR_INVALID_NEW_BLOB_STATE_ROOT indicates that the input parameter new_blob_state_root is invalid
EXECUTOR_ERROR_INVALID_NEW_BLOB_STATE_ROOT = 126;
// EXECUTOR_ERROR_INVALID_NEW_BLOB_ACC_INPUT_HASH indicates that the input parameter new_blob_acc_input_hash is invalid
EXECUTOR_ERROR_INVALID_NEW_BLOB_ACC_INPUT_HASH = 127;
// EXECUTOR_ERROR_INVALID_BLOB_DATA indicates that the input parameter blob_data is invalid (too long)
EXECUTOR_ERROR_INVALID_BLOB_DATA = 128;
// EXECUTOR_ERROR_INVALID_ZK_GAS_LIMIT indicates that the input parameter zk_gas_limit is invalid
EXECUTOR_ERROR_INVALID_ZK_GAS_LIMIT = 129;
// EXECUTOR_ERROR_INVALID_POINT_Z indicates that the input parameter point_z is invalid
EXECUTOR_ERROR_INVALID_POINT_Z = 130;
// EXECUTOR_ERROR_INVALID_POINT_Y indicates that the input parameter point_y is invalid
EXECUTOR_ERROR_INVALID_POINT_Y = 131;
// EXECUTOR_ERROR_SM_MAIN_POINT_Z_MISMATCH indicates that the input parameter point_z is different from the one calculated by the executor
EXECUTOR_ERROR_SM_MAIN_POINT_Z_MISMATCH = 132;
// EXECUTOR_ERROR_SM_MAIN_BLOB_L2_HASH_DATA_MISMATCH indicates that the input parameter blob L2 data hash is different from the one calculated by the executor
EXECUTOR_ERROR_SM_MAIN_BLOB_L2_HASH_DATA_MISMATCH = 133;
// EXECUTOR_ERROR_SM_MAIN_BATCH_HASH_DATA_MISMATCH indicates that the input parameter batch data hash is different from the one calculated by the executor
EXECUTOR_ERROR_SM_MAIN_BATCH_HASH_DATA_MISMATCH = 134;
// EXECUTOR_ERROR_SM_MAIN_INVALID_BLOB_TYPE indicates that the input parameter blob type is invalid
EXECUTOR_ERROR_SM_MAIN_INVALID_BLOB_TYPE = 135;
// EXECUTOR_ERROR_SM_MAIN_UNRESTORED_SAVED_CONTEXT indicates that at least one saved context was not restored before finishing the execution
EXECUTOR_ERROR_SM_MAIN_UNRESTORED_SAVED_CONTEXT = 136;
// EXECUTOR_ERROR_SM_MAIN_INVALID_MEMORY_CTX indicates that the memory context polynomial was assigned an invalid value
EXECUTOR_ERROR_SM_MAIN_INVALID_MEMORY_CTX = 137;
}

////////////////////////////////////////////////
//////////// START V3 SECTION ////////////////
////////////////////////////////////////////////

message ProcessBatchRequestV3 {
bytes old_state_root = 1;
bytes old_acc_input_hash = 2;
bytes previous_l1_info_tree_root = 3;
uint32 previous_l1_info_tree_index = 4;
uint64 chain_id = 5;
uint64 fork_id = 6;
bytes batch_l2_data = 7;
bytes forced_hash_data = 8;
ForcedData forced_data = 9;
string coinbase = 10;
uint32 update_merkle_tree = 11;
// flag to indicate that counters should not be taken into account
uint32 no_counters = 12;
// from is used for unsigned transactions with sender
string from = 13;
// flag to skip the restriction to start a batch with a changeL2Block transaction
uint32 skip_first_change_l2_block = 14;
// flag to skip writing the block info root in the state
uint32 skip_write_block_info_root = 15;
// lInfoTree information
map<uint32, L1DataV3> l1_info_tree_data = 16;
// For testing purposes only
map<string, string> db = 17;
map<string, string> contracts_bytecode = 18; // For debug/testing purpposes only. Don't fill this on production
TraceConfigV2 trace_config = 19;
string context_id = 20;
uint32 get_keys = 21; // if 1, the keys used to read or write storage values will be returned
// The state override set is an optional address-to-state mapping,
// where each entry specifies some state to be ephemerally overridden
// prior to executing the call.
map<string, OverrideAccountV2> state_override = 22;
DebugV2 debug = 23;
}

message L1DataV3 {
bytes global_exit_root = 1;
bytes block_hash_l1 = 2;
uint64 min_timestamp = 3;
repeated bytes smt_proof_previous_index = 4;
bytes initial_historic_root = 5;
}

message ProcessBatchResponseV3 {
bytes new_state_root = 1;
bytes new_acc_input_hash = 2;
bytes new_local_exit_root = 3;
uint64 new_last_timestamp = 4;
bytes current_l1_info_tree_root = 5;
uint32 current_l1_info_tree_index = 6;
uint32 cnt_keccak_hashes = 7;
uint32 cnt_poseidon_hashes = 8;
uint32 cnt_poseidon_paddings = 9;
uint32 cnt_mem_aligns = 10;
uint32 cnt_arithmetics = 11;
uint32 cnt_binaries = 12;
uint32 cnt_steps = 13;
uint32 cnt_sha256_hashes = 14;
repeated ProcessBlockResponseV2 block_responses = 15;
ExecutorError error = 16;
map<string, InfoReadWriteV2> read_write_addresses = 17;
uint64 flush_id = 18;
uint64 stored_flush_id = 19;
string prover_id = 20;
uint64 gas_used = 21;
repeated bytes smt_keys = 22;
repeated bytes program_keys = 23;
uint64 fork_id = 24;
uint32 invalid_batch = 25;
RomError error_rom = 26;
uint32 cnt_reserve_keccak_hashes = 27;
uint32 cnt_reserve_poseidon_hashes = 28;
uint32 cnt_reserve_poseidon_paddings = 29;
uint32 cnt_reserve_mem_aligns = 30;
uint32 cnt_reserve_arithmetics = 31;
uint32 cnt_reserve_binaries = 32;
uint32 cnt_reserve_steps = 33;
uint32 cnt_reserve_sha256_hashes = 34;
bytes old_state_root = 35;
ResponseDebug debug = 36;
}

message ForcedData {
bytes global_exit_root = 1;
bytes block_hash_l1 = 2;
uint64 min_timestamp = 3;
}

message ProcessBlobInnerRequestV3 {
// inputs
bytes old_blob_state_root = 1;
bytes old_blob_acc_input_hash = 2;
uint64 old_num_blob = 3;
bytes old_state_root = 4;
uint64 fork_id = 5;
// belong to blobAccInputHash
uint32 last_l1_info_tree_index = 6;
bytes last_l1_info_tree_root = 7;
uint64 timestamp_limit = 8;
string coinbase = 9;
uint64 zk_gas_limit = 10;
uint32 blob_type = 11;
bytes point_z = 12;
bytes point_y = 13;
bytes blob_data = 14;
bytes forced_hash_data = 15;
string context_id = 16;
DebugV3 debug = 17;
map<string, string> db = 18;
map<string, string> contracts_bytecode = 19; // For debug/testing purpposes only. Don't fill this on production
}

message DebugV3 {
bytes new_blob_state_root = 1;
bytes new_blob_acc_input_hash = 2;
uint64 new_blob_num = 3;
}

message ProcessBlobInnerResponseV3 {
// outputs
bytes new_blob_state_root = 1;
bytes new_blob_acc_input_hash = 2;
uint64 new_num_blob = 3;
bytes final_acc_batch_hash_data = 4;
bytes local_exit_root_from_blob = 5;
uint32 is_invalid = 6;
// extra
repeated bytes batch_data = 7;
ExecutorError error = 8;
RomBlobError error_rom_blob = 9;
ResponseDebug debug = 10;
}

enum RomBlobError {
ROM_BLOB_ERROR_UNSPECIFIED = 0;
// ROM_ERROR_NO_ERROR indicates the execution ended successfully
ROM_BLOB_ERROR_NO_ERROR = 1;
// ROM_BLOB_ERROR_INVALID_PARSING indicates that has been an error while parsing the blob data
ROM_BLOB_ERROR_INVALID_PARSING = 2;
// ROM_BLOB_ERROR_INVALID_MSB_BYTE indicates that the MSB on one field element is different than zero (only for blob_type = 1)
ROM_BLOB_ERROR_INVALID_MSB_BYTE = 3;
// ROM_BLOB_ERROR_INVALID_ZK_GAS_LIMIT not enough zk_gas_limit supplied to pay for batches proofs
ROM_BLOB_ERROR_INVALID_ZK_GAS_LIMIT = 4;
// ROM_BLOB_ERROR_INVALID_BLOB_TYPE blob_type not supported
ROM_BLOB_ERROR_INVALID_BLOB_TYPE = 5;
// ROM_BLOB_ERROR_INVALID_COMPRESSION_TYPE compression type not supported
ROM_BLOB_ERROR_INVALID_COMPRESSION_TYPE = 6;
// ROM_BLOB_ERROR_INVALID_FORCED_BATCHES blobtype = 2 and numBatches > 1
ROM_BLOB_ERROR_INVALID_FORCED_BATCHES = 7;
// ROM_BLOB_ERROR_INVALID_TOTALBODY_LEN totalBodyLen != blobDataLen - 1 (byte compression) - 4 (bytes totalBodyLen)
ROM_BLOB_ERROR_INVALID_TOTALBODY_LEN = 8;
}
16 changes: 8 additions & 8 deletions state/batchV2.go
Original file line number Diff line number Diff line change
Expand Up @@ -168,7 +168,7 @@ func (s *State) ExecuteBatchV2(ctx context.Context, batch Batch, L1InfoTreeRoot
return nil, err
} else if processBatchResponse != nil && processBatchResponse.Error != executor.ExecutorError_EXECUTOR_ERROR_NO_ERROR {
err = executor.ExecutorErr(processBatchResponse.Error)
s.eventLog.LogExecutorErrorV2(ctx, processBatchResponse.Error, processBatchRequest)
s.eventLog.LogExecutorError(ctx, processBatchResponse.Error, processBatchRequest)
}

return processBatchResponse, err
Expand Down Expand Up @@ -299,12 +299,12 @@ func (s *State) sendBatchRequestToExecutorV2(ctx context.Context, batchRequest *
log.Errorf("error executor ProcessBatchV2: %s", err.Error())
log.Errorf("error executor ProcessBatchV2 response: %v", batchResponse)
} else {
batchResponseToString := processBatchResponseToString(newBatchNum, batchResponse, elapsed)
batchResponseToString := processBatchResponseV2ToString(newBatchNum, batchResponse, elapsed)
if batchResponse.Error != executor.ExecutorError_EXECUTOR_ERROR_NO_ERROR {
err = executor.ExecutorErr(batchResponse.Error)
log.Warnf("executor batch %d response, executor error: %v", newBatchNum, err)
log.Warn(batchResponseToString)
s.eventLog.LogExecutorErrorV2(ctx, batchResponse.Error, batchRequest)
s.eventLog.LogExecutorError(ctx, batchResponse.Error, batchRequest)
} else if batchResponse.ErrorRom != executor.RomError_ROM_ERROR_NO_ERROR && executor.IsROMOutOfCountersError(batchResponse.ErrorRom) {
err = executor.RomErr(batchResponse.ErrorRom)
log.Warnf("executor batch %d response, ROM OOC, error: %v", newBatchNum, err)
Expand All @@ -321,32 +321,32 @@ func (s *State) sendBatchRequestToExecutorV2(ctx context.Context, batchRequest *
return batchResponse, err
}

func processBatchResponseToString(batchNum uint64, batchResponse *executor.ProcessBatchResponseV2, executionTime time.Duration) string {
func processBatchResponseV2ToString(batchNum uint64, batchResponse *executor.ProcessBatchResponseV2, executionTime time.Duration) string {
batchResponseLog := "executor batch %d response, Time: %v, NewStateRoot: %v, NewAccInputHash: %v, NewLocalExitRoot: %v, NewBatchNumber: %v, GasUsed: %v, FlushId: %v, StoredFlushId: %v, ProverId:%v, ForkId:%v, Error: %v\n"
batchResponseLog = fmt.Sprintf(batchResponseLog, batchNum, executionTime, hex.EncodeToHex(batchResponse.NewStateRoot), hex.EncodeToHex(batchResponse.NewAccInputHash), hex.EncodeToHex(batchResponse.NewLocalExitRoot),
batchResponse.NewBatchNum, batchResponse.GasUsed, batchResponse.FlushId, batchResponse.StoredFlushId, batchResponse.ProverId, batchResponse.ForkId, batchResponse.Error)

for blockIndex, block := range batchResponse.BlockResponses {
prefix := " " + fmt.Sprintf("block[%v]: ", blockIndex)
batchResponseLog += blockResponseToString(block, prefix)
batchResponseLog += blockResponseV2ToString(block, prefix)
}

return batchResponseLog
}
func blockResponseToString(blockResponse *executor.ProcessBlockResponseV2, prefix string) string {
func blockResponseV2ToString(blockResponse *executor.ProcessBlockResponseV2, prefix string) string {
blockResponseLog := prefix + "ParentHash: %v, Coinbase: %v, GasLimit: %v, BlockNumber: %v, Timestamp: %v, GlobalExitRoot: %v, BlockHashL1: %v, GasUsed: %v, BlockInfoRoot: %v, BlockHash: %v\n"
blockResponseLog = fmt.Sprintf(blockResponseLog, common.BytesToHash(blockResponse.ParentHash), blockResponse.Coinbase, blockResponse.GasLimit, blockResponse.BlockNumber, blockResponse.Timestamp,
common.BytesToHash(blockResponse.Ger), common.BytesToHash(blockResponse.BlockHashL1), blockResponse.GasUsed, common.BytesToHash(blockResponse.BlockInfoRoot), common.BytesToHash(blockResponse.BlockHash))

for txIndex, tx := range blockResponse.Responses {
prefix := " " + fmt.Sprintf("tx[%v]: ", txIndex)
blockResponseLog += transactionResponseToString(tx, prefix)
blockResponseLog += transactionResponseV2ToString(tx, prefix)
}

return blockResponseLog
}

func transactionResponseToString(txResponse *executor.ProcessTransactionResponseV2, prefix string) string {
func transactionResponseV2ToString(txResponse *executor.ProcessTransactionResponseV2, prefix string) string {
txResponseLog := prefix + "TxHash: %v, TxHashL2: %v, Type: %v, StateRoot:%v, GasUsed: %v, GasLeft: %v, GasRefund: %v, Error: %v\n"
txResponseLog = fmt.Sprintf(txResponseLog, common.BytesToHash(txResponse.TxHash), common.BytesToHash(txResponse.TxHashL2), txResponse.Type,
common.BytesToHash(txResponse.StateRoot), txResponse.GasUsed, txResponse.GasLeft, txResponse.GasRefunded, txResponse.Error)
Expand Down
Loading
Loading