77 "time"
88
99 "github.com/sei-protocol/sei-chain/sei-db/state_db/bench/wrappers"
10+ "golang.org/x/time/rate"
1011)
1112
1213const (
@@ -17,8 +18,9 @@ const (
1718
1819// EVM key sizes (matches sei-db/common/evm).
1920const (
20- AddressLen = 20 // EVM address length
21- SlotLen = 32 // EVM storage slot length
21+ AddressLen = 20 // EVM address length
22+ SlotLen = 32 // EVM storage slot length
23+ StorageKeyLen = AddressLen + SlotLen
2224)
2325
2426// The test runner for the cryptosim benchmark.
@@ -74,6 +76,12 @@ type CryptoSim struct {
7476 // This is fixed after initial setup is complete, since we don't currently simulate
7577 // the creation of new ERC20 contracts during the benchmark.
7678 nextERC20ContractID int64
79+
80+ // The channel that holds blocks sent to the receipt store.
81+ recieptsChan chan * block
82+
83+ // Enforces a maximum transaction rate (if enabled).
84+ rateLimiter * rate.Limiter
7785}
7886
7987// Creates a new cryptosim benchmark runner.
@@ -137,7 +145,7 @@ func NewCryptoSim(
137145
138146 start := time .Now ()
139147
140- database := NewDatabase (config , db , metrics )
148+ database := NewDatabase (config , db , metrics , 0 )
141149
142150 dataGenerator , err := NewDataGenerator (config , database , rand , metrics )
143151 if err != nil {
@@ -147,6 +155,7 @@ func NewCryptoSim(
147155 }
148156 return nil , fmt .Errorf ("failed to create data generator: %w" , err )
149157 }
158+ database .nextBlockNumber = dataGenerator .InitialNextBlockNumber ()
150159 threadCount := int (config .ThreadsPerCore )* runtime .NumCPU () + config .ConstantThreadCount
151160 if threadCount < 1 {
152161 threadCount = 1
@@ -156,7 +165,23 @@ func NewCryptoSim(
156165 executors := make ([]* TransactionExecutor , threadCount )
157166 for i := 0 ; i < threadCount ; i ++ {
158167 executors [i ] = NewTransactionExecutor (
159- ctx , cancel , database , dataGenerator .FeeCollectionAddress (), config .ExecutorQueueSize , metrics )
168+ ctx , cancel , config , database , dataGenerator .FeeCollectionAddress (), config .ExecutorQueueSize , metrics )
169+ }
170+
171+ var recieptsChan chan * block
172+ if config .GenerateReceipts {
173+ recieptsChan = make (chan * block , config .RecieptChannelCapacity )
174+ _ , err := NewRecieptStoreSimulator (ctx , config , recieptsChan , metrics )
175+ if err != nil {
176+ cancel ()
177+ return nil , fmt .Errorf ("failed to create receipt store simulator: %w" , err )
178+ }
179+ metrics .startReceiptChannelDepthSampling (recieptsChan , config .BackgroundMetricsScrapeInterval )
180+ }
181+
182+ var rateLimiter * rate.Limiter
183+ if config .MaxTPS > 0 {
184+ rateLimiter = rate .NewLimiter (rate .Limit (config .MaxTPS ), config .TransactionsPerBlock )
160185 }
161186
162187 blockBuilder := NewBlockBuilder (ctx , config , metrics , dataGenerator )
@@ -175,6 +200,8 @@ func NewCryptoSim(
175200 executors : executors ,
176201 metrics : metrics ,
177202 suspendChan : make (chan bool , 1 ),
203+ recieptsChan : recieptsChan ,
204+ rateLimiter : rateLimiter ,
178205 }
179206
180207 database .SetFlushFunc (c .flushExecutors )
@@ -233,7 +260,7 @@ func (c *CryptoSim) setupAccounts() error {
233260 if err != nil {
234261 return fmt .Errorf ("failed to create new account: %w" , err )
235262 }
236- c .database .IncrementTransactionCount (1 )
263+ c .database .IncrementTransactionCount ()
237264 finalized , err := c .database .MaybeFinalizeBlock (
238265 c .dataGenerator .NextAccountID (), c .dataGenerator .NextErc20ContractID ())
239266 if err != nil {
@@ -255,7 +282,8 @@ func (c *CryptoSim) setupAccounts() error {
255282 fmt .Printf ("Created %s of %s accounts. \n " ,
256283 int64Commas (c .dataGenerator .NextAccountID ()), int64Commas (int64 (requiredNumberOfAccounts )))
257284
258- err := c .database .FinalizeBlock (c .dataGenerator .NextAccountID (), c .dataGenerator .NextErc20ContractID (), true )
285+ err := c .database .FinalizeBlock (
286+ c .dataGenerator .NextAccountID (), c .dataGenerator .NextErc20ContractID (), true )
259287 if err != nil {
260288 return fmt .Errorf ("failed to finalize block: %w" , err )
261289 }
@@ -290,7 +318,7 @@ func (c *CryptoSim) setupErc20Contracts() error {
290318 break
291319 }
292320
293- c .database .IncrementTransactionCount (1 )
321+ c .database .IncrementTransactionCount ()
294322
295323 _ , _ , err := c .dataGenerator .CreateNewErc20Contract (c .config .Erc20ContractSize , true )
296324 if err != nil {
@@ -320,7 +348,10 @@ func (c *CryptoSim) setupErc20Contracts() error {
320348 fmt .Printf ("Created %s of %s simulated ERC20 contracts. \n " ,
321349 int64Commas (c .dataGenerator .NextErc20ContractID ()), int64Commas (int64 (c .config .MinimumNumberOfErc20Contracts )))
322350
323- err := c .database .FinalizeBlock (c .dataGenerator .NextAccountID (), c .dataGenerator .NextErc20ContractID (), true )
351+ err := c .database .FinalizeBlock (
352+ c .dataGenerator .NextAccountID (),
353+ c .dataGenerator .NextErc20ContractID (),
354+ true )
324355 if err != nil {
325356 return fmt .Errorf ("failed to finalize block: %w" , err )
326357 }
@@ -365,19 +396,38 @@ func (c *CryptoSim) run() {
365396 c .cancel ()
366397 return
367398 case blk := <- c .blockBuilder .blocksChan :
399+ c .maybeThrottle ()
368400 c .handleNextBlock (blk )
369401 }
370402
371403 c .generateConsoleReport (false )
372404 }
373405}
374406
407+ // Potentially block for a while if we are throttling the transaction rate.
408+ func (c * CryptoSim ) maybeThrottle () {
409+ if c .config .MaxTPS == 0 {
410+ // Throttling is disabled.
411+ return
412+ }
413+
414+ c .metrics .SetMainThreadPhase ("throttling" )
415+
416+ if err := c .rateLimiter .WaitN (c .ctx , c .config .TransactionsPerBlock ); err != nil {
417+ fmt .Printf ("failed to wait for rate limit: %v\n " , err )
418+ c .cancel ()
419+ return
420+ }
421+ }
422+
375423// Execute and finalize the next block.
376424func (c * CryptoSim ) handleNextBlock (blk * block ) {
377425 c .mostRecentBlock = blk
378426 c .metrics .SetMainThreadPhase ("send_to_executors" )
379427
380- c .database .IncrementTransactionCount (blk .TransactionCount ())
428+ for i := int64 (0 ); i < blk .TransactionCount (); i ++ {
429+ c .database .IncrementTransactionCount ()
430+ }
381431
382432 for txn := range blk .Iterator () {
383433 c .executors [c .nextExecutorIndex ].ScheduleForExecution (txn )
@@ -389,6 +439,15 @@ func (c *CryptoSim) handleNextBlock(blk *block) {
389439 c .cancel ()
390440 return
391441 }
442+
443+ if c .config .GenerateReceipts {
444+ select {
445+ case <- c .ctx .Done ():
446+ return
447+ case c .recieptsChan <- blk :
448+ }
449+ }
450+
392451 blk .ReportBlockMetrics ()
393452}
394453
0 commit comments