mirror of
https://github.com/ethereum/go-ethereum.git
synced 2026-08-19 18:32:23 +00:00
Add support for logs
This commit is contained in:
parent
d92e373123
commit
b235d18367
1 changed files with 133 additions and 1 deletions
|
|
@ -31,6 +31,7 @@ import (
|
||||||
"github.com/ethereum/go-ethereum/core/types"
|
"github.com/ethereum/go-ethereum/core/types"
|
||||||
"github.com/ethereum/go-ethereum/core/vm"
|
"github.com/ethereum/go-ethereum/core/vm"
|
||||||
"github.com/ethereum/go-ethereum/eth"
|
"github.com/ethereum/go-ethereum/eth"
|
||||||
|
"github.com/ethereum/go-ethereum/eth/filters"
|
||||||
"github.com/ethereum/go-ethereum/internal/ethapi"
|
"github.com/ethereum/go-ethereum/internal/ethapi"
|
||||||
"github.com/ethereum/go-ethereum/log"
|
"github.com/ethereum/go-ethereum/log"
|
||||||
"github.com/ethereum/go-ethereum/node"
|
"github.com/ethereum/go-ethereum/node"
|
||||||
|
|
@ -41,7 +42,7 @@ import (
|
||||||
"github.com/graph-gophers/graphql-go/relay"
|
"github.com/graph-gophers/graphql-go/relay"
|
||||||
)
|
)
|
||||||
|
|
||||||
func getBackend(n *node.Node) (ethapi.Backend, error) {
|
func getBackend(n *node.Node) (*eth.EthAPIBackend, error) {
|
||||||
var ethereum *eth.Ethereum
|
var ethereum *eth.Ethereum
|
||||||
if err := n.Service(ðereum); err != nil {
|
if err := n.Service(ðereum); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
|
|
@ -682,6 +683,72 @@ func (b *Block) OmmerAt(ctx context.Context, args ArrayIndexArgs) (*Block, error
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type BlockFilterCriteria struct {
|
||||||
|
Addresses *[]common.Address // restricts matches to events created by specific contracts
|
||||||
|
|
||||||
|
// The Topic list restricts matches to particular event topics. Each event has a list
|
||||||
|
// of topics. Topics matches a prefix of that list. An empty element slice matches any
|
||||||
|
// topic. Non-empty elements represent an alternative that matches any of the
|
||||||
|
// contained topics.
|
||||||
|
//
|
||||||
|
// Examples:
|
||||||
|
// {} or nil matches any topic list
|
||||||
|
// {{A}} matches topic A in first position
|
||||||
|
// {{}, {B}} matches any topic in first position, B in second position
|
||||||
|
// {{A}, {B}} matches topic A in first position, B in second position
|
||||||
|
// {{A, B}}, {C, D}} matches topic (A OR B) in first position, (C OR D) in second position
|
||||||
|
Topics *[][]common.Hash
|
||||||
|
}
|
||||||
|
|
||||||
|
func runFilter(ctx context.Context, node *node.Node, filter *filters.Filter) ([]*Log, error) {
|
||||||
|
logs, err := filter.Logs(ctx)
|
||||||
|
if err != nil || logs == nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
ret := make([]*Log, 0, len(logs))
|
||||||
|
for _, log := range logs {
|
||||||
|
ret = append(ret, &Log{
|
||||||
|
node: node,
|
||||||
|
transaction: &Transaction{hash: log.TxHash},
|
||||||
|
log: log,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
return ret, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (b *Block) Logs(ctx context.Context, args struct{ Filter BlockFilterCriteria }) ([]*Log, error) {
|
||||||
|
be, err := getBackend(b.node)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
var addresses []common.Address
|
||||||
|
if args.Filter.Addresses != nil {
|
||||||
|
addresses = *args.Filter.Addresses
|
||||||
|
}
|
||||||
|
|
||||||
|
var topics [][]common.Hash
|
||||||
|
if args.Filter.Topics != nil {
|
||||||
|
topics = *args.Filter.Topics
|
||||||
|
}
|
||||||
|
|
||||||
|
hash := b.hash
|
||||||
|
if hash == (common.Hash{}) {
|
||||||
|
block, err := b.resolve(ctx)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
hash = block.Hash()
|
||||||
|
}
|
||||||
|
|
||||||
|
// Construct the range filter
|
||||||
|
filter := filters.NewBlockFilter(be, hash, addresses, topics)
|
||||||
|
|
||||||
|
// Run the filter and return all the logs
|
||||||
|
return runFilter(ctx, b.node, filter)
|
||||||
|
}
|
||||||
|
|
||||||
type Resolver struct {
|
type Resolver struct {
|
||||||
node *node.Node
|
node *node.Node
|
||||||
}
|
}
|
||||||
|
|
@ -880,6 +947,57 @@ func (r *Resolver) EstimateGas(ctx context.Context, args struct {
|
||||||
return hexutil.Uint64(gas), err
|
return hexutil.Uint64(gas), err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type FilterCriteria struct {
|
||||||
|
FromBlock *hexutil.Uint64 // beginning of the queried range, nil means genesis block
|
||||||
|
ToBlock *hexutil.Uint64 // end of the range, nil means latest block
|
||||||
|
Addresses *[]common.Address // restricts matches to events created by specific contracts
|
||||||
|
|
||||||
|
// The Topic list restricts matches to particular event topics. Each event has a list
|
||||||
|
// of topics. Topics matches a prefix of that list. An empty element slice matches any
|
||||||
|
// topic. Non-empty elements represent an alternative that matches any of the
|
||||||
|
// contained topics.
|
||||||
|
//
|
||||||
|
// Examples:
|
||||||
|
// {} or nil matches any topic list
|
||||||
|
// {{A}} matches topic A in first position
|
||||||
|
// {{}, {B}} matches any topic in first position, B in second position
|
||||||
|
// {{A}, {B}} matches topic A in first position, B in second position
|
||||||
|
// {{A, B}}, {C, D}} matches topic (A OR B) in first position, (C OR D) in second position
|
||||||
|
Topics *[][]common.Hash
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *Resolver) Logs(ctx context.Context, args struct{ Filter FilterCriteria }) ([]*Log, error) {
|
||||||
|
be, err := getBackend(r.node)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// Convert the RPC block numbers into internal representations
|
||||||
|
begin := rpc.LatestBlockNumber.Int64()
|
||||||
|
if args.Filter.FromBlock != nil {
|
||||||
|
begin = int64(*args.Filter.FromBlock)
|
||||||
|
}
|
||||||
|
end := rpc.LatestBlockNumber.Int64()
|
||||||
|
if args.Filter.ToBlock != nil {
|
||||||
|
end = int64(*args.Filter.ToBlock)
|
||||||
|
}
|
||||||
|
|
||||||
|
var addresses []common.Address
|
||||||
|
if args.Filter.Addresses != nil {
|
||||||
|
addresses = *args.Filter.Addresses
|
||||||
|
}
|
||||||
|
|
||||||
|
var topics [][]common.Hash
|
||||||
|
if args.Filter.Topics != nil {
|
||||||
|
topics = *args.Filter.Topics
|
||||||
|
}
|
||||||
|
|
||||||
|
// Construct the range filter
|
||||||
|
filter := filters.NewRangeFilter(filters.Backend(be), begin, end, addresses, topics)
|
||||||
|
|
||||||
|
return runFilter(ctx, r.node, filter)
|
||||||
|
}
|
||||||
|
|
||||||
func NewHandler(n *node.Node) (http.Handler, error) {
|
func NewHandler(n *node.Node) (http.Handler, error) {
|
||||||
q := Resolver{n}
|
q := Resolver{n}
|
||||||
|
|
||||||
|
|
@ -930,6 +1048,11 @@ func NewHandler(n *node.Node) (http.Handler, error) {
|
||||||
logs: [Log!]
|
logs: [Log!]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
input BlockFilterCriteria {
|
||||||
|
addresses: [Address!]
|
||||||
|
topics: [[Bytes32!]!]
|
||||||
|
}
|
||||||
|
|
||||||
type Block {
|
type Block {
|
||||||
number: Long!
|
number: Long!
|
||||||
hash: Bytes32!
|
hash: Bytes32!
|
||||||
|
|
@ -954,6 +1077,7 @@ func NewHandler(n *node.Node) (http.Handler, error) {
|
||||||
ommerHash: Bytes32!
|
ommerHash: Bytes32!
|
||||||
transactions: [Transaction!]!
|
transactions: [Transaction!]!
|
||||||
transactionAt(index: Int!): Transaction
|
transactionAt(index: Int!): Transaction
|
||||||
|
logs(filter: BlockFilterCriteria!): [Log!]!
|
||||||
}
|
}
|
||||||
|
|
||||||
input CallData {
|
input CallData {
|
||||||
|
|
@ -971,6 +1095,13 @@ func NewHandler(n *node.Node) (http.Handler, error) {
|
||||||
status: Long!
|
status: Long!
|
||||||
}
|
}
|
||||||
|
|
||||||
|
input FilterCriteria {
|
||||||
|
fromBlock: Long
|
||||||
|
toBlock: Long
|
||||||
|
addresses: [Address!]
|
||||||
|
topics: [[Bytes32!]!]
|
||||||
|
}
|
||||||
|
|
||||||
type Query {
|
type Query {
|
||||||
account(address: Address!, blockNumber: Long): Account!
|
account(address: Address!, blockNumber: Long): Account!
|
||||||
block(number: Long, hash: Bytes32): Block
|
block(number: Long, hash: Bytes32): Block
|
||||||
|
|
@ -978,6 +1109,7 @@ func NewHandler(n *node.Node) (http.Handler, error) {
|
||||||
transaction(hash: Bytes32!): Transaction
|
transaction(hash: Bytes32!): Transaction
|
||||||
call(data: CallData!, blockNumber: Long): CallResult
|
call(data: CallData!, blockNumber: Long): CallResult
|
||||||
estimateGas(data: CallData!, blockNumber: Long): Long!
|
estimateGas(data: CallData!, blockNumber: Long): Long!
|
||||||
|
logs(filter: FilterCriteria!): [Log!]!
|
||||||
}
|
}
|
||||||
|
|
||||||
type Mutation {
|
type Mutation {
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue