Skip to content

Commit

Permalink
Fixes for ots on e3 (#8978)
Browse files Browse the repository at this point in the history
- fix magic number handling (block == 0)
- add support for ots_searchTransactionsAfter
- add missing fields on receipts

---------

Co-authored-by: alex.sharov <[email protected]>
  • Loading branch information
wmitsuda and AskAlexSharov authored May 5, 2024
1 parent d15d528 commit 884b7c3
Show file tree
Hide file tree
Showing 4 changed files with 257 additions and 99 deletions.
99 changes: 4 additions & 95 deletions turbo/jsonrpc/otterscan_api.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,17 +7,13 @@ import (
"math/big"

hexutil2 "github.com/ledgerwatch/erigon-lib/common/hexutil"
"github.com/ledgerwatch/erigon/cmd/state/exec3"
"golang.org/x/sync/errgroup"

"github.com/holiman/uint256"
"github.com/ledgerwatch/erigon-lib/chain"
"github.com/ledgerwatch/erigon-lib/common"
"github.com/ledgerwatch/erigon-lib/common/hexutility"
"github.com/ledgerwatch/erigon-lib/kv"
"github.com/ledgerwatch/erigon-lib/kv/iter"
"github.com/ledgerwatch/erigon-lib/kv/order"
"github.com/ledgerwatch/erigon-lib/kv/rawdbv3"
"github.com/ledgerwatch/erigon/consensus"
"github.com/ledgerwatch/erigon/core"
"github.com/ledgerwatch/erigon/core/rawdb"
Expand All @@ -28,7 +24,6 @@ import (
"github.com/ledgerwatch/erigon/turbo/adapter/ethapi"
"github.com/ledgerwatch/erigon/turbo/rpchelper"
"github.com/ledgerwatch/erigon/turbo/transactions"
"github.com/ledgerwatch/log/v3"
)

// API_LEVEL Must be incremented every time new additions are made
Expand Down Expand Up @@ -258,96 +253,6 @@ func (api *OtterscanAPIImpl) SearchTransactionsBefore(ctx context.Context, addr
return &TransactionsWithReceipts{txs, receipts, isFirstPage, !hasMore}, nil
}

func (api *OtterscanAPIImpl) searchTransactionsBeforeV3(tx kv.TemporalTx, ctx context.Context, addr common.Address, fromBlockNum uint64, pageSize uint16) (*TransactionsWithReceipts, error) {
chainConfig, err := api.chainConfig(ctx, tx)
if err != nil {
return nil, err
}

isFirstPage := false
if fromBlockNum == 0 {
isFirstPage = true
} else {
// Internal search code considers blockNum [including], so adjust the value
fromBlockNum--
}
fromTxNum, err := rawdbv3.TxNums.Max(tx, fromBlockNum)
if err != nil {
return nil, err
}
itTo, err := tx.IndexRange(kv.TracesToIdx, addr[:], int(fromTxNum), -1, order.Desc, kv.Unlim)
if err != nil {
return nil, err
}
itFrom, err := tx.IndexRange(kv.TracesFromIdx, addr[:], int(fromTxNum), -1, order.Desc, kv.Unlim)
if err != nil {
return nil, err
}
txNums := iter.Union[uint64](itFrom, itTo, order.Desc, kv.Unlim)
txNumsIter := rawdbv3.TxNums2BlockNums(tx, txNums, order.Desc)
defer txNumsIter.Close()

exec := exec3.NewTraceWorker(tx, chainConfig, api.engine(), api._blockReader, nil)
var blockHash common.Hash
var header *types.Header
txs := make([]*RPCTransaction, 0, pageSize)
receipts := make([]map[string]interface{}, 0, pageSize)
resultCount := uint16(0)

for txNumsIter.HasNext() {
txNum, blockNum, txIndex, isFinalTxn, blockNumChanged, err := txNumsIter.Next()
if err != nil {
return nil, err
}
if isFinalTxn {
continue
}

if blockNumChanged { // things which not changed within 1 block
if header, err = api._blockReader.HeaderByNumber(ctx, tx, blockNum); err != nil {
return nil, err
}
if header == nil {
log.Warn("[rpc] header is nil", "blockNum", blockNum)
continue
}
blockHash = header.Hash()
exec.ChangeBlock(header)
}

//fmt.Printf("txNum=%d, blockNum=%d, txIndex=%d, maxTxNumInBlock=%d,mixTxNumInBlock=%d\n", txNum, blockNum, txIndex, maxTxNumInBlock, minTxNumInBlock)
txn, err := api._txnReader.TxnByIdxInBlock(ctx, tx, blockNum, txIndex)
if err != nil {
return nil, err
}
if txn == nil {
continue
}
res, err := exec.ExecTxn(txNum, txIndex, txn)
if err != nil {
return nil, err
}
rawLogs := exec.GetLogs(txIndex, txn)
rpcTx := NewRPCTransaction(txn, blockHash, blockNum, uint64(txIndex), header.BaseFee)
txs = append(txs, rpcTx)
receipt := &types.Receipt{
Type: txn.Type(), CumulativeGasUsed: res.UsedGas,
TransactionIndex: uint(txIndex),
BlockNumber: header.Number, BlockHash: blockHash, Logs: rawLogs,
}
mReceipt := ethutils.MarshalReceipt(receipt, txn, chainConfig, header, txn.Hash(), true)
mReceipt["timestamp"] = header.Time
receipts = append(receipts, mReceipt)

resultCount++
if resultCount >= pageSize {
break
}
}
hasMore := txNumsIter.HasNext()
return &TransactionsWithReceipts{txs, receipts, isFirstPage, !hasMore}, nil
}

// Search transactions that touch a certain address.
//
// It searches forward a certain block (excluding); the results are sorted descending.
Expand All @@ -367,6 +272,10 @@ func (api *OtterscanAPIImpl) SearchTransactionsAfter(ctx context.Context, addr c
}
defer dbtx.Rollback()

if api.historyV3(dbtx) {
return api.searchTransactionsAfterV3(dbtx.(kv.TemporalTx), ctx, addr, blockNum, pageSize)
}

callFromCursor, err := dbtx.Cursor(kv.CallFromIndex)
if err != nil {
return nil, err
Expand Down
7 changes: 3 additions & 4 deletions turbo/jsonrpc/otterscan_search_backward_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -190,9 +190,8 @@ func TestSearchTransactionsBefore(t *testing.T) {
require.Equal(3, int(results.Txs[1].BlockNumber.ToInt().Uint64()))
require.Equal(2, int(results.Txs[1].Nonce))
require.Equal(3, int(results.Receipts[1]["blockNumber"].(hexutil.Uint64)))
require.Equal(libcommon.HexToHash("0x79491e16fd1b1ceea44c46af850b2ef121683055cd579fd4d877beba22e77c1c"), results.Receipts[0]["transactionHash"].(libcommon.Hash))
require.Equal(libcommon.HexToAddress("0x0D3ab14BBaD3D99F4203bd7a11aCB94882050E7e"), results.Receipts[0]["from"].(libcommon.Address))
require.Equal(addr, *results.Receipts[0]["to"].(*libcommon.Address))
require.Equal(libcommon.HexToHash("0x6e25f89e24254ba3eb460291393a4715fd3c33d805334cbd05c1b2efe1080f18"), results.Receipts[1]["transactionHash"].(libcommon.Hash))
require.Equal(libcommon.HexToAddress("0x71562b71999873DB5b286dF957af199Ec94617F7"), results.Receipts[1]["from"].(libcommon.Address))
require.Nil(results.Receipts[1]["to"].(*libcommon.Address))
})

}
53 changes: 53 additions & 0 deletions turbo/jsonrpc/otterscan_search_forward_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,10 @@ import (
"testing"

"github.com/RoaringBitmap/roaring/roaring64"
libcommon "github.com/ledgerwatch/erigon-lib/common"
"github.com/ledgerwatch/erigon-lib/common/hexutil"
"github.com/ledgerwatch/erigon/cmd/rpcdaemon/rpcdaemontest"
"github.com/stretchr/testify/require"
)

func newMockForwardChunkLocator(chunks [][]byte) ChunkLocator {
Expand Down Expand Up @@ -141,3 +145,52 @@ func TestForwardBlockProviderWithMultipleChunksBlockNotFound(t *testing.T) {

checkNext(t, blockProvider, 0, false)
}

func TestSearchTransactionsAfter(t *testing.T) {
m, _, _ := rpcdaemontest.CreateTestSentry(t)
api := NewOtterscanAPI(newBaseApiForTest(m), m.DB, 25)

addr := libcommon.HexToAddress("0x537e697c7ab75a26f9ecf0ce810e3154dfcaaf44")
t.Run("small page size", func(t *testing.T) {
require := require.New(t)
results, err := api.SearchTransactionsAfter(m.Ctx, addr, 2, 2)
require.NoError(err)
require.False(results.FirstPage)
require.False(results.LastPage)
require.Equal(2, len(results.Txs))
require.Equal(2, len(results.Receipts))
})
t.Run("big page size", func(t *testing.T) {
require := require.New(t)
results, err := api.SearchTransactionsAfter(m.Ctx, addr, 2, 10)
require.NoError(err)
require.True(results.FirstPage)
require.False(results.LastPage)
require.Equal(3, len(results.Txs))
require.Equal(3, len(results.Receipts))
})
t.Run("filter last block", func(t *testing.T) {
require := require.New(t)
results, err := api.SearchTransactionsAfter(m.Ctx, addr, 3, 10)

require.NoError(err)
require.True(results.FirstPage)
require.False(results.LastPage)
require.Equal(2, len(results.Txs))
require.Equal(2, len(results.Receipts))

require.Equal(5, int(results.Txs[0].BlockNumber.ToInt().Uint64()))
require.Equal(0, int(results.Txs[0].Nonce))
require.Equal(5, int(results.Receipts[0]["blockNumber"].(hexutil.Uint64)))
require.Equal(libcommon.HexToHash("0x469bd6281c0a1b1c2225b692752b627e3b935e988d8878925cb7e26e40e3ca14"), results.Receipts[0]["transactionHash"].(libcommon.Hash))
require.Equal(libcommon.HexToAddress("0x703c4b2bD70c169f5717101CaeE543299Fc946C7"), results.Receipts[0]["from"].(libcommon.Address))
require.Equal(addr, *results.Receipts[0]["to"].(*libcommon.Address))

require.Equal(4, int(results.Txs[1].BlockNumber.ToInt().Uint64()))
require.Equal(0, int(results.Txs[1].Nonce))
require.Equal(4, int(results.Receipts[1]["blockNumber"].(hexutil.Uint64)))
require.Equal(libcommon.HexToHash("0x79491e16fd1b1ceea44c46af850b2ef121683055cd579fd4d877beba22e77c1c"), results.Receipts[1]["transactionHash"].(libcommon.Hash))
require.Equal(libcommon.HexToAddress("0x0D3ab14BBaD3D99F4203bd7a11aCB94882050E7e"), results.Receipts[1]["from"].(libcommon.Address))
require.Equal(addr, *results.Receipts[1]["to"].(*libcommon.Address))
})
}
Loading

0 comments on commit 884b7c3

Please sign in to comment.