@@ -2,32 +2,54 @@ package proposer
2
2
3
3
import (
4
4
"context"
5
- "math/big"
6
5
"os"
7
6
"testing"
8
7
"time"
9
8
10
9
"github.com/ethereum-optimism/optimism/op-service/txmgr"
11
10
"github.com/ethereum/go-ethereum/common"
11
+ "github.com/ethereum/go-ethereum/common/math"
12
12
"github.com/ethereum/go-ethereum/core/types"
13
13
"github.com/ethereum/go-ethereum/crypto"
14
+ "github.com/ethereum/go-ethereum/log"
15
+ "github.com/ethereum/go-ethereum/miner"
16
+ "github.com/ethereum/go-ethereum/rlp"
14
17
"github.com/stretchr/testify/suite"
15
18
16
19
"github.com/taikoxyz/taiko-client/bindings"
20
+ "github.com/taikoxyz/taiko-client/driver/chain_syncer/beaconsync"
21
+ "github.com/taikoxyz/taiko-client/driver/chain_syncer/calldata"
22
+ "github.com/taikoxyz/taiko-client/driver/state"
23
+ txlistfetcher "github.com/taikoxyz/taiko-client/driver/txlist_fetcher"
17
24
"github.com/taikoxyz/taiko-client/internal/testutils"
25
+ "github.com/taikoxyz/taiko-client/internal/utils"
18
26
"github.com/taikoxyz/taiko-client/pkg/jwt"
19
27
"github.com/taikoxyz/taiko-client/pkg/rpc"
20
28
)
21
29
22
30
type ProposerTestSuite struct {
23
31
testutils.ClientTestSuite
32
+ s * calldata.Syncer
24
33
p * Proposer
25
34
cancel context.CancelFunc
26
35
}
27
36
28
37
func (s * ProposerTestSuite ) SetupTest () {
29
38
s .ClientTestSuite .SetupTest ()
30
39
40
+ state2 , err := state .New (context .Background (), s .RPCClient )
41
+ s .Nil (err )
42
+
43
+ syncer , err := calldata .NewSyncer (
44
+ context .Background (),
45
+ s .RPCClient ,
46
+ state2 ,
47
+ beaconsync .NewSyncProgressTracker (s .RPCClient .L2 , 1 * time .Hour ),
48
+ 0 ,
49
+ )
50
+ s .Nil (err )
51
+ s .s = syncer
52
+
31
53
l1ProposerPrivKey , err := crypto .ToECDSA (common .FromHex (os .Getenv ("L1_PROPOSER_PRIVATE_KEY" )))
32
54
s .Nil (err )
33
55
@@ -82,6 +104,132 @@ func (s *ProposerTestSuite) SetupTest() {
82
104
s .cancel = cancel
83
105
}
84
106
107
+ func parseTxs (client * rpc.Client , event * bindings.TaikoL1ClientBlockProposed ) (types.Transactions , error ) {
108
+ tx , err := client .L1 .TransactionInBlock (context .Background (), event .Raw .BlockHash , event .Raw .TxIndex )
109
+ if err != nil {
110
+ return nil , err
111
+ }
112
+
113
+ // Decode transactions list.
114
+ var txListDecoder txlistfetcher.TxListFetcher
115
+ if event .Meta .BlobUsed {
116
+ txListDecoder = txlistfetcher .NewBlobTxListFetcher (client .L1Beacon )
117
+ } else {
118
+ txListDecoder = new (txlistfetcher.CalldataFetcher )
119
+ }
120
+ txListBytes , err := txListDecoder .Fetch (context .Background (), tx , & event .Meta )
121
+ if err != nil {
122
+ return nil , err
123
+ }
124
+
125
+ txListBytes , err = utils .Decompress (txListBytes )
126
+ if err != nil {
127
+ return nil , err
128
+ }
129
+
130
+ var txs types.Transactions
131
+ return txs , rlp .DecodeBytes (txListBytes , & txs )
132
+ }
133
+
134
+ func (s * ProposerTestSuite ) getLatestProposedTxs (
135
+ n int ,
136
+ timeout time.Duration ,
137
+ ) (<- chan []types.Transactions , error ) {
138
+ sink := make (chan * bindings.TaikoL1ClientBlockProposed )
139
+ sub , err := s .p .rpc .TaikoL1 .WatchBlockProposed (nil , sink , nil , nil )
140
+ if err != nil {
141
+ return nil , err
142
+ }
143
+
144
+ var resCh = make (chan []types.Transactions , 1 )
145
+ go func () {
146
+ defer sub .Unsubscribe ()
147
+
148
+ txLst := make ([]types.Transactions , 0 , n )
149
+ tick := time .After (timeout )
150
+ for len (txLst ) < cap (txLst ) {
151
+ select {
152
+ case event := <- sink :
153
+ txs , err := parseTxs (s .RPCClient , event )
154
+ if err != nil {
155
+ log .Error ("failed to parse txs" , "err" , err )
156
+ }
157
+ txLst = append (txLst , txs )
158
+ case <- tick :
159
+ return
160
+ }
161
+ }
162
+ resCh <- txLst
163
+ }()
164
+
165
+ return resCh , nil
166
+ }
167
+
168
+ func (s * ProposerTestSuite ) TestProposeOpNoEmptyBlock () {
169
+ defer s .Nil (s .s .ProcessL1Blocks (context .Background ()))
170
+
171
+ p := s .p
172
+
173
+ batchSize := 100
174
+
175
+ var err error
176
+ for i := 0 ; i < batchSize ; i ++ {
177
+ to := common .BytesToAddress (testutils .RandomBytes (32 ))
178
+ _ , err = testutils .SendDynamicFeeTx (s .RPCClient .L2 , s .TestAddrPrivKey , & to , nil , nil )
179
+ s .Nil (err )
180
+ }
181
+
182
+ var preBuiltTxList []* miner.PreBuiltTxList
183
+ for i := 0 ; i < 3 && len (preBuiltTxList ) == 0 ; i ++ {
184
+ preBuiltTxList , err = s .RPCClient .GetPoolContent (
185
+ context .Background (),
186
+ p .proposerAddress ,
187
+ p .protocolConfigs .BlockMaxGasLimit ,
188
+ rpc .BlockMaxTxListBytes ,
189
+ p .LocalAddresses ,
190
+ p .MaxProposedTxListsPerEpoch ,
191
+ )
192
+ time .Sleep (time .Second )
193
+ }
194
+ s .Nil (err )
195
+ s .Equal (true , len (preBuiltTxList ) > 0 )
196
+
197
+ txsCh , err := s .getLatestProposedTxs (len (preBuiltTxList ), time .Minute )
198
+ s .Nil (err )
199
+
200
+ var (
201
+ blockMinGasLimit uint64 = math .MaxUint64
202
+ blockMinTxListBytes uint64 = math .MaxUint64
203
+ txLists = make ([]types.Transactions , 0 , len (preBuiltTxList ))
204
+ )
205
+ for _ , txs := range preBuiltTxList {
206
+ if txs .EstimatedGasUsed <= blockMinGasLimit {
207
+ blockMinGasLimit = txs .EstimatedGasUsed
208
+ } else {
209
+ break
210
+ }
211
+ if txs .BytesLength <= blockMinTxListBytes {
212
+ blockMinTxListBytes = txs .BytesLength
213
+ } else {
214
+ break
215
+ }
216
+ txLists = append (txLists , txs .TxList )
217
+ }
218
+
219
+ // Start proposer
220
+ p .LocalAddressesOnly = false
221
+ p .MinGasUsed = blockMinGasLimit
222
+ p .MinTxListBytes = blockMinTxListBytes
223
+ p .ProposeInterval = time .Second
224
+ p .MinProposingInternal = time .Minute
225
+ s .Nil (p .ProposeOp (context .Background ()))
226
+
227
+ txs := <- txsCh
228
+ for i := 0 ; i < len (txLists ); i ++ {
229
+ s .Equal (txLists [i ].Len (), txs [i ].Len ())
230
+ }
231
+ }
232
+
85
233
func (s * ProposerTestSuite ) TestName () {
86
234
s .Equal ("proposer" , s .p .Name ())
87
235
}
@@ -97,29 +245,9 @@ func (s *ProposerTestSuite) TestProposeOp() {
97
245
close (sink )
98
246
}()
99
247
100
- nonce , err := s .p .rpc .L2 .PendingNonceAt (context .Background (), s .TestAddr )
101
- s .Nil (err )
102
-
103
- parent , err := s .p .rpc .L2 .BlockByNumber (context .Background (), nil )
104
- s .Nil (err )
105
-
106
- baseFeeInfo , err := s .p .rpc .TaikoL2 .GetBasefee (nil , 1 , uint32 (parent .GasUsed ()))
107
- s .Nil (err )
108
-
109
248
to := common .BytesToAddress (testutils .RandomBytes (32 ))
110
- tx := types .NewTx (& types.DynamicFeeTx {
111
- ChainID : s .RPCClient .L2 .ChainID ,
112
- Nonce : nonce ,
113
- GasTipCap : common .Big0 ,
114
- GasFeeCap : new (big.Int ).SetUint64 (baseFeeInfo .Basefee .Uint64 () * 2 ),
115
- Gas : 21000 ,
116
- To : & to ,
117
- Value : common .Big1 ,
118
- })
119
-
120
- signedTx , err := types .SignTx (tx , types .LatestSignerForChainID (s .p .rpc .L2 .ChainID ), s .TestAddrPrivKey )
249
+ _ , err = testutils .SendDynamicFeeTx (s .p .rpc .L2 , s .TestAddrPrivKey , & to , common .Big1 , nil )
121
250
s .Nil (err )
122
- s .Nil (s .p .rpc .L2 .SendTransaction (context .Background (), signedTx ))
123
251
124
252
s .Nil (s .p .ProposeOp (context .Background ()))
125
253
0 commit comments