github.com/deso-protocol/core@v1.2.9/lib/block_view_bitcoin_test.go (about)

     1  package lib
     2  
     3  import (
     4  	"bytes"
     5  	"encoding/hex"
     6  	"fmt"
     7  	"github.com/btcsuite/btcd/btcec"
     8  	"github.com/btcsuite/btcd/wire"
     9  	merkletree "github.com/deso-protocol/go-merkle-tree"
    10  	"github.com/dgraph-io/badger/v3"
    11  	"github.com/stretchr/testify/assert"
    12  	"github.com/stretchr/testify/require"
    13  	"io/ioutil"
    14  	"math/big"
    15  	"os"
    16  	"strconv"
    17  	"strings"
    18  	"testing"
    19  )
    20  
    21  const (
    22  	BitcoinTestnetMnemonic       = "clump donkey smoke"
    23  	BitcoinTestnetDerivationPath = "m/44'/1'/0'/"
    24  
    25  	BitcoinTestnetBurnAddress = "ms9ybkD3E685i54ZqW8osN7qg3KnQXZabH"
    26  	BitcoinTestnetBurnPub     = "02bcb72f2dcc0a21aaa31ba792c8bf4a13e3393d7d1b3073afbac613a06dd1d99f"
    27  	BitcoinTestnetBurnPriv    = "cUFfryF4sMvdPzcXMXRVFfK4D5wZzsbZDEqGfBdb7o2MJfE9aoiN"
    28  
    29  	BitcoinTestnetAddress1 = "mqsT6WSy5D1xa2GGxsVm1dPGrk7shccwk3"
    30  	BitcoinTestnetPub1     = "02bce3413e2c2eb510208fefd883861f4d65ac494070a76a837196ea663c00f23c"
    31  	BitcoinTestnetPriv1    = "cQ6NjLY85qGNpEr8rsHZRs4USVpYVLUzYiqufVTpw2gvQ3Hrcfdf"
    32  
    33  	BitcoinTestnetAddress2 = "mzcT3DXVuEZho8FZS6428Tk8gbyDTeBRyF"
    34  	BitcoinTestnetPub2     = "0368bb82e27246e4fc386eb641fee1ae7bc0b0e0684753a58c64370eab9573ce80"
    35  	BitcoinTestnetPriv2    = "cR2cSmj3pZ51JGjVzmvHiJwAY1m7tb9x8FCesdSkqzBUHayzifM8"
    36  
    37  	BitcoinTestnetAddress3 = "myewf7QQJbXhzdx8QUZuxbtqUuD71Dhwy2"
    38  	BitcoinTestnetPub3     = "03da23d9ac943570a2ecf543733c3f39b8037144397b3bd2306e881539170e47d6"
    39  	BitcoinTestnetPriv3    = "cU5PpBsfZbiHfFaCoBVDnCo8wYEUjkr4NxbhnRcSd5qPvG5ofKvN"
    40  
    41  	TestDataDir = "../test_data"
    42  )
    43  
    44  func GetTestParamsCopy(
    45  	startHeader *wire.BlockHeader, startHeight uint32,
    46  	paramss *DeSoParams, minBurnBlocks uint32,
    47  ) *DeSoParams {
    48  	// Set the BitcoinExchange-related params to canned values.
    49  	paramsCopy := *paramss
    50  	headerHash := (BlockHash)(startHeader.BlockHash())
    51  	paramsCopy.BitcoinStartBlockNode = NewBlockNode(
    52  		nil,         /*ParentNode*/
    53  		&headerHash, /*Hash*/
    54  		startHeight,
    55  		_difficultyBitsToHash(startHeader.Bits),
    56  		// CumWork: We set the work of the start node such that, when added to all of the
    57  		// blocks that follow it, it hurdles the min chain work.
    58  		big.NewInt(0),
    59  		// We are bastardizing the DeSo header to store Bitcoin information here.
    60  		&MsgDeSoHeader{
    61  			TstampSecs: uint64(startHeader.Timestamp.Unix()),
    62  			Height:     0,
    63  		},
    64  		StatusBitcoinHeaderValidated,
    65  	)
    66  
    67  	return &paramsCopy
    68  }
    69  
    70  func _dumpAndLoadMempool(mempool *DeSoMempool) {
    71  	mempoolDir := os.TempDir()
    72  	mempool.mempoolDir = mempoolDir
    73  	mempool.DumpTxnsToDB()
    74  	newMempool := NewDeSoMempool(
    75  		mempool.bc, 0, /* rateLimitFeeRateNanosPerKB */
    76  		0 /* minFeeRateNanosPerKB */, "", true,
    77  		mempool.dataDir, mempoolDir)
    78  	mempool.mempoolDir = ""
    79  	mempool.resetPool(newMempool)
    80  }
    81  
    82  func _readBitcoinExchangeTestData(t *testing.T) (
    83  	_blocks []*wire.MsgBlock, _headers []*wire.BlockHeader, _headerHeights []uint32) {
    84  
    85  	require := require.New(t)
    86  
    87  	blocks := []*wire.MsgBlock{}
    88  	{
    89  		data, err := ioutil.ReadFile(TestDataDir + "/bitcoin_testnet_blocks_containing_burn.txt")
    90  		require.NoError(err)
    91  
    92  		lines := strings.Split(string(data), "\n")
    93  		lines = lines[:len(lines)-1]
    94  
    95  		for _, ll := range lines {
    96  			cols := strings.Split(ll, ",")
    97  			blockHash := mustDecodeHexBlockHash(cols[0])
    98  			block := &wire.MsgBlock{}
    99  			blockBytes, err := hex.DecodeString(cols[1])
   100  			require.NoError(err)
   101  
   102  			err = block.Deserialize(bytes.NewBuffer(blockBytes))
   103  			require.NoError(err)
   104  
   105  			parsedBlockHash := (BlockHash)(block.BlockHash())
   106  			require.Equal(*blockHash, parsedBlockHash)
   107  
   108  			blocks = append(blocks, block)
   109  		}
   110  	}
   111  
   112  	headers := []*wire.BlockHeader{}
   113  	headerHeights := []uint32{}
   114  	{
   115  		data, err := ioutil.ReadFile(TestDataDir + "/bitcoin_testnet_headers_for_burn.txt")
   116  		require.NoError(err)
   117  
   118  		lines := strings.Split(string(data), "\n")
   119  		lines = lines[:len(lines)-1]
   120  
   121  		for _, ll := range lines {
   122  			cols := strings.Split(ll, ",")
   123  
   124  			// Parse the block height
   125  			blockHeight, err := strconv.Atoi(cols[0])
   126  			require.NoError(err)
   127  
   128  			// Parse the header hash
   129  			headerHashBytes, err := hex.DecodeString(cols[1])
   130  			require.NoError(err)
   131  			headerHash := BlockHash{}
   132  			copy(headerHash[:], headerHashBytes[:])
   133  
   134  			// Parse the header
   135  			headerBytes, err := hex.DecodeString(cols[2])
   136  			require.NoError(err)
   137  			header := &wire.BlockHeader{}
   138  			header.Deserialize(bytes.NewBuffer(headerBytes))
   139  
   140  			// Verify that the header hash matches the hash of the header.
   141  			require.Equal(headerHash, (BlockHash)(header.BlockHash()))
   142  
   143  			headers = append(headers, header)
   144  			headerHeights = append(headerHeights, uint32(blockHeight))
   145  		}
   146  	}
   147  	return blocks, headers, headerHeights
   148  }
   149  
   150  func _privStringToKeys(t *testing.T, privString string) (*btcec.PrivateKey, *btcec.PublicKey) {
   151  	require := require.New(t)
   152  	result, _, err := Base58CheckDecodePrefix(privString, 1)
   153  	require.NoError(err)
   154  	result = result[:len(result)-1]
   155  	return btcec.PrivKeyFromBytes(btcec.S256(), result)
   156  }
   157  
   158  func _updateUSDCentsPerBitcoinExchangeRate(t *testing.T, chain *Blockchain, db *badger.DB,
   159  	params *DeSoParams, feeRateNanosPerKB uint64, updaterPkBase58Check string,
   160  	updaterPrivBase58Check string, usdCentsPerBitcoin uint64) (
   161  	_utxoOps []*UtxoOperation, _txn *MsgDeSoTxn, _height uint32, _err error) {
   162  
   163  	assert := assert.New(t)
   164  	require := require.New(t)
   165  	_ = assert
   166  	_ = require
   167  
   168  	updaterPkBytes, _, err := Base58CheckDecode(updaterPkBase58Check)
   169  	require.NoError(err)
   170  
   171  	txn, totalInputMake, changeAmountMake, feesMake, err := chain.CreateUpdateBitcoinUSDExchangeRateTxn(
   172  		updaterPkBytes,
   173  		usdCentsPerBitcoin,
   174  		feeRateNanosPerKB,
   175  		nil,
   176  		[]*DeSoOutput{})
   177  	if err != nil {
   178  		return nil, nil, 0, err
   179  	}
   180  
   181  	require.Equal(totalInputMake, changeAmountMake+feesMake)
   182  
   183  	// Sign the transaction now that its inputs are set up.
   184  	_signTxn(t, txn, updaterPrivBase58Check)
   185  
   186  	utxoView, err := NewUtxoView(db, params, nil)
   187  	require.NoError(err)
   188  
   189  	txHash := txn.Hash()
   190  	// Always use height+1 for validation since it's assumed the transaction will
   191  	// get mined into the next block.
   192  	blockHeight := chain.blockTip().Height + 1
   193  	utxoOps, totalInput, totalOutput, fees, err :=
   194  		utxoView.ConnectTransaction(txn, txHash, getTxnSize(*txn), blockHeight, true /*verifySignature*/, false /*ignoreUtxos*/)
   195  	// ConnectTransaction should treat the amount locked as contributing to the
   196  	// output.
   197  	if err != nil {
   198  		return nil, nil, 0, err
   199  	}
   200  	require.Equal(totalInput, totalOutput+fees)
   201  	require.Equal(totalInput, totalInputMake)
   202  
   203  	// We should have one SPEND UtxoOperation for each input, one ADD operation
   204  	// for each output, and one OperationTypePrivateMessage operation at the end.
   205  	require.Equal(len(txn.TxInputs)+len(txn.TxOutputs)+1, len(utxoOps))
   206  	for ii := 0; ii < len(txn.TxInputs); ii++ {
   207  		require.Equal(OperationTypeSpendUtxo, utxoOps[ii].Type)
   208  	}
   209  	require.Equal(
   210  		OperationTypeUpdateBitcoinUSDExchangeRate, utxoOps[len(utxoOps)-1].Type)
   211  
   212  	return utxoOps, txn, blockHeight, nil
   213  }
   214  
   215  func TestBitcoinExchange(t *testing.T) {
   216  	assert := assert.New(t)
   217  	require := require.New(t)
   218  	_ = assert
   219  	_ = require
   220  
   221  	// Don't refresh the universal view for this test, since it causes a race condition
   222  	// to trigger.
   223  	// TODO: Lower this value to .1 and fix this race condition.
   224  	ReadOnlyUtxoViewRegenerationIntervalSeconds = 100
   225  
   226  	oldInitialUSDCentsPerBitcoinExchangeRate := InitialUSDCentsPerBitcoinExchangeRate
   227  	InitialUSDCentsPerBitcoinExchangeRate = uint64(1350000)
   228  	defer func() {
   229  		InitialUSDCentsPerBitcoinExchangeRate = oldInitialUSDCentsPerBitcoinExchangeRate
   230  	}()
   231  
   232  	paramsTmp := DeSoTestnetParams
   233  	paramsTmp.DeSoNanosPurchasedAtGenesis = 0
   234  	chain, params, db := NewLowDifficultyBlockchainWithParams(&paramsTmp)
   235  	mempool, miner := NewTestMiner(t, chain, params, true /*isSender*/)
   236  
   237  	// Read in the test Bitcoin blocks and headers.
   238  	bitcoinBlocks, bitcoinHeaders, bitcoinHeaderHeights := _readBitcoinExchangeTestData(t)
   239  
   240  	// Extract BitcoinExchange transactions from the test Bitcoin blocks.
   241  	bitcoinExchangeTxns := []*MsgDeSoTxn{}
   242  	for _, block := range bitcoinBlocks {
   243  		currentBurnTxns, err :=
   244  			ExtractBitcoinExchangeTransactionsFromBitcoinBlock(
   245  				block, BitcoinTestnetBurnAddress, params)
   246  		require.NoError(err)
   247  		bitcoinExchangeTxns = append(bitcoinExchangeTxns, currentBurnTxns...)
   248  	}
   249  
   250  	// Verify that Bitcoin burn transactions are properly extracted from Bitcoin blocks
   251  	// and the their burn amounts are computed correctly.
   252  	require.Equal(9, len(bitcoinExchangeTxns))
   253  	expectedBitcoinBurnAmounts := []int64{
   254  		10000,
   255  		12500,
   256  		41000,
   257  		20000,
   258  		15000,
   259  		50000,
   260  		15000,
   261  		20482,
   262  		2490,
   263  	}
   264  	rateUpdateIndex := 4
   265  	expectedDeSoNanosMinted := []int64{
   266  		2700510570,
   267  		3375631103,
   268  		11072014581,
   269  		5400951887,
   270  		// We double the exchange rate at this point. Include a zero
   271  		// here to account for this.
   272  		0,
   273  		8103578296,
   274  		27011598923,
   275  		8103381058,
   276  		11064823217,
   277  		1345146534,
   278  	}
   279  	blockIndexesForTransactions := []int{1, 1, 1, 1, 1, 1, 1, 3, 3}
   280  	for ii, bitcoinExchangeTxn := range bitcoinExchangeTxns {
   281  		txnMeta := bitcoinExchangeTxn.TxnMeta.(*BitcoinExchangeMetadata)
   282  		burnTxn := txnMeta.BitcoinTransaction
   283  		burnOutput, err := _computeBitcoinBurnOutput(
   284  			burnTxn, BitcoinTestnetBurnAddress, params.BitcoinBtcdParams)
   285  		require.NoError(err)
   286  		assert.Equalf(expectedBitcoinBurnAmounts[ii], burnOutput,
   287  			"Bitcoin burn amount for burn txn %d doesn't line up with "+
   288  				"what is expected", ii)
   289  
   290  		// Sanity-check that the Bitcoin block hashes line up.
   291  		blockIndex := blockIndexesForTransactions[ii]
   292  		blockForTxn := bitcoinBlocks[blockIndex]
   293  		{
   294  			hash1 := (BlockHash)(blockForTxn.BlockHash())
   295  			hash2 := *txnMeta.BitcoinBlockHash
   296  			require.Equalf(
   297  				hash1, hash2,
   298  				"Bitcoin block hash for txn does not line up with block hash: %v %v %d", &hash1, &hash2, ii)
   299  		}
   300  
   301  		// Sanity-check that the Merkle root lines up with what's in the block.
   302  		{
   303  			hash1 := (BlockHash)(blockForTxn.Header.MerkleRoot)
   304  			hash2 := *txnMeta.BitcoinMerkleRoot
   305  			require.Equalf(
   306  				hash1, hash2,
   307  				"Bitcoin merkle root for txn does not line up with block hash: %v %v %d", &hash1, &hash2, ii)
   308  		}
   309  
   310  		// Verify that the merkle proof checks out.
   311  		{
   312  			txHash := ((BlockHash)(txnMeta.BitcoinTransaction.TxHash()))
   313  			merkleProofIsValid := merkletree.VerifyProof(
   314  				txHash[:], txnMeta.BitcoinMerkleProof, txnMeta.BitcoinMerkleRoot[:])
   315  			require.Truef(
   316  				merkleProofIsValid, "Problem verifying merkle proof for burn txn %d", ii)
   317  		}
   318  
   319  		// Verify that using the wrong Merkle root doesn't work.
   320  		{
   321  			badBlock := bitcoinBlocks[blockIndex-1]
   322  			badMerkleRoot := badBlock.Header.MerkleRoot[:]
   323  			txHash := ((BlockHash)(txnMeta.BitcoinTransaction.TxHash()))
   324  			merkleProofIsValid := merkletree.VerifyProof(
   325  				txHash[:], txnMeta.BitcoinMerkleProof, badMerkleRoot)
   326  			require.Falsef(
   327  				merkleProofIsValid, "Bad Merkle root was actually verified for burn txn %d", ii)
   328  		}
   329  
   330  		// Verify that serializing and deserializing work for this transaction.
   331  		bb, err := bitcoinExchangeTxn.ToBytes(false /*preSignature*/)
   332  		require.NoError(err)
   333  		parsedBitcoinExchangeTxn := &MsgDeSoTxn{}
   334  		parsedBitcoinExchangeTxn.FromBytes(bb)
   335  		require.Equal(bitcoinExchangeTxn, parsedBitcoinExchangeTxn)
   336  	}
   337  
   338  	// Find the header in our header list corresponding to the first test block,
   339  	// which contains the first Bitcoin
   340  	firstBitcoinBurnBlock := bitcoinBlocks[1]
   341  	firstBitcoinBurnBlockHash := firstBitcoinBurnBlock.BlockHash()
   342  	headerIndexOfFirstBurn := -1
   343  	for headerIndex := range bitcoinHeaders {
   344  		if firstBitcoinBurnBlockHash == bitcoinHeaders[headerIndex].BlockHash() {
   345  			headerIndexOfFirstBurn = headerIndex
   346  			break
   347  		}
   348  	}
   349  	require.Greater(headerIndexOfFirstBurn, 0)
   350  
   351  	minBurnBlocks := uint32(2)
   352  	startHeaderIndex := 0
   353  	paramsCopy := GetTestParamsCopy(
   354  		bitcoinHeaders[startHeaderIndex], bitcoinHeaderHeights[startHeaderIndex],
   355  		params, minBurnBlocks,
   356  	)
   357  	paramsCopy.BitcoinBurnAddress = BitcoinTestnetBurnAddress
   358  	chain.params = paramsCopy
   359  	// Reset the pool to give the mempool access to the new BitcoinManager object.
   360  	mempool.resetPool(NewDeSoMempool(chain, 0, /* rateLimitFeeRateNanosPerKB */
   361  		0, /* minFeeRateNanosPerKB */
   362  		"" /*blockCypherAPIKey*/, false,
   363  		"" /*dataDir*/, ""))
   364  
   365  	// Validating the first Bitcoin burn transaction via a UtxoView should
   366  	// fail because the block corresponding to it is not yet in the BitcoinManager.
   367  	burnTxn1 := bitcoinExchangeTxns[0]
   368  	burnTxn2 := bitcoinExchangeTxns[1]
   369  
   370  	// Applying the full transaction with its merkle proof should work.
   371  	{
   372  		mempoolTxs, err := mempool.processTransaction(
   373  			burnTxn1, true /*allowUnconnectedTxn*/, true /*rateLimit*/, 0 /*peerID*/, true /*verifySignatures*/)
   374  		require.NoError(err)
   375  		require.Equal(1, len(mempoolTxs))
   376  		require.Equal(1, len(mempool.poolMap))
   377  		mempoolTxRet := mempool.poolMap[*mempoolTxs[0].Hash]
   378  		require.Equal(
   379  			mempoolTxRet.Tx.TxnMeta.(*BitcoinExchangeMetadata),
   380  			burnTxn1.TxnMeta.(*BitcoinExchangeMetadata))
   381  	}
   382  
   383  	// According to the mempool, the balance of the user whose public key created
   384  	// the Bitcoin burn transaction should now have some DeSo.
   385  	pkBytes1, _ := hex.DecodeString(BitcoinTestnetPub1)
   386  	pkBytes2, _ := hex.DecodeString(BitcoinTestnetPub2)
   387  	pkBytes3, _ := hex.DecodeString(BitcoinTestnetPub3)
   388  	{
   389  		utxoEntries, err := chain.GetSpendableUtxosForPublicKey(pkBytes1, mempool, nil)
   390  		require.NoError(err)
   391  
   392  		require.Equal(1, len(utxoEntries))
   393  		assert.Equal(int64(2697810060), int64(utxoEntries[0].AmountNanos))
   394  	}
   395  
   396  	// The mempool should be able to process a burn transaction directly.
   397  	{
   398  		mempoolTxsAdded, err := mempool.processTransaction(
   399  			burnTxn2, true /*allowUnconnectedTxn*/, true /*rateLimit*/, 0, /*peerID*/
   400  			true /*verifySignatures*/)
   401  		require.NoError(err)
   402  		require.Equal(1, len(mempoolTxsAdded))
   403  		require.Equal(2, len(mempool.poolMap))
   404  		mempoolTxRet := mempool.poolMap[*mempoolTxsAdded[0].Hash]
   405  		require.Equal(
   406  			mempoolTxRet.Tx.TxnMeta.(*BitcoinExchangeMetadata),
   407  			burnTxn2.TxnMeta.(*BitcoinExchangeMetadata))
   408  	}
   409  
   410  	// According to the mempool, the balances should have updated.
   411  	{
   412  		utxoEntries, err := chain.GetSpendableUtxosForPublicKey(pkBytes3, mempool, nil)
   413  		require.NoError(err)
   414  
   415  		require.Equal(1, len(utxoEntries))
   416  		assert.Equal(int64(3372255472), int64(utxoEntries[0].AmountNanos))
   417  	}
   418  
   419  	// If the mempool is not consulted, the balances should be zero.
   420  	{
   421  		utxoEntries, err := chain.GetSpendableUtxosForPublicKey(pkBytes3, nil, nil)
   422  		require.NoError(err)
   423  		require.Equal(0, len(utxoEntries))
   424  	}
   425  
   426  	// The UtxoView should accept all of the burn transactions now that their blocks
   427  	// have enough work built on them.
   428  
   429  	// Set the founder public key to something else for the remainder of the test.
   430  	// Give this public key a bit of money to play with.
   431  	//oldFounderRewardPubKey := FounderRewardPubKeyBase58Check
   432  	//FounderRewardPubKeyBase58Check = moneyPkString
   433  	//defer func() {
   434  	//FounderRewardPubKeyBase58Check = oldFounderRewardPubKey
   435  	//}()
   436  
   437  	// Make the moneyPkString the paramUpdater so they can update the exchange rate.
   438  	params.ParamUpdaterPublicKeys = make(map[PkMapKey]bool)
   439  	params.ParamUpdaterPublicKeys[MakePkMapKey(MustBase58CheckDecode(moneyPkString))] = true
   440  	paramsCopy.ParamUpdaterPublicKeys = params.ParamUpdaterPublicKeys
   441  
   442  	// Applying all the txns to the UtxoView should work. Include a rate update
   443  	// in the middle.
   444  	utxoOpsList := [][]*UtxoOperation{}
   445  	{
   446  		utxoView, err := NewUtxoView(db, paramsCopy, nil)
   447  		require.NoError(err)
   448  
   449  		// Add a placeholder where the rate update is going to be
   450  		fff := append([]*MsgDeSoTxn{}, bitcoinExchangeTxns[:rateUpdateIndex]...)
   451  		fff = append(fff, nil)
   452  		fff = append(fff, bitcoinExchangeTxns[rateUpdateIndex:]...)
   453  		bitcoinExchangeTxns = fff
   454  
   455  		for ii := range bitcoinExchangeTxns {
   456  			fmt.Println("Processing BitcoinExchange: ", ii)
   457  
   458  			// When we hit the rate update, populate the placeholder.
   459  			if ii == rateUpdateIndex {
   460  				newUSDCentsPerBitcoin := uint64(27000 * 100)
   461  				_, rateUpdateTxn, _, err := _updateUSDCentsPerBitcoinExchangeRate(
   462  					t, chain, db, params, 100, /*feeRateNanosPerKB*/
   463  					moneyPkString,
   464  					moneyPrivString,
   465  					newUSDCentsPerBitcoin)
   466  				require.NoError(err)
   467  
   468  				bitcoinExchangeTxns[ii] = rateUpdateTxn
   469  				burnTxn := bitcoinExchangeTxns[ii]
   470  				burnTxnSize := getTxnSize(*burnTxn)
   471  				blockHeight := chain.blockTip().Height + 1
   472  				utxoOps, totalInput, totalOutput, fees, err :=
   473  					utxoView.ConnectTransaction(
   474  						burnTxn, burnTxn.Hash(), burnTxnSize, blockHeight, true /*verifySignature*/, false /*ignoreUtxos*/)
   475  				_, _, _ = totalInput, totalOutput, fees
   476  				require.NoError(err)
   477  				utxoOpsList = append(utxoOpsList, utxoOps)
   478  				continue
   479  			}
   480  
   481  			burnTxn := bitcoinExchangeTxns[ii]
   482  			burnTxnSize := getTxnSize(*burnTxn)
   483  			blockHeight := chain.blockTip().Height + 1
   484  			utxoOps, totalInput, totalOutput, fees, err :=
   485  				utxoView.ConnectTransaction(
   486  					burnTxn, burnTxn.Hash(), burnTxnSize, blockHeight, true /*verifySignature*/, false /*ignoreUtxos*/)
   487  			require.NoError(err)
   488  
   489  			require.Equal(2, len(utxoOps))
   490  			//fmt.Println(int64(totalInput), ",")
   491  			assert.Equal(expectedDeSoNanosMinted[ii], int64(totalInput))
   492  			assert.Equal(expectedDeSoNanosMinted[ii]*int64(paramsCopy.BitcoinExchangeFeeBasisPoints)/10000, int64(fees))
   493  			assert.Equal(int64(fees), int64(totalInput-totalOutput))
   494  
   495  			_, _, _ = ii, totalOutput, fees
   496  			utxoOpsList = append(utxoOpsList, utxoOps)
   497  		}
   498  
   499  		// Flushing the UtxoView should work.
   500  		require.NoError(utxoView.FlushToDb())
   501  	}
   502  
   503  	// The balances according to the db after the flush should be correct.
   504  	{
   505  		utxoEntries, err := chain.GetSpendableUtxosForPublicKey(pkBytes1, nil, nil)
   506  		require.NoError(err)
   507  		require.Equal(5, len(utxoEntries))
   508  		totalBalance := uint64(0)
   509  		for _, utxoEntry := range utxoEntries {
   510  			totalBalance += utxoEntry.AmountNanos
   511  		}
   512  		// Note the 10bp fee.
   513  		assert.Equal(int64(47475508103), int64(totalBalance))
   514  	}
   515  	{
   516  		utxoEntries, err := chain.GetSpendableUtxosForPublicKey(pkBytes2, nil, nil)
   517  		require.NoError(err)
   518  		require.Equal(1, len(utxoEntries))
   519  		// Note the 10bp fee.
   520  		assert.Equal(int64(8095277677), int64(utxoEntries[0].AmountNanos))
   521  	}
   522  	{
   523  		utxoEntries, err := chain.GetSpendableUtxosForPublicKey(pkBytes3, nil, nil)
   524  		require.NoError(err)
   525  		require.Equal(3, len(utxoEntries))
   526  		totalBalance := uint64(0)
   527  		for _, utxoEntry := range utxoEntries {
   528  			totalBalance += utxoEntry.AmountNanos
   529  		}
   530  		// Note the 10bp fee.
   531  		assert.Equal(int64(22528672757), int64(totalBalance))
   532  	}
   533  
   534  	// Spending from the outputs created by a burn should work.
   535  	desoPub1 := Base58CheckEncode(pkBytes1, false /*isPrivate*/, paramsCopy)
   536  	priv1, _ := _privStringToKeys(t, BitcoinTestnetPriv1)
   537  	desoPriv1 := Base58CheckEncode(priv1.Serialize(), true /*isPrivate*/, paramsCopy)
   538  	desoPub2 := Base58CheckEncode(pkBytes2, false /*isPrivate*/, paramsCopy)
   539  	priv2, _ := _privStringToKeys(t, BitcoinTestnetPriv2)
   540  	desoPriv2 := Base58CheckEncode(priv2.Serialize(), true /*isPrivate*/, paramsCopy)
   541  	desoPub3 := Base58CheckEncode(pkBytes3, false /*isPrivate*/, paramsCopy)
   542  	priv3, _ := _privStringToKeys(t, BitcoinTestnetPriv3)
   543  	desoPriv3 := Base58CheckEncode(priv3.Serialize(), true /*isPrivate*/, paramsCopy)
   544  	{
   545  		currentOps, currentTxn, _ := _doBasicTransferWithViewFlush(
   546  			t, chain, db, params, desoPub1, desoPub2,
   547  			desoPriv1, 100000*100000 /*amount to send*/, 11 /*feerate*/)
   548  
   549  		utxoOpsList = append(utxoOpsList, currentOps)
   550  		bitcoinExchangeTxns = append(bitcoinExchangeTxns, currentTxn)
   551  	}
   552  	{
   553  		currentOps, currentTxn, _ := _doBasicTransferWithViewFlush(
   554  			t, chain, db, params, desoPub3, desoPub1,
   555  			desoPriv3, 60000*100000 /*amount to send*/, 11 /*feerate*/)
   556  
   557  		utxoOpsList = append(utxoOpsList, currentOps)
   558  		bitcoinExchangeTxns = append(bitcoinExchangeTxns, currentTxn)
   559  	}
   560  	{
   561  		currentOps, currentTxn, _ := _doBasicTransferWithViewFlush(
   562  			t, chain, db, params, desoPub2, desoPub1,
   563  			desoPriv2, 60000*100000 /*amount to send*/, 11 /*feerate*/)
   564  
   565  		utxoOpsList = append(utxoOpsList, currentOps)
   566  		bitcoinExchangeTxns = append(bitcoinExchangeTxns, currentTxn)
   567  	}
   568  
   569  	// The balances according to the db after the spends above should be correct.
   570  	{
   571  		utxoEntries, err := chain.GetSpendableUtxosForPublicKey(pkBytes1, nil, nil)
   572  		require.NoError(err)
   573  		totalBalance := uint64(0)
   574  		for _, utxoEntry := range utxoEntries {
   575  			totalBalance += utxoEntry.AmountNanos
   576  		}
   577  		assert.Equal(int64(49455017177), int64(totalBalance))
   578  	}
   579  	{
   580  		utxoEntries, err := chain.GetSpendableUtxosForPublicKey(pkBytes2, nil, nil)
   581  		require.NoError(err)
   582  		assert.Equal(int64(2087182397), int64(utxoEntries[0].AmountNanos))
   583  	}
   584  	{
   585  		utxoEntries, err := chain.GetSpendableUtxosForPublicKey(pkBytes3, nil, nil)
   586  		require.NoError(err)
   587  		totalBalance := uint64(0)
   588  		for _, utxoEntry := range utxoEntries {
   589  			totalBalance += utxoEntry.AmountNanos
   590  		}
   591  		assert.Equal(int64(16517205024), int64(totalBalance))
   592  	}
   593  
   594  	{
   595  		// Rolling back all the transactions should work.
   596  		utxoView, err := NewUtxoView(db, paramsCopy, nil)
   597  		require.NoError(err)
   598  		for ii := range bitcoinExchangeTxns {
   599  			index := len(bitcoinExchangeTxns) - 1 - ii
   600  			burnTxn := bitcoinExchangeTxns[index]
   601  			blockHeight := chain.blockTip().Height + 1
   602  			err := utxoView.DisconnectTransaction(burnTxn, burnTxn.Hash(), utxoOpsList[index], blockHeight)
   603  			require.NoErrorf(err, "Transaction index: %v", index)
   604  		}
   605  
   606  		// Flushing the UtxoView back to the db after rolling back the
   607  		require.NoError(utxoView.FlushToDb())
   608  	}
   609  
   610  	// The balances according to the db after rolling back and flushing everything
   611  	// should be zero.
   612  	{
   613  		utxoEntries, err := chain.GetSpendableUtxosForPublicKey(pkBytes1, nil, nil)
   614  		require.NoError(err)
   615  		require.Equal(0, len(utxoEntries))
   616  	}
   617  	{
   618  		utxoEntries, err := chain.GetSpendableUtxosForPublicKey(pkBytes2, nil, nil)
   619  		require.NoError(err)
   620  		require.Equal(0, len(utxoEntries))
   621  	}
   622  	{
   623  		utxoEntries, err := chain.GetSpendableUtxosForPublicKey(pkBytes3, nil, nil)
   624  		require.NoError(err)
   625  		require.Equal(0, len(utxoEntries))
   626  	}
   627  
   628  	// Re-applying all the transactions to the view and rolling back without
   629  	// flushing should be fine.
   630  	utxoOpsList = [][]*UtxoOperation{}
   631  	{
   632  		utxoView, err := NewUtxoView(db, paramsCopy, nil)
   633  		require.NoError(err)
   634  		for ii, burnTxn := range bitcoinExchangeTxns {
   635  			blockHeight := chain.blockTip().Height + 1
   636  			burnTxnSize := getTxnSize(*burnTxn)
   637  			utxoOps, totalInput, totalOutput, fees, err :=
   638  				utxoView.ConnectTransaction(burnTxn, burnTxn.Hash(), burnTxnSize, blockHeight, true /*verifySignature*/, false /*ignoreUtxos*/)
   639  			require.NoError(err)
   640  
   641  			if ii < len(expectedBitcoinBurnAmounts) {
   642  				if ii != rateUpdateIndex {
   643  					require.Equal(2, len(utxoOps))
   644  					assert.Equal(int64(totalInput), expectedDeSoNanosMinted[ii])
   645  					assert.Equal(int64(fees), expectedDeSoNanosMinted[ii]*int64(paramsCopy.BitcoinExchangeFeeBasisPoints)/10000)
   646  					assert.Equal(int64(fees), int64(totalInput-totalOutput))
   647  				}
   648  			}
   649  
   650  			utxoOpsList = append(utxoOpsList, utxoOps)
   651  		}
   652  
   653  		for ii := range bitcoinExchangeTxns {
   654  			index := len(bitcoinExchangeTxns) - 1 - ii
   655  			burnTxn := bitcoinExchangeTxns[index]
   656  			blockHeight := chain.blockTip().Height + 1
   657  			err := utxoView.DisconnectTransaction(burnTxn, burnTxn.Hash(), utxoOpsList[index], blockHeight)
   658  			require.NoError(err)
   659  		}
   660  
   661  		// Flushing the view after applying and rolling back should work.
   662  		require.NoError(utxoView.FlushToDb())
   663  	}
   664  
   665  	// The balances according to the db after applying and unapplying all the
   666  	// transactions to a view with a flush at the end should be zero.
   667  	{
   668  		utxoEntries, err := chain.GetSpendableUtxosForPublicKey(pkBytes1, nil, nil)
   669  		require.NoError(err)
   670  		require.Equal(0, len(utxoEntries))
   671  	}
   672  	{
   673  		utxoEntries, err := chain.GetSpendableUtxosForPublicKey(pkBytes2, nil, nil)
   674  		require.NoError(err)
   675  		require.Equal(0, len(utxoEntries))
   676  	}
   677  	{
   678  		utxoEntries, err := chain.GetSpendableUtxosForPublicKey(pkBytes3, nil, nil)
   679  		require.NoError(err)
   680  		require.Equal(0, len(utxoEntries))
   681  	}
   682  
   683  	// Running all the transactions through the mempool should work and result
   684  	// in all of them being added.
   685  	{
   686  		for _, burnTxn := range bitcoinExchangeTxns {
   687  			// We have to remove the transactions first.
   688  			mempool.inefficientRemoveTransaction(burnTxn)
   689  		}
   690  		for ii, burnTxn := range bitcoinExchangeTxns {
   691  			require.Equal(ii, len(mempool.poolMap))
   692  			mempoolTxsAdded, err := mempool.processTransaction(
   693  				burnTxn, true /*allowUnconnectedTxn*/, true /*rateLimit*/, 0, /*peerID*/
   694  				true /*verifySignatures*/)
   695  			require.NoErrorf(err, "on index: %v", ii)
   696  			require.Equal(1, len(mempoolTxsAdded))
   697  		}
   698  	}
   699  
   700  	// Test that the mempool can be backed up properly by dumping them and then
   701  	// reloading them.
   702  	_dumpAndLoadMempool(mempool)
   703  
   704  	// The balances according to the mempool after applying all the transactions
   705  	// should be correct.
   706  	{
   707  		utxoEntries, err := chain.GetSpendableUtxosForPublicKey(pkBytes1, mempool, nil)
   708  		require.NoError(err)
   709  		totalBalance := uint64(0)
   710  		for _, utxoEntry := range utxoEntries {
   711  			totalBalance += utxoEntry.AmountNanos
   712  		}
   713  		assert.Equal(int64(49455017177), int64(totalBalance))
   714  	}
   715  	{
   716  		utxoEntries, err := chain.GetSpendableUtxosForPublicKey(pkBytes2, mempool, nil)
   717  		require.NoError(err)
   718  		assert.Equal(int64(2087182397), int64(utxoEntries[0].AmountNanos))
   719  	}
   720  	{
   721  		utxoEntries, err := chain.GetSpendableUtxosForPublicKey(pkBytes3, mempool, nil)
   722  		require.NoError(err)
   723  		totalBalance := uint64(0)
   724  		for _, utxoEntry := range utxoEntries {
   725  			totalBalance += utxoEntry.AmountNanos
   726  		}
   727  		assert.Equal(int64(16517205024), int64(totalBalance))
   728  	}
   729  
   730  	// Remove all the transactions from the mempool.
   731  	for _, burnTxn := range bitcoinExchangeTxns {
   732  		mempool.inefficientRemoveTransaction(burnTxn)
   733  	}
   734  
   735  	// Check that removals hit the database properly by calling a dump and
   736  	// then reloading the db state into the view.
   737  	_dumpAndLoadMempool(mempool)
   738  
   739  	// The balances should be zero after removing transactions from the mempool.
   740  	{
   741  		utxoEntries, err := chain.GetSpendableUtxosForPublicKey(pkBytes1, mempool, nil)
   742  		require.NoError(err)
   743  		require.Equal(0, len(utxoEntries))
   744  	}
   745  	{
   746  		utxoEntries, err := chain.GetSpendableUtxosForPublicKey(pkBytes2, mempool, nil)
   747  		require.NoError(err)
   748  		require.Equal(0, len(utxoEntries))
   749  	}
   750  	{
   751  		utxoEntries, err := chain.GetSpendableUtxosForPublicKey(pkBytes3, mempool, nil)
   752  		require.NoError(err)
   753  		require.Equal(0, len(utxoEntries))
   754  	}
   755  
   756  	// Re-add all of the transactions to the mempool so we can mine them into a block.
   757  	{
   758  		for _, burnTxn := range bitcoinExchangeTxns {
   759  			mempoolTxsAdded, err := mempool.processTransaction(
   760  				burnTxn, true /*allowUnconnectedTxn*/, true /*rateLimit*/, 0, /*peerID*/
   761  				true /*verifySignatures*/)
   762  			require.NoError(err)
   763  			require.Equal(1, len(mempoolTxsAdded))
   764  			//require.Equal(0, len(mempool.immatureBitcoinTxns))
   765  		}
   766  	}
   767  
   768  	// Check the db one more time after adding back all the txns.
   769  	_dumpAndLoadMempool(mempool)
   770  
   771  	// Mine a block with all the mempool transactions.
   772  	miner.params = paramsCopy
   773  	miner.BlockProducer.params = paramsCopy
   774  	//
   775  	// All the txns should be in the mempool already but only some of them have enough
   776  	// burn work to satisfy the miner. Note we need to mine two blocks since the first
   777  	// one just makes the DeSo chain time-current.
   778  	finalBlock1, err := miner.MineAndProcessSingleBlock(0 /*threadIndex*/, mempool)
   779  	require.NoError(err)
   780  	_ = finalBlock1
   781  	// Check the mempool dumps and loads from the db properly each time
   782  	_dumpAndLoadMempool(mempool)
   783  
   784  	finalBlock2, err := miner.MineAndProcessSingleBlock(0 /*threadIndex*/, mempool)
   785  	require.NoError(err)
   786  	_dumpAndLoadMempool(mempool)
   787  
   788  	finalBlock3, err := miner.MineAndProcessSingleBlock(0 /*threadIndex*/, mempool)
   789  	require.NoError(err)
   790  	_dumpAndLoadMempool(mempool)
   791  
   792  	finalBlock4, err := miner.MineAndProcessSingleBlock(0 /*threadIndex*/, mempool)
   793  	require.NoError(err)
   794  	_dumpAndLoadMempool(mempool)
   795  
   796  	// Add one for the block reward.
   797  	assert.Equal(len(finalBlock1.Txns), 1)
   798  	// The first block should only have some of the Bitcoin txns since
   799  	// the MinerBitcoinBurnWorkBlocks is higher than the regular burn work.
   800  	assert.Equal(len(finalBlock2.Txns), 14)
   801  	assert.Equal(len(finalBlock3.Txns), 1)
   802  	require.Equal(len(finalBlock4.Txns), 1)
   803  
   804  	// The balances after mining the block should line up.
   805  	{
   806  		utxoEntries, err := chain.GetSpendableUtxosForPublicKey(pkBytes1, nil, nil)
   807  		require.NoError(err)
   808  		totalBalance := uint64(0)
   809  		for _, utxoEntry := range utxoEntries {
   810  			totalBalance += utxoEntry.AmountNanos
   811  		}
   812  		assert.Equal(int64(49455017177), int64(totalBalance))
   813  	}
   814  	{
   815  		utxoEntries, err := chain.GetSpendableUtxosForPublicKey(pkBytes2, nil, nil)
   816  		require.NoError(err)
   817  		assert.Equal(int64(2087182397), int64(utxoEntries[0].AmountNanos))
   818  	}
   819  	{
   820  		utxoEntries, err := chain.GetSpendableUtxosForPublicKey(pkBytes3, nil, nil)
   821  		require.NoError(err)
   822  		totalBalance := uint64(0)
   823  		for _, utxoEntry := range utxoEntries {
   824  			totalBalance += utxoEntry.AmountNanos
   825  		}
   826  		assert.Equal(int64(16517205024), int64(totalBalance))
   827  	}
   828  
   829  	// Roll back the blocks and make sure we don't hit any errors.
   830  	{
   831  		utxoView, err := NewUtxoView(db, paramsCopy, nil)
   832  		require.NoError(err)
   833  
   834  		{
   835  			// Fetch the utxo operations for the block we're detaching. We need these
   836  			// in order to be able to detach the block.
   837  			hash, err := finalBlock4.Header.Hash()
   838  			require.NoError(err)
   839  			utxoOps, err := GetUtxoOperationsForBlock(db, hash)
   840  			require.NoError(err)
   841  
   842  			// Compute the hashes for all the transactions.
   843  			txHashes, err := ComputeTransactionHashes(finalBlock4.Txns)
   844  			require.NoError(err)
   845  			require.NoError(utxoView.DisconnectBlock(finalBlock4, txHashes, utxoOps))
   846  		}
   847  		{
   848  			// Fetch the utxo operations for the block we're detaching. We need these
   849  			// in order to be able to detach the block.
   850  			hash, err := finalBlock3.Header.Hash()
   851  			require.NoError(err)
   852  			utxoOps, err := GetUtxoOperationsForBlock(db, hash)
   853  			require.NoError(err)
   854  
   855  			// Compute the hashes for all the transactions.
   856  			txHashes, err := ComputeTransactionHashes(finalBlock3.Txns)
   857  			require.NoError(err)
   858  			require.NoError(utxoView.DisconnectBlock(finalBlock3, txHashes, utxoOps))
   859  		}
   860  		{
   861  			// Fetch the utxo operations for the block we're detaching. We need these
   862  			// in order to be able to detach the block.
   863  			hash, err := finalBlock2.Header.Hash()
   864  			require.NoError(err)
   865  			utxoOps, err := GetUtxoOperationsForBlock(db, hash)
   866  			require.NoError(err)
   867  
   868  			// Compute the hashes for all the transactions.
   869  			txHashes, err := ComputeTransactionHashes(finalBlock2.Txns)
   870  			require.NoError(err)
   871  			require.NoError(utxoView.DisconnectBlock(finalBlock2, txHashes, utxoOps))
   872  		}
   873  		{
   874  			// Fetch the utxo operations for the block we're detaching. We need these
   875  			// in order to be able to detach the block.
   876  			hash, err := finalBlock1.Header.Hash()
   877  			require.NoError(err)
   878  			utxoOps, err := GetUtxoOperationsForBlock(db, hash)
   879  			require.NoError(err)
   880  
   881  			// Compute the hashes for all the transactions.
   882  			txHashes, err := ComputeTransactionHashes(finalBlock1.Txns)
   883  			require.NoError(err)
   884  			require.NoError(utxoView.DisconnectBlock(finalBlock1, txHashes, utxoOps))
   885  		}
   886  
   887  		// Flushing the view after applying and rolling back should work.
   888  		require.NoError(utxoView.FlushToDb())
   889  	}
   890  
   891  	// The balances according to the db after applying and unapplying all the
   892  	// transactions to a view with a flush at the end should be zero.
   893  	{
   894  		utxoEntries, err := chain.GetSpendableUtxosForPublicKey(pkBytes1, nil, nil)
   895  		require.NoError(err)
   896  		require.Equal(0, len(utxoEntries))
   897  	}
   898  	{
   899  		utxoEntries, err := chain.GetSpendableUtxosForPublicKey(pkBytes2, nil, nil)
   900  		require.NoError(err)
   901  		require.Equal(0, len(utxoEntries))
   902  	}
   903  	{
   904  		utxoEntries, err := chain.GetSpendableUtxosForPublicKey(pkBytes3, nil, nil)
   905  		require.NoError(err)
   906  		require.Equal(0, len(utxoEntries))
   907  	}
   908  
   909  	_, _, _, _, _, _ = db, mempool, miner, bitcoinBlocks, bitcoinHeaders, bitcoinHeaderHeights
   910  }
   911  
   912  func TestBitcoinExchangeGlobalParams(t *testing.T) {
   913  	assert := assert.New(t)
   914  	require := require.New(t)
   915  	_ = assert
   916  	_ = require
   917  
   918  	// Don't refresh the universal view for this test, since it causes a race condition
   919  	// to trigger.
   920  	// TODO: Lower this value to .1 and fix this race condition.
   921  	ReadOnlyUtxoViewRegenerationIntervalSeconds = 100
   922  
   923  	oldInitialUSDCentsPerBitcoinExchangeRate := InitialUSDCentsPerBitcoinExchangeRate
   924  	InitialUSDCentsPerBitcoinExchangeRate = uint64(1350000)
   925  	defer func() {
   926  		InitialUSDCentsPerBitcoinExchangeRate = oldInitialUSDCentsPerBitcoinExchangeRate
   927  	}()
   928  
   929  	paramsTmp := DeSoTestnetParams
   930  	paramsTmp.DeSoNanosPurchasedAtGenesis = 0
   931  	chain, params, db := NewLowDifficultyBlockchainWithParams(&paramsTmp)
   932  	mempool, miner := NewTestMiner(t, chain, params, true /*isSender*/)
   933  
   934  	// Read in the test Bitcoin blocks and headers.
   935  	bitcoinBlocks, bitcoinHeaders, bitcoinHeaderHeights := _readBitcoinExchangeTestData(t)
   936  
   937  	// Extract BitcoinExchange transactions from the test Bitcoin blocks.
   938  	bitcoinExchangeTxns := []*MsgDeSoTxn{}
   939  	for _, block := range bitcoinBlocks {
   940  		currentBurnTxns, err :=
   941  			ExtractBitcoinExchangeTransactionsFromBitcoinBlock(
   942  				block, BitcoinTestnetBurnAddress, params)
   943  		require.NoError(err)
   944  		bitcoinExchangeTxns = append(bitcoinExchangeTxns, currentBurnTxns...)
   945  	}
   946  
   947  	// Verify that Bitcoin burn transactions are properly extracted from Bitcoin blocks
   948  	// and the their burn amounts are computed correctly.
   949  	require.Equal(9, len(bitcoinExchangeTxns))
   950  	expectedBitcoinBurnAmounts := []int64{
   951  		10000,
   952  		12500,
   953  		41000,
   954  		20000,
   955  		15000,
   956  		50000,
   957  		15000,
   958  		20482,
   959  		2490,
   960  	}
   961  	rateUpdateIndex := 4
   962  	expectedDeSoNanosMinted := []int64{
   963  		2700510570,
   964  		3375631103,
   965  		11072014581,
   966  		5400951887,
   967  		// We double the exchange rate at this point. Include a zero
   968  		// here to account for this.
   969  		0,
   970  		8103578296,
   971  		27011598923,
   972  		8103381058,
   973  		11064823217,
   974  		1345146534,
   975  	}
   976  	blockIndexesForTransactions := []int{1, 1, 1, 1, 1, 1, 1, 3, 3}
   977  	for ii, bitcoinExchangeTxn := range bitcoinExchangeTxns {
   978  		txnMeta := bitcoinExchangeTxn.TxnMeta.(*BitcoinExchangeMetadata)
   979  		burnTxn := txnMeta.BitcoinTransaction
   980  		burnOutput, err := _computeBitcoinBurnOutput(
   981  			burnTxn, BitcoinTestnetBurnAddress, params.BitcoinBtcdParams)
   982  		require.NoError(err)
   983  		assert.Equalf(expectedBitcoinBurnAmounts[ii], burnOutput,
   984  			"Bitcoin burn amount for burn txn %d doesn't line up with "+
   985  				"what is expected", ii)
   986  
   987  		// Sanity-check that the Bitcoin block hashes line up.
   988  		blockIndex := blockIndexesForTransactions[ii]
   989  		blockForTxn := bitcoinBlocks[blockIndex]
   990  		{
   991  			hash1 := (BlockHash)(blockForTxn.BlockHash())
   992  			hash2 := *txnMeta.BitcoinBlockHash
   993  			require.Equalf(
   994  				hash1, hash2,
   995  				"Bitcoin block hash for txn does not line up with block hash: %v %v %d", &hash1, &hash2, ii)
   996  		}
   997  
   998  		// Sanity-check that the Merkle root lines up with what's in the block.
   999  		{
  1000  			hash1 := (BlockHash)(blockForTxn.Header.MerkleRoot)
  1001  			hash2 := *txnMeta.BitcoinMerkleRoot
  1002  			require.Equalf(
  1003  				hash1, hash2,
  1004  				"Bitcoin merkle root for txn does not line up with block hash: %v %v %d", &hash1, &hash2, ii)
  1005  		}
  1006  
  1007  		// Verify that the merkle proof checks out.
  1008  		{
  1009  			txHash := ((BlockHash)(txnMeta.BitcoinTransaction.TxHash()))
  1010  			merkleProofIsValid := merkletree.VerifyProof(
  1011  				txHash[:], txnMeta.BitcoinMerkleProof, txnMeta.BitcoinMerkleRoot[:])
  1012  			require.Truef(
  1013  				merkleProofIsValid, "Problem verifying merkle proof for burn txn %d", ii)
  1014  		}
  1015  
  1016  		// Verify that using the wrong Merkle root doesn't work.
  1017  		{
  1018  			badBlock := bitcoinBlocks[blockIndex-1]
  1019  			badMerkleRoot := badBlock.Header.MerkleRoot[:]
  1020  			txHash := ((BlockHash)(txnMeta.BitcoinTransaction.TxHash()))
  1021  			merkleProofIsValid := merkletree.VerifyProof(
  1022  				txHash[:], txnMeta.BitcoinMerkleProof, badMerkleRoot)
  1023  			require.Falsef(
  1024  				merkleProofIsValid, "Bad Merkle root was actually verified for burn txn %d", ii)
  1025  		}
  1026  
  1027  		// Verify that serializing and deserializing work for this transaction.
  1028  		bb, err := bitcoinExchangeTxn.ToBytes(false /*preSignature*/)
  1029  		require.NoError(err)
  1030  		parsedBitcoinExchangeTxn := &MsgDeSoTxn{}
  1031  		parsedBitcoinExchangeTxn.FromBytes(bb)
  1032  		require.Equal(bitcoinExchangeTxn, parsedBitcoinExchangeTxn)
  1033  	}
  1034  
  1035  	// Find the header in our header list corresponding to the first test block,
  1036  	// which contains the first Bitcoin
  1037  	firstBitcoinBurnBlock := bitcoinBlocks[1]
  1038  	firstBitcoinBurnBlockHash := firstBitcoinBurnBlock.BlockHash()
  1039  	headerIndexOfFirstBurn := -1
  1040  	for headerIndex := range bitcoinHeaders {
  1041  		if firstBitcoinBurnBlockHash == bitcoinHeaders[headerIndex].BlockHash() {
  1042  			headerIndexOfFirstBurn = headerIndex
  1043  			break
  1044  		}
  1045  	}
  1046  	require.Greater(headerIndexOfFirstBurn, 0)
  1047  
  1048  	// Create a Bitcoinmanager that is current whose tip corresponds to the block
  1049  	// just before the block containing the first Bitcoin burn transaction.
  1050  	minBurnBlocks := uint32(2)
  1051  	startHeaderIndex := 0
  1052  	paramsCopy := GetTestParamsCopy(bitcoinHeaders[startHeaderIndex],
  1053  		bitcoinHeaderHeights[startHeaderIndex], params, minBurnBlocks)
  1054  
  1055  	// Update some of the params to make them reflect what we've hacked into
  1056  	// the bitcoinManager.
  1057  	paramsCopy.BitcoinBurnAddress = BitcoinTestnetBurnAddress
  1058  	chain.params = paramsCopy
  1059  	// Reset the pool to give the mempool access to the new BitcoinManager object.
  1060  	mempool.resetPool(NewDeSoMempool(chain, 0, /* rateLimitFeeRateNanosPerKB */
  1061  		0, /* minFeeRateNanosPerKB */
  1062  		"" /*blockCypherAPIKey*/, false,
  1063  		"" /*dataDir*/, ""))
  1064  
  1065  	//// Validating the first Bitcoin burn transaction via a UtxoView should
  1066  	//// fail because the block corresponding to it is not yet in the BitcoinManager.
  1067  	burnTxn1 := bitcoinExchangeTxns[0]
  1068  	burnTxn1Size := getTxnSize(*burnTxn1)
  1069  	txHash1 := burnTxn1.Hash()
  1070  	burnTxn2 := bitcoinExchangeTxns[1]
  1071  
  1072  	// The user we just applied this transaction for should have a balance now.
  1073  	pkBytes1, _ := hex.DecodeString(BitcoinTestnetPub1)
  1074  
  1075  	// Applying the full transaction with its merkle proof to the mempool should
  1076  	// replace the existing "unmined" version that we added previously.
  1077  	{
  1078  		mempoolTxs, err := mempool.processTransaction(
  1079  			burnTxn1, true /*allowUnconnectedTxn*/, true /*rateLimit*/, 0 /*peerID*/, true /*verifySignatures*/)
  1080  		require.NoError(err)
  1081  		require.Equal(1, len(mempoolTxs))
  1082  		require.Equal(1, len(mempool.poolMap))
  1083  		mempoolTxRet := mempool.poolMap[*mempoolTxs[0].Hash]
  1084  		require.Equal(
  1085  			mempoolTxRet.Tx.TxnMeta.(*BitcoinExchangeMetadata),
  1086  			burnTxn1.TxnMeta.(*BitcoinExchangeMetadata))
  1087  	}
  1088  
  1089  	// Applying the full txns a second time should fail.
  1090  	{
  1091  		mempoolTxs, err := mempool.processTransaction(
  1092  			burnTxn1, true /*allowUnconnectedTxn*/, true /*rateLimit*/, 0 /*peerID*/, true /*verifySignatures*/)
  1093  		require.Error(err)
  1094  		require.Equal(0, len(mempoolTxs))
  1095  		require.Equal(1, len(mempool.poolMap))
  1096  		mempoolTxRet := mempool.poolMap[*burnTxn1.Hash()]
  1097  		require.Equal(
  1098  			mempoolTxRet.Tx.TxnMeta.(*BitcoinExchangeMetadata),
  1099  			burnTxn1.TxnMeta.(*BitcoinExchangeMetadata))
  1100  	}
  1101  
  1102  	// According to the mempool, the balance of the user whose public key created
  1103  	// the Bitcoin burn transaction should now have some DeSo.
  1104  	pkBytes2, _ := hex.DecodeString(BitcoinTestnetPub2)
  1105  	pkBytes3, _ := hex.DecodeString(BitcoinTestnetPub3)
  1106  	{
  1107  		utxoEntries, err := chain.GetSpendableUtxosForPublicKey(pkBytes1, mempool, nil)
  1108  		require.NoError(err)
  1109  
  1110  		require.Equal(1, len(utxoEntries))
  1111  		assert.Equal(int64(2697810060), int64(utxoEntries[0].AmountNanos))
  1112  	}
  1113  
  1114  	// The mempool should be able to process a burn transaction directly.
  1115  	{
  1116  		mempoolTxsAdded, err := mempool.processTransaction(
  1117  			burnTxn2, true /*allowUnconnectedTxn*/, true /*rateLimit*/, 0, /*peerID*/
  1118  			true /*verifySignatures*/)
  1119  		require.NoError(err)
  1120  		require.Equal(1, len(mempoolTxsAdded))
  1121  		require.Equal(2, len(mempool.poolMap))
  1122  		mempoolTxRet := mempool.poolMap[*mempoolTxsAdded[0].Hash]
  1123  		require.Equal(
  1124  			mempoolTxRet.Tx.TxnMeta.(*BitcoinExchangeMetadata),
  1125  			burnTxn2.TxnMeta.(*BitcoinExchangeMetadata))
  1126  	}
  1127  
  1128  	// According to the mempool, the balances should have updated.
  1129  	{
  1130  		utxoEntries, err := chain.GetSpendableUtxosForPublicKey(pkBytes3, mempool, nil)
  1131  		require.NoError(err)
  1132  
  1133  		require.Equal(1, len(utxoEntries))
  1134  		assert.Equal(int64(3372255472), int64(utxoEntries[0].AmountNanos))
  1135  	}
  1136  
  1137  	// If the mempool is not consulted, the balances should be zero.
  1138  	{
  1139  		utxoEntries, err := chain.GetSpendableUtxosForPublicKey(pkBytes3, nil, nil)
  1140  		require.NoError(err)
  1141  		require.Equal(0, len(utxoEntries))
  1142  	}
  1143  
  1144  	// Verify that adding the transaction to the UtxoView fails because there is
  1145  	// not enough work on the burn block yet.
  1146  	{
  1147  		utxoView, _ := NewUtxoView(db, paramsCopy, nil)
  1148  		blockHeight := chain.blockTip().Height + 1
  1149  		utxoView.ConnectTransaction(burnTxn1, txHash1, burnTxn1Size, blockHeight, true /*verifySignature*/, false /*ignoreUtxos*/)
  1150  	}
  1151  
  1152  	{
  1153  		utxoView, _ := NewUtxoView(db, paramsCopy, nil)
  1154  		blockHeight := chain.blockTip().Height + 1
  1155  		utxoView.ConnectTransaction(burnTxn1, txHash1, burnTxn1Size, blockHeight, true /*verifySignature*/, false /*ignoreUtxos*/)
  1156  	}
  1157  
  1158  	// The transaction should pass now
  1159  	{
  1160  		utxoView, _ := NewUtxoView(db, paramsCopy, nil)
  1161  		blockHeight := chain.blockTip().Height + 1
  1162  		_, _, _, _, err :=
  1163  			utxoView.ConnectTransaction(burnTxn1, txHash1, burnTxn1Size, blockHeight, true /*verifySignature*/, false /*ignoreUtxos*/)
  1164  		require.NoError(err)
  1165  	}
  1166  
  1167  	// Make the moneyPkString the paramUpdater so they can update the exchange rate.
  1168  	params.ParamUpdaterPublicKeys = make(map[PkMapKey]bool)
  1169  	params.ParamUpdaterPublicKeys[MakePkMapKey(MustBase58CheckDecode(moneyPkString))] = true
  1170  	paramsCopy.ParamUpdaterPublicKeys = params.ParamUpdaterPublicKeys
  1171  
  1172  	// Applying all the txns to the UtxoView should work. Include a rate update
  1173  	// in the middle.
  1174  	utxoOpsList := [][]*UtxoOperation{}
  1175  	{
  1176  		utxoView, err := NewUtxoView(db, paramsCopy, nil)
  1177  		require.NoError(err)
  1178  
  1179  		// Add a placeholder where the rate update is going to be
  1180  		fff := append([]*MsgDeSoTxn{}, bitcoinExchangeTxns[:rateUpdateIndex]...)
  1181  		fff = append(fff, nil)
  1182  		fff = append(fff, bitcoinExchangeTxns[rateUpdateIndex:]...)
  1183  		bitcoinExchangeTxns = fff
  1184  
  1185  		for ii := range bitcoinExchangeTxns {
  1186  			fmt.Println("Processing BitcoinExchange: ", ii)
  1187  
  1188  			// When we hit the rate update, populate the placeholder.
  1189  			if ii == rateUpdateIndex {
  1190  				newUSDCentsPerBitcoin := int64(27000 * 100)
  1191  				_, rateUpdateTxn, _, err := _updateGlobalParamsEntry(t, chain, db, params, 10,
  1192  					moneyPkString, moneyPrivString, newUSDCentsPerBitcoin, 0, 0, 0, -1, false)
  1193  
  1194  				require.NoError(err)
  1195  
  1196  				bitcoinExchangeTxns[ii] = rateUpdateTxn
  1197  				burnTxn := bitcoinExchangeTxns[ii]
  1198  				burnTxnSize := getTxnSize(*burnTxn)
  1199  				blockHeight := chain.blockTip().Height + 1
  1200  				utxoOps, totalInput, totalOutput, fees, err :=
  1201  					utxoView.ConnectTransaction(
  1202  						burnTxn, burnTxn.Hash(), burnTxnSize, blockHeight, true /*verifySignature*/, false /*ignoreUtxos*/)
  1203  				_, _, _ = totalInput, totalOutput, fees
  1204  				require.NoError(err)
  1205  				utxoOpsList = append(utxoOpsList, utxoOps)
  1206  				continue
  1207  			}
  1208  
  1209  			burnTxn := bitcoinExchangeTxns[ii]
  1210  			burnTxnSize := getTxnSize(*burnTxn)
  1211  			blockHeight := chain.blockTip().Height + 1
  1212  			utxoOps, totalInput, totalOutput, fees, err :=
  1213  				utxoView.ConnectTransaction(
  1214  					burnTxn, burnTxn.Hash(), burnTxnSize, blockHeight, true /*verifySignature*/, false /*ignoreUtxos*/)
  1215  			require.NoError(err)
  1216  
  1217  			require.Equal(2, len(utxoOps))
  1218  			//fmt.Println(int64(totalInput), ",")
  1219  			assert.Equal(expectedDeSoNanosMinted[ii], int64(totalInput))
  1220  			assert.Equal(expectedDeSoNanosMinted[ii]*int64(paramsCopy.BitcoinExchangeFeeBasisPoints)/10000, int64(fees))
  1221  			assert.Equal(int64(fees), int64(totalInput-totalOutput))
  1222  
  1223  			_, _, _ = ii, totalOutput, fees
  1224  			utxoOpsList = append(utxoOpsList, utxoOps)
  1225  		}
  1226  
  1227  		// Flushing the UtxoView should work.
  1228  		require.NoError(utxoView.FlushToDb())
  1229  	}
  1230  
  1231  	// The balances according to the db after the flush should be correct.
  1232  	{
  1233  		utxoEntries, err := chain.GetSpendableUtxosForPublicKey(pkBytes1, nil, nil)
  1234  		require.NoError(err)
  1235  		require.Equal(5, len(utxoEntries))
  1236  		totalBalance := uint64(0)
  1237  		for _, utxoEntry := range utxoEntries {
  1238  			totalBalance += utxoEntry.AmountNanos
  1239  		}
  1240  		// Note the 10bp fee.
  1241  		assert.Equal(int64(47475508103), int64(totalBalance))
  1242  	}
  1243  	{
  1244  		utxoEntries, err := chain.GetSpendableUtxosForPublicKey(pkBytes2, nil, nil)
  1245  		require.NoError(err)
  1246  		require.Equal(1, len(utxoEntries))
  1247  		// Note the 10bp fee.
  1248  		assert.Equal(int64(8095277677), int64(utxoEntries[0].AmountNanos))
  1249  	}
  1250  	{
  1251  		utxoEntries, err := chain.GetSpendableUtxosForPublicKey(pkBytes3, nil, nil)
  1252  		require.NoError(err)
  1253  		require.Equal(3, len(utxoEntries))
  1254  		totalBalance := uint64(0)
  1255  		for _, utxoEntry := range utxoEntries {
  1256  			totalBalance += utxoEntry.AmountNanos
  1257  		}
  1258  		// Note the 10bp fee.
  1259  		assert.Equal(int64(22528672757), int64(totalBalance))
  1260  	}
  1261  
  1262  	// Spending from the outputs created by a burn should work.
  1263  	desoPub1 := Base58CheckEncode(pkBytes1, false /*isPrivate*/, paramsCopy)
  1264  	priv1, _ := _privStringToKeys(t, BitcoinTestnetPriv1)
  1265  	desoPriv1 := Base58CheckEncode(priv1.Serialize(), true /*isPrivate*/, paramsCopy)
  1266  	desoPub2 := Base58CheckEncode(pkBytes2, false /*isPrivate*/, paramsCopy)
  1267  	priv2, _ := _privStringToKeys(t, BitcoinTestnetPriv2)
  1268  	desoPriv2 := Base58CheckEncode(priv2.Serialize(), true /*isPrivate*/, paramsCopy)
  1269  	desoPub3 := Base58CheckEncode(pkBytes3, false /*isPrivate*/, paramsCopy)
  1270  	priv3, _ := _privStringToKeys(t, BitcoinTestnetPriv3)
  1271  	desoPriv3 := Base58CheckEncode(priv3.Serialize(), true /*isPrivate*/, paramsCopy)
  1272  	{
  1273  		currentOps, currentTxn, _ := _doBasicTransferWithViewFlush(
  1274  			t, chain, db, params, desoPub1, desoPub2,
  1275  			desoPriv1, 100000*100000 /*amount to send*/, 11 /*feerate*/)
  1276  
  1277  		utxoOpsList = append(utxoOpsList, currentOps)
  1278  		bitcoinExchangeTxns = append(bitcoinExchangeTxns, currentTxn)
  1279  	}
  1280  	{
  1281  		currentOps, currentTxn, _ := _doBasicTransferWithViewFlush(
  1282  			t, chain, db, params, desoPub3, desoPub1,
  1283  			desoPriv3, 60000*100000 /*amount to send*/, 11 /*feerate*/)
  1284  
  1285  		utxoOpsList = append(utxoOpsList, currentOps)
  1286  		bitcoinExchangeTxns = append(bitcoinExchangeTxns, currentTxn)
  1287  	}
  1288  	{
  1289  		currentOps, currentTxn, _ := _doBasicTransferWithViewFlush(
  1290  			t, chain, db, params, desoPub2, desoPub1,
  1291  			desoPriv2, 60000*100000 /*amount to send*/, 11 /*feerate*/)
  1292  
  1293  		utxoOpsList = append(utxoOpsList, currentOps)
  1294  		bitcoinExchangeTxns = append(bitcoinExchangeTxns, currentTxn)
  1295  	}
  1296  
  1297  	// The balances according to the db after the spends above should be correct.
  1298  	{
  1299  		utxoEntries, err := chain.GetSpendableUtxosForPublicKey(pkBytes1, nil, nil)
  1300  		require.NoError(err)
  1301  		totalBalance := uint64(0)
  1302  		for _, utxoEntry := range utxoEntries {
  1303  			totalBalance += utxoEntry.AmountNanos
  1304  		}
  1305  		assert.Equal(int64(49455017177), int64(totalBalance))
  1306  	}
  1307  	{
  1308  		utxoEntries, err := chain.GetSpendableUtxosForPublicKey(pkBytes2, nil, nil)
  1309  		require.NoError(err)
  1310  		assert.Equal(int64(2087182397), int64(utxoEntries[0].AmountNanos))
  1311  	}
  1312  	{
  1313  		utxoEntries, err := chain.GetSpendableUtxosForPublicKey(pkBytes3, nil, nil)
  1314  		require.NoError(err)
  1315  		totalBalance := uint64(0)
  1316  		for _, utxoEntry := range utxoEntries {
  1317  			totalBalance += utxoEntry.AmountNanos
  1318  		}
  1319  		assert.Equal(int64(16517205024), int64(totalBalance))
  1320  	}
  1321  
  1322  	{
  1323  		// Rolling back all the transactions should work.
  1324  		utxoView, err := NewUtxoView(db, paramsCopy, nil)
  1325  		require.NoError(err)
  1326  		for ii := range bitcoinExchangeTxns {
  1327  			index := len(bitcoinExchangeTxns) - 1 - ii
  1328  			burnTxn := bitcoinExchangeTxns[index]
  1329  			blockHeight := chain.blockTip().Height + 1
  1330  			err := utxoView.DisconnectTransaction(burnTxn, burnTxn.Hash(), utxoOpsList[index], blockHeight)
  1331  			require.NoErrorf(err, "Transaction index: %v", index)
  1332  		}
  1333  
  1334  		// Flushing the UtxoView back to the db after rolling back the
  1335  		require.NoError(utxoView.FlushToDb())
  1336  	}
  1337  
  1338  	// The balances according to the db after rolling back and flushing everything
  1339  	// should be zero.
  1340  	{
  1341  		utxoEntries, err := chain.GetSpendableUtxosForPublicKey(pkBytes1, nil, nil)
  1342  		require.NoError(err)
  1343  		require.Equal(0, len(utxoEntries))
  1344  	}
  1345  	{
  1346  		utxoEntries, err := chain.GetSpendableUtxosForPublicKey(pkBytes2, nil, nil)
  1347  		require.NoError(err)
  1348  		require.Equal(0, len(utxoEntries))
  1349  	}
  1350  	{
  1351  		utxoEntries, err := chain.GetSpendableUtxosForPublicKey(pkBytes3, nil, nil)
  1352  		require.NoError(err)
  1353  		require.Equal(0, len(utxoEntries))
  1354  	}
  1355  
  1356  	// Re-applying all the transactions to the view and rolling back without
  1357  	// flushing should be fine.
  1358  	utxoOpsList = [][]*UtxoOperation{}
  1359  	{
  1360  		utxoView, err := NewUtxoView(db, paramsCopy, nil)
  1361  		require.NoError(err)
  1362  		for ii, burnTxn := range bitcoinExchangeTxns {
  1363  			blockHeight := chain.blockTip().Height + 1
  1364  			burnTxnSize := getTxnSize(*burnTxn)
  1365  			utxoOps, totalInput, totalOutput, fees, err :=
  1366  				utxoView.ConnectTransaction(burnTxn, burnTxn.Hash(), burnTxnSize, blockHeight, true /*verifySignature*/, false /*ignoreUtxos*/)
  1367  			require.NoError(err)
  1368  
  1369  			if ii < len(expectedBitcoinBurnAmounts) {
  1370  				if ii != rateUpdateIndex {
  1371  					require.Equal(2, len(utxoOps))
  1372  					assert.Equal(int64(totalInput), expectedDeSoNanosMinted[ii])
  1373  					assert.Equal(int64(fees), expectedDeSoNanosMinted[ii]*int64(paramsCopy.BitcoinExchangeFeeBasisPoints)/10000)
  1374  					assert.Equal(int64(fees), int64(totalInput-totalOutput))
  1375  				}
  1376  			}
  1377  
  1378  			utxoOpsList = append(utxoOpsList, utxoOps)
  1379  		}
  1380  
  1381  		for ii := range bitcoinExchangeTxns {
  1382  			index := len(bitcoinExchangeTxns) - 1 - ii
  1383  			burnTxn := bitcoinExchangeTxns[index]
  1384  			blockHeight := chain.blockTip().Height + 1
  1385  			err := utxoView.DisconnectTransaction(burnTxn, burnTxn.Hash(), utxoOpsList[index], blockHeight)
  1386  			require.NoError(err)
  1387  		}
  1388  
  1389  		// Flushing the view after applying and rolling back should work.
  1390  		require.NoError(utxoView.FlushToDb())
  1391  	}
  1392  
  1393  	// The balances according to the db after applying and unapplying all the
  1394  	// transactions to a view with a flush at the end should be zero.
  1395  	{
  1396  		utxoEntries, err := chain.GetSpendableUtxosForPublicKey(pkBytes1, nil, nil)
  1397  		require.NoError(err)
  1398  		require.Equal(0, len(utxoEntries))
  1399  	}
  1400  	{
  1401  		utxoEntries, err := chain.GetSpendableUtxosForPublicKey(pkBytes2, nil, nil)
  1402  		require.NoError(err)
  1403  		require.Equal(0, len(utxoEntries))
  1404  	}
  1405  	{
  1406  		utxoEntries, err := chain.GetSpendableUtxosForPublicKey(pkBytes3, nil, nil)
  1407  		require.NoError(err)
  1408  		require.Equal(0, len(utxoEntries))
  1409  	}
  1410  
  1411  	// Running all the transactions through the mempool should work and result
  1412  	// in all of them being added.
  1413  	{
  1414  		for _, burnTxn := range bitcoinExchangeTxns {
  1415  			// We have to remove the transactions first.
  1416  			mempool.inefficientRemoveTransaction(burnTxn)
  1417  		}
  1418  		for ii, burnTxn := range bitcoinExchangeTxns {
  1419  			require.Equal(ii, len(mempool.poolMap))
  1420  			mempoolTxsAdded, err := mempool.processTransaction(
  1421  				burnTxn, true /*allowUnconnectedTxn*/, true /*rateLimit*/, 0, /*peerID*/
  1422  				true /*verifySignatures*/)
  1423  			require.NoErrorf(err, "on index: %v", ii)
  1424  			require.Equal(1, len(mempoolTxsAdded))
  1425  		}
  1426  	}
  1427  
  1428  	// Test that the mempool can be backed up properly by dumping them and then
  1429  	// reloading them.
  1430  	_dumpAndLoadMempool(mempool)
  1431  
  1432  	// The balances according to the mempool after applying all the transactions
  1433  	// should be correct.
  1434  	{
  1435  		utxoEntries, err := chain.GetSpendableUtxosForPublicKey(pkBytes1, mempool, nil)
  1436  		require.NoError(err)
  1437  		totalBalance := uint64(0)
  1438  		for _, utxoEntry := range utxoEntries {
  1439  			totalBalance += utxoEntry.AmountNanos
  1440  		}
  1441  		assert.Equal(int64(49455017177), int64(totalBalance))
  1442  	}
  1443  	{
  1444  		utxoEntries, err := chain.GetSpendableUtxosForPublicKey(pkBytes2, mempool, nil)
  1445  		require.NoError(err)
  1446  		assert.Equal(int64(2087182397), int64(utxoEntries[0].AmountNanos))
  1447  	}
  1448  	{
  1449  		utxoEntries, err := chain.GetSpendableUtxosForPublicKey(pkBytes3, mempool, nil)
  1450  		require.NoError(err)
  1451  		totalBalance := uint64(0)
  1452  		for _, utxoEntry := range utxoEntries {
  1453  			totalBalance += utxoEntry.AmountNanos
  1454  		}
  1455  		assert.Equal(int64(16517205024), int64(totalBalance))
  1456  	}
  1457  
  1458  	// Remove all the transactions from the mempool.
  1459  	for _, burnTxn := range bitcoinExchangeTxns {
  1460  		mempool.inefficientRemoveTransaction(burnTxn)
  1461  	}
  1462  
  1463  	// Check that removals hit the database properly by calling a dump and
  1464  	// then reloading the db state into the view.
  1465  	_dumpAndLoadMempool(mempool)
  1466  
  1467  	// The balances should be zero after removing transactions from the mempool.
  1468  	{
  1469  		utxoEntries, err := chain.GetSpendableUtxosForPublicKey(pkBytes1, mempool, nil)
  1470  		require.NoError(err)
  1471  		require.Equal(0, len(utxoEntries))
  1472  	}
  1473  	{
  1474  		utxoEntries, err := chain.GetSpendableUtxosForPublicKey(pkBytes2, mempool, nil)
  1475  		require.NoError(err)
  1476  		require.Equal(0, len(utxoEntries))
  1477  	}
  1478  	{
  1479  		utxoEntries, err := chain.GetSpendableUtxosForPublicKey(pkBytes3, mempool, nil)
  1480  		require.NoError(err)
  1481  		require.Equal(0, len(utxoEntries))
  1482  	}
  1483  
  1484  	// Re-add all of the transactions to the mempool so we can mine them into a block.
  1485  	{
  1486  		for _, burnTxn := range bitcoinExchangeTxns {
  1487  			mempoolTxsAdded, err := mempool.processTransaction(
  1488  				burnTxn, true /*allowUnconnectedTxn*/, true /*rateLimit*/, 0, /*peerID*/
  1489  				true /*verifySignatures*/)
  1490  			require.NoError(err)
  1491  			require.Equal(1, len(mempoolTxsAdded))
  1492  			//require.Equal(0, len(mempool.immatureBitcoinTxns))
  1493  		}
  1494  	}
  1495  
  1496  	// Check the db one more time after adding back all the txns.
  1497  	_dumpAndLoadMempool(mempool)
  1498  
  1499  	miner.params = paramsCopy
  1500  	miner.BlockProducer.params = paramsCopy
  1501  
  1502  	// All the txns should be in the mempool already but only some of them have enough
  1503  	// burn work to satisfy the miner. Note we need to mine two blocks since the first
  1504  	// one just makes the DeSo chain time-current.
  1505  	finalBlock1, err := miner.MineAndProcessSingleBlock(0 /*threadIndex*/, mempool)
  1506  	require.NoError(err)
  1507  	_ = finalBlock1
  1508  	// Check the mempool dumps and loads from the db properly each time
  1509  	_dumpAndLoadMempool(mempool)
  1510  
  1511  	finalBlock2, err := miner.MineAndProcessSingleBlock(0 /*threadIndex*/, mempool)
  1512  	require.NoError(err)
  1513  	_dumpAndLoadMempool(mempool)
  1514  
  1515  	finalBlock3, err := miner.MineAndProcessSingleBlock(0 /*threadIndex*/, mempool)
  1516  	require.NoError(err)
  1517  	_dumpAndLoadMempool(mempool)
  1518  
  1519  	finalBlock4, err := miner.MineAndProcessSingleBlock(0 /*threadIndex*/, mempool)
  1520  	require.NoError(err)
  1521  	_dumpAndLoadMempool(mempool)
  1522  
  1523  	// Add one for the block reward.
  1524  	assert.Equal(len(finalBlock1.Txns), 1)
  1525  	// The first block should only have some of the Bitcoin txns since
  1526  	// the MinerBitcoinBurnWorkBlocks is higher than the regular burn work.
  1527  	assert.Equal(len(finalBlock2.Txns), 14)
  1528  	assert.Equal(len(finalBlock3.Txns), 1)
  1529  	require.Equal(len(finalBlock4.Txns), 1)
  1530  
  1531  	// The balances after mining the block should line up.
  1532  	{
  1533  		utxoEntries, err := chain.GetSpendableUtxosForPublicKey(pkBytes1, nil, nil)
  1534  		require.NoError(err)
  1535  		totalBalance := uint64(0)
  1536  		for _, utxoEntry := range utxoEntries {
  1537  			totalBalance += utxoEntry.AmountNanos
  1538  		}
  1539  		assert.Equal(int64(49455017177), int64(totalBalance))
  1540  	}
  1541  	{
  1542  		utxoEntries, err := chain.GetSpendableUtxosForPublicKey(pkBytes2, nil, nil)
  1543  		require.NoError(err)
  1544  		assert.Equal(int64(2087182397), int64(utxoEntries[0].AmountNanos))
  1545  	}
  1546  	{
  1547  		utxoEntries, err := chain.GetSpendableUtxosForPublicKey(pkBytes3, nil, nil)
  1548  		require.NoError(err)
  1549  		totalBalance := uint64(0)
  1550  		for _, utxoEntry := range utxoEntries {
  1551  			totalBalance += utxoEntry.AmountNanos
  1552  		}
  1553  		assert.Equal(int64(16517205024), int64(totalBalance))
  1554  	}
  1555  
  1556  	// Roll back the blocks and make sure we don't hit any errors.
  1557  	{
  1558  		utxoView, err := NewUtxoView(db, paramsCopy, nil)
  1559  		require.NoError(err)
  1560  
  1561  		{
  1562  			// Fetch the utxo operations for the block we're detaching. We need these
  1563  			// in order to be able to detach the block.
  1564  			hash, err := finalBlock4.Header.Hash()
  1565  			require.NoError(err)
  1566  			utxoOps, err := GetUtxoOperationsForBlock(db, hash)
  1567  			require.NoError(err)
  1568  
  1569  			// Compute the hashes for all the transactions.
  1570  			txHashes, err := ComputeTransactionHashes(finalBlock4.Txns)
  1571  			require.NoError(err)
  1572  			require.NoError(utxoView.DisconnectBlock(finalBlock4, txHashes, utxoOps))
  1573  		}
  1574  		{
  1575  			// Fetch the utxo operations for the block we're detaching. We need these
  1576  			// in order to be able to detach the block.
  1577  			hash, err := finalBlock3.Header.Hash()
  1578  			require.NoError(err)
  1579  			utxoOps, err := GetUtxoOperationsForBlock(db, hash)
  1580  			require.NoError(err)
  1581  
  1582  			// Compute the hashes for all the transactions.
  1583  			txHashes, err := ComputeTransactionHashes(finalBlock3.Txns)
  1584  			require.NoError(err)
  1585  			require.NoError(utxoView.DisconnectBlock(finalBlock3, txHashes, utxoOps))
  1586  		}
  1587  		{
  1588  			// Fetch the utxo operations for the block we're detaching. We need these
  1589  			// in order to be able to detach the block.
  1590  			hash, err := finalBlock2.Header.Hash()
  1591  			require.NoError(err)
  1592  			utxoOps, err := GetUtxoOperationsForBlock(db, hash)
  1593  			require.NoError(err)
  1594  
  1595  			// Compute the hashes for all the transactions.
  1596  			txHashes, err := ComputeTransactionHashes(finalBlock2.Txns)
  1597  			require.NoError(err)
  1598  			require.NoError(utxoView.DisconnectBlock(finalBlock2, txHashes, utxoOps))
  1599  		}
  1600  		{
  1601  			// Fetch the utxo operations for the block we're detaching. We need these
  1602  			// in order to be able to detach the block.
  1603  			hash, err := finalBlock1.Header.Hash()
  1604  			require.NoError(err)
  1605  			utxoOps, err := GetUtxoOperationsForBlock(db, hash)
  1606  			require.NoError(err)
  1607  
  1608  			// Compute the hashes for all the transactions.
  1609  			txHashes, err := ComputeTransactionHashes(finalBlock1.Txns)
  1610  			require.NoError(err)
  1611  			require.NoError(utxoView.DisconnectBlock(finalBlock1, txHashes, utxoOps))
  1612  		}
  1613  
  1614  		// Flushing the view after applying and rolling back should work.
  1615  		require.NoError(utxoView.FlushToDb())
  1616  	}
  1617  
  1618  	// The balances according to the db after applying and unapplying all the
  1619  	// transactions to a view with a flush at the end should be zero.
  1620  	{
  1621  		utxoEntries, err := chain.GetSpendableUtxosForPublicKey(pkBytes1, nil, nil)
  1622  		require.NoError(err)
  1623  		require.Equal(0, len(utxoEntries))
  1624  	}
  1625  	{
  1626  		utxoEntries, err := chain.GetSpendableUtxosForPublicKey(pkBytes2, nil, nil)
  1627  		require.NoError(err)
  1628  		require.Equal(0, len(utxoEntries))
  1629  	}
  1630  	{
  1631  		utxoEntries, err := chain.GetSpendableUtxosForPublicKey(pkBytes3, nil, nil)
  1632  		require.NoError(err)
  1633  		require.Equal(0, len(utxoEntries))
  1634  	}
  1635  
  1636  	_, _, _, _, _, _ = db, mempool, miner, bitcoinBlocks, bitcoinHeaders, bitcoinHeaderHeights
  1637  }
  1638  
  1639  func TestSpendOffOfUnminedTxnsBitcoinExchange(t *testing.T) {
  1640  	assert := assert.New(t)
  1641  	require := require.New(t)
  1642  	_ = assert
  1643  	_ = require
  1644  
  1645  	oldInitialUSDCentsPerBitcoinExchangeRate := InitialUSDCentsPerBitcoinExchangeRate
  1646  	InitialUSDCentsPerBitcoinExchangeRate = 1350000
  1647  	defer func() {
  1648  		InitialUSDCentsPerBitcoinExchangeRate = oldInitialUSDCentsPerBitcoinExchangeRate
  1649  	}()
  1650  
  1651  	paramsTmp := DeSoTestnetParams
  1652  	paramsTmp.DeSoNanosPurchasedAtGenesis = 0
  1653  	chain, params, db := NewLowDifficultyBlockchainWithParams(&paramsTmp)
  1654  	mempool, miner := NewTestMiner(t, chain, params, true /*isSender*/)
  1655  
  1656  	// Read in the test Bitcoin blocks and headers.
  1657  	bitcoinBlocks, bitcoinHeaders, bitcoinHeaderHeights := _readBitcoinExchangeTestData(t)
  1658  
  1659  	// Extract BitcoinExchange transactions from the test Bitcoin blocks.
  1660  	bitcoinExchangeTxns := []*MsgDeSoTxn{}
  1661  	for _, block := range bitcoinBlocks {
  1662  		currentBurnTxns, err :=
  1663  			ExtractBitcoinExchangeTransactionsFromBitcoinBlock(
  1664  				block, BitcoinTestnetBurnAddress, params)
  1665  		require.NoError(err)
  1666  		bitcoinExchangeTxns = append(bitcoinExchangeTxns, currentBurnTxns...)
  1667  	}
  1668  
  1669  	// Verify that Bitcoin burn transactions are properly extracted from Bitcoin blocks
  1670  	// and the their burn amounts are computed correctly.
  1671  	require.Equal(9, len(bitcoinExchangeTxns))
  1672  	expectedBitcoinBurnAmounts := []int64{
  1673  		10000,
  1674  		12500,
  1675  		41000,
  1676  		20000,
  1677  		15000,
  1678  		50000,
  1679  		15000,
  1680  		20482,
  1681  		2490,
  1682  	}
  1683  	rateUpdateIndex := 4
  1684  	// We don't need these for this test because checking the final balances
  1685  	// is sufficient.
  1686  	//expectedDeSoNanosMinted := []int64{
  1687  	//2700510570,
  1688  	//3375631103,
  1689  	//11072014581,
  1690  	//5400951887,
  1691  	//// We double the exchange rate at this point. Include a zero
  1692  	//// here to account for this.
  1693  	//0,
  1694  	//8103578296,
  1695  	//27011598923,
  1696  	//8103381058,
  1697  	//11064823217,
  1698  	//1345146534,
  1699  	//}
  1700  	blockIndexesForTransactions := []int{1, 1, 1, 1, 1, 1, 1, 3, 3}
  1701  	for ii, bitcoinExchangeTxn := range bitcoinExchangeTxns {
  1702  		txnMeta := bitcoinExchangeTxn.TxnMeta.(*BitcoinExchangeMetadata)
  1703  		burnTxn := txnMeta.BitcoinTransaction
  1704  		burnOutput, err := _computeBitcoinBurnOutput(
  1705  			burnTxn, BitcoinTestnetBurnAddress, params.BitcoinBtcdParams)
  1706  		require.NoError(err)
  1707  		assert.Equalf(expectedBitcoinBurnAmounts[ii], burnOutput,
  1708  			"Bitcoin burn amount for burn txn %d doesn't line up with "+
  1709  				"what is expected", ii)
  1710  
  1711  		// Sanity-check that the Bitcoin block hashes line up.
  1712  		blockIndex := blockIndexesForTransactions[ii]
  1713  		blockForTxn := bitcoinBlocks[blockIndex]
  1714  		{
  1715  			hash1 := (BlockHash)(blockForTxn.BlockHash())
  1716  			hash2 := *txnMeta.BitcoinBlockHash
  1717  			require.Equalf(
  1718  				hash1, hash2,
  1719  				"Bitcoin block hash for txn does not line up with block hash: %v %v %d", &hash1, &hash2, ii)
  1720  		}
  1721  
  1722  		// Sanity-check that the Merkle root lines up with what's in the block.
  1723  		{
  1724  			hash1 := (BlockHash)(blockForTxn.Header.MerkleRoot)
  1725  			hash2 := *txnMeta.BitcoinMerkleRoot
  1726  			require.Equalf(
  1727  				hash1, hash2,
  1728  				"Bitcoin merkle root for txn does not line up with block hash: %v %v %d", &hash1, &hash2, ii)
  1729  		}
  1730  
  1731  		// Verify that the merkle proof checks out.
  1732  		{
  1733  			txHash := ((BlockHash)(txnMeta.BitcoinTransaction.TxHash()))
  1734  			merkleProofIsValid := merkletree.VerifyProof(
  1735  				txHash[:], txnMeta.BitcoinMerkleProof, txnMeta.BitcoinMerkleRoot[:])
  1736  			require.Truef(
  1737  				merkleProofIsValid, "Problem verifying merkle proof for burn txn %d", ii)
  1738  		}
  1739  
  1740  		// Verify that using the wrong Merkle root doesn't work.
  1741  		{
  1742  			badBlock := bitcoinBlocks[blockIndex-1]
  1743  			badMerkleRoot := badBlock.Header.MerkleRoot[:]
  1744  			txHash := ((BlockHash)(txnMeta.BitcoinTransaction.TxHash()))
  1745  			merkleProofIsValid := merkletree.VerifyProof(
  1746  				txHash[:], txnMeta.BitcoinMerkleProof, badMerkleRoot)
  1747  			require.Falsef(
  1748  				merkleProofIsValid, "Bad Merkle root was actually verified for burn txn %d", ii)
  1749  		}
  1750  
  1751  		// Verify that serializing and deserializing work for this transaction.
  1752  		bb, err := bitcoinExchangeTxn.ToBytes(false /*preSignature*/)
  1753  		require.NoError(err)
  1754  		parsedBitcoinExchangeTxn := &MsgDeSoTxn{}
  1755  		parsedBitcoinExchangeTxn.FromBytes(bb)
  1756  		require.Equal(bitcoinExchangeTxn, parsedBitcoinExchangeTxn)
  1757  	}
  1758  
  1759  	// Find the header in our header list corresponding to the first test block,
  1760  	// which contains the first Bitcoin
  1761  	firstBitcoinBurnBlock := bitcoinBlocks[1]
  1762  	firstBitcoinBurnBlockHash := firstBitcoinBurnBlock.BlockHash()
  1763  	headerIndexOfFirstBurn := -1
  1764  	for headerIndex := range bitcoinHeaders {
  1765  		if firstBitcoinBurnBlockHash == bitcoinHeaders[headerIndex].BlockHash() {
  1766  			headerIndexOfFirstBurn = headerIndex
  1767  			break
  1768  		}
  1769  	}
  1770  	require.Greater(headerIndexOfFirstBurn, 0)
  1771  
  1772  	// Create a Bitcoinmanager that is current whose tip corresponds to the block
  1773  	// just before the block containing the first Bitcoin burn transaction.
  1774  	minBurnBlocks := uint32(2)
  1775  	startHeaderIndex := 0
  1776  	paramsCopy := GetTestParamsCopy(
  1777  		bitcoinHeaders[startHeaderIndex], bitcoinHeaderHeights[startHeaderIndex],
  1778  		params, minBurnBlocks,
  1779  	)
  1780  
  1781  	// Update some of the params to make them reflect what we've hacked into
  1782  	// the bitcoinManager.
  1783  	paramsCopy.BitcoinBurnAddress = BitcoinTestnetBurnAddress
  1784  	chain.params = paramsCopy
  1785  	// Reset the pool to give the mempool access to the new BitcoinManager object.
  1786  	mempool.resetPool(NewDeSoMempool(chain, 0, /* rateLimitFeeRateNanosPerKB */
  1787  		0, /* minFeeRateNanosPerKB */
  1788  		"" /*blockCypherAPIKey*/, false,
  1789  		"" /*dataDir*/, ""))
  1790  
  1791  	// The amount of work on the first burn transaction should be zero.
  1792  	burnTxn1 := bitcoinExchangeTxns[0]
  1793  	burnTxn1Size := getTxnSize(*burnTxn1)
  1794  	burnTxn2 := bitcoinExchangeTxns[1]
  1795  	txHash1 := burnTxn1.Hash()
  1796  
  1797  	// The mempool should accept a BitcoinExchange transaction if its merkle proof
  1798  	// is empty, since it skips the merkle proof checks in this case.
  1799  	{
  1800  		txnCopy := *burnTxn1
  1801  		txnCopy.TxnMeta = &BitcoinExchangeMetadata{
  1802  			BitcoinTransaction: txnCopy.TxnMeta.(*BitcoinExchangeMetadata).BitcoinTransaction,
  1803  			BitcoinBlockHash:   &BlockHash{},
  1804  			BitcoinMerkleRoot:  &BlockHash{},
  1805  			BitcoinMerkleProof: []*merkletree.ProofPart{},
  1806  		}
  1807  		mempoolTxs, err := mempool.processTransaction(
  1808  			&txnCopy, true /*allowUnconnectedTxn*/, true /*rateLimit*/, 0 /*peerID*/, true /*verifySignatures*/)
  1809  		require.NoError(err)
  1810  		require.Equal(1, len(mempoolTxs))
  1811  		require.Equal(1, len(mempool.poolMap))
  1812  	}
  1813  
  1814  	// The user we just applied this transaction for should have a balance now.
  1815  	pkBytes1, _ := hex.DecodeString(BitcoinTestnetPub1)
  1816  	{
  1817  		utxoEntries, err := chain.GetSpendableUtxosForPublicKey(pkBytes1, mempool, nil)
  1818  		require.NoError(err)
  1819  
  1820  		require.Equal(1, len(utxoEntries))
  1821  		assert.Equal(int64(2697810060), int64(utxoEntries[0].AmountNanos))
  1822  	}
  1823  
  1824  	// DO NOT process the Bitcoin block containing the first set of burn transactions.
  1825  	// This is the difference between this test and the previous test.
  1826  
  1827  	// According to the mempool, the balance of the user whose public key created
  1828  	// the Bitcoin burn transaction should now have some DeSo.
  1829  	pkBytes2, _ := hex.DecodeString(BitcoinTestnetPub2)
  1830  	pkBytes3, _ := hex.DecodeString(BitcoinTestnetPub3)
  1831  
  1832  	// The mempool should be able to process a burn transaction directly.
  1833  	{
  1834  		txnCopy := *burnTxn2
  1835  		txnCopy.TxnMeta = &BitcoinExchangeMetadata{
  1836  			BitcoinTransaction: txnCopy.TxnMeta.(*BitcoinExchangeMetadata).BitcoinTransaction,
  1837  			BitcoinBlockHash:   &BlockHash{},
  1838  			BitcoinMerkleRoot:  &BlockHash{},
  1839  			BitcoinMerkleProof: []*merkletree.ProofPart{},
  1840  		}
  1841  		mempoolTxsAdded, err := mempool.processTransaction(
  1842  			&txnCopy, true /*allowUnconnectedTxn*/, true /*rateLimit*/, 0, /*peerID*/
  1843  			true /*verifySignatures*/)
  1844  		require.NoError(err)
  1845  		require.Equal(1, len(mempoolTxsAdded))
  1846  		require.Equal(2, len(mempool.poolMap))
  1847  		mempoolTxRet := mempool.poolMap[*mempoolTxsAdded[0].Hash]
  1848  		require.Equal(
  1849  			mempoolTxRet.Tx.TxnMeta.(*BitcoinExchangeMetadata),
  1850  			txnCopy.TxnMeta.(*BitcoinExchangeMetadata))
  1851  	}
  1852  
  1853  	// According to the mempool, the balances should have updated.
  1854  	{
  1855  		utxoEntries, err := chain.GetSpendableUtxosForPublicKey(pkBytes3, mempool, nil)
  1856  		require.NoError(err)
  1857  
  1858  		require.Equal(1, len(utxoEntries))
  1859  		assert.Equal(int64(3372255472), int64(utxoEntries[0].AmountNanos))
  1860  	}
  1861  
  1862  	// If the mempool is not consulted, the balances should be zero.
  1863  	{
  1864  		utxoEntries, err := chain.GetSpendableUtxosForPublicKey(pkBytes3, nil, nil)
  1865  		require.NoError(err)
  1866  		require.Equal(0, len(utxoEntries))
  1867  	}
  1868  
  1869  	// Make the moneyPkString the paramUpdater so they can update the exchange rate.
  1870  	params.ParamUpdaterPublicKeys = make(map[PkMapKey]bool)
  1871  	params.ParamUpdaterPublicKeys[MakePkMapKey(MustBase58CheckDecode(moneyPkString))] = true
  1872  	paramsCopy.ParamUpdaterPublicKeys = params.ParamUpdaterPublicKeys
  1873  
  1874  	// Running the remaining transactions through the mempool should work and result
  1875  	// in all of them being added.
  1876  	{
  1877  		// Add a placeholder where the rate update is going to be
  1878  		fff := append([]*MsgDeSoTxn{}, bitcoinExchangeTxns[:rateUpdateIndex]...)
  1879  		fff = append(fff, nil)
  1880  		fff = append(fff, bitcoinExchangeTxns[rateUpdateIndex:]...)
  1881  		bitcoinExchangeTxns = fff
  1882  
  1883  		for fakeIndex, burnTxn := range bitcoinExchangeTxns[2:] {
  1884  			realIndex := fakeIndex + 2
  1885  			if realIndex == rateUpdateIndex {
  1886  				newUSDCentsPerBitcoin := int64(27000 * 100)
  1887  				updaterPkBytes, _, err := Base58CheckDecode(moneyPkString)
  1888  				require.NoError(err)
  1889  				rateUpdateTxn, _, _, _, err := chain.CreateUpdateGlobalParamsTxn(
  1890  					updaterPkBytes,
  1891  					newUSDCentsPerBitcoin,
  1892  					0,
  1893  					0,
  1894  					-1,
  1895  					0,
  1896  					nil,
  1897  					100, /*feeRateNanosPerKB*/
  1898  					nil,
  1899  					[]*DeSoOutput{})
  1900  				require.NoError(err)
  1901  				// Sign the transaction now that its inputs are set up.
  1902  				_signTxn(t, rateUpdateTxn, moneyPrivString)
  1903  
  1904  				bitcoinExchangeTxns[realIndex] = rateUpdateTxn
  1905  				burnTxn := bitcoinExchangeTxns[realIndex]
  1906  
  1907  				require.Equal(realIndex, len(mempool.poolMap))
  1908  				mempoolTxsAdded, err := mempool.processTransaction(
  1909  					burnTxn, true /*allowUnconnectedTxn*/, true /*rateLimit*/, 0, /*peerID*/
  1910  					true /*verifySignatures*/)
  1911  				require.NoErrorf(err, "on index: %v", realIndex)
  1912  				require.Equal(1, len(mempoolTxsAdded))
  1913  
  1914  				continue
  1915  			}
  1916  
  1917  			txnCopy := *burnTxn
  1918  			txnCopy.TxnMeta = &BitcoinExchangeMetadata{
  1919  				BitcoinTransaction: txnCopy.TxnMeta.(*BitcoinExchangeMetadata).BitcoinTransaction,
  1920  				BitcoinBlockHash:   &BlockHash{},
  1921  				BitcoinMerkleRoot:  &BlockHash{},
  1922  				BitcoinMerkleProof: []*merkletree.ProofPart{},
  1923  			}
  1924  			require.Equal(realIndex, len(mempool.poolMap))
  1925  			mempoolTxsAdded, err := mempool.processTransaction(
  1926  				&txnCopy, true /*allowUnconnectedTxn*/, true /*rateLimit*/, 0, /*peerID*/
  1927  				true /*verifySignatures*/)
  1928  			require.NoErrorf(err, "on index: %v", realIndex)
  1929  			require.Equal(1, len(mempoolTxsAdded))
  1930  		}
  1931  	}
  1932  
  1933  	{
  1934  		utxoEntries, err := chain.GetSpendableUtxosForPublicKey(pkBytes1, mempool, nil)
  1935  		require.NoError(err)
  1936  		require.Equal(5, len(utxoEntries))
  1937  		totalBalance := uint64(0)
  1938  		for _, utxoEntry := range utxoEntries {
  1939  			totalBalance += utxoEntry.AmountNanos
  1940  		}
  1941  		// Note the 10bp fee.
  1942  		assert.Equal(int64(47475508103), int64(totalBalance))
  1943  	}
  1944  	{
  1945  		utxoEntries, err := chain.GetSpendableUtxosForPublicKey(pkBytes2, mempool, nil)
  1946  		require.NoError(err)
  1947  		require.Equal(1, len(utxoEntries))
  1948  		// Note the 10bp fee.
  1949  		assert.Equal(int64(8095277677), int64(utxoEntries[0].AmountNanos))
  1950  	}
  1951  	{
  1952  		utxoEntries, err := chain.GetSpendableUtxosForPublicKey(pkBytes3, mempool, nil)
  1953  		require.NoError(err)
  1954  		require.Equal(3, len(utxoEntries))
  1955  		totalBalance := uint64(0)
  1956  		for _, utxoEntry := range utxoEntries {
  1957  			totalBalance += utxoEntry.AmountNanos
  1958  		}
  1959  		// Note the 10bp fee.
  1960  		assert.Equal(int64(22528672757), int64(totalBalance))
  1961  	}
  1962  
  1963  	// Spending from the outputs created by a burn should work.
  1964  	desoPub1 := Base58CheckEncode(pkBytes1, false /*isPrivate*/, paramsCopy)
  1965  	priv1, _ := _privStringToKeys(t, BitcoinTestnetPriv1)
  1966  	desoPriv1 := Base58CheckEncode(priv1.Serialize(), true /*isPrivate*/, paramsCopy)
  1967  	desoPub2 := Base58CheckEncode(pkBytes2, false /*isPrivate*/, paramsCopy)
  1968  	priv2, _ := _privStringToKeys(t, BitcoinTestnetPriv2)
  1969  	desoPriv2 := Base58CheckEncode(priv2.Serialize(), true /*isPrivate*/, paramsCopy)
  1970  	desoPub3 := Base58CheckEncode(pkBytes3, false /*isPrivate*/, paramsCopy)
  1971  	priv3, _ := _privStringToKeys(t, BitcoinTestnetPriv3)
  1972  	desoPriv3 := Base58CheckEncode(priv3.Serialize(), true /*isPrivate*/, paramsCopy)
  1973  	{
  1974  		txn := _assembleBasicTransferTxnFullySigned(
  1975  			t, chain, 100000*100000, 11, desoPub1, desoPub2,
  1976  			desoPriv1, mempool)
  1977  		mempoolTxsAdded, err := mempool.processTransaction(
  1978  			txn, true /*allowUnconnectedTxn*/, true /*rateLimit*/, 0, /*peerID*/
  1979  			true /*verifySignatures*/)
  1980  		require.NoError(err)
  1981  		require.Equal(1, len(mempoolTxsAdded))
  1982  		bitcoinExchangeTxns = append(bitcoinExchangeTxns, txn)
  1983  	}
  1984  	{
  1985  		txn := _assembleBasicTransferTxnFullySigned(
  1986  			t, chain, 60000*100000, 11, desoPub3, desoPub1,
  1987  			desoPriv3, mempool)
  1988  		mempoolTxsAdded, err := mempool.processTransaction(
  1989  			txn, true /*allowUnconnectedTxn*/, true /*rateLimit*/, 0, /*peerID*/
  1990  			true /*verifySignatures*/)
  1991  		require.NoError(err)
  1992  		require.Equal(1, len(mempoolTxsAdded))
  1993  		bitcoinExchangeTxns = append(bitcoinExchangeTxns, txn)
  1994  	}
  1995  	{
  1996  		txn := _assembleBasicTransferTxnFullySigned(
  1997  			t, chain, 60000*100000, 11, desoPub2, desoPub1,
  1998  			desoPriv2, mempool)
  1999  		mempoolTxsAdded, err := mempool.processTransaction(
  2000  			txn, true /*allowUnconnectedTxn*/, true /*rateLimit*/, 0, /*peerID*/
  2001  			true /*verifySignatures*/)
  2002  		require.NoError(err)
  2003  		require.Equal(1, len(mempoolTxsAdded))
  2004  		bitcoinExchangeTxns = append(bitcoinExchangeTxns, txn)
  2005  	}
  2006  
  2007  	// The balances according to the db after the spends above should be correct.
  2008  	{
  2009  		utxoEntries, err := chain.GetSpendableUtxosForPublicKey(pkBytes1, mempool, nil)
  2010  		require.NoError(err)
  2011  		totalBalance := uint64(0)
  2012  		for _, utxoEntry := range utxoEntries {
  2013  			totalBalance += utxoEntry.AmountNanos
  2014  		}
  2015  		assert.Equal(int64(49455017177), int64(totalBalance))
  2016  	}
  2017  	{
  2018  		utxoEntries, err := chain.GetSpendableUtxosForPublicKey(pkBytes2, mempool, nil)
  2019  		require.NoError(err)
  2020  		assert.Equal(int64(2087182397), int64(utxoEntries[0].AmountNanos))
  2021  	}
  2022  	{
  2023  		utxoEntries, err := chain.GetSpendableUtxosForPublicKey(pkBytes3, mempool, nil)
  2024  		require.NoError(err)
  2025  		totalBalance := uint64(0)
  2026  		for _, utxoEntry := range utxoEntries {
  2027  			totalBalance += utxoEntry.AmountNanos
  2028  		}
  2029  		assert.Equal(int64(16517205024), int64(totalBalance))
  2030  	}
  2031  	prevMempoolSize := len(mempool.poolMap)
  2032  
  2033  	// The transaction should pass now
  2034  	{
  2035  		utxoView, _ := NewUtxoView(db, paramsCopy, nil)
  2036  		blockHeight := chain.blockTip().Height + 1
  2037  
  2038  		_, _, _, _, err :=
  2039  			utxoView.ConnectTransaction(burnTxn1, txHash1, burnTxn1Size, blockHeight, true /*verifySignature*/, false /*ignoreUtxos*/)
  2040  		require.NoError(err)
  2041  	}
  2042  
  2043  	miner.params = paramsCopy
  2044  	miner.BlockProducer.params = paramsCopy
  2045  
  2046  	// At this point, the mempool should contain *mined* BitcoinExchange
  2047  	// transactions with fully proper merkle proofs.
  2048  
  2049  	// Now mining the blocks should get us the balances that the mempool
  2050  	// reported previously.
  2051  	finalBlock1, err := miner.MineAndProcessSingleBlock(0 /*threadIndex*/, mempool)
  2052  	require.NoError(err)
  2053  	_ = finalBlock1
  2054  	finalBlock2, err := miner.MineAndProcessSingleBlock(0 /*threadIndex*/, mempool)
  2055  	require.NoError(err)
  2056  	finalBlock3, err := miner.MineAndProcessSingleBlock(0 /*threadIndex*/, mempool)
  2057  	require.NoError(err)
  2058  	finalBlock4, err := miner.MineAndProcessSingleBlock(0 /*threadIndex*/, mempool)
  2059  	require.NoError(err)
  2060  
  2061  	// The first block should contain the txns because we mined a
  2062  	// block to get the chain current previously.
  2063  	require.Equal(len(finalBlock1.Txns), 1)
  2064  	require.Equal(len(finalBlock2.Txns), 14)
  2065  	require.Equal(len(finalBlock3.Txns), 1)
  2066  	require.Equal(len(finalBlock4.Txns), 1)
  2067  
  2068  	// The transactions should all have been processed into blocks and
  2069  	// removed from the mempool.
  2070  	require.Equal(0, len(mempool.poolMap))
  2071  	// The balances should be what they were even if you query the mempool
  2072  	// because the txns have now moved into the db.
  2073  	{
  2074  		utxoEntries, err := chain.GetSpendableUtxosForPublicKey(pkBytes1, mempool, nil)
  2075  		require.NoError(err)
  2076  		totalBalance := uint64(0)
  2077  		for _, utxoEntry := range utxoEntries {
  2078  			totalBalance += utxoEntry.AmountNanos
  2079  		}
  2080  		assert.Equal(int64(49455017177), int64(totalBalance))
  2081  	}
  2082  	{
  2083  		utxoEntries, err := chain.GetSpendableUtxosForPublicKey(pkBytes2, mempool, nil)
  2084  		require.NoError(err)
  2085  		assert.Equal(int64(2087182397), int64(utxoEntries[0].AmountNanos))
  2086  	}
  2087  	{
  2088  		utxoEntries, err := chain.GetSpendableUtxosForPublicKey(pkBytes3, mempool, nil)
  2089  		require.NoError(err)
  2090  		totalBalance := uint64(0)
  2091  		for _, utxoEntry := range utxoEntries {
  2092  			totalBalance += utxoEntry.AmountNanos
  2093  		}
  2094  		assert.Equal(int64(16517205024), int64(totalBalance))
  2095  	}
  2096  
  2097  	// The balances after mining the block should line up.
  2098  	{
  2099  		utxoEntries, err := chain.GetSpendableUtxosForPublicKey(pkBytes1, nil, nil)
  2100  		require.NoError(err)
  2101  		totalBalance := uint64(0)
  2102  		for _, utxoEntry := range utxoEntries {
  2103  			totalBalance += utxoEntry.AmountNanos
  2104  		}
  2105  		assert.Equal(int64(49455017177), int64(totalBalance))
  2106  	}
  2107  	{
  2108  		utxoEntries, err := chain.GetSpendableUtxosForPublicKey(pkBytes2, nil, nil)
  2109  		require.NoError(err)
  2110  		assert.Equal(int64(2087182397), int64(utxoEntries[0].AmountNanos))
  2111  	}
  2112  	{
  2113  		utxoEntries, err := chain.GetSpendableUtxosForPublicKey(pkBytes3, nil, nil)
  2114  		require.NoError(err)
  2115  		totalBalance := uint64(0)
  2116  		for _, utxoEntry := range utxoEntries {
  2117  			totalBalance += utxoEntry.AmountNanos
  2118  		}
  2119  		assert.Equal(int64(16517205024), int64(totalBalance))
  2120  	}
  2121  
  2122  	// Roll back the blocks and make sure we don't hit any errors. Call
  2123  	// the mempool's disconnect function to make sure we get the txns
  2124  	// back during a reorg.
  2125  	{
  2126  		utxoView, err := NewUtxoView(db, paramsCopy, nil)
  2127  		require.NoError(err)
  2128  
  2129  		{
  2130  			// Fetch the utxo operations for the block we're detaching. We need these
  2131  			// in order to be able to detach the block.
  2132  			hash, err := finalBlock4.Header.Hash()
  2133  			require.NoError(err)
  2134  			utxoOps, err := GetUtxoOperationsForBlock(db, hash)
  2135  			require.NoError(err)
  2136  
  2137  			// Compute the hashes for all the transactions.
  2138  			txHashes, err := ComputeTransactionHashes(finalBlock4.Txns)
  2139  			require.NoError(err)
  2140  			require.NoError(utxoView.DisconnectBlock(finalBlock4, txHashes, utxoOps))
  2141  		}
  2142  		{
  2143  			// Fetch the utxo operations for the block we're detaching. We need these
  2144  			// in order to be able to detach the block.
  2145  			hash, err := finalBlock3.Header.Hash()
  2146  			require.NoError(err)
  2147  			utxoOps, err := GetUtxoOperationsForBlock(db, hash)
  2148  			require.NoError(err)
  2149  
  2150  			// Compute the hashes for all the transactions.
  2151  			txHashes, err := ComputeTransactionHashes(finalBlock3.Txns)
  2152  			require.NoError(err)
  2153  			require.NoError(utxoView.DisconnectBlock(finalBlock3, txHashes, utxoOps))
  2154  		}
  2155  		{
  2156  			// Fetch the utxo operations for the block we're detaching. We need these
  2157  			// in order to be able to detach the block.
  2158  			hash, err := finalBlock2.Header.Hash()
  2159  			require.NoError(err)
  2160  			utxoOps, err := GetUtxoOperationsForBlock(db, hash)
  2161  			require.NoError(err)
  2162  
  2163  			// Compute the hashes for all the transactions.
  2164  			txHashes, err := ComputeTransactionHashes(finalBlock2.Txns)
  2165  			require.NoError(err)
  2166  			require.NoError(utxoView.DisconnectBlock(finalBlock2, txHashes, utxoOps))
  2167  		}
  2168  		{
  2169  			// Fetch the utxo operations for the block we're detaching. We need these
  2170  			// in order to be able to detach the block.
  2171  			hash, err := finalBlock1.Header.Hash()
  2172  			require.NoError(err)
  2173  			utxoOps, err := GetUtxoOperationsForBlock(db, hash)
  2174  			require.NoError(err)
  2175  
  2176  			// Compute the hashes for all the transactions.
  2177  			txHashes, err := ComputeTransactionHashes(finalBlock1.Txns)
  2178  			require.NoError(err)
  2179  			require.NoError(utxoView.DisconnectBlock(finalBlock1, txHashes, utxoOps))
  2180  		}
  2181  
  2182  		// Flushing the view after applying and rolling back should work.
  2183  		require.NoError(utxoView.FlushToDb())
  2184  
  2185  		mempool.UpdateAfterDisconnectBlock(finalBlock4)
  2186  		mempool.UpdateAfterDisconnectBlock(finalBlock3)
  2187  		mempool.UpdateAfterDisconnectBlock(finalBlock2)
  2188  		mempool.UpdateAfterDisconnectBlock(finalBlock1)
  2189  	}
  2190  
  2191  	// The balances according to the db without querying the mempool should
  2192  	// be zero again.
  2193  	{
  2194  		utxoEntries, err := chain.GetSpendableUtxosForPublicKey(pkBytes1, nil, nil)
  2195  		require.NoError(err)
  2196  		require.Equal(0, len(utxoEntries))
  2197  	}
  2198  	{
  2199  		utxoEntries, err := chain.GetSpendableUtxosForPublicKey(pkBytes2, nil, nil)
  2200  		require.NoError(err)
  2201  		require.Equal(0, len(utxoEntries))
  2202  	}
  2203  	{
  2204  		utxoEntries, err := chain.GetSpendableUtxosForPublicKey(pkBytes3, nil, nil)
  2205  		require.NoError(err)
  2206  		require.Equal(0, len(utxoEntries))
  2207  	}
  2208  
  2209  	// The mempool should have all of its txns back and the balances should be what
  2210  	// they were before we did a block reorg.
  2211  	require.Equal(prevMempoolSize, len(mempool.poolMap))
  2212  	{
  2213  		utxoEntries, err := chain.GetSpendableUtxosForPublicKey(pkBytes1, mempool, nil)
  2214  		require.NoError(err)
  2215  		totalBalance := uint64(0)
  2216  		for _, utxoEntry := range utxoEntries {
  2217  			totalBalance += utxoEntry.AmountNanos
  2218  		}
  2219  		assert.Equal(int64(49455017177), int64(totalBalance))
  2220  	}
  2221  	{
  2222  		utxoEntries, err := chain.GetSpendableUtxosForPublicKey(pkBytes2, mempool, nil)
  2223  		require.NoError(err)
  2224  		assert.Equal(int64(2087182397), int64(utxoEntries[0].AmountNanos))
  2225  	}
  2226  	{
  2227  		utxoEntries, err := chain.GetSpendableUtxosForPublicKey(pkBytes3, mempool, nil)
  2228  		require.NoError(err)
  2229  		totalBalance := uint64(0)
  2230  		for _, utxoEntry := range utxoEntries {
  2231  			totalBalance += utxoEntry.AmountNanos
  2232  		}
  2233  		assert.Equal(int64(16517205024), int64(totalBalance))
  2234  	}
  2235  
  2236  	_, _, _, _, _, _ = db, mempool, miner, bitcoinBlocks, bitcoinHeaders, bitcoinHeaderHeights
  2237  }
  2238  
  2239  func TestBitcoinExchangeWithAmountNanosNonZeroAtGenesis(t *testing.T) {
  2240  	assert := assert.New(t)
  2241  	require := require.New(t)
  2242  	_ = assert
  2243  	_ = require
  2244  
  2245  	// Don't refresh the universal view for this test, since it causes a race condition
  2246  	// to trigger.
  2247  	// TODO: Lower this value to .1 and fix this race condition.
  2248  	ReadOnlyUtxoViewRegenerationIntervalSeconds = 100
  2249  
  2250  	oldInitialUSDCentsPerBitcoinExchangeRate := InitialUSDCentsPerBitcoinExchangeRate
  2251  	InitialUSDCentsPerBitcoinExchangeRate = 1350000
  2252  	defer func() {
  2253  		InitialUSDCentsPerBitcoinExchangeRate = oldInitialUSDCentsPerBitcoinExchangeRate
  2254  	}()
  2255  
  2256  	paramsTmp := DeSoTestnetParams
  2257  	paramsTmp.DeSoNanosPurchasedAtGenesis = 500000123456789
  2258  	chain, params, db := NewLowDifficultyBlockchainWithParams(&paramsTmp)
  2259  	mempool, miner := NewTestMiner(t, chain, params, true /*isSender*/)
  2260  
  2261  	// Read in the test Bitcoin blocks and headers.
  2262  	bitcoinBlocks, bitcoinHeaders, bitcoinHeaderHeights := _readBitcoinExchangeTestData(t)
  2263  
  2264  	// Extract BitcoinExchange transactions from the test Bitcoin blocks.
  2265  	bitcoinExchangeTxns := []*MsgDeSoTxn{}
  2266  	for _, block := range bitcoinBlocks {
  2267  		currentBurnTxns, err :=
  2268  			ExtractBitcoinExchangeTransactionsFromBitcoinBlock(
  2269  				block, BitcoinTestnetBurnAddress, params)
  2270  		require.NoError(err)
  2271  		bitcoinExchangeTxns = append(bitcoinExchangeTxns, currentBurnTxns...)
  2272  	}
  2273  
  2274  	// Verify that Bitcoin burn transactions are properly extracted from Bitcoin blocks
  2275  	// and the their burn amounts are computed correctly.
  2276  	require.Equal(9, len(bitcoinExchangeTxns))
  2277  	expectedBitcoinBurnAmounts := []int64{
  2278  		10000,
  2279  		12500,
  2280  		41000,
  2281  		20000,
  2282  		15000,
  2283  		50000,
  2284  		15000,
  2285  		20482,
  2286  		2490,
  2287  	}
  2288  	rateUpdateIndex := 4
  2289  	expectedDeSoNanosMinted := []int64{
  2290  		1909549696,
  2291  		2386933566,
  2292  		7829114379,
  2293  		3819064767,
  2294  		// We double the exchange rate at this point. Include a zero
  2295  		// here to account for this.
  2296  		0,
  2297  		5730125620,
  2298  		19100254365,
  2299  		5730026999,
  2300  		7824124112,
  2301  		951177121,
  2302  	}
  2303  	blockIndexesForTransactions := []int{1, 1, 1, 1, 1, 1, 1, 3, 3}
  2304  	for ii, bitcoinExchangeTxn := range bitcoinExchangeTxns {
  2305  		txnMeta := bitcoinExchangeTxn.TxnMeta.(*BitcoinExchangeMetadata)
  2306  		burnTxn := txnMeta.BitcoinTransaction
  2307  		burnOutput, err := _computeBitcoinBurnOutput(
  2308  			burnTxn, BitcoinTestnetBurnAddress, params.BitcoinBtcdParams)
  2309  		require.NoError(err)
  2310  		assert.Equalf(expectedBitcoinBurnAmounts[ii], burnOutput,
  2311  			"Bitcoin burn amount for burn txn %d doesn't line up with "+
  2312  				"what is expected", ii)
  2313  
  2314  		// Sanity-check that the Bitcoin block hashes line up.
  2315  		blockIndex := blockIndexesForTransactions[ii]
  2316  		blockForTxn := bitcoinBlocks[blockIndex]
  2317  		{
  2318  			hash1 := (BlockHash)(blockForTxn.BlockHash())
  2319  			hash2 := *txnMeta.BitcoinBlockHash
  2320  			require.Equalf(
  2321  				hash1, hash2,
  2322  				"Bitcoin block hash for txn does not line up with block hash: %v %v %d", &hash1, &hash2, ii)
  2323  		}
  2324  
  2325  		// Sanity-check that the Merkle root lines up with what's in the block.
  2326  		{
  2327  			hash1 := (BlockHash)(blockForTxn.Header.MerkleRoot)
  2328  			hash2 := *txnMeta.BitcoinMerkleRoot
  2329  			require.Equalf(
  2330  				hash1, hash2,
  2331  				"Bitcoin merkle root for txn does not line up with block hash: %v %v %d", &hash1, &hash2, ii)
  2332  		}
  2333  
  2334  		// Verify that the merkle proof checks out.
  2335  		{
  2336  			txHash := ((BlockHash)(txnMeta.BitcoinTransaction.TxHash()))
  2337  			merkleProofIsValid := merkletree.VerifyProof(
  2338  				txHash[:], txnMeta.BitcoinMerkleProof, txnMeta.BitcoinMerkleRoot[:])
  2339  			require.Truef(
  2340  				merkleProofIsValid, "Problem verifying merkle proof for burn txn %d", ii)
  2341  		}
  2342  
  2343  		// Verify that using the wrong Merkle root doesn't work.
  2344  		{
  2345  			badBlock := bitcoinBlocks[blockIndex-1]
  2346  			badMerkleRoot := badBlock.Header.MerkleRoot[:]
  2347  			txHash := ((BlockHash)(txnMeta.BitcoinTransaction.TxHash()))
  2348  			merkleProofIsValid := merkletree.VerifyProof(
  2349  				txHash[:], txnMeta.BitcoinMerkleProof, badMerkleRoot)
  2350  			require.Falsef(
  2351  				merkleProofIsValid, "Bad Merkle root was actually verified for burn txn %d", ii)
  2352  		}
  2353  
  2354  		// Verify that serializing and deserializing work for this transaction.
  2355  		bb, err := bitcoinExchangeTxn.ToBytes(false /*preSignature*/)
  2356  		require.NoError(err)
  2357  		parsedBitcoinExchangeTxn := &MsgDeSoTxn{}
  2358  		parsedBitcoinExchangeTxn.FromBytes(bb)
  2359  		require.Equal(bitcoinExchangeTxn, parsedBitcoinExchangeTxn)
  2360  	}
  2361  
  2362  	// Find the header in our header list corresponding to the first test block,
  2363  	// which contains the first Bitcoin
  2364  	firstBitcoinBurnBlock := bitcoinBlocks[1]
  2365  	firstBitcoinBurnBlockHash := firstBitcoinBurnBlock.BlockHash()
  2366  	headerIndexOfFirstBurn := -1
  2367  	for headerIndex := range bitcoinHeaders {
  2368  		if firstBitcoinBurnBlockHash == bitcoinHeaders[headerIndex].BlockHash() {
  2369  			headerIndexOfFirstBurn = headerIndex
  2370  			break
  2371  		}
  2372  	}
  2373  	require.Greater(headerIndexOfFirstBurn, 0)
  2374  
  2375  	// Create a Bitcoinmanager that is current whose tip corresponds to the block
  2376  	// just before the block containing the first Bitcoin burn transaction.
  2377  	minBurnBlocks := uint32(2)
  2378  	startHeaderIndex := 0
  2379  	paramsCopy := GetTestParamsCopy(
  2380  		bitcoinHeaders[startHeaderIndex], bitcoinHeaderHeights[startHeaderIndex],
  2381  		params, minBurnBlocks,
  2382  	)
  2383  
  2384  	// Update some of the params to make them reflect what we've hacked into
  2385  	// the bitcoinManager.
  2386  	paramsCopy.BitcoinBurnAddress = BitcoinTestnetBurnAddress
  2387  	chain.params = paramsCopy
  2388  	// Reset the pool to give the mempool access to the new BitcoinManager object.
  2389  	mempool.resetPool(NewDeSoMempool(chain, 0, /* rateLimitFeeRateNanosPerKB */
  2390  		0, /* minFeeRateNanosPerKB */
  2391  		"" /*blockCypherAPIKey*/, false,
  2392  		"" /*dataDir*/, ""))
  2393  
  2394  	// The amount of work on the first burn transaction should be zero.
  2395  	burnTxn1 := bitcoinExchangeTxns[0]
  2396  	burnTxn2 := bitcoinExchangeTxns[1]
  2397  
  2398  	// Applying the full transaction with its merkle proof to the mempool should work
  2399  	{
  2400  		mempoolTxs, err := mempool.processTransaction(
  2401  			burnTxn1, true /*allowUnconnectedTxn*/, true /*rateLimit*/, 0 /*peerID*/, true /*verifySignatures*/)
  2402  		require.NoError(err)
  2403  		require.Equal(1, len(mempoolTxs))
  2404  		require.Equal(1, len(mempool.poolMap))
  2405  		mempoolTxRet := mempool.poolMap[*mempoolTxs[0].Hash]
  2406  		require.Equal(
  2407  			mempoolTxRet.Tx.TxnMeta.(*BitcoinExchangeMetadata),
  2408  			burnTxn1.TxnMeta.(*BitcoinExchangeMetadata))
  2409  	}
  2410  
  2411  	// According to the mempool, the balance of the user whose public key created
  2412  	// the Bitcoin burn transaction should now have some DeSo.
  2413  	pkBytes1, _ := hex.DecodeString(BitcoinTestnetPub1)
  2414  	pkBytes2, _ := hex.DecodeString(BitcoinTestnetPub2)
  2415  	pkBytes3, _ := hex.DecodeString(BitcoinTestnetPub3)
  2416  	{
  2417  		utxoEntries, err := chain.GetSpendableUtxosForPublicKey(pkBytes1, mempool, nil)
  2418  		require.NoError(err)
  2419  
  2420  		require.Equal(1, len(utxoEntries))
  2421  		assert.Equal(int64(1907640147), int64(utxoEntries[0].AmountNanos))
  2422  	}
  2423  
  2424  	// The mempool should be able to process a burn transaction directly.
  2425  	{
  2426  		mempoolTxsAdded, err := mempool.processTransaction(
  2427  			burnTxn2, true /*allowUnconnectedTxn*/, true /*rateLimit*/, 0, /*peerID*/
  2428  			true /*verifySignatures*/)
  2429  		require.NoError(err)
  2430  		require.Equal(1, len(mempoolTxsAdded))
  2431  		require.Equal(2, len(mempool.poolMap))
  2432  		mempoolTxRet := mempool.poolMap[*mempoolTxsAdded[0].Hash]
  2433  		require.Equal(
  2434  			mempoolTxRet.Tx.TxnMeta.(*BitcoinExchangeMetadata),
  2435  			burnTxn2.TxnMeta.(*BitcoinExchangeMetadata))
  2436  	}
  2437  
  2438  	// According to the mempool, the balances should have updated.
  2439  	{
  2440  		utxoEntries, err := chain.GetSpendableUtxosForPublicKey(pkBytes3, mempool, nil)
  2441  		require.NoError(err)
  2442  
  2443  		require.Equal(1, len(utxoEntries))
  2444  		assert.Equal(int64(2384546633), int64(utxoEntries[0].AmountNanos))
  2445  	}
  2446  
  2447  	// If the mempool is not consulted, the balances should be zero.
  2448  	{
  2449  		utxoEntries, err := chain.GetSpendableUtxosForPublicKey(pkBytes3, nil, nil)
  2450  		require.NoError(err)
  2451  		require.Equal(0, len(utxoEntries))
  2452  	}
  2453  
  2454  	// Make the moneyPkString the paramUpdater so they can update the exchange rate.
  2455  	params.ParamUpdaterPublicKeys = make(map[PkMapKey]bool)
  2456  	params.ParamUpdaterPublicKeys[MakePkMapKey(MustBase58CheckDecode(moneyPkString))] = true
  2457  	paramsCopy.ParamUpdaterPublicKeys = params.ParamUpdaterPublicKeys
  2458  
  2459  	// Applying all the txns to the UtxoView should work. Include a rate update
  2460  	// in the middle.
  2461  	utxoOpsList := [][]*UtxoOperation{}
  2462  	{
  2463  		utxoView, err := NewUtxoView(db, paramsCopy, nil)
  2464  		require.NoError(err)
  2465  
  2466  		// Add a placeholder where the rate update is going to be
  2467  		fff := append([]*MsgDeSoTxn{}, bitcoinExchangeTxns[:rateUpdateIndex]...)
  2468  		fff = append(fff, nil)
  2469  		fff = append(fff, bitcoinExchangeTxns[rateUpdateIndex:]...)
  2470  		bitcoinExchangeTxns = fff
  2471  
  2472  		for ii := range bitcoinExchangeTxns {
  2473  			// When we hit the rate update, populate the placeholder.
  2474  			if ii == rateUpdateIndex {
  2475  				newUSDCentsPerBitcoin := uint64(27000 * 100)
  2476  				_, rateUpdateTxn, _, err := _updateUSDCentsPerBitcoinExchangeRate(
  2477  					t, chain, db, params, 100, /*feeRateNanosPerKB*/
  2478  					moneyPkString,
  2479  					moneyPrivString,
  2480  					newUSDCentsPerBitcoin)
  2481  				require.NoError(err)
  2482  
  2483  				bitcoinExchangeTxns[ii] = rateUpdateTxn
  2484  				burnTxn := bitcoinExchangeTxns[ii]
  2485  				burnTxnSize := getTxnSize(*burnTxn)
  2486  				blockHeight := chain.blockTip().Height + 1
  2487  				utxoOps, totalInput, totalOutput, fees, err :=
  2488  					utxoView.ConnectTransaction(
  2489  						burnTxn, burnTxn.Hash(), burnTxnSize, blockHeight, true /*verifySignature*/, false /*ignoreUtxos*/)
  2490  				_, _, _ = totalInput, totalOutput, fees
  2491  				require.NoError(err)
  2492  				utxoOpsList = append(utxoOpsList, utxoOps)
  2493  				continue
  2494  			}
  2495  
  2496  			burnTxn := bitcoinExchangeTxns[ii]
  2497  			burnTxnSize := getTxnSize(*burnTxn)
  2498  			blockHeight := chain.blockTip().Height + 1
  2499  			utxoOps, totalInput, totalOutput, fees, err :=
  2500  				utxoView.ConnectTransaction(
  2501  					burnTxn, burnTxn.Hash(), burnTxnSize, blockHeight, true /*verifySignature*/, false /*ignoreUtxos*/)
  2502  			require.NoError(err)
  2503  
  2504  			require.Equal(2, len(utxoOps))
  2505  			//fmt.Println(int64(totalInput), ",")
  2506  			assert.Equal(expectedDeSoNanosMinted[ii], int64(totalInput))
  2507  			assert.Equal(expectedDeSoNanosMinted[ii]*int64(paramsCopy.BitcoinExchangeFeeBasisPoints)/10000, int64(fees))
  2508  			assert.Equal(int64(fees), int64(totalInput-totalOutput))
  2509  
  2510  			_, _, _ = ii, totalOutput, fees
  2511  			utxoOpsList = append(utxoOpsList, utxoOps)
  2512  		}
  2513  
  2514  		// Flushing the UtxoView should work.
  2515  		require.NoError(utxoView.FlushToDb())
  2516  	}
  2517  
  2518  	// The balances according to the db after the flush should be correct.
  2519  	{
  2520  		utxoEntries, err := chain.GetSpendableUtxosForPublicKey(pkBytes1, nil, nil)
  2521  		require.NoError(err)
  2522  		require.Equal(5, len(utxoEntries))
  2523  		totalBalance := uint64(0)
  2524  		for _, utxoEntry := range utxoEntries {
  2525  			totalBalance += utxoEntry.AmountNanos
  2526  		}
  2527  		// Note the 10bp fee.
  2528  		assert.Equal(int64(33570565893), int64(totalBalance))
  2529  	}
  2530  	{
  2531  		utxoEntries, err := chain.GetSpendableUtxosForPublicKey(pkBytes2, nil, nil)
  2532  		require.NoError(err)
  2533  		require.Equal(1, len(utxoEntries))
  2534  		// Note the 10bp fee.
  2535  		assert.Equal(int64(5724296973), int64(utxoEntries[0].AmountNanos))
  2536  	}
  2537  	{
  2538  		utxoEntries, err := chain.GetSpendableUtxosForPublicKey(pkBytes3, nil, nil)
  2539  		require.NoError(err)
  2540  		require.Equal(3, len(utxoEntries))
  2541  		totalBalance := uint64(0)
  2542  		for _, utxoEntry := range utxoEntries {
  2543  			totalBalance += utxoEntry.AmountNanos
  2544  		}
  2545  		// Note the 10bp fee.
  2546  		assert.Equal(int64(15930227393), int64(totalBalance))
  2547  	}
  2548  
  2549  	// Spending from the outputs created by a burn should work.
  2550  	desoPub1 := Base58CheckEncode(pkBytes1, false /*isPrivate*/, paramsCopy)
  2551  	priv1, _ := _privStringToKeys(t, BitcoinTestnetPriv1)
  2552  	desoPriv1 := Base58CheckEncode(priv1.Serialize(), true /*isPrivate*/, paramsCopy)
  2553  	desoPub2 := Base58CheckEncode(pkBytes2, false /*isPrivate*/, paramsCopy)
  2554  	priv2, _ := _privStringToKeys(t, BitcoinTestnetPriv2)
  2555  	desoPriv2 := Base58CheckEncode(priv2.Serialize(), true /*isPrivate*/, paramsCopy)
  2556  	desoPub3 := Base58CheckEncode(pkBytes3, false /*isPrivate*/, paramsCopy)
  2557  	priv3, _ := _privStringToKeys(t, BitcoinTestnetPriv3)
  2558  	desoPriv3 := Base58CheckEncode(priv3.Serialize(), true /*isPrivate*/, paramsCopy)
  2559  	{
  2560  		currentOps, currentTxn, _ := _doBasicTransferWithViewFlush(
  2561  			t, chain, db, params, desoPub1, desoPub2,
  2562  			desoPriv1, 100000*100000 /*amount to send*/, 11 /*feerate*/)
  2563  
  2564  		utxoOpsList = append(utxoOpsList, currentOps)
  2565  		bitcoinExchangeTxns = append(bitcoinExchangeTxns, currentTxn)
  2566  	}
  2567  	{
  2568  		currentOps, currentTxn, _ := _doBasicTransferWithViewFlush(
  2569  			t, chain, db, params, desoPub3, desoPub1,
  2570  			desoPriv3, 60000*100000 /*amount to send*/, 11 /*feerate*/)
  2571  
  2572  		utxoOpsList = append(utxoOpsList, currentOps)
  2573  		bitcoinExchangeTxns = append(bitcoinExchangeTxns, currentTxn)
  2574  	}
  2575  	{
  2576  		currentOps, currentTxn, _ := _doBasicTransferWithViewFlush(
  2577  			t, chain, db, params, desoPub2, desoPub1,
  2578  			desoPriv2, 60000*100000 /*amount to send*/, 11 /*feerate*/)
  2579  
  2580  		utxoOpsList = append(utxoOpsList, currentOps)
  2581  		bitcoinExchangeTxns = append(bitcoinExchangeTxns, currentTxn)
  2582  	}
  2583  
  2584  	// The balances according to the db after the spends above should be correct.
  2585  	{
  2586  		utxoEntries, err := chain.GetSpendableUtxosForPublicKey(pkBytes1, nil, nil)
  2587  		require.NoError(err)
  2588  		totalBalance := uint64(0)
  2589  		for _, utxoEntry := range utxoEntries {
  2590  			totalBalance += utxoEntry.AmountNanos
  2591  		}
  2592  		assert.Equal(int64(35556076477), int64(totalBalance))
  2593  	}
  2594  	{
  2595  		utxoEntries, err := chain.GetSpendableUtxosForPublicKey(pkBytes2, nil, nil)
  2596  		require.NoError(err)
  2597  		assert.Equal(int64(9718572674), int64(utxoEntries[0].AmountNanos))
  2598  	}
  2599  	{
  2600  		utxoEntries, err := chain.GetSpendableUtxosForPublicKey(pkBytes3, nil, nil)
  2601  		require.NoError(err)
  2602  		totalBalance := uint64(0)
  2603  		for _, utxoEntry := range utxoEntries {
  2604  			totalBalance += utxoEntry.AmountNanos
  2605  		}
  2606  		assert.Equal(int64(9922118448), int64(totalBalance))
  2607  	}
  2608  
  2609  	{
  2610  		// Rolling back all the transactions should work.
  2611  		utxoView, err := NewUtxoView(db, paramsCopy, nil)
  2612  		require.NoError(err)
  2613  		for ii := range bitcoinExchangeTxns {
  2614  			index := len(bitcoinExchangeTxns) - 1 - ii
  2615  			burnTxn := bitcoinExchangeTxns[index]
  2616  			blockHeight := chain.blockTip().Height + 1
  2617  			err := utxoView.DisconnectTransaction(burnTxn, burnTxn.Hash(), utxoOpsList[index], blockHeight)
  2618  			require.NoErrorf(err, "Transaction index: %v", index)
  2619  		}
  2620  
  2621  		// Flushing the UtxoView back to the db after rolling back the
  2622  		require.NoError(utxoView.FlushToDb())
  2623  	}
  2624  
  2625  	// The balances according to the db after rolling back and flushing everything
  2626  	// should be zero.
  2627  	{
  2628  		utxoEntries, err := chain.GetSpendableUtxosForPublicKey(pkBytes1, nil, nil)
  2629  		require.NoError(err)
  2630  		require.Equal(0, len(utxoEntries))
  2631  	}
  2632  	{
  2633  		utxoEntries, err := chain.GetSpendableUtxosForPublicKey(pkBytes2, nil, nil)
  2634  		require.NoError(err)
  2635  		require.Equal(0, len(utxoEntries))
  2636  	}
  2637  	{
  2638  		utxoEntries, err := chain.GetSpendableUtxosForPublicKey(pkBytes3, nil, nil)
  2639  		require.NoError(err)
  2640  		require.Equal(0, len(utxoEntries))
  2641  	}
  2642  
  2643  	// Re-applying all the transactions to the view and rolling back without
  2644  	// flushing should be fine.
  2645  	utxoOpsList = [][]*UtxoOperation{}
  2646  	{
  2647  		utxoView, err := NewUtxoView(db, paramsCopy, nil)
  2648  		require.NoError(err)
  2649  		for ii, burnTxn := range bitcoinExchangeTxns {
  2650  			blockHeight := chain.blockTip().Height + 1
  2651  			burnTxnSize := getTxnSize(*burnTxn)
  2652  			utxoOps, totalInput, totalOutput, fees, err :=
  2653  				utxoView.ConnectTransaction(burnTxn, burnTxn.Hash(), burnTxnSize, blockHeight, true /*verifySignature*/, false /*ignoreUtxos*/)
  2654  			require.NoError(err)
  2655  
  2656  			if ii < len(expectedBitcoinBurnAmounts) {
  2657  				if ii != rateUpdateIndex {
  2658  					require.Equal(2, len(utxoOps))
  2659  					assert.Equal(int64(totalInput), expectedDeSoNanosMinted[ii])
  2660  					assert.Equal(int64(fees), expectedDeSoNanosMinted[ii]*int64(paramsCopy.BitcoinExchangeFeeBasisPoints)/10000)
  2661  					assert.Equal(int64(fees), int64(totalInput-totalOutput))
  2662  				}
  2663  			}
  2664  
  2665  			utxoOpsList = append(utxoOpsList, utxoOps)
  2666  		}
  2667  
  2668  		for ii := range bitcoinExchangeTxns {
  2669  			index := len(bitcoinExchangeTxns) - 1 - ii
  2670  			burnTxn := bitcoinExchangeTxns[index]
  2671  			blockHeight := chain.blockTip().Height + 1
  2672  			err := utxoView.DisconnectTransaction(burnTxn, burnTxn.Hash(), utxoOpsList[index], blockHeight)
  2673  			require.NoError(err)
  2674  		}
  2675  
  2676  		// Flushing the view after applying and rolling back should work.
  2677  		require.NoError(utxoView.FlushToDb())
  2678  	}
  2679  
  2680  	// The balances according to the db after applying and unapplying all the
  2681  	// transactions to a view with a flush at the end should be zero.
  2682  	{
  2683  		utxoEntries, err := chain.GetSpendableUtxosForPublicKey(pkBytes1, nil, nil)
  2684  		require.NoError(err)
  2685  		require.Equal(0, len(utxoEntries))
  2686  	}
  2687  	{
  2688  		utxoEntries, err := chain.GetSpendableUtxosForPublicKey(pkBytes2, nil, nil)
  2689  		require.NoError(err)
  2690  		require.Equal(0, len(utxoEntries))
  2691  	}
  2692  	{
  2693  		utxoEntries, err := chain.GetSpendableUtxosForPublicKey(pkBytes3, nil, nil)
  2694  		require.NoError(err)
  2695  		require.Equal(0, len(utxoEntries))
  2696  	}
  2697  
  2698  	// Running all the transactions through the mempool should work and result
  2699  	// in all of them being added.
  2700  	{
  2701  		for _, burnTxn := range bitcoinExchangeTxns {
  2702  			// We have to remove the transactions first.
  2703  			mempool.inefficientRemoveTransaction(burnTxn)
  2704  		}
  2705  		for ii, burnTxn := range bitcoinExchangeTxns {
  2706  			require.Equal(ii, len(mempool.poolMap))
  2707  			mempoolTxsAdded, err := mempool.processTransaction(
  2708  				burnTxn, true /*allowUnconnectedTxn*/, true /*rateLimit*/, 0, /*peerID*/
  2709  				true /*verifySignatures*/)
  2710  			require.NoErrorf(err, "on index: %v", ii)
  2711  			require.Equal(1, len(mempoolTxsAdded))
  2712  		}
  2713  	}
  2714  
  2715  	// The balances according to the mempool after applying all the transactions
  2716  	// should be correct.
  2717  	{
  2718  		utxoEntries, err := chain.GetSpendableUtxosForPublicKey(pkBytes1, mempool, nil)
  2719  		require.NoError(err)
  2720  		totalBalance := uint64(0)
  2721  		for _, utxoEntry := range utxoEntries {
  2722  			totalBalance += utxoEntry.AmountNanos
  2723  		}
  2724  		assert.Equal(int64(35556076477), int64(totalBalance))
  2725  	}
  2726  	{
  2727  		utxoEntries, err := chain.GetSpendableUtxosForPublicKey(pkBytes2, mempool, nil)
  2728  		require.NoError(err)
  2729  		assert.Equal(int64(9718572674), int64(utxoEntries[0].AmountNanos))
  2730  	}
  2731  	{
  2732  		utxoEntries, err := chain.GetSpendableUtxosForPublicKey(pkBytes3, mempool, nil)
  2733  		require.NoError(err)
  2734  		totalBalance := uint64(0)
  2735  		for _, utxoEntry := range utxoEntries {
  2736  			totalBalance += utxoEntry.AmountNanos
  2737  		}
  2738  		assert.Equal(int64(9922118448), int64(totalBalance))
  2739  	}
  2740  
  2741  	// Remove all the transactions from the mempool.
  2742  	for _, burnTxn := range bitcoinExchangeTxns {
  2743  		mempool.inefficientRemoveTransaction(burnTxn)
  2744  	}
  2745  
  2746  	// The balances should be zero after removing transactions from the mempool.
  2747  	{
  2748  		utxoEntries, err := chain.GetSpendableUtxosForPublicKey(pkBytes1, mempool, nil)
  2749  		require.NoError(err)
  2750  		require.Equal(0, len(utxoEntries))
  2751  	}
  2752  	{
  2753  		utxoEntries, err := chain.GetSpendableUtxosForPublicKey(pkBytes2, mempool, nil)
  2754  		require.NoError(err)
  2755  		require.Equal(0, len(utxoEntries))
  2756  	}
  2757  	{
  2758  		utxoEntries, err := chain.GetSpendableUtxosForPublicKey(pkBytes3, mempool, nil)
  2759  		require.NoError(err)
  2760  		require.Equal(0, len(utxoEntries))
  2761  	}
  2762  
  2763  	// Re-add all of the transactions to the mempool so we can mine them into a block.
  2764  	{
  2765  		for _, burnTxn := range bitcoinExchangeTxns {
  2766  			mempoolTxsAdded, err := mempool.processTransaction(
  2767  				burnTxn, true /*allowUnconnectedTxn*/, true /*rateLimit*/, 0, /*peerID*/
  2768  				true /*verifySignatures*/)
  2769  			require.NoError(err)
  2770  			require.Equal(1, len(mempoolTxsAdded))
  2771  			//require.Equal(0, len(mempool.immatureBitcoinTxns))
  2772  		}
  2773  	}
  2774  
  2775  	miner.params = paramsCopy
  2776  	miner.BlockProducer.params = paramsCopy
  2777  	// All the txns should be in the mempool already so mining a block should put
  2778  	// all those transactions in it. Note we need to mine two blocks since the first
  2779  	// one just makes the DeSo chain time-current.
  2780  	finalBlock1, err := miner.MineAndProcessSingleBlock(0 /*threadIndex*/, mempool)
  2781  	require.NoError(err)
  2782  	_ = finalBlock1
  2783  	finalBlock2, err := miner.MineAndProcessSingleBlock(0 /*threadIndex*/, mempool)
  2784  	require.NoError(err)
  2785  
  2786  	finalBlock3, err := miner.MineAndProcessSingleBlock(0 /*threadIndex*/, mempool)
  2787  	require.NoError(err)
  2788  
  2789  	finalBlock4, err := miner.MineAndProcessSingleBlock(0 /*threadIndex*/, mempool)
  2790  	require.NoError(err)
  2791  
  2792  	// Add one for the block reward. Now we have a meaty block.
  2793  	assert.Equal(len(finalBlock1.Txns), 1)
  2794  	assert.Equal(len(finalBlock2.Txns), 14)
  2795  	assert.Equal(len(finalBlock3.Txns), 1)
  2796  	require.Equal(len(finalBlock4.Txns), 1)
  2797  
  2798  	// The balances after mining the block should line up.
  2799  	{
  2800  		utxoEntries, err := chain.GetSpendableUtxosForPublicKey(pkBytes1, nil, nil)
  2801  		require.NoError(err)
  2802  		totalBalance := uint64(0)
  2803  		for _, utxoEntry := range utxoEntries {
  2804  			totalBalance += utxoEntry.AmountNanos
  2805  		}
  2806  		assert.Equal(int64(35556076477), int64(totalBalance))
  2807  	}
  2808  	{
  2809  		utxoEntries, err := chain.GetSpendableUtxosForPublicKey(pkBytes2, nil, nil)
  2810  		require.NoError(err)
  2811  		assert.Equal(int64(9718572674), int64(utxoEntries[0].AmountNanos))
  2812  	}
  2813  	{
  2814  		utxoEntries, err := chain.GetSpendableUtxosForPublicKey(pkBytes3, nil, nil)
  2815  		require.NoError(err)
  2816  		totalBalance := uint64(0)
  2817  		for _, utxoEntry := range utxoEntries {
  2818  			totalBalance += utxoEntry.AmountNanos
  2819  		}
  2820  		assert.Equal(int64(9922118448), int64(totalBalance))
  2821  	}
  2822  
  2823  	// Roll back the blocks and make sure we don't hit any errors.
  2824  	{
  2825  		utxoView, err := NewUtxoView(db, paramsCopy, nil)
  2826  		require.NoError(err)
  2827  
  2828  		{
  2829  			// Fetch the utxo operations for the block we're detaching. We need these
  2830  			// in order to be able to detach the block.
  2831  			hash, err := finalBlock4.Header.Hash()
  2832  			require.NoError(err)
  2833  			utxoOps, err := GetUtxoOperationsForBlock(db, hash)
  2834  			require.NoError(err)
  2835  
  2836  			// Compute the hashes for all the transactions.
  2837  			txHashes, err := ComputeTransactionHashes(finalBlock4.Txns)
  2838  			require.NoError(err)
  2839  			require.NoError(utxoView.DisconnectBlock(finalBlock4, txHashes, utxoOps))
  2840  		}
  2841  		{
  2842  			// Fetch the utxo operations for the block we're detaching. We need these
  2843  			// in order to be able to detach the block.
  2844  			hash, err := finalBlock3.Header.Hash()
  2845  			require.NoError(err)
  2846  			utxoOps, err := GetUtxoOperationsForBlock(db, hash)
  2847  			require.NoError(err)
  2848  
  2849  			// Compute the hashes for all the transactions.
  2850  			txHashes, err := ComputeTransactionHashes(finalBlock3.Txns)
  2851  			require.NoError(err)
  2852  			require.NoError(utxoView.DisconnectBlock(finalBlock3, txHashes, utxoOps))
  2853  		}
  2854  		{
  2855  			// Fetch the utxo operations for the block we're detaching. We need these
  2856  			// in order to be able to detach the block.
  2857  			hash, err := finalBlock2.Header.Hash()
  2858  			require.NoError(err)
  2859  			utxoOps, err := GetUtxoOperationsForBlock(db, hash)
  2860  			require.NoError(err)
  2861  
  2862  			// Compute the hashes for all the transactions.
  2863  			txHashes, err := ComputeTransactionHashes(finalBlock2.Txns)
  2864  			require.NoError(err)
  2865  			require.NoError(utxoView.DisconnectBlock(finalBlock2, txHashes, utxoOps))
  2866  		}
  2867  		{
  2868  			// Fetch the utxo operations for the block we're detaching. We need these
  2869  			// in order to be able to detach the block.
  2870  			hash, err := finalBlock1.Header.Hash()
  2871  			require.NoError(err)
  2872  			utxoOps, err := GetUtxoOperationsForBlock(db, hash)
  2873  			require.NoError(err)
  2874  
  2875  			// Compute the hashes for all the transactions.
  2876  			txHashes, err := ComputeTransactionHashes(finalBlock1.Txns)
  2877  			require.NoError(err)
  2878  			require.NoError(utxoView.DisconnectBlock(finalBlock1, txHashes, utxoOps))
  2879  		}
  2880  
  2881  		// Flushing the view after applying and rolling back should work.
  2882  		require.NoError(utxoView.FlushToDb())
  2883  	}
  2884  
  2885  	// The balances according to the db after applying and unapplying all the
  2886  	// transactions to a view with a flush at the end should be zero.
  2887  	{
  2888  		utxoEntries, err := chain.GetSpendableUtxosForPublicKey(pkBytes1, nil, nil)
  2889  		require.NoError(err)
  2890  		require.Equal(0, len(utxoEntries))
  2891  	}
  2892  	{
  2893  		utxoEntries, err := chain.GetSpendableUtxosForPublicKey(pkBytes2, nil, nil)
  2894  		require.NoError(err)
  2895  		require.Equal(0, len(utxoEntries))
  2896  	}
  2897  	{
  2898  		utxoEntries, err := chain.GetSpendableUtxosForPublicKey(pkBytes3, nil, nil)
  2899  		require.NoError(err)
  2900  		require.Equal(0, len(utxoEntries))
  2901  	}
  2902  
  2903  	_, _, _, _, _, _ = db, mempool, miner, bitcoinBlocks, bitcoinHeaders, bitcoinHeaderHeights
  2904  }
  2905  
  2906  func TestUpdateExchangeRate(t *testing.T) {
  2907  	// Set up a blockchain
  2908  	assert := assert.New(t)
  2909  	require := require.New(t)
  2910  	_, _ = assert, require
  2911  
  2912  	chain, params, db := NewLowDifficultyBlockchain()
  2913  	mempool, miner := NewTestMiner(t, chain, params, true /*isSender*/)
  2914  	_, _ = mempool, miner
  2915  
  2916  	// Set the founder equal to the moneyPk
  2917  	params.ParamUpdaterPublicKeys = make(map[PkMapKey]bool)
  2918  	params.ParamUpdaterPublicKeys[MakePkMapKey(MustBase58CheckDecode(moneyPkString))] = true
  2919  
  2920  	// Send money to m0 from moneyPk
  2921  	_, _, _ = _doBasicTransferWithViewFlush(
  2922  		t, chain, db, params, moneyPkString, m0Pub,
  2923  		moneyPrivString, 6*NanosPerUnit /*amount to send*/, 11 /*feerate*/)
  2924  
  2925  	// Should fail when founder key is not equal to moneyPk
  2926  	{
  2927  		newUSDCentsPerBitcoin := uint64(27000 * 100)
  2928  		_, _, _, err := _updateUSDCentsPerBitcoinExchangeRate(
  2929  			t, chain, db, params, 100, /*feeRateNanosPerKB*/
  2930  			m0Pub,
  2931  			m0Priv,
  2932  			newUSDCentsPerBitcoin)
  2933  		require.Error(err)
  2934  		require.Contains(err.Error(), RuleErrorUserNotAuthorizedToUpdateExchangeRate)
  2935  	}
  2936  
  2937  	// Should pass when founder key is equal to moneyPk
  2938  	var updateExchangeRateTxn *MsgDeSoTxn
  2939  	var err error
  2940  	{
  2941  		newUSDCentsPerBitcoin := uint64(27000 * 100)
  2942  		_, updateExchangeRateTxn, _, err = _updateUSDCentsPerBitcoinExchangeRate(
  2943  			t, chain, db, params, 100, /*feeRateNanosPerKB*/
  2944  			moneyPkString,
  2945  			moneyPrivString,
  2946  			newUSDCentsPerBitcoin)
  2947  		require.NoError(err)
  2948  
  2949  		utxoView, err := NewUtxoView(db, params, nil)
  2950  		require.NoError(err)
  2951  		txnSize := getTxnSize(*updateExchangeRateTxn)
  2952  		blockHeight := chain.blockTip().Height + 1
  2953  		utxoOps, totalInput, totalOutput, fees, err :=
  2954  			utxoView.ConnectTransaction(updateExchangeRateTxn,
  2955  				updateExchangeRateTxn.Hash(), txnSize, blockHeight, true, /*verifySignature*/
  2956  				false /*ignoreUtxos*/)
  2957  		require.NoError(err)
  2958  		_, _, _, _ = utxoOps, totalInput, totalOutput, fees
  2959  		require.NoError(utxoView.FlushToDb())
  2960  
  2961  		// Check the balance of the updater after this txn
  2962  		require.NotEqual(0, _getBalance(t, chain, nil, moneyPkString))
  2963  	}
  2964  }