mirror of
https://gitlab.com/pulsechaincom/erigon-pulse.git
synced 2024-12-22 19:50:36 +00:00
459ccf8de4
…testing on Sepolia) (#9151) --------- Co-authored-by: Alex Sharp <alexsharp@Alexs-MacBook-Pro-2.local>
178 lines
6.5 KiB
Go
178 lines
6.5 KiB
Go
package jsonrpc_test
|
|
|
|
import (
|
|
"bytes"
|
|
"crypto/ecdsa"
|
|
"math/big"
|
|
"testing"
|
|
"time"
|
|
|
|
"github.com/holiman/uint256"
|
|
"github.com/ledgerwatch/erigon-lib/common"
|
|
"github.com/ledgerwatch/erigon-lib/txpool/txpoolcfg"
|
|
"github.com/ledgerwatch/erigon-lib/wrap"
|
|
|
|
"github.com/ledgerwatch/erigon-lib/gointerfaces/sentry"
|
|
"github.com/ledgerwatch/erigon-lib/gointerfaces/txpool"
|
|
"github.com/ledgerwatch/erigon-lib/kv/kvcache"
|
|
"github.com/ledgerwatch/erigon/rpc/rpccfg"
|
|
"github.com/stretchr/testify/require"
|
|
|
|
"github.com/ledgerwatch/erigon/cmd/rpcdaemon/rpcdaemontest"
|
|
"github.com/ledgerwatch/erigon/common/u256"
|
|
|
|
txpool_proto "github.com/ledgerwatch/erigon-lib/gointerfaces/txpool"
|
|
"github.com/ledgerwatch/erigon/core"
|
|
"github.com/ledgerwatch/erigon/core/types"
|
|
"github.com/ledgerwatch/erigon/eth/protocols/eth"
|
|
"github.com/ledgerwatch/erigon/params"
|
|
"github.com/ledgerwatch/erigon/rlp"
|
|
"github.com/ledgerwatch/erigon/turbo/jsonrpc"
|
|
"github.com/ledgerwatch/erigon/turbo/rpchelper"
|
|
"github.com/ledgerwatch/erigon/turbo/stages"
|
|
"github.com/ledgerwatch/erigon/turbo/stages/mock"
|
|
"github.com/ledgerwatch/log/v3"
|
|
)
|
|
|
|
func newBaseApiForTest(m *mock.MockSentry) *jsonrpc.BaseAPI {
|
|
agg := m.HistoryV3Components()
|
|
stateCache := kvcache.New(kvcache.DefaultCoherentConfig)
|
|
return jsonrpc.NewBaseApi(nil, stateCache, m.BlockReader, agg, false, rpccfg.DefaultEvmCallTimeout, m.Engine, m.Dirs)
|
|
}
|
|
|
|
// 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) {
|
|
b.SetCoinbase(common.Address{1})
|
|
})
|
|
require.NoError(err)
|
|
|
|
// Send NewBlock message
|
|
b, err := rlp.EncodeToBytes(ð.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}) {
|
|
require.NoError(err)
|
|
}
|
|
// Send all the headers
|
|
b, err = rlp.EncodeToBytes(ð.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}) {
|
|
require.NoError(err)
|
|
}
|
|
mockSentry.ReceiveWg.Wait() // Wait for all messages to be processed before we proceed
|
|
|
|
initialCycle := mock.MockInsertAsInitialCycle
|
|
if err := stages.StageLoopIteration(mockSentry.Ctx, mockSentry.DB, wrap.TxContainer{}, mockSentry.Sync, initialCycle, log.New(), mockSentry.BlockReader, nil, false); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
}
|
|
|
|
func TestSendRawTransaction(t *testing.T) {
|
|
mockSentry, require := mock.MockWithTxPool(t), require.New(t)
|
|
logger := log.New()
|
|
|
|
oneBlockStep(mockSentry, require, t)
|
|
|
|
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)
|
|
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)
|
|
api := jsonrpc.NewEthAPI(newBaseApiForTest(mockSentry), mockSentry.DB, nil, txPool, nil, 5000000, 100_000, false, 100_000, logger)
|
|
|
|
buf := bytes.NewBuffer(nil)
|
|
err = txn.MarshalBinary(buf)
|
|
require.NoError(err)
|
|
|
|
txsCh, id := ff.SubscribePendingTxs(1)
|
|
defer ff.UnsubscribePendingTxs(id)
|
|
|
|
txHash, err := api.SendRawTransaction(ctx, buf.Bytes())
|
|
require.NoError(err)
|
|
|
|
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)
|
|
require.Equal(expectedValue, jsonTx.Value.Uint64())
|
|
}
|
|
|
|
//send same tx second time and expect error
|
|
_, err = api.SendRawTransaction(ctx, buf.Bytes())
|
|
require.NotNil(err)
|
|
expectedErr := txpool_proto.ImportResult_name[int32(txpool_proto.ImportResult_ALREADY_EXISTS)] + ": " + txpoolcfg.AlreadyKnown.String()
|
|
require.Equal(expectedErr, err.Error())
|
|
mockSentry.ReceiveWg.Wait()
|
|
|
|
//TODO: make propagation easy to test - now race
|
|
//time.Sleep(time.Second)
|
|
//sent := m.SentMessage(0)
|
|
//require.Equal(eth.ToProto[m.MultiClient.Protocol()][eth.NewPooledTransactionHashesMsg], sent.Id)
|
|
}
|
|
|
|
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)
|
|
api := jsonrpc.NewEthAPI(newBaseApiForTest(mockSentry), mockSentry.DB, nil, txPool, nil, 5000000, 100_000, false, 100_000, logger)
|
|
|
|
// 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)
|
|
|
|
txHash, err := api.SendRawTransaction(ctx, buf.Bytes())
|
|
require.NoError(err)
|
|
|
|
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())
|
|
}
|
|
}
|
|
|
|
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 {
|
|
tx, _ := types.SignTx(types.NewTransaction(nonce, common.Address{}, uint256.NewInt(100), gaslimit, gasprice, nil), *types.LatestSignerForChainID(big.NewInt(1337)), key)
|
|
return tx
|
|
}
|