2023-07-08 17:01:26 +00:00
package jsonrpc_test
2021-05-04 01:37:17 +00:00
import (
"bytes"
"crypto/ecdsa"
2022-09-18 10:41:01 +00:00
"math/big"
"testing"
2023-10-08 20:59:49 +00:00
"time"
2022-09-18 10:41:01 +00:00
2021-05-04 01:37:17 +00:00
"github.com/holiman/uint256"
2023-01-27 04:39:34 +00:00
"github.com/ledgerwatch/erigon-lib/common"
2023-10-08 01:18:14 +00:00
"github.com/ledgerwatch/erigon-lib/txpool/txpoolcfg"
2024-01-09 01:26:26 +00:00
"github.com/ledgerwatch/erigon-lib/wrap"
2023-10-08 01:18:14 +00:00
2021-07-01 21:31:14 +00:00
"github.com/ledgerwatch/erigon-lib/gointerfaces/sentry"
"github.com/ledgerwatch/erigon-lib/gointerfaces/txpool"
2021-09-29 01:36:25 +00:00
"github.com/ledgerwatch/erigon-lib/kv/kvcache"
2023-06-15 06:11:51 +00:00
"github.com/ledgerwatch/erigon/rpc/rpccfg"
2023-01-13 18:12:18 +00:00
"github.com/stretchr/testify/require"
2021-06-29 10:00:22 +00:00
"github.com/ledgerwatch/erigon/cmd/rpcdaemon/rpcdaemontest"
2021-05-20 18:25:53 +00:00
"github.com/ledgerwatch/erigon/common/u256"
2023-10-08 01:18:14 +00:00
txpool_proto "github.com/ledgerwatch/erigon-lib/gointerfaces/txpool"
2021-06-27 06:41:21 +00:00
"github.com/ledgerwatch/erigon/core"
2021-05-20 18:25:53 +00:00
"github.com/ledgerwatch/erigon/core/types"
2021-06-27 06:41:21 +00:00
"github.com/ledgerwatch/erigon/eth/protocols/eth"
"github.com/ledgerwatch/erigon/params"
"github.com/ledgerwatch/erigon/rlp"
2023-07-08 17:01:26 +00:00
"github.com/ledgerwatch/erigon/turbo/jsonrpc"
2022-06-10 15:18:43 +00:00
"github.com/ledgerwatch/erigon/turbo/rpchelper"
2021-06-27 06:41:21 +00:00
"github.com/ledgerwatch/erigon/turbo/stages"
2023-08-05 21:33:10 +00:00
"github.com/ledgerwatch/erigon/turbo/stages/mock"
2023-05-08 16:52:31 +00:00
"github.com/ledgerwatch/log/v3"
2021-05-04 01:37:17 +00:00
)
2023-08-05 21:33:10 +00:00
func newBaseApiForTest ( m * mock . MockSentry ) * jsonrpc . BaseAPI {
2023-06-15 06:11:51 +00:00
agg := m . HistoryV3Components ( )
stateCache := kvcache . New ( kvcache . DefaultCoherentConfig )
2023-07-08 17:01:26 +00:00
return jsonrpc . NewBaseApi ( nil , stateCache , m . BlockReader , agg , false , rpccfg . DefaultEvmCallTimeout , m . Engine , m . Dirs )
2023-06-15 06:11:51 +00:00
}
2023-10-08 01:18:14 +00:00
// Do 1 step to start txPool
func oneBlockStep ( mockSentry * mock . MockSentry , require * require . Assertions , t * testing . T ) {
chain , err := core . GenerateChain ( mockSentry . ChainConfig , mockSentry . Genesis , mockSentry . Engine , mockSentry . DB , 1 /*number of blocks:*/ , func ( i int , b * core . BlockGen ) {
2023-01-27 04:39:34 +00:00
b . SetCoinbase ( common . Address { 1 } )
2023-06-23 03:07:42 +00:00
} )
2021-06-27 06:41:21 +00:00
require . NoError ( err )
2023-10-08 01:18:14 +00:00
// Send NewBlock message
b , err := rlp . EncodeToBytes ( & eth . NewBlockPacket {
Block : chain . TopBlock ,
TD : big . NewInt ( 1 ) , // This is ignored anyway
} )
require . NoError ( err )
mockSentry . ReceiveWg . Add ( 1 )
for _ , err = range mockSentry . Send ( & sentry . InboundMessage { Id : sentry . MessageId_NEW_BLOCK_66 , Data : b , PeerId : mockSentry . PeerId } ) {
2021-06-27 06:41:21 +00:00
require . NoError ( err )
2023-10-08 01:18:14 +00:00
}
// Send all the headers
b , err = rlp . EncodeToBytes ( & eth . BlockHeadersPacket66 {
RequestId : 1 ,
BlockHeadersPacket : chain . Headers ,
} )
require . NoError ( err )
mockSentry . ReceiveWg . Add ( 1 )
for _ , err = range mockSentry . Send ( & sentry . InboundMessage { Id : sentry . MessageId_BLOCK_HEADERS_66 , Data : b , PeerId : mockSentry . PeerId } ) {
2021-06-27 06:41:21 +00:00
require . NoError ( err )
}
2023-10-08 01:18:14 +00:00
mockSentry . ReceiveWg . Wait ( ) // Wait for all messages to be processed before we proceed
initialCycle := mock . MockInsertAsInitialCycle
2024-01-09 01:26:26 +00:00
if err := stages . StageLoopIteration ( mockSentry . Ctx , mockSentry . DB , wrap . TxContainer { } , mockSentry . Sync , initialCycle , log . New ( ) , mockSentry . BlockReader , nil , false ) ; err != nil {
2023-10-08 01:18:14 +00:00
t . Fatal ( err )
}
}
func TestSendRawTransaction ( t * testing . T ) {
mockSentry , require := mock . MockWithTxPool ( t ) , require . New ( t )
logger := log . New ( )
oneBlockStep ( mockSentry , require , t )
2021-06-27 06:41:21 +00:00
2023-10-08 20:59:49 +00:00
expectedValue := uint64 ( 1234 )
txn , err := types . SignTx ( types . NewTransaction ( 0 , common . Address { 1 } , uint256 . NewInt ( expectedValue ) , params . TxGas , uint256 . NewInt ( 10 * params . GWei ) , nil ) , * types . LatestSignerForChainID ( mockSentry . ChainConfig . ChainID ) , mockSentry . Key )
2021-06-27 06:41:21 +00:00
require . NoError ( err )
2023-10-08 01:18:14 +00:00
ctx , conn := rpcdaemontest . CreateTestGrpcConn ( t , mockSentry )
2021-05-04 01:37:17 +00:00
txPool := txpool . NewTxpoolClient ( conn )
2023-10-08 01:18:14 +00:00
ff := rpchelper . New ( ctx , nil , txPool , txpool . NewMiningClient ( conn ) , func ( ) { } , mockSentry . Log )
2023-11-13 16:11:35 +00:00
api := jsonrpc . NewEthAPI ( newBaseApiForTest ( mockSentry ) , mockSentry . DB , nil , txPool , nil , 5000000 , 100_000 , false , 100_000 , logger )
2021-05-04 01:37:17 +00:00
buf := bytes . NewBuffer ( nil )
2021-06-27 06:41:21 +00:00
err = txn . MarshalBinary ( buf )
require . NoError ( err )
2021-05-04 01:37:17 +00:00
2023-01-02 04:42:40 +00:00
txsCh , id := ff . SubscribePendingTxs ( 1 )
2021-06-29 10:00:22 +00:00
defer ff . UnsubscribePendingTxs ( id )
2021-05-04 01:37:17 +00:00
2023-10-08 20:59:49 +00:00
txHash , err := api . SendRawTransaction ( ctx , buf . Bytes ( ) )
2021-06-27 06:41:21 +00:00
require . NoError ( err )
2023-10-08 20:59:49 +00:00
select {
case got := <- txsCh :
require . Equal ( expectedValue , got [ 0 ] . GetValue ( ) . Uint64 ( ) )
case <- time . After ( 20 * time . Second ) : // Sometimes the channel times out on github actions
t . Log ( "Timeout waiting for txn from channel" )
jsonTx , err := api . GetTransactionByHash ( ctx , txHash )
require . NoError ( err )
2023-10-09 17:12:54 +00:00
require . Equal ( expectedValue , jsonTx . Value . Uint64 ( ) )
2023-10-08 20:59:49 +00:00
}
2021-06-27 06:41:21 +00:00
//send same tx second time and expect error
_ , err = api . SendRawTransaction ( ctx , buf . Bytes ( ) )
require . NotNil ( err )
2023-10-08 01:18:14 +00:00
expectedErr := txpool_proto . ImportResult_name [ int32 ( txpool_proto . ImportResult_ALREADY_EXISTS ) ] + ": " + txpoolcfg . AlreadyKnown . String ( )
require . Equal ( expectedErr , err . Error ( ) )
mockSentry . ReceiveWg . Wait ( )
2021-06-29 10:00:22 +00:00
//TODO: make propagation easy to test - now race
//time.Sleep(time.Second)
//sent := m.SentMessage(0)
2022-05-26 03:45:35 +00:00
//require.Equal(eth.ToProto[m.MultiClient.Protocol()][eth.NewPooledTransactionHashesMsg], sent.Id)
2021-05-04 01:37:17 +00:00
}
2023-10-08 01:18:14 +00:00
func TestSendRawTransactionUnprotected ( t * testing . T ) {
mockSentry , require := mock . MockWithTxPool ( t ) , require . New ( t )
logger := log . New ( )
oneBlockStep ( mockSentry , require , t )
expectedTxValue := uint64 ( 4444 )
// Create a legacy signer pre-155
unprotectedSigner := types . MakeFrontierSigner ( )
txn , err := types . SignTx ( types . NewTransaction ( 0 , common . Address { 1 } , uint256 . NewInt ( expectedTxValue ) , params . TxGas , uint256 . NewInt ( 10 * params . GWei ) , nil ) , * unprotectedSigner , mockSentry . Key )
require . NoError ( err )
ctx , conn := rpcdaemontest . CreateTestGrpcConn ( t , mockSentry )
txPool := txpool . NewTxpoolClient ( conn )
ff := rpchelper . New ( ctx , nil , txPool , txpool . NewMiningClient ( conn ) , func ( ) { } , mockSentry . Log )
2023-11-13 16:11:35 +00:00
api := jsonrpc . NewEthAPI ( newBaseApiForTest ( mockSentry ) , mockSentry . DB , nil , txPool , nil , 5000000 , 100_000 , false , 100_000 , logger )
2023-10-08 01:18:14 +00:00
// Enable unproteced txs flag
api . AllowUnprotectedTxs = true
buf := bytes . NewBuffer ( nil )
err = txn . MarshalBinary ( buf )
require . NoError ( err )
txsCh , id := ff . SubscribePendingTxs ( 1 )
defer ff . UnsubscribePendingTxs ( id )
2023-10-08 20:59:49 +00:00
txHash , err := api . SendRawTransaction ( ctx , buf . Bytes ( ) )
2023-10-08 01:18:14 +00:00
require . NoError ( err )
2023-10-08 20:59:49 +00:00
select {
case got := <- txsCh :
require . Equal ( expectedTxValue , got [ 0 ] . GetValue ( ) . Uint64 ( ) )
case <- time . After ( 20 * time . Second ) : // Sometimes the channel times out on github actions
t . Log ( "Timeout waiting for txn from channel" )
jsonTx , err := api . GetTransactionByHash ( ctx , txHash )
require . NoError ( err )
require . Equal ( expectedTxValue , jsonTx . Value . Uint64 ( ) )
}
2023-10-08 01:18:14 +00:00
}
2021-05-04 01:37:17 +00:00
func transaction ( nonce uint64 , gaslimit uint64 , key * ecdsa . PrivateKey ) types . Transaction {
return pricedTransaction ( nonce , gaslimit , u256 . Num1 , key )
}
func pricedTransaction ( nonce uint64 , gaslimit uint64 , gasprice * uint256 . Int , key * ecdsa . PrivateKey ) types . Transaction {
2023-01-27 04:39:34 +00:00
tx , _ := types . SignTx ( types . NewTransaction ( nonce , common . Address { } , uint256 . NewInt ( 100 ) , gaslimit , gasprice , nil ) , * types . LatestSignerForChainID ( big . NewInt ( 1337 ) ) , key )
2021-05-04 01:37:17 +00:00
return tx
}