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