Skip to content

Commit 2efc303

Browse files
Extract peer and target (#14)
* extract peer and load_target classes * lint * lint (2) * extract generateAndSendTx method * use ticker instead of sleep * refactor(tx_load_tool): improve transaction generation timing and logging * feat(tx_load_tool): add logging for transaction generation intervals * fix(tx_load_tool): correct log interval calculation for transaction generation * fix(tx_load_tool): adjust transaction count in logging for accuracy --------- Co-authored-by: Michelangelo Riccobene <michelangelo.riccobene@gmail.com>
1 parent 18a3023 commit 2efc303

File tree

4 files changed

+262
-169
lines changed

4 files changed

+262
-169
lines changed

pkg/coordinator/utils/sentry/conn.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -98,7 +98,7 @@ func (c *Conn) Write(proto Proto, code uint64, msg any) error {
9898
return err
9999
}
100100

101-
var errDisc error = fmt.Errorf("disconnect")
101+
var errDisc = fmt.Errorf("disconnect")
102102

103103
// ReadEth reads an Eth sub-protocol wire message.
104104
func (c *Conn) ReadEth() (any, error) {
Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
package txloadtool
2+
3+
import (
4+
"context"
5+
crand "crypto/rand"
6+
"fmt"
7+
"math/big"
8+
9+
"github.com/erigontech/assertoor/pkg/coordinator/clients/execution"
10+
"github.com/erigontech/assertoor/pkg/coordinator/helper"
11+
"github.com/erigontech/assertoor/pkg/coordinator/types"
12+
"github.com/erigontech/assertoor/pkg/coordinator/wallet"
13+
"github.com/ethereum/go-ethereum/accounts/abi/bind"
14+
ethtypes "github.com/ethereum/go-ethereum/core/types"
15+
"github.com/sirupsen/logrus"
16+
)
17+
18+
// LoadTarget represents the target for the load test
19+
type LoadTarget struct {
20+
ctx context.Context
21+
taskCtx *types.TaskContext
22+
wallet *wallet.Wallet
23+
logger logrus.FieldLogger
24+
node *execution.Client
25+
}
26+
27+
// NewLoadTarget creates a new LoadTarget instance
28+
func NewLoadTarget(ctx context.Context, taskCtx *types.TaskContext, logger logrus.FieldLogger,
29+
w *wallet.Wallet, client *execution.Client) *LoadTarget {
30+
return &LoadTarget{
31+
ctx: ctx,
32+
taskCtx: taskCtx,
33+
wallet: w,
34+
logger: logger,
35+
node: client,
36+
}
37+
}
38+
39+
// GenerateTransaction creates a new transaction for the load test
40+
func (t *LoadTarget) GenerateTransaction(i int) (*ethtypes.Transaction, error) {
41+
tx, err := t.wallet.BuildTransaction(t.ctx, func(_ context.Context, nonce uint64, _ bind.SignerFn) (*ethtypes.Transaction, error) {
42+
addr := t.wallet.GetAddress()
43+
toAddr := &addr
44+
45+
txAmount, _ := crand.Int(crand.Reader, big.NewInt(0).SetUint64(10*1e18))
46+
47+
feeCap := &helper.BigInt{Value: *big.NewInt(100000000000)} // 100 Gwei
48+
tipCap := &helper.BigInt{Value: *big.NewInt(1000000000)} // 1 Gwei
49+
50+
txObj := &ethtypes.DynamicFeeTx{
51+
ChainID: t.taskCtx.Scheduler.GetServices().ClientPool().GetExecutionPool().GetBlockCache().GetChainID(),
52+
Nonce: nonce,
53+
GasTipCap: &tipCap.Value,
54+
GasFeeCap: &feeCap.Value,
55+
Gas: 50000,
56+
To: toAddr,
57+
Value: txAmount,
58+
Data: []byte(fmt.Sprintf("txIndex:%d", i)),
59+
}
60+
61+
return ethtypes.NewTx(txObj), nil
62+
})
63+
64+
if err != nil {
65+
return nil, err
66+
}
67+
68+
return tx, nil
69+
}
70+
71+
// SendTransaction sends a transaction to the execution node
72+
func (t *LoadTarget) SendTransaction(tx *ethtypes.Transaction) error {
73+
return t.node.GetRPCClient().SendTransaction(t.ctx, tx)
74+
}
Lines changed: 111 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,111 @@
1+
package txloadtool
2+
3+
import (
4+
"context"
5+
"fmt"
6+
"time"
7+
8+
"github.com/ethereum/go-ethereum/eth/protocols/eth"
9+
10+
"math/big"
11+
12+
"github.com/erigontech/assertoor/pkg/coordinator/clients/execution"
13+
"github.com/erigontech/assertoor/pkg/coordinator/types"
14+
"github.com/erigontech/assertoor/pkg/coordinator/utils/sentry"
15+
"github.com/ethereum/go-ethereum/core/forkid"
16+
"github.com/ethereum/go-ethereum/params"
17+
"github.com/sirupsen/logrus"
18+
)
19+
20+
// Peer connects to an execution client (a bockchain node) on the p2p network (i.e., the peer of the node)
21+
type Peer struct {
22+
ctx context.Context
23+
taskCtx *types.TaskContext
24+
logger logrus.FieldLogger
25+
node *execution.Client
26+
conn *sentry.Conn
27+
}
28+
29+
// NewPeer creates a new peer
30+
func NewPeer(ctx context.Context, taskCtx *types.TaskContext, logger logrus.FieldLogger, client *execution.Client) *Peer {
31+
return &Peer{
32+
ctx: ctx,
33+
taskCtx: taskCtx,
34+
logger: logger,
35+
node: client,
36+
conn: nil,
37+
}
38+
}
39+
40+
// Close closes the connection to the execution node
41+
func (p *Peer) Close() error {
42+
if p.conn != nil {
43+
err := p.conn.Close()
44+
p.conn = nil
45+
46+
return err
47+
}
48+
49+
return nil
50+
}
51+
52+
// Connect establishes a connection to the execution node and performs the handshake
53+
func (p *Peer) Connect() error {
54+
chainConfig := params.AllDevChainProtocolChanges
55+
56+
head, err := p.node.GetRPCClient().GetLatestBlock(p.ctx)
57+
if err != nil {
58+
p.taskCtx.SetResult(types.TaskResultFailure)
59+
return err
60+
}
61+
62+
chainID, err := p.node.GetRPCClient().GetEthClient().ChainID(p.ctx)
63+
if err != nil {
64+
return err
65+
}
66+
67+
chainConfig.ChainID = chainID
68+
69+
genesis, err := p.node.GetRPCClient().GetEthClient().BlockByNumber(p.ctx, new(big.Int).SetUint64(0))
70+
if err != nil {
71+
p.logger.Errorf("Failed to fetch genesis block: %v", err)
72+
p.taskCtx.SetResult(types.TaskResultFailure)
73+
74+
return err
75+
}
76+
77+
conn, err := sentry.GetTCPConn(p.node)
78+
if err != nil {
79+
p.logger.Errorf("Failed to get TCP connection: %v", err)
80+
p.taskCtx.SetResult(types.TaskResultFailure)
81+
82+
return err
83+
}
84+
85+
p.conn = conn
86+
forkID := forkid.NewID(chainConfig, genesis, head.NumberU64(), head.Time())
87+
88+
// handshake
89+
err = p.conn.Peer(chainConfig.ChainID, genesis.Hash(), head.Hash(), forkID, nil)
90+
if err != nil {
91+
return err
92+
}
93+
94+
p.logger.Infof("Connected to %s", p.node.GetName())
95+
96+
return nil
97+
}
98+
99+
func (p *Peer) ReadTransactionMessages(timeout time.Duration) (*eth.TransactionsPacket, error) {
100+
// Check if the connection is nil
101+
if p.conn == nil {
102+
p.logger.Errorf("Peer has no active connection, cannot read transaction messages")
103+
p.taskCtx.SetResult(types.TaskResultFailure)
104+
105+
return nil, fmt.Errorf("peer has no active connection, cannot read transaction messages")
106+
}
107+
108+
txs, err := p.conn.ReadTransactionMessages(timeout)
109+
110+
return txs, err
111+
}

0 commit comments

Comments
 (0)