make votingpool tests compile and pass
This commit is contained in:
parent
f143d095d6
commit
1075ad3fa0
10 changed files with 1145 additions and 629 deletions
|
@ -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()
|
||||
|
|
|
@ -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)
|
||||
}
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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)
|
||||
}
|
||||
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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)
|
||||
}
|
||||
})
|
||||
|
|
Loading…
Add table
Reference in a new issue