From b6abba0b2e80d748744cba072c57d17bc4ef7774 Mon Sep 17 00:00:00 2001 From: Ganesh Vanahalli Date: Tue, 29 Oct 2024 17:03:24 +0530 Subject: [PATCH 1/4] Add a boolean field to tx receipt object indicating if the tx was timeboosted --- arbitrum/apibackend.go | 5 +++++ common/types.go | 11 +++++++++++ eth/api_backend.go | 4 ++++ internal/ethapi/api.go | 8 ++++++++ internal/ethapi/api_test.go | 3 +++ internal/ethapi/backend.go | 1 + internal/ethapi/transaction_args_test.go | 3 +++ 7 files changed, 35 insertions(+) diff --git a/arbitrum/apibackend.go b/arbitrum/apibackend.go index 3e90a3738c..2536b0b434 100644 --- a/arbitrum/apibackend.go +++ b/arbitrum/apibackend.go @@ -95,6 +95,7 @@ type SyncProgressBackend interface { SyncProgressMap() map[string]interface{} SafeBlockNumber(ctx context.Context) (uint64, error) FinalizedBlockNumber(ctx context.Context) (uint64, error) + BlockMetadataByNumber(blockNum uint64) (common.BlockMetadata, error) } func createRegisterAPIBackend(backend *Backend, filterConfig filters.Config, fallbackClientUrl string, fallbackClientTimeout time.Duration) (*filters.FilterSystem, error) { @@ -451,6 +452,10 @@ func (a *APIBackend) BlockByNumberOrHash(ctx context.Context, blockNrOrHash rpc. return nil, errors.New("invalid arguments; neither block nor hash specified") } +func (a *APIBackend) BlockMetadataByNumber(blockNum uint64) (common.BlockMetadata, error) { + return a.sync.BlockMetadataByNumber(blockNum) +} + func StateAndHeaderFromHeader(ctx context.Context, chainDb ethdb.Database, bc *core.BlockChain, maxRecreateStateDepth int64, header *types.Header, err error) (*state.StateDB, *types.Header, error) { if err != nil { return nil, header, err diff --git a/common/types.go b/common/types.go index aadca87f82..8c3a137876 100644 --- a/common/types.go +++ b/common/types.go @@ -475,3 +475,14 @@ func (d *Decimal) UnmarshalJSON(input []byte) error { return err } } + +type BlockMetadata []byte + +// IsTxTimeboosted given a tx's index in the block returns whether the tx was timeboosted or not +func (b BlockMetadata) IsTxTimeboosted(txIndex int) bool { + maxTxCount := (len(b) - 1) * 8 + if txIndex >= maxTxCount { + return false + } + return b[1+(txIndex/8)]&(1<<(txIndex%8)) != 0 +} diff --git a/eth/api_backend.go b/eth/api_backend.go index b366527395..98b220de79 100644 --- a/eth/api_backend.go +++ b/eth/api_backend.go @@ -182,6 +182,10 @@ func (b *EthAPIBackend) BlockByNumberOrHash(ctx context.Context, blockNrOrHash r return nil, errors.New("invalid arguments; neither block nor hash specified") } +func (b *EthAPIBackend) BlockMetadataByNumber(blockNum uint64) (common.BlockMetadata, error) { + return nil, nil +} + func (b *EthAPIBackend) PendingBlockAndReceipts() (*types.Block, types.Receipts) { return b.eth.miner.PendingBlockAndReceipts() } diff --git a/internal/ethapi/api.go b/internal/ethapi/api.go index f745c193d6..ca029bb45e 100644 --- a/internal/ethapi/api.go +++ b/internal/ethapi/api.go @@ -1963,6 +1963,14 @@ func marshalReceipt(ctx context.Context, receipt *types.Receipt, blockHash commo fields["l1BlockNumber"] = hexutil.Uint64(arbTx.L1BlockNumber) } } + + blockMetadata, err := backend.BlockMetadataByNumber(blockNumber) + if err != nil { + return nil, err + } + if blockMetadata != nil && blockMetadata.IsTxTimeboosted(txIndex) { + fields["timeboosted"] = true + } } return fields, nil } diff --git a/internal/ethapi/api_test.go b/internal/ethapi/api_test.go index d84c846bfd..794efff48c 100644 --- a/internal/ethapi/api_test.go +++ b/internal/ethapi/api_test.go @@ -525,6 +525,9 @@ func (b testBackend) BlockByNumberOrHash(ctx context.Context, blockNrOrHash rpc. } panic("unknown type rpc.BlockNumberOrHash") } +func (b testBackend) BlockMetadataByNumber(blockNum uint64) (common.BlockMetadata, error) { + return nil, nil +} func (b testBackend) GetBody(ctx context.Context, hash common.Hash, number rpc.BlockNumber) (*types.Body, error) { return b.chain.GetBlock(hash, uint64(number.Int64())).Body(), nil } diff --git a/internal/ethapi/backend.go b/internal/ethapi/backend.go index f911a01cd5..ab9837ea10 100644 --- a/internal/ethapi/backend.go +++ b/internal/ethapi/backend.go @@ -66,6 +66,7 @@ type Backend interface { BlockByNumber(ctx context.Context, number rpc.BlockNumber) (*types.Block, error) BlockByHash(ctx context.Context, hash common.Hash) (*types.Block, error) BlockByNumberOrHash(ctx context.Context, blockNrOrHash rpc.BlockNumberOrHash) (*types.Block, error) + BlockMetadataByNumber(blockNum uint64) (common.BlockMetadata, error) StateAndHeaderByNumber(ctx context.Context, number rpc.BlockNumber) (*state.StateDB, *types.Header, error) StateAndHeaderByNumberOrHash(ctx context.Context, blockNrOrHash rpc.BlockNumberOrHash) (*state.StateDB, *types.Header, error) PendingBlockAndReceipts() (*types.Block, types.Receipts) diff --git a/internal/ethapi/transaction_args_test.go b/internal/ethapi/transaction_args_test.go index 667f7b3068..3178b92ae3 100644 --- a/internal/ethapi/transaction_args_test.go +++ b/internal/ethapi/transaction_args_test.go @@ -349,6 +349,9 @@ func (b *backendMock) BlockByHash(ctx context.Context, hash common.Hash) (*types func (b *backendMock) BlockByNumberOrHash(ctx context.Context, blockNrOrHash rpc.BlockNumberOrHash) (*types.Block, error) { return nil, nil } +func (b *backendMock) BlockMetadataByNumber(blockNum uint64) (common.BlockMetadata, error) { + return nil, nil +} func (b *backendMock) GetBody(ctx context.Context, hash common.Hash, number rpc.BlockNumber) (*types.Body, error) { return nil, nil } From 5c7cde2e1dae20e90621f3781edef35be683769a Mon Sep 17 00:00:00 2001 From: Ganesh Vanahalli Date: Thu, 14 Nov 2024 19:02:43 +0530 Subject: [PATCH 2/4] address PR comments --- internal/ethapi/api.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/internal/ethapi/api.go b/internal/ethapi/api.go index ca029bb45e..b9740d9d45 100644 --- a/internal/ethapi/api.go +++ b/internal/ethapi/api.go @@ -1968,8 +1968,8 @@ func marshalReceipt(ctx context.Context, receipt *types.Receipt, blockHash commo if err != nil { return nil, err } - if blockMetadata != nil && blockMetadata.IsTxTimeboosted(txIndex) { - fields["timeboosted"] = true + if blockMetadata != nil { + fields["timeboosted"] = blockMetadata.IsTxTimeboosted(txIndex) } } return fields, nil From 17286562eb2f0dcd02dafdaf5da0fce5ff1f6096 Mon Sep 17 00:00:00 2001 From: Ganesh Vanahalli Date: Fri, 27 Dec 2024 11:35:16 -0600 Subject: [PATCH 3/4] update IsTxTimeboosted method on BlockMetadata --- common/types.go | 12 +++++++++--- internal/ethapi/api.go | 5 ++++- 2 files changed, 13 insertions(+), 4 deletions(-) diff --git a/common/types.go b/common/types.go index 9527e833ea..e2fe42e133 100644 --- a/common/types.go +++ b/common/types.go @@ -490,10 +490,16 @@ func (b PrettyBytes) TerminalString() string { type BlockMetadata []byte // IsTxTimeboosted given a tx's index in the block returns whether the tx was timeboosted or not -func (b BlockMetadata) IsTxTimeboosted(txIndex int) bool { +func (b BlockMetadata) IsTxTimeboosted(txIndex int) (bool, error) { + if len(b) == 0 { + return false, errors.New("blockMetadata is not set") + } + if txIndex < 0 { + return false, fmt.Errorf("invalid transaction index- %d, should be positive", txIndex) + } maxTxCount := (len(b) - 1) * 8 if txIndex >= maxTxCount { - return false + return false, nil } - return b[1+(txIndex/8)]&(1<<(txIndex%8)) != 0 + return b[1+(txIndex/8)]&(1<<(txIndex%8)) != 0, nil } diff --git a/internal/ethapi/api.go b/internal/ethapi/api.go index 41b807c605..7bcdcf57e5 100644 --- a/internal/ethapi/api.go +++ b/internal/ethapi/api.go @@ -1989,7 +1989,10 @@ func marshalReceipt(ctx context.Context, receipt *types.Receipt, blockHash commo return nil, err } if blockMetadata != nil { - fields["timeboosted"] = blockMetadata.IsTxTimeboosted(txIndex) + fields["timeboosted"], err = blockMetadata.IsTxTimeboosted(txIndex) + if err != nil { + log.Error("Error checking if a tx was timeboosted", "txIndex", txIndex, "txHash", tx.Hash(), "err", err) + } } } return fields, nil From 0efc662e2f0fe1e49503a22a85b5a6825b6fcbf8 Mon Sep 17 00:00:00 2001 From: Ganesh Vanahalli Date: Tue, 21 Jan 2025 20:56:42 +0530 Subject: [PATCH 4/4] add descriptive comment for blockMetadata creation --- common/types.go | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/common/types.go b/common/types.go index e2fe42e133..bf6b620c76 100644 --- a/common/types.go +++ b/common/types.go @@ -489,7 +489,11 @@ func (b PrettyBytes) TerminalString() string { type BlockMetadata []byte -// IsTxTimeboosted given a tx's index in the block returns whether the tx was timeboosted or not +// IsTxTimeboosted given a tx's index in the block returns whether the tx was timeboosted +// or not. The first byte of blockMetadata byte array is reserved to indicate the version, +// starting from the second byte, (N)th bit would represent if (N)th tx is timeboosted or not, 1 means yes and 0 means no +// blockMetadata[index / 8 + 1] & (1 << (index % 8)) != 0; where index = (N - 1), implies whether (N)th tx in a block is timeboosted +// note that number of txs in a block will always lag behind (len(blockMetadata) - 1) * 8 but it wont lag more than a value of 7 func (b BlockMetadata) IsTxTimeboosted(txIndex int) (bool, error) { if len(b) == 0 { return false, errors.New("blockMetadata is not set")