eth/filters, ethereum: EIP-234 add blockHash param for eth_getLogs
This commit is contained in:
parent
e8824f6e74
commit
96339daf40
@ -28,6 +28,7 @@ import (
|
|||||||
ethereum "github.com/ethereum/go-ethereum"
|
ethereum "github.com/ethereum/go-ethereum"
|
||||||
"github.com/ethereum/go-ethereum/common"
|
"github.com/ethereum/go-ethereum/common"
|
||||||
"github.com/ethereum/go-ethereum/common/hexutil"
|
"github.com/ethereum/go-ethereum/common/hexutil"
|
||||||
|
"github.com/ethereum/go-ethereum/core/rawdb"
|
||||||
"github.com/ethereum/go-ethereum/core/types"
|
"github.com/ethereum/go-ethereum/core/types"
|
||||||
"github.com/ethereum/go-ethereum/ethdb"
|
"github.com/ethereum/go-ethereum/ethdb"
|
||||||
"github.com/ethereum/go-ethereum/event"
|
"github.com/ethereum/go-ethereum/event"
|
||||||
@ -324,15 +325,35 @@ func (api *PublicFilterAPI) NewFilter(crit FilterCriteria) (rpc.ID, error) {
|
|||||||
//
|
//
|
||||||
// https://github.com/ethereum/wiki/wiki/JSON-RPC#eth_getlogs
|
// https://github.com/ethereum/wiki/wiki/JSON-RPC#eth_getlogs
|
||||||
func (api *PublicFilterAPI) GetLogs(ctx context.Context, crit FilterCriteria) ([]*types.Log, error) {
|
func (api *PublicFilterAPI) GetLogs(ctx context.Context, crit FilterCriteria) ([]*types.Log, error) {
|
||||||
|
var (
|
||||||
|
fromBlock int64
|
||||||
|
toBlock int64
|
||||||
|
)
|
||||||
|
|
||||||
|
if crit.BlockHash != nil {
|
||||||
|
// look up block number from block hash
|
||||||
|
if block := rawdb.ReadHeaderNumber(api.chainDb, *crit.BlockHash); block != nil {
|
||||||
|
// verify block is part of canonical chain
|
||||||
|
if canonical := rawdb.ReadCanonicalHash(api.chainDb, *block); canonical != *crit.BlockHash {
|
||||||
|
return nil, fmt.Errorf("Block with hash %s was removed from canonical chain", crit.BlockHash.Hex())
|
||||||
|
}
|
||||||
|
fromBlock = int64(*block)
|
||||||
|
toBlock = fromBlock
|
||||||
|
} else {
|
||||||
|
return nil, fmt.Errorf("Block with hash %s was not found", crit.BlockHash.Hex())
|
||||||
|
}
|
||||||
|
} else {
|
||||||
// Convert the RPC block numbers into internal representations
|
// Convert the RPC block numbers into internal representations
|
||||||
if crit.FromBlock == nil {
|
if crit.FromBlock == nil {
|
||||||
crit.FromBlock = big.NewInt(rpc.LatestBlockNumber.Int64())
|
fromBlock = int64(rpc.LatestBlockNumber)
|
||||||
}
|
}
|
||||||
if crit.ToBlock == nil {
|
if crit.ToBlock == nil {
|
||||||
crit.ToBlock = big.NewInt(rpc.LatestBlockNumber.Int64())
|
toBlock = int64(rpc.LatestBlockNumber)
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Create and run the filter to get all the logs
|
// Create and run the filter to get all the logs
|
||||||
filter := New(api.backend, crit.FromBlock.Int64(), crit.ToBlock.Int64(), crit.Addresses, crit.Topics)
|
filter := New(api.backend, fromBlock, toBlock, crit.Addresses, crit.Topics)
|
||||||
|
|
||||||
logs, err := filter.Logs(ctx)
|
logs, err := filter.Logs(ctx)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -444,7 +465,8 @@ func returnLogs(logs []*types.Log) []*types.Log {
|
|||||||
// UnmarshalJSON sets *args fields with given data.
|
// UnmarshalJSON sets *args fields with given data.
|
||||||
func (args *FilterCriteria) UnmarshalJSON(data []byte) error {
|
func (args *FilterCriteria) UnmarshalJSON(data []byte) error {
|
||||||
type input struct {
|
type input struct {
|
||||||
From *rpc.BlockNumber `json:"fromBlock"`
|
BlockHash *common.Hash `json:"blockHash"`
|
||||||
|
FromBlock *rpc.BlockNumber `json:"fromBlock"`
|
||||||
ToBlock *rpc.BlockNumber `json:"toBlock"`
|
ToBlock *rpc.BlockNumber `json:"toBlock"`
|
||||||
Addresses interface{} `json:"address"`
|
Addresses interface{} `json:"address"`
|
||||||
Topics []interface{} `json:"topics"`
|
Topics []interface{} `json:"topics"`
|
||||||
@ -455,13 +477,21 @@ func (args *FilterCriteria) UnmarshalJSON(data []byte) error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
if raw.From != nil {
|
if raw.BlockHash != nil {
|
||||||
args.FromBlock = big.NewInt(raw.From.Int64())
|
if raw.FromBlock != nil || raw.ToBlock != nil {
|
||||||
|
// BlockHash is mutually exclusive with FromBlock/ToBlock criteria
|
||||||
|
return fmt.Errorf("cannot specify both BlockHash and FromBlock/ToBlock, choose one or the other")
|
||||||
|
}
|
||||||
|
args.BlockHash = raw.BlockHash
|
||||||
|
} else {
|
||||||
|
if raw.FromBlock != nil {
|
||||||
|
args.FromBlock = big.NewInt(raw.FromBlock.Int64())
|
||||||
}
|
}
|
||||||
|
|
||||||
if raw.ToBlock != nil {
|
if raw.ToBlock != nil {
|
||||||
args.ToBlock = big.NewInt(raw.ToBlock.Int64())
|
args.ToBlock = big.NewInt(raw.ToBlock.Int64())
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
args.Addresses = []common.Address{}
|
args.Addresses = []common.Address{}
|
||||||
|
|
||||||
|
@ -343,6 +343,33 @@ func TestInvalidLogFilterCreation(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestInvalidGetLogsRequest(t *testing.T) {
|
||||||
|
var (
|
||||||
|
mux = new(event.TypeMux)
|
||||||
|
db = ethdb.NewMemDatabase()
|
||||||
|
txFeed = new(event.Feed)
|
||||||
|
rmLogsFeed = new(event.Feed)
|
||||||
|
logsFeed = new(event.Feed)
|
||||||
|
chainFeed = new(event.Feed)
|
||||||
|
backend = &testBackend{mux, db, 0, txFeed, rmLogsFeed, logsFeed, chainFeed}
|
||||||
|
api = NewPublicFilterAPI(backend, false)
|
||||||
|
blockHash = common.HexToHash("0x1111111111111111111111111111111111111111111111111111111111111111")
|
||||||
|
)
|
||||||
|
|
||||||
|
// Reason: Cannot specify both BlockHash and FromBlock/ToBlock)
|
||||||
|
testCases := []FilterCriteria{
|
||||||
|
0: {BlockHash: &blockHash, FromBlock: big.NewInt(100)},
|
||||||
|
1: {BlockHash: &blockHash, ToBlock: big.NewInt(500)},
|
||||||
|
2: {BlockHash: &blockHash, FromBlock: big.NewInt(rpc.LatestBlockNumber.Int64())},
|
||||||
|
}
|
||||||
|
|
||||||
|
for i, test := range testCases {
|
||||||
|
if _, err := api.GetLogs(context.Background(), test); err == nil {
|
||||||
|
t.Errorf("Expected Logs for case #%d to fail", i)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// TestLogFilter tests whether log filters match the correct logs that are posted to the event feed.
|
// TestLogFilter tests whether log filters match the correct logs that are posted to the event feed.
|
||||||
func TestLogFilter(t *testing.T) {
|
func TestLogFilter(t *testing.T) {
|
||||||
t.Parallel()
|
t.Parallel()
|
||||||
|
@ -131,6 +131,7 @@ type ContractCaller interface {
|
|||||||
|
|
||||||
// FilterQuery contains options for contract log filtering.
|
// FilterQuery contains options for contract log filtering.
|
||||||
type FilterQuery struct {
|
type FilterQuery struct {
|
||||||
|
BlockHash *common.Hash // used by eth_getLogs, return logs only from block with this hash
|
||||||
FromBlock *big.Int // beginning of the queried range, nil means genesis block
|
FromBlock *big.Int // beginning of the queried range, nil means genesis block
|
||||||
ToBlock *big.Int // end of the range, nil means latest block
|
ToBlock *big.Int // end of the range, nil means latest block
|
||||||
Addresses []common.Address // restricts matches to events created by specific contracts
|
Addresses []common.Address // restricts matches to events created by specific contracts
|
||||||
|
Loading…
Reference in New Issue
Block a user