diff --git a/tools/block-generator/generator/daemon.go b/tools/block-generator/generator/daemon.go index 36c49cac51..fb4f52bab3 100644 --- a/tools/block-generator/generator/daemon.go +++ b/tools/block-generator/generator/daemon.go @@ -31,13 +31,14 @@ func init() { var configFile string var port uint64 + var verbose bool DaemonCmd = &cobra.Command{ Use: "daemon", Short: "Start the generator daemon in standalone mode.", Run: func(cmd *cobra.Command, args []string) { addr := fmt.Sprintf(":%d", port) - srv, _ := MakeServer(configFile, addr) + srv, _ := MakeServer(configFile, addr, verbose) err := srv.ListenAndServe() if err != nil { panic(err) @@ -47,6 +48,7 @@ func init() { DaemonCmd.Flags().StringVarP(&configFile, "config", "c", "", "Specify the block configuration yaml file.") DaemonCmd.Flags().Uint64VarP(&port, "port", "p", 4010, "Port to start the server at.") + DaemonCmd.Flags().BoolVarP(&verbose, "verbose", "v", false, "If set the runner will print debugging information from the generator and ledger.") DaemonCmd.MarkFlagRequired("config") } diff --git a/tools/block-generator/generator/generate.go b/tools/block-generator/generator/generate.go index 3a899a33b4..22246e047b 100644 --- a/tools/block-generator/generator/generate.go +++ b/tools/block-generator/generator/generate.go @@ -32,25 +32,49 @@ import ( "github.com/algorand/go-algorand/data/basics" "github.com/algorand/go-algorand/data/bookkeeping" txn "github.com/algorand/go-algorand/data/transactions" + "github.com/algorand/go-algorand/data/transactions/logic" "github.com/algorand/go-algorand/ledger/ledgercore" "github.com/algorand/go-algorand/logging" "github.com/algorand/go-algorand/protocol" "github.com/algorand/go-algorand/rpcs" + "github.com/algorand/go-algorand/tools/block-generator/util" ) // ---- templates ---- //go:embed teal/poap_boxes.teal var approvalBoxes string +var approvalBoxesBytes interface{} //go:embed teal/poap_clear.teal var clearBoxes string +var clearBoxesBytes interface{} //go:embed teal/swap_amm.teal var approvalSwap string +var approvalSwapBytes interface{} //go:embed teal/swap_clear.teal var clearSwap string +var clearSwapBytes interface{} + +func init() { + prog, err := logic.AssembleString(approvalBoxes) + util.MaybeFail(err, "failed to assemble approval program") + approvalBoxesBytes = prog.Program + + prog, err = logic.AssembleString(clearBoxes) + util.MaybeFail(err, "failed to assemble clear program") + clearBoxesBytes = prog.Program + + prog, err = logic.AssembleString(approvalSwap) + util.MaybeFail(err, "failed to assemble approvalSwap program") + approvalSwapBytes = prog.Program + + prog, err = logic.AssembleString(clearSwap) + util.MaybeFail(err, "failed to assemble clearSwap program") + clearSwapBytes = prog.Program +} // ---- constructors ---- @@ -305,8 +329,8 @@ func (g *generator) WriteBlock(output io.Writer, round uint64) error { } return nil } - // round == nextRound case + // round == nextRound case err := g.startRound() if err != nil { return err @@ -321,6 +345,15 @@ func (g *generator) WriteBlock(output io.Writer, round uint64) error { // we'll write genesis block / offset round for non-empty database cert.Block, _, _ = g.ledger.BlockCert(basics.Round(round - g.roundOffset)) } else { + start := time.Now() + var generated, evaluated, validated time.Time + if g.verbose { + defer func() { + fmt.Printf("block generation stats txn generation (%s), ledger eval (%s), ledger add block (%s)\n", + generated.Sub(start), evaluated.Sub(generated), validated.Sub(evaluated)) + }() + } + g.setBlockHeader(&cert) intra := uint64(0) @@ -337,6 +370,7 @@ func (g *generator) WriteBlock(output io.Writer, round uint64) error { intra += numTxns } + generated = time.Now() vBlock, ledgerTxnCount, err := g.evaluateBlock(cert.Block.BlockHeader, txGroupsAD, int(intra)) if err != nil { @@ -345,11 +379,13 @@ func (g *generator) WriteBlock(output io.Writer, round uint64) error { if ledgerTxnCount != g.txnCounter+intra { return fmt.Errorf("evaluateBlock() txn count mismatches theoretical intra: %d != %d", ledgerTxnCount, g.txnCounter+intra) } + evaluated = time.Now() err = g.ledger.AddValidatedBlock(*vBlock, cert.Certificate) if err != nil { return fmt.Errorf("failed to add validated block: %w", err) } + validated = time.Now() cert.Block.Payset = vBlock.Block().Payset diff --git a/tools/block-generator/generator/make_transactions.go b/tools/block-generator/generator/make_transactions.go index e733d4339b..6caffe25b7 100644 --- a/tools/block-generator/generator/make_transactions.go +++ b/tools/block-generator/generator/make_transactions.go @@ -123,11 +123,11 @@ func (g *generator) makeAssetAcceptanceTxn(header txn.Header, index uint64) txn. // ---- application transactions ---- func (g *generator) makeAppCreateTxn(kind appKind, sender basics.Address, round, intra uint64, futureAppId uint64) []txn.SignedTxn { - var approval, clear string + var approval, clear interface{} if kind == appKindSwap { - approval, clear = approvalSwap, clearSwap + approval, clear = approvalSwapBytes, clearSwapBytes } else { - approval, clear = approvalBoxes, clearBoxes + approval, clear = approvalBoxesBytes, clearBoxesBytes } createTxn := g.makeTestTxn(sender, round, intra) diff --git a/tools/block-generator/generator/server.go b/tools/block-generator/generator/server.go index 4de0d08322..edfe470f3d 100644 --- a/tools/block-generator/generator/server.go +++ b/tools/block-generator/generator/server.go @@ -29,11 +29,11 @@ import ( ) // MakeServer configures http handlers. Returns the http server. -func MakeServer(configFile string, addr string) (*http.Server, Generator) { +func MakeServer(configFile string, addr string, verbose bool) (*http.Server, Generator) { noOp := func(next http.Handler) http.Handler { return next } - return MakeServerWithMiddleware(nil, 0, "", configFile, false, addr, noOp) + return MakeServerWithMiddleware(nil, 0, "", configFile, verbose, addr, noOp) } // BlocksMiddleware is a middleware for the blocks endpoint.