diff --git a/hmy/blockchain.go b/hmy/blockchain.go index c7838020b..dd5ef0d66 100644 --- a/hmy/blockchain.go +++ b/hmy/blockchain.go @@ -308,11 +308,20 @@ func (hmy *Harmony) GetLeaderAddress(coinbaseAddr common.Address, epoch *big.Int // Filter related APIs // GetLogs ... -func (hmy *Harmony) GetLogs(ctx context.Context, blockHash common.Hash) ([][]*types.Log, error) { +func (hmy *Harmony) GetLogs(ctx context.Context, blockHash common.Hash, isEth bool) ([][]*types.Log, error) { receipts := hmy.BlockChain.GetReceiptsByHash(blockHash) if receipts == nil { return nil, errors.New("Missing receipts") } + if isEth { + for i, _ := range receipts { + for j, _ := range receipts[i].Logs { + // Override log txHash with receipt's + receipts[i].Logs[j].TxHash = receipts[i].TxHash + } + } + } + logs := make([][]*types.Log, len(receipts)) for i, receipt := range receipts { logs[i] = receipt.Logs diff --git a/rpc/eth/types.go b/rpc/eth/types.go index c88c3ef64..d8dc79627 100644 --- a/rpc/eth/types.go +++ b/rpc/eth/types.go @@ -112,10 +112,16 @@ func NewReceipt(tx *types.EthTransaction, blockHash common.Hash, blockNumber, bl return nil, err } + ethTxHash := tx.Hash() + for i, _ := range receipt.Logs { + // Override log txHash with receipt's + receipt.Logs[i].TxHash = ethTxHash + } + fields := map[string]interface{}{ "blockHash": blockHash, "blockNumber": hexutil.Uint64(blockNumber), - "transactionHash": tx.Hash(), + "transactionHash": ethTxHash, "transactionIndex": hexutil.Uint64(blockIndex), "from": senderAddr, "to": tx.To(), diff --git a/rpc/filters/api.go b/rpc/filters/api.go index 0a4ae2aff..ef5805c97 100644 --- a/rpc/filters/api.go +++ b/rpc/filters/api.go @@ -37,14 +37,16 @@ type PublicFilterAPI struct { events *EventSystem filtersMu sync.Mutex filters map[rpc.ID]*filter + namespace string } // NewPublicFilterAPI returns a new PublicFilterAPI instance. func NewPublicFilterAPI(backend Backend, lightMode bool, namespace string) rpc.API { api := &PublicFilterAPI{ - backend: backend, - events: NewEventSystem(backend, lightMode), - filters: make(map[rpc.ID]*filter), + backend: backend, + events: NewEventSystem(backend, lightMode, namespace == "eth"), + filters: make(map[rpc.ID]*filter), + namespace: namespace, } go api.timeoutLoop() @@ -56,6 +58,10 @@ func NewPublicFilterAPI(backend Backend, lightMode bool, namespace string) rpc.A } } +func (api *PublicFilterAPI) isEth() bool { + return api.namespace == "eth" +} + // timeoutLoop runs every 5 minutes and deletes filters that have not been recently used. // Tt is started when the api is created. func (api *PublicFilterAPI) timeoutLoop() { @@ -357,7 +363,7 @@ func (api *PublicFilterAPI) GetLogs(ctx context.Context, crit FilterCriteria) ([ var filter *Filter if crit.BlockHash != nil { // Block filter requested, construct a single-shot filter - filter = NewBlockFilter(api.backend, *crit.BlockHash, crit.Addresses, crit.Topics) + filter = NewBlockFilter(api.backend, *crit.BlockHash, crit.Addresses, crit.Topics, api.isEth()) } else { // Convert the RPC block numbers into internal representations begin := rpc.LatestBlockNumber.Int64() @@ -369,7 +375,7 @@ func (api *PublicFilterAPI) GetLogs(ctx context.Context, crit FilterCriteria) ([ end = crit.ToBlock.Int64() } // Construct the range filter - filter = NewRangeFilter(api.backend, begin, end, crit.Addresses, crit.Topics) + filter = NewRangeFilter(api.backend, begin, end, crit.Addresses, crit.Topics, api.isEth()) } // Run the filter and return all the logs logs, err := filter.Logs(ctx) @@ -412,7 +418,7 @@ func (api *PublicFilterAPI) GetFilterLogs(ctx context.Context, id rpc.ID) ([]*ty var filter *Filter if f.crit.BlockHash != nil { // Block filter requested, construct a single-shot filter - filter = NewBlockFilter(api.backend, *f.crit.BlockHash, f.crit.Addresses, f.crit.Topics) + filter = NewBlockFilter(api.backend, *f.crit.BlockHash, f.crit.Addresses, f.crit.Topics, api.isEth()) } else { // Convert the RPC block numbers into internal representations begin := rpc.LatestBlockNumber.Int64() @@ -424,7 +430,7 @@ func (api *PublicFilterAPI) GetFilterLogs(ctx context.Context, id rpc.ID) ([]*ty end = f.crit.ToBlock.Int64() } // Construct the range filter - filter = NewRangeFilter(api.backend, begin, end, f.crit.Addresses, f.crit.Topics) + filter = NewRangeFilter(api.backend, begin, end, f.crit.Addresses, f.crit.Topics, api.isEth()) } // Run the filter and return all the logs logs, err := filter.Logs(ctx) diff --git a/rpc/filters/filter.go b/rpc/filters/filter.go index fa4ab2d96..d6ad24245 100644 --- a/rpc/filters/filter.go +++ b/rpc/filters/filter.go @@ -39,7 +39,7 @@ type Backend interface { HeaderByNumber(ctx context.Context, blockNum rpc.BlockNumber) (*block.Header, error) HeaderByHash(ctx context.Context, blockHash common.Hash) (*block.Header, error) GetReceipts(ctx context.Context, blockHash common.Hash) (types.Receipts, error) - GetLogs(ctx context.Context, blockHash common.Hash) ([][]*types.Log, error) + GetLogs(ctx context.Context, blockHash common.Hash, isEth bool) ([][]*types.Log, error) SubscribeNewTxsEvent(chan<- core.NewTxsEvent) event.Subscription SubscribeChainEvent(ch chan<- core.ChainEvent) event.Subscription @@ -62,11 +62,12 @@ type Filter struct { begin, end int64 // Range interval if filtering multiple blocks matcher *bloombits.Matcher + isEth bool // Whether this is used for eth_ rpc. } // NewRangeFilter creates a new filter which uses a bloom filter on blocks to // figure out whether a particular block is interesting or not. -func NewRangeFilter(backend Backend, begin, end int64, addresses []common.Address, topics [][]common.Hash) *Filter { +func NewRangeFilter(backend Backend, begin, end int64, addresses []common.Address, topics [][]common.Hash, isEth bool) *Filter { // Flatten the address and topic filter clauses into a single bloombits filter // system. Since the bloombits are not positional, nil topics are permitted, // which get flattened into a nil byte slice. @@ -88,7 +89,7 @@ func NewRangeFilter(backend Backend, begin, end int64, addresses []common.Addres size, _ := backend.BloomStatus() // Create a generic filter and convert it into a range filter - filter := newFilter(backend, addresses, topics) + filter := newFilter(backend, addresses, topics, isEth) filter.matcher = bloombits.NewMatcher(size, filters) filter.begin = begin @@ -99,20 +100,21 @@ func NewRangeFilter(backend Backend, begin, end int64, addresses []common.Addres // NewBlockFilter creates a new filter which directly inspects the contents of // a block to figure out whether it is interesting or not. -func NewBlockFilter(backend Backend, block common.Hash, addresses []common.Address, topics [][]common.Hash) *Filter { +func NewBlockFilter(backend Backend, block common.Hash, addresses []common.Address, topics [][]common.Hash, isEth bool) *Filter { // Create a generic filter and convert it into a block filter - filter := newFilter(backend, addresses, topics) + filter := newFilter(backend, addresses, topics, isEth) filter.block = block return filter } // newFilter creates a generic filter that can either filter based on a block hash, // or based on range queries. The search criteria needs to be explicitly set. -func newFilter(backend Backend, addresses []common.Address, topics [][]common.Hash) *Filter { +func newFilter(backend Backend, addresses []common.Address, topics [][]common.Hash, isEth bool) *Filter { return &Filter{ backend: backend, addresses: addresses, topics: topics, + isEth: isEth, } } @@ -247,7 +249,7 @@ func (f *Filter) blockLogs(ctx context.Context, header *block.Header) (logs []*t // match the filter criteria. This function is called when the bloom filter signals a potential match. func (f *Filter) checkMatches(ctx context.Context, header *block.Header) (logs []*types.Log, err error) { // Get the logs of the block - logsList, err := f.backend.GetLogs(ctx, header.Hash()) + logsList, err := f.backend.GetLogs(ctx, header.Hash(), f.isEth) if err != nil { return nil, err } diff --git a/rpc/filters/filter_system.go b/rpc/filters/filter_system.go index 5b671f949..714bcc7d6 100644 --- a/rpc/filters/filter_system.go +++ b/rpc/filters/filter_system.go @@ -104,6 +104,7 @@ type EventSystem struct { logsCh chan []*types.Log // Channel to receive new log event rmLogsCh chan core.RemovedLogsEvent // Channel to receive removed log event chainCh chan core.ChainEvent // Channel to receive new chain event + isEth bool } // NewEventSystem creates a new manager that listens for event on the given mux, @@ -112,7 +113,7 @@ type EventSystem struct { // // The returned manager has a loop that needs to be stopped with the Stop function // or by stopping the given mux. -func NewEventSystem(backend Backend, lightMode bool) *EventSystem { +func NewEventSystem(backend Backend, lightMode bool, isEth bool) *EventSystem { m := &EventSystem{ mux: backend.EventMux(), backend: backend, @@ -123,6 +124,7 @@ func NewEventSystem(backend Backend, lightMode bool) *EventSystem { logsCh: make(chan []*types.Log, logsChanSize), rmLogsCh: make(chan core.RemovedLogsEvent, rmLogsChanSize), chainCh: make(chan core.ChainEvent, chainEvChanSize), + isEth: isEth, } // Subscribe events @@ -406,7 +408,7 @@ func (es *EventSystem) lightFilterLogs(header *block.Header, addresses []common. // Get the logs of the block ctx, cancel := context.WithTimeout(context.Background(), time.Second*5) defer cancel() - logsList, err := es.backend.GetLogs(ctx, header.Hash()) + logsList, err := es.backend.GetLogs(ctx, header.Hash(), es.isEth) if err != nil { return nil }