Skip to content

Commit 5df6a68

Browse files
Kourin1996piersy
andauthored
Add totalDifficulty field to JSON-RPC schema of Celo1 block (#310)
* Add totalDifficulty field to JSON-RPC response for Celo1 header & block * Fix test * Remove new line --------- Co-authored-by: piersy <[email protected]>
1 parent 1d58f64 commit 5df6a68

File tree

2 files changed

+95
-4
lines changed

2 files changed

+95
-4
lines changed

internal/ethapi/api.go

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -844,7 +844,7 @@ func (api *BlockChainAPI) GetHeaderByNumber(ctx context.Context, number rpc.Bloc
844844
header, err := api.b.HeaderByNumber(ctx, number)
845845
if header != nil && err == nil {
846846
header := PopulatePreGingerbreadHeaderFields(ctx, api.b, header)
847-
response := RPCMarshalHeader(header)
847+
response := RPCMarshalHeader(header, isCelo1Block(api.b.ChainConfig(), header.Time))
848848
if number == rpc.PendingBlockNumber && api.b.ChainConfig().Optimism == nil {
849849
// Pending header need to nil out a few fields
850850
for _, field := range []string{"hash", "nonce", "miner"} {
@@ -861,7 +861,7 @@ func (api *BlockChainAPI) GetHeaderByHash(ctx context.Context, hash common.Hash)
861861
header, _ := api.b.HeaderByHash(ctx, hash)
862862
if header != nil {
863863
header := PopulatePreGingerbreadHeaderFields(ctx, api.b, header)
864-
return RPCMarshalHeader(header)
864+
return RPCMarshalHeader(header, isCelo1Block(api.b.ChainConfig(), header.Time))
865865
}
866866
return nil
867867
}
@@ -1520,7 +1520,7 @@ func (api *BlockChainAPI) EstimateGas(ctx context.Context, args TransactionArgs,
15201520
}
15211521

15221522
// RPCMarshalHeader converts the given header to the RPC output .
1523-
func RPCMarshalHeader(head *types.Header) map[string]interface{} {
1523+
func RPCMarshalHeader(head *types.Header, isCelo1 bool) map[string]interface{} {
15241524
result := map[string]interface{}{
15251525
"number": (*hexutil.Big)(head.Number),
15261526
"hash": head.Hash(),
@@ -1557,14 +1557,23 @@ func RPCMarshalHeader(head *types.Header) map[string]interface{} {
15571557
if head.RequestsHash != nil {
15581558
result["requestsRoot"] = head.RequestsHash
15591559
}
1560+
if isCelo1 {
1561+
result["totalDifficulty"] = (*hexutil.Big)(new(big.Int).Add(head.Number, common.Big1))
1562+
}
15601563
return result
15611564
}
15621565

1566+
// isCelo1Block determines whether the given block is a Celo1 block
1567+
// based on the chain config and the provided block time
1568+
func isCelo1Block(config *params.ChainConfig, blockTime uint64) bool {
1569+
return config.Cel2Time != nil && !config.IsCel2(blockTime)
1570+
}
1571+
15631572
// RPCMarshalBlock converts the given block to the RPC output which depends on fullTx. If inclTx is true transactions are
15641573
// returned. When fullTx is true the returned block contains full transaction details, otherwise it will only contain
15651574
// transaction hashes.
15661575
func RPCMarshalBlock(ctx context.Context, block *types.Block, inclTx bool, fullTx bool, config *params.ChainConfig, backend Backend) (map[string]interface{}, error) {
1567-
fields := RPCMarshalHeader(block.Header())
1576+
fields := RPCMarshalHeader(block.Header(), isCelo1Block(config, block.Header().Time))
15681577
fields["size"] = hexutil.Uint64(block.Size())
15691578

15701579
if inclTx {

internal/ethapi/celo_api_test.go

Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,15 @@
11
package ethapi
22

33
import (
4+
"context"
45
"math/big"
56
"testing"
67

78
"github.com/ethereum/go-ethereum/common"
89
"github.com/ethereum/go-ethereum/common/hexutil"
910
"github.com/ethereum/go-ethereum/core/types"
1011
"github.com/ethereum/go-ethereum/crypto"
12+
"github.com/ethereum/go-ethereum/internal/blocktest"
1113
"github.com/ethereum/go-ethereum/params"
1214
"github.com/stretchr/testify/assert"
1315
"github.com/stretchr/testify/require"
@@ -531,3 +533,83 @@ func checkTxFields(
531533
assert.Equal(t, (*hexutil.Big)(tx.GatewayFee()), rpcTx.GatewayFee)
532534
assert.Equal(t, tx.GatewayFeeRecipient(), rpcTx.GatewayFeeRecipient)
533535
}
536+
537+
// Test_isCelo1Block tests isCelo1Block function to determine whether the given block time
538+
// corresponds to Celo1 chain based on the provided chain configuration
539+
func Test_isCelo1Block(t *testing.T) {
540+
cel2Time := uint64(1000)
541+
542+
t.Run("Non-Celo", func(t *testing.T) {
543+
res := isCelo1Block(&params.ChainConfig{
544+
Cel2Time: nil,
545+
}, 1000)
546+
547+
assert.False(t, res)
548+
})
549+
550+
t.Run("Celo1", func(t *testing.T) {
551+
res := isCelo1Block(&params.ChainConfig{
552+
Cel2Time: &cel2Time,
553+
}, 500)
554+
555+
assert.True(t, res)
556+
})
557+
558+
t.Run("Celo2", func(t *testing.T) {
559+
res := isCelo1Block(&params.ChainConfig{
560+
Cel2Time: &cel2Time,
561+
}, 1000)
562+
563+
assert.False(t, res)
564+
})
565+
}
566+
567+
// TestRPCMarshalBlock_Celo1TotalDifficulty tests the RPCMarshalBlock function, specifically for totalDifficulty field
568+
// It validates the result has `totalDifficulty` field only if it's Celo1 block
569+
func TestRPCMarshalBlock_Celo1TotalDifficulty(t *testing.T) {
570+
t.Parallel()
571+
572+
blockTime := uint64(1000)
573+
block := types.NewBlock(&types.Header{Number: big.NewInt(100), Time: blockTime}, &types.Body{Transactions: []*types.Transaction{}}, nil, blocktest.NewHasher())
574+
575+
marshalBlock := func(t *testing.T, config *params.ChainConfig) map[string]interface{} {
576+
t.Helper()
577+
578+
resp, err := RPCMarshalBlock(context.Background(), block, false, false, config, testBackend{})
579+
if err != nil {
580+
require.NoError(t, err)
581+
}
582+
583+
return resp
584+
}
585+
586+
t.Run("Non-Celo", func(t *testing.T) {
587+
config := *params.MainnetChainConfig
588+
589+
res := marshalBlock(t, &config)
590+
591+
assert.Equal(t, nil, res["totalDifficulty"])
592+
})
593+
594+
t.Run("Celo1", func(t *testing.T) {
595+
expected := (*hexutil.Big)(new(big.Int).Add(block.Number(), common.Big1))
596+
597+
cel2Time := blockTime + 500
598+
config := *params.MainnetChainConfig
599+
config.Cel2Time = &cel2Time
600+
601+
res := marshalBlock(t, &config)
602+
603+
assert.Equal(t, expected, res["totalDifficulty"])
604+
})
605+
606+
t.Run("Celo2", func(t *testing.T) {
607+
cel2Time := blockTime - 500
608+
config := *params.MainnetChainConfig
609+
config.Cel2Time = &cel2Time
610+
611+
res := marshalBlock(t, &config)
612+
613+
assert.Equal(t, nil, res["totalDifficulty"])
614+
})
615+
}

0 commit comments

Comments
 (0)