Skip to content

Commit

Permalink
feat: introduce safe and finalized as block number filters (#412)
Browse files Browse the repository at this point in the history
* feat: introduce safe and finalized as block number filtes

* address comment
  • Loading branch information
Stefan-Ethernal authored Oct 30, 2024
1 parent 55b7239 commit a044bd1
Show file tree
Hide file tree
Showing 5 changed files with 111 additions and 23 deletions.
12 changes: 12 additions & 0 deletions e2e-polybft/e2e/jsonrpc_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,18 @@ func TestE2E_JsonRPC(t *testing.T) {
// since we asked for the full block, and epoch ending block has a transaction
require.Equal(t, 1, len(blockByHash.Transactions))

// get safe block (act as the latest, because of the instant finality)
safeBlock, err := ethClient.GetBlockByNumber(jsonrpc.SafeBlockNumber, false)
require.NoError(t, err)
require.NotNil(t, safeBlock)
require.GreaterOrEqual(t, safeBlock.Number(), epochSize)

// get finalized block (act as the latest, because of the instant finality)
finalizedBlock, err := ethClient.GetBlockByNumber(jsonrpc.FinalizedBlockNumber, false)
require.NoError(t, err)
require.NotNil(t, finalizedBlock)
require.GreaterOrEqual(t, finalizedBlock.Number(), epochSize)

// get latest block
latestBlock, err := ethClient.GetBlockByNumber(jsonrpc.LatestBlockNumber, false)
require.NoError(t, err)
Expand Down
62 changes: 41 additions & 21 deletions jsonrpc/codec.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,12 +10,18 @@ import (
)

func init() {
pendingBN := PendingBlockNumber
PendingBlockNumberOrHash = BlockNumberOrHash{BlockNumber: &pendingBN}
safeBN := SafeBlockNumber
SafeBlockNumberOrHash = BlockNumberOrHash{BlockNumber: &safeBN}

finalizedBN := FinalizedBlockNumber
FinalizedBlockNumberOrHash = BlockNumberOrHash{BlockNumber: &finalizedBN}

latestBN := LatestBlockNumber
LatestBlockNumberOrHash = BlockNumberOrHash{BlockNumber: &latestBN}

pendingBN := PendingBlockNumber
PendingBlockNumberOrHash = BlockNumberOrHash{BlockNumber: &pendingBN}

earliestBN := EarliestBlockNumber
EarliestBlockNumberOrHash = BlockNumberOrHash{BlockNumber: &earliestBN}
}
Expand Down Expand Up @@ -127,32 +133,42 @@ func (e *ObjectError) MarshalJSON() ([]byte, error) {
}

const (
pending = "pending"
latest = "latest"
earliest = "earliest"
safe = "safe"
finalized = "finalized"
latest = "latest"
pending = "pending"
earliest = "earliest"
)

const (
PendingBlockNumber = BlockNumber(-3)
LatestBlockNumber = BlockNumber(-2)
EarliestBlockNumber = BlockNumber(-1)
SafeBlockNumber = BlockNumber(-4)
FinalizedBlockNumber = BlockNumber(-3)
LatestBlockNumber = BlockNumber(-2)
PendingBlockNumber = BlockNumber(-1)
EarliestBlockNumber = BlockNumber(0)
)

var (
PendingBlockNumberOrHash BlockNumberOrHash
LatestBlockNumberOrHash BlockNumberOrHash
EarliestBlockNumberOrHash BlockNumberOrHash
SafeBlockNumberOrHash BlockNumberOrHash
FinalizedBlockNumberOrHash BlockNumberOrHash
LatestBlockNumberOrHash BlockNumberOrHash
PendingBlockNumberOrHash BlockNumberOrHash
EarliestBlockNumberOrHash BlockNumberOrHash
)

type BlockNumber int64

// String returns the string representation of the block number
func (b BlockNumber) String() string {
switch b {
case PendingBlockNumber:
return pending
case SafeBlockNumber:
return safe
case FinalizedBlockNumber:
return finalized
case LatestBlockNumber:
return latest
case PendingBlockNumber:
return pending
case EarliestBlockNumber:
return earliest
}
Expand Down Expand Up @@ -231,10 +247,14 @@ func stringToBlockNumber(str string) (BlockNumber, error) {

str = strings.Trim(str, "\"")
switch str {
case pending:
return PendingBlockNumber, nil
case safe:
return SafeBlockNumber, nil
case finalized:
return FinalizedBlockNumber, nil
case latest:
return LatestBlockNumber, nil
case pending:
return PendingBlockNumber, nil
case earliest:
return EarliestBlockNumber, nil
}
Expand Down Expand Up @@ -269,11 +289,11 @@ func (b *BlockNumber) UnmarshalJSON(buffer []byte) error {
}

// NewRPCErrorResponse is used to create a custom error response
func NewRPCErrorResponse(id interface{}, errCode int, err string, data []byte, jsonrpcver string) Response {
errObject := &ObjectError{errCode, err, data}
func NewRPCErrorResponse(id interface{}, errCode int, err string, data []byte, jsonRPCVersion string) Response {
errObject := &ObjectError{Code: errCode, Message: err, Data: data}

response := &ErrorResponse{
JSONRPC: jsonrpcver,
JSONRPC: jsonRPCVersion,
ID: id,
Error: errObject,
}
Expand All @@ -282,13 +302,13 @@ func NewRPCErrorResponse(id interface{}, errCode int, err string, data []byte, j
}

// NewRPCResponse returns Success/Error response object
func NewRPCResponse(id interface{}, jsonrpcver string, reply []byte, err Error) Response {
func NewRPCResponse(id interface{}, jsonRPCVersion string, reply []byte, err Error) Response {
var response Response
switch err.(type) {
case nil:
response = &SuccessResponse{JSONRPC: jsonrpcver, ID: id, Result: reply}
response = &SuccessResponse{JSONRPC: jsonRPCVersion, ID: id, Result: reply}
default:
response = NewRPCErrorResponse(id, err.ErrorCode(), err.Error(), reply, jsonrpcver)
response = NewRPCErrorResponse(id, err.ErrorCode(), err.Error(), reply, jsonRPCVersion)
}

return response
Expand Down
18 changes: 18 additions & 0 deletions jsonrpc/codec_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@ func TestBlockNumberOrHash_UnmarshalJSON(t *testing.T) {
assert.NoError(t, err)

blockNumberZero := BlockNumber(0x0)
blockNumberSafe := SafeBlockNumber
blockNumberFinalized := FinalizedBlockNumber
blockNumberLatest := LatestBlockNumber
blockNumberPending := PendingBlockNumber

Expand Down Expand Up @@ -51,6 +53,22 @@ func TestBlockNumberOrHash_UnmarshalJSON(t *testing.T) {
true,
BlockNumberOrHash{},
},
{
"should unmarshal safe block number properly",
`"safe"`,
false,
BlockNumberOrHash{
BlockNumber: &blockNumberSafe,
},
},
{
"should unmarshal finalized block number properly",
`"finalized"`,
false,
BlockNumberOrHash{
BlockNumber: &blockNumberFinalized,
},
},
{
"should unmarshal latest block number properly",
`"latest"`,
Expand Down
16 changes: 14 additions & 2 deletions jsonrpc/helper.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,13 @@ type latestHeaderGetter interface {
// GetNumericBlockNumber returns block number based on current state or specified number
func GetNumericBlockNumber(number BlockNumber, store latestHeaderGetter) (uint64, error) {
switch number {
case LatestBlockNumber, PendingBlockNumber:
case SafeBlockNumber:
fallthrough
case FinalizedBlockNumber:
fallthrough
case LatestBlockNumber:
fallthrough
case PendingBlockNumber:
latest := store.Header()
if latest == nil {
return 0, ErrLatestNotFound
Expand Down Expand Up @@ -74,7 +80,13 @@ type headerGetter interface {
// GetBlockHeader returns a header using the provided number
func GetBlockHeader(number BlockNumber, store headerGetter) (*types.Header, error) {
switch number {
case PendingBlockNumber, LatestBlockNumber:
case SafeBlockNumber:
fallthrough
case FinalizedBlockNumber:
fallthrough
case LatestBlockNumber:
fallthrough
case PendingBlockNumber:
return store.Header(), nil

case EarliestBlockNumber:
Expand Down
26 changes: 26 additions & 0 deletions jsonrpc/helper_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -127,6 +127,32 @@ func TestGetNumericBlockNumber(t *testing.T) {
expected: 10,
err: nil,
},
{
name: "should return the latest block's number for finalized block",
num: FinalizedBlockNumber,
store: &debugEndpointMockStore{
headerFn: func() *types.Header {
return &types.Header{
Number: 10,
}
},
},
expected: 10,
err: nil,
},
{
name: "should return the latest block's number for safe block",
num: SafeBlockNumber,
store: &debugEndpointMockStore{
headerFn: func() *types.Header {
return &types.Header{
Number: 20,
}
},
},
expected: 20,
err: nil,
},
{
name: "should return error if the latest block's number is not found",
num: LatestBlockNumber,
Expand Down

0 comments on commit a044bd1

Please sign in to comment.