gitlab.com/flarenetwork/coreth@v0.1.1/chain/subscribe_block_logs_test.go (about)

     1  package chain
     2  
     3  import (
     4  	"context"
     5  	"math/big"
     6  	"testing"
     7  	"time"
     8  
     9  	"gitlab.com/flarenetwork/coreth/eth/filters"
    10  
    11  	"github.com/ethereum/go-ethereum/common"
    12  	"gitlab.com/flarenetwork/coreth/core/types"
    13  )
    14  
    15  func TestBlockLogsAllowUnfinalized(t *testing.T) {
    16  	chain, newTxPoolHeadChan, txSubmitCh := NewDefaultChain(t)
    17  
    18  	chain.Start()
    19  	defer chain.Stop()
    20  
    21  	acceptedLogsCh := make(chan []*types.Log, 1000)
    22  	ethBackend := chain.APIBackend()
    23  	ethBackend.SubscribeAcceptedLogsEvent(acceptedLogsCh)
    24  
    25  	api := filters.NewPublicFilterAPI(ethBackend, true, 5*time.Minute)
    26  
    27  	// *NOTE* this was pre-compiled for the test..
    28  	/*
    29  		pragma solidity >=0.6.0;
    30  
    31  		contract Counter {
    32  		    uint256 x;
    33  
    34  		    event CounterEmit(uint256 indexed oldval, uint256 indexed newval);
    35  
    36  		    constructor() public {
    37  		        emit CounterEmit(0, 42);
    38  		        x = 42;
    39  		    }
    40  
    41  		    function add(uint256 y) public returns (uint256) {
    42  		        x = x + y;
    43  		        emit CounterEmit(y, x);
    44  		        return x;
    45  		    }
    46  		}
    47  	*/
    48  	// contracts, err := compiler.CompileSolidityString("", src)
    49  	// checkError(err)
    50  	// contract, _ := contracts[fmt.Sprintf("%s:%s", ".", "Counter")]
    51  	// _ = contract
    52  
    53  	// solc-linux-amd64-v0.6.12+commit.27d51765 --bin -o counter.bin counter.sol
    54  
    55  	code := common.Hex2Bytes(
    56  		"608060405234801561001057600080fd5b50602a60007f53564ba0be98bdbd40460eb78d2387edab91de6a842e1449053dae1f07439a3160405160405180910390a3602a60008190555060e9806100576000396000f3fe6080604052348015600f57600080fd5b506004361060285760003560e01c80631003e2d214602d575b600080fd5b605660048036036020811015604157600080fd5b8101908080359060200190929190505050606c565b6040518082815260200191505060405180910390f35b60008160005401600081905550600054827f53564ba0be98bdbd40460eb78d2387edab91de6a842e1449053dae1f07439a3160405160405180910390a3600054905091905056fea2646970667358221220dd9c84516cd903bf6a151cbdaef2f2514c28f2f422782a388a2774412b81f08864736f6c634300060c0033",
    57  		// contract.Code[2:],
    58  	)
    59  
    60  	tx := types.NewContractCreation(uint64(0), big.NewInt(0), uint64(gasLimit), gasPrice, code)
    61  	signedTx, err := types.SignTx(tx, types.NewEIP155Signer(chainID), fundedKey.PrivateKey)
    62  	if err != nil {
    63  		t.Fatal(err)
    64  	}
    65  	for _, err := range chain.AddRemoteTxs([]*types.Transaction{signedTx}) {
    66  		if err != nil {
    67  			t.Fatal(err)
    68  		}
    69  	}
    70  	<-txSubmitCh
    71  	block, err := chain.GenerateBlock()
    72  	if err != nil {
    73  		t.Fatal(err)
    74  	}
    75  	insertAndSetPreference(t, chain, block)
    76  
    77  	<-newTxPoolHeadChan
    78  
    79  	if block.NumberU64() != uint64(1) {
    80  		t.Fatalf("Expected to create a new block with height 1, but found %d", block.NumberU64())
    81  	}
    82  
    83  	ctx := context.Background()
    84  	fc := filters.FilterCriteria{
    85  		FromBlock: big.NewInt(1),
    86  		ToBlock:   big.NewInt(1),
    87  	}
    88  
    89  	fid, err := api.NewFilter(fc)
    90  	if err != nil {
    91  		t.Fatalf("Failed to create NewFilter due to %s", err)
    92  	}
    93  
    94  	chain.BlockChain().GetVMConfig().AllowUnfinalizedQueries = true
    95  	logs, err := api.GetLogs(ctx, fc)
    96  	if err != nil {
    97  		t.Fatalf("GetLogs failed due to %s", err)
    98  	}
    99  	if len(logs) != 1 {
   100  		t.Fatalf("Expected GetLogs to return 1 log, but found %d", len(logs))
   101  	}
   102  	if logs[0].BlockNumber != 1 {
   103  		t.Fatalf("Expected GetLogs to return 1 log with block number 1, but found block number %d", logs[0].BlockNumber)
   104  	}
   105  
   106  	logs, err = api.GetFilterLogs(ctx, fid)
   107  	if err != nil {
   108  		t.Fatalf("GetFilter failed due to %s", err)
   109  	}
   110  	if len(logs) != 1 {
   111  		t.Fatalf("Expected GetFilterLogs to return 1 log, but found %d", len(logs))
   112  	}
   113  	if logs[0].BlockNumber != 1 {
   114  		t.Fatalf("Expected GetFilterLogs to return 1 log with BlockNumber 1, but found BlockNumber %d", logs[0].BlockNumber)
   115  	}
   116  
   117  	// Fetching blocks from an unfinalized height without specifying a to height
   118  	// will not yield any logs because the to block is populated using the last
   119  	// accepted block.
   120  	fc2 := filters.FilterCriteria{
   121  		FromBlock: big.NewInt(1),
   122  	}
   123  
   124  	fid2, err := api.NewFilter(fc2)
   125  	if err != nil {
   126  		t.Fatalf("Failed to create NewFilter due to %s", err)
   127  	}
   128  
   129  	logs, err = api.GetLogs(ctx, fc2)
   130  	if err == nil || err.Error() != "begin block 1 is greater than end block 0" {
   131  		t.Fatalf("Expected GetLogs to error about invalid range, but found error %s", err)
   132  	}
   133  	if len(logs) != 0 {
   134  		t.Fatalf("Expected GetLogs to return 0 log, but found %d", len(logs))
   135  	}
   136  
   137  	logs, err = api.GetFilterLogs(ctx, fid2)
   138  	if err == nil || err.Error() != "begin block 1 is greater than end block 0" {
   139  		t.Fatalf("Expected GetLogs to error about invalid range, but found error %s", err)
   140  	}
   141  	if len(logs) != 0 {
   142  		t.Fatalf("Expected GetFilterLogs to return 0 log, but found %d", len(logs))
   143  	}
   144  
   145  	chain.BlockChain().GetVMConfig().AllowUnfinalizedQueries = false
   146  	logs, err = api.GetLogs(ctx, fc)
   147  	if logs != nil {
   148  		t.Fatalf("Expected logs to be empty, but found %d logs", len(logs))
   149  	}
   150  	if err == nil || err.Error() != "requested from block 1 after last accepted block 0" {
   151  		t.Fatalf("Expected GetLogs to error due to requesting above last accepted block, but found error %s", err)
   152  	}
   153  
   154  	logs, err = api.GetFilterLogs(ctx, fid)
   155  	if logs != nil {
   156  		t.Fatalf("Expected GetFilterLogs to return empty logs, but found %d logs", len(logs))
   157  	}
   158  	if err == nil || err.Error() != "requested from block 1 after last accepted block 0" {
   159  		t.Fatalf("Expected GetLogs to fail due to requesting block above last accepted block, but found error %s", err)
   160  	}
   161  
   162  	logs, err = api.GetLogs(ctx, fc2)
   163  	if logs != nil {
   164  		t.Fatalf("Expected logs to be empty, but found %d logs", len(logs))
   165  	}
   166  	if err == nil || err.Error() != "requested from block 1 after last accepted block 0" {
   167  		t.Fatalf("Expected GetLogs to error due to requesting above last accepted block, but found error %s", err)
   168  	}
   169  
   170  	logs, err = api.GetFilterLogs(ctx, fid2)
   171  	if logs != nil {
   172  		t.Fatalf("Expected GetFilterLogs to return empty logs, but found %d logs", len(logs))
   173  	}
   174  	if err == nil || err.Error() != "requested from block 1 after last accepted block 0" {
   175  		t.Fatalf("Expected GetLogs to fail due to requesting block above last accepted block, but found error %s", err)
   176  	}
   177  
   178  	fc3 := filters.FilterCriteria{
   179  		FromBlock: big.NewInt(0),
   180  		ToBlock:   big.NewInt(1),
   181  	}
   182  	logs, err = api.GetLogs(ctx, fc3)
   183  	if logs != nil {
   184  		t.Fatalf("Expected GetLogs to return empty, but found %d logs", len(logs))
   185  	}
   186  	if err == nil || err.Error() != "requested to block 1 after last accepted block 0" {
   187  		t.Fatalf("Expected GetLogs to error due to requesting block above last accepted block, but found error %s", err)
   188  	}
   189  
   190  	fid3, err := api.NewFilter(fc3)
   191  	if err != nil {
   192  		t.Fatalf("NewFilter failed due to %s", err)
   193  	}
   194  	logs, err = api.GetFilterLogs(ctx, fid3)
   195  	if logs != nil {
   196  		t.Fatalf("Expected GetFilterLogs to return empty logs but found %d logs", len(logs))
   197  	}
   198  	if err == nil || err.Error() != "requested to block 1 after last accepted block 0" {
   199  		t.Fatalf("Expected GetFilterLogs to fail due to requesting block above last accepted block, but found error %s", err)
   200  	}
   201  
   202  	// Unless otherwise specified, getting the latest will still return the last
   203  	// accepted logs even when AllowUnfinalizedQueries = true.
   204  	fc4 := filters.FilterCriteria{}
   205  	logs, err = api.GetLogs(ctx, fc4)
   206  	if err != nil {
   207  		t.Fatalf("Failed to GetLogs for FilterCriteria with empty from and to block due to %s", err)
   208  	}
   209  	if len(logs) != 0 {
   210  		t.Fatalf("Expected GetLogs to return 0 log, but found %d", len(logs))
   211  	}
   212  	fid4, err := api.NewFilter(fc4)
   213  	if err != nil {
   214  		t.Fatalf("NewFilter failed due to %s", err)
   215  	}
   216  	logs, err = api.GetFilterLogs(ctx, fid4)
   217  	if err != nil {
   218  		t.Fatalf("GetFilterLogs failed due to %s", err)
   219  	}
   220  	if len(logs) != 0 {
   221  		t.Fatalf("Expected GetFilterLogs to return 0 log, but found %d", len(logs))
   222  	}
   223  
   224  	select {
   225  	case <-acceptedLogsCh:
   226  		t.Fatal("Received accepted logs event before Accepting block")
   227  	default:
   228  	}
   229  
   230  	if err := chain.Accept(block); err != nil {
   231  		t.Fatal(err)
   232  	}
   233  
   234  	chain.BlockChain().GetVMConfig().AllowUnfinalizedQueries = false
   235  	logs, err = api.GetLogs(ctx, fc)
   236  	if err != nil {
   237  		t.Fatalf("GetLogs failed due to %s", err)
   238  	}
   239  	if len(logs) != 1 {
   240  		t.Fatalf("Expected GetLogs to return 1 log, but found %d", len(logs))
   241  	}
   242  	if logs[0].BlockNumber != 1 {
   243  		t.Fatalf("Expected single log to have block number 1, but found %d", logs[0].BlockNumber)
   244  	}
   245  
   246  	logs, err = api.GetFilterLogs(ctx, fid)
   247  	if err != nil {
   248  		t.Fatalf("GetFilterLogs failed due to %s", err)
   249  	}
   250  	if len(logs) != 1 {
   251  		t.Fatalf("Expected GetFilterLogs to return 1 log, but found %d", len(logs))
   252  	}
   253  	if logs[0].BlockNumber != 1 {
   254  		t.Fatalf("Expected GetFilterLogs to return 1 log with BlocKNumber 1, but found BlockNumber %d", logs[0].BlockNumber)
   255  	}
   256  
   257  	logs, err = api.GetLogs(ctx, fc4)
   258  	if err != nil {
   259  		t.Fatalf("Failed to GetLogs for FilterCriteria with empty from and to block due to %s", err)
   260  	}
   261  	if len(logs) != 1 {
   262  		t.Fatalf("Expected GetLogs to return 1 log, but found %d", len(logs))
   263  	}
   264  	if logs[0].BlockNumber != 1 {
   265  		t.Fatalf("Expected single log to have block number 1, but found %d", logs[0].BlockNumber)
   266  	}
   267  	fid4, err = api.NewFilter(fc4)
   268  	if err != nil {
   269  		t.Fatalf("NewFilter failed due to %s", err)
   270  	}
   271  	logs, err = api.GetFilterLogs(ctx, fid4)
   272  	if err != nil {
   273  		t.Fatalf("GetFilterLogs failed due to %s", err)
   274  	}
   275  	if len(logs) != 1 {
   276  		t.Fatalf("Expected GetFilterLogs to return 1 log, but found %d", len(logs))
   277  	}
   278  	if logs[0].BlockNumber != 1 {
   279  		t.Fatalf("Expected GetFilterLogs to return 1 log with BlockNumber 1, but found BlockNumber %d", logs[0].BlockNumber)
   280  	}
   281  
   282  	select {
   283  	case acceptedLogs := <-acceptedLogsCh:
   284  		if len(acceptedLogs) != 1 {
   285  			t.Fatalf("Expected accepted logs channel to return 1 log, but found %d", len(acceptedLogs))
   286  		}
   287  		if acceptedLogs[0].BlockNumber != 1 {
   288  			t.Fatalf("Expected accepted logs channel to return 1 log with BlockNumber 1, but found BlockNumber %d", acceptedLogs[0].BlockNumber)
   289  		}
   290  	default:
   291  		t.Fatal("Failed to receive logs via accepted logs channel")
   292  	}
   293  }