Skip to content

Commit

Permalink
fix debug trace for injected tx (#3469)
Browse files Browse the repository at this point in the history
  • Loading branch information
tclemos authored Mar 20, 2024
1 parent baaa333 commit da09fe9
Show file tree
Hide file tree
Showing 2 changed files with 131 additions and 53 deletions.
132 changes: 79 additions & 53 deletions state/trace.go
Original file line number Diff line number Diff line change
Expand Up @@ -188,41 +188,50 @@ func (s *State) DebugTransaction(ctx context.Context, transactionHash common.Has
}
}

// build the raw batch so we can get the index l1 info tree for the l2 block
rawBatch, err := DecodeBatchV2(batch.BatchL2Data)
if err != nil {
log.Errorf("error decoding BatchL2Data for batch %d, error: %v", batch.BatchNumber, err)
return nil, err
}

// identify the first l1 block number so we can identify the
// current l2 block index in the block array
firstBlockNumberForBatch, err := s.GetFirstL2BlockNumberForBatchNumber(ctx, batch.BatchNumber, dbTx)
if err != nil {
log.Errorf("failed to get first l2 block number for batch %v: %v ", batch.BatchNumber, err)
return nil, err
}
// if the l2 block number is 1, it means this is a network that started
// at least on Etrog fork, in this case the l2 block 1 will contain the
// injected tx that needs to be processed in a different way
isInjectedTx := l2Block.NumberU64() == 1

var transactions, batchL2Data []byte
if isInjectedTx {
transactions = append([]byte{}, batch.BatchL2Data...)
} else {
// build the raw batch so we can get the index l1 info tree for the l2 block
rawBatch, err := DecodeBatchV2(batch.BatchL2Data)
if err != nil {
log.Errorf("error decoding BatchL2Data for batch %d, error: %v", batch.BatchNumber, err)
return nil, err
}

// computes the l2 block index
rawL2BlockIndex := l2Block.NumberU64() - firstBlockNumberForBatch
if rawL2BlockIndex > uint64(len(rawBatch.Blocks)-1) {
log.Errorf("computed rawL2BlockIndex is greater than the number of blocks we have in the batch %v: %v ", batch.BatchNumber, err)
return nil, err
}
// identify the first l1 block number so we can identify the
// current l2 block index in the block array
firstBlockNumberForBatch, err := s.GetFirstL2BlockNumberForBatchNumber(ctx, batch.BatchNumber, dbTx)
if err != nil {
log.Errorf("failed to get first l2 block number for batch %v: %v ", batch.BatchNumber, err)
return nil, err
}

// builds the ChangeL2Block transaction with the correct timestamp and IndexL1InfoTree
rawL2Block := rawBatch.Blocks[rawL2BlockIndex]
deltaTimestamp := uint32(l2Block.Time() - previousL2Block.Time())
transactions := s.BuildChangeL2Block(deltaTimestamp, rawL2Block.IndexL1InfoTree)
// computes the l2 block index
rawL2BlockIndex := l2Block.NumberU64() - firstBlockNumberForBatch
if rawL2BlockIndex > uint64(len(rawBatch.Blocks)-1) {
log.Errorf("computed rawL2BlockIndex is greater than the number of blocks we have in the batch %v: %v ", batch.BatchNumber, err)
return nil, err
}

batchL2Data, err := EncodeTransactions(txsToEncode, effectivePercentage, forkId)
if err != nil {
log.Errorf("error encoding transaction ", err)
return nil, err
}
// builds the ChangeL2Block transaction with the correct timestamp and IndexL1InfoTree
rawL2Block := rawBatch.Blocks[rawL2BlockIndex]
deltaTimestamp := uint32(l2Block.Time() - previousL2Block.Time())
transactions = s.BuildChangeL2Block(deltaTimestamp, rawL2Block.IndexL1InfoTree)

transactions = append(transactions, batchL2Data...)
batchL2Data, err = EncodeTransactions(txsToEncode, effectivePercentage, forkId)
if err != nil {
log.Errorf("error encoding transaction ", err)
return nil, err
}

transactions = append(transactions, batchL2Data...)
}
// prepare process batch request
processBatchRequestV2 := &executor.ProcessBatchRequestV2{
OldBatchNum: batch.BatchNumber - 1,
Expand All @@ -244,21 +253,37 @@ func (s *State) DebugTransaction(ctx context.Context, transactionHash common.Has
SkipWriteBlockInfoRoot: cTrue,
}

// gets the L1InfoTreeData for the transactions
l1InfoTreeData, _, _, err := s.GetL1InfoTreeDataFromBatchL2Data(ctx, transactions, dbTx)
if err != nil {
return nil, err
}
if isInjectedTx {
virtualBatch, err := s.GetVirtualBatch(ctx, batch.BatchNumber, dbTx)
if err != nil {
log.Errorf("failed to load virtual batch %v", batch.BatchNumber, err)
return nil, err
}
l1Block, err := s.GetBlockByNumber(ctx, virtualBatch.BlockNumber, dbTx)
if err != nil {
log.Errorf("failed to load l1 block %v", virtualBatch.BlockNumber, err)
return nil, err
}

processBatchRequestV2.ForcedBlockhashL1 = l1Block.BlockHash.Bytes()
processBatchRequestV2.SkipVerifyL1InfoRoot = 1
} else {
// gets the L1InfoTreeData for the transactions
l1InfoTreeData, _, _, err := s.GetL1InfoTreeDataFromBatchL2Data(ctx, transactions, dbTx)
if err != nil {
return nil, err
}

// In case we have any l1InfoTreeData, add them to the request
if len(l1InfoTreeData) > 0 {
processBatchRequestV2.L1InfoTreeData = map[uint32]*executor.L1DataV2{}
processBatchRequestV2.SkipVerifyL1InfoRoot = cTrue
for k, v := range l1InfoTreeData {
processBatchRequestV2.L1InfoTreeData[k] = &executor.L1DataV2{
GlobalExitRoot: v.GlobalExitRoot.Bytes(),
BlockHashL1: v.BlockHashL1.Bytes(),
MinTimestamp: v.MinTimestamp,
// In case we have any l1InfoTreeData, add them to the request
if len(l1InfoTreeData) > 0 {
processBatchRequestV2.L1InfoTreeData = map[uint32]*executor.L1DataV2{}
processBatchRequestV2.SkipVerifyL1InfoRoot = cTrue
for k, v := range l1InfoTreeData {
processBatchRequestV2.L1InfoTreeData[k] = &executor.L1DataV2{
GlobalExitRoot: v.GlobalExitRoot.Bytes(),
BlockHashL1: v.BlockHashL1.Bytes(),
MinTimestamp: v.MinTimestamp,
}
}
}
}
Expand All @@ -275,15 +300,16 @@ func (s *State) DebugTransaction(ctx context.Context, transactionHash common.Has
return nil, err
}

// Transactions are decoded only for logging purposes
// as they are not longer needed in the convertToProcessBatchResponse function
txs, _, _, err := DecodeTxs(batchL2Data, forkId)
if err != nil && !errors.Is(err, ErrInvalidData) {
return nil, err
}

for _, tx := range txs {
log.Debugf(tx.Hash().String())
if !isInjectedTx {
// Transactions are decoded only for logging purposes
// as they are no longer needed in the convertToProcessBatchResponse function
txs, _, _, err := DecodeTxs(batchL2Data, forkId)
if err != nil && !errors.Is(err, ErrInvalidData) {
return nil, err
}
for _, tx := range txs {
log.Debugf(tx.Hash().String())
}
}

convertedResponse, err := s.convertToProcessBatchResponseV2(processBatchResponseV2)
Expand Down
52 changes: 52 additions & 0 deletions test/e2e/debug_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -736,6 +736,58 @@ func TestDebugTraceBlock(t *testing.T) {
}
}

func Test_DebugFirstBatch(t *testing.T) {
if testing.Short() {
t.Skip()
}

const l2NetworkURL = "http://localhost:8124"
const l2ExplorerRPCComponentName = "l2-explorer-json-rpc"

var err error
if !dockersArePreLaunchedForDebugTests {
err = operations.Teardown()
require.NoError(t, err)

defer func() {
require.NoError(t, operations.Teardown())
require.NoError(t, operations.StopComponent(l2ExplorerRPCComponentName))
}()
}

ctx := context.Background()
opsCfg := operations.GetDefaultOperationsConfig()
if !dockersArePreLaunchedForDebugTests {
opsMan, err := operations.NewManager(ctx, opsCfg)
require.NoError(t, err)
err = opsMan.Setup()
require.NoError(t, err)

err = operations.StartComponent(l2ExplorerRPCComponentName, func() (bool, error) { return operations.NodeUpCondition(l2NetworkURL) })
require.NoError(t, err)
} else {
log.Info("Using pre-launched dockers: no reset Database")
}

debugOptions := map[string]interface{}{
"tracer": "callTracer",
"tracerConfig": map[string]interface{}{
"onlyTopCall": false,
"withLog": true,
},
}

response, err := client.JSONRPCCall(l2NetworkURL, "debug_traceBlockByNumber", "0x1", debugOptions)
require.NoError(t, err)
require.Nil(t, response.Error)
require.NotNil(t, response.Result)

response, err = client.JSONRPCCall(l2NetworkURL, "debug_traceBlockByNumber", "0x1")
require.NoError(t, err)
require.Nil(t, response.Error)
require.NotNil(t, response.Result)
}

func getTxInResponseDebugTest(t *testing.T, response json.RawMessage, txIndex uint, debugPrefix string) map[string]interface{} {
valueMap := []interface{}{}
err := json.Unmarshal(response, &valueMap)
Expand Down

0 comments on commit da09fe9

Please sign in to comment.