@ -187,9 +187,34 @@ var (
testBalance = big . NewInt ( 2e15 )
testBalance = big . NewInt ( 2e15 )
)
)
var genesis = & core . Genesis {
Config : params . AllEthashProtocolChanges ,
Alloc : core . GenesisAlloc { testAddr : { Balance : testBalance } } ,
ExtraData : [ ] byte ( "test genesis" ) ,
Timestamp : 9000 ,
BaseFee : big . NewInt ( params . InitialBaseFee ) ,
}
var testTx1 = types . MustSignNewTx ( testKey , types . LatestSigner ( genesis . Config ) , & types . LegacyTx {
Nonce : 0 ,
Value : big . NewInt ( 12 ) ,
GasPrice : big . NewInt ( params . InitialBaseFee ) ,
Gas : params . TxGas ,
To : & common . Address { 2 } ,
} )
var testTx2 = types . MustSignNewTx ( testKey , types . LatestSigner ( genesis . Config ) , & types . LegacyTx {
Nonce : 1 ,
Value : big . NewInt ( 8 ) ,
GasPrice : big . NewInt ( params . InitialBaseFee ) ,
Gas : params . TxGas ,
To : & common . Address { 2 } ,
} )
func newTestBackend ( t * testing . T ) ( * node . Node , [ ] * types . Block ) {
func newTestBackend ( t * testing . T ) ( * node . Node , [ ] * types . Block ) {
// Generate test chain.
// Generate test chain.
genesis , blocks := generateTestChain ( )
blocks := generateTestChain ( )
// Create node
// Create node
n , err := node . New ( & node . Config { } )
n , err := node . New ( & node . Config { } )
if err != nil {
if err != nil {
@ -212,25 +237,22 @@ func newTestBackend(t *testing.T) (*node.Node, []*types.Block) {
return n , blocks
return n , blocks
}
}
func generateTestChain ( ) ( * core . Genesis , [ ] * types . Block ) {
func generateTestChain ( ) [ ] * types . Block {
db := rawdb . NewMemoryDatabase ( )
db := rawdb . NewMemoryDatabase ( )
config := params . AllEthashProtocolChanges
genesis := & core . Genesis {
Config : config ,
Alloc : core . GenesisAlloc { testAddr : { Balance : testBalance } } ,
ExtraData : [ ] byte ( "test genesis" ) ,
Timestamp : 9000 ,
BaseFee : big . NewInt ( params . InitialBaseFee ) ,
}
generate := func ( i int , g * core . BlockGen ) {
generate := func ( i int , g * core . BlockGen ) {
g . OffsetTime ( 5 )
g . OffsetTime ( 5 )
g . SetExtra ( [ ] byte ( "test" ) )
g . SetExtra ( [ ] byte ( "test" ) )
if i == 1 {
// Test transactions are included in block #2.
g . AddTx ( testTx1 )
g . AddTx ( testTx2 )
}
}
}
gblock := genesis . ToBlock ( db )
gblock := genesis . ToBlock ( db )
engine := ethash . NewFaker ( )
engine := ethash . NewFaker ( )
blocks , _ := core . GenerateChain ( config , gblock , engine , db , 1 , generate )
blocks , _ := core . GenerateChain ( genesis . C onfig, gblock , engine , db , 2 , generate )
blocks = append ( [ ] * types . Block { gblock } , blocks ... )
blocks = append ( [ ] * types . Block { gblock } , blocks ... )
return genesis , blocks
return blocks
}
}
func TestEthClient ( t * testing . T ) {
func TestEthClient ( t * testing . T ) {
@ -242,30 +264,33 @@ func TestEthClient(t *testing.T) {
tests := map [ string ] struct {
tests := map [ string ] struct {
test func ( t * testing . T )
test func ( t * testing . T )
} {
} {
"Test Header" : {
"Header" : {
func ( t * testing . T ) { testHeader ( t , chain , client ) } ,
func ( t * testing . T ) { testHeader ( t , chain , client ) } ,
} ,
} ,
"Test BalanceAt" : {
"BalanceAt" : {
func ( t * testing . T ) { testBalanceAt ( t , client ) } ,
func ( t * testing . T ) { testBalanceAt ( t , client ) } ,
} ,
} ,
"TestT xInBlockInterrupted" : {
"TxInBlockInterrupted" : {
func ( t * testing . T ) { testTransactionInBlockInterrupted ( t , client ) } ,
func ( t * testing . T ) { testTransactionInBlockInterrupted ( t , client ) } ,
} ,
} ,
"Test ChainID" : {
"ChainID" : {
func ( t * testing . T ) { testChainID ( t , client ) } ,
func ( t * testing . T ) { testChainID ( t , client ) } ,
} ,
} ,
"Test GetBlock" : {
"GetBlock" : {
func ( t * testing . T ) { testGetBlock ( t , client ) } ,
func ( t * testing . T ) { testGetBlock ( t , client ) } ,
} ,
} ,
"Test StatusFunctions" : {
"StatusFunctions" : {
func ( t * testing . T ) { testStatusFunctions ( t , client ) } ,
func ( t * testing . T ) { testStatusFunctions ( t , client ) } ,
} ,
} ,
"Test CallContract" : {
"CallContract" : {
func ( t * testing . T ) { testCallContract ( t , client ) } ,
func ( t * testing . T ) { testCallContract ( t , client ) } ,
} ,
} ,
"Test AtFunctions" : {
"AtFunctions" : {
func ( t * testing . T ) { testAtFunctions ( t , client ) } ,
func ( t * testing . T ) { testAtFunctions ( t , client ) } ,
} ,
} ,
"TransactionSender" : {
func ( t * testing . T ) { testTransactionSender ( t , client ) } ,
} ,
}
}
t . Parallel ( )
t . Parallel ( )
@ -321,6 +346,11 @@ func testBalanceAt(t *testing.T, client *rpc.Client) {
want * big . Int
want * big . Int
wantErr error
wantErr error
} {
} {
"valid_account_genesis" : {
account : testAddr ,
block : big . NewInt ( 0 ) ,
want : testBalance ,
} ,
"valid_account" : {
"valid_account" : {
account : testAddr ,
account : testAddr ,
block : big . NewInt ( 1 ) ,
block : big . NewInt ( 1 ) ,
@ -358,23 +388,25 @@ func testBalanceAt(t *testing.T, client *rpc.Client) {
func testTransactionInBlockInterrupted ( t * testing . T , client * rpc . Client ) {
func testTransactionInBlockInterrupted ( t * testing . T , client * rpc . Client ) {
ec := NewClient ( client )
ec := NewClient ( client )
// Get current block by number
// Get current block by number.
block , err := ec . BlockByNumber ( context . Background ( ) , nil )
block , err := ec . BlockByNumber ( context . Background ( ) , nil )
if err != nil {
if err != nil {
t . Fatalf ( "unexpected error: %v" , err )
t . Fatalf ( "unexpected error: %v" , err )
}
}
// Test tx in block interupted
// Test tx in block interupted.
ctx , cancel := context . WithCancel ( context . Background ( ) )
ctx , cancel := context . WithCancel ( context . Background ( ) )
cancel ( )
cancel ( )
tx , err := ec . TransactionInBlock ( ctx , block . Hash ( ) , 1 )
tx , err := ec . TransactionInBlock ( ctx , block . Hash ( ) , 0 )
if tx != nil {
if tx != nil {
t . Fatal ( "transaction should be nil" )
t . Fatal ( "transaction should be nil" )
}
}
if err == nil || err == ethereum . NotFound {
if err == nil || err == ethereum . NotFound {
t . Fatal ( "error should not be nil/notfound" )
t . Fatal ( "error should not be nil/notfound" )
}
}
// Test tx in block not found
if _ , err := ec . TransactionInBlock ( context . Background ( ) , block . Hash ( ) , 1 ) ; err != ethereum . NotFound {
// Test tx in block not found.
if _ , err := ec . TransactionInBlock ( context . Background ( ) , block . Hash ( ) , 20 ) ; err != ethereum . NotFound {
t . Fatal ( "error should be ethereum.NotFound" )
t . Fatal ( "error should be ethereum.NotFound" )
}
}
}
}
@ -392,12 +424,13 @@ func testChainID(t *testing.T, client *rpc.Client) {
func testGetBlock ( t * testing . T , client * rpc . Client ) {
func testGetBlock ( t * testing . T , client * rpc . Client ) {
ec := NewClient ( client )
ec := NewClient ( client )
// Get current block number
// Get current block number
blockNumber , err := ec . BlockNumber ( context . Background ( ) )
blockNumber , err := ec . BlockNumber ( context . Background ( ) )
if err != nil {
if err != nil {
t . Fatalf ( "unexpected error: %v" , err )
t . Fatalf ( "unexpected error: %v" , err )
}
}
if blockNumber != 1 {
if blockNumber != 2 {
t . Fatalf ( "BlockNumber returned wrong number: %d" , blockNumber )
t . Fatalf ( "BlockNumber returned wrong number: %d" , blockNumber )
}
}
// Get current block by number
// Get current block by number
@ -445,6 +478,7 @@ func testStatusFunctions(t *testing.T, client *rpc.Client) {
if progress != nil {
if progress != nil {
t . Fatalf ( "unexpected progress: %v" , progress )
t . Fatalf ( "unexpected progress: %v" , progress )
}
}
// NetworkID
// NetworkID
networkID , err := ec . NetworkID ( context . Background ( ) )
networkID , err := ec . NetworkID ( context . Background ( ) )
if err != nil {
if err != nil {
@ -453,20 +487,22 @@ func testStatusFunctions(t *testing.T, client *rpc.Client) {
if networkID . Cmp ( big . NewInt ( 0 ) ) != 0 {
if networkID . Cmp ( big . NewInt ( 0 ) ) != 0 {
t . Fatalf ( "unexpected networkID: %v" , networkID )
t . Fatalf ( "unexpected networkID: %v" , networkID )
}
}
// SuggestGasPrice (should suggest 1 Gwei)
// SuggestGasPrice
gasPrice , err := ec . SuggestGasPrice ( context . Background ( ) )
gasPrice , err := ec . SuggestGasPrice ( context . Background ( ) )
if err != nil {
if err != nil {
t . Fatalf ( "unexpected error: %v" , err )
t . Fatalf ( "unexpected error: %v" , err )
}
}
if gasPrice . Cmp ( big . NewInt ( 1875 000000 ) ) != 0 { // 1 gwei tip + 0.875 basefee after a 1 gwei fee empty block
if gasPrice . Cmp ( big . NewInt ( 1000 000000 ) ) != 0 {
t . Fatalf ( "unexpected gas price: %v" , gasPrice )
t . Fatalf ( "unexpected gas price: %v" , gasPrice )
}
}
// SuggestGasTipCap (should suggest 1 Gwei)
// SuggestGasTipCap
gasTipCap , err := ec . SuggestGasTipCap ( context . Background ( ) )
gasTipCap , err := ec . SuggestGasTipCap ( context . Background ( ) )
if err != nil {
if err != nil {
t . Fatalf ( "unexpected error: %v" , err )
t . Fatalf ( "unexpected error: %v" , err )
}
}
if gasTipCap . Cmp ( big . NewInt ( 1000000 000) ) != 0 {
if gasTipCap . Cmp ( big . NewInt ( 234375 000) ) != 0 {
t . Fatalf ( "unexpected gas tip cap: %v" , gasTipCap )
t . Fatalf ( "unexpected gas tip cap: %v" , gasTipCap )
}
}
}
}
@ -500,9 +536,11 @@ func testCallContract(t *testing.T, client *rpc.Client) {
func testAtFunctions ( t * testing . T , client * rpc . Client ) {
func testAtFunctions ( t * testing . T , client * rpc . Client ) {
ec := NewClient ( client )
ec := NewClient ( client )
// send a transaction for some interesting pending status
// send a transaction for some interesting pending status
sendTransaction ( ec )
sendTransaction ( ec )
time . Sleep ( 100 * time . Millisecond )
time . Sleep ( 100 * time . Millisecond )
// Check pending transaction count
// Check pending transaction count
pending , err := ec . PendingTransactionCount ( context . Background ( ) )
pending , err := ec . PendingTransactionCount ( context . Background ( ) )
if err != nil {
if err != nil {
@ -561,23 +599,66 @@ func testAtFunctions(t *testing.T, client *rpc.Client) {
}
}
}
}
func testTransactionSender ( t * testing . T , client * rpc . Client ) {
ec := NewClient ( client )
ctx := context . Background ( )
// Retrieve testTx1 via RPC.
block2 , err := ec . HeaderByNumber ( ctx , big . NewInt ( 2 ) )
if err != nil {
t . Fatal ( "can't get block 1:" , err )
}
tx1 , err := ec . TransactionInBlock ( ctx , block2 . Hash ( ) , 0 )
if err != nil {
t . Fatal ( "can't get tx:" , err )
}
if tx1 . Hash ( ) != testTx1 . Hash ( ) {
t . Fatalf ( "wrong tx hash %v, want %v" , tx1 . Hash ( ) , testTx1 . Hash ( ) )
}
// The sender address is cached in tx1, so no additional RPC should be required in
// TransactionSender. Ensure the server is not asked by canceling the context here.
canceledCtx , cancel := context . WithCancel ( context . Background ( ) )
cancel ( )
sender1 , err := ec . TransactionSender ( canceledCtx , tx1 , block2 . Hash ( ) , 0 )
if err != nil {
t . Fatal ( err )
}
if sender1 != testAddr {
t . Fatal ( "wrong sender:" , sender1 )
}
// Now try to get the sender of testTx2, which was not fetched through RPC.
// TransactionSender should query the server here.
sender2 , err := ec . TransactionSender ( ctx , testTx2 , block2 . Hash ( ) , 1 )
if err != nil {
t . Fatal ( err )
}
if sender2 != testAddr {
t . Fatal ( "wrong sender:" , sender2 )
}
}
func sendTransaction ( ec * Client ) error {
func sendTransaction ( ec * Client ) error {
// Retrieve chainID
chainID , err := ec . ChainID ( context . Background ( ) )
chainID , err := ec . ChainID ( context . Background ( ) )
if err != nil {
if err != nil {
return err
return err
}
}
// Create transaction
nonce , err := ec . PendingNonceAt ( context . Background ( ) , testAddr )
tx := types . NewTransaction ( 0 , common . Address { 1 } , big . NewInt ( 1 ) , 22000 , big . NewInt ( params . InitialBaseFee ) , nil )
signer := types . LatestSignerForChainID ( chainID )
signature , err := crypto . Sign ( signer . Hash ( tx ) . Bytes ( ) , testKey )
if err != nil {
if err != nil {
return err
return err
}
}
signedTx , err := tx . WithSignature ( signer , signature )
signer := types . LatestSignerForChainID ( chainID )
tx , err := types . SignNewTx ( testKey , signer , & types . LegacyTx {
Nonce : nonce ,
To : & common . Address { 2 } ,
Value : big . NewInt ( 1 ) ,
Gas : 22000 ,
GasPrice : big . NewInt ( params . InitialBaseFee ) ,
} )
if err != nil {
if err != nil {
return err
return err
}
}
// Send transaction
return ec . SendTransaction ( context . Background ( ) , tx )
return ec . SendTransaction ( context . Background ( ) , signedTx )
}
}