eth/filters: fix a breaking change and return rpctransaction (#26757)
* eth/filters: fix a breaking change and return rpctransaction * eth/filters: fix test cases --------- Co-authored-by: Catror <me@catror.com>
This commit is contained in:
		
							parent
							
								
									fe01a2f63b
								
							
						
					
					
						commit
						4034c675be
					
				| @ -39,6 +39,7 @@ type filter struct { | ||||
| 	typ      Type | ||||
| 	deadline *time.Timer // filter is inactive when deadline triggers
 | ||||
| 	hashes   []common.Hash | ||||
| 	fullTx   bool | ||||
| 	txs      []*types.Transaction | ||||
| 	crit     FilterCriteria | ||||
| 	logs     []*types.Log | ||||
| @ -103,14 +104,14 @@ func (api *FilterAPI) timeoutLoop(timeout time.Duration) { | ||||
| //
 | ||||
| // It is part of the filter package because this filter can be used through the
 | ||||
| // `eth_getFilterChanges` polling method that is also used for log filters.
 | ||||
| func (api *FilterAPI) NewPendingTransactionFilter() rpc.ID { | ||||
| func (api *FilterAPI) NewPendingTransactionFilter(fullTx *bool) rpc.ID { | ||||
| 	var ( | ||||
| 		pendingTxs   = make(chan []*types.Transaction) | ||||
| 		pendingTxSub = api.events.SubscribePendingTxs(pendingTxs) | ||||
| 	) | ||||
| 
 | ||||
| 	api.filtersMu.Lock() | ||||
| 	api.filters[pendingTxSub.ID] = &filter{typ: PendingTransactionsSubscription, deadline: time.NewTimer(api.timeout), txs: make([]*types.Transaction, 0), s: pendingTxSub} | ||||
| 	api.filters[pendingTxSub.ID] = &filter{typ: PendingTransactionsSubscription, fullTx: fullTx != nil && *fullTx, deadline: time.NewTimer(api.timeout), txs: make([]*types.Transaction, 0), s: pendingTxSub} | ||||
| 	api.filtersMu.Unlock() | ||||
| 
 | ||||
| 	go func() { | ||||
| @ -412,6 +413,9 @@ func (api *FilterAPI) GetFilterChanges(id rpc.ID) (interface{}, error) { | ||||
| 	api.filtersMu.Lock() | ||||
| 	defer api.filtersMu.Unlock() | ||||
| 
 | ||||
| 	chainConfig := api.sys.backend.ChainConfig() | ||||
| 	latest := api.sys.backend.CurrentHeader() | ||||
| 
 | ||||
| 	if f, found := api.filters[id]; found { | ||||
| 		if !f.deadline.Stop() { | ||||
| 			// timer expired but filter is not yet removed in timeout loop
 | ||||
| @ -426,9 +430,21 @@ func (api *FilterAPI) GetFilterChanges(id rpc.ID) (interface{}, error) { | ||||
| 			f.hashes = nil | ||||
| 			return returnHashes(hashes), nil | ||||
| 		case PendingTransactionsSubscription: | ||||
| 			txs := f.txs | ||||
| 			f.txs = nil | ||||
| 			return txs, nil | ||||
| 			if f.fullTx { | ||||
| 				txs := make([]*ethapi.RPCTransaction, 0, len(f.txs)) | ||||
| 				for _, tx := range f.txs { | ||||
| 					txs = append(txs, ethapi.NewRPCPendingTransaction(tx, latest, chainConfig)) | ||||
| 				} | ||||
| 				f.txs = nil | ||||
| 				return txs, nil | ||||
| 			} else { | ||||
| 				hashes := make([]common.Hash, 0, len(f.txs)) | ||||
| 				for _, tx := range f.txs { | ||||
| 					hashes = append(hashes, tx.Hash()) | ||||
| 				} | ||||
| 				f.txs = nil | ||||
| 				return hashes, nil | ||||
| 			} | ||||
| 		case LogsSubscription, MinedAndPendingLogsSubscription: | ||||
| 			logs := f.logs | ||||
| 			f.logs = nil | ||||
|  | ||||
| @ -37,6 +37,7 @@ import ( | ||||
| 	"github.com/ethereum/go-ethereum/crypto" | ||||
| 	"github.com/ethereum/go-ethereum/ethdb" | ||||
| 	"github.com/ethereum/go-ethereum/event" | ||||
| 	"github.com/ethereum/go-ethereum/internal/ethapi" | ||||
| 	"github.com/ethereum/go-ethereum/params" | ||||
| 	"github.com/ethereum/go-ethereum/rpc" | ||||
| ) | ||||
| @ -52,11 +53,12 @@ type testBackend struct { | ||||
| } | ||||
| 
 | ||||
| func (b *testBackend) ChainConfig() *params.ChainConfig { | ||||
| 	panic("implement me") | ||||
| 	return params.TestChainConfig | ||||
| } | ||||
| 
 | ||||
| func (b *testBackend) CurrentHeader() *types.Header { | ||||
| 	panic("implement me") | ||||
| 	hdr, _ := b.HeaderByNumber(context.TODO(), rpc.LatestBlockNumber) | ||||
| 	return hdr | ||||
| } | ||||
| 
 | ||||
| func (b *testBackend) ChainDb() ethdb.Database { | ||||
| @ -256,10 +258,10 @@ func TestPendingTxFilter(t *testing.T) { | ||||
| 			types.NewTransaction(4, common.HexToAddress("0xb794f5ea0ba39494ce83a213fffba74279579268"), new(big.Int), 0, new(big.Int), nil), | ||||
| 		} | ||||
| 
 | ||||
| 		txs []*types.Transaction | ||||
| 		hashes []common.Hash | ||||
| 	) | ||||
| 
 | ||||
| 	fid0 := api.NewPendingTransactionFilter() | ||||
| 	fid0 := api.NewPendingTransactionFilter(nil) | ||||
| 
 | ||||
| 	time.Sleep(1 * time.Second) | ||||
| 	backend.txFeed.Send(core.NewTxsEvent{Txs: transactions}) | ||||
| @ -271,7 +273,64 @@ func TestPendingTxFilter(t *testing.T) { | ||||
| 			t.Fatalf("Unable to retrieve logs: %v", err) | ||||
| 		} | ||||
| 
 | ||||
| 		tx := results.([]*types.Transaction) | ||||
| 		h := results.([]common.Hash) | ||||
| 		hashes = append(hashes, h...) | ||||
| 		if len(hashes) >= len(transactions) { | ||||
| 			break | ||||
| 		} | ||||
| 		// check timeout
 | ||||
| 		if time.Now().After(timeout) { | ||||
| 			break | ||||
| 		} | ||||
| 
 | ||||
| 		time.Sleep(100 * time.Millisecond) | ||||
| 	} | ||||
| 
 | ||||
| 	if len(hashes) != len(transactions) { | ||||
| 		t.Errorf("invalid number of transactions, want %d transactions(s), got %d", len(transactions), len(hashes)) | ||||
| 		return | ||||
| 	} | ||||
| 	for i := range hashes { | ||||
| 		if hashes[i] != transactions[i].Hash() { | ||||
| 			t.Errorf("hashes[%d] invalid, want %x, got %x", i, transactions[i].Hash(), hashes[i]) | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| // TestPendingTxFilterFullTx tests whether pending tx filters retrieve all pending transactions that are posted to the event mux.
 | ||||
| func TestPendingTxFilterFullTx(t *testing.T) { | ||||
| 	t.Parallel() | ||||
| 
 | ||||
| 	var ( | ||||
| 		db           = rawdb.NewMemoryDatabase() | ||||
| 		backend, sys = newTestFilterSystem(t, db, Config{}) | ||||
| 		api          = NewFilterAPI(sys, false) | ||||
| 
 | ||||
| 		transactions = []*types.Transaction{ | ||||
| 			types.NewTransaction(0, common.HexToAddress("0xb794f5ea0ba39494ce83a213fffba74279579268"), new(big.Int), 0, new(big.Int), nil), | ||||
| 			types.NewTransaction(1, common.HexToAddress("0xb794f5ea0ba39494ce83a213fffba74279579268"), new(big.Int), 0, new(big.Int), nil), | ||||
| 			types.NewTransaction(2, common.HexToAddress("0xb794f5ea0ba39494ce83a213fffba74279579268"), new(big.Int), 0, new(big.Int), nil), | ||||
| 			types.NewTransaction(3, common.HexToAddress("0xb794f5ea0ba39494ce83a213fffba74279579268"), new(big.Int), 0, new(big.Int), nil), | ||||
| 			types.NewTransaction(4, common.HexToAddress("0xb794f5ea0ba39494ce83a213fffba74279579268"), new(big.Int), 0, new(big.Int), nil), | ||||
| 		} | ||||
| 
 | ||||
| 		txs []*ethapi.RPCTransaction | ||||
| 	) | ||||
| 
 | ||||
| 	fullTx := true | ||||
| 	fid0 := api.NewPendingTransactionFilter(&fullTx) | ||||
| 
 | ||||
| 	time.Sleep(1 * time.Second) | ||||
| 	backend.txFeed.Send(core.NewTxsEvent{Txs: transactions}) | ||||
| 
 | ||||
| 	timeout := time.Now().Add(1 * time.Second) | ||||
| 	for { | ||||
| 		results, err := api.GetFilterChanges(fid0) | ||||
| 		if err != nil { | ||||
| 			t.Fatalf("Unable to retrieve logs: %v", err) | ||||
| 		} | ||||
| 
 | ||||
| 		tx := results.([]*ethapi.RPCTransaction) | ||||
| 		txs = append(txs, tx...) | ||||
| 		if len(txs) >= len(transactions) { | ||||
| 			break | ||||
| @ -289,8 +348,8 @@ func TestPendingTxFilter(t *testing.T) { | ||||
| 		return | ||||
| 	} | ||||
| 	for i := range txs { | ||||
| 		if txs[i].Hash() != transactions[i].Hash() { | ||||
| 			t.Errorf("hashes[%d] invalid, want %x, got %x", i, transactions[i].Hash(), txs[i].Hash()) | ||||
| 		if txs[i].Hash != transactions[i].Hash() { | ||||
| 			t.Errorf("hashes[%d] invalid, want %x, got %x", i, transactions[i].Hash(), txs[i].Hash) | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
| @ -854,15 +913,15 @@ func TestPendingTxFilterDeadlock(t *testing.T) { | ||||
| 	// timeout either in 100ms or 200ms
 | ||||
| 	fids := make([]rpc.ID, 20) | ||||
| 	for i := 0; i < len(fids); i++ { | ||||
| 		fid := api.NewPendingTransactionFilter() | ||||
| 		fid := api.NewPendingTransactionFilter(nil) | ||||
| 		fids[i] = fid | ||||
| 		// Wait for at least one tx to arrive in filter
 | ||||
| 		for { | ||||
| 			txs, err := api.GetFilterChanges(fid) | ||||
| 			hashes, err := api.GetFilterChanges(fid) | ||||
| 			if err != nil { | ||||
| 				t.Fatalf("Filter should exist: %v\n", err) | ||||
| 			} | ||||
| 			if len(txs.([]*types.Transaction)) > 0 { | ||||
| 			if len(hashes.([]common.Hash)) > 0 { | ||||
| 				break | ||||
| 			} | ||||
| 			runtime.Gosched() | ||||
|  | ||||
		Loading…
	
		Reference in New Issue
	
	Block a user