From 1075ad3fa0d9b7b31a5952d068f9aff214280a09 Mon Sep 17 00:00:00 2001 From: Josh Rickmar Date: Thu, 19 Jan 2017 15:24:57 -0500 Subject: [PATCH] make votingpool tests compile and pass --- votingpool/common_test.go | 7 +- votingpool/db_wb_test.go | 98 +++--- votingpool/example_test.go | 346 +++++++++---------- votingpool/factory_test.go | 202 ++++++------ votingpool/input_selection_wb_test.go | 150 +++++---- votingpool/internal_test.go | 37 +-- votingpool/pool_test.go | 328 +++++++++++++----- votingpool/pool_wb_test.go | 116 ++++--- votingpool/withdrawal_test.go | 34 +- votingpool/withdrawal_wb_test.go | 456 +++++++++++++++++++------- 10 files changed, 1145 insertions(+), 629 deletions(-) diff --git a/votingpool/common_test.go b/votingpool/common_test.go index d8c5a73..b4059a9 100644 --- a/votingpool/common_test.go +++ b/votingpool/common_test.go @@ -11,7 +11,8 @@ import ( "testing" "github.com/btcsuite/btclog" - "github.com/roasbeef/btcwallet/waddrmgr" + "github.com/btcsuite/btcwallet/waddrmgr" + "github.com/btcsuite/btcwallet/walletdb" ) func init() { @@ -39,8 +40,8 @@ func TstCheckError(t *testing.T, testName string, gotErr error, wantErrCode Erro // TstRunWithManagerUnlocked calls the given callback with the manager unlocked, // and locks it again before returning. -func TstRunWithManagerUnlocked(t *testing.T, mgr *waddrmgr.Manager, callback func()) { - if err := mgr.Unlock(privPassphrase); err != nil { +func TstRunWithManagerUnlocked(t *testing.T, mgr *waddrmgr.Manager, addrmgrNs walletdb.ReadBucket, callback func()) { + if err := mgr.Unlock(addrmgrNs, privPassphrase); err != nil { t.Fatal(err) } defer mgr.Lock() diff --git a/votingpool/db_wb_test.go b/votingpool/db_wb_test.go index 29f8b5c..7521a7b 100644 --- a/votingpool/db_wb_test.go +++ b/votingpool/db_wb_test.go @@ -13,24 +13,24 @@ import ( ) func TestPutUsedAddrHash(t *testing.T) { - tearDown, _, pool := TstCreatePool(t) + tearDown, db, pool := TstCreatePool(t) defer tearDown() dummyHash := bytes.Repeat([]byte{0x09}, 10) - err := pool.namespace.Update( - func(tx walletdb.Tx) error { - return putUsedAddrHash(tx, pool.ID, 0, 0, 0, dummyHash) - }) + err := walletdb.Update(db, func(tx walletdb.ReadWriteTx) error { + ns, _ := TstRWNamespaces(tx) + return putUsedAddrHash(ns, pool.ID, 0, 0, 0, dummyHash) + }) if err != nil { t.Fatal(err) } var storedHash []byte - err = pool.namespace.View( - func(tx walletdb.Tx) error { - storedHash = getUsedAddrHash(tx, pool.ID, 0, 0, 0) - return nil - }) + err = walletdb.View(db, func(tx walletdb.ReadTx) error { + ns, _ := TstRNamespaces(tx) + storedHash = getUsedAddrHash(ns, pool.ID, 0, 0, 0) + return nil + }) if err != nil { t.Fatal(err) } @@ -40,42 +40,52 @@ func TestPutUsedAddrHash(t *testing.T) { } func TestGetMaxUsedIdx(t *testing.T) { - tearDown, _, pool := TstCreatePool(t) + tearDown, db, pool := TstCreatePool(t) defer tearDown() - var err error - pool.namespace.Update( - func(tx walletdb.Tx) error { - for i, idx := range []int{0, 7, 9, 3001, 41, 500, 6} { - dummyHash := bytes.Repeat([]byte{byte(i)}, 10) - err = putUsedAddrHash(tx, pool.ID, 0, 0, Index(idx), dummyHash) - if err != nil { - t.Fatal(err) - } + err := walletdb.Update(db, func(tx walletdb.ReadWriteTx) error { + ns, _ := TstRWNamespaces(tx) + for i, idx := range []int{0, 7, 9, 3001, 41, 500, 6} { + dummyHash := bytes.Repeat([]byte{byte(i)}, 10) + err := putUsedAddrHash(ns, pool.ID, 0, 0, Index(idx), dummyHash) + if err != nil { + return err } - return nil - }) + } + return nil + }) + if err != nil { + t.Fatal(err) + } var maxIdx Index - pool.namespace.View( - func(tx walletdb.Tx) error { - maxIdx, err = getMaxUsedIdx(tx, pool.ID, 0, 0) - if err != nil { - t.Fatal(err) - } - return nil - }) + err = walletdb.View(db, func(tx walletdb.ReadTx) error { + ns, _ := TstRNamespaces(tx) + var err error + maxIdx, err = getMaxUsedIdx(ns, pool.ID, 0, 0) + return err + }) + if err != nil { + t.Fatal(err) + } if maxIdx != Index(3001) { t.Fatalf("Wrong max idx; got %d, want %d", maxIdx, Index(3001)) } } func TestWithdrawalSerialization(t *testing.T) { - tearDown, _, pool := TstCreatePool(t) + tearDown, db, pool := TstCreatePool(t) defer tearDown() + dbtx, err := db.BeginReadWriteTx() + if err != nil { + t.Fatal(err) + } + defer dbtx.Commit() + ns, addrmgrNs := TstRWNamespaces(dbtx) + roundID := uint32(0) - wi := createAndFulfillWithdrawalRequests(t, pool, roundID) + wi := createAndFulfillWithdrawalRequests(t, dbtx, pool, roundID) serialized, err := serializeWithdrawal(wi.requests, wi.startAddress, wi.lastSeriesID, wi.changeStart, wi.dustThreshold, wi.status) @@ -84,8 +94,8 @@ func TestWithdrawalSerialization(t *testing.T) { } var wInfo *withdrawalInfo - TstRunWithManagerUnlocked(t, pool.Manager(), func() { - wInfo, err = deserializeWithdrawal(pool, serialized) + TstRunWithManagerUnlocked(t, pool.Manager(), addrmgrNs, func() { + wInfo, err = deserializeWithdrawal(pool, ns, addrmgrNs, serialized) if err != nil { t.Fatal(err) } @@ -115,26 +125,26 @@ func TestWithdrawalSerialization(t *testing.T) { } func TestPutAndGetWithdrawal(t *testing.T) { - tearDown, _, pool := TstCreatePool(t) + tearDown, db, _ := TstCreatePool(t) defer tearDown() serialized := bytes.Repeat([]byte{1}, 10) poolID := []byte{0x00} roundID := uint32(0) - err := pool.namespace.Update( - func(tx walletdb.Tx) error { - return putWithdrawal(tx, poolID, roundID, serialized) - }) + err := walletdb.Update(db, func(tx walletdb.ReadWriteTx) error { + ns, _ := TstRWNamespaces(tx) + return putWithdrawal(ns, poolID, roundID, serialized) + }) if err != nil { t.Fatal(err) } var retrieved []byte - err = pool.namespace.View( - func(tx walletdb.Tx) error { - retrieved = getWithdrawal(tx, poolID, roundID) - return nil - }) + err = walletdb.View(db, func(tx walletdb.ReadTx) error { + ns, _ := TstRNamespaces(tx) + retrieved = getWithdrawal(ns, poolID, roundID) + return nil + }) if err != nil { t.Fatal(err) } diff --git a/votingpool/example_test.go b/votingpool/example_test.go index 1e87b60..c9eae91 100644 --- a/votingpool/example_test.go +++ b/votingpool/example_test.go @@ -40,13 +40,13 @@ var ( fastScrypt = &waddrmgr.ScryptOptions{N: 16, R: 8, P: 1} ) -func createWaddrmgr(ns walletdb.Namespace, params *chaincfg.Params) (*waddrmgr.Manager, error) { +func createWaddrmgr(ns walletdb.ReadWriteBucket, params *chaincfg.Params) (*waddrmgr.Manager, error) { err := waddrmgr.Create(ns, seed, pubPassphrase, privPassphrase, params, fastScrypt) if err != nil { return nil, err } - return waddrmgr.Open(ns, pubPassphrase, params, nil) + return waddrmgr.Open(ns, pubPassphrase, params) } func ExampleCreate() { @@ -59,8 +59,15 @@ func ExampleCreate() { } defer dbTearDown() + dbtx, err := db.BeginReadWriteTx() + if err != nil { + fmt.Println(err) + return + } + defer dbtx.Commit() + // Create a new walletdb namespace for the address manager. - mgrNamespace, err := db.Namespace([]byte("waddrmgr")) + mgrNamespace, err := dbtx.CreateTopLevelBucket([]byte("waddrmgr")) if err != nil { fmt.Println(err) return @@ -74,7 +81,7 @@ func ExampleCreate() { } // Create a walletdb namespace for votingpools. - vpNamespace, err := db.Namespace([]byte("votingpool")) + vpNamespace, err := dbtx.CreateTopLevelBucket([]byte("votingpool")) if err != nil { fmt.Println(err) return @@ -96,41 +103,43 @@ func ExampleCreate() { func Example_depositAddress() { // Create the address manager and votingpool DB namespace. See the example // for the Create() function for more info on how this is done. - mgr, vpNamespace, tearDownFunc, err := exampleCreateMgrAndDBNamespace() - if err != nil { - fmt.Println(err) - return - } - defer tearDownFunc() + teardown, db, mgr := exampleCreateDBAndMgr() + defer teardown() - // Create the voting pool. - pool, err := votingpool.Create(vpNamespace, mgr, []byte{0x00}) - if err != nil { - fmt.Println(err) - return - } + err := walletdb.Update(db, func(tx walletdb.ReadWriteTx) error { + ns := votingpoolNamespace(tx) - // Create a 2-of-3 series. - seriesID := uint32(1) - requiredSignatures := uint32(2) - pubKeys := []string{ - "xpub661MyMwAqRbcFDDrR5jY7LqsRioFDwg3cLjc7tML3RRcfYyhXqqgCH5SqMSQdpQ1Xh8EtVwcfm8psD8zXKPcRaCVSY4GCqbb3aMEs27GitE", - "xpub661MyMwAqRbcGsxyD8hTmJFtpmwoZhy4NBBVxzvFU8tDXD2ME49A6JjQCYgbpSUpHGP1q4S2S1Pxv2EqTjwfERS5pc9Q2yeLkPFzSgRpjs9", - "xpub661MyMwAqRbcEbc4uYVXvQQpH9L3YuZLZ1gxCmj59yAhNy33vXxbXadmRpx5YZEupNSqWRrR7PqU6duS2FiVCGEiugBEa5zuEAjsyLJjKCh", - } - err = pool.CreateSeries(votingpool.CurrentVersion, seriesID, requiredSignatures, pubKeys) - if err != nil { - fmt.Println(err) - return - } + // Create the voting pool. + pool, err := votingpool.Create(ns, mgr, []byte{0x00}) + if err != nil { + return err + } - // Create a deposit address. - addr, err := pool.DepositScriptAddress(seriesID, votingpool.Branch(0), votingpool.Index(1)) + // Create a 2-of-3 series. + seriesID := uint32(1) + requiredSignatures := uint32(2) + pubKeys := []string{ + "xpub661MyMwAqRbcFDDrR5jY7LqsRioFDwg3cLjc7tML3RRcfYyhXqqgCH5SqMSQdpQ1Xh8EtVwcfm8psD8zXKPcRaCVSY4GCqbb3aMEs27GitE", + "xpub661MyMwAqRbcGsxyD8hTmJFtpmwoZhy4NBBVxzvFU8tDXD2ME49A6JjQCYgbpSUpHGP1q4S2S1Pxv2EqTjwfERS5pc9Q2yeLkPFzSgRpjs9", + "xpub661MyMwAqRbcEbc4uYVXvQQpH9L3YuZLZ1gxCmj59yAhNy33vXxbXadmRpx5YZEupNSqWRrR7PqU6duS2FiVCGEiugBEa5zuEAjsyLJjKCh", + } + err = pool.CreateSeries(ns, votingpool.CurrentVersion, seriesID, requiredSignatures, pubKeys) + if err != nil { + return err + } + + // Create a deposit address. + addr, err := pool.DepositScriptAddress(seriesID, votingpool.Branch(0), votingpool.Index(1)) + if err != nil { + return err + } + fmt.Println("Generated deposit address:", addr.EncodeAddress()) + return nil + }) if err != nil { fmt.Println(err) return } - fmt.Println("Generated deposit address:", addr.EncodeAddress()) // Output: // Generated deposit address: 3QTzpc9d3tTbNLJLB7xwt87nWM38boAhAw @@ -141,30 +150,27 @@ func Example_depositAddress() { func Example_empowerSeries() { // Create the address manager and votingpool DB namespace. See the example // for the Create() function for more info on how this is done. - mgr, vpNamespace, tearDownFunc, err := exampleCreateMgrAndDBNamespace() - if err != nil { - fmt.Println(err) - return - } - defer tearDownFunc() + teardown, db, mgr := exampleCreateDBAndMgr() + defer teardown() // Create a pool and a series. See the DepositAddress example for more info // on how this is done. - pool, seriesID, err := exampleCreatePoolAndSeries(mgr, vpNamespace) - if err != nil { - fmt.Println(err) - return - } + pool, seriesID := exampleCreatePoolAndSeries(db, mgr) - // Now empower the series with one of its private keys. Notice that in order - // to do that we need to unlock the address manager. - if err := mgr.Unlock(privPassphrase); err != nil { - fmt.Println(err) - return - } - defer mgr.Lock() - privKey := "xprv9s21ZrQH143K2j9PK4CXkCu8sgxkpUxCF7p1KVwiV5tdnkeYzJXReUkxz5iB2FUzTXC1L15abCDG4RMxSYT5zhm67uvsnLYxuDhZfoFcB6a" - err = pool.EmpowerSeries(seriesID, privKey) + err := walletdb.Update(db, func(tx walletdb.ReadWriteTx) error { + ns := votingpoolNamespace(tx) + addrmgrNs := addrmgrNamespace(tx) + + // Now empower the series with one of its private keys. Notice that in order + // to do that we need to unlock the address manager. + err := mgr.Unlock(addrmgrNs, privPassphrase) + if err != nil { + return err + } + defer mgr.Lock() + privKey := "xprv9s21ZrQH143K2j9PK4CXkCu8sgxkpUxCF7p1KVwiV5tdnkeYzJXReUkxz5iB2FUzTXC1L15abCDG4RMxSYT5zhm67uvsnLYxuDhZfoFcB6a" + return pool.EmpowerSeries(ns, seriesID, privKey) + }) if err != nil { fmt.Println(err) return @@ -178,70 +184,67 @@ func Example_empowerSeries() { func Example_startWithdrawal() { // Create the address manager and votingpool DB namespace. See the example // for the Create() function for more info on how this is done. - mgr, vpNamespace, tearDownFunc, err := exampleCreateMgrAndDBNamespace() - if err != nil { - fmt.Println(err) - return - } - defer tearDownFunc() + teardown, db, mgr := exampleCreateDBAndMgr() + defer teardown() // Create a pool and a series. See the DepositAddress example for more info // on how this is done. - pool, seriesID, err := exampleCreatePoolAndSeries(mgr, vpNamespace) - if err != nil { - fmt.Println(err) - return - } + pool, seriesID := exampleCreatePoolAndSeries(db, mgr) - // Unlock the manager - if err := mgr.Unlock(privPassphrase); err != nil { - fmt.Println(err) - return - } - defer mgr.Lock() + err := walletdb.Update(db, func(tx walletdb.ReadWriteTx) error { + ns := votingpoolNamespace(tx) + addrmgrNs := addrmgrNamespace(tx) + txmgrNs := txmgrNamespace(tx) - addr, _ := btcutil.DecodeAddress("1MirQ9bwyQcGVJPwKUgapu5ouK2E2Ey4gX", mgr.ChainParams()) - pkScript, _ := txscript.PayToAddrScript(addr) - requests := []votingpool.OutputRequest{ - { - PkScript: pkScript, - Address: addr, - Amount: 1e6, - Server: "server-id", - Transaction: 123}, - } - changeStart, err := pool.ChangeAddress(seriesID, votingpool.Index(0)) + // Create the transaction store for later use. + txstore := exampleCreateTxStore(txmgrNs) + + // Unlock the manager + err := mgr.Unlock(addrmgrNs, privPassphrase) + if err != nil { + return err + } + defer mgr.Lock() + + addr, _ := btcutil.DecodeAddress("1MirQ9bwyQcGVJPwKUgapu5ouK2E2Ey4gX", mgr.ChainParams()) + pkScript, _ := txscript.PayToAddrScript(addr) + requests := []votingpool.OutputRequest{ + { + PkScript: pkScript, + Address: addr, + Amount: 1e6, + Server: "server-id", + Transaction: 123, + }, + } + changeStart, err := pool.ChangeAddress(seriesID, votingpool.Index(0)) + if err != nil { + return err + } + // This is only needed because we have not used any deposit addresses from + // the series, and we cannot create a WithdrawalAddress for an unused + // branch/idx pair. + err = pool.EnsureUsedAddr(ns, addrmgrNs, seriesID, votingpool.Branch(1), votingpool.Index(0)) + if err != nil { + return err + } + startAddr, err := pool.WithdrawalAddress(ns, addrmgrNs, seriesID, votingpool.Branch(1), votingpool.Index(0)) + if err != nil { + return err + } + lastSeriesID := seriesID + dustThreshold := btcutil.Amount(1e4) + currentBlock := int32(19432) + roundID := uint32(0) + _, err = pool.StartWithdrawal(ns, addrmgrNs, + roundID, requests, *startAddr, lastSeriesID, *changeStart, txstore, txmgrNs, currentBlock, + dustThreshold) + return err + }) if err != nil { fmt.Println(err) return } - // This is only needed because we have not used any deposit addresses from - // the series, and we cannot create a WithdrawalAddress for an unused - // branch/idx pair. - if err = pool.EnsureUsedAddr(seriesID, votingpool.Branch(1), votingpool.Index(0)); err != nil { - fmt.Println(err) - return - } - startAddr, err := pool.WithdrawalAddress(seriesID, votingpool.Branch(1), votingpool.Index(0)) - if err != nil { - fmt.Println(err) - return - } - lastSeriesID := seriesID - dustThreshold := btcutil.Amount(1e4) - currentBlock := int32(19432) - roundID := uint32(0) - txstore, tearDownFunc, err := exampleCreateTxStore() - if err != nil { - fmt.Println(err) - return - } - _, err = pool.StartWithdrawal( - roundID, requests, *startAddr, lastSeriesID, *changeStart, txstore, currentBlock, - dustThreshold) - if err != nil { - fmt.Println(err) - } // Output: // @@ -263,86 +266,99 @@ func createWalletDB() (walletdb.DB, func(), error) { return db, dbTearDown, nil } -func exampleCreateMgrAndDBNamespace() (*waddrmgr.Manager, walletdb.Namespace, func(), error) { +var ( + addrmgrNamespaceKey = []byte("addrmgr") + txmgrNamespaceKey = []byte("txmgr") + votingpoolNamespaceKey = []byte("votingpool") +) + +func addrmgrNamespace(dbtx walletdb.ReadWriteTx) walletdb.ReadWriteBucket { + return dbtx.ReadWriteBucket(addrmgrNamespaceKey) +} + +func txmgrNamespace(dbtx walletdb.ReadWriteTx) walletdb.ReadWriteBucket { + return dbtx.ReadWriteBucket(txmgrNamespaceKey) +} + +func votingpoolNamespace(dbtx walletdb.ReadWriteTx) walletdb.ReadWriteBucket { + return dbtx.ReadWriteBucket(votingpoolNamespaceKey) +} + +func exampleCreateDBAndMgr() (teardown func(), db walletdb.DB, mgr *waddrmgr.Manager) { db, dbTearDown, err := createWalletDB() if err != nil { - return nil, nil, nil, err + panic(err) } // Create a new walletdb namespace for the address manager. - mgrNamespace, err := db.Namespace([]byte("waddrmgr")) + err = walletdb.Update(db, func(tx walletdb.ReadWriteTx) error { + addrmgrNs, err := tx.CreateTopLevelBucket(addrmgrNamespaceKey) + if err != nil { + return err + } + _, err = tx.CreateTopLevelBucket(votingpoolNamespaceKey) + if err != nil { + return err + } + _, err = tx.CreateTopLevelBucket(txmgrNamespaceKey) + if err != nil { + return err + } + // Create the address manager + mgr, err = createWaddrmgr(addrmgrNs, &chaincfg.MainNetParams) + return err + }) if err != nil { dbTearDown() - return nil, nil, nil, err + panic(err) } - // Create the address manager - mgr, err := createWaddrmgr(mgrNamespace, &chaincfg.MainNetParams) - if err != nil { - dbTearDown() - return nil, nil, nil, err - } - - tearDownFunc := func() { + teardown = func() { mgr.Close() dbTearDown() } - // Create a walletdb namespace for votingpools. - vpNamespace, err := db.Namespace([]byte("votingpool")) - if err != nil { - tearDownFunc() - return nil, nil, nil, err - } - return mgr, vpNamespace, tearDownFunc, nil + return teardown, db, mgr } -func exampleCreatePoolAndSeries(mgr *waddrmgr.Manager, vpNamespace walletdb.Namespace) ( - *votingpool.Pool, uint32, error) { - pool, err := votingpool.Create(vpNamespace, mgr, []byte{0x00}) +func exampleCreatePoolAndSeries(db walletdb.DB, mgr *waddrmgr.Manager) (pool *votingpool.Pool, seriesID uint32) { + err := walletdb.Update(db, func(tx walletdb.ReadWriteTx) error { + ns := votingpoolNamespace(tx) + var err error + pool, err = votingpool.Create(ns, mgr, []byte{0x00}) + if err != nil { + return err + } + + // Create a 2-of-3 series. + seriesID = uint32(1) + requiredSignatures := uint32(2) + pubKeys := []string{ + "xpub661MyMwAqRbcFDDrR5jY7LqsRioFDwg3cLjc7tML3RRcfYyhXqqgCH5SqMSQdpQ1Xh8EtVwcfm8psD8zXKPcRaCVSY4GCqbb3aMEs27GitE", + "xpub661MyMwAqRbcGsxyD8hTmJFtpmwoZhy4NBBVxzvFU8tDXD2ME49A6JjQCYgbpSUpHGP1q4S2S1Pxv2EqTjwfERS5pc9Q2yeLkPFzSgRpjs9", + "xpub661MyMwAqRbcEbc4uYVXvQQpH9L3YuZLZ1gxCmj59yAhNy33vXxbXadmRpx5YZEupNSqWRrR7PqU6duS2FiVCGEiugBEa5zuEAjsyLJjKCh", + } + err = pool.CreateSeries(ns, votingpool.CurrentVersion, seriesID, requiredSignatures, pubKeys) + if err != nil { + return err + } + return pool.ActivateSeries(ns, seriesID) + }) if err != nil { - return nil, 0, err + panic(err) } - // Create a 2-of-3 series. - seriesID := uint32(1) - requiredSignatures := uint32(2) - pubKeys := []string{ - "xpub661MyMwAqRbcFDDrR5jY7LqsRioFDwg3cLjc7tML3RRcfYyhXqqgCH5SqMSQdpQ1Xh8EtVwcfm8psD8zXKPcRaCVSY4GCqbb3aMEs27GitE", - "xpub661MyMwAqRbcGsxyD8hTmJFtpmwoZhy4NBBVxzvFU8tDXD2ME49A6JjQCYgbpSUpHGP1q4S2S1Pxv2EqTjwfERS5pc9Q2yeLkPFzSgRpjs9", - "xpub661MyMwAqRbcEbc4uYVXvQQpH9L3YuZLZ1gxCmj59yAhNy33vXxbXadmRpx5YZEupNSqWRrR7PqU6duS2FiVCGEiugBEa5zuEAjsyLJjKCh", - } - err = pool.CreateSeries(votingpool.CurrentVersion, seriesID, requiredSignatures, pubKeys) - if err != nil { - return nil, 0, err - } - err = pool.ActivateSeries(seriesID) - if err != nil { - return nil, 0, err - } - return pool, seriesID, nil + return pool, seriesID } -func exampleCreateTxStore() (*wtxmgr.Store, func(), error) { - dir, err := ioutil.TempDir("", "pool_test_txstore") +func exampleCreateTxStore(ns walletdb.ReadWriteBucket) *wtxmgr.Store { + err := wtxmgr.Create(ns) if err != nil { - return nil, nil, err + panic(err) } - db, err := walletdb.Create("bdb", filepath.Join(dir, "txstore.db")) + s, err := wtxmgr.Open(ns, &chaincfg.MainNetParams) if err != nil { - return nil, nil, err + panic(err) } - wtxmgrNamespace, err := db.Namespace([]byte("testtxstore")) - if err != nil { - return nil, nil, err - } - err = wtxmgr.Create(wtxmgrNamespace) - if err != nil { - return nil, nil, err - } - s, err := wtxmgr.Open(wtxmgrNamespace, &chaincfg.MainNetParams) - if err != nil { - return nil, nil, err - } - return s, func() { os.RemoveAll(dir) }, nil + return s } diff --git a/votingpool/factory_test.go b/votingpool/factory_test.go index 21f0d74..ca00df7 100644 --- a/votingpool/factory_test.go +++ b/votingpool/factory_test.go @@ -53,10 +53,10 @@ func getUniqueID() uint32 { } // createWithdrawalTx creates a withdrawalTx with the given input and output amounts. -func createWithdrawalTx(t *testing.T, pool *Pool, inputAmounts []int64, outputAmounts []int64) *withdrawalTx { +func createWithdrawalTx(t *testing.T, dbtx walletdb.ReadWriteTx, pool *Pool, inputAmounts []int64, outputAmounts []int64) *withdrawalTx { net := pool.Manager().ChainParams() tx := newWithdrawalTx(defaultTxOptions) - _, credits := TstCreateCreditsOnNewSeries(t, pool, inputAmounts) + _, credits := TstCreateCreditsOnNewSeries(t, dbtx, pool, inputAmounts) for _, c := range credits { tx.addInput(c) } @@ -99,15 +99,28 @@ func TstNewDepositScript(t *testing.T, p *Pool, seriesID uint32, branch Branch, return script } +func TstRNamespaces(tx walletdb.ReadTx) (votingpoolNs, addrmgrNs walletdb.ReadBucket) { + return tx.ReadBucket(votingpoolNamespaceKey), tx.ReadBucket(addrmgrNamespaceKey) +} + +func TstRWNamespaces(tx walletdb.ReadWriteTx) (votingpoolNs, addrmgrNs walletdb.ReadWriteBucket) { + return tx.ReadWriteBucket(votingpoolNamespaceKey), tx.ReadWriteBucket(addrmgrNamespaceKey) +} + +func TstTxStoreRWNamespace(tx walletdb.ReadWriteTx) walletdb.ReadWriteBucket { + return tx.ReadWriteBucket(txmgrNamespaceKey) +} + // TstEnsureUsedAddr ensures the addresses defined by the given series/branch and // index==0..idx are present in the set of used addresses for the given Pool. -func TstEnsureUsedAddr(t *testing.T, p *Pool, seriesID uint32, branch Branch, idx Index) []byte { - addr, err := p.getUsedAddr(seriesID, branch, idx) +func TstEnsureUsedAddr(t *testing.T, dbtx walletdb.ReadWriteTx, p *Pool, seriesID uint32, branch Branch, idx Index) []byte { + ns, addrmgrNs := TstRWNamespaces(dbtx) + addr, err := p.getUsedAddr(ns, addrmgrNs, seriesID, branch, idx) if err != nil { t.Fatal(err) } else if addr != nil { var script []byte - TstRunWithManagerUnlocked(t, p.Manager(), func() { + TstRunWithManagerUnlocked(t, p.Manager(), addrmgrNs, func() { script, err = addr.Script() }) if err != nil { @@ -115,8 +128,8 @@ func TstEnsureUsedAddr(t *testing.T, p *Pool, seriesID uint32, branch Branch, id } return script } - TstRunWithManagerUnlocked(t, p.Manager(), func() { - err = p.EnsureUsedAddr(seriesID, branch, idx) + TstRunWithManagerUnlocked(t, p.Manager(), addrmgrNs, func() { + err = p.EnsureUsedAddr(ns, addrmgrNs, seriesID, branch, idx) }) if err != nil { t.Fatal(err) @@ -124,8 +137,8 @@ func TstEnsureUsedAddr(t *testing.T, p *Pool, seriesID uint32, branch Branch, id return TstNewDepositScript(t, p, seriesID, branch, idx) } -func TstCreatePkScript(t *testing.T, p *Pool, seriesID uint32, branch Branch, idx Index) []byte { - script := TstEnsureUsedAddr(t, p, seriesID, branch, idx) +func TstCreatePkScript(t *testing.T, dbtx walletdb.ReadWriteTx, p *Pool, seriesID uint32, branch Branch, idx Index) []byte { + script := TstEnsureUsedAddr(t, dbtx, p, seriesID, branch, idx) addr, err := p.addressFor(script) if err != nil { t.Fatal(err) @@ -137,30 +150,6 @@ func TstCreatePkScript(t *testing.T, p *Pool, seriesID uint32, branch Branch, id return pkScript } -func TstCreateTxStore(t *testing.T) (store *wtxmgr.Store, tearDown func()) { - dir, err := ioutil.TempDir("", "pool_test_txstore") - if err != nil { - t.Fatalf("Failed to create txstore dir: %v", err) - } - db, err := walletdb.Create("bdb", filepath.Join(dir, "txstore.db")) - if err != nil { - t.Fatalf("Failed to create walletdb: %v", err) - } - wtxmgrNamespace, err := db.Namespace([]byte("testtxstore")) - if err != nil { - t.Fatalf("Failed to create walletdb namespace: %v", err) - } - err = wtxmgr.Create(wtxmgrNamespace) - if err != nil { - t.Fatalf("Failed to create txstore: %v", err) - } - s, err := wtxmgr.Open(wtxmgrNamespace, &chaincfg.MainNetParams) - if err != nil { - t.Fatalf("Failed to open txstore: %v", err) - } - return s, func() { os.RemoveAll(dir) } -} - type TstSeriesDef struct { ReqSigs uint32 PubKeys []string @@ -172,15 +161,16 @@ type TstSeriesDef struct { // TstCreateSeries creates a new Series for every definition in the given slice // of TstSeriesDef. If the definition includes any private keys, the Series is // empowered with them. -func TstCreateSeries(t *testing.T, pool *Pool, definitions []TstSeriesDef) { +func TstCreateSeries(t *testing.T, dbtx walletdb.ReadWriteTx, pool *Pool, definitions []TstSeriesDef) { + ns, addrmgrNs := TstRWNamespaces(dbtx) for _, def := range definitions { - err := pool.CreateSeries(CurrentVersion, def.SeriesID, def.ReqSigs, def.PubKeys) + err := pool.CreateSeries(ns, CurrentVersion, def.SeriesID, def.ReqSigs, def.PubKeys) if err != nil { t.Fatalf("Cannot creates series %d: %v", def.SeriesID, err) } - TstRunWithManagerUnlocked(t, pool.Manager(), func() { + TstRunWithManagerUnlocked(t, pool.Manager(), addrmgrNs, func() { for _, key := range def.PrivKeys { - if err := pool.EmpowerSeries(def.SeriesID, key); err != nil { + if err := pool.EmpowerSeries(ns, def.SeriesID, key); err != nil { t.Fatal(err) } } @@ -222,35 +212,31 @@ func TstCreateSeriesDef(t *testing.T, pool *Pool, reqSigs uint32, keys []*hdkeyc ReqSigs: reqSigs, SeriesID: seriesID, PubKeys: pubKeys, PrivKeys: privKeys} } -func TstCreatePoolAndTxStore(t *testing.T) (tearDown func(), pool *Pool, store *wtxmgr.Store) { - mgrTearDown, _, pool := TstCreatePool(t) - store, storeTearDown := TstCreateTxStore(t) - tearDown = func() { - mgrTearDown() - storeTearDown() - } - return tearDown, pool, store +func TstCreatePoolAndTxStore(t *testing.T) (tearDown func(), db walletdb.DB, pool *Pool, store *wtxmgr.Store) { + teardown, db, pool := TstCreatePool(t) + store = TstCreateTxStore(t, db) + return teardown, db, pool, store } // TstCreateCreditsOnNewSeries creates a new Series (with a unique ID) and a // slice of credits locked to the series' address with branch==1 and index==0. // The new Series will use a 2-of-3 configuration and will be empowered with // all of its private keys. -func TstCreateCreditsOnNewSeries(t *testing.T, pool *Pool, amounts []int64) (uint32, []credit) { +func TstCreateCreditsOnNewSeries(t *testing.T, dbtx walletdb.ReadWriteTx, pool *Pool, amounts []int64) (uint32, []credit) { masters := []*hdkeychain.ExtendedKey{ TstCreateMasterKey(t, bytes.Repeat(uint32ToBytes(getUniqueID()), 4)), TstCreateMasterKey(t, bytes.Repeat(uint32ToBytes(getUniqueID()), 4)), TstCreateMasterKey(t, bytes.Repeat(uint32ToBytes(getUniqueID()), 4)), } def := TstCreateSeriesDef(t, pool, 2, masters) - TstCreateSeries(t, pool, []TstSeriesDef{def}) - return def.SeriesID, TstCreateSeriesCredits(t, pool, def.SeriesID, amounts) + TstCreateSeries(t, dbtx, pool, []TstSeriesDef{def}) + return def.SeriesID, TstCreateSeriesCredits(t, dbtx, pool, def.SeriesID, amounts) } // TstCreateSeriesCredits creates a new credit for every item in the amounts // slice, locked to the given series' address with branch==1 and index==0. -func TstCreateSeriesCredits(t *testing.T, pool *Pool, seriesID uint32, amounts []int64) []credit { - addr := TstNewWithdrawalAddress(t, pool, seriesID, Branch(1), Index(0)) +func TstCreateSeriesCredits(t *testing.T, dbtx walletdb.ReadWriteTx, pool *Pool, seriesID uint32, amounts []int64) []credit { + addr := TstNewWithdrawalAddress(t, dbtx, pool, seriesID, Branch(1), Index(0)) pkScript, err := txscript.PayToAddrScript(addr.addr) if err != nil { t.Fatal(err) @@ -278,22 +264,21 @@ func TstCreateSeriesCredits(t *testing.T, pool *Pool, seriesID uint32, amounts [ // TstCreateSeriesCreditsOnStore inserts a new credit in the given store for // every item in the amounts slice. These credits are locked to the votingpool // address composed of the given seriesID, branch==1 and index==0. -func TstCreateSeriesCreditsOnStore(t *testing.T, pool *Pool, seriesID uint32, amounts []int64, +func TstCreateSeriesCreditsOnStore(t *testing.T, dbtx walletdb.ReadWriteTx, pool *Pool, seriesID uint32, amounts []int64, store *wtxmgr.Store) []credit { branch := Branch(1) idx := Index(0) - pkScript := TstCreatePkScript(t, pool, seriesID, branch, idx) + pkScript := TstCreatePkScript(t, dbtx, pool, seriesID, branch, idx) eligible := make([]credit, len(amounts)) - for i, credit := range TstCreateCreditsOnStore(t, store, pkScript, amounts) { - eligible[i] = newCredit(credit, *TstNewWithdrawalAddress(t, pool, seriesID, branch, idx)) + for i, credit := range TstCreateCreditsOnStore(t, dbtx, store, pkScript, amounts) { + eligible[i] = newCredit(credit, *TstNewWithdrawalAddress(t, dbtx, pool, seriesID, branch, idx)) } return eligible } // TstCreateCreditsOnStore inserts a new credit in the given store for // every item in the amounts slice. -func TstCreateCreditsOnStore(t *testing.T, s *wtxmgr.Store, pkScript []byte, - amounts []int64) []wtxmgr.Credit { +func TstCreateCreditsOnStore(t *testing.T, dbtx walletdb.ReadWriteTx, s *wtxmgr.Store, pkScript []byte, amounts []int64) []wtxmgr.Credit { msgTx := createMsgTx(pkScript, amounts) meta := &wtxmgr.BlockMeta{ Block: wtxmgr.Block{Height: TstInputsBlock}, @@ -304,13 +289,14 @@ func TstCreateCreditsOnStore(t *testing.T, s *wtxmgr.Store, pkScript []byte, t.Fatal(err) } - if err := s.InsertTx(rec, meta); err != nil { + txmgrNs := dbtx.ReadWriteBucket(txmgrNamespaceKey) + if err := s.InsertTx(txmgrNs, rec, meta); err != nil { t.Fatal("Failed to create inputs: ", err) } credits := make([]wtxmgr.Credit, len(msgTx.TxOut)) for i := range msgTx.TxOut { - if err := s.AddCredit(rec, meta, uint32(i), false); err != nil { + if err := s.AddCredit(txmgrNs, rec, meta, uint32(i), false); err != nil { t.Fatal("Failed to create inputs: ", err) } credits[i] = wtxmgr.Credit{ @@ -326,11 +312,16 @@ func TstCreateCreditsOnStore(t *testing.T, s *wtxmgr.Store, pkScript []byte, return credits } +var ( + addrmgrNamespaceKey = []byte("waddrmgr") + votingpoolNamespaceKey = []byte("votingpool") + txmgrNamespaceKey = []byte("testtxstore") +) + // TstCreatePool creates a Pool on a fresh walletdb and returns it. It also -// returns the pool's waddrmgr.Manager (which uses the same walletdb, but with a -// different namespace) as a convenience, and a teardown function that closes -// the Manager and removes the directory used to store the database. -func TstCreatePool(t *testing.T) (tearDownFunc func(), mgr *waddrmgr.Manager, pool *Pool) { +// returns a teardown function that closes the Manager and removes the directory +// used to store the database. +func TstCreatePool(t *testing.T) (tearDownFunc func(), db walletdb.DB, pool *Pool) { // This should be moved somewhere else eventually as not all of our tests // call this function, but right now the only option would be to have the // t.Parallel() call in each of our tests. @@ -341,40 +332,62 @@ func TstCreatePool(t *testing.T) (tearDownFunc func(), mgr *waddrmgr.Manager, po if err != nil { t.Fatalf("Failed to create db dir: %v", err) } - db, err := walletdb.Create("bdb", filepath.Join(dir, "wallet.db")) + db, err = walletdb.Create("bdb", filepath.Join(dir, "wallet.db")) if err != nil { t.Fatalf("Failed to create wallet DB: %v", err) } - mgrNamespace, err := db.Namespace([]byte("waddrmgr")) + var addrMgr *waddrmgr.Manager + err = walletdb.Update(db, func(tx walletdb.ReadWriteTx) error { + addrmgrNs, err := tx.CreateTopLevelBucket(addrmgrNamespaceKey) + if err != nil { + return err + } + votingpoolNs, err := tx.CreateTopLevelBucket(votingpoolNamespaceKey) + if err != nil { + return err + } + fastScrypt := &waddrmgr.ScryptOptions{N: 16, R: 8, P: 1} + err = waddrmgr.Create(addrmgrNs, seed, pubPassphrase, privPassphrase, + &chaincfg.MainNetParams, fastScrypt) + if err != nil { + return err + } + addrMgr, err = waddrmgr.Open(addrmgrNs, pubPassphrase, &chaincfg.MainNetParams) + if err != nil { + return err + } + pool, err = Create(votingpoolNs, addrMgr, []byte{0x00}) + return err + }) if err != nil { - t.Fatalf("Failed to create addr manager DB namespace: %v", err) - } - var fastScrypt = &waddrmgr.ScryptOptions{N: 16, R: 8, P: 1} - err = waddrmgr.Create(mgrNamespace, seed, pubPassphrase, privPassphrase, - &chaincfg.MainNetParams, fastScrypt) - if err == nil { - mgr, err = waddrmgr.Open(mgrNamespace, pubPassphrase, - &chaincfg.MainNetParams, nil) - } - if err != nil { - t.Fatalf("Failed to create addr manager: %v", err) - } - - // Create a walletdb for votingpools. - vpNamespace, err := db.Namespace([]byte("votingpool")) - if err != nil { - t.Fatalf("Failed to create VotingPool DB namespace: %v", err) - } - pool, err = Create(vpNamespace, mgr, []byte{0x00}) - if err != nil { - t.Fatalf("Voting Pool creation failed: %v", err) + t.Fatalf("Could not set up DB: %v", err) } tearDownFunc = func() { + addrMgr.Close() db.Close() - mgr.Close() os.RemoveAll(dir) } - return tearDownFunc, mgr, pool + return tearDownFunc, db, pool +} + +func TstCreateTxStore(t *testing.T, db walletdb.DB) *wtxmgr.Store { + var store *wtxmgr.Store + err := walletdb.Update(db, func(tx walletdb.ReadWriteTx) error { + txmgrNs, err := tx.CreateTopLevelBucket(txmgrNamespaceKey) + if err != nil { + return err + } + err = wtxmgr.Create(txmgrNs) + if err != nil { + return err + } + store, err = wtxmgr.Open(txmgrNs, &chaincfg.MainNetParams) + return err + }) + if err != nil { + t.Fatalf("Failed to create txmgr: %v", err) + } + return store } func TstNewOutputRequest(t *testing.T, transaction uint32, address string, amount btcutil.Amount, @@ -406,12 +419,13 @@ func TstNewWithdrawalOutput(r OutputRequest, status outputStatus, return output } -func TstNewWithdrawalAddress(t *testing.T, p *Pool, seriesID uint32, branch Branch, +func TstNewWithdrawalAddress(t *testing.T, dbtx walletdb.ReadWriteTx, p *Pool, seriesID uint32, branch Branch, index Index) (addr *WithdrawalAddress) { - TstEnsureUsedAddr(t, p, seriesID, branch, index) + TstEnsureUsedAddr(t, dbtx, p, seriesID, branch, index) + ns, addrmgrNs := TstRNamespaces(dbtx) var err error - TstRunWithManagerUnlocked(t, p.Manager(), func() { - addr, err = p.WithdrawalAddress(seriesID, branch, index) + TstRunWithManagerUnlocked(t, p.Manager(), addrmgrNs, func() { + addr, err = p.WithdrawalAddress(ns, addrmgrNs, seriesID, branch, index) }) if err != nil { t.Fatalf("Failed to get WithdrawalAddress: %v", err) @@ -431,17 +445,17 @@ func TstConstantFee(fee btcutil.Amount) func() btcutil.Amount { return func() btcutil.Amount { return fee } } -func createAndFulfillWithdrawalRequests(t *testing.T, pool *Pool, roundID uint32) withdrawalInfo { +func createAndFulfillWithdrawalRequests(t *testing.T, dbtx walletdb.ReadWriteTx, pool *Pool, roundID uint32) withdrawalInfo { params := pool.Manager().ChainParams() - seriesID, eligible := TstCreateCreditsOnNewSeries(t, pool, []int64{2e6, 4e6}) + seriesID, eligible := TstCreateCreditsOnNewSeries(t, dbtx, pool, []int64{2e6, 4e6}) requests := []OutputRequest{ TstNewOutputRequest(t, 1, "34eVkREKgvvGASZW7hkgE2uNc1yycntMK6", 3e6, params), TstNewOutputRequest(t, 2, "3PbExiaztsSYgh6zeMswC49hLUwhTQ86XG", 2e6, params), } changeStart := TstNewChangeAddress(t, pool, seriesID, 0) dustThreshold := btcutil.Amount(1e4) - startAddr := TstNewWithdrawalAddress(t, pool, seriesID, 1, 0) + startAddr := TstNewWithdrawalAddress(t, dbtx, pool, seriesID, 1, 0) lastSeriesID := seriesID w := newWithdrawal(roundID, requests, eligible, *changeStart) if err := w.fulfillRequests(); err != nil { diff --git a/votingpool/input_selection_wb_test.go b/votingpool/input_selection_wb_test.go index 1aebda4..8136968 100644 --- a/votingpool/input_selection_wb_test.go +++ b/votingpool/input_selection_wb_test.go @@ -13,6 +13,7 @@ import ( "github.com/btcsuite/btcd/chaincfg/chainhash" "github.com/btcsuite/btcd/wire" "github.com/btcsuite/btcutil" + "github.com/btcsuite/btcwallet/walletdb" "github.com/btcsuite/btcwallet/wtxmgr" ) @@ -22,35 +23,42 @@ var ( ) func TestGetEligibleInputs(t *testing.T) { - tearDown, pool, store := TstCreatePoolAndTxStore(t) + tearDown, db, pool, store := TstCreatePoolAndTxStore(t) defer tearDown() + dbtx, err := db.BeginReadWriteTx() + if err != nil { + t.Fatal(err) + } + defer dbtx.Commit() + ns, addrmgrNs := TstRWNamespaces(dbtx) + series := []TstSeriesDef{ {ReqSigs: 2, PubKeys: TstPubKeys[1:4], SeriesID: 1}, {ReqSigs: 2, PubKeys: TstPubKeys[3:6], SeriesID: 2}, } - TstCreateSeries(t, pool, series) + TstCreateSeries(t, dbtx, pool, series) scripts := append( - getPKScriptsForAddressRange(t, pool, 1, 0, 2, 0, 4), - getPKScriptsForAddressRange(t, pool, 2, 0, 2, 0, 6)...) + getPKScriptsForAddressRange(t, dbtx, pool, 1, 0, 2, 0, 4), + getPKScriptsForAddressRange(t, dbtx, pool, 2, 0, 2, 0, 6)...) // Create two eligible inputs locked to each of the PKScripts above. expNoEligibleInputs := 2 * len(scripts) eligibleAmounts := []int64{int64(dustThreshold + 1), int64(dustThreshold + 1)} var inputs []wtxmgr.Credit for i := 0; i < len(scripts); i++ { - created := TstCreateCreditsOnStore(t, store, scripts[i], eligibleAmounts) + created := TstCreateCreditsOnStore(t, dbtx, store, scripts[i], eligibleAmounts) inputs = append(inputs, created...) } - startAddr := TstNewWithdrawalAddress(t, pool, 1, 0, 0) + startAddr := TstNewWithdrawalAddress(t, dbtx, pool, 1, 0, 0) lastSeriesID := uint32(2) currentBlock := int32(TstInputsBlock + eligibleInputMinConfirmations + 1) var eligibles []credit - var err error - TstRunWithManagerUnlocked(t, pool.Manager(), func() { - eligibles, err = pool.getEligibleInputs( - store, *startAddr, lastSeriesID, dustThreshold, int32(currentBlock), + txmgrNs := dbtx.ReadBucket(txmgrNamespaceKey) + TstRunWithManagerUnlocked(t, pool.Manager(), addrmgrNs, func() { + eligibles, err = pool.getEligibleInputs(ns, addrmgrNs, + store, txmgrNs, *startAddr, lastSeriesID, dustThreshold, int32(currentBlock), eligibleInputMinConfirmations) }) if err != nil { @@ -73,29 +81,35 @@ func TestGetEligibleInputs(t *testing.T) { } func TestNextAddrWithVaryingHighestIndices(t *testing.T) { - tearDown, mgr, pool := TstCreatePool(t) + tearDown, db, pool := TstCreatePool(t) defer tearDown() + dbtx, err := db.BeginReadWriteTx() + if err != nil { + t.Fatal(err) + } + defer dbtx.Commit() + ns, addrmgrNs := TstRWNamespaces(dbtx) + series := []TstSeriesDef{ {ReqSigs: 2, PubKeys: TstPubKeys[1:4], SeriesID: 1}, } - TstCreateSeries(t, pool, series) + TstCreateSeries(t, dbtx, pool, series) stopSeriesID := uint32(2) // Populate the used addr DB for branch 0 and indices ranging from 0 to 2. - TstEnsureUsedAddr(t, pool, 1, Branch(0), 2) + TstEnsureUsedAddr(t, dbtx, pool, 1, Branch(0), 2) // Populate the used addr DB for branch 1 and indices ranging from 0 to 1. - TstEnsureUsedAddr(t, pool, 1, Branch(1), 1) + TstEnsureUsedAddr(t, dbtx, pool, 1, Branch(1), 1) // Start with the address for branch==0, index==1. - addr := TstNewWithdrawalAddress(t, pool, 1, 0, 1) + addr := TstNewWithdrawalAddress(t, dbtx, pool, 1, 0, 1) - var err error // The first call to nextAddr() should give us the address for branch==1 // and index==1. - TstRunWithManagerUnlocked(t, mgr, func() { - addr, err = nextAddr(pool, addr.seriesID, addr.branch, addr.index, stopSeriesID) + TstRunWithManagerUnlocked(t, pool.Manager(), addrmgrNs, func() { + addr, err = nextAddr(pool, ns, addrmgrNs, addr.seriesID, addr.branch, addr.index, stopSeriesID) }) if err != nil { t.Fatalf("Failed to get next address: %v", err) @@ -104,8 +118,8 @@ func TestNextAddrWithVaryingHighestIndices(t *testing.T) { // The next call should give us the address for branch==0, index==2 since // there are no used addresses for branch==2. - TstRunWithManagerUnlocked(t, mgr, func() { - addr, err = nextAddr(pool, addr.seriesID, addr.branch, addr.index, stopSeriesID) + TstRunWithManagerUnlocked(t, pool.Manager(), addrmgrNs, func() { + addr, err = nextAddr(pool, ns, addrmgrNs, addr.seriesID, addr.branch, addr.index, stopSeriesID) }) if err != nil { t.Fatalf("Failed to get next address: %v", err) @@ -114,8 +128,8 @@ func TestNextAddrWithVaryingHighestIndices(t *testing.T) { // Since the last addr for branch==1 was the one with index==1, a subsequent // call will return nil. - TstRunWithManagerUnlocked(t, mgr, func() { - addr, err = nextAddr(pool, addr.seriesID, addr.branch, addr.index, stopSeriesID) + TstRunWithManagerUnlocked(t, pool.Manager(), addrmgrNs, func() { + addr, err = nextAddr(pool, ns, addrmgrNs, addr.seriesID, addr.branch, addr.index, stopSeriesID) }) if err != nil { t.Fatalf("Failed to get next address: %v", err) @@ -126,29 +140,35 @@ func TestNextAddrWithVaryingHighestIndices(t *testing.T) { } func TestNextAddr(t *testing.T) { - tearDown, mgr, pool := TstCreatePool(t) + tearDown, db, pool := TstCreatePool(t) defer tearDown() + dbtx, err := db.BeginReadWriteTx() + if err != nil { + t.Fatal(err) + } + defer dbtx.Commit() + ns, addrmgrNs := TstRWNamespaces(dbtx) + series := []TstSeriesDef{ {ReqSigs: 2, PubKeys: TstPubKeys[1:4], SeriesID: 1}, {ReqSigs: 2, PubKeys: TstPubKeys[3:6], SeriesID: 2}, } - TstCreateSeries(t, pool, series) + TstCreateSeries(t, dbtx, pool, series) stopSeriesID := uint32(3) lastIdx := Index(10) // Populate used addresses DB with entries for seriesID==1, branch==0..3, // idx==0..10. for _, i := range []int{0, 1, 2, 3} { - TstEnsureUsedAddr(t, pool, 1, Branch(i), lastIdx) + TstEnsureUsedAddr(t, dbtx, pool, 1, Branch(i), lastIdx) } - addr := TstNewWithdrawalAddress(t, pool, 1, 0, lastIdx-1) - var err error + addr := TstNewWithdrawalAddress(t, dbtx, pool, 1, 0, lastIdx-1) // nextAddr() first increments just the branch, which ranges from 0 to 3 // here (because our series has 3 public keys). for _, i := range []int{1, 2, 3} { - TstRunWithManagerUnlocked(t, mgr, func() { - addr, err = nextAddr(pool, addr.seriesID, addr.branch, addr.index, stopSeriesID) + TstRunWithManagerUnlocked(t, pool.Manager(), addrmgrNs, func() { + addr, err = nextAddr(pool, ns, addrmgrNs, addr.seriesID, addr.branch, addr.index, stopSeriesID) }) if err != nil { t.Fatalf("Failed to get next address: %v", err) @@ -160,8 +180,8 @@ func TestNextAddr(t *testing.T) { // idx=lastIdx-1, so the next 4 calls should give us the addresses with // branch=[0-3] and idx=lastIdx. for _, i := range []int{0, 1, 2, 3} { - TstRunWithManagerUnlocked(t, mgr, func() { - addr, err = nextAddr(pool, addr.seriesID, addr.branch, addr.index, stopSeriesID) + TstRunWithManagerUnlocked(t, pool.Manager(), addrmgrNs, func() { + addr, err = nextAddr(pool, ns, addrmgrNs, addr.seriesID, addr.branch, addr.index, stopSeriesID) }) if err != nil { t.Fatalf("Failed to get next address: %v", err) @@ -172,13 +192,13 @@ func TestNextAddr(t *testing.T) { // Populate used addresses DB with entries for seriesID==2, branch==0..3, // idx==0..10. for _, i := range []int{0, 1, 2, 3} { - TstEnsureUsedAddr(t, pool, 2, Branch(i), lastIdx) + TstEnsureUsedAddr(t, dbtx, pool, 2, Branch(i), lastIdx) } // Now we've gone through all the available branch/idx combinations, so // we should move to the next series and start again with branch=0, idx=0. for _, i := range []int{0, 1, 2, 3} { - TstRunWithManagerUnlocked(t, mgr, func() { - addr, err = nextAddr(pool, addr.seriesID, addr.branch, addr.index, stopSeriesID) + TstRunWithManagerUnlocked(t, pool.Manager(), addrmgrNs, func() { + addr, err = nextAddr(pool, ns, addrmgrNs, addr.seriesID, addr.branch, addr.index, stopSeriesID) }) if err != nil { t.Fatalf("Failed to get next address: %v", err) @@ -188,9 +208,9 @@ func TestNextAddr(t *testing.T) { // Finally check that nextAddr() returns nil when we've reached the last // available address before stopSeriesID. - addr = TstNewWithdrawalAddress(t, pool, 2, 3, lastIdx) - TstRunWithManagerUnlocked(t, mgr, func() { - addr, err = nextAddr(pool, addr.seriesID, addr.branch, addr.index, stopSeriesID) + addr = TstNewWithdrawalAddress(t, dbtx, pool, 2, 3, lastIdx) + TstRunWithManagerUnlocked(t, pool.Manager(), addrmgrNs, func() { + addr, err = nextAddr(pool, ns, addrmgrNs, addr.seriesID, addr.branch, addr.index, stopSeriesID) }) if err != nil { t.Fatalf("Failed to get next address: %v", err) @@ -201,11 +221,17 @@ func TestNextAddr(t *testing.T) { } func TestEligibleInputsAreEligible(t *testing.T) { - tearDown, pool, _ := TstCreatePoolAndTxStore(t) + tearDown, db, pool := TstCreatePool(t) defer tearDown() + dbtx, err := db.BeginReadWriteTx() + if err != nil { + t.Fatal(err) + } + defer dbtx.Commit() + var chainHeight int32 = 1000 - _, credits := TstCreateCreditsOnNewSeries(t, pool, []int64{int64(dustThreshold)}) + _, credits := TstCreateCreditsOnNewSeries(t, dbtx, pool, []int64{int64(dustThreshold)}) c := credits[0] // Make sure credit is old enough to pass the minConf check. c.BlockMeta.Height = int32(eligibleInputMinConfirmations) @@ -216,11 +242,17 @@ func TestEligibleInputsAreEligible(t *testing.T) { } func TestNonEligibleInputsAreNotEligible(t *testing.T) { - tearDown, pool, _ := TstCreatePoolAndTxStore(t) + tearDown, db, pool := TstCreatePool(t) defer tearDown() + dbtx, err := db.BeginReadWriteTx() + if err != nil { + t.Fatal(err) + } + defer dbtx.Commit() + var chainHeight int32 = 1000 - _, credits := TstCreateCreditsOnNewSeries(t, pool, []int64{int64(dustThreshold - 1)}) + _, credits := TstCreateCreditsOnNewSeries(t, dbtx, pool, []int64{int64(dustThreshold - 1)}) c := credits[0] // Make sure credit is old enough to pass the minConf check. c.BlockMeta.Height = int32(eligibleInputMinConfirmations) @@ -231,7 +263,7 @@ func TestNonEligibleInputsAreNotEligible(t *testing.T) { } // Check that a credit with not enough confirmations is rejected. - _, credits = TstCreateCreditsOnNewSeries(t, pool, []int64{int64(dustThreshold)}) + _, credits = TstCreateCreditsOnNewSeries(t, dbtx, pool, []int64{int64(dustThreshold)}) c = credits[0] // The calculation of if it has been confirmed does this: chainheigt - bh + // 1 >= target, which is quite weird, but the reason why I need to put 902 @@ -243,25 +275,31 @@ func TestNonEligibleInputsAreNotEligible(t *testing.T) { } func TestCreditSortingByAddress(t *testing.T) { - teardown, _, pool := TstCreatePool(t) + teardown, db, pool := TstCreatePool(t) defer teardown() + dbtx, err := db.BeginReadWriteTx() + if err != nil { + t.Fatal(err) + } + defer dbtx.Commit() + series := []TstSeriesDef{ {ReqSigs: 2, PubKeys: TstPubKeys[1:4], SeriesID: 1}, {ReqSigs: 2, PubKeys: TstPubKeys[3:6], SeriesID: 2}, } - TstCreateSeries(t, pool, series) + TstCreateSeries(t, dbtx, pool, series) shaHash0 := bytes.Repeat([]byte{0}, 32) shaHash1 := bytes.Repeat([]byte{1}, 32) shaHash2 := bytes.Repeat([]byte{2}, 32) - c0 := newDummyCredit(t, pool, 1, 0, 0, shaHash0, 0) - c1 := newDummyCredit(t, pool, 1, 0, 0, shaHash0, 1) - c2 := newDummyCredit(t, pool, 1, 0, 0, shaHash1, 0) - c3 := newDummyCredit(t, pool, 1, 0, 0, shaHash2, 0) - c4 := newDummyCredit(t, pool, 1, 0, 1, shaHash0, 0) - c5 := newDummyCredit(t, pool, 1, 1, 0, shaHash0, 0) - c6 := newDummyCredit(t, pool, 2, 0, 0, shaHash0, 0) + c0 := newDummyCredit(t, dbtx, pool, 1, 0, 0, shaHash0, 0) + c1 := newDummyCredit(t, dbtx, pool, 1, 0, 0, shaHash0, 1) + c2 := newDummyCredit(t, dbtx, pool, 1, 0, 0, shaHash1, 0) + c3 := newDummyCredit(t, dbtx, pool, 1, 0, 0, shaHash2, 0) + c4 := newDummyCredit(t, dbtx, pool, 1, 0, 1, shaHash0, 0) + c5 := newDummyCredit(t, dbtx, pool, 1, 1, 0, shaHash0, 0) + c6 := newDummyCredit(t, dbtx, pool, 2, 0, 0, shaHash0, 0) randomCredits := [][]credit{ {c6, c5, c4, c3, c2, c1, c0}, @@ -292,7 +330,7 @@ func TestCreditSortingByAddress(t *testing.T) { // newDummyCredit creates a new credit with the given hash and outpointIdx, // locked to the votingpool address identified by the given // series/index/branch. -func newDummyCredit(t *testing.T, pool *Pool, series uint32, index Index, branch Branch, +func newDummyCredit(t *testing.T, dbtx walletdb.ReadWriteTx, pool *Pool, series uint32, index Index, branch Branch, txHash []byte, outpointIdx uint32) credit { var hash chainhash.Hash if err := hash.SetBytes(txHash); err != nil { @@ -300,8 +338,8 @@ func newDummyCredit(t *testing.T, pool *Pool, series uint32, index Index, branch } // Ensure the address defined by the given series/branch/index is present on // the set of used addresses as that's a requirement of WithdrawalAddress. - TstEnsureUsedAddr(t, pool, series, branch, index) - addr := TstNewWithdrawalAddress(t, pool, series, branch, index) + TstEnsureUsedAddr(t, dbtx, pool, series, branch, index) + addr := TstNewWithdrawalAddress(t, dbtx, pool, series, branch, index) c := wtxmgr.Credit{ OutPoint: wire.OutPoint{ Hash: hash, @@ -337,12 +375,12 @@ func checkUniqueness(t *testing.T, credits byAddress) { } } -func getPKScriptsForAddressRange(t *testing.T, pool *Pool, seriesID uint32, +func getPKScriptsForAddressRange(t *testing.T, dbtx walletdb.ReadWriteTx, pool *Pool, seriesID uint32, startBranch, stopBranch Branch, startIdx, stopIdx Index) [][]byte { var pkScripts [][]byte for idx := startIdx; idx <= stopIdx; idx++ { for branch := startBranch; branch <= stopBranch; branch++ { - pkScripts = append(pkScripts, TstCreatePkScript(t, pool, seriesID, branch, idx)) + pkScripts = append(pkScripts, TstCreatePkScript(t, dbtx, pool, seriesID, branch, idx)) } } return pkScripts diff --git a/votingpool/internal_test.go b/votingpool/internal_test.go index 62e0541..ad8b14e 100644 --- a/votingpool/internal_test.go +++ b/votingpool/internal_test.go @@ -16,37 +16,24 @@ var TstLastErr = lastErr const TstEligibleInputMinConfirmations = eligibleInputMinConfirmations // TstPutSeries transparently wraps the voting pool putSeries method. -func (vp *Pool) TstPutSeries(version, seriesID, reqSigs uint32, inRawPubKeys []string) error { - return vp.putSeries(version, seriesID, reqSigs, inRawPubKeys) +func (vp *Pool) TstPutSeries(ns walletdb.ReadWriteBucket, version, seriesID, reqSigs uint32, inRawPubKeys []string) error { + return vp.putSeries(ns, version, seriesID, reqSigs, inRawPubKeys) } var TstBranchOrder = branchOrder // TstExistsSeries checks whether a series is stored in the database. -func (vp *Pool) TstExistsSeries(seriesID uint32) (bool, error) { - var exists bool - err := vp.namespace.View( - func(tx walletdb.Tx) error { - poolBucket := tx.RootBucket().Bucket(vp.ID) - if poolBucket == nil { - return nil - } - bucket := poolBucket.Bucket(seriesBucketName) - if bucket == nil { - return nil - } - exists = bucket.Get(uint32ToBytes(seriesID)) != nil - return nil - }) - if err != nil { - return false, err +func (vp *Pool) TstExistsSeries(dbtx walletdb.ReadTx, seriesID uint32) (bool, error) { + ns, _ := TstRNamespaces(dbtx) + poolBucket := ns.NestedReadBucket(vp.ID) + if poolBucket == nil { + return false, nil } - return exists, nil -} - -// TstNamespace exposes the Pool's namespace as it's needed in some tests. -func (vp *Pool) TstNamespace() walletdb.Namespace { - return vp.namespace + bucket := poolBucket.NestedReadBucket(seriesBucketName) + if bucket == nil { + return false, nil + } + return bucket.Get(uint32ToBytes(seriesID)) != nil, nil } // TstGetRawPublicKeys gets a series public keys in string format. diff --git a/votingpool/pool_test.go b/votingpool/pool_test.go index 4e51a73..2c69502 100644 --- a/votingpool/pool_test.go +++ b/votingpool/pool_test.go @@ -19,18 +19,26 @@ import ( ) func TestLoadPoolAndDepositScript(t *testing.T) { - tearDown, manager, pool := vp.TstCreatePool(t) + tearDown, db, pool := vp.TstCreatePool(t) defer tearDown() + + dbtx, err := db.BeginReadWriteTx() + if err != nil { + t.Fatal(err) + } + defer dbtx.Commit() + ns, _ := vp.TstRWNamespaces(dbtx) + // setup poolID := "test" pubKeys := vp.TstPubKeys[0:3] - err := vp.LoadAndCreateSeries(pool.TstNamespace(), manager, 1, poolID, 1, 2, pubKeys) + err = vp.LoadAndCreateSeries(ns, pool.Manager(), 1, poolID, 1, 2, pubKeys) if err != nil { t.Fatalf("Failed to create voting pool and series: %v", err) } // execute - script, err := vp.LoadAndGetDepositScript(pool.TstNamespace(), manager, poolID, 1, 0, 0) + script, err := vp.LoadAndGetDepositScript(ns, pool.Manager(), poolID, 1, 0, 0) if err != nil { t.Fatalf("Failed to get deposit script: %v", err) } @@ -45,21 +53,28 @@ func TestLoadPoolAndDepositScript(t *testing.T) { } func TestLoadPoolAndCreateSeries(t *testing.T) { - tearDown, manager, pool := vp.TstCreatePool(t) + tearDown, db, pool := vp.TstCreatePool(t) defer tearDown() + dbtx, err := db.BeginReadWriteTx() + if err != nil { + t.Fatal(err) + } + defer dbtx.Commit() + ns, _ := vp.TstRWNamespaces(dbtx) + poolID := "test" // first time, the voting pool is created pubKeys := vp.TstPubKeys[0:3] - err := vp.LoadAndCreateSeries(pool.TstNamespace(), manager, 1, poolID, 1, 2, pubKeys) + err = vp.LoadAndCreateSeries(ns, pool.Manager(), 1, poolID, 1, 2, pubKeys) if err != nil { t.Fatalf("Creating voting pool and Creating series failed: %v", err) } // create another series where the voting pool is loaded this time pubKeys = vp.TstPubKeys[3:6] - err = vp.LoadAndCreateSeries(pool.TstNamespace(), manager, 1, poolID, 2, 2, pubKeys) + err = vp.LoadAndCreateSeries(ns, pool.Manager(), 1, poolID, 2, 2, pubKeys) if err != nil { t.Fatalf("Loading voting pool and Creating series failed: %v", err) @@ -67,38 +82,52 @@ func TestLoadPoolAndCreateSeries(t *testing.T) { } func TestLoadPoolAndReplaceSeries(t *testing.T) { - tearDown, manager, pool := vp.TstCreatePool(t) + tearDown, db, pool := vp.TstCreatePool(t) defer tearDown() + dbtx, err := db.BeginReadWriteTx() + if err != nil { + t.Fatal(err) + } + defer dbtx.Commit() + ns, _ := vp.TstRWNamespaces(dbtx) + // setup poolID := "test" pubKeys := vp.TstPubKeys[0:3] - err := vp.LoadAndCreateSeries(pool.TstNamespace(), manager, 1, poolID, 1, 2, pubKeys) + err = vp.LoadAndCreateSeries(ns, pool.Manager(), 1, poolID, 1, 2, pubKeys) if err != nil { t.Fatalf("Failed to create voting pool and series: %v", err) } pubKeys = vp.TstPubKeys[3:6] - err = vp.LoadAndReplaceSeries(pool.TstNamespace(), manager, 1, poolID, 1, 2, pubKeys) + err = vp.LoadAndReplaceSeries(ns, pool.Manager(), 1, poolID, 1, 2, pubKeys) if err != nil { t.Fatalf("Failed to replace series: %v", err) } } func TestLoadPoolAndEmpowerSeries(t *testing.T) { - tearDown, manager, pool := vp.TstCreatePool(t) + tearDown, db, pool := vp.TstCreatePool(t) defer tearDown() + dbtx, err := db.BeginReadWriteTx() + if err != nil { + t.Fatal(err) + } + defer dbtx.Commit() + ns, addrmgrNs := vp.TstRWNamespaces(dbtx) + // setup poolID := "test" pubKeys := vp.TstPubKeys[0:3] - err := vp.LoadAndCreateSeries(pool.TstNamespace(), manager, 1, poolID, 1, 2, pubKeys) + err = vp.LoadAndCreateSeries(ns, pool.Manager(), 1, poolID, 1, 2, pubKeys) if err != nil { t.Fatalf("Creating voting pool and Creating series failed: %v", err) } - vp.TstRunWithManagerUnlocked(t, pool.Manager(), func() { - err = vp.LoadAndEmpowerSeries(pool.TstNamespace(), manager, poolID, 1, vp.TstPrivKeys[0]) + vp.TstRunWithManagerUnlocked(t, pool.Manager(), addrmgrNs, func() { + err = vp.LoadAndEmpowerSeries(ns, pool.Manager(), poolID, 1, vp.TstPrivKeys[0]) }) if err != nil { t.Fatalf("Load voting pool and Empower series failed: %v", err) @@ -106,9 +135,16 @@ func TestLoadPoolAndEmpowerSeries(t *testing.T) { } func TestDepositScriptAddress(t *testing.T) { - tearDown, _, pool := vp.TstCreatePool(t) + tearDown, db, pool := vp.TstCreatePool(t) defer tearDown() + dbtx, err := db.BeginReadWriteTx() + if err != nil { + t.Fatal(err) + } + defer dbtx.Commit() + ns, _ := vp.TstRWNamespaces(dbtx) + tests := []struct { version uint32 series uint32 @@ -132,7 +168,7 @@ func TestDepositScriptAddress(t *testing.T) { } for i, test := range tests { - if err := pool.CreateSeries(test.version, test.series, + if err := pool.CreateSeries(ns, test.version, test.series, test.reqSigs, test.pubKeys); err != nil { t.Fatalf("Cannot creates series %v", test.series) } @@ -160,24 +196,39 @@ func TestDepositScriptAddressForNonExistentSeries(t *testing.T) { } func TestDepositScriptAddressForHardenedPubKey(t *testing.T) { - tearDown, _, pool := vp.TstCreatePool(t) + tearDown, db, pool := vp.TstCreatePool(t) defer tearDown() - if err := pool.CreateSeries(1, 1, 2, vp.TstPubKeys[0:3]); err != nil { + + dbtx, err := db.BeginReadWriteTx() + if err != nil { + t.Fatal(err) + } + defer dbtx.Commit() + ns, _ := vp.TstRWNamespaces(dbtx) + + if err := pool.CreateSeries(ns, 1, 1, 2, vp.TstPubKeys[0:3]); err != nil { t.Fatalf("Cannot creates series") } // Ask for a DepositScriptAddress using an index for a hardened child, which should // fail as we use the extended public keys to derive childs. - _, err := pool.DepositScriptAddress(1, 0, vp.Index(hdkeychain.HardenedKeyStart+1)) + _, err = pool.DepositScriptAddress(1, 0, vp.Index(hdkeychain.HardenedKeyStart+1)) vp.TstCheckError(t, "", err, vp.ErrKeyChain) } func TestLoadPool(t *testing.T) { - tearDown, mgr, pool := vp.TstCreatePool(t) + tearDown, db, pool := vp.TstCreatePool(t) defer tearDown() - pool2, err := vp.Load(pool.TstNamespace(), mgr, pool.ID) + dbtx, err := db.BeginReadWriteTx() + if err != nil { + t.Fatal(err) + } + defer dbtx.Commit() + ns, _ := vp.TstRWNamespaces(dbtx) + + pool2, err := vp.Load(ns, pool.Manager(), pool.ID) if err != nil { t.Errorf("Error loading Pool: %v", err) } @@ -187,10 +238,17 @@ func TestLoadPool(t *testing.T) { } func TestCreatePool(t *testing.T) { - tearDown, mgr, pool := vp.TstCreatePool(t) + tearDown, db, pool := vp.TstCreatePool(t) defer tearDown() - pool2, err := vp.Create(pool.TstNamespace(), mgr, []byte{0x02}) + dbtx, err := db.BeginReadWriteTx() + if err != nil { + t.Fatal(err) + } + defer dbtx.Commit() + ns, _ := vp.TstRWNamespaces(dbtx) + + pool2, err := vp.Create(ns, pool.Manager(), []byte{0x02}) if err != nil { t.Errorf("Error creating Pool: %v", err) } @@ -200,18 +258,32 @@ func TestCreatePool(t *testing.T) { } func TestCreatePoolWhenAlreadyExists(t *testing.T) { - tearDown, mgr, pool := vp.TstCreatePool(t) + tearDown, db, pool := vp.TstCreatePool(t) defer tearDown() - _, err := vp.Create(pool.TstNamespace(), mgr, pool.ID) + dbtx, err := db.BeginReadWriteTx() + if err != nil { + t.Fatal(err) + } + defer dbtx.Commit() + ns, _ := vp.TstRWNamespaces(dbtx) + + _, err = vp.Create(ns, pool.Manager(), pool.ID) vp.TstCheckError(t, "", err, vp.ErrPoolAlreadyExists) } func TestCreateSeries(t *testing.T) { - tearDown, _, pool := vp.TstCreatePool(t) + tearDown, db, pool := vp.TstCreatePool(t) defer tearDown() + dbtx, err := db.BeginReadWriteTx() + if err != nil { + t.Fatal(err) + } + defer dbtx.Commit() + ns, _ := vp.TstRWNamespaces(dbtx) + tests := []struct { version uint32 series uint32 @@ -245,11 +317,11 @@ func TestCreateSeries(t *testing.T) { } for testNum, test := range tests { - err := pool.CreateSeries(test.version, test.series, test.reqSigs, test.pubKeys[:]) + err := pool.CreateSeries(ns, test.version, test.series, test.reqSigs, test.pubKeys[:]) if err != nil { t.Fatalf("%d: Cannot create series %d", testNum, test.series) } - exists, err := pool.TstExistsSeries(test.series) + exists, err := pool.TstExistsSeries(dbtx, test.series) if err != nil { t.Fatal(err) } @@ -260,45 +332,74 @@ func TestCreateSeries(t *testing.T) { } func TestPoolCreateSeriesInvalidID(t *testing.T) { - tearDown, _, pool := vp.TstCreatePool(t) + tearDown, db, pool := vp.TstCreatePool(t) defer tearDown() - err := pool.CreateSeries(vp.CurrentVersion, 0, 1, vp.TstPubKeys[0:3]) + dbtx, err := db.BeginReadWriteTx() + if err != nil { + t.Fatal(err) + } + defer dbtx.Commit() + ns, _ := vp.TstRWNamespaces(dbtx) + + err = pool.CreateSeries(ns, vp.CurrentVersion, 0, 1, vp.TstPubKeys[0:3]) vp.TstCheckError(t, "", err, vp.ErrSeriesIDInvalid) } func TestPoolCreateSeriesWhenAlreadyExists(t *testing.T) { - tearDown, _, pool := vp.TstCreatePool(t) + tearDown, db, pool := vp.TstCreatePool(t) defer tearDown() + + dbtx, err := db.BeginReadWriteTx() + if err != nil { + t.Fatal(err) + } + defer dbtx.Commit() + ns, _ := vp.TstRWNamespaces(dbtx) + pubKeys := vp.TstPubKeys[0:3] - if err := pool.CreateSeries(1, 1, 1, pubKeys); err != nil { + if err := pool.CreateSeries(ns, 1, 1, 1, pubKeys); err != nil { t.Fatalf("Cannot create series: %v", err) } - err := pool.CreateSeries(1, 1, 1, pubKeys) + err = pool.CreateSeries(ns, 1, 1, 1, pubKeys) vp.TstCheckError(t, "", err, vp.ErrSeriesAlreadyExists) } func TestPoolCreateSeriesIDNotSequential(t *testing.T) { - tearDown, _, pool := vp.TstCreatePool(t) + tearDown, db, pool := vp.TstCreatePool(t) defer tearDown() + dbtx, err := db.BeginReadWriteTx() + if err != nil { + t.Fatal(err) + } + defer dbtx.Commit() + ns, _ := vp.TstRWNamespaces(dbtx) + pubKeys := vp.TstPubKeys[0:4] - if err := pool.CreateSeries(1, 1, 2, pubKeys); err != nil { + if err := pool.CreateSeries(ns, 1, 1, 2, pubKeys); err != nil { t.Fatalf("Cannot create series: %v", err) } - err := pool.CreateSeries(1, 3, 2, pubKeys) + err = pool.CreateSeries(ns, 1, 3, 2, pubKeys) vp.TstCheckError(t, "", err, vp.ErrSeriesIDNotSequential) } func TestPutSeriesErrors(t *testing.T) { - tearDown, _, pool := vp.TstCreatePool(t) + tearDown, db, pool := vp.TstCreatePool(t) defer tearDown() + dbtx, err := db.BeginReadWriteTx() + if err != nil { + t.Fatal(err) + } + defer dbtx.Commit() + ns, _ := vp.TstRWNamespaces(dbtx) + tests := []struct { version uint32 reqSigs uint32 @@ -335,40 +436,54 @@ func TestPutSeriesErrors(t *testing.T) { } for i, test := range tests { - err := pool.TstPutSeries(test.version, uint32(i+1), test.reqSigs, test.pubKeys) + err := pool.TstPutSeries(ns, test.version, uint32(i+1), test.reqSigs, test.pubKeys) vp.TstCheckError(t, fmt.Sprintf("Create series #%d", i), err, test.err) } } func TestCannotReplaceEmpoweredSeries(t *testing.T) { - tearDown, mgr, pool := vp.TstCreatePool(t) + tearDown, db, pool := vp.TstCreatePool(t) defer tearDown() + dbtx, err := db.BeginReadWriteTx() + if err != nil { + t.Fatal(err) + } + defer dbtx.Commit() + ns, addrmgrNs := vp.TstRWNamespaces(dbtx) + seriesID := uint32(1) - if err := pool.CreateSeries(1, seriesID, 3, vp.TstPubKeys[0:4]); err != nil { + if err := pool.CreateSeries(ns, 1, seriesID, 3, vp.TstPubKeys[0:4]); err != nil { t.Fatalf("Failed to create series: %v", err) } - vp.TstRunWithManagerUnlocked(t, mgr, func() { - if err := pool.EmpowerSeries(seriesID, vp.TstPrivKeys[1]); err != nil { + vp.TstRunWithManagerUnlocked(t, pool.Manager(), addrmgrNs, func() { + if err := pool.EmpowerSeries(ns, seriesID, vp.TstPrivKeys[1]); err != nil { t.Fatalf("Failed to empower series: %v", err) } }) - err := pool.ReplaceSeries(1, seriesID, 2, []string{vp.TstPubKeys[0], vp.TstPubKeys[2], + err = pool.ReplaceSeries(ns, 1, seriesID, 2, []string{vp.TstPubKeys[0], vp.TstPubKeys[2], vp.TstPubKeys[3]}) vp.TstCheckError(t, "", err, vp.ErrSeriesAlreadyEmpowered) } func TestReplaceNonExistingSeries(t *testing.T) { - tearDown, _, pool := vp.TstCreatePool(t) + tearDown, db, pool := vp.TstCreatePool(t) defer tearDown() + dbtx, err := db.BeginReadWriteTx() + if err != nil { + t.Fatal(err) + } + defer dbtx.Commit() + ns, _ := vp.TstRWNamespaces(dbtx) + pubKeys := vp.TstPubKeys[0:3] - err := pool.ReplaceSeries(1, 1, 3, pubKeys) + err = pool.ReplaceSeries(ns, 1, 1, 3, pubKeys) vp.TstCheckError(t, "", err, vp.ErrSeriesNotExists) } @@ -429,19 +544,26 @@ var replaceSeriesTestData = []replaceSeriesTestEntry{ } func TestReplaceExistingSeries(t *testing.T) { - tearDown, _, pool := vp.TstCreatePool(t) + tearDown, db, pool := vp.TstCreatePool(t) defer tearDown() + dbtx, err := db.BeginReadWriteTx() + if err != nil { + t.Fatal(err) + } + defer dbtx.Commit() + ns, _ := vp.TstRWNamespaces(dbtx) + for _, data := range replaceSeriesTestData { seriesID := data.orig.id testID := data.testID - if err := pool.CreateSeries(data.orig.version, seriesID, data.orig.reqSigs, data.orig.pubKeys); err != nil { + if err := pool.CreateSeries(ns, data.orig.version, seriesID, data.orig.reqSigs, data.orig.pubKeys); err != nil { t.Fatalf("Test #%d: failed to create series in replace series setup: %v", testID, err) } - if err := pool.ReplaceSeries(data.replaceWith.version, seriesID, + if err := pool.ReplaceSeries(ns, data.replaceWith.version, seriesID, data.replaceWith.reqSigs, data.replaceWith.pubKeys); err != nil { t.Errorf("Test #%d: replaceSeries failed: %v", testID, err) } @@ -480,27 +602,41 @@ func validateReplaceSeries(t *testing.T, pool *vp.Pool, testID int, replacedWith } func TestEmpowerSeries(t *testing.T) { - tearDown, mgr, pool := vp.TstCreatePool(t) + tearDown, db, pool := vp.TstCreatePool(t) defer tearDown() + dbtx, err := db.BeginReadWriteTx() + if err != nil { + t.Fatal(err) + } + defer dbtx.Commit() + ns, addrmgrNs := vp.TstRWNamespaces(dbtx) + seriesID := uint32(1) - if err := pool.CreateSeries(1, seriesID, 2, vp.TstPubKeys[0:3]); err != nil { + if err := pool.CreateSeries(ns, 1, seriesID, 2, vp.TstPubKeys[0:3]); err != nil { t.Fatalf("Failed to create series: %v", err) } - vp.TstRunWithManagerUnlocked(t, mgr, func() { - if err := pool.EmpowerSeries(seriesID, vp.TstPrivKeys[0]); err != nil { + vp.TstRunWithManagerUnlocked(t, pool.Manager(), addrmgrNs, func() { + if err := pool.EmpowerSeries(ns, seriesID, vp.TstPrivKeys[0]); err != nil { t.Errorf("Failed to empower series: %v", err) } }) } func TestEmpowerSeriesErrors(t *testing.T) { - tearDown, _, pool := vp.TstCreatePool(t) + tearDown, db, pool := vp.TstCreatePool(t) defer tearDown() + dbtx, err := db.BeginReadWriteTx() + if err != nil { + t.Fatal(err) + } + defer dbtx.Commit() + ns, _ := vp.TstRWNamespaces(dbtx) + seriesID := uint32(1) - if err := pool.CreateSeries(1, seriesID, 2, vp.TstPubKeys[0:3]); err != nil { + if err := pool.CreateSeries(ns, 1, seriesID, 2, vp.TstPubKeys[0:3]); err != nil { t.Fatalf("Failed to create series: %v", err) } @@ -536,17 +672,25 @@ func TestEmpowerSeriesErrors(t *testing.T) { } for i, test := range tests { - err := pool.EmpowerSeries(test.seriesID, test.key) + err := pool.EmpowerSeries(ns, test.seriesID, test.key) vp.TstCheckError(t, fmt.Sprintf("EmpowerSeries #%d", i), err, test.err) } } func TestPoolSeries(t *testing.T) { - tearDown, _, pool := vp.TstCreatePool(t) + tearDown, db, pool := vp.TstCreatePool(t) defer tearDown() + + dbtx, err := db.BeginReadWriteTx() + if err != nil { + t.Fatal(err) + } + defer dbtx.Commit() + ns, _ := vp.TstRWNamespaces(dbtx) + expectedPubKeys := vp.CanonicalKeyOrder(vp.TstPubKeys[0:3]) - if err := pool.CreateSeries(vp.CurrentVersion, 1, 2, expectedPubKeys); err != nil { + if err := pool.CreateSeries(ns, vp.CurrentVersion, 1, 2, expectedPubKeys); err != nil { t.Fatalf("Failed to create series: %v", err) } @@ -613,15 +757,16 @@ var testLoadAllSeriesTests = []testLoadAllSeriesTest{ }, } -func setUpLoadAllSeries(t *testing.T, namespace walletdb.Namespace, mgr *waddrmgr.Manager, +func setUpLoadAllSeries(t *testing.T, dbtx walletdb.ReadWriteTx, mgr *waddrmgr.Manager, test testLoadAllSeriesTest) *vp.Pool { - pool, err := vp.Create(namespace, mgr, []byte{byte(test.id + 1)}) + ns, addrmgrNs := vp.TstRWNamespaces(dbtx) + pool, err := vp.Create(ns, mgr, []byte{byte(test.id + 1)}) if err != nil { t.Fatalf("Voting Pool creation failed: %v", err) } for _, series := range test.series { - err := pool.CreateSeries(series.version, series.id, + err := pool.CreateSeries(ns, series.version, series.id, series.reqSigs, series.pubKeys) if err != nil { t.Fatalf("Test #%d Series #%d: failed to create series: %v", @@ -629,8 +774,8 @@ func setUpLoadAllSeries(t *testing.T, namespace walletdb.Namespace, mgr *waddrmg } for _, privKey := range series.privKeys { - vp.TstRunWithManagerUnlocked(t, mgr, func() { - if err := pool.EmpowerSeries(series.id, privKey); err != nil { + vp.TstRunWithManagerUnlocked(t, mgr, addrmgrNs, func() { + if err := pool.EmpowerSeries(ns, series.id, privKey); err != nil { t.Fatalf("Test #%d Series #%d: empower with privKey %v failed: %v", test.id, series.id, privKey, err) } @@ -641,14 +786,21 @@ func setUpLoadAllSeries(t *testing.T, namespace walletdb.Namespace, mgr *waddrmg } func TestLoadAllSeries(t *testing.T) { - tearDown, manager, pool := vp.TstCreatePool(t) + tearDown, db, pool := vp.TstCreatePool(t) defer tearDown() + dbtx, err := db.BeginReadWriteTx() + if err != nil { + t.Fatal(err) + } + defer dbtx.Commit() + ns, addrmgrNs := vp.TstRWNamespaces(dbtx) + for _, test := range testLoadAllSeriesTests { - pool := setUpLoadAllSeries(t, pool.TstNamespace(), manager, test) + pool := setUpLoadAllSeries(t, dbtx, pool.Manager(), test) pool.TstEmptySeriesLookup() - vp.TstRunWithManagerUnlocked(t, manager, func() { - if err := pool.LoadAllSeries(); err != nil { + vp.TstRunWithManagerUnlocked(t, pool.Manager(), addrmgrNs, func() { + if err := pool.LoadAllSeries(ns); err != nil { t.Fatalf("Test #%d: failed to load voting pool: %v", test.id, err) } }) @@ -842,11 +994,18 @@ func TestReverse(t *testing.T) { } func TestEmpowerSeriesNeuterFailed(t *testing.T) { - tearDown, _, pool := vp.TstCreatePool(t) + tearDown, db, pool := vp.TstCreatePool(t) defer tearDown() + dbtx, err := db.BeginReadWriteTx() + if err != nil { + t.Fatal(err) + } + defer dbtx.Commit() + ns, _ := vp.TstRWNamespaces(dbtx) + seriesID := uint32(1) - err := pool.CreateSeries(1, seriesID, 2, vp.TstPubKeys[0:3]) + err = pool.CreateSeries(ns, 1, seriesID, 2, vp.TstPubKeys[0:3]) if err != nil { t.Fatalf("Failed to create series: %v", err) } @@ -855,17 +1014,17 @@ func TestEmpowerSeriesNeuterFailed(t *testing.T) { // error in (k *ExtendedKey).Neuter and the associated error path // in EmpowerSeries. badKey := "wM5uZBNTYmaYGiK8VaGi7zPGbZGLuQgDiR2Zk4nGfbRFLXwHGcMUdVdazRpNHFSR7X7WLmzzbAq8dA1ViN6eWKgKqPye1rJTDQTvBiXvZ7E3nmdx" - err = pool.EmpowerSeries(seriesID, badKey) + err = pool.EmpowerSeries(ns, seriesID, badKey) vp.TstCheckError(t, "", err, vp.ErrKeyNeuter) } func TestDecryptExtendedKeyCannotCreateResultKey(t *testing.T) { - tearDown, mgr, pool := vp.TstCreatePool(t) + tearDown, _, pool := vp.TstCreatePool(t) defer tearDown() // the plaintext not being base58 encoded triggers the error - cipherText, err := mgr.Encrypt(waddrmgr.CKTPublic, []byte("not-base58-encoded")) + cipherText, err := pool.Manager().Encrypt(waddrmgr.CKTPublic, []byte("not-base58-encoded")) if err != nil { t.Fatalf("Failed to encrypt plaintext: %v", err) } @@ -885,35 +1044,48 @@ func TestDecryptExtendedKeyCannotDecrypt(t *testing.T) { } func TestPoolChangeAddress(t *testing.T) { - tearDown, _, pool := vp.TstCreatePool(t) + tearDown, db, pool := vp.TstCreatePool(t) defer tearDown() + dbtx, err := db.BeginReadWriteTx() + if err != nil { + t.Fatal(err) + } + defer dbtx.Commit() + pubKeys := vp.TstPubKeys[1:4] - vp.TstCreateSeries(t, pool, []vp.TstSeriesDef{{ReqSigs: 2, PubKeys: pubKeys, SeriesID: 1}}) + vp.TstCreateSeries(t, dbtx, pool, []vp.TstSeriesDef{{ReqSigs: 2, PubKeys: pubKeys, SeriesID: 1}}) addr := vp.TstNewChangeAddress(t, pool, 1, 0) checkPoolAddress(t, addr, 1, 0, 0) // When the series is not active, we should get an error. pubKeys = vp.TstPubKeys[3:6] - vp.TstCreateSeries(t, pool, + vp.TstCreateSeries(t, dbtx, pool, []vp.TstSeriesDef{{ReqSigs: 2, PubKeys: pubKeys, SeriesID: 2, Inactive: true}}) - _, err := pool.ChangeAddress(2, 0) + _, err = pool.ChangeAddress(2, 0) vp.TstCheckError(t, "", err, vp.ErrSeriesNotActive) } func TestPoolWithdrawalAddress(t *testing.T) { - tearDown, _, pool := vp.TstCreatePool(t) + tearDown, db, pool := vp.TstCreatePool(t) defer tearDown() + dbtx, err := db.BeginReadWriteTx() + if err != nil { + t.Fatal(err) + } + defer dbtx.Commit() + ns, addrmgrNs := vp.TstRWNamespaces(dbtx) + pubKeys := vp.TstPubKeys[1:4] - vp.TstCreateSeries(t, pool, []vp.TstSeriesDef{{ReqSigs: 2, PubKeys: pubKeys, SeriesID: 1}}) - addr := vp.TstNewWithdrawalAddress(t, pool, 1, 0, 0) + vp.TstCreateSeries(t, dbtx, pool, []vp.TstSeriesDef{{ReqSigs: 2, PubKeys: pubKeys, SeriesID: 1}}) + addr := vp.TstNewWithdrawalAddress(t, dbtx, pool, 1, 0, 0) checkPoolAddress(t, addr, 1, 0, 0) // When the requested address is not present in the set of used addresses // for that Pool, we should get an error. - _, err := pool.WithdrawalAddress(1, 2, 3) + _, err = pool.WithdrawalAddress(ns, addrmgrNs, 1, 2, 3) vp.TstCheckError(t, "", err, vp.ErrWithdrawFromUnusedAddr) } diff --git a/votingpool/pool_wb_test.go b/votingpool/pool_wb_test.go index 03ca2b7..9429500 100644 --- a/votingpool/pool_wb_test.go +++ b/votingpool/pool_wb_test.go @@ -14,26 +14,32 @@ import ( ) func TestPoolEnsureUsedAddr(t *testing.T) { - tearDown, mgr, pool := TstCreatePool(t) + tearDown, db, pool := TstCreatePool(t) defer tearDown() - var err error + dbtx, err := db.BeginReadWriteTx() + if err != nil { + t.Fatal(err) + } + defer dbtx.Commit() + ns, addrmgrNs := TstRWNamespaces(dbtx) + var script []byte var addr waddrmgr.ManagedScriptAddress - TstCreateSeries(t, pool, []TstSeriesDef{{ReqSigs: 2, PubKeys: TstPubKeys[0:3], SeriesID: 1}}) + TstCreateSeries(t, dbtx, pool, []TstSeriesDef{{ReqSigs: 2, PubKeys: TstPubKeys[0:3], SeriesID: 1}}) idx := Index(0) - TstRunWithManagerUnlocked(t, mgr, func() { - err = pool.EnsureUsedAddr(1, 0, idx) + TstRunWithManagerUnlocked(t, pool.Manager(), addrmgrNs, func() { + err = pool.EnsureUsedAddr(ns, addrmgrNs, 1, 0, idx) }) if err != nil { t.Fatalf("Failed to ensure used addresses: %v", err) } - addr, err = pool.getUsedAddr(1, 0, 0) + addr, err = pool.getUsedAddr(ns, addrmgrNs, 1, 0, 0) if err != nil { t.Fatalf("Failed to get addr from used addresses set: %v", err) } - TstRunWithManagerUnlocked(t, mgr, func() { + TstRunWithManagerUnlocked(t, pool.Manager(), addrmgrNs, func() { script, err = addr.Script() }) if err != nil { @@ -45,18 +51,18 @@ func TestPoolEnsureUsedAddr(t *testing.T) { } idx = Index(3) - TstRunWithManagerUnlocked(t, mgr, func() { - err = pool.EnsureUsedAddr(1, 0, idx) + TstRunWithManagerUnlocked(t, pool.Manager(), addrmgrNs, func() { + err = pool.EnsureUsedAddr(ns, addrmgrNs, 1, 0, idx) }) if err != nil { t.Fatalf("Failed to ensure used addresses: %v", err) } for _, i := range []int{0, 1, 2, 3} { - addr, err = pool.getUsedAddr(1, 0, Index(i)) + addr, err = pool.getUsedAddr(ns, addrmgrNs, 1, 0, Index(i)) if err != nil { t.Fatalf("Failed to get addr from used addresses set: %v", err) } - TstRunWithManagerUnlocked(t, mgr, func() { + TstRunWithManagerUnlocked(t, pool.Manager(), addrmgrNs, func() { script, err = addr.Script() }) if err != nil { @@ -70,14 +76,21 @@ func TestPoolEnsureUsedAddr(t *testing.T) { } func TestPoolGetUsedAddr(t *testing.T) { - tearDown, mgr, pool := TstCreatePool(t) + tearDown, db, pool := TstCreatePool(t) defer tearDown() - TstCreateSeries(t, pool, []TstSeriesDef{{ReqSigs: 2, PubKeys: TstPubKeys[0:3], SeriesID: 1}}) + dbtx, err := db.BeginReadWriteTx() + if err != nil { + t.Fatal(err) + } + defer dbtx.Commit() + ns, addrmgrNs := TstRWNamespaces(dbtx) + + TstCreateSeries(t, dbtx, pool, []TstSeriesDef{{ReqSigs: 2, PubKeys: TstPubKeys[0:3], SeriesID: 1}}) // Addr with series=1, branch=0, index=10 has never been used, so it should // return nil. - addr, err := pool.getUsedAddr(1, 0, 10) + addr, err := pool.getUsedAddr(ns, addrmgrNs, 1, 0, 10) if err != nil { t.Fatalf("Error when looking up used addr: %v", err) } @@ -87,18 +100,18 @@ func TestPoolGetUsedAddr(t *testing.T) { // Now we add that addr to the used addresses DB and check that the value // returned by getUsedAddr() is what we expect. - TstRunWithManagerUnlocked(t, mgr, func() { - err = pool.addUsedAddr(1, 0, 10) + TstRunWithManagerUnlocked(t, pool.Manager(), addrmgrNs, func() { + err = pool.addUsedAddr(ns, addrmgrNs, 1, 0, 10) }) if err != nil { t.Fatalf("Error when storing addr in used addresses DB: %v", err) } var script []byte - addr, err = pool.getUsedAddr(1, 0, 10) + addr, err = pool.getUsedAddr(ns, addrmgrNs, 1, 0, 10) if err != nil { t.Fatalf("Error when looking up used addr: %v", err) } - TstRunWithManagerUnlocked(t, mgr, func() { + TstRunWithManagerUnlocked(t, pool.Manager(), addrmgrNs, func() { script, err = addr.Script() }) if err != nil { @@ -111,9 +124,16 @@ func TestPoolGetUsedAddr(t *testing.T) { } func TestSerializationErrors(t *testing.T) { - tearDown, mgr, _ := TstCreatePool(t) + tearDown, db, pool := TstCreatePool(t) defer tearDown() + dbtx, err := db.BeginReadWriteTx() + if err != nil { + t.Fatal(err) + } + defer dbtx.Commit() + _, addrmgrNs := TstRWNamespaces(dbtx) + tests := []struct { version uint32 pubKeys []string @@ -147,13 +167,13 @@ func TestSerializationErrors(t *testing.T) { active := true for testNum, test := range tests { - encryptedPubs, err := encryptKeys(test.pubKeys, mgr, waddrmgr.CKTPublic) + encryptedPubs, err := encryptKeys(test.pubKeys, pool.Manager(), waddrmgr.CKTPublic) if err != nil { t.Fatalf("Test #%d - Error encrypting pubkeys: %v", testNum, err) } var encryptedPrivs [][]byte - TstRunWithManagerUnlocked(t, mgr, func() { - encryptedPrivs, err = encryptKeys(test.privKeys, mgr, waddrmgr.CKTPrivate) + TstRunWithManagerUnlocked(t, pool.Manager(), addrmgrNs, func() { + encryptedPrivs, err = encryptKeys(test.privKeys, pool.Manager(), waddrmgr.CKTPrivate) }) if err != nil { t.Fatalf("Test #%d - Error encrypting privkeys: %v", testNum, err) @@ -172,9 +192,16 @@ func TestSerializationErrors(t *testing.T) { } func TestSerialization(t *testing.T) { - tearDown, mgr, _ := TstCreatePool(t) + tearDown, db, pool := TstCreatePool(t) defer tearDown() + dbtx, err := db.BeginReadWriteTx() + if err != nil { + t.Fatal(err) + } + defer dbtx.Commit() + _, addrmgrNs := TstRWNamespaces(dbtx) + tests := []struct { version uint32 active bool @@ -213,12 +240,12 @@ func TestSerialization(t *testing.T) { var encryptedPrivs [][]byte for testNum, test := range tests { - encryptedPubs, err := encryptKeys(test.pubKeys, mgr, waddrmgr.CKTPublic) + encryptedPubs, err := encryptKeys(test.pubKeys, pool.Manager(), waddrmgr.CKTPublic) if err != nil { t.Fatalf("Test #%d - Error encrypting pubkeys: %v", testNum, err) } - TstRunWithManagerUnlocked(t, mgr, func() { - encryptedPrivs, err = encryptKeys(test.privKeys, mgr, waddrmgr.CKTPrivate) + TstRunWithManagerUnlocked(t, pool.Manager(), addrmgrNs, func() { + encryptedPrivs, err = encryptKeys(test.privKeys, pool.Manager(), waddrmgr.CKTPrivate) }) if err != nil { t.Fatalf("Test #%d - Error encrypting privkeys: %v", testNum, err) @@ -287,8 +314,7 @@ func TestSerialization(t *testing.T) { } func TestDeserializationErrors(t *testing.T) { - tearDown, _, _ := TstCreatePool(t) - defer tearDown() + t.Parallel() tests := []struct { serialized []byte @@ -329,24 +355,31 @@ func TestDeserializationErrors(t *testing.T) { } func TestValidateAndDecryptKeys(t *testing.T) { - tearDown, manager, pool := TstCreatePool(t) + tearDown, db, pool := TstCreatePool(t) defer tearDown() - rawPubKeys, err := encryptKeys(TstPubKeys[0:2], manager, waddrmgr.CKTPublic) + dbtx, err := db.BeginReadWriteTx() + if err != nil { + t.Fatal(err) + } + defer dbtx.Commit() + _, addrmgrNs := TstRWNamespaces(dbtx) + + rawPubKeys, err := encryptKeys(TstPubKeys[0:2], pool.Manager(), waddrmgr.CKTPublic) if err != nil { t.Fatalf("Failed to encrypt public keys: %v", err) } var rawPrivKeys [][]byte - TstRunWithManagerUnlocked(t, manager, func() { - rawPrivKeys, err = encryptKeys([]string{TstPrivKeys[0], ""}, manager, waddrmgr.CKTPrivate) + TstRunWithManagerUnlocked(t, pool.Manager(), addrmgrNs, func() { + rawPrivKeys, err = encryptKeys([]string{TstPrivKeys[0], ""}, pool.Manager(), waddrmgr.CKTPrivate) }) if err != nil { t.Fatalf("Failed to encrypt private keys: %v", err) } var pubKeys, privKeys []*hdkeychain.ExtendedKey - TstRunWithManagerUnlocked(t, manager, func() { + TstRunWithManagerUnlocked(t, pool.Manager(), addrmgrNs, func() { pubKeys, privKeys, err = validateAndDecryptKeys(rawPubKeys, rawPrivKeys, pool) }) if err != nil { @@ -379,17 +412,24 @@ func TestValidateAndDecryptKeys(t *testing.T) { } func TestValidateAndDecryptKeysErrors(t *testing.T) { - tearDown, manager, pool := TstCreatePool(t) + tearDown, db, pool := TstCreatePool(t) defer tearDown() - encryptedPubKeys, err := encryptKeys(TstPubKeys[0:1], manager, waddrmgr.CKTPublic) + dbtx, err := db.BeginReadWriteTx() + if err != nil { + t.Fatal(err) + } + defer dbtx.Commit() + _, addrmgrNs := TstRWNamespaces(dbtx) + + encryptedPubKeys, err := encryptKeys(TstPubKeys[0:1], pool.Manager(), waddrmgr.CKTPublic) if err != nil { t.Fatalf("Failed to encrypt public key: %v", err) } var encryptedPrivKeys [][]byte - TstRunWithManagerUnlocked(t, manager, func() { - encryptedPrivKeys, err = encryptKeys(TstPrivKeys[1:2], manager, waddrmgr.CKTPrivate) + TstRunWithManagerUnlocked(t, pool.Manager(), addrmgrNs, func() { + encryptedPrivKeys, err = encryptKeys(TstPrivKeys[1:2], pool.Manager(), waddrmgr.CKTPrivate) }) if err != nil { t.Fatalf("Failed to encrypt private key: %v", err) @@ -427,7 +467,7 @@ func TestValidateAndDecryptKeysErrors(t *testing.T) { } for i, test := range tests { - TstRunWithManagerUnlocked(t, manager, func() { + TstRunWithManagerUnlocked(t, pool.Manager(), addrmgrNs, func() { _, _, err = validateAndDecryptKeys(test.rawPubKeys, test.rawPrivKeys, pool) }) TstCheckError(t, fmt.Sprintf("Test #%d", i), err, test.err) diff --git a/votingpool/withdrawal_test.go b/votingpool/withdrawal_test.go index 4a27f08..1e1933e 100644 --- a/votingpool/withdrawal_test.go +++ b/votingpool/withdrawal_test.go @@ -14,8 +14,17 @@ import ( ) func TestStartWithdrawal(t *testing.T) { - tearDown, pool, store := vp.TstCreatePoolAndTxStore(t) + tearDown, db, pool, store := vp.TstCreatePoolAndTxStore(t) defer tearDown() + + dbtx, err := db.BeginReadWriteTx() + if err != nil { + t.Fatal(err) + } + defer dbtx.Commit() + ns, addrmgrNs := vp.TstRWNamespaces(dbtx) + txmgrNs := vp.TstTxStoreRWNamespace(dbtx) + mgr := pool.Manager() masters := []*hdkeychain.ExtendedKey{ @@ -23,9 +32,9 @@ func TestStartWithdrawal(t *testing.T) { vp.TstCreateMasterKey(t, bytes.Repeat([]byte{0x02, 0x01}, 16)), vp.TstCreateMasterKey(t, bytes.Repeat([]byte{0x03, 0x01}, 16))} def := vp.TstCreateSeriesDef(t, pool, 2, masters) - vp.TstCreateSeries(t, pool, []vp.TstSeriesDef{def}) + vp.TstCreateSeries(t, dbtx, pool, []vp.TstSeriesDef{def}) // Create eligible inputs and the list of outputs we need to fulfil. - vp.TstCreateSeriesCreditsOnStore(t, pool, def.SeriesID, []int64{5e6, 4e6}, store) + vp.TstCreateSeriesCreditsOnStore(t, dbtx, pool, def.SeriesID, []int64{5e6, 4e6}, store) address1 := "34eVkREKgvvGASZW7hkgE2uNc1yycntMK6" address2 := "3PbExiaztsSYgh6zeMswC49hLUwhTQ86XG" requests := []vp.OutputRequest{ @@ -34,15 +43,14 @@ func TestStartWithdrawal(t *testing.T) { } changeStart := vp.TstNewChangeAddress(t, pool, def.SeriesID, 0) - startAddr := vp.TstNewWithdrawalAddress(t, pool, def.SeriesID, 0, 0) + startAddr := vp.TstNewWithdrawalAddress(t, dbtx, pool, def.SeriesID, 0, 0) lastSeriesID := def.SeriesID dustThreshold := btcutil.Amount(1e4) currentBlock := int32(vp.TstInputsBlock + vp.TstEligibleInputMinConfirmations + 1) var status *vp.WithdrawalStatus - var err error - vp.TstRunWithManagerUnlocked(t, mgr, func() { - status, err = pool.StartWithdrawal(0, requests, *startAddr, lastSeriesID, *changeStart, - store, currentBlock, dustThreshold) + vp.TstRunWithManagerUnlocked(t, mgr, addrmgrNs, func() { + status, err = pool.StartWithdrawal(ns, addrmgrNs, 0, requests, *startAddr, lastSeriesID, *changeStart, + store, txmgrNs, currentBlock, dustThreshold) }) if err != nil { t.Fatal(err) @@ -79,8 +87,8 @@ func TestStartWithdrawal(t *testing.T) { // signatures). Must unlock the manager as signing involves looking up the // redeem script, which is stored encrypted. msgtx := status.TstGetMsgTx(ntxid) - vp.TstRunWithManagerUnlocked(t, mgr, func() { - if err = vp.SignTx(msgtx, txSigs, mgr, store); err != nil { + vp.TstRunWithManagerUnlocked(t, mgr, addrmgrNs, func() { + if err = vp.SignTx(msgtx, txSigs, mgr, addrmgrNs, store, txmgrNs); err != nil { t.Fatal(err) } }) @@ -88,9 +96,9 @@ func TestStartWithdrawal(t *testing.T) { // Any subsequent StartWithdrawal() calls with the same parameters will // return the previously stored WithdrawalStatus. var status2 *vp.WithdrawalStatus - vp.TstRunWithManagerUnlocked(t, mgr, func() { - status2, err = pool.StartWithdrawal(0, requests, *startAddr, lastSeriesID, *changeStart, - store, currentBlock, dustThreshold) + vp.TstRunWithManagerUnlocked(t, mgr, addrmgrNs, func() { + status2, err = pool.StartWithdrawal(ns, addrmgrNs, 0, requests, *startAddr, lastSeriesID, *changeStart, + store, txmgrNs, currentBlock, dustThreshold) }) if err != nil { t.Fatal(err) diff --git a/votingpool/withdrawal_wb_test.go b/votingpool/withdrawal_wb_test.go index 5d77819..5b24a7c 100644 --- a/votingpool/withdrawal_wb_test.go +++ b/votingpool/withdrawal_wb_test.go @@ -23,9 +23,15 @@ import ( // TestOutputSplittingNotEnoughInputs checks that an output will get split if we // don't have enough inputs to fulfil it. func TestOutputSplittingNotEnoughInputs(t *testing.T) { - tearDown, pool, _ := TstCreatePoolAndTxStore(t) + tearDown, db, pool := TstCreatePool(t) defer tearDown() + dbtx, err := db.BeginReadWriteTx() + if err != nil { + t.Fatal(err) + } + defer dbtx.Commit() + net := pool.Manager().ChainParams() output1Amount := btcutil.Amount(2) output2Amount := btcutil.Amount(3) @@ -36,7 +42,7 @@ func TestOutputSplittingNotEnoughInputs(t *testing.T) { TstNewOutputRequest(t, 1, "34eVkREKgvvGASZW7hkgE2uNc1yycntMK6", output1Amount, net), TstNewOutputRequest(t, 2, "34eVkREKgvvGASZW7hkgE2uNc1yycntMK6", output2Amount, net), } - seriesID, eligible := TstCreateCreditsOnNewSeries(t, pool, []int64{7}) + seriesID, eligible := TstCreateCreditsOnNewSeries(t, dbtx, pool, []int64{7}) w := newWithdrawal(0, requests, eligible, *TstNewChangeAddress(t, pool, seriesID, 0)) w.txOptions = func(tx *withdrawalTx) { // Trigger an output split because of lack of inputs by forcing a high fee. @@ -71,15 +77,21 @@ func TestOutputSplittingNotEnoughInputs(t *testing.T) { } func TestOutputSplittingOversizeTx(t *testing.T) { - tearDown, pool, _ := TstCreatePoolAndTxStore(t) + tearDown, db, pool := TstCreatePool(t) defer tearDown() + dbtx, err := db.BeginReadWriteTx() + if err != nil { + t.Fatal(err) + } + defer dbtx.Commit() + requestAmount := btcutil.Amount(5) bigInput := int64(3) smallInput := int64(2) request := TstNewOutputRequest( t, 1, "34eVkREKgvvGASZW7hkgE2uNc1yycntMK6", requestAmount, pool.Manager().ChainParams()) - seriesID, eligible := TstCreateCreditsOnNewSeries(t, pool, []int64{smallInput, bigInput}) + seriesID, eligible := TstCreateCreditsOnNewSeries(t, dbtx, pool, []int64{smallInput, bigInput}) changeStart := TstNewChangeAddress(t, pool, seriesID, 0) w := newWithdrawal(0, []OutputRequest{request}, eligible, *changeStart) w.txOptions = func(tx *withdrawalTx) { @@ -129,13 +141,19 @@ func TestOutputSplittingOversizeTx(t *testing.T) { } func TestSplitLastOutputNoOutputs(t *testing.T) { - tearDown, pool, _ := TstCreatePoolAndTxStore(t) + tearDown, db, pool := TstCreatePool(t) defer tearDown() - w := newWithdrawal(0, []OutputRequest{}, []credit{}, ChangeAddress{}) - w.current = createWithdrawalTx(t, pool, []int64{}, []int64{}) + dbtx, err := db.BeginReadWriteTx() + if err != nil { + t.Fatal(err) + } + defer dbtx.Commit() - err := w.splitLastOutput() + w := newWithdrawal(0, []OutputRequest{}, []credit{}, ChangeAddress{}) + w.current = createWithdrawalTx(t, dbtx, pool, []int64{}, []int64{}) + + err = w.splitLastOutput() TstCheckError(t, "", err, ErrPreconditionNotMet) } @@ -143,12 +161,19 @@ func TestSplitLastOutputNoOutputs(t *testing.T) { // Check that all outputs requested in a withdrawal match the outputs of the generated // transaction(s). func TestWithdrawalTxOutputs(t *testing.T) { - tearDown, pool, _ := TstCreatePoolAndTxStore(t) + tearDown, db, pool := TstCreatePool(t) defer tearDown() + + dbtx, err := db.BeginReadWriteTx() + if err != nil { + t.Fatal(err) + } + defer dbtx.Commit() + net := pool.Manager().ChainParams() // Create eligible inputs and the list of outputs we need to fulfil. - seriesID, eligible := TstCreateCreditsOnNewSeries(t, pool, []int64{2e6, 4e6}) + seriesID, eligible := TstCreateCreditsOnNewSeries(t, dbtx, pool, []int64{2e6, 4e6}) outputs := []OutputRequest{ TstNewOutputRequest(t, 1, "34eVkREKgvvGASZW7hkgE2uNc1yycntMK6", 3e6, net), TstNewOutputRequest(t, 2, "3PbExiaztsSYgh6zeMswC49hLUwhTQ86XG", 2e6, net), @@ -178,10 +203,16 @@ func TestWithdrawalTxOutputs(t *testing.T) { // Check that withdrawal.status correctly states that no outputs were fulfilled when we // don't have enough eligible credits for any of them. func TestFulfillRequestsNoSatisfiableOutputs(t *testing.T) { - tearDown, pool, _ := TstCreatePoolAndTxStore(t) + tearDown, db, pool := TstCreatePool(t) defer tearDown() - seriesID, eligible := TstCreateCreditsOnNewSeries(t, pool, []int64{1e6}) + dbtx, err := db.BeginReadWriteTx() + if err != nil { + t.Fatal(err) + } + defer dbtx.Commit() + + seriesID, eligible := TstCreateCreditsOnNewSeries(t, dbtx, pool, []int64{1e6}) request := TstNewOutputRequest( t, 1, "3Qt1EaKRD9g9FeL2DGkLLswhK1AKmmXFSe", btcutil.Amount(3e6), pool.Manager().ChainParams()) changeStart := TstNewChangeAddress(t, pool, seriesID, 0) @@ -210,12 +241,19 @@ func TestFulfillRequestsNoSatisfiableOutputs(t *testing.T) { // Check that some requested outputs are not fulfilled when we don't have credits for all // of them. func TestFulfillRequestsNotEnoughCreditsForAllRequests(t *testing.T) { - tearDown, pool, _ := TstCreatePoolAndTxStore(t) + tearDown, db, pool := TstCreatePool(t) defer tearDown() + + dbtx, err := db.BeginReadWriteTx() + if err != nil { + t.Fatal(err) + } + defer dbtx.Commit() + net := pool.Manager().ChainParams() // Create eligible inputs and the list of outputs we need to fulfil. - seriesID, eligible := TstCreateCreditsOnNewSeries(t, pool, []int64{2e6, 4e6}) + seriesID, eligible := TstCreateCreditsOnNewSeries(t, dbtx, pool, []int64{2e6, 4e6}) out1 := TstNewOutputRequest( t, 1, "34eVkREKgvvGASZW7hkgE2uNc1yycntMK6", btcutil.Amount(3e6), net) out2 := TstNewOutputRequest( @@ -261,10 +299,16 @@ func TestFulfillRequestsNotEnoughCreditsForAllRequests(t *testing.T) { // TestRollbackLastOutput tests the case where we rollback one output // and one input, such that sum(in) >= sum(out) + fee. func TestRollbackLastOutput(t *testing.T) { - tearDown, pool, _ := TstCreatePoolAndTxStore(t) + tearDown, db, pool := TstCreatePool(t) defer tearDown() - tx := createWithdrawalTx(t, pool, []int64{3, 3, 2, 1, 3}, []int64{3, 3, 2, 2}) + dbtx, err := db.BeginReadWriteTx() + if err != nil { + t.Fatal(err) + } + defer dbtx.Commit() + + tx := createWithdrawalTx(t, dbtx, pool, []int64{3, 3, 2, 1, 3}, []int64{3, 3, 2, 2}) initialInputs := tx.inputs initialOutputs := tx.outputs @@ -295,12 +339,18 @@ func TestRollbackLastOutput(t *testing.T) { } func TestRollbackLastOutputMultipleInputsRolledBack(t *testing.T) { - tearDown, pool, _ := TstCreatePoolAndTxStore(t) + tearDown, db, pool := TstCreatePool(t) defer tearDown() + dbtx, err := db.BeginReadWriteTx() + if err != nil { + t.Fatal(err) + } + defer dbtx.Commit() + // This tx will need the 3 last inputs to fulfill the second output, so they // should all be rolled back and returned in the reverse order they were added. - tx := createWithdrawalTx(t, pool, []int64{1, 2, 3, 4}, []int64{1, 8}) + tx := createWithdrawalTx(t, dbtx, pool, []int64{1, 2, 3, 4}, []int64{1, 8}) initialInputs := tx.inputs initialOutputs := tx.outputs @@ -328,10 +378,16 @@ func TestRollbackLastOutputMultipleInputsRolledBack(t *testing.T) { // TestRollbackLastOutputNoInputsRolledBack tests the case where we roll back // one output but don't need to roll back any inputs. func TestRollbackLastOutputNoInputsRolledBack(t *testing.T) { - tearDown, pool, _ := TstCreatePoolAndTxStore(t) + tearDown, db, pool := TstCreatePool(t) defer tearDown() - tx := createWithdrawalTx(t, pool, []int64{4}, []int64{2, 3}) + dbtx, err := db.BeginReadWriteTx() + if err != nil { + t.Fatal(err) + } + defer dbtx.Commit() + + tx := createWithdrawalTx(t, dbtx, pool, []int64{4}, []int64{2, 3}) initialInputs := tx.inputs initialOutputs := tx.outputs @@ -375,11 +431,17 @@ func TestRollBackLastOutputInsufficientOutputs(t *testing.T) { // TestRollbackLastOutputWhenNewOutputAdded checks that we roll back the last // output if a tx becomes too big right after we add a new output to it. func TestRollbackLastOutputWhenNewOutputAdded(t *testing.T) { - tearDown, pool, _ := TstCreatePoolAndTxStore(t) + tearDown, db, pool := TstCreatePool(t) defer tearDown() + dbtx, err := db.BeginReadWriteTx() + if err != nil { + t.Fatal(err) + } + defer dbtx.Commit() + net := pool.Manager().ChainParams() - series, eligible := TstCreateCreditsOnNewSeries(t, pool, []int64{5, 5}) + series, eligible := TstCreateCreditsOnNewSeries(t, dbtx, pool, []int64{5, 5}) requests := []OutputRequest{ // This is ordered by bailment ID TstNewOutputRequest(t, 1, "34eVkREKgvvGASZW7hkgE2uNc1yycntMK6", 1, net), @@ -427,11 +489,17 @@ func TestRollbackLastOutputWhenNewOutputAdded(t *testing.T) { // TestRollbackLastOutputWhenNewInputAdded checks that we roll back the last // output if a tx becomes too big right after we add a new input to it. func TestRollbackLastOutputWhenNewInputAdded(t *testing.T) { - tearDown, pool, _ := TstCreatePoolAndTxStore(t) + tearDown, db, pool := TstCreatePool(t) defer tearDown() + dbtx, err := db.BeginReadWriteTx() + if err != nil { + t.Fatal(err) + } + defer dbtx.Commit() + net := pool.Manager().ChainParams() - series, eligible := TstCreateCreditsOnNewSeries(t, pool, []int64{6, 5, 4, 3, 2, 1}) + series, eligible := TstCreateCreditsOnNewSeries(t, dbtx, pool, []int64{6, 5, 4, 3, 2, 1}) requests := []OutputRequest{ // This is manually ordered by outBailmentIDHash, which is the order in // which they're going to be fulfilled by w.fulfillRequests(). @@ -486,10 +554,16 @@ func TestRollbackLastOutputWhenNewInputAdded(t *testing.T) { } func TestWithdrawalTxRemoveOutput(t *testing.T) { - tearDown, pool, _ := TstCreatePoolAndTxStore(t) + tearDown, db, pool := TstCreatePool(t) defer tearDown() - tx := createWithdrawalTx(t, pool, []int64{}, []int64{1, 2}) + dbtx, err := db.BeginReadWriteTx() + if err != nil { + t.Fatal(err) + } + defer dbtx.Commit() + + tx := createWithdrawalTx(t, dbtx, pool, []int64{}, []int64{1, 2}) outputs := tx.outputs // Make sure we have created the transaction with the expected // outputs. @@ -514,10 +588,16 @@ func TestWithdrawalTxRemoveOutput(t *testing.T) { } func TestWithdrawalTxRemoveInput(t *testing.T) { - tearDown, pool, _ := TstCreatePoolAndTxStore(t) + tearDown, db, pool := TstCreatePool(t) defer tearDown() - tx := createWithdrawalTx(t, pool, []int64{1, 2}, []int64{}) + dbtx, err := db.BeginReadWriteTx() + if err != nil { + t.Fatal(err) + } + defer dbtx.Commit() + + tx := createWithdrawalTx(t, dbtx, pool, []int64{1, 2}, []int64{}) inputs := tx.inputs // Make sure we have created the transaction with the expected inputs checkTxInputs(t, tx, inputs) @@ -540,11 +620,17 @@ func TestWithdrawalTxRemoveInput(t *testing.T) { } func TestWithdrawalTxAddChange(t *testing.T) { - tearDown, pool, _ := TstCreatePoolAndTxStore(t) + tearDown, db, pool := TstCreatePool(t) defer tearDown() + dbtx, err := db.BeginReadWriteTx() + if err != nil { + t.Fatal(err) + } + defer dbtx.Commit() + input, output, fee := int64(4e6), int64(3e6), int64(10) - tx := createWithdrawalTx(t, pool, []int64{input}, []int64{output}) + tx := createWithdrawalTx(t, dbtx, pool, []int64{input}, []int64{output}) tx.calculateFee = TstConstantFee(btcutil.Amount(fee)) if !tx.addChange([]byte{}) { @@ -566,11 +652,17 @@ func TestWithdrawalTxAddChange(t *testing.T) { // add a change output when there's no satoshis left after paying all // outputs+fees. func TestWithdrawalTxAddChangeNoChange(t *testing.T) { - tearDown, pool, _ := TstCreatePoolAndTxStore(t) + tearDown, db, pool := TstCreatePool(t) defer tearDown() + dbtx, err := db.BeginReadWriteTx() + if err != nil { + t.Fatal(err) + } + defer dbtx.Commit() + input, output, fee := int64(4e6), int64(4e6), int64(0) - tx := createWithdrawalTx(t, pool, []int64{input}, []int64{output}) + tx := createWithdrawalTx(t, dbtx, pool, []int64{input}, []int64{output}) tx.calculateFee = TstConstantFee(btcutil.Amount(fee)) if tx.addChange([]byte{}) { @@ -583,20 +675,32 @@ func TestWithdrawalTxAddChangeNoChange(t *testing.T) { } func TestWithdrawalTxToMsgTxNoInputsOrOutputsOrChange(t *testing.T) { - tearDown, pool, _ := TstCreatePoolAndTxStore(t) + tearDown, db, pool := TstCreatePool(t) defer tearDown() - tx := createWithdrawalTx(t, pool, []int64{}, []int64{}) + dbtx, err := db.BeginReadWriteTx() + if err != nil { + t.Fatal(err) + } + defer dbtx.Commit() + + tx := createWithdrawalTx(t, dbtx, pool, []int64{}, []int64{}) msgtx := tx.toMsgTx() compareMsgTxAndWithdrawalTxOutputs(t, msgtx, tx) compareMsgTxAndWithdrawalTxInputs(t, msgtx, tx) } func TestWithdrawalTxToMsgTxNoInputsOrOutputsWithChange(t *testing.T) { - tearDown, pool, _ := TstCreatePoolAndTxStore(t) + tearDown, db, pool := TstCreatePool(t) defer tearDown() - tx := createWithdrawalTx(t, pool, []int64{}, []int64{}) + dbtx, err := db.BeginReadWriteTx() + if err != nil { + t.Fatal(err) + } + defer dbtx.Commit() + + tx := createWithdrawalTx(t, dbtx, pool, []int64{}, []int64{}) tx.changeOutput = wire.NewTxOut(int64(1), []byte{}) msgtx := tx.toMsgTx() @@ -606,10 +710,16 @@ func TestWithdrawalTxToMsgTxNoInputsOrOutputsWithChange(t *testing.T) { } func TestWithdrawalTxToMsgTxWithInputButNoOutputsWithChange(t *testing.T) { - tearDown, pool, _ := TstCreatePoolAndTxStore(t) + tearDown, db, pool := TstCreatePool(t) defer tearDown() - tx := createWithdrawalTx(t, pool, []int64{1}, []int64{}) + dbtx, err := db.BeginReadWriteTx() + if err != nil { + t.Fatal(err) + } + defer dbtx.Commit() + + tx := createWithdrawalTx(t, dbtx, pool, []int64{1}, []int64{}) tx.changeOutput = wire.NewTxOut(int64(1), []byte{}) msgtx := tx.toMsgTx() @@ -619,11 +729,16 @@ func TestWithdrawalTxToMsgTxWithInputButNoOutputsWithChange(t *testing.T) { } func TestWithdrawalTxToMsgTxWithInputOutputsAndChange(t *testing.T) { - tearDown, pool, _ := TstCreatePoolAndTxStore(t) - + tearDown, db, pool := TstCreatePool(t) defer tearDown() - tx := createWithdrawalTx(t, pool, []int64{1, 2, 3}, []int64{4, 5, 6}) + dbtx, err := db.BeginReadWriteTx() + if err != nil { + t.Fatal(err) + } + defer dbtx.Commit() + + tx := createWithdrawalTx(t, dbtx, pool, []int64{1, 2, 3}, []int64{4, 5, 6}) tx.changeOutput = wire.NewTxOut(int64(7), []byte{}) msgtx := tx.toMsgTx() @@ -633,10 +748,16 @@ func TestWithdrawalTxToMsgTxWithInputOutputsAndChange(t *testing.T) { } func TestWithdrawalTxInputTotal(t *testing.T) { - tearDown, pool, _ := TstCreatePoolAndTxStore(t) + tearDown, db, pool := TstCreatePool(t) defer tearDown() - tx := createWithdrawalTx(t, pool, []int64{5}, []int64{}) + dbtx, err := db.BeginReadWriteTx() + if err != nil { + t.Fatal(err) + } + defer dbtx.Commit() + + tx := createWithdrawalTx(t, dbtx, pool, []int64{5}, []int64{}) if tx.inputTotal() != btcutil.Amount(5) { t.Fatalf("Wrong total output; got %v, want %v", tx.outputTotal(), btcutil.Amount(5)) @@ -644,10 +765,16 @@ func TestWithdrawalTxInputTotal(t *testing.T) { } func TestWithdrawalTxOutputTotal(t *testing.T) { - tearDown, pool, _ := TstCreatePoolAndTxStore(t) + tearDown, db, pool := TstCreatePool(t) defer tearDown() - tx := createWithdrawalTx(t, pool, []int64{}, []int64{4}) + dbtx, err := db.BeginReadWriteTx() + if err != nil { + t.Fatal(err) + } + defer dbtx.Commit() + + tx := createWithdrawalTx(t, dbtx, pool, []int64{}, []int64{4}) tx.changeOutput = wire.NewTxOut(int64(1), []byte{}) if tx.outputTotal() != btcutil.Amount(4) { @@ -656,18 +783,24 @@ func TestWithdrawalTxOutputTotal(t *testing.T) { } func TestWithdrawalInfoMatch(t *testing.T) { - tearDown, _, pool := TstCreatePool(t) + tearDown, db, pool := TstCreatePool(t) defer tearDown() + dbtx, err := db.BeginReadWriteTx() + if err != nil { + t.Fatal(err) + } + defer dbtx.Commit() + roundID := uint32(0) - wi := createAndFulfillWithdrawalRequests(t, pool, roundID) + wi := createAndFulfillWithdrawalRequests(t, dbtx, pool, roundID) // Use freshly created values for requests, startAddress and changeStart // to simulate what would happen if we had recreated them from the // serialized data in the DB. requestsCopy := make([]OutputRequest, len(wi.requests)) copy(requestsCopy, wi.requests) - startAddr := TstNewWithdrawalAddress(t, pool, wi.startAddress.seriesID, wi.startAddress.branch, + startAddr := TstNewWithdrawalAddress(t, dbtx, pool, wi.startAddress.seriesID, wi.startAddress.branch, wi.startAddress.index) changeStart := TstNewChangeAddress(t, pool, wi.changeStart.seriesID, wi.changeStart.index) @@ -708,7 +841,7 @@ func TestWithdrawalInfoMatch(t *testing.T) { } // It should not match when startAddress is not equal. - diffStartAddr := TstNewWithdrawalAddress(t, pool, startAddr.seriesID, startAddr.branch+1, + diffStartAddr := TstNewWithdrawalAddress(t, dbtx, pool, startAddr.seriesID, startAddr.branch+1, startAddr.index) matches = wi.match(requestsCopy, *diffStartAddr, wi.lastSeriesID, *changeStart, wi.dustThreshold) @@ -726,29 +859,33 @@ func TestWithdrawalInfoMatch(t *testing.T) { } func TestGetWithdrawalStatus(t *testing.T) { - tearDown, _, pool := TstCreatePool(t) + tearDown, db, pool := TstCreatePool(t) defer tearDown() + dbtx, err := db.BeginReadWriteTx() + if err != nil { + t.Fatal(err) + } + defer dbtx.Commit() + ns, addrmgrNs := TstRWNamespaces(dbtx) + roundID := uint32(0) - wi := createAndFulfillWithdrawalRequests(t, pool, roundID) + wi := createAndFulfillWithdrawalRequests(t, dbtx, pool, roundID) serialized, err := serializeWithdrawal(wi.requests, wi.startAddress, wi.lastSeriesID, wi.changeStart, wi.dustThreshold, wi.status) if err != nil { t.Fatal(err) } - err = pool.namespace.Update( - func(tx walletdb.Tx) error { - return putWithdrawal(tx, pool.ID, roundID, serialized) - }) + err = putWithdrawal(ns, pool.ID, roundID, serialized) if err != nil { t.Fatal(err) } // Here we should get a WithdrawalStatus that matches wi.status. var status *WithdrawalStatus - TstRunWithManagerUnlocked(t, pool.Manager(), func() { - status, err = getWithdrawalStatus(pool, roundID, wi.requests, wi.startAddress, + TstRunWithManagerUnlocked(t, pool.Manager(), addrmgrNs, func() { + status, err = getWithdrawalStatus(pool, ns, addrmgrNs, roundID, wi.requests, wi.startAddress, wi.lastSeriesID, wi.changeStart, wi.dustThreshold) }) if err != nil { @@ -759,8 +896,8 @@ func TestGetWithdrawalStatus(t *testing.T) { // Here we should get a nil WithdrawalStatus because the parameters are not // identical to those of the stored WithdrawalStatus with this roundID. dustThreshold := wi.dustThreshold + 1 - TstRunWithManagerUnlocked(t, pool.Manager(), func() { - status, err = getWithdrawalStatus(pool, roundID, wi.requests, wi.startAddress, + TstRunWithManagerUnlocked(t, pool.Manager(), addrmgrNs, func() { + status, err = getWithdrawalStatus(pool, ns, addrmgrNs, roundID, wi.requests, wi.startAddress, wi.lastSeriesID, wi.changeStart, dustThreshold) }) if err != nil { @@ -772,12 +909,19 @@ func TestGetWithdrawalStatus(t *testing.T) { } func TestSignMultiSigUTXO(t *testing.T) { - tearDown, pool, _ := TstCreatePoolAndTxStore(t) + tearDown, db, pool := TstCreatePool(t) defer tearDown() + dbtx, err := db.BeginReadWriteTx() + if err != nil { + t.Fatal(err) + } + defer dbtx.Commit() + _, addrmgrNs := TstRWNamespaces(dbtx) + // Create a new tx with a single input that we're going to sign. mgr := pool.Manager() - tx := createWithdrawalTx(t, pool, []int64{4e6}, []int64{4e6}) + tx := createWithdrawalTx(t, dbtx, pool, []int64{4e6}, []int64{4e6}) sigs, err := getRawSigs([]*withdrawalTx{tx}) if err != nil { t.Fatal(err) @@ -788,68 +932,96 @@ func TestSignMultiSigUTXO(t *testing.T) { idx := 0 // The index of the tx input we're going to sign. pkScript := tx.inputs[idx].PkScript - TstRunWithManagerUnlocked(t, mgr, func() { - if err = signMultiSigUTXO(mgr, msgtx, idx, pkScript, txSigs[idx]); err != nil { + TstRunWithManagerUnlocked(t, mgr, addrmgrNs, func() { + if err = signMultiSigUTXO(mgr, addrmgrNs, msgtx, idx, pkScript, txSigs[idx]); err != nil { t.Fatal(err) } }) } func TestSignMultiSigUTXOUnparseablePkScript(t *testing.T) { - tearDown, pool, _ := TstCreatePoolAndTxStore(t) + tearDown, db, pool := TstCreatePool(t) defer tearDown() + dbtx, err := db.BeginReadWriteTx() + if err != nil { + t.Fatal(err) + } + defer dbtx.Commit() + _, addrmgrNs := TstRWNamespaces(dbtx) + mgr := pool.Manager() - tx := createWithdrawalTx(t, pool, []int64{4e6}, []int64{}) + tx := createWithdrawalTx(t, dbtx, pool, []int64{4e6}, []int64{}) msgtx := tx.toMsgTx() unparseablePkScript := []byte{0x01} - err := signMultiSigUTXO(mgr, msgtx, 0, unparseablePkScript, []RawSig{{}}) + err = signMultiSigUTXO(mgr, addrmgrNs, msgtx, 0, unparseablePkScript, []RawSig{{}}) TstCheckError(t, "", err, ErrTxSigning) } func TestSignMultiSigUTXOPkScriptNotP2SH(t *testing.T) { - tearDown, pool, _ := TstCreatePoolAndTxStore(t) + tearDown, db, pool := TstCreatePool(t) defer tearDown() + dbtx, err := db.BeginReadWriteTx() + if err != nil { + t.Fatal(err) + } + defer dbtx.Commit() + _, addrmgrNs := TstRWNamespaces(dbtx) + mgr := pool.Manager() - tx := createWithdrawalTx(t, pool, []int64{4e6}, []int64{}) + tx := createWithdrawalTx(t, dbtx, pool, []int64{4e6}, []int64{}) addr, _ := btcutil.DecodeAddress("1MirQ9bwyQcGVJPwKUgapu5ouK2E2Ey4gX", mgr.ChainParams()) pubKeyHashPkScript, _ := txscript.PayToAddrScript(addr.(*btcutil.AddressPubKeyHash)) msgtx := tx.toMsgTx() - err := signMultiSigUTXO(mgr, msgtx, 0, pubKeyHashPkScript, []RawSig{{}}) + err = signMultiSigUTXO(mgr, addrmgrNs, msgtx, 0, pubKeyHashPkScript, []RawSig{{}}) TstCheckError(t, "", err, ErrTxSigning) } func TestSignMultiSigUTXORedeemScriptNotFound(t *testing.T) { - tearDown, pool, _ := TstCreatePoolAndTxStore(t) + tearDown, db, pool := TstCreatePool(t) defer tearDown() + dbtx, err := db.BeginReadWriteTx() + if err != nil { + t.Fatal(err) + } + defer dbtx.Commit() + _, addrmgrNs := TstRWNamespaces(dbtx) + mgr := pool.Manager() - tx := createWithdrawalTx(t, pool, []int64{4e6}, []int64{}) + tx := createWithdrawalTx(t, dbtx, pool, []int64{4e6}, []int64{}) // This is a P2SH address for which the addr manager doesn't have the redeem // script. addr, _ := btcutil.DecodeAddress("3Hb4xcebcKg4DiETJfwjh8sF4uDw9rqtVC", mgr.ChainParams()) - if _, err := mgr.Address(addr); err == nil { + if _, err := mgr.Address(addrmgrNs, addr); err == nil { t.Fatalf("Address %s found in manager when it shouldn't", addr) } msgtx := tx.toMsgTx() pkScript, _ := txscript.PayToAddrScript(addr.(*btcutil.AddressScriptHash)) - err := signMultiSigUTXO(mgr, msgtx, 0, pkScript, []RawSig{{}}) + err = signMultiSigUTXO(mgr, addrmgrNs, msgtx, 0, pkScript, []RawSig{{}}) TstCheckError(t, "", err, ErrTxSigning) } func TestSignMultiSigUTXONotEnoughSigs(t *testing.T) { - tearDown, pool, _ := TstCreatePoolAndTxStore(t) + tearDown, db, pool := TstCreatePool(t) defer tearDown() + dbtx, err := db.BeginReadWriteTx() + if err != nil { + t.Fatal(err) + } + defer dbtx.Commit() + _, addrmgrNs := TstRWNamespaces(dbtx) + mgr := pool.Manager() - tx := createWithdrawalTx(t, pool, []int64{4e6}, []int64{}) + tx := createWithdrawalTx(t, dbtx, pool, []int64{4e6}, []int64{}) sigs, err := getRawSigs([]*withdrawalTx{tx}) if err != nil { t.Fatal(err) @@ -862,36 +1034,49 @@ func TestSignMultiSigUTXONotEnoughSigs(t *testing.T) { reqSigs := tx.inputs[idx].addr.series().TstGetReqSigs() txInSigs := txSigs[idx][:reqSigs-1] pkScript := tx.inputs[idx].PkScript - TstRunWithManagerUnlocked(t, mgr, func() { - err = signMultiSigUTXO(mgr, msgtx, idx, pkScript, txInSigs) + TstRunWithManagerUnlocked(t, mgr, addrmgrNs, func() { + err = signMultiSigUTXO(mgr, addrmgrNs, msgtx, idx, pkScript, txInSigs) }) TstCheckError(t, "", err, ErrTxSigning) } func TestSignMultiSigUTXOWrongRawSigs(t *testing.T) { - tearDown, pool, _ := TstCreatePoolAndTxStore(t) + tearDown, db, pool := TstCreatePool(t) defer tearDown() + dbtx, err := db.BeginReadWriteTx() + if err != nil { + t.Fatal(err) + } + defer dbtx.Commit() + _, addrmgrNs := TstRWNamespaces(dbtx) + mgr := pool.Manager() - tx := createWithdrawalTx(t, pool, []int64{4e6}, []int64{}) + tx := createWithdrawalTx(t, dbtx, pool, []int64{4e6}, []int64{}) sigs := []RawSig{{0x00}, {0x01}} idx := 0 // The index of the tx input we're going to sign. pkScript := tx.inputs[idx].PkScript - var err error - TstRunWithManagerUnlocked(t, mgr, func() { - err = signMultiSigUTXO(mgr, tx.toMsgTx(), idx, pkScript, sigs) + TstRunWithManagerUnlocked(t, mgr, addrmgrNs, func() { + err = signMultiSigUTXO(mgr, addrmgrNs, tx.toMsgTx(), idx, pkScript, sigs) }) TstCheckError(t, "", err, ErrTxSigning) } func TestGetRawSigs(t *testing.T) { - tearDown, pool, _ := TstCreatePoolAndTxStore(t) + tearDown, db, pool := TstCreatePool(t) defer tearDown() - tx := createWithdrawalTx(t, pool, []int64{5e6, 4e6}, []int64{}) + dbtx, err := db.BeginReadWriteTx() + if err != nil { + t.Fatal(err) + } + defer dbtx.Commit() + _, addrmgrNs := TstRWNamespaces(dbtx) + + tx := createWithdrawalTx(t, dbtx, pool, []int64{5e6, 4e6}, []int64{}) sigs, err := getRawSigs([]*withdrawalTx{tx}) if err != nil { @@ -908,14 +1093,20 @@ func TestGetRawSigs(t *testing.T) { // Since we have all the necessary signatures (m-of-n), we construct the // sigsnature scripts and execute them to make sure the raw signatures are // valid. - signTxAndValidate(t, pool.Manager(), msgtx, txSigs, tx.inputs) + signTxAndValidate(t, pool.Manager(), addrmgrNs, msgtx, txSigs, tx.inputs) } func TestGetRawSigsOnlyOnePrivKeyAvailable(t *testing.T) { - tearDown, pool, _ := TstCreatePoolAndTxStore(t) + tearDown, db, pool := TstCreatePool(t) defer tearDown() - tx := createWithdrawalTx(t, pool, []int64{5e6, 4e6}, []int64{}) + dbtx, err := db.BeginReadWriteTx() + if err != nil { + t.Fatal(err) + } + defer dbtx.Commit() + + tx := createWithdrawalTx(t, dbtx, pool, []int64{5e6, 4e6}, []int64{}) // Remove all private keys but the first one from the credit's series. series := tx.inputs[0].addr.series() for i := range series.privateKeys[1:] { @@ -936,29 +1127,41 @@ func TestGetRawSigsOnlyOnePrivKeyAvailable(t *testing.T) { } func TestGetRawSigsUnparseableRedeemScript(t *testing.T) { - tearDown, pool, _ := TstCreatePoolAndTxStore(t) + tearDown, db, pool := TstCreatePool(t) defer tearDown() - tx := createWithdrawalTx(t, pool, []int64{5e6, 4e6}, []int64{}) + dbtx, err := db.BeginReadWriteTx() + if err != nil { + t.Fatal(err) + } + defer dbtx.Commit() + + tx := createWithdrawalTx(t, dbtx, pool, []int64{5e6, 4e6}, []int64{}) // Change the redeem script for one of our tx inputs, to force an error in // getRawSigs(). tx.inputs[0].addr.script = []byte{0x01} - _, err := getRawSigs([]*withdrawalTx{tx}) + _, err = getRawSigs([]*withdrawalTx{tx}) TstCheckError(t, "", err, ErrRawSigning) } func TestGetRawSigsInvalidAddrBranch(t *testing.T) { - tearDown, pool, _ := TstCreatePoolAndTxStore(t) + tearDown, db, pool := TstCreatePool(t) defer tearDown() - tx := createWithdrawalTx(t, pool, []int64{5e6, 4e6}, []int64{}) + dbtx, err := db.BeginReadWriteTx() + if err != nil { + t.Fatal(err) + } + defer dbtx.Commit() + + tx := createWithdrawalTx(t, dbtx, pool, []int64{5e6, 4e6}, []int64{}) // Change the branch of our input's address to an invalid value, to force // an error in getRawSigs(). tx.inputs[0].addr.branch = Branch(999) - _, err := getRawSigs([]*withdrawalTx{tx}) + _, err = getRawSigs([]*withdrawalTx{tx}) TstCheckError(t, "", err, ErrInvalidBranch) } @@ -982,10 +1185,16 @@ func TestOutBailmentIDSort(t *testing.T) { } func TestTxTooBig(t *testing.T) { - tearDown, pool, _ := TstCreatePoolAndTxStore(t) + tearDown, db, pool := TstCreatePool(t) defer tearDown() - tx := createWithdrawalTx(t, pool, []int64{5}, []int64{1}) + dbtx, err := db.BeginReadWriteTx() + if err != nil { + t.Fatal(err) + } + defer dbtx.Commit() + + tx := createWithdrawalTx(t, dbtx, pool, []int64{5}, []int64{1}) tx.calculateSize = func() int { return txMaxSize - 1 } if tx.isTooBig() { @@ -1008,10 +1217,17 @@ func TestTxTooBig(t *testing.T) { } func TestTxSizeCalculation(t *testing.T) { - tearDown, pool, _ := TstCreatePoolAndTxStore(t) + tearDown, db, pool := TstCreatePool(t) defer tearDown() - tx := createWithdrawalTx(t, pool, []int64{1, 5}, []int64{2}) + dbtx, err := db.BeginReadWriteTx() + if err != nil { + t.Fatal(err) + } + defer dbtx.Commit() + _, addrmgrNs := TstRWNamespaces(dbtx) + + tx := createWithdrawalTx(t, dbtx, pool, []int64{1, 5}, []int64{2}) size := tx.calculateSize() @@ -1027,7 +1243,7 @@ func TestTxSizeCalculation(t *testing.T) { if err != nil { t.Fatal(err) } - signTxAndValidate(t, pool.Manager(), msgtx, sigs[tx.ntxid()], tx.inputs) + signTxAndValidate(t, pool.Manager(), addrmgrNs, msgtx, sigs[tx.ntxid()], tx.inputs) // ECDSA signatures have variable length (71-73 bytes) but in // calculateSize() we use a dummy signature for the worst-case scenario (73 @@ -1080,16 +1296,23 @@ func TestTxFeeEstimationForLargeTx(t *testing.T) { } func TestStoreTransactionsWithoutChangeOutput(t *testing.T) { - tearDown, pool, store := TstCreatePoolAndTxStore(t) + tearDown, db, pool, store := TstCreatePoolAndTxStore(t) defer tearDown() - wtx := createWithdrawalTxWithStoreCredits(t, store, pool, []int64{4e6}, []int64{3e6}) + dbtx, err := db.BeginReadWriteTx() + if err != nil { + t.Fatal(err) + } + defer dbtx.Commit() + txmgrNs := dbtx.ReadWriteBucket(txmgrNamespaceKey) + + wtx := createWithdrawalTxWithStoreCredits(t, dbtx, store, pool, []int64{4e6}, []int64{3e6}) tx := &changeAwareTx{MsgTx: wtx.toMsgTx(), changeIdx: int32(-1)} - if err := storeTransactions(store, []*changeAwareTx{tx}); err != nil { + if err := storeTransactions(store, txmgrNs, []*changeAwareTx{tx}); err != nil { t.Fatal(err) } - credits, err := store.UnspentOutputs() + credits, err := store.UnspentOutputs(txmgrNs) if err != nil { t.Fatal(err) } @@ -1099,20 +1322,27 @@ func TestStoreTransactionsWithoutChangeOutput(t *testing.T) { } func TestStoreTransactionsWithChangeOutput(t *testing.T) { - tearDown, pool, store := TstCreatePoolAndTxStore(t) + tearDown, db, pool, store := TstCreatePoolAndTxStore(t) defer tearDown() - wtx := createWithdrawalTxWithStoreCredits(t, store, pool, []int64{5e6}, []int64{1e6, 1e6}) + dbtx, err := db.BeginReadWriteTx() + if err != nil { + t.Fatal(err) + } + defer dbtx.Commit() + txmgrNs := dbtx.ReadWriteBucket(txmgrNamespaceKey) + + wtx := createWithdrawalTxWithStoreCredits(t, dbtx, store, pool, []int64{5e6}, []int64{1e6, 1e6}) wtx.changeOutput = wire.NewTxOut(int64(3e6), []byte{}) msgtx := wtx.toMsgTx() tx := &changeAwareTx{MsgTx: msgtx, changeIdx: int32(len(msgtx.TxOut) - 1)} - if err := storeTransactions(store, []*changeAwareTx{tx}); err != nil { + if err := storeTransactions(store, txmgrNs, []*changeAwareTx{tx}); err != nil { t.Fatal(err) } hash := msgtx.TxHash() - txDetails, err := store.TxDetails(&hash) + txDetails, err := store.TxDetails(txmgrNs, &hash) if err != nil { t.Fatal(err) } @@ -1139,7 +1369,7 @@ func TestStoreTransactionsWithChangeOutput(t *testing.T) { t.Fatalf("Unexpected input amount; got %v, want %v", inputTotal, btcutil.Amount(5e6)) } - credits, err := store.UnspentOutputs() + credits, err := store.UnspentOutputs(txmgrNs) if err != nil { t.Fatal(err) } @@ -1156,7 +1386,7 @@ func TestStoreTransactionsWithChangeOutput(t *testing.T) { // createWithdrawalTxWithStoreCredits creates a new Credit in the given store // for each entry in inputAmounts, and uses them to construct a withdrawalTx // with one output for every entry in outputAmounts. -func createWithdrawalTxWithStoreCredits(t *testing.T, store *wtxmgr.Store, pool *Pool, +func createWithdrawalTxWithStoreCredits(t *testing.T, dbtx walletdb.ReadWriteTx, store *wtxmgr.Store, pool *Pool, inputAmounts []int64, outputAmounts []int64) *withdrawalTx { masters := []*hdkeychain.ExtendedKey{ TstCreateMasterKey(t, bytes.Repeat(uint32ToBytes(getUniqueID()), 4)), @@ -1164,10 +1394,10 @@ func createWithdrawalTxWithStoreCredits(t *testing.T, store *wtxmgr.Store, pool TstCreateMasterKey(t, bytes.Repeat(uint32ToBytes(getUniqueID()), 4)), } def := TstCreateSeriesDef(t, pool, 2, masters) - TstCreateSeries(t, pool, []TstSeriesDef{def}) + TstCreateSeries(t, dbtx, pool, []TstSeriesDef{def}) net := pool.Manager().ChainParams() tx := newWithdrawalTx(defaultTxOptions) - for _, c := range TstCreateSeriesCreditsOnStore(t, pool, def.SeriesID, inputAmounts, store) { + for _, c := range TstCreateSeriesCreditsOnStore(t, dbtx, pool, def.SeriesID, inputAmounts, store) { tx.addInput(c) } for i, amount := range outputAmounts { @@ -1252,12 +1482,12 @@ func checkTxInputs(t *testing.T, tx *withdrawalTx, inputs []credit) { // signTxAndValidate will construct the signature script for each input of the given // transaction (using the given raw signatures and the pkScripts from credits) and execute // those scripts to validate them. -func signTxAndValidate(t *testing.T, mgr *waddrmgr.Manager, tx *wire.MsgTx, txSigs TxSigs, +func signTxAndValidate(t *testing.T, mgr *waddrmgr.Manager, addrmgrNs walletdb.ReadBucket, tx *wire.MsgTx, txSigs TxSigs, credits []credit) { for i := range tx.TxIn { pkScript := credits[i].PkScript - TstRunWithManagerUnlocked(t, mgr, func() { - if err := signMultiSigUTXO(mgr, tx, i, pkScript, txSigs[i]); err != nil { + TstRunWithManagerUnlocked(t, mgr, addrmgrNs, func() { + if err := signMultiSigUTXO(mgr, addrmgrNs, tx, i, pkScript, txSigs[i]); err != nil { t.Fatal(err) } })