// Copyright 2016 The go-ethereum Authors // This file is part of the go-ethereum library. // // The go-ethereum library is free software: you can redistribute it and/or modify // it under the terms of the GNU Lesser General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // // The go-ethereum library is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU Lesser General Public License for more details. // // You should have received a copy of the GNU Lesser General Public License // along with the go-ethereum library. If not, see . package ethclient import ( "context" "errors" "math/big" "reflect" "testing" ethereum "github.com/XinFinOrg/XDPoSChain" "github.com/XinFinOrg/XDPoSChain/common" "github.com/XinFinOrg/XDPoSChain/core/types" "github.com/XinFinOrg/XDPoSChain/rpc" ) // Verify that Client implements the ethereum interfaces. var ( _ = ethereum.ChainReader(&Client{}) _ = ethereum.TransactionReader(&Client{}) _ = ethereum.ChainStateReader(&Client{}) _ = ethereum.ChainSyncReader(&Client{}) _ = ethereum.ContractCaller(&Client{}) _ = ethereum.GasEstimator(&Client{}) _ = ethereum.GasPricer(&Client{}) _ = ethereum.LogFilterer(&Client{}) _ = ethereum.PendingStateReader(&Client{}) // _ = ethereum.PendingStateEventer(&Client{}) _ = ethereum.PendingContractCaller(&Client{}) ) func TestToFilterArg(t *testing.T) { blockHashErr := errors.New("cannot specify both BlockHash and FromBlock/ToBlock") addresses := []common.Address{ common.HexToAddress("0xD36722ADeC3EdCB29c8e7b5a47f352D701393462"), } blockHash := common.HexToHash( "0xeb94bb7d78b73657a9d7a99792413f50c0a45c51fc62bdcb08a53f18e9a2b4eb", ) for _, testCase := range []struct { name string input ethereum.FilterQuery output interface{} err error }{ { "without BlockHash", ethereum.FilterQuery{ Addresses: addresses, FromBlock: big.NewInt(1), ToBlock: big.NewInt(2), Topics: [][]common.Hash{}, }, map[string]interface{}{ "address": addresses, "fromBlock": "0x1", "toBlock": "0x2", "topics": [][]common.Hash{}, }, nil, }, { "with nil fromBlock and nil toBlock", ethereum.FilterQuery{ Addresses: addresses, Topics: [][]common.Hash{}, }, map[string]interface{}{ "address": addresses, "fromBlock": "0x0", "toBlock": "latest", "topics": [][]common.Hash{}, }, nil, }, { "with negative fromBlock and negative toBlock", ethereum.FilterQuery{ Addresses: addresses, FromBlock: big.NewInt(-1), ToBlock: big.NewInt(-1), Topics: [][]common.Hash{}, }, map[string]interface{}{ "address": addresses, "fromBlock": "pending", "toBlock": "pending", "topics": [][]common.Hash{}, }, nil, }, { "with blockhash", ethereum.FilterQuery{ Addresses: addresses, BlockHash: &blockHash, Topics: [][]common.Hash{}, }, map[string]interface{}{ "address": addresses, "blockHash": blockHash, "fromBlock": "0x0", "topics": [][]common.Hash{}, }, nil, }, { "with blockhash and from block", ethereum.FilterQuery{ Addresses: addresses, BlockHash: &blockHash, FromBlock: big.NewInt(1), Topics: [][]common.Hash{}, }, nil, blockHashErr, }, { "with blockhash and to block", ethereum.FilterQuery{ Addresses: addresses, BlockHash: &blockHash, ToBlock: big.NewInt(1), Topics: [][]common.Hash{}, }, nil, blockHashErr, }, { "with blockhash and both from / to block", ethereum.FilterQuery{ Addresses: addresses, BlockHash: &blockHash, FromBlock: big.NewInt(1), ToBlock: big.NewInt(2), Topics: [][]common.Hash{}, }, nil, blockHashErr, }, } { t.Run(testCase.name, func(t *testing.T) { output, err := toFilterArg(testCase.input) if (testCase.err == nil) != (err == nil) { t.Fatalf("expected error %v but got %v", testCase.err, err) } if testCase.err != nil { if testCase.err.Error() != err.Error() { t.Fatalf("expected error %v but got %v", testCase.err, err) } } else if !reflect.DeepEqual(testCase.output, output) { t.Fatalf("expected filter arg %v but got %v", testCase.output, output) } }) } } func TestBlockReceiptsPreservesCanonicalFlag(t *testing.T) { srv := rpc.NewServer() service := &blockReceiptsTestService{calls: make(chan rpc.BlockNumberOrHash, 1)} if err := srv.RegisterName("eth", service); err != nil { t.Fatalf("failed to register service: %v", err) } defer srv.Stop() client := rpc.DialInProc(srv) defer client.Close() ec := NewClient(client) defer ec.Close() hash := common.HexToHash("0x01") ref := rpc.BlockNumberOrHashWithHash(hash, true) if _, err := ec.BlockReceipts(context.Background(), ref); err != nil { t.Fatalf("BlockReceipts returned error: %v", err) } select { case call := <-service.calls: if call.BlockHash == nil || *call.BlockHash != hash { t.Fatalf("unexpected block hash: got %v, want %v", call.BlockHash, hash) } if !call.RequireCanonical { t.Fatalf("requireCanonical flag was lost: %+v", call) } default: t.Fatal("service was not called") } } type blockReceiptsTestService struct { calls chan rpc.BlockNumberOrHash } func (s *blockReceiptsTestService) GetBlockReceipts(ctx context.Context, block rpc.BlockNumberOrHash) ([]*types.Receipt, error) { s.calls <- block return []*types.Receipt{}, nil }