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

Problem: gasUsed, gasLimit and bloom are not aligned in subscribe newHeads #544

Draft
wants to merge 2 commits into
base: develop
Choose a base branch
from
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
30 changes: 4 additions & 26 deletions rpc/backend/blocks.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@
package backend

import (
"bytes"
"fmt"
"math/big"
"strconv"
Expand Down Expand Up @@ -397,18 +396,7 @@

// BlockBloom query block bloom filter from block results
func (b *Backend) BlockBloom(blockRes *tmrpctypes.ResultBlockResults) (ethtypes.Bloom, error) {
for _, event := range blockRes.FinalizeBlockEvents {
if event.Type != evmtypes.EventTypeBlockBloom {
continue
}

for _, attr := range event.Attributes {
if bytes.Equal([]byte(attr.Key), bAttributeKeyEthereumBloom) {
return ethtypes.BytesToBloom([]byte(attr.Value)), nil
}
}
}
return ethtypes.Bloom{}, errors.New("block bloom event is not found")
return GetBlockBloom(blockRes)
}

// RPCBlockFromTendermintBlock returns a JSON-RPC compatible Ethereum block from a
Expand Down Expand Up @@ -491,20 +479,10 @@
b.logger.Error("failed to query consensus params", "error", err.Error())
}

var gasUsed uint64
for _, txsResult := range blockRes.TxsResults {
// workaround for cosmos-sdk bug. https://github.com/cosmos/cosmos-sdk/issues/10832
if ShouldIgnoreGasUsed(txsResult) {
// block gas limit has exceeded, other txs must have failed with same reason.
break
}
gas, err := ethermint.SafeUint64(txsResult.GetGasUsed())
if err != nil {
return nil, err
}
gasUsed += gas
gasUsed, err := GetGasUsed(blockRes)
if err != nil {
return nil, err

Check warning on line 484 in rpc/backend/blocks.go

View check run for this annotation

Codecov / codecov/patch

rpc/backend/blocks.go#L484

Added line #L484 was not covered by tests
}

formattedBlock := rpctypes.FormatBlock(
block.Header, block.Size(),
gasLimit, new(big.Int).SetUint64(gasUsed),
Expand Down
33 changes: 33 additions & 0 deletions rpc/backend/utils.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
package backend

import (
"bytes"
"fmt"
"math/big"
"sort"
Expand Down Expand Up @@ -339,3 +340,35 @@
}
return sdk.AccAddressFromBech32(res.AccountAddress)
}

func GetBlockBloom(blockRes *tmrpctypes.ResultBlockResults) (ethtypes.Bloom, error) {
for _, event := range blockRes.FinalizeBlockEvents {
if event.Type != evmtypes.EventTypeBlockBloom {
continue
}

for _, attr := range event.Attributes {
if bytes.Equal([]byte(attr.Key), bAttributeKeyEthereumBloom) {
return ethtypes.BytesToBloom([]byte(attr.Value)), nil
}
}
}
return ethtypes.Bloom{}, errors.New("block bloom event is not found")
}

func GetGasUsed(blockRes *tmrpctypes.ResultBlockResults) (uint64, error) {
var gasUsed uint64
for _, txsResult := range blockRes.TxsResults {
// workaround for cosmos-sdk bug. https://github.com/cosmos/cosmos-sdk/issues/10832
if ShouldIgnoreGasUsed(txsResult) {
// block gas limit has exceeded, other txs must have failed with same reason.
break
}
gas, err := ethermint.SafeUint64(txsResult.GetGasUsed())
if err != nil {
return 0, err
}

Check warning on line 370 in rpc/backend/utils.go

View check run for this annotation

Codecov / codecov/patch

rpc/backend/utils.go#L369-L370

Added lines #L369 - L370 were not covered by tests
gasUsed += gas
}
return gasUsed, nil
}
58 changes: 46 additions & 12 deletions rpc/stream/rpc.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,16 @@

"cosmossdk.io/log"
cmtquery "github.com/cometbft/cometbft/libs/pubsub/query"
rpcclient "github.com/cometbft/cometbft/rpc/client"

Check failure on line 10 in rpc/stream/rpc.go

View workflow job for this annotation

GitHub Actions / Run golangci-lint

ST1019: package "github.com/cometbft/cometbft/rpc/client" is being imported more than once (stylecheck)
tmrpcclient "github.com/cometbft/cometbft/rpc/client"

Check failure on line 11 in rpc/stream/rpc.go

View workflow job for this annotation

GitHub Actions / Run golangci-lint

ST1019(related information): other import of "github.com/cometbft/cometbft/rpc/client" (stylecheck)
coretypes "github.com/cometbft/cometbft/rpc/core/types"
tmtypes "github.com/cometbft/cometbft/types"
"github.com/cosmos/cosmos-sdk/client"
sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/ethereum/go-ethereum/common"
ethtypes "github.com/ethereum/go-ethereum/core/types"
"github.com/evmos/ethermint/rpc/types"
"github.com/evmos/ethermint/rpc/backend"
rpctypes "github.com/evmos/ethermint/rpc/types"
ethermint "github.com/evmos/ethermint/types"
evmtypes "github.com/evmos/ethermint/x/evm/types"
"google.golang.org/grpc"
Expand Down Expand Up @@ -54,7 +57,7 @@
type RPCStream struct {
evtClient rpcclient.EventsClient
logger log.Logger
txDecoder sdk.TxDecoder
clientCtx client.Context

headerStream *Stream[RPCHeader]
pendingTxStream *Stream[common.Hash]
Expand All @@ -67,14 +70,13 @@
func NewRPCStreams(
evtClient rpcclient.EventsClient,
logger log.Logger,
txDecoder sdk.TxDecoder,
clientCtx client.Context,
validatorAccount validatorAccountFunc,
) (*RPCStream, error) {
s := &RPCStream{
evtClient: evtClient,
logger: logger,
txDecoder: txDecoder,

evtClient: evtClient,
logger: logger,
clientCtx: clientCtx,

Check warning on line 79 in rpc/stream/rpc.go

View check run for this annotation

Codecov / codecov/patch

rpc/stream/rpc.go#L77-L79

Added lines #L77 - L79 were not covered by tests
headerStream: NewStream[RPCHeader](headerStreamSegmentSize, headerStreamCapacity),
pendingTxStream: NewStream[common.Hash](txStreamSegmentSize, txStreamCapacity),
logStream: NewStream[*ethtypes.Log](logStreamSegmentSize, logStreamCapacity),
Expand Down Expand Up @@ -153,9 +155,9 @@
continue
}

baseFee := types.BaseFeeFromEvents(data.ResultFinalizeBlock.Events)
baseFee := rpctypes.BaseFeeFromEvents(data.ResultFinalizeBlock.Events)

Check warning on line 158 in rpc/stream/rpc.go

View check run for this annotation

Codecov / codecov/patch

rpc/stream/rpc.go#L158

Added line #L158 was not covered by tests
res, err := s.validatorAccount(
types.ContextWithHeight(data.Block.Height),
rpctypes.ContextWithHeight(data.Block.Height),

Check warning on line 160 in rpc/stream/rpc.go

View check run for this annotation

Codecov / codecov/patch

rpc/stream/rpc.go#L160

Added line #L160 was not covered by tests
&evmtypes.QueryValidatorAccountRequest{
ConsAddress: sdk.ConsAddress(data.Block.Header.ProposerAddress).String(),
},
Expand All @@ -169,10 +171,42 @@
s.logger.Error("failed to convert validator account", "err", err)
continue
}
// TODO: fetch bloom from events
header := types.EthHeaderFromTendermint(data.Block.Header, ethtypes.Bloom{}, baseFee, validator)
height := data.Block.Header.Height
ctx := rpctypes.ContextWithHeight(height)
gasLimit, err := rpctypes.BlockMaxGasFromConsensusParams(ctx, s.clientCtx, height)
if err != nil {
s.logger.Error("failed to query consensus params", "error", err.Error())
continue

Check warning on line 179 in rpc/stream/rpc.go

View check run for this annotation

Codecov / codecov/patch

rpc/stream/rpc.go#L174-L179

Added lines #L174 - L179 were not covered by tests
}
sc, ok := s.clientCtx.Client.(tmrpcclient.SignClient)
if !ok {
fmt.Println("failed to fetch block result from Tendermint", "height", height, "error", "invalid rpc client")
continue

Check warning on line 184 in rpc/stream/rpc.go

View check run for this annotation

Codecov / codecov/patch

rpc/stream/rpc.go#L181-L184

Added lines #L181 - L184 were not covered by tests
}
blockRes, err := sc.BlockResults(ctx, &height)
if err != nil {
s.logger.Error("failed to fetch block result from Tendermint", "height", height, "error", err.Error())
continue

Check warning on line 189 in rpc/stream/rpc.go

View check run for this annotation

Codecov / codecov/patch

rpc/stream/rpc.go#L186-L189

Added lines #L186 - L189 were not covered by tests
}
gasUsed, err := backend.GetGasUsed(blockRes)
if err != nil {
s.logger.Error("failed to get gasUsed", "height", height, "error", err.Error())
continue

Check warning on line 194 in rpc/stream/rpc.go

View check run for this annotation

Codecov / codecov/patch

rpc/stream/rpc.go#L191-L194

Added lines #L191 - L194 were not covered by tests
}
bloom, err := backend.GetBlockBloom(blockRes)
if err != nil {
s.logger.Error("HeaderByHash BlockBloom failed", "height", height, "error", err.Error())
continue

Check warning on line 199 in rpc/stream/rpc.go

View check run for this annotation

Codecov / codecov/patch

rpc/stream/rpc.go#L196-L199

Added lines #L196 - L199 were not covered by tests
}
header := rpctypes.EthHeaderFromTendermint(data.Block.Header, bloom, baseFee, validator)
limit, err := ethermint.SafeUint64(gasLimit)
if err != nil {
s.logger.Error("invalid gasLimit", "height", height, "error", err.Error())
continue

Check warning on line 205 in rpc/stream/rpc.go

View check run for this annotation

Codecov / codecov/patch

rpc/stream/rpc.go#L201-L205

Added lines #L201 - L205 were not covered by tests
}
header.GasLimit = limit
header.GasUsed = gasUsed

Check warning on line 208 in rpc/stream/rpc.go

View check run for this annotation

Codecov / codecov/patch

rpc/stream/rpc.go#L207-L208

Added lines #L207 - L208 were not covered by tests
s.headerStream.Add(RPCHeader{EthHeader: header, Hash: common.BytesToHash(data.Block.Header.Hash())})

case ev, ok := <-chLogs:
if !ok {
chLogs = nil
Expand Down
2 changes: 1 addition & 1 deletion server/json_rpc.go
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@
var err error
queryClient := rpctypes.NewQueryClient(clientCtx)
for i := 0; i < MaxRetry; i++ {
rpcStream, err = stream.NewRPCStreams(evtClient, logger, clientCtx.TxConfig.TxDecoder(), queryClient.ValidatorAccount)
rpcStream, err = stream.NewRPCStreams(evtClient, logger, clientCtx, queryClient.ValidatorAccount)

Check warning on line 71 in server/json_rpc.go

View check run for this annotation

Codecov / codecov/patch

server/json_rpc.go#L71

Added line #L71 was not covered by tests
if err == nil {
break
}
Expand Down
14 changes: 11 additions & 3 deletions tests/integration_tests/test_websockets.py
Original file line number Diff line number Diff line change
Expand Up @@ -108,9 +108,17 @@ async def subscriber_test(c: Client, w3):
assert int(msgs[1]["number"], 0) == int(msgs[0]["number"], 0) + 1
assert int(msgs[2]["number"], 0) == int(msgs[1]["number"], 0) + 1
for msg in msgs:
b = w3.eth.get_block(msg["number"])
assert HexBytes(msg["hash"]) == b["hash"]
assert msg["miner"] == b["miner"]
b = w3.provider.make_request(
"eth_getBlockByNumber", [msg["number"], True]
)["result"]
for key in b:
if not msg.get(key):
continue
if key == "miner":
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

eq = msg[key].lower() == b[key]
else:
eq = msg[key] == b[key]
assert eq, key
await assert_unsubscribe(c, sub_id)

async def logs_test(c: Client, w3, contract):
Expand Down
Loading