Repository: algorand/indexer
Pull request #541 (2021-06-11 20:48:54)

Replace `GetMaxRoundLoaded()` with `GetNextRoundToLoad()`
Also fixes a bug in `GetMaxRoundLoaded()`.


Patch:
diff --git a/cmd/algorand-indexer/daemon.go b/cmd/algorand-indexer/daemon.go
index da16fae..958c196 100644
--- a/cmd/algorand-indexer/daemon.go
+++ b/cmd/algorand-indexer/daemon.go
@@ -82,15 +82,14 @@ var daemonCmd = &cobra.Command{
 		db := indexerDbFromFlags(opts)
 		if bot != nil {
 			logger.Info("Initializing block import handler.")
-			maxRound, err := db.GetMaxRoundLoaded()
-			if err == idb.ErrorNotInitialized {
-				bot.SetNextRound(0)
-			} else {
-				maybeFail(err, "failed to get max round, %v", err)
-				bot.SetNextRound(maxRound + 1)
-			}
+
+			nextRound, err := db.GetNextRoundToLoad()
+			maybeFail(err, "failed to get next round, %v", err)
+			bot.SetNextRound(nextRound)
+
 			cache, err := db.GetDefaultFrozen()
 			maybeFail(err, "failed to get default frozen cache")
+
 			bih := blockImporterHandler{
 				imp:   importer.NewDBImporter(db),
 				db:    db,
@@ -98,6 +97,7 @@ var daemonCmd = &cobra.Command{
 			}
 			bot.AddBlockHandler(&bih)
 			bot.SetContext(ctx)
+
 			go func() {
 				waitForDBAvailable(db)
 
diff --git a/cmd/algorand-indexer/reset.go b/cmd/algorand-indexer/reset.go
index f4dc574..b2f54ca 100644
--- a/cmd/algorand-indexer/reset.go
+++ b/cmd/algorand-indexer/reset.go
@@ -59,17 +59,20 @@ var resetCmd = &cobra.Command{
 				err = db.Reset()
 				maybeFail(err, "database reset failed")
 				if andRebuild {
-					blockround, err := db.GetMaxRoundLoaded()
-					maybeFail(err, "could not find max block loaded, %v", err)
-					if blockround > 0 {
-						fmt.Printf("Done resetting. Re-building accounting through block %d...", blockround)
+					nextRound, err := db.GetNextRoundToLoad()
+					maybeFail(err, "failed to get next round, %v", err)
+
+					if nextRound > 0 {
+						fmt.Printf(
+							"Done resetting. Re-building accounting through block %d...",
+							nextRound-1)
 						opts.NoMigrate = false
 						// db.Close() // TODO: add Close() to IndxerDb interface?
 						db = indexerDbFromFlags(opts)
 						cache, err := db.GetDefaultFrozen()
 						maybeFail(err, "failed to get default frozen cache")
 						filter := idb.UpdateFilter{
-							MaxRound: blockround,
+							MaxRound: nextRound - 1,
 						}
 						importer.UpdateAccounting(db, cache, filter, logger)
 						fmt.Println("Done rebuilding accounting.")
diff --git a/cmd/block-generator/daemon.go b/cmd/block-generator/daemon.go
new file mode 100644
index 0000000..34450c3
--- /dev/null
+++ b/cmd/block-generator/daemon.go
@@ -0,0 +1,32 @@
+package main
+
+import (
+	"math/rand"
+
+	"github.com/algorand/indexer/cmd/block-generator/generator"
+	"github.com/spf13/cobra"
+)
+
+const configFileName = "block_generator_config"
+
+func init() {
+	rand.Seed(12345)
+
+	var configFile string
+	var port uint64
+
+	var daemonCmd = &cobra.Command{
+		Use:   "daemon",
+		Short: "Start the generator daemon in standalone mode.",
+		Run: func(cmd *cobra.Command, args []string) {
+			generator.StartServer(configFile, port)
+		},
+	}
+
+	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.MarkFlagRequired("config")
+
+	rootCmd.AddCommand(daemonCmd)
+}
diff --git a/cmd/block-generator/docker/Dockerfile-generator b/cmd/block-generator/docker/Dockerfile-generator
index bad5b7e..16c7e70 100644
--- a/cmd/block-generator/docker/Dockerfile-generator
+++ b/cmd/block-generator/docker/Dockerfile-generator
@@ -10,4 +10,4 @@ RUN go build
 RUN ls
 RUN mkdir /config
 RUN cp test_config.yml /config/config.yml
-CMD ["/bin/sh", "-c", "./block-generator -port 11111 -config /config/config.yml"]
+CMD ["/bin/sh", "-c", "./block-generator daemon --port 11111 --config /config/config.yml"]
diff --git a/cmd/block-generator/docker/Dockerfile-indexer b/cmd/block-generator/docker/Dockerfile-indexer
index 59b1ef5..bfb17c6 100644
--- a/cmd/block-generator/docker/Dockerfile-indexer
+++ b/cmd/block-generator/docker/Dockerfile-indexer
@@ -11,7 +11,7 @@ RUN go build
 CMD ["/bin/sh", "-c", "\
   echo $ALGOD_NET && \
   echo $CONNECTION_STRING &&\
-  sleep 10 && \
+  sleep 5 && \
   ./algorand-indexer daemon \
     --server \":${PORT}\" \
     -P \"${CONNECTION_STRING}\" \
diff --git a/cmd/block-generator/docker/docker-compose.yml b/cmd/block-generator/docker/docker-compose.yml
index 2f74f05..694c5a8 100644
--- a/cmd/block-generator/docker/docker-compose.yml
+++ b/cmd/block-generator/docker/docker-compose.yml
@@ -13,6 +13,7 @@ services:
     volumes:
       # Override generator config file.
       - ../scenarios/config.mixed.jumbo.yml:/config/config.yml
+        #- ../scenarios/config.payment.small.yml:/config/config.yml
 
   indexer:
     container_name: "indexer"
diff --git a/cmd/block-generator/generator/generate.go b/cmd/block-generator/generator/generate.go
index df63580..1e8120b 100644
--- a/cmd/block-generator/generator/generate.go
+++ b/cmd/block-generator/generator/generate.go
@@ -409,13 +409,16 @@ func getPaymentTxOptions() []interface{} {
 
 // generatePaymentTxn creates a new payment transaction. The sender is always a genesis account, the receiver is random,
 // or a new account.
-func (g *generator) generatePaymentTxn(sp sdk_types.SuggestedParams, _ uint64 /*round*/, _ uint64 /*intra*/) (types.SignedTxnInBlock, error) {
+func (g *generator) generatePaymentTxn(sp sdk_types.SuggestedParams, round uint64, intra uint64) (types.SignedTxnInBlock, error) {
 	selection, err := weightedSelection(g.payTxWeights, getPaymentTxOptions(), paymentTx)
 	if err != nil {
 		return types.SignedTxnInBlock{}, err
 	}
+	return g.generatePaymentTxnInternal(selection.(txTypeID), sp, round, intra)
+}
 
-	defer g.recordData(track(selection.(txTypeID)))
+func (g *generator) generatePaymentTxnInternal(selection txTypeID, sp sdk_types.SuggestedParams, _ uint64 /*round*/, _ uint64 /*intra*/) (types.SignedTxnInBlock, error) {
+	defer g.recordData(track(selection))
 
 	var receiveIndex uint64
 	switch selection {
diff --git a/cmd/block-generator/generator/server.go b/cmd/block-generator/generator/server.go
new file mode 100644
index 0000000..b961840
--- /dev/null
+++ b/cmd/block-generator/generator/server.go
@@ -0,0 +1,108 @@
+package generator
+
+import (
+	"fmt"
+	"net/http"
+	"os"
+	"strings"
+
+	"github.com/spf13/viper"
+
+	"github.com/algorand/indexer/util"
+)
+
+func initializeConfigFile(configFile string) (config GenerationConfig, err error) {
+	f, err := os.Open(configFile)
+	if err != nil {
+		return
+	}
+
+	viper.SetConfigType("yaml")
+	viper.AddConfigPath(".")
+	err = viper.ReadConfig(f)
+
+	// Problem reading config
+	if err != nil {
+		return
+	}
+
+	err = viper.Unmarshal(&config)
+	return
+}
+
+// StartServer configures http handlers then runs ListanAndServe.
+func StartServer(configFile string, port uint64) {
+	config, err := initializeConfigFile(configFile)
+	util.MaybeFail(err, "problem loading config file. Use '--config' or create a config file.")
+
+	gen, err := MakeGenerator(config)
+	if err != nil {
+		fmt.Fprintf(os.Stderr, "Unable to create generator: %v", err)
+		os.Exit(1)
+	}
+
+	http.HandleFunc("/", help)
+	http.HandleFunc("/v2/blocks/", getBlockHandler(gen))
+	http.HandleFunc("/genesis", getGenesisHandler(gen))
+	http.HandleFunc("/report", getReportHandler(gen))
+
+	portStr := fmt.Sprintf(":%d", port)
+	fmt.Printf("Starting server at %s\n", portStr)
+	http.ListenAndServe(portStr, nil)
+}
+
+func help(w http.ResponseWriter, r *http.Request) {
+	fmt.Fprintf(w, "Use /v2/blocks/:blocknum: to get a block.")
+}
+
+func getReportHandler(gen Generator) func(w http.ResponseWriter, r *http.Request) {
+	return func(w http.ResponseWriter, r *http.Request) {
+		gen.WriteReport(w)
+	}
+}
+
+func getGenesisHandler(gen Generator) func(w http.ResponseWriter, r *http.Request) {
+	return func(w http.ResponseWriter, r *http.Request) {
+		gen.WriteGenesis(w)
+	}
+}
+
+func getBlockHandler(gen Generator) func(w http.ResponseWriter, r *http.Request) {
+	return func(w http.ResponseWriter, r *http.Request) {
+		// The generator doesn't actually care about the block...
+		round, err := parseRound(r.URL.Path)
+		if err != nil {
+			fmt.Fprintf(w, err.Error())
+			return
+		}
+
+		gen.WriteBlock(w, round)
+	}
+}
+
+const blockQueryPrefix = "/v2/blocks/"
+const blockQueryBlockIdx = len(blockQueryPrefix)
+
+func parseRound(path string) (uint64, error) {
+	if !strings.HasPrefix(path, blockQueryPrefix) {
+		return 0, fmt.Errorf("not a blocks query: %s", path)
+	}
+
+	result := uint64(0)
+	pathlen := len(path)
+
+	if pathlen == blockQueryBlockIdx {
+		return 0, fmt.Errorf("no block in path")
+	}
+
+	for i := blockQueryBlockIdx; i < pathlen; i++ {
+		if path[i] < '0' || path[i] > '9' {
+			if i == blockQueryBlockIdx {
+				return 0, fmt.Errorf("no block in path")
+			}
+			break
+		}
+		result = (uint64(10) * result) + uint64(int(path[i])-'0')
+	}
+	return result, nil
+}
diff --git a/cmd/block-generator/main.go b/cmd/block-generator/main.go
index 83939fc..26622fa 100644
--- a/cmd/block-generator/main.go
+++ b/cmd/block-generator/main.go
@@ -1,125 +1,12 @@
 package main
 
-import (
-	"flag"
-	"fmt"
-	"math/rand"
-	"net/http"
-	"os"
-	"strings"
+import "github.com/spf13/cobra"
 
-	"github.com/spf13/viper"
-
-	"github.com/algorand/indexer/cmd/block-generator/generator"
-	"github.com/algorand/indexer/util"
-)
-
-var configFile string
-var port uint
-var gen generator.Generator
-
-const configFileName = "block_generator_config"
-
-func init() {
-	rand.Seed(12345)
-	flag.StringVar(&configFile, "config", "", fmt.Sprintf("Override default config file from '%s'.", configFileName))
-	flag.UintVar(&port, "port", 4010, "Port to start the server at.")
-
-	viper.SetConfigName(configFileName)
-	viper.SetConfigType("yaml")
-	viper.AddConfigPath(".")
-}
-
-func initializeConfigFile() (config generator.GenerationConfig, err error) {
-	if len(configFile) > 0 {
-		var f *os.File
-		f, err = os.Open(configFile)
-		if err != nil {
-			return
-		}
-
-		err = viper.ReadConfig(f)
-	} else {
-		err = viper.ReadInConfig()
-	}
-
-	// Problem reading config
-	if err != nil {
-		return
-	}
-
-	err = viper.Unmarshal(&config)
-	return
+var rootCmd = &cobra.Command{
+	Use:   `block-generator`,
+	Short: `Block generator testing tools.`,
 }
 
 func main() {
-	flag.Parse()
-
-	config, err := initializeConfigFile()
-	util.MaybeFail(err, "problem loading config file. Use '-config' or create a config file.")
-
-	gen, err = generator.MakeGenerator(config)
-	if err != nil {
-		fmt.Fprintf(os.Stderr, "Unable to create generator: %v", err)
-		os.Exit(1)
-	}
-
-	http.HandleFunc("/", help)
-	http.HandleFunc("/v2/blocks/", handleBlock)
-	http.HandleFunc("/genesis", handleGenesis)
-	http.HandleFunc("/report", handleReport)
-
-	portStr := fmt.Sprintf(":%d", port)
-	fmt.Printf("Starting server at %s\n", portStr)
-	http.ListenAndServe(portStr, nil)
-}
-
-func help(w http.ResponseWriter, r *http.Request) {
-	fmt.Fprintf(w, "Use /v2/blocks/:blocknum: to get a block.")
-}
-
-func handleReport(w http.ResponseWriter, r *http.Request) {
-	gen.WriteReport(w)
-}
-
-func handleGenesis(w http.ResponseWriter, r *http.Request) {
-	gen.WriteGenesis(w)
-}
-
-func handleBlock(w http.ResponseWriter, r *http.Request) {
-	// The generator doesn't actually care about the block...
-	round, err := parseRound(r.URL.Path)
-	if err != nil {
-		fmt.Fprintf(w, err.Error())
-		return
-	}
-
-	gen.WriteBlock(w, round)
-}
-
-const blockQueryPrefix = "/v2/blocks/"
-const blockQueryBlockIdx = len(blockQueryPrefix)
-
-func parseRound(path string) (uint64, error) {
-	if !strings.HasPrefix(path, blockQueryPrefix) {
-		return 0, fmt.Errorf("not a blocks query: %s", path)
-	}
-
-	result := uint64(0)
-	pathlen := len(path)
-
-	if pathlen == blockQueryBlockIdx {
-		return 0, fmt.Errorf("no block in path")
-	}
-
-	for i := blockQueryBlockIdx; i < pathlen; i++ {
-		if path[i] < '0' || path[i] > '9' {
-			if i == blockQueryBlockIdx {
-				return 0, fmt.Errorf("no block in path")
-			}
-			break
-		}
-		result = (uint64(10) * result) + uint64(int(path[i])-'0')
-	}
-	return result, nil
+	rootCmd.Execute()
 }
diff --git a/cmd/block-generator/run_generator.sh b/cmd/block-generator/run_generator.sh
index eb4fa2a..47e87b2 100755
--- a/cmd/block-generator/run_generator.sh
+++ b/cmd/block-generator/run_generator.sh
@@ -45,11 +45,12 @@ popd
 echo "Starting postgres container."
 start_postgres
 echo "Starting block generator (see generator.log)"
-$(dirname "$0")/block-generator -port 11111 -config "${CONFIG}" &
+$(dirname "$0")/block-generator daemon --port 11111 --config "${CONFIG}" &
 GENERATOR_PID=$!
 echo "Starting indexer"
 $(dirname "$0")/../../cmd/algorand-indexer/algorand-indexer daemon \
               -S localhost:8980 \
               --algod-net localhost:11111 \
               --algod-token security-is-our-number-one-priority \
+              --metrics-mode VERBOSE \
               -P "host=localhost user=algorand password=algorand dbname=generator_db port=15432 sslmode=disable"
diff --git a/idb/dummy/dummy.go b/idb/dummy/dummy.go
index 1ea7a50..e6df86f 100644
--- a/idb/dummy/dummy.go
+++ b/idb/dummy/dummy.go
@@ -47,8 +47,8 @@ func (db *dummyIndexerDb) GetMaxRoundAccounted() (round uint64, err error) {
 	return 0, nil
 }
 
-// GetMaxRoundLoaded is part of idb.IndexerDB
-func (db *dummyIndexerDb) GetMaxRoundLoaded() (round uint64, err error) {
+// GetNextRoundToLoad is part of idb.IndexerDB
+func (db *dummyIndexerDb) GetNextRoundToLoad() (round uint64, err error) {
 	return 0, nil
 }
 
diff --git a/idb/idb.go b/idb/idb.go
index 3b12082..cb43435 100644
--- a/idb/idb.go
+++ b/idb/idb.go
@@ -87,8 +87,7 @@ type IndexerDb interface {
 
 	// GetMaxRoundAccounted returns ErrorNotInitialized if there are no accounted rounds.
 	GetMaxRoundAccounted() (round uint64, err error)
-	// GetMaxRoundLoaded returns ErrorNotInitialized if there are no loaded rounds.
-	GetMaxRoundLoaded() (round uint64, err error)
+	GetNextRoundToLoad() (round uint64, err error)
 	GetSpecialAccounts() (SpecialAccounts, error)
 	GetDefaultFrozen() (defaultFrozen map[uint64]bool, err error)
 
diff --git a/idb/mocks/IndexerDb.go b/idb/mocks/IndexerDb.go
index 51fea68..6f59627 100644
--- a/idb/mocks/IndexerDb.go
+++ b/idb/mocks/IndexerDb.go
@@ -226,8 +226,8 @@ func (_m *IndexerDb) GetMaxRoundAccounted() (uint64, error) {
 	return r0, r1
 }
 
-// GetMaxRoundLoaded provides a mock function with given fields:
-func (_m *IndexerDb) GetMaxRoundLoaded() (uint64, error) {
+// GetNextRoundToLoad provides a mock function with given fields:
+func (_m *IndexerDb) GetNextRoundToLoad() (uint64, error) {
 	ret := _m.Called()
 
 	var r0 uint64
diff --git a/idb/postgres/postgres.go b/idb/postgres/postgres.go
index ccbc4be..bebe523 100644
--- a/idb/postgres/postgres.go
+++ b/idb/postgres/postgres.go
@@ -37,7 +37,7 @@ import (
 
 type importState struct {
 	// Last accounted round.
-	AccountRound int64 `codec:"account_round"`
+	AccountRound *int64 `codec:"account_round"`
 }
 
 const stateMetastateKey = "state"
@@ -132,9 +132,9 @@ func (db *IndexerDb) txWithRetry(ctx context.Context, opts sql.TxOptions, f func
 }
 
 func (db *IndexerDb) init(opts idb.IndexerDbOptions) (err error) {
-	accountingStateJSON, _ := db.getMetastate(stateMetastateKey)
+	accountingStateJSON, _ := db.getMetastate(nil, stateMetastateKey)
 	hasAccounting := len(accountingStateJSON) > 0
-	migrationStateJSON, _ := db.getMetastate(migrationMetastateKey)
+	migrationStateJSON, _ := db.getMetastate(nil, migrationMetastateKey)
 	hasMigration := len(migrationStateJSON) > 0
 
 	db.GetSpecialAccounts()
@@ -333,19 +333,32 @@ func (db *IndexerDb) LoadGenesis(genesis types.Genesis) (err error) {
 			return fmt.Errorf("error setting genesis account[%d], %v", ai, err)
 		}
 	}
-	var importState importState
-	_, err = tx.Exec(
-		setMetastateUpsert, stateMetastateKey, encoding.EncodeJSON(importState))
+
+	round := int64(0)
+	importstate := importState{
+		AccountRound: &round,
+	}
+	err = db.setImportState(nil, importstate)
 	if err != nil {
 		return
 	}
+
 	err = tx.Commit()
 	db.log.Printf("genesis %d accounts %d microalgos, err=%v", len(genesis.Allocation), total, err)
 	return err
 }
 
-func (db *IndexerDb) getMetastate(key string) (jsonStrValue string, err error) {
-	row := db.db.QueryRow(`SELECT v FROM metastate WHERE k = $1`, key)
+// If `tx` is nil, use a normal query.
+func (db *IndexerDb) getMetastate(tx *sql.Tx, key string) (jsonStrValue string, err error) {
+	query := `SELECT v FROM metastate WHERE k = $1`
+
+	var row *sql.Row
+	if tx == nil {
+		row = db.db.QueryRow(query, key)
+	} else {
+		row = tx.QueryRow(query, key)
+	}
+
 	err = row.Scan(&jsonStrValue)
 	if err == sql.ErrNoRows {
 		err = nil
@@ -358,65 +371,86 @@ func (db *IndexerDb) getMetastate(key string) (jsonStrValue string, err error) {
 
 const setMetastateUpsert = `INSERT INTO metastate (k, v) VALUES ($1, $2) ON CONFLICT (k) DO UPDATE SET v = EXCLUDED.v`
 
-func (db *IndexerDb) setMetastate(key, jsonStrValue string) (err error) {
-	_, err = db.db.Exec(setMetastateUpsert, key, jsonStrValue)
-	return
-}
-
-// If `tx` is null, make a standalone query.
-func (db *IndexerDb) getMaxRoundAccounted(tx *sql.Tx) (round uint64, err error) {
-	query := `select v->>'account_round' from metastate where k = 'state'`
-
-	var row *sql.Row
+// If `tx` is nil, use a normal query.
+func (db *IndexerDb) setMetastate(tx *sql.Tx, key, jsonStrValue string) (err error) {
 	if tx == nil {
-		row = db.db.QueryRow(query)
+		_, err = db.db.Exec(setMetastateUpsert, key, jsonStrValue)
 	} else {
-		row = tx.QueryRow(query)
+		_, err = tx.Exec(setMetastateUpsert, key, jsonStrValue)
 	}
+	return
+}
 
-	var nullableRound sql.NullInt64
-	err = row.Scan(&nullableRound)
+// Returns idb.ErrorNotInitialized if uninitialized.
+// If `tx` is nil, use a normal query.
+func (db *IndexerDb) getImportState(tx *sql.Tx) (importState, error) {
+	importStateJSON, err := db.getMetastate(tx, stateMetastateKey)
 	if err == sql.ErrNoRows {
-		err = idb.ErrorNotInitialized
-		round = 0
+		return importState{}, idb.ErrorNotInitialized
+	}
+	if err != nil {
+		return importState{}, fmt.Errorf("unable to get import state err: %w", err)
+	}
+
+	if importStateJSON == "" {
+		return importState{}, idb.ErrorNotInitialized
 	}
 
+	var state importState
+	err = encoding.DecodeJSON([]byte(importStateJSON), &state)
 	if err != nil {
-		return
+		return importState{},
+			fmt.Errorf("unable to parse import state v: \"%s\" err: %w", importStateJSON, err)
 	}
 
-	if nullableRound.Valid {
-		round = uint64(nullableRound.Int64)
-	} else {
-		err = idb.ErrorNotInitialized
+	return state, nil
+}
+
+// If `tx` is nil, use a normal query.
+func (db *IndexerDb) setImportState(tx *sql.Tx, state importState) error {
+	return db.setMetastate(tx, stateMetastateKey, string(encoding.EncodeJSON(state)))
+}
+
+// Returns idb.ErrorNotInitialized if uninitialized.
+// If `tx` is nil, use a normal query.
+func (db *IndexerDb) getMaxRoundAccounted(tx *sql.Tx) (uint64, error) {
+	state, err := db.getImportState(tx)
+	if err == idb.ErrorNotInitialized {
+		return 0, err
+	}
+	if err != nil {
+		return 0, fmt.Errorf("getNextRoundToAccount() err: %w", err)
 	}
 
-	return
+	if state.AccountRound == nil {
+		return 0, idb.ErrorNotInitialized
+	}
+	return uint64(*state.AccountRound), nil
 }
 
 // GetMaxRoundAccounted is part of idb.IndexerDB
+// Returns idb.ErrorNotInitialized if uninitialized.
 func (db *IndexerDb) GetMaxRoundAccounted() (round uint64, err error) {
 	return db.getMaxRoundAccounted(nil)
 }
 
-// GetMaxRoundLoaded is part of idb.IndexerDB
-func (db *IndexerDb) GetMaxRoundLoaded() (round uint64, err error) {
-	var nullableRound sql.NullInt64
-	round = 0
+// GetNextRoundToLoad is part of idb.IndexerDB
+func (db *IndexerDb) GetNextRoundToLoad() (uint64, error) {
 	row := db.db.QueryRow(`SELECT max(round) FROM block_header`)
-	err = row.Scan(&nullableRound)
 
-	if err == sql.ErrNoRows || !nullableRound.Valid {
-		err = idb.ErrorNotInitialized
-		return
+	var nullableRound sql.NullInt64
+	err := row.Scan(&nullableRound)
+	if err == sql.ErrNoRows {
+		return 0, nil
 	}
-
 	if err != nil {
-		return
+		return 0, err
 	}
 
-	round = uint64(nullableRound.Int64)
-	return
+	if !nullableRound.Valid {
+		return 0, nil
+	}
+	return uint64(nullableRound.Int64 + 1), nil
 }
 
 // Break the read query so that PostgreSQL doesn't get bogged down
@@ -1251,30 +1285,28 @@ ON CONFLICT (addr, assetid) DO UPDATE SET amount = account_asset.amount + EXCLUD
 	if !any {
 		db.log.Debugf("empty round %d", round)
 	}
-	var importState importState
-	staterow := tx.QueryRow(`SELECT v FROM metastate WHERE k = 'state'`)
-	var stateJSONStr string
-	err = staterow.Scan(&stateJSONStr)
+
+	importstate, err := db.getImportState(tx)
 	if err != nil {
-		return
+		return err
 	}
-	err = encoding.DecodeJSON([]byte(stateJSONStr), &importState)
-	if err != nil {
-		return
+
+	if importstate.AccountRound == nil {
+		return fmt.Errorf("importstate.AccountRound is nil")
 	}
-	if importState.AccountRound >= int64(round) {
-		msg := fmt.Sprintf(
+
+	if uint64(*importstate.AccountRound) >= round {
+		return fmt.Errorf(
 			"metastate round = %d while trying to write round %d",
-			importState.AccountRound, round)
-		db.log.Error(msg)
-		return errors.New(msg)
+			*importstate.AccountRound, round)
 	}
-	importState.AccountRound = int64(round)
-	_, err = tx.Exec(
-		setMetastateUpsert, stateMetastateKey, encoding.EncodeJSON(importState))
+
+	*importstate.AccountRound = int64(round)
+	err = db.setImportState(tx, importstate)
 	if err != nil {
 		return
 	}
+
 	return tx.Commit()
 }
 
@@ -2904,7 +2936,7 @@ func (db *IndexerDb) Health() (idb.Health, error) {
 // GetSpecialAccounts is part of idb.IndexerDB
 func (db *IndexerDb) GetSpecialAccounts() (accounts idb.SpecialAccounts, err error) {
 	var cache string
-	cache, err = db.getMetastate(specialAccountsMetastateKey)
+	cache, err = db.getMetastate(nil, specialAccountsMetastateKey)
 	if err != nil || cache == "" {
 		// Initialize specialAccountsMetastateKey
 		var blockHeader types.BlockHeader
@@ -2919,7 +2951,7 @@ func (db *IndexerDb) GetSpecialAccounts() (accounts idb.SpecialAccounts, err err
 		}
 
 		cache := encoding.EncodeJSON(accounts)
-		err = db.setMetastate(specialAccountsMetastateKey, string(cache))
+		err = db.setMetastate(nil, specialAccountsMetastateKey, string(cache))
 		if err != nil {
 			return idb.SpecialAccounts{}, fmt.Errorf("problem saving metastate: %v", err)
 		}
diff --git a/idb/postgres/postgres_migrations.go b/idb/postgres/postgres_migrations.go
index bab3221..0333147 100644
--- a/idb/postgres/postgres_migrations.go
+++ b/idb/postgres/postgres_migrations.go
@@ -186,11 +186,11 @@ func (db *IndexerDb) markMigrationsAsDone() (err error) {
 		NextMigration: len(migrations),
 	}
 	migrationStateJSON := encoding.EncodeJSON(state)
-	return db.setMetastate(migrationMetastateKey, string(migrationStateJSON))
+	return db.setMetastate(nil, migrationMetastateKey, string(migrationStateJSON))
 }
 
 func (db *IndexerDb) getMigrationState() (*MigrationState, error) {
-	migrationStateJSON, err := db.getMetastate(migrationMetastateKey)
+	migrationStateJSON, err := db.getMetastate(nil, migrationMetastateKey)
 	if err == sql.ErrNoRows {
 		// no previous state, ok
 		return nil, nil
@@ -1268,7 +1268,7 @@ func (mtxid *txidFiuxpMigrationContext) asyncTxidFixup() (err error) {
 	state.NextMigration++
 	state.NextRound = 0
 	migrationStateJSON := encoding.EncodeJSON(state)
-	err = db.setMetastate(migrationMetastateKey, string(migrationStateJSON))
+	err = db.setMetastate(nil, migrationMetastateKey, string(migrationStateJSON))
 	if err != nil {
 		db.log.WithError(err).Errorf("%s, error setting final migration state", txidMigrationErrMsg)
 		return
@@ -1665,7 +1665,7 @@ func m9TxnJSONEncoding(db *IndexerDb, state *MigrationState) (err error) {
 	state.NextMigration++
 	state.NextRound = 0
 	migrationStateJSON := string(encoding.EncodeJSON(state))
-	err = db.setMetastate(migrationMetastateKey, migrationStateJSON)
+	err = db.setMetastate(nil, migrationMetastateKey, migrationStateJSON)
 	if err != nil {
 		db.log.WithError(err).Errorf("%s, error setting final migration state", m9ErrPrefix)
 		return


Test patch:
diff --git a/cmd/block-generator/generator/generate_test.go b/cmd/block-generator/generator/generate_test.go
index 5358e19..8c799b9 100644
--- a/cmd/block-generator/generator/generate_test.go
+++ b/cmd/block-generator/generator/generate_test.go
@@ -23,6 +23,20 @@ func makePrivateGenerator(t *testing.T) *generator {
 	return publicGenerator.(*generator)
 }
 
+func TestPaymentAcctCreate(t *testing.T) {
+	g := makePrivateGenerator(t)
+	sp := g.getSuggestedParams(1)
+	g.generatePaymentTxnInternal(paymentAcctCreateTx, sp, 0, 0)
+	require.Len(t, g.balances, int(g.config.NumGenesisAccounts+1))
+}
+
+func TestPaymentTransfer(t *testing.T) {
+	g := makePrivateGenerator(t)
+	sp := g.getSuggestedParams(1)
+	g.generatePaymentTxnInternal(paymentTx, sp, 0, 0)
+	require.Len(t, g.balances, int(g.config.NumGenesisAccounts))
+}
+
 func TestAssetXferNoAssetsOverride(t *testing.T) {
 	g := makePrivateGenerator(t)
 	sp := g.getSuggestedParams(1)
diff --git a/cmd/block-generator/generator/server_test.go b/cmd/block-generator/generator/server_test.go
new file mode 100644
index 0000000..bb7a48f
--- /dev/null
+++ b/cmd/block-generator/generator/server_test.go
@@ -0,0 +1,88 @@
+package generator
+
+import (
+	"fmt"
+	"os"
+	"strings"
+	"testing"
+
+	"github.com/stretchr/testify/assert"
+	"github.com/stretchr/testify/require"
+)
+
+func TestInitConfigFile(t *testing.T) {
+	config, err := initializeConfigFile("../test_config.yml")
+	require.NoError(t, err)
+	require.Equal(t, uint64(10), config.NumGenesisAccounts)
+	require.Equal(t, float32(0.25), config.AssetCloseFraction)
+	require.Equal(t, float32(0.0), config.AssetDestroyFraction)
+}
+
+func TestInitConfigFileNotExist(t *testing.T) {
+	_, err := initializeConfigFile("this_is_not_a_config_file")
+
+	if _, ok := err.(*os.PathError); !ok {
+		require.Fail(t, "This should generate a path error")
+	}
+}
+
+func TestParseRound(t *testing.T) {
+	var testcases = []struct {
+		name          string
+		url           string
+		expectedRound uint64
+		err           string
+	}{
+		{
+			name:          "no block",
+			url:           "/v2/blocks/",
+			expectedRound: 0,
+			err:           "no block in path",
+		},
+		{
+			name:          "no block 2",
+			url:           "/v2/blocks/?nothing",
+			expectedRound: 0,
+			err:           "no block in path",
+		},
+		{
+			name:          "invalid prefix",
+			url:           fmt.Sprintf("/v2/wrong/prefix/1"),
+			expectedRound: 0,
+			err:           "not a blocks query",
+		},
+		{
+			name:          "normal one digit",
+			url:           fmt.Sprintf("%s1", blockQueryPrefix),
+			expectedRound: 1,
+			err:           "",
+		},
+		{
+			name:          "normal long number",
+			url:           fmt.Sprintf("%s12345678", blockQueryPrefix),
+			expectedRound: 12345678,
+			err:           "",
+		},
+		{
+			name:          "with query parameters",
+			url:           fmt.Sprintf("%s1234?pretty", blockQueryPrefix),
+			expectedRound: 1234,
+			err:           "",
+		},
+	}
+
+	for _, testcase := range testcases {
+		t.Run(testcase.name, func(t *testing.T) {
+			round, err := parseRound(testcase.url)
+			if len(testcase.err) == 0 {
+				msg := fmt.Sprintf("Unexpected error parsing '%s', expected round '%d' received error: %v",
+					testcase.url, testcase.expectedRound, err)
+				require.NoError(t, err, msg)
+				assert.Equal(t, testcase.expectedRound, round)
+			} else {
+				require.Error(t, err, fmt.Sprintf("Expected an error containing: %s", testcase.err))
+				require.True(t, strings.Contains(err.Error(), testcase.err))
+			}
+		})
+	}
+}
diff --git a/cmd/block-generator/generator/utils_test.go b/cmd/block-generator/generator/utils_test.go
index 278a1f2..09dbb8b 100644
--- a/cmd/block-generator/generator/utils_test.go
+++ b/cmd/block-generator/generator/utils_test.go
@@ -8,6 +8,13 @@ import (
 	"github.com/stretchr/testify/require"
 )
 
+func TestWeightedSelectionInternalBadInput(t *testing.T) {
+	weights := []float32{0.10, 0.30}
+	options := []interface{}{"10"}
+	_, err := weightedSelectionInternal(0, weights, options, nil)
+	require.EqualError(t, err, "number of weights must equal number of options: 2 != 1")
+}
+
 func TestWeightedSelectionInternal(t *testing.T) {
 	weights := []float32{0.10, 0.30, 0.60}
 	options := []interface{}{"10", "30", "60"}
diff --git a/cmd/block-generator/main_test.go b/cmd/block-generator/main_test.go
deleted file mode 100644
index 17330e1..0000000
--- a/cmd/block-generator/main_test.go
+++ /dev/null
@@ -1,46 +0,0 @@
-package main
-
-import (
-	"fmt"
-	"github.com/stretchr/testify/assert"
-	"testing"
-)
-
-func TestParseRound(t *testing.T) {
-	var testcases = []struct {
-		name          string
-		url           string
-		expectedRound uint64
-	}{
-		{
-			name:          "invalid prefix",
-			url:           fmt.Sprintf("/v2/wrong/prefix/1"),
-			expectedRound: 0,
-		},
-		{
-			name:          "normal one digit",
-			url:           fmt.Sprintf("%s1", blockQueryPrefix),
-			expectedRound: 1,
-		},
-		{
-			name:          "normal long number",
-			url:           fmt.Sprintf("%s12345678", blockQueryPrefix),
-			expectedRound: 12345678,
-		},
-		{
-			name:          "with query parameters",
-			url:           fmt.Sprintf("%s1234?pretty", blockQueryPrefix),
-			expectedRound: 1234,
-		},
-	}
-
-	for _, testcase := range testcases {
-		t.Run(testcase.name, func(t *testing.T) {
-			round, err := parseRound(testcase.url)
-			if err != nil && testcase.expectedRound != 0 {
-				assert.Fail(t, fmt.Sprintf("Unexpected error parsing '%s', expected round '%d' received error: %v", testcase.url, testcase.expectedRound, err))
-			}
-			assert.Equal(t, testcase.expectedRound, round)
-		})
-	}
-}
diff --git a/idb/postgres/postgres_integration_common_test.go b/idb/postgres/postgres_integration_common_test.go
index 48aba9f..ce1a1aa 100644
--- a/idb/postgres/postgres_integration_common_test.go
+++ b/idb/postgres/postgres_integration_common_test.go
@@ -8,7 +8,7 @@ import (
 	sdk_types "github.com/algorand/go-algorand-sdk/types"
 	"github.com/orlangure/gnomock"
 	"github.com/orlangure/gnomock/preset/postgres"
-	"github.com/stretchr/testify/assert"
+	"github.com/stretchr/testify/require"
 
 	"github.com/algorand/indexer/accounting"
 	"github.com/algorand/indexer/idb"
@@ -25,11 +25,11 @@ func setupPostgres(t *testing.T) (*sql.DB, string, func()) {
 		postgres.WithDatabase("mydb"),
 	)
 	container, err := gnomock.Start(p)
-	assert.NoError(t, err, "Error starting gnomock")
+	require.NoError(t, err, "Error starting gnomock")
 
 	shutdownFunc := func() {
 		err = gnomock.Stop(container)
-		assert.NoError(t, err, "Error stoping gnomock")
+		require.NoError(t, err, "Error stoping gnomock")
 	}
 
 	connStr := fmt.Sprintf(
@@ -39,15 +39,19 @@ func setupPostgres(t *testing.T) (*sql.DB, string, func()) {
 	)
 
 	db, err := sql.Open("postgres", connStr)
-	assert.NoError(t, err, "Error opening pg connection")
+	require.NoError(t, err, "Error opening pg connection")
+
 	return db, connStr, shutdownFunc
 }
 
-func setupIdb(t *testing.T) (*IndexerDb /*db*/, func() /*shutdownFunc*/) {
+func setupIdb(t *testing.T, genesis types.Genesis) (*IndexerDb /*db*/, func() /*shutdownFunc*/) {
 	_, connStr, shutdownFunc := setupPostgres(t)
 
 	idb, err := OpenPostgres(connStr, idb.IndexerDbOptions{}, nil)
-	assert.NoError(t, err)
+	require.NoError(t, err)
+
+	err = idb.LoadGenesis(genesis)
+	require.NoError(t, err)
 
 	return idb, shutdownFunc
 }
@@ -56,24 +60,24 @@ func importTxns(t *testing.T, db *IndexerDb, round uint64, txns ...*sdk_types.Si
 	block := test.MakeBlockForTxns(round, txns...)
 
 	_, err := importer.NewDBImporter(db).ImportDecodedBlock(&block)
-	assert.NoError(t, err)
+	require.NoError(t, err)
 }
 
 func accountTxns(t *testing.T, db *IndexerDb, round uint64, txns ...*idb.TxnRow) {
 	cache, err := db.GetDefaultFrozen()
-	assert.NoError(t, err)
+	require.NoError(t, err)
 
 	state := accounting.New(cache)
 	err = state.InitRoundParts(round, test.FeeAddr, test.RewardAddr, 0)
-	assert.NoError(t, err)
+	require.NoError(t, err)
 
 	for _, txn := range txns {
 		err := state.AddTransaction(txn)
-		assert.NoError(t, err)
+		require.NoError(t, err)
 	}
 
 	err = db.CommitRoundAccounting(state.RoundUpdates, round, &types.BlockHeader{})
-	assert.NoError(t, err)
+	require.NoError(t, err)
 }
 
 // Helper to execute a query returning an integer, for example COUNT(*). Returns -1 on an error.
diff --git a/idb/postgres/postgres_integration_test.go b/idb/postgres/postgres_integration_test.go
index 3aa6803..597a42d 100644
--- a/idb/postgres/postgres_integration_test.go
+++ b/idb/postgres/postgres_integration_test.go
@@ -44,14 +44,15 @@ func TestMaxRoundOnUninitializedDB(t *testing.T) {
 	// When // We request the max round.
 	//////////
 	roundA, errA := db.GetMaxRoundAccounted()
-	roundL, errL := db.GetMaxRoundLoaded()
+	roundL, errL := db.GetNextRoundToLoad()
 
 	//////////
 	// Then // The error message should be set.
 	//////////
 	assert.Equal(t, errA, idb.ErrorNotInitialized)
-	assert.Equal(t, errL, idb.ErrorNotInitialized)
 	assert.Equal(t, uint64(0), roundA)
+
+	require.NoError(t, errL)
 	assert.Equal(t, uint64(0), roundL)
 }
 
@@ -95,14 +96,14 @@ func TestMaxRound(t *testing.T) {
 	//////////
 	roundA, err := pdb.GetMaxRoundAccounted()
 	assert.NoError(t, err)
-	roundL, err := pdb.GetMaxRoundLoaded()
+	roundL, err := pdb.GetNextRoundToLoad()
 	assert.NoError(t, err)
 
 	//////////
 	// Then // There should be no error and we return that there are zero rounds.
 	//////////
 	assert.Equal(t, uint64(123454321), roundA)
-	assert.Equal(t, uint64(543212345), roundL)
+	assert.Equal(t, uint64(543212346), roundL)
 }
 
 func assertAccountAsset(t *testing.T, db *sql.DB, addr sdk_types.Address, assetid uint64, frozen bool, amount uint64) {
@@ -119,15 +120,9 @@ func assertAccountAsset(t *testing.T, db *sql.DB, addr sdk_types.Address, asseti
 
 // TestAssetCloseReopenTransfer tests a scenario that requires asset subround accounting
 func TestAssetCloseReopenTransfer(t *testing.T) {
-	db, connStr, shutdownFunc := setupPostgres(t)
+	db, shutdownFunc := setupIdb(t, test.MakeGenesis())
 	defer shutdownFunc()
 
-	pdb, err := idb.IndexerDbByName("postgres", connStr, idb.IndexerDbOptions{}, nil)
-	assert.NoError(t, err)
-
-	err = pdb.LoadGenesis(test.MakeGenesis())
-	require.NoError(t, err)
-
 	assetid := uint64(2222)
 	amt := uint64(10000)
 	total := uint64(1000000)
@@ -141,7 +136,7 @@ func TestAssetCloseReopenTransfer(t *testing.T) {
 	_, optinMain := test.MakeAssetTxnOrPanic(test.Round, assetid, 0, test.AccountA, test.AccountA, sdk_types.ZeroAddress)
 	_, payMain := test.MakeAssetTxnOrPanic(test.Round, assetid, amt, test.AccountD, test.AccountA, sdk_types.ZeroAddress)
 
-	cache, err := pdb.GetDefaultFrozen()
+	cache, err := db.GetDefaultFrozen()
 	assert.NoError(t, err)
 	state := getAccounting(test.Round, cache)
 	state.AddTransaction(createAsset)
@@ -153,34 +148,28 @@ func TestAssetCloseReopenTransfer(t *testing.T) {
 	//////////
 	// When // We commit the round accounting to the database.
 	//////////
-	err = pdb.CommitRoundAccounting(state.RoundUpdates, test.Round, &types.BlockHeader{})
+	err = db.CommitRoundAccounting(state.RoundUpdates, test.Round, &types.BlockHeader{})
 	assert.NoError(t, err, "failed to commit")
 
 	//////////
 	// Then // Accounts A, B, C and D have the correct balances.
 	//////////
 	// A has the final payment after being closed out
-	assertAccountAsset(t, db, test.AccountA, assetid, false, amt)
+	assertAccountAsset(t, db.db, test.AccountA, assetid, false, amt)
 	// B has the closing transfer amount
-	assertAccountAsset(t, db, test.AccountB, assetid, false, 1000)
+	assertAccountAsset(t, db.db, test.AccountB, assetid, false, 1000)
 	// C has the close-to remainder
-	assertAccountAsset(t, db, test.AccountC, assetid, false, 9000)
+	assertAccountAsset(t, db.db, test.AccountC, assetid, false, 9000)
 	// D has the total minus both payments to A
-	assertAccountAsset(t, db, test.AccountD, assetid, false, total-2*amt)
+	assertAccountAsset(t, db.db, test.AccountD, assetid, false, total-2*amt)
 }
 
 // TestDefaultFrozenAndCache checks that values are added to the default frozen cache, and that the cache is used when
 // accounts optin to an asset.
 func TestDefaultFrozenAndCache(t *testing.T) {
-	db, connStr, shutdownFunc := setupPostgres(t)
+	db, shutdownFunc := setupIdb(t, test.MakeGenesis())
 	defer shutdownFunc()
 
-	pdb, err := idb.IndexerDbByName("postgres", connStr, idb.IndexerDbOptions{}, nil)
-	assert.NoError(t, err)
-
-	err = pdb.LoadGenesis(test.MakeGenesis())
-	require.NoError(t, err)
-
 	assetid := uint64(2222)
 	total := uint64(1000000)
 
@@ -192,7 +181,7 @@ func TestDefaultFrozenAndCache(t *testing.T) {
 	_, optinB1 := test.MakeAssetTxnOrPanic(test.Round, assetid, 0, test.AccountB, test.AccountB, sdk_types.ZeroAddress)
 	_, optinB2 := test.MakeAssetTxnOrPanic(test.Round, assetid+1, 0, test.AccountB, test.AccountB, sdk_types.ZeroAddress)
 
-	cache, err := pdb.GetDefaultFrozen()
+	cache, err := db.GetDefaultFrozen()
 	assert.NoError(t, err)
 	state := getAccounting(test.Round, cache)
 	state.AddTransaction(createAssetFrozen)
@@ -203,19 +192,19 @@ func TestDefaultFrozenAndCache(t *testing.T) {
 	//////////
 	// When // We commit the round accounting to the database.
 	//////////
-	err = pdb.CommitRoundAccounting(state.RoundUpdates, test.Round, &types.BlockHeader{})
+	err = db.CommitRoundAccounting(state.RoundUpdates, test.Round, &types.BlockHeader{})
 	assert.NoError(t, err, "failed to commit")
 
 	//////////
 	// Then // Make sure the accounts have the correct default-frozen after create/optin
 	//////////
 	// default-frozen = true
-	assertAccountAsset(t, db, test.AccountA, assetid, false, total) // the creator ignores default-frozen
-	assertAccountAsset(t, db, test.AccountB, assetid, true, 0)
+	assertAccountAsset(t, db.db, test.AccountA, assetid, false, total) // the creator ignores default-frozen
+	assertAccountAsset(t, db.db, test.AccountB, assetid, true, 0)
 
 	// default-frozen = false
-	assertAccountAsset(t, db, test.AccountA, assetid+1, false, total)
-	assertAccountAsset(t, db, test.AccountB, assetid+1, false, 0)
+	assertAccountAsset(t, db.db, test.AccountA, assetid+1, false, total)
+	assertAccountAsset(t, db.db, test.AccountB, assetid+1, false, 0)
 }
 
 // TestInitializeFrozenCache checks that the frozen cache is properly initialized on startup.
@@ -255,15 +244,9 @@ func TestInitializeFrozenCache(t *testing.T) {
 
 // TestReCreateAssetHolding checks that the optin value of a defunct
 func TestReCreateAssetHolding(t *testing.T) {
-	db, connStr, shutdownFunc := setupPostgres(t)
+	db, shutdownFunc := setupIdb(t, test.MakeGenesis())
 	defer shutdownFunc()
 
-	pdb, err := idb.IndexerDbByName("postgres", connStr, idb.IndexerDbOptions{}, nil)
-	assert.NoError(t, err)
-
-	err = pdb.LoadGenesis(test.MakeGenesis())
-	require.NoError(t, err)
-
 	assetid := uint64(2222)
 	total := uint64(1000000)
 
@@ -292,7 +275,7 @@ func TestReCreateAssetHolding(t *testing.T) {
 		_, unfreezeB := test.MakeAssetFreezeOrPanic(round, aid, !testcase.frozen, test.AccountB, test.AccountB)
 		_, optoutB := test.MakeAssetTxnOrPanic(round, aid, 0, test.AccountB, test.AccountC, test.AccountD)
 
-		cache, err := pdb.GetDefaultFrozen()
+		cache, err := db.GetDefaultFrozen()
 		assert.NoError(t, err)
 		state := getAccounting(round, cache)
 		state.AddTransaction(createAssetFrozen)
@@ -304,19 +287,19 @@ func TestReCreateAssetHolding(t *testing.T) {
 		//////////
 		// When // We commit the round accounting to the database.
 		//////////
-		err = pdb.CommitRoundAccounting(state.RoundUpdates, round, &types.BlockHeader{})
+		err = db.CommitRoundAccounting(state.RoundUpdates, round, &types.BlockHeader{})
 		assert.NoError(t, err, "failed to commit")
 
 		//////////
 		// Then // AccountB should have its frozen state set back to the default value
 		//////////
-		assertAccountAsset(t, db, test.AccountB, aid, testcase.frozen, 0)
+		assertAccountAsset(t, db.db, test.AccountB, aid, testcase.frozen, 0)
 	}
 }
 
 // TestMultipleAssetOptins make sure no-op transactions don't reset the default frozen value.
 func TestNoopOptins(t *testing.T) {
-	db, connStr, shutdownFunc := setupPostgres(t)
+	db, shutdownFunc := setupIdb(t, test.MakeGenesis())
 	defer shutdownFunc()
 
 	///////////
@@ -327,17 +310,11 @@ func TestNoopOptins(t *testing.T) {
 	// create asst
 	//db.Exec(`INSERT INTO asset (index, creator_addr, params) values ($1, $2, $3)`, assetid, test.AccountA[:], `{"df":true}`)
 
-	pdb, err := idb.IndexerDbByName("postgres", connStr, idb.IndexerDbOptions{}, nil)
-	assert.NoError(t, err)
-
-	err = pdb.LoadGenesis(test.MakeGenesis())
-	require.NoError(t, err)
-
 	_, createAsset := test.MakeAssetConfigOrPanic(test.Round, 0, assetid, uint64(1000000), uint64(6), true, "icicles", "frozen coin", "http://antarctica.com", test.AccountD)
 	_, optinB := test.MakeAssetTxnOrPanic(test.Round, assetid, 0, test.AccountB, test.AccountB, sdk_types.ZeroAddress)
 	_, unfreezeB := test.MakeAssetFreezeOrPanic(test.Round, assetid, false, test.AccountB, test.AccountB)
 
-	cache, err := pdb.GetDefaultFrozen()
+	cache, err := db.GetDefaultFrozen()
 	assert.NoError(t, err)
 	state := getAccounting(test.Round, cache)
 	state.AddTransaction(createAsset)
@@ -348,27 +325,21 @@ func TestNoopOptins(t *testing.T) {
 	//////////
 	// When // We commit the round accounting to the database.
 	//////////
-	err = pdb.CommitRoundAccounting(state.RoundUpdates, test.Round, &types.BlockHeader{})
+	err = db.CommitRoundAccounting(state.RoundUpdates, test.Round, &types.BlockHeader{})
 	assert.NoError(t, err, "failed to commit")
 
 	//////////
 	// Then // AccountB should have its frozen state set back to the default value
 	//////////
 	// TODO: This isn't working yet
-	assertAccountAsset(t, db, test.AccountB, assetid, false, 0)
+	assertAccountAsset(t, db.db, test.AccountB, assetid, false, 0)
 }
 
 // TestMultipleWriters tests that accounting cannot be double committed.
 func TestMultipleWriters(t *testing.T) {
-	db, connStr, shutdownFunc := setupPostgres(t)
+	db, shutdownFunc := setupIdb(t, test.MakeGenesis())
 	defer shutdownFunc()
 
-	pdb, err := idb.IndexerDbByName("postgres", connStr, idb.IndexerDbOptions{}, nil)
-	assert.NoError(t, err)
-
-	err = pdb.LoadGenesis(test.MakeGenesis())
-	require.NoError(t, err)
-
 	amt := uint64(10000)
 
 	///////////
@@ -377,7 +348,7 @@ func TestMultipleWriters(t *testing.T) {
 	_, payAccountE := test.MakePayTxnRowOrPanic(test.Round, 1000, amt, 0, 0, 0, 0, test.AccountD,
 		test.AccountE, sdk_types.ZeroAddress, sdk_types.ZeroAddress)
 
-	cache, err := pdb.GetDefaultFrozen()
+	cache, err := db.GetDefaultFrozen()
 	assert.NoError(t, err)
 	state := getAccounting(test.Round, cache)
 	state.AddTransaction(payAccountE)
@@ -394,7 +365,8 @@ func TestMultipleWriters(t *testing.T) {
 		go func() {
 			defer wg.Done()
 			<-start
-			errors <- pdb.CommitRoundAccounting(state.RoundUpdates, test.Round, &types.BlockHeader{})
+			errors <- db.CommitRoundAccounting(
+				state.RoundUpdates, test.Round, &types.BlockHeader{})
 		}()
 	}
 	close(start)
@@ -415,12 +387,13 @@ func TestMultipleWriters(t *testing.T) {
 
 	// AccountE should contain the final payment.
 	var balance uint64
-	row := db.QueryRow(`SELECT microalgos FROM account WHERE account.addr = $1`, test.AccountE[:])
+	row := db.db.QueryRow(`SELECT microalgos FROM account WHERE account.addr = $1`, test.AccountE[:])
 	err = row.Scan(&balance)
 	assert.NoError(t, err, "checking balance")
 	assert.Equal(t, amt, balance)
 }
 
+// TestBlockWithTransactions tests that the block with transactions endpoint works.
 // TestBlockWithTransactions tests that the block with transactions endpoint works.
 func TestBlockWithTransactions(t *testing.T) {
 	var err error
@@ -480,34 +453,28 @@ func TestBlockWithTransactions(t *testing.T) {
 }
 
 func TestRekeyBasic(t *testing.T) {
-	db, connStr, shutdownFunc := setupPostgres(t)
+	db, shutdownFunc := setupIdb(t, test.MakeGenesis())
 	defer shutdownFunc()
 
-	pdb, err := idb.IndexerDbByName("postgres", connStr, idb.IndexerDbOptions{}, nil)
-	assert.NoError(t, err)
-
-	err = pdb.LoadGenesis(test.MakeGenesis())
-	require.NoError(t, err)
-
 	///////////
 	// Given // Send rekey transaction
 	///////////
 	_, txnRow := test.MakePayTxnRowOrPanic(test.Round, 1000, 0, 0, 0, 0, 0, test.AccountA,
 		test.AccountA, sdk_types.ZeroAddress, test.AccountB)
 
-	cache, err := pdb.GetDefaultFrozen()
+	cache, err := db.GetDefaultFrozen()
 	assert.NoError(t, err)
 	state := getAccounting(test.Round, cache)
 	state.AddTransaction(txnRow)
 
-	err = pdb.CommitRoundAccounting(state.RoundUpdates, test.Round, &types.BlockHeader{})
+	err = db.CommitRoundAccounting(state.RoundUpdates, test.Round, &types.BlockHeader{})
 	assert.NoError(t, err, "failed to commit")
 
 	//////////
 	// Then // Account A is rekeyed to account B
 	//////////
 	var accountDataStr []byte
-	row := db.QueryRow(`SELECT account_data FROM account WHERE account.addr = $1`, test.AccountA[:])
+	row := db.db.QueryRow(`SELECT account_data FROM account WHERE account.addr = $1`, test.AccountA[:])
 	err = row.Scan(&accountDataStr)
 	assert.NoError(t, err, "querying account data")
 
@@ -518,15 +485,9 @@ func TestRekeyBasic(t *testing.T) {
 }
 
 func TestRekeyToItself(t *testing.T) {
-	db, connStr, shutdownFunc := setupPostgres(t)
+	db, shutdownFunc := setupIdb(t, test.MakeGenesis())
 	defer shutdownFunc()
 
-	pdb, err := idb.IndexerDbByName("postgres", connStr, idb.IndexerDbOptions{}, nil)
-	assert.NoError(t, err)
-
-	err = pdb.LoadGenesis(test.MakeGenesis())
-	require.NoError(t, err)
-
 	///////////
 	// Given // Send rekey transaction
 	///////////
@@ -534,24 +495,25 @@ func TestRekeyToItself(t *testing.T) {
 		_, txnRow := test.MakePayTxnRowOrPanic(test.Round, 1000, 0, 0, 0, 0, 0, test.AccountA,
 			test.AccountA, sdk_types.ZeroAddress, test.AccountB)
 
-		cache, err := pdb.GetDefaultFrozen()
+		cache, err := db.GetDefaultFrozen()
 		assert.NoError(t, err)
 		state := getAccounting(test.Round, cache)
 		state.AddTransaction(txnRow)
 
-		err = pdb.CommitRoundAccounting(state.RoundUpdates, test.Round, &types.BlockHeader{})
+		err = db.CommitRoundAccounting(state.RoundUpdates, test.Round, &types.BlockHeader{})
 		assert.NoError(t, err, "failed to commit")
 	}
 	{
 		_, txnRow := test.MakePayTxnRowOrPanic(test.Round+1, 1000, 0, 0, 0, 0, 0, test.AccountA,
 			test.AccountA, sdk_types.ZeroAddress, test.AccountA)
 
-		cache, err := pdb.GetDefaultFrozen()
+		cache, err := db.GetDefaultFrozen()
 		assert.NoError(t, err)
 		state := getAccounting(test.Round+1, cache)
 		state.AddTransaction(txnRow)
 
-		err = pdb.CommitRoundAccounting(state.RoundUpdates, test.Round+1, &types.BlockHeader{})
+		err = db.CommitRoundAccounting(
+			state.RoundUpdates, test.Round+1, &types.BlockHeader{})
 		assert.NoError(t, err, "failed to commit")
 	}
 
@@ -559,8 +521,8 @@ func TestRekeyToItself(t *testing.T) {
 	// Then // Account's A auth-address is not recorded
 	//////////
 	var accountDataStr []byte
-	row := db.QueryRow(`SELECT account_data FROM account WHERE account.addr = $1`, test.AccountA[:])
-	err = row.Scan(&accountDataStr)
+	row := db.db.QueryRow(`SELECT account_data FROM account WHERE account.addr = $1`, test.AccountA[:])
+	err := row.Scan(&accountDataStr)
 	assert.NoError(t, err, "querying account data")
 
 	var ad types.AccountData
@@ -570,19 +532,13 @@ func TestRekeyToItself(t *testing.T) {
 }
 
 func TestRekeyThreeTimesInSameRound(t *testing.T) {
-	db, connStr, shutdownFunc := setupPostgres(t)
+	db, shutdownFunc := setupIdb(t, test.MakeGenesis())
 	defer shutdownFunc()
 
-	pdb, err := idb.IndexerDbByName("postgres", connStr, idb.IndexerDbOptions{}, nil)
-	assert.NoError(t, err)
-
-	err = pdb.LoadGenesis(test.MakeGenesis())
-	require.NoError(t, err)
-
 	///////////
 	// Given // Send rekey transaction
 	///////////
-	cache, err := pdb.GetDefaultFrozen()
+	cache, err := db.GetDefaultFrozen()
 	assert.NoError(t, err)
 	state := getAccounting(test.Round, cache)
 
@@ -602,14 +558,14 @@ func TestRekeyThreeTimesInSameRound(t *testing.T) {
 		state.AddTransaction(txnRow)
 	}
 
-	err = pdb.CommitRoundAccounting(state.RoundUpdates, test.Round, &types.BlockHeader{})
+	err = db.CommitRoundAccounting(state.RoundUpdates, test.Round, &types.BlockHeader{})
 	assert.NoError(t, err, "failed to commit")
 
 	//////////
 	// Then // Account A is rekeyed to account C
 	//////////
 	var accountDataStr []byte
-	row := db.QueryRow(`SELECT account_data FROM account WHERE account.addr = $1`, test.AccountA[:])
+	row := db.db.QueryRow(`SELECT account_data FROM account WHERE account.addr = $1`, test.AccountA[:])
 	err = row.Scan(&accountDataStr)
 	assert.NoError(t, err, "querying account data")
 
@@ -620,22 +576,16 @@ func TestRekeyThreeTimesInSameRound(t *testing.T) {
 }
 
 func TestRekeyToItselfHasNotBeenRekeyed(t *testing.T) {
-	_, connStr, shutdownFunc := setupPostgres(t)
+	db, shutdownFunc := setupIdb(t, test.MakeGenesis())
 	defer shutdownFunc()
 
-	pdb, err := idb.IndexerDbByName("postgres", connStr, idb.IndexerDbOptions{}, nil)
-	assert.NoError(t, err)
-
-	err = pdb.LoadGenesis(test.MakeGenesis())
-	require.NoError(t, err)
-
 	///////////
 	// Given // Send rekey transaction
 	///////////
 	_, txnRow := test.MakePayTxnRowOrPanic(test.Round, 1000, 0, 0, 0, 0, 0, test.AccountA,
 		test.AccountA, sdk_types.ZeroAddress, sdk_types.ZeroAddress)
 
-	cache, err := pdb.GetDefaultFrozen()
+	cache, err := db.GetDefaultFrozen()
 	assert.NoError(t, err)
 	state := getAccounting(test.Round, cache)
 	state.AddTransaction(txnRow)
@@ -643,21 +593,15 @@ func TestRekeyToItselfHasNotBeenRekeyed(t *testing.T) {
 	//////////
 	// Then // No error when committing to the DB.
 	//////////
-	err = pdb.CommitRoundAccounting(state.RoundUpdates, test.Round, &types.BlockHeader{})
+	err = db.CommitRoundAccounting(state.RoundUpdates, test.Round, &types.BlockHeader{})
 	assert.NoError(t, err, "failed to commit")
 }
 
 // TestIgnoreDefaultFrozenConfigUpdate the creator asset holding should ignore default-frozen = true.
 func TestIgnoreDefaultFrozenConfigUpdate(t *testing.T) {
-	db, connStr, shutdownFunc := setupPostgres(t)
+	db, shutdownFunc := setupIdb(t, test.MakeGenesis())
 	defer shutdownFunc()
 
-	pdb, err := idb.IndexerDbByName("postgres", connStr, idb.IndexerDbOptions{}, nil)
-	assert.NoError(t, err)
-
-	err = pdb.LoadGenesis(test.MakeGenesis())
-	require.NoError(t, err)
-
 	assetid := uint64(2222)
 	total := uint64(1000000)
 
@@ -668,7 +612,7 @@ func TestIgnoreDefaultFrozenConfigUpdate(t *testing.T) {
 	_, modifyAssetToFrozen := test.MakeAssetConfigOrPanic(test.Round, assetid, assetid, total, uint64(6), true, "icicles", "frozen coin", "http://antarctica.com", test.AccountA)
 	_, optin := test.MakeAssetTxnOrPanic(test.Round, assetid, 0, test.AccountB, test.AccountB, sdk_types.ZeroAddress)
 
-	cache, err := pdb.GetDefaultFrozen()
+	cache, err := db.GetDefaultFrozen()
 	assert.NoError(t, err)
 	state := getAccounting(test.Round, cache)
 	state.AddTransaction(createAssetNotFrozen)
@@ -678,28 +622,22 @@ func TestIgnoreDefaultFrozenConfigUpdate(t *testing.T) {
 	//////////
 	// When // We commit the round accounting to the database.
 	//////////
-	err = pdb.CommitRoundAccounting(state.RoundUpdates, test.Round, &types.BlockHeader{})
+	err = db.CommitRoundAccounting(state.RoundUpdates, test.Round, &types.BlockHeader{})
 	assert.NoError(t, err, "failed to commit")
 
 	//////////
 	// Then // Make sure the accounts have the correct default-frozen after create/optin
 	//////////
 	// default-frozen = true
-	assertAccountAsset(t, db, test.AccountA, assetid, false, total)
-	assertAccountAsset(t, db, test.AccountB, assetid, false, 0)
+	assertAccountAsset(t, db.db, test.AccountA, assetid, false, total)
+	assertAccountAsset(t, db.db, test.AccountB, assetid, false, 0)
 }
 
 // TestZeroTotalAssetCreate tests that the asset holding with total of 0 is created.
 func TestZeroTotalAssetCreate(t *testing.T) {
-	db, connStr, shutdownFunc := setupPostgres(t)
+	db, shutdownFunc := setupIdb(t, test.MakeGenesis())
 	defer shutdownFunc()
 
-	pdb, err := idb.IndexerDbByName("postgres", connStr, idb.IndexerDbOptions{}, nil)
-	assert.NoError(t, err)
-
-	err = pdb.LoadGenesis(test.MakeGenesis())
-	require.NoError(t, err)
-
 	assetid := uint64(2222)
 	total := uint64(0)
 
@@ -708,7 +646,7 @@ func TestZeroTotalAssetCreate(t *testing.T) {
 	///////////
 	_, createAsset := test.MakeAssetConfigOrPanic(test.Round, 0, assetid, total, uint64(6), false, "icicles", "frozen coin", "http://antarctica.com", test.AccountA)
 
-	cache, err := pdb.GetDefaultFrozen()
+	cache, err := db.GetDefaultFrozen()
 	assert.NoError(t, err)
 	state := getAccounting(test.Round, cache)
 	state.AddTransaction(createAsset)
@@ -716,13 +654,13 @@ func TestZeroTotalAssetCreate(t *testing.T) {
 	//////////
 	// When // We commit the round accounting to the database.
 	//////////
-	err = pdb.CommitRoundAccounting(state.RoundUpdates, test.Round, &types.BlockHeader{})
+	err = db.CommitRoundAccounting(state.RoundUpdates, test.Round, &types.BlockHeader{})
 	assert.NoError(t, err, "failed to commit")
 
 	//////////
 	// Then // Make sure the creator has an asset holding with amount = 0.
 	//////////
-	assertAccountAsset(t, db, test.AccountA, assetid, false, 0)
+	assertAccountAsset(t, db.db, test.AccountA, assetid, false, 0)
 }
 
 func assertAssetDates(t *testing.T, db *sql.DB, assetID uint64, deleted sql.NullBool, createdAt sql.NullInt64, closedAt sql.NullInt64) {
@@ -758,16 +696,10 @@ func assertAssetHoldingDates(t *testing.T, db *sql.DB, address sdk_types.Address
 }
 
 func TestDestroyAssetBasic(t *testing.T) {
-	db, connStr, shutdownFunc := setupPostgres(t)
+	db, shutdownFunc := setupIdb(t, test.MakeGenesis())
 	defer shutdownFunc()
 
-	pdb, err := idb.IndexerDbByName("postgres", connStr, idb.IndexerDbOptions{}, nil)
-	assert.NoError(t, err)
-
-	err = pdb.LoadGenesis(test.MakeGenesis())
-	require.NoError(t, err)
-
-	cache, err := pdb.GetDefaultFrozen()
+	cache, err := db.GetDefaultFrozen()
 	assert.NoError(t, err)
 
 	assetID := uint64(3)
@@ -781,7 +713,7 @@ func TestDestroyAssetBasic(t *testing.T) {
 		err := state.AddTransaction(txnRow)
 		assert.NoError(t, err)
 
-		err = pdb.CommitRoundAccounting(state.RoundUpdates, test.Round, &types.BlockHeader{})
+		err = db.CommitRoundAccounting(state.RoundUpdates, test.Round, &types.BlockHeader{})
 		assert.NoError(t, err, "failed to commit")
 	}
 	// Destroy an asset.
@@ -792,34 +724,28 @@ func TestDestroyAssetBasic(t *testing.T) {
 		err := state.AddTransaction(txnRow)
 		assert.NoError(t, err)
 
-		err = pdb.CommitRoundAccounting(state.RoundUpdates, test.Round+1, &types.BlockHeader{})
+		err = db.CommitRoundAccounting(state.RoundUpdates, test.Round+1, &types.BlockHeader{})
 		assert.NoError(t, err, "failed to commit")
 	}
 
 	// Check that the asset is deleted.
-	assertAssetDates(t, db, assetID,
+	assertAssetDates(t, db.db, assetID,
 		sql.NullBool{Valid: true, Bool: true},
 		sql.NullInt64{Valid: true, Int64: int64(test.Round)},
 		sql.NullInt64{Valid: true, Int64: int64(test.Round + 1)})
 
 	// Check that the account's asset holding is deleted.
-	assertAssetHoldingDates(t, db, test.AccountA, assetID,
+	assertAssetHoldingDates(t, db.db, test.AccountA, assetID,
 		sql.NullBool{Valid: true, Bool: true},
 		sql.NullInt64{Valid: true, Int64: int64(test.Round)},
 		sql.NullInt64{Valid: true, Int64: int64(test.Round + 1)})
 }
 
 func TestDestroyAssetZeroSupply(t *testing.T) {
-	db, connStr, shutdownFunc := setupPostgres(t)
+	db, shutdownFunc := setupIdb(t, test.MakeGenesis())
 	defer shutdownFunc()
 
-	pdb, err := idb.IndexerDbByName("postgres", connStr, idb.IndexerDbOptions{}, nil)
-	assert.NoError(t, err)
-
-	err = pdb.LoadGenesis(test.MakeGenesis())
-	require.NoError(t, err)
-
-	cache, err := pdb.GetDefaultFrozen()
+	cache, err := db.GetDefaultFrozen()
 	assert.NoError(t, err)
 
 	assetID := uint64(3)
@@ -843,33 +769,27 @@ func TestDestroyAssetZeroSupply(t *testing.T) {
 		assert.NoError(t, err)
 	}
 
-	err = pdb.CommitRoundAccounting(state.RoundUpdates, test.Round, &types.BlockHeader{})
+	err = db.CommitRoundAccounting(state.RoundUpdates, test.Round, &types.BlockHeader{})
 	assert.NoError(t, err, "failed to commit")
 
 	// Check that the asset is deleted.
-	assertAssetDates(t, db, assetID,
+	assertAssetDates(t, db.db, assetID,
 		sql.NullBool{Valid: true, Bool: true},
 		sql.NullInt64{Valid: true, Int64: int64(test.Round)},
 		sql.NullInt64{Valid: true, Int64: int64(test.Round)})
 
 	// Check that the account's asset holding is deleted.
-	assertAssetHoldingDates(t, db, test.AccountA, assetID,
+	assertAssetHoldingDates(t, db.db, test.AccountA, assetID,
 		sql.NullBool{Valid: true, Bool: true},
 		sql.NullInt64{Valid: true, Int64: int64(test.Round)},
 		sql.NullInt64{Valid: true, Int64: int64(test.Round)})
 }
 
 func TestDestroyAssetDeleteCreatorsHolding(t *testing.T) {
-	db, connStr, shutdownFunc := setupPostgres(t)
+	db, shutdownFunc := setupIdb(t, test.MakeGenesis())
 	defer shutdownFunc()
 
-	pdb, err := idb.IndexerDbByName("postgres", connStr, idb.IndexerDbOptions{}, nil)
-	assert.NoError(t, err)
-
-	err = pdb.LoadGenesis(test.MakeGenesis())
-	require.NoError(t, err)
-
-	cache, err := pdb.GetDefaultFrozen()
+	cache, err := db.GetDefaultFrozen()
 	assert.NoError(t, err)
 
 	assetID := uint64(3)
@@ -918,35 +838,34 @@ func TestDestroyAssetDeleteCreatorsHolding(t *testing.T) {
 		state.AddTransaction(txnRow)
 	}
 
-	err = pdb.CommitRoundAccounting(state.RoundUpdates, test.Round, &types.BlockHeader{})
+	err = db.CommitRoundAccounting(state.RoundUpdates, test.Round, &types.BlockHeader{})
 	assert.NoError(t, err, "failed to commit")
 
 	// Check that the creator's asset holding is deleted.
-	assertAssetHoldingDates(t, db, test.AccountA, assetID,
+	assertAssetHoldingDates(t, db.db, test.AccountA, assetID,
 		sql.NullBool{Valid: true, Bool: true},
 		sql.NullInt64{Valid: true, Int64: int64(test.Round)},
 		sql.NullInt64{Valid: true, Int64: int64(test.Round)})
 
 	// Check that other account's asset holding was not deleted.
-	assertAssetHoldingDates(t, db, test.AccountC, assetID,
+	assertAssetHoldingDates(t, db.db, test.AccountC, assetID,
 		sql.NullBool{Valid: true, Bool: false},
 		sql.NullInt64{Valid: true, Int64: int64(test.Round)},
 		sql.NullInt64{Valid: false, Int64: 0})
 
 	// Check that the manager does not have an asset holding.
 	{
-		count := queryInt(db, "SELECT COUNT(*) FROM account_asset WHERE addr = $1", test.AccountB[:])
+		count := queryInt(db.db, "SELECT COUNT(*) FROM account_asset WHERE addr = $1", test.AccountB[:])
 		assert.Equal(t, 0, count)
 	}
 }
 
 // Test that block import adds the freeze/sender accounts to txn_participation.
 func TestAssetFreezeTxnParticipation(t *testing.T) {
-	db, connStr, shutdownFunc := setupPostgres(t)
+	db, shutdownFunc := setupIdb(t, test.MakeGenesis())
 	defer shutdownFunc()
-	pdb, err := idb.IndexerDbByName("postgres", connStr, idb.IndexerDbOptions{}, nil)
-	assert.NoError(t, err)
-	blockImporter := importer.NewDBImporter(pdb)
+
+	blockImporter := importer.NewDBImporter(db)
 
 	///////////
 	// Given // A block containing an asset freeze txn
@@ -966,8 +885,8 @@ func TestAssetFreezeTxnParticipation(t *testing.T) {
 	//////////
 	// Then // Both accounts should have an entry in the txn_participation table.
 	//////////
-	acctACount := queryInt(db, "SELECT COUNT(*) FROM txn_participation WHERE addr = $1", test.AccountA[:])
-	acctBCount := queryInt(db, "SELECT COUNT(*) FROM txn_participation WHERE addr = $1", test.AccountB[:])
+	acctACount := queryInt(db.db, "SELECT COUNT(*) FROM txn_participation WHERE addr = $1", test.AccountA[:])
+	acctBCount := queryInt(db.db, "SELECT COUNT(*) FROM txn_participation WHERE addr = $1", test.AccountB[:])
 	assert.Equal(t, 1, acctACount)
 	assert.Equal(t, 1, acctBCount)
 }
diff --git a/idb/postgres/postgres_migrations_integration_test.go b/idb/postgres/postgres_migrations_integration_test.go
index d55e815..d4ed575 100644
--- a/idb/postgres/postgres_migrations_integration_test.go
+++ b/idb/postgres/postgres_migrations_integration_test.go
@@ -16,7 +16,7 @@ import (
 )
 
 func nextMigrationNum(t *testing.T, db *IndexerDb) int {
-	j, err := db.getMetastate(migrationMetastateKey)
+	j, err := db.getMetastate(nil, migrationMetastateKey)
 	assert.NoError(t, err)
 
 	assert.True(t, len(j) > 0)
@@ -29,7 +29,7 @@ func nextMigrationNum(t *testing.T, db *IndexerDb) int {
 }
 
 func TestFixFreezeLookupMigration(t *testing.T) {
-	db, shutdownFunc := setupIdb(t)
+	db, shutdownFunc := setupIdb(t, test.MakeGenesis())
 	defer shutdownFunc()
 
 	var sender types.Address
@@ -61,12 +61,9 @@ func TestFixFreezeLookupMigration(t *testing.T) {
 
 // Test that ClearAccountDataMigration() clears account data for closed accounts.
 func TestClearAccountDataMigrationClosedAccounts(t *testing.T) {
-	db, shutdownFunc := setupIdb(t)
+	db, shutdownFunc := setupIdb(t, test.MakeGenesis())
 	defer shutdownFunc()
 
-	err := db.LoadGenesis(test.MakeGenesis())
-	require.NoError(t, err)
-
 	// Rekey account A.
 	{
 		stxn, txnRow := test.MakePayTxnRowOrPanic(
@@ -85,7 +82,7 @@ func TestClearAccountDataMigrationClosedAccounts(t *testing.T) {
 	}
 
 	// Run migration.
-	err = ClearAccountDataMigration(db, &MigrationState{})
+	err := ClearAccountDataMigration(db, &MigrationState{})
 	assert.NoError(t, err)
 
 	// Check that account A has no account data.
@@ -103,12 +100,9 @@ func TestClearAccountDataMigrationClosedAccounts(t *testing.T) {
 
 // Test that ClearAccountDataMigration() clears account data that was set before account was closed.
 func TestClearAccountDataMigrationClearsReopenedAccounts(t *testing.T) {
-	db, shutdownFunc := setupIdb(t)
+	db, shutdownFunc := setupIdb(t, test.MakeGenesis())
 	defer shutdownFunc()
 
-	err := db.LoadGenesis(test.MakeGenesis())
-	require.NoError(t, err)
-
 	// Create account A.
 	{
 		stxn, txnRow := test.MakePayTxnRowOrPanic(
@@ -153,7 +147,7 @@ func TestClearAccountDataMigrationClearsReopenedAccounts(t *testing.T) {
 	}
 
 	// Run migration.
-	err = ClearAccountDataMigration(db, &MigrationState{})
+	err := ClearAccountDataMigration(db, &MigrationState{})
 	assert.NoError(t, err)
 
 	// Check that account A is offline and has no account data.
@@ -172,12 +166,9 @@ func TestClearAccountDataMigrationClearsReopenedAccounts(t *testing.T) {
 // Test that ClearAccountDataMigration() does not clear account data because is was updated after
 // account was closed.
 func TestClearAccountDataMigrationDoesNotClear(t *testing.T) {
-	db, shutdownFunc := setupIdb(t)
+	db, shutdownFunc := setupIdb(t, test.MakeGenesis())
 	defer shutdownFunc()
 
-	err := db.LoadGenesis(test.MakeGenesis())
-	require.NoError(t, err)
-
 	// Create account A.
 	{
 		stxn, txnRow := test.MakePayTxnRowOrPanic(
@@ -214,7 +205,7 @@ func TestClearAccountDataMigrationDoesNotClear(t *testing.T) {
 	}
 
 	// Run migration.
-	err = ClearAccountDataMigration(db, &MigrationState{})
+	err := ClearAccountDataMigration(db, &MigrationState{})
 	assert.NoError(t, err)
 
 	// Check that account A is online and has auth addr and keyreg data.
@@ -233,15 +224,12 @@ func TestClearAccountDataMigrationDoesNotClear(t *testing.T) {
 
 // Test that ClearAccountDataMigration() increments the next migration number.
 func TestClearAccountDataMigrationIncMigrationNum(t *testing.T) {
-	db, shutdownFunc := setupIdb(t)
+	db, shutdownFunc := setupIdb(t, test.MakeGenesis())
 	defer shutdownFunc()
 
-	err := db.LoadGenesis(test.MakeGenesis())
-	require.NoError(t, err)
-
 	// Run migration.
 	state := MigrationState{NextMigration: 13}
-	err = ClearAccountDataMigration(db, &state)
+	err := ClearAccountDataMigration(db, &state)
 	assert.NoError(t, err)
 
 	assert.Equal(t, 14, state.NextMigration)
@@ -250,7 +238,7 @@ func TestClearAccountDataMigrationIncMigrationNum(t *testing.T) {
 }
 
 func TestMakeDeletedNotNullMigration(t *testing.T) {
-	db, shutdownFunc := setupIdb(t)
+	db, shutdownFunc := setupIdb(t, test.MakeGenesis())
 	defer shutdownFunc()
 
 	// Make deleted columns nullable.