Skip to content
Draft
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
5 changes: 5 additions & 0 deletions db/kv/membatchwithdb/memory_mutation.go
Original file line number Diff line number Diff line change
Expand Up @@ -1097,6 +1097,11 @@ func (m *MemoryMutation) NewReadView(tx kv.Tx) kv.TemporalTx {
return m.newReadViewMut(tx)
}

// IsOverlayReadView reports whether this mutation is a view created from an overlay.
func (m *MemoryMutation) IsOverlayReadView() bool {
return m != nil && m.memDb == nil
}

// newReadViewMut is the internal constructor that returns the full
// *MemoryMutation. Used by NewTemporalReadView which needs to embed it.
func (m *MemoryMutation) newReadViewMut(tx kv.Tx) *MemoryMutation {
Expand Down
2 changes: 1 addition & 1 deletion db/seg/decompress.go
Original file line number Diff line number Diff line change
Expand Up @@ -196,7 +196,7 @@ type Decompressor struct {
readAheadRefcnt atomic.Int32 // ref-counter: allow enable/disable read-ahead from goroutines. only when refcnt=0 - disable read-ahead once

residency atomic.Pointer[residencyBitmap] // page-residency bitmap for the async-io gate; nil unless enabled
residencyOnce sync.Once
residencyOnce sync.Once //nolint:unused // Used by the Linux-only residency gate.
}

const (
Expand Down
8 changes: 4 additions & 4 deletions docs/site/docs/interacting-with-erigon/trace.md
Original file line number Diff line number Diff line change
Expand Up @@ -199,7 +199,7 @@ Executes the given call and returns a number of possible traces for it.

1. `Object` - \[Transaction object] where `from` field is optional and `nonce` field is omitted.
2. `Array` - Type of trace, one or more of: `"vmTrace"`, `"trace"`, `"stateDiff"`.
3. `Quantity` or `Tag` - (optional) Integer of a block number, or the string `'earliest'`, `'latest'` or `'pending'`.
3. `Quantity` or `Tag` - (optional) Integer of a block number, or the string `'earliest'` or `'latest'`. `'pending'` is not supported: the call is executed against committed state, so there is no pending block to execute on top of.

#### Returns

Expand Down Expand Up @@ -247,7 +247,7 @@ Performs multiple call traces on top of the same block. i.e. transaction `n` wil
#### Parameters

1. `Array` - List of trace calls with the type of trace, one or more of: `"vmTrace"`, `"trace"`, `"stateDiff"`.
2. `Quantity` or `Tag` - (optional) integer block number, or the string `'latest'`, `'earliest'` or `'pending'` (default block parameter).
2. `Quantity` or `Tag` - (optional) integer block number, or the string `'latest'` or `'earliest'` (default block parameter). `'pending'` is not supported: the calls are executed against committed state, so there is no pending block to execute on top of.

```js
params: [
Expand Down Expand Up @@ -405,7 +405,7 @@ Replays all transactions in a block returning the requested traces for each tran

#### Parameters

1. `Quantity` or `Tag` - Integer of a block number, or the string `'earliest'`, `'latest'` or `'pending'`.
1. `Quantity` or `Tag` - Integer of a block number, or the string `'earliest'` or `'latest'`. `'pending'` is not supported: tracing replays committed state, so there is no pending block to replay.
2. `Array` - Type of trace, one or more of: `"vmTrace"`, `"trace"`, `"stateDiff"`.

```js
Expand Down Expand Up @@ -519,7 +519,7 @@ Returns traces created at given block.

#### Parameters

1. `Quantity` or `Tag` - Integer of a block number, or the string `'earliest'`, `'latest'` or `'pending'`.
1. `Quantity` or `Tag` - Integer of a block number, or the string `'earliest'` or `'latest'`. `'pending'` is not supported: tracing replays committed state, so there is no pending block to replay.

```js
params: [
Expand Down
8 changes: 4 additions & 4 deletions docs/site/static/llms-full.txt
Original file line number Diff line number Diff line change
Expand Up @@ -6037,7 +6037,7 @@ Executes the given call and returns a number of possible traces for it.

1. `Object` - \[Transaction object] where `from` field is optional and `nonce` field is omitted.
2. `Array` - Type of trace, one or more of: `"vmTrace"`, `"trace"`, `"stateDiff"`.
3. `Quantity` or `Tag` - (optional) Integer of a block number, or the string `'earliest'`, `'latest'` or `'pending'`.
3. `Quantity` or `Tag` - (optional) Integer of a block number, or the string `'earliest'` or `'latest'`. `'pending'` is not supported: the call is executed against committed state, so there is no pending block to execute on top of.

#### Returns

Expand Down Expand Up @@ -6084,7 +6084,7 @@ Performs multiple call traces on top of the same block. i.e. transaction `n` wil
#### Parameters

1. `Array` - List of trace calls with the type of trace, one or more of: `"vmTrace"`, `"trace"`, `"stateDiff"`.
2. `Quantity` or `Tag` - (optional) integer block number, or the string `'latest'`, `'earliest'` or `'pending'` (default block parameter).
2. `Quantity` or `Tag` - (optional) integer block number, or the string `'latest'` or `'earliest'` (default block parameter). `'pending'` is not supported: the calls are executed against committed state, so there is no pending block to execute on top of.

```js
params: [
Expand Down Expand Up @@ -6239,7 +6239,7 @@ Replays all transactions in a block returning the requested traces for each tran

#### Parameters

1. `Quantity` or `Tag` - Integer of a block number, or the string `'earliest'`, `'latest'` or `'pending'`.
1. `Quantity` or `Tag` - Integer of a block number, or the string `'earliest'` or `'latest'`. `'pending'` is not supported: tracing replays committed state, so there is no pending block to replay.
2. `Array` - Type of trace, one or more of: `"vmTrace"`, `"trace"`, `"stateDiff"`.

```js
Expand Down Expand Up @@ -6351,7 +6351,7 @@ Returns traces created at given block.

#### Parameters

1. `Quantity` or `Tag` - Integer of a block number, or the string `'earliest'`, `'latest'` or `'pending'`.
1. `Quantity` or `Tag` - Integer of a block number, or the string `'earliest'` or `'latest'`. `'pending'` is not supported: tracing replays committed state, so there is no pending block to replay.

```js
params: [
Expand Down
8 changes: 4 additions & 4 deletions llms-full.txt
Original file line number Diff line number Diff line change
Expand Up @@ -6037,7 +6037,7 @@ Executes the given call and returns a number of possible traces for it.

1. `Object` - \[Transaction object] where `from` field is optional and `nonce` field is omitted.
2. `Array` - Type of trace, one or more of: `"vmTrace"`, `"trace"`, `"stateDiff"`.
3. `Quantity` or `Tag` - (optional) Integer of a block number, or the string `'earliest'`, `'latest'` or `'pending'`.
3. `Quantity` or `Tag` - (optional) Integer of a block number, or the string `'earliest'` or `'latest'`. `'pending'` is not supported: the call is executed against committed state, so there is no pending block to execute on top of.

#### Returns

Expand Down Expand Up @@ -6084,7 +6084,7 @@ Performs multiple call traces on top of the same block. i.e. transaction `n` wil
#### Parameters

1. `Array` - List of trace calls with the type of trace, one or more of: `"vmTrace"`, `"trace"`, `"stateDiff"`.
2. `Quantity` or `Tag` - (optional) integer block number, or the string `'latest'`, `'earliest'` or `'pending'` (default block parameter).
2. `Quantity` or `Tag` - (optional) integer block number, or the string `'latest'` or `'earliest'` (default block parameter). `'pending'` is not supported: the calls are executed against committed state, so there is no pending block to execute on top of.

```js
params: [
Expand Down Expand Up @@ -6239,7 +6239,7 @@ Replays all transactions in a block returning the requested traces for each tran

#### Parameters

1. `Quantity` or `Tag` - Integer of a block number, or the string `'earliest'`, `'latest'` or `'pending'`.
1. `Quantity` or `Tag` - Integer of a block number, or the string `'earliest'` or `'latest'`. `'pending'` is not supported: tracing replays committed state, so there is no pending block to replay.
2. `Array` - Type of trace, one or more of: `"vmTrace"`, `"trace"`, `"stateDiff"`.

```js
Expand Down Expand Up @@ -6351,7 +6351,7 @@ Returns traces created at given block.

#### Parameters

1. `Quantity` or `Tag` - Integer of a block number, or the string `'earliest'`, `'latest'` or `'pending'`.
1. `Quantity` or `Tag` - Integer of a block number, or the string `'earliest'` or `'latest'`. `'pending'` is not supported: tracing replays committed state, so there is no pending block to replay.

```js
params: [
Expand Down
78 changes: 24 additions & 54 deletions rpc/jsonrpc/bor_api_impl.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,6 @@ import (
"errors"

"github.com/erigontech/erigon/common"
"github.com/erigontech/erigon/db/rawdb"
"github.com/erigontech/erigon/execution/types"
"github.com/erigontech/erigon/execution/types/accounts"
"github.com/erigontech/erigon/polygon/heimdall"
Expand Down Expand Up @@ -58,12 +57,11 @@ func (api *BorImpl) GetSnapshot(number *rpc.BlockNumber) (*Snapshot, error) {
defer tx.Rollback()

// Retrieve the requested block number (or current if none requested)
var header *types.Header
if number == nil || *number == rpc.LatestBlockNumber {
header = rawdb.ReadCurrentHeader(tx)
} else {
header, _ = api.headerByNumber(ctx, *number, tx)
blockNr := rpc.LatestBlockNumber
if number != nil {
blockNr = *number
}
header, _ := api.headerByNumber(ctx, blockNr, tx)
// Ensure we have an actually valid block
if header == nil {
return nil, errUnknownBlock
Expand Down Expand Up @@ -99,22 +97,12 @@ func (api *BorImpl) GetAuthor(blockNrOrHash *rpc.BlockNumberOrHash) (accounts.Ad

// Retrieve the requested block number (or current if none requested)
var header *types.Header

//nolint:nestif
if blockNrOrHash == nil {
latestBlockNum, err2 := rpchelper.GetLatestBlockNumber(tx)
if err2 != nil {
return accounts.NilAddress, err2
}
header, err = api._blockReader.HeaderByNumber(ctx, tx, latestBlockNum)
} else {
if blockNr, ok := blockNrOrHash.Number(); ok {
header, err = api._blockReader.HeaderByNumber(ctx, tx, uint64(blockNr))
} else {
if blockHash, ok := blockNrOrHash.Hash(); ok {
header, err = api._blockReader.HeaderByHash(ctx, tx, blockHash)
}
}
header, err = api.headerByNumber(ctx, rpc.LatestBlockNumber, tx)
} else if blockNr, ok := blockNrOrHash.Number(); ok {
header, err = api.headerByNumber(ctx, blockNr, tx)
} else if blockHash, ok := blockNrOrHash.Hash(); ok {
header, err = api.headerByHash(ctx, blockHash, tx)
}

// Ensure we have an actually valid block and return its snapshot
Expand Down Expand Up @@ -172,12 +160,11 @@ func (api *BorImpl) GetSigners(number *rpc.BlockNumber) ([]common.Address, error
defer tx.Rollback()

// Retrieve the requested block number (or current if none requested)
var header *types.Header
if number == nil || *number == rpc.LatestBlockNumber {
header = rawdb.ReadCurrentHeader(tx)
} else {
header, _ = api.headerByNumber(ctx, *number, tx)
blockNr := rpc.LatestBlockNumber
if number != nil {
blockNr = *number
}
header, _ := api.headerByNumber(ctx, blockNr, tx)
// Ensure we have an actually valid block
if header == nil {
return nil, errUnknownBlock
Expand Down Expand Up @@ -298,7 +285,7 @@ func (api *BorImpl) getLatestBlockNum(ctx context.Context) (uint64, error) {
}
defer tx.Rollback()

return rpchelper.GetLatestBlockNumber(tx)
return rpchelper.GetLatestBlockNumber(api.filters.WithOverlay(tx))
}

// GetSnapshotProposer retrieves the in-turn signer at a given block.
Expand All @@ -312,21 +299,12 @@ func (api *BorImpl) GetSnapshotProposer(blockNrOrHash *rpc.BlockNumberOrHash) (c
defer tx.Rollback()

var header *types.Header
//nolint:nestif
if blockNrOrHash == nil {
header = rawdb.ReadCurrentHeader(tx)
} else {
if blockNr, ok := blockNrOrHash.Number(); ok {
if blockNr == rpc.LatestBlockNumber {
header = rawdb.ReadCurrentHeader(tx)
} else {
header, err = api.headerByNumber(ctx, blockNr, tx)
}
} else {
if blockHash, ok := blockNrOrHash.Hash(); ok {
header, err = api.headerByHash(ctx, blockHash, tx)
}
}
header, err = api.headerByNumber(ctx, rpc.LatestBlockNumber, tx)
} else if blockNr, ok := blockNrOrHash.Number(); ok {
header, err = api.headerByNumber(ctx, blockNr, tx)
} else if blockHash, ok := blockNrOrHash.Hash(); ok {
header, err = api.headerByHash(ctx, blockHash, tx)
}

if header == nil || err != nil {
Expand All @@ -352,19 +330,11 @@ func (api *BorImpl) GetSnapshotProposerSequence(blockNrOrHash *rpc.BlockNumberOr
// Retrieve the requested block number (or current if none requested)
var header *types.Header
if blockNrOrHash == nil {
header = rawdb.ReadCurrentHeader(tx)
} else {
if blockNr, ok := blockNrOrHash.Number(); ok {
if blockNr == rpc.LatestBlockNumber {
header = rawdb.ReadCurrentHeader(tx)
} else {
header, err = api.headerByNumber(ctx, blockNr, tx)
}
} else {
if blockHash, ok := blockNrOrHash.Hash(); ok {
header, err = api.headerByHash(ctx, blockHash, tx)
}
}
header, err = api.headerByNumber(ctx, rpc.LatestBlockNumber, tx)
} else if blockNr, ok := blockNrOrHash.Number(); ok {
header, err = api.headerByNumber(ctx, blockNr, tx)
} else if blockHash, ok := blockNrOrHash.Hash(); ok {
header, err = api.headerByHash(ctx, blockHash, tx)
}

// Ensure we have an actually valid block
Expand Down
36 changes: 24 additions & 12 deletions rpc/jsonrpc/debug_api.go
Original file line number Diff line number Diff line change
Expand Up @@ -130,7 +130,9 @@ func (api *DebugAPIImpl) SetHead(ctx context.Context, number hexutil.Uint64) err
}
defer tx.Rollback()

currentHead, err := rpchelper.GetLatestBlockNumber(tx)
// Overlay-aware head, so setHead(N) isn't rejected as future while N's
// commit is still in flight.
currentHead, err := rpchelper.GetLatestBlockNumber(api.filters.WithOverlay(tx))
if err != nil {
return err
}
Expand Down Expand Up @@ -161,7 +163,8 @@ func (api *DebugAPIImpl) StorageRangeAt(ctx context.Context, blockHash common.Ha
}

blockNrOrHash := rpc.BlockNumberOrHashWithHash(blockHash, true)
blockNumber, _, _, err := rpchelper.GetCanonicalBlockNumber(ctx, blockNrOrHash, tx, api._blockReader, api.filters)
// nil filters: committed view — the scan below reads temporal data through this tx.
blockNumber, _, _, err := rpchelper.GetCanonicalBlockNumber(ctx, blockNrOrHash, tx, api._blockReader, nil)
if err != nil {
if errors.As(err, &rpc.BlockNotFoundErr{}) {
return StorageRangeResult{}, nil
Expand Down Expand Up @@ -256,7 +259,8 @@ func (api *DebugAPIImpl) AccountRange(ctx context.Context, blockNrOrHash rpc.Blo
}

} else if _, ok := blockNrOrHash.Hash(); ok {
bn, _, _, err2 := rpchelper.GetCanonicalBlockNumber(ctx, blockNrOrHash, tx, api._blockReader, api.filters)
// nil filters: committed view — the dumper reads temporal data through this tx.
bn, _, _, err2 := rpchelper.GetCanonicalBlockNumber(ctx, blockNrOrHash, tx, api._blockReader, nil)
if err2 != nil {
return state.IteratorDump{}, err2
}
Expand Down Expand Up @@ -588,31 +592,33 @@ func (api *DebugAPIImpl) AccountAt(ctx context.Context, blockHash common.Hash, t
}
defer tx.Rollback()

header, err := api.headerByHash(ctx, blockHash, tx)
// Committed view: the canonical-hash check and the GetAsOf reads below all
// go through this plain tx.
blockNumber, err := api._blockReader.HeaderNumber(ctx, tx, blockHash)
if err != nil {
return &AccountResult{}, err
return nil, err
}
if header == nil {
if blockNumber == nil {
return nil, nil // not error, see https://github.com/erigontech/erigon/issues/1645
}
canonicalHash, ok, err := api._blockReader.CanonicalHash(ctx, tx, header.Number.Uint64())
canonicalHash, ok, err := api._blockReader.CanonicalHash(ctx, tx, *blockNumber)
if err != nil {
return nil, err
}
if !ok {
return nil, fmt.Errorf("canonical hash not found %d", header.Number.Uint64())
return nil, fmt.Errorf("canonical hash not found %d", *blockNumber)
}
isCanonical := canonicalHash == blockHash
if !isCanonical {
return nil, errors.New("block hash is not canonical")
}

err = api.BaseAPI.checkPruneHistory(ctx, tx, header.Number.Uint64())
err = api.BaseAPI.checkPruneHistory(ctx, tx, *blockNumber)
if err != nil {
return nil, err
}

minTxNum, err := api._txNumReader.Min(ctx, tx, header.Number.Uint64())
minTxNum, err := api._txNumReader.Min(ctx, tx, *blockNumber)
if err != nil {
return nil, err
}
Expand Down Expand Up @@ -651,19 +657,25 @@ type AccountResult struct {

// GetRawHeader implements debug_getRawHeader - returns a an RLP-encoded header, given a block number or hash
func (api *DebugAPIImpl) GetRawHeader(ctx context.Context, blockNrOrHash rpc.BlockNumberOrHash) (hexutil.Bytes, error) {
if number, ok := blockNrOrHash.Number(); ok && number == rpc.PendingBlockNumber {
if block := api.pendingBlock(); block != nil {
return rlp.EncodeToBytes(block.Header())
}
}
tx, err := api.db.BeginTemporalRo(ctx)
if err != nil {
return nil, err
}
defer tx.Rollback()
n, h, _, err := rpchelper.GetBlockNumber(ctx, blockNrOrHash, tx, api._blockReader, api.filters)
overlayTx := api.filters.WithOverlay(tx)
n, h, _, err := rpchelper.GetBlockNumber(ctx, blockNrOrHash, overlayTx, api._blockReader, nil)
if err != nil {
if errors.As(err, &rpc.BlockNotFoundErr{}) {
return nil, nil // waiting for spec: not error, see Geth and https://github.com/erigontech/erigon/issues/1645
}
return nil, err
}
header, err := api._blockReader.Header(ctx, tx, h, n)
header, err := api._blockReader.Header(ctx, overlayTx, h, n)
if err != nil {
return nil, err
}
Expand Down
8 changes: 5 additions & 3 deletions rpc/jsonrpc/erigon_block.go
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,8 @@ func (api *ErigonImpl) GetBlockByTimestamp(ctx context.Context, timeStamp rpc.Ti
return nil, err
}
defer tx.Rollback()
// Everything here is a block-table read, so one overlay view keeps the
// head, the search bounds, and the lookups consistent.
overlayTx := api.filters.WithOverlay(tx)

uintTimestamp := timeStamp.TurnIntoUint64()
Expand All @@ -102,7 +104,7 @@ func (api *ErigonImpl) GetBlockByTimestamp(ctx context.Context, timeStamp rpc.Ti
currentHeaderTime := currentHeader.Time
highestNumber := currentHeader.Number.Uint64()

firstHeader, err := api.headerByNumber(ctx, 0, tx)
firstHeader, err := api.headerByNumber(ctx, 0, overlayTx)
if err != nil {
return nil, err
}
Expand Down Expand Up @@ -144,7 +146,7 @@ func (api *ErigonImpl) GetBlockByTimestamp(ctx context.Context, timeStamp rpc.Ti
return currentHeader.Time >= uintTimestamp
})

resultingHeader, err := api.headerByNumber(ctx, rpc.BlockNumber(blockNum), tx)
resultingHeader, err := api.headerByNumber(ctx, rpc.BlockNumber(blockNum), overlayTx)
if err != nil {
return nil, err
}
Expand All @@ -154,7 +156,7 @@ func (api *ErigonImpl) GetBlockByTimestamp(ctx context.Context, timeStamp rpc.Ti
}

for resultingHeader.Time > uintTimestamp {
beforeHeader, err := api.headerByNumber(ctx, rpc.BlockNumber(blockNum)-1, tx)
beforeHeader, err := api.headerByNumber(ctx, rpc.BlockNumber(blockNum)-1, overlayTx)
if err != nil {
return nil, err
}
Expand Down
Loading
Loading