@@ -2,43 +2,19 @@ package benchmark
22
33import (
44 "math/big"
5+ "sync"
56 "testing"
7+ "time"
68
79 "github.com/0xPolygon/polygon-edge/consensus/polybft/contractsapi"
810 "github.com/0xPolygon/polygon-edge/e2e-polybft/framework"
911 "github.com/0xPolygon/polygon-edge/txrelayer"
1012 "github.com/0xPolygon/polygon-edge/types"
1113 "github.com/stretchr/testify/require"
1214 "github.com/umbracle/ethgo"
13- "github.com/umbracle/ethgo/abi"
1415 "github.com/umbracle/ethgo/wallet"
1516)
1617
17- var (
18- singleContCalcFunc = abi .MustNewMethod ("function compute(uint256 x, uint256 y) public returns (uint256)" )
19- singleContGetFunc = abi .MustNewMethod ("function getValue() public returns (uint256[] memory)" )
20- singleContSetFunc = abi .MustNewMethod ("function addValue(uint256 value) public" )
21- multiContSetAddrFunc = abi .MustNewMethod ("function setContractAddr(address _contract) public" )
22- multiContFnA = abi .MustNewMethod ("function fnA() public returns (uint256)" )
23- )
24-
25- // The rootChildSendTx function executes test cases that measure transaction execution on both the root and child chains
26- // To do this, it first calls RootChildSendTxSetUp to set up the testing environment,
27- // which may include starting the cluster, deploying contracts, and building the test cases.
28- // After building the test cases, rootChildSendTx returns them along with a cleanup function that should be called
29- // after the test cases have been executed. The test cases are executed by the TxTestCasesExecutor.
30- func rootChildSendTx (b * testing.B ) {
31- b .Helper ()
32- // set up environment, get test cases and clean up fn
33- testCases , cleanUpFn := RootChildSendTxSetUp (b , "" , "" , "" , true )
34- defer cleanUpFn ()
35-
36- // Loop over the test cases and measure the execution time of the transactions
37- for _ , testInput := range testCases {
38- TxTestCasesExecutor (b , testInput )
39- }
40- }
41-
4218// RootChildSendTxSetUp sets environment for execution of sentTx test cases on both root and child chains and
4319// returns test cases and clean up fn.
4420// The rootJSONRPC, childJSONRPC, privateKey and startCluster params are used to configure the testing environment.
@@ -111,14 +87,14 @@ func RootChildSendTxSetUp(b *testing.B, rootNodeAddr, childNodeAddr,
11187 // set callee contract addresses for multi call contracts (A->B->C)
11288 // set B contract address in A contract
11389 setContractDependencyAddress (b , childTxRelayer , multiAContChildAddr , multiBContChildAddr ,
114- multiContSetAddrFunc , sender )
90+ multiContSetAAddrFunc , sender )
11591 setContractDependencyAddress (b , rootTxRelayer , multiAContRootAddr , multiBContRootAddr ,
116- multiContSetAddrFunc , sender )
92+ multiContSetAAddrFunc , sender )
11793 // set C contract address in B contract
11894 setContractDependencyAddress (b , childTxRelayer , multiBContChildAddr , multiCContChildAddr ,
119- multiContSetAddrFunc , sender )
95+ multiContSetBAddrFunc , sender )
12096 setContractDependencyAddress (b , rootTxRelayer , multiBContRootAddr , multiCContRootAddr ,
121- multiContSetAddrFunc , sender )
97+ multiContSetBAddrFunc , sender )
12298
12399 // create inputs for contract calls
124100 singleContInputs := map [string ][]byte {
@@ -198,3 +174,74 @@ func RootChildSendTxSetUp(b *testing.B, rootNodeAddr, childNodeAddr,
198174
199175 return testCases , cleanUpFn
200176}
177+
178+ // TxTestCase represents a test case data to be run with txTestCasesExecutor
179+ type TxTestCase struct {
180+ Name string
181+ Relayer txrelayer.TxRelayer
182+ ContractAddr ethgo.Address
183+ Input [][]byte
184+ Sender ethgo.Key
185+ TxNumber int
186+ }
187+
188+ // TxTestCasesExecutor executes transactions from testInput and waits in separate
189+ // go routins for each tx receipt
190+ func TxTestCasesExecutor (b * testing.B , testInput TxTestCase ) {
191+ b .Helper ()
192+ b .Run (testInput .Name , func (b * testing.B ) {
193+ b .ReportAllocs ()
194+ b .ResetTimer ()
195+ var wg sync.WaitGroup
196+
197+ // submit all tx 'repeatCall' times
198+ for i := 0 ; i < testInput .TxNumber ; i ++ {
199+ // call contract for the all inputs
200+ for j := 0 ; j < len (testInput .Input ); j ++ {
201+ nonce , err := testInput .Relayer .Client ().Eth ().GetNonce (testInput .Sender .Address (), ethgo .Pending )
202+ require .NoError (b , err )
203+
204+ // the tx is submitted to the blockchain without waiting for the receipt,
205+ // since we want to have multiple tx in one block
206+ txHash , err := testInput .Relayer .SumbitTransaction (
207+ & ethgo.Transaction {
208+ To : & testInput .ContractAddr ,
209+ Input : testInput .Input [j ],
210+ }, testInput .Sender )
211+ require .NoError (b , err )
212+ require .NotEqual (b , ethgo .ZeroHash , txHash )
213+
214+ wg .Add (1 )
215+
216+ // wait for receipt of submitted tx in a separate routine, and continue with the next tx
217+ go func (hash ethgo.Hash ) {
218+ defer wg .Done ()
219+
220+ receipt , err := testInput .Relayer .WaitForReceipt (hash )
221+ require .NoError (b , err )
222+ require .Equal (b , uint64 (types .ReceiptSuccess ), receipt .Status )
223+ }(txHash )
224+
225+ // wait for tx to be added in mem pool so that we can create tx with the next nonce
226+ waitForNextNonce (b , nonce , testInput .Sender .Address (), testInput .Relayer )
227+ }
228+ }
229+
230+ wg .Wait ()
231+ })
232+ }
233+
234+ func waitForNextNonce (b * testing.B , nonce uint64 , address ethgo.Address , txRelayer txrelayer.TxRelayer ) {
235+ startTime := time .Now ()
236+
237+ for {
238+ newNonce , err := txRelayer .Client ().Eth ().GetNonce (address , ethgo .Pending )
239+ require .NoError (b , err )
240+ if newNonce > nonce {
241+ return
242+ }
243+
244+ elapsedTime := time .Since (startTime )
245+ require .True (b , elapsedTime <= 5 * time .Second , "tx not added to the mem poolin 2s" )
246+ }
247+ }
0 commit comments