Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: introduce safe and finalized as block number filters #412

Merged
merged 2 commits into from
Oct 30, 2024
Merged
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
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