本文整理汇总了Golang中github.com/skycoin/skycoin/src/coin.SortTransactions函数的典型用法代码示例。如果您正苦于以下问题:Golang SortTransactions函数的具体用法?Golang SortTransactions怎么用?Golang SortTransactions使用的例子?那么恭喜您, 这里精选的函数代码示例或许可以为您提供帮助。
在下文中一共展示了SortTransactions函数的10个代码示例,这些例子默认根据受欢迎程度排序。您可以为喜欢或者感觉有用的代码点赞,您的评价将有助于系统推荐出更棒的Golang代码示例。
示例1: TestCreateAndExecuteBlock
func TestCreateAndExecuteBlock(t *testing.T) {
defer cleanupVisor()
// Test as not master, should fail
vc := newGenesisConfig(t)
v := NewVisor(vc)
assert.Panics(t, func() { v.CreateAndExecuteBlock() })
// Test as master, no txns
vc = newMasterVisorConfig(t)
v = NewVisor(vc)
_, err := v.CreateAndExecuteBlock()
assert.NotNil(t, err)
assert.Equal(t, err.Error(), "No transactions")
// Test as master, more txns than allowed
vc.BlockCreationInterval = uint64(101)
v = NewVisor(vc)
txns := addValidTxns(t, v, 3)
txns = coin.SortTransactions(txns, getFee)
v.Config.MaxBlockSize = txns[0].Size()
assert.Equal(t, len(v.blockchain.Blocks), 1)
assert.Equal(t, len(v.blockSigs.Sigs), 1)
sb, err := v.CreateAndExecuteBlock()
assert.Nil(t, err)
assert.Equal(t, len(sb.Block.Body.Transactions), 1)
assert.Equal(t, len(v.blockchain.Blocks), 2)
assert.Equal(t, len(v.blockSigs.Sigs), 2)
assert.Equal(t, v.blockchain.Blocks[1], sb.Block)
assert.Equal(t, v.blockSigs.Sigs[1], sb.Sig)
assert.Equal(t, len(v.Unconfirmed.Txns), 2)
assert.Equal(t, sb.Block.Head.Time-v.blockchain.Blocks[0].Head.Time,
vc.BlockCreationInterval)
rawTxns := v.Unconfirmed.RawTxns()
rawTxns = coin.SortTransactions(rawTxns, getFee)
assert.Equal(t, len(rawTxns), 2)
for _, tx := range sb.Block.Body.Transactions {
assert.NotEqual(t, tx.Hash(), rawTxns[0].Hash())
assert.NotEqual(t, tx.Hash(), rawTxns[1].Hash())
}
assert.Equal(t, txns[1].Hash(), rawTxns[0].Hash())
assert.Equal(t, txns[2].Hash(), rawTxns[1].Hash())
assert.Nil(t, v.blockSigs.Verify(v.Config.MasterKeys.Public, v.blockchain))
// No txns, forcing NewBlockFromTransactions to fail
v = NewVisor(vc)
assert.Equal(t, len(v.Unconfirmed.Txns), 0)
txns = addValidTxns(t, v, 3)
v.Config.MaxBlockSize = 0
sb, err = v.CreateAndExecuteBlock()
assert.NotNil(t, err)
assert.Equal(t, len(v.blockchain.Blocks), 1)
assert.Equal(t, len(v.blockSigs.Sigs), 1)
assert.Equal(t, len(v.Unconfirmed.Txns), 3)
}
示例2: TestRawTxns
func TestRawTxns(t *testing.T) {
ut := NewUnconfirmedTxnPool()
utxs := make(coin.Transactions, 4)
for i := 0; i < len(utxs); i++ {
utx := addUnconfirmedTxnToPool(ut)
utxs[i] = utx.Txn
}
utxs = coin.SortTransactions(utxs, getFee)
txns := ut.RawTxns()
txns = coin.SortTransactions(txns, getFee)
for i, tx := range txns {
assert.Equal(t, utxs[i], tx)
}
}
示例3: CreateBlock
// Creates a SignedBlock from pending transactions
// Applies transaction limit constraint
// Applies max block size constraint
// Should order transactions by priority
func (self *Blockchain) CreateBlock() (coin.Block, error) {
//var sb SignedBlock
if self.SecKey == (cipher.SecKey{}) {
log.Panic("Only master chain can create blocks")
}
txns := self.Unconfirmed.RawTxns()
//sort
//arbritrate
//truncate
//TODO: sort by arrival time/announce time
//TODO: filter valid first
txns = coin.SortTransactions(txns, self.Blockchain.TransactionFee)
txns = self.blockchain.ArbitrateTransactions(txns)
nTxns := len(txns)
if nTxns > MaxTransactionsPerBlock {
txns = txns[:MaxTransactionsPerBlock]
}
txns = txns.TruncateBytesTo(MaxBlockSize) //cap at 32 KB
//TODO: ERROR< NewBlockFromTransactions arbritates!
b, err := self.blockchain.NewBlockFromTransactions(txns,
uint64(time.Now().Unix()))
//remove creation interval, from new block
if err != nil {
return b, err
}
return b, err
}
示例4: addValidTxns
func addValidTxns(t *testing.T, v *Visor, n int) coin.Transactions {
txns := make(coin.Transactions, n)
for i := 0; i < len(txns); i++ {
txn, err := makeValidTxn(v)
assert.Nil(t, err)
txns[i] = txn
}
for _, txn := range txns {
err, known := v.RecordTxn(txn)
assert.Nil(t, err)
assert.False(t, known)
}
txns = coin.SortTransactions(txns, getFee)
assert.Equal(t, len(v.Unconfirmed.Txns), n)
return txns
}
示例5: CreateBlock
// Creates a SignedBlock from pending transactions
func (self *Visor) CreateBlock(when uint64) (SignedBlock, error) {
var sb SignedBlock
if !self.Config.IsMaster {
log.Panic("Only master chain can create blocks")
}
if len(self.Unconfirmed.Txns) == 0 {
return sb, errors.New("No transactions")
}
txns := self.Unconfirmed.RawTxns()
txns = coin.SortTransactions(txns, self.Blockchain.TransactionFee)
txns = txns.TruncateBytesTo(self.Config.MaxBlockSize)
b, err := self.Blockchain.NewBlockFromTransactions(txns, when)
if err != nil {
return sb, err
}
return self.SignBlock(b), nil
}
示例6: processTransactions
// Validates a set of Transactions, individually, against each other and
// against the Blockchain. If firstFail is true, it will return an error
// as soon as it encounters one. Else, it will return an array of
// Transactions that are valid as a whole. It may return an error if
// firstFalse is false, if there is no way to filter the txns into a valid
// array, i.e. processTransactions(processTransactions(txn, false), true)
// should not result in an error, unless all txns are invalid.
// TODO:
// - move arbitration to visor
// - blockchain should have strict checking
func (bc Blockchain) processTransactions(txns coin.Transactions, arbitrating bool) (coin.Transactions, error) {
// Transactions need to be sorted by fee and hash before arbitrating
if arbitrating {
txns = coin.SortTransactions(txns, bc.TransactionFee)
}
//TODO: audit
if len(txns) == 0 {
if arbitrating {
return txns, nil
}
// If there are no transactions, a block should not be made
return nil, errors.New("No transactions")
}
skip := make(map[int]byte)
uxHashes := make(coin.UxHashSet, len(txns))
for i, tx := range txns {
// Check the transaction against itself. This covers the hash,
// signature indices and duplicate spends within itself
err := bc.VerifyTransaction(tx)
if err != nil {
if arbitrating {
skip[i] = byte(1)
continue
} else {
return nil, err
}
}
// Check that each pending unspent will be unique
uxb := coin.UxBody{
SrcTransaction: tx.Hash(),
}
for _, to := range tx.Out {
uxb.Coins = to.Coins
uxb.Hours = to.Hours
uxb.Address = to.Address
h := uxb.Hash()
_, exists := uxHashes[h]
if exists {
if arbitrating {
skip[i] = byte(1)
continue
} else {
m := "Duplicate unspent output across transactions"
return nil, errors.New(m)
}
}
if DebugLevel1 {
// Check that the expected unspent is not already in the pool.
// This should never happen because its a hash collision
if bc.unspent.Has(h) {
if arbitrating {
skip[i] = byte(1)
continue
} else {
m := "Output hash is in the UnspentPool"
return nil, errors.New(m)
}
}
}
uxHashes[h] = byte(1)
}
}
// Filter invalid transactions before arbitrating between colliding ones
if len(skip) > 0 {
newtxns := make(coin.Transactions, len(txns)-len(skip))
j := 0
for i := range txns {
if _, shouldSkip := skip[i]; !shouldSkip {
newtxns[j] = txns[i]
j++
}
}
txns = newtxns
skip = make(map[int]byte)
}
// Check to ensure that there are no duplicate spends in the entire block,
// and that we aren't creating duplicate outputs. Duplicate outputs
// within a single Transaction are already checked by VerifyTransaction
hashes := txns.Hashes()
for i := 0; i < len(txns)-1; i++ {
s := txns[i]
for j := i + 1; j < len(txns); j++ {
t := txns[j]
if DebugLevel1 {
if hashes[i] == hashes[j] {
// This is a non-recoverable error for filtering, and
// should never occur. It indicates a hash collision
//.........这里部分代码省略.........
示例7: TestGetOldOwnedTransactions
func TestGetOldOwnedTransactions(t *testing.T) {
mv := setupMasterVisor()
up := mv.Unconfirmed
// Setup txns
notOursNew, err := makeValidTxn(mv)
assert.Nil(t, err)
notOursOld, err := makeValidTxn(mv)
assert.Nil(t, err)
ourSpendNew, err := makeValidTxn(mv)
assert.Nil(t, err)
ourSpendOld, err := makeValidTxn(mv)
assert.Nil(t, err)
ourReceiveNew, err := makeValidTxn(mv)
assert.Nil(t, err)
ourReceiveOld, err := makeValidTxn(mv)
assert.Nil(t, err)
ourBothNew, err := makeValidTxn(mv)
assert.Nil(t, err)
ourBothOld, err := makeValidTxn(mv)
assert.Nil(t, err)
// Add a transaction that is not ours, both new and old
err, known := up.RecordTxn(mv.blockchain, notOursNew, nil, testBlockSize, 0)
assert.Nil(t, err)
assert.False(t, known)
up.SetAnnounced(notOursNew.Hash(), util.Now())
err, known = up.RecordTxn(mv.blockchain, notOursOld, nil, testBlockSize, 0)
assert.Nil(t, err)
assert.False(t, known)
// Add a transaction that is our spend, both new and old
addrs := make(map[coin.Address]byte, 1)
ux, ok := mv.blockchain.Unspent.Get(ourSpendNew.In[0])
assert.True(t, ok)
addrs[ux.Body.Address] = byte(1)
err, known = up.RecordTxn(mv.blockchain, ourSpendNew, addrs, testBlockSize, 0)
assert.Nil(t, err)
assert.False(t, known)
up.SetAnnounced(ourSpendNew.Hash(), util.Now())
addrs = make(map[coin.Address]byte, 1)
ux, ok = mv.blockchain.Unspent.Get(ourSpendNew.In[0])
assert.True(t, ok)
addrs[ux.Body.Address] = byte(1)
err, known = up.RecordTxn(mv.blockchain, ourSpendOld, addrs, testBlockSize, 0)
assert.Nil(t, err)
assert.False(t, known)
// Add a transaction that is our receive, both new and old
addrs = make(map[coin.Address]byte, 1)
addrs[ourReceiveNew.Out[1].Address] = byte(1)
err, known = up.RecordTxn(mv.blockchain, ourReceiveNew, addrs,
testBlockSize, 0)
assert.Nil(t, err)
assert.False(t, known)
up.SetAnnounced(ourReceiveNew.Hash(), util.Now())
addrs = make(map[coin.Address]byte, 1)
addrs[ourReceiveOld.Out[1].Address] = byte(1)
err, known = up.RecordTxn(mv.blockchain, ourReceiveOld, addrs,
testBlockSize, 0)
assert.Nil(t, err)
assert.False(t, known)
// Add a transaction that is both our spend and receive, both new and old
addrs = make(map[coin.Address]byte, 2)
ux, ok = mv.blockchain.Unspent.Get(ourBothNew.In[0])
assert.True(t, ok)
addrs[ux.Body.Address] = byte(1)
addrs[ourBothNew.Out[1].Address] = byte(1)
assert.Equal(t, len(addrs), 2)
err, known = up.RecordTxn(mv.blockchain, ourBothNew, addrs, testBlockSize, 0)
assert.Nil(t, err)
assert.False(t, known)
up.SetAnnounced(ourBothNew.Hash(), util.Now())
addrs = make(map[coin.Address]byte, 1)
ux, ok = mv.blockchain.Unspent.Get(ourBothOld.In[0])
assert.True(t, ok)
addrs[ux.Body.Address] = byte(1)
addrs[ourBothOld.Out[1].Address] = byte(1)
assert.Equal(t, len(addrs), 2)
err, known = up.RecordTxn(mv.blockchain, ourBothOld, addrs, testBlockSize, 0)
assert.Nil(t, err)
assert.False(t, known)
// Get the old owned txns
utxns := up.GetOldOwnedTransactions(time.Hour)
// Check that the 3 txns are ones we are interested in and old enough
assert.Equal(t, len(utxns), 3)
mapTxns := make(map[coin.SHA256]bool)
txns := make(coin.Transactions, len(utxns))
for i, utx := range utxns {
txns[i] = utx.Txn
assert.True(t, utx.IsOurSpend || utx.IsOurReceive)
assert.True(t, utx.Announced.IsZero())
mapTxns[utx.Hash()] = true
}
assert.Equal(t, len(mapTxns), 3)
txns = coin.SortTransactions(txns, getFee)
expectTxns := coin.Transactions{ourSpendOld, ourReceiveOld, ourBothOld}
expectTxns = coin.SortTransactions(expectTxns, getFee)
//.........这里部分代码省略.........
示例8: TestProcessTransactions
func TestProcessTransactions(t *testing.T) {
ft := FakeTree{}
bc := NewBlockchain(&ft, nil)
bc.CreateGenesisBlock(genAddress, _genCoins, _genTime)
fmt.Println("genesis time:", bc.GetGenesisBlock().Time())
assert.Equal(t, bc.Len(), uint64(1))
_, ux := addBlockToBlockchain(t, bc)
assert.Equal(t, bc.Len(), uint64(3))
// Invalid, no transactions in block
// arbitrating=false
txns, err := bc.processTransactions(coin.Transactions{}, false)
assert.Nil(t, txns)
assertError(t, err, "No transactions")
// arbitrating=true
txns, err = bc.processTransactions(coin.Transactions{}, true)
assert.Equal(t, len(txns), 0)
assert.Nil(t, err)
// Invalid, txn.Verify() fails
// TODO -- combine all txn.Verify() failures into one test
// method, and call it from here, from ExecuteBlock(), from
// Verify(), from VerifyTransaction()
txns = coin.Transactions{}
txn := coin.Transaction{}
txn.PushInput(ux.Hash())
txn.PushOutput(genAddress, 777, 100)
txn.SignInputs([]cipher.SecKey{genSecret})
txn.UpdateHeader()
txns = append(txns, txn)
// arbitrating=false
txns2, err := bc.processTransactions(txns, false)
assert.Nil(t, txns2)
assertError(t, err,
"Transaction outputs must be multiple of 1e6 base units")
// arbitrating=true
txns2, err = bc.processTransactions(txns, true)
assert.NotNil(t, txns2)
assert.Nil(t, err)
assert.Equal(t, len(txns2), 0)
// Invalid, duplicate unspent will be created by these txns
txn, _ = makeTransactionForChainWithHoursFee(t, bc, ux, genSecret, 100,
100)
txns = coin.Transactions{txn, txn}
// arbitrating=false
txns2, err = bc.processTransactions(txns, false)
assertError(t, err, "Duplicate unspent output across transactions")
assert.Nil(t, txns2)
// arbitrating=true. One of the offending transactions should be removed
txns2, err = bc.processTransactions(txns, true)
assert.Nil(t, err)
assert.Equal(t, len(txns2), 1)
assert.Equal(t, txns2[0], txn)
// Check that a new output will not collide with the existing pool
txn, _ = makeTransactionForChainWithHoursFee(t, bc, ux, genSecret, 100,
100)
txns = coin.Transactions{txn}
uxb := coin.UxBody{
SrcTransaction: txn.Hash(),
Coins: txn.Out[0].Coins,
Hours: txn.Out[0].Hours,
Address: txn.Out[0].Address,
}
bc.GetUnspent().Add(coin.UxOut{Body: uxb})
// arbitrating=false
txns2, err = bc.processTransactions(txns, false)
assertError(t, err, "New unspent collides with existing unspent")
assert.Nil(t, txns2)
// arbitrating=true
txns2, err = bc.processTransactions(txns, true)
assert.Equal(t, len(txns2), 0)
assert.NotNil(t, txns2)
assert.Nil(t, err)
// Spending of duplicate inputs being spent across txns
txn, _ = makeTransactionForChainWithHoursFee(t, bc, ux, genSecret, 100,
100)
txn2, _ := makeTransactionForChainWithHoursFee(t, bc, ux, genSecret, 100,
100)
txn2.Out = nil
txn2.PushOutput(makeAddress(), 1e6, 100)
txn2.PushOutput(makeAddress(), ux.Body.Coins-1e6, 100)
txn2.Sigs = nil
txn2.SignInputs([]cipher.SecKey{genSecret})
txn2.UpdateHeader()
txns = coin.SortTransactions(coin.Transactions{txn, txn2}, bc.TransactionFee)
// arbitrating=false
txns2, err = bc.processTransactions(txns, false)
assertError(t, err, "Cannot spend output twice in the same block")
assert.Nil(t, txns2)
// arbitrating=true
txns2, err = bc.processTransactions(txns, true)
assert.Nil(t, err)
assert.Equal(t, len(txns2), 1)
assert.Equal(t, txns2[0], txns[0])
}
示例9: TestNewBlockFromTransactions
func TestNewBlockFromTransactions(t *testing.T) {
ft := FakeTree{}
bc := NewBlockchain(&ft, nil)
gb := bc.CreateGenesisBlock(genAddress, _genCoins, _genTime)
// gb.Head.Version = 0x0F
// bc.Blocks[0] = gb
// assert.Equal(t, bc.GetGenesisBlock().Head.Version, uint32(0x0F))
assert.Equal(t, bc.Len(), uint64(1))
_, ux := addBlockToBlockchain(t, bc)
assert.Equal(t, bc.Len(), uint64(3))
// No transactions
_, err := bc.NewBlockFromTransactions(coin.Transactions{},
bc.Time()+_incTime)
assertError(t, err, "No transactions")
assert.Equal(t, bc.Len(), uint64(3))
// Bad currentTime, must be greater than head time
fee := uint64(100)
txn, _ := makeTransactionForChainWithHoursFee(t, bc, ux, genSecret, 100,
fee)
txns := coin.Transactions{txn}
assert.Panics(t, func() {
bc.NewBlockFromTransactions(txns, bc.Time())
})
// Valid transaction
hrs := ux.CoinHours(bc.Time())
seq := bc.Head().Head.BkSeq
b, err := bc.NewBlockFromTransactions(txns, bc.Time()+_incTime)
assert.Nil(t, err)
assert.Equal(t, len(b.Body.Transactions), 1)
assert.Equal(t, b.Body.Transactions[0], txn)
assert.Equal(t, b.Head.BkSeq, seq+1)
assert.Equal(t, b.Head.Time, bc.Time()+_incTime)
assert.Equal(t, b.Head.Version, gb.Head.Version)
assert.Equal(t, b.Head.Fee, fee)
assert.Equal(t, b.Head.Fee, hrs-txn.OutputHours())
assert.NotEqual(t, b.Head.Fee, uint64(0))
// Invalid transaction
txn.InnerHash = cipher.SHA256{}
txns = coin.Transactions{txn}
_, err = bc.NewBlockFromTransactions(txns, bc.Time()+_incTime)
assertError(t, err, "Invalid header hash")
// Multiple transactions, sorted
// First, split our genesis block into two, so we can make 2 valid txns
uxs := splitUnspent(t, bc, ux)
// tNow, make two valid txns
txn = coin.Transaction{}
txn.PushInput(uxs[0].Hash())
txn.PushOutput(genAddress, uxs[0].Body.Coins, uxs[0].Body.Hours)
txn.SignInputs([]cipher.SecKey{genSecret})
txn.UpdateHeader()
txn2 := coin.Transaction{}
txn2.PushInput(uxs[1].Hash())
txn2.PushOutput(genAddress, uxs[1].Body.Coins, uxs[1].Body.Hours)
txn2.SignInputs([]cipher.SecKey{genSecret})
txn2.UpdateHeader()
// Combine them and sort
txns = coin.Transactions{txn, txn2}
txns = coin.SortTransactions(txns, bc.TransactionFee)
b, err = bc.NewBlockFromTransactions(txns, bc.Time()+_incTime)
assert.Nil(t, err)
assert.Equal(t, len(b.Body.Transactions), 2)
assert.Equal(t, b.Body.Transactions, txns)
// Order should be preserved
txns2 := coin.Transactions{txn, txn2}
sTxns := coin.NewSortableTransactions(txns2, bc.TransactionFee)
if sTxns.IsSorted() {
txns2[0], txns2[1] = txns2[1], txns2[0]
}
b, err = bc.NewBlockFromTransactions(txns2, bc.Time()+_incTime)
assert.Nil(t, err)
assert.Equal(t, len(b.Body.Transactions), 2)
assert.Equal(t, b.Body.Transactions, txns2)
}
示例10: TestExecuteBlock
func TestExecuteBlock(t *testing.T) {
ft := FakeTree{}
bc := NewBlockchain(&ft, nil)
bc.CreateGenesisBlock(genAddress, _genCoins, _genTime)
assert.Equal(t, bc.Len(), uint64(1))
_, ux := addBlockToBlockchain(t, bc)
assert.Equal(t, bc.Len(), uint64(3))
// Invalid block returns error
b := coin.Block{}
uxs, err := bc.ExecuteBlock(&b)
assert.NotNil(t, err)
assert.Nil(t, uxs)
// Valid block, spends are removed from the unspent pool, new ones are
// added. Blocks is updated, and new unspents are returns
assert.Equal(t, bc.Len(), uint64(3))
assert.Equal(t, len(bc.GetUnspent().Pool), 2)
spuxs := splitUnspent(t, bc, ux)
tx := coin.Transaction{}
tx.PushInput(spuxs[0].Hash())
coins := spuxs[0].Body.Coins
extra := coins % 4e6
coins = (coins - extra) / 4
tx.PushOutput(genAddress, coins+extra, spuxs[0].Body.Hours/5)
tx.PushOutput(genAddress, coins, spuxs[0].Body.Hours/6)
tx.PushOutput(genAddress, coins, spuxs[0].Body.Hours/7)
tx.PushOutput(genAddress, coins, spuxs[0].Body.Hours/8)
tx.SignInputs([]cipher.SecKey{genSecret})
tx.UpdateHeader()
tx2 := coin.Transaction{}
tx2.PushInput(spuxs[1].Hash())
tx2.PushOutput(genAddress, spuxs[1].Body.Coins, spuxs[1].Body.Hours/10)
tx2.SignInputs([]cipher.SecKey{genSecret})
tx2.UpdateHeader()
txns := coin.Transactions{tx, tx2}
sTxns := coin.NewSortableTransactions(txns, bc.TransactionFee)
unswapped := sTxns.IsSorted()
txns = coin.SortTransactions(txns, bc.TransactionFee)
assert.Nil(t, bc.verifyTransactions(txns))
seq := bc.Head().Head.BkSeq
b, err = bc.NewBlockFromTransactions(txns, bc.Time()+_incTime)
assert.Equal(t, b.Head.BkSeq, seq+1)
assert.Nil(t, err)
assert.Equal(t, len(b.Body.Transactions), 2)
assert.Equal(t, b.Body.Transactions, txns)
uxs, err = bc.ExecuteBlock(&b)
assert.Nil(t, err)
assert.Equal(t, len(uxs), 5)
// Check that all unspents look correct and are in the unspent pool
txOuts := []coin.TransactionOutput{}
if unswapped {
txOuts = append(txOuts, tx.Out...)
txOuts = append(txOuts, tx2.Out...)
} else {
txOuts = append(txOuts, tx2.Out...)
txOuts = append(txOuts, tx.Out...)
}
for i, ux := range uxs {
if unswapped {
if i < len(tx.Out) {
assert.Equal(t, ux.Body.SrcTransaction, tx.Hash())
} else {
assert.Equal(t, ux.Body.SrcTransaction, tx2.Hash())
}
} else {
if i < len(tx2.Out) {
assert.Equal(t, ux.Body.SrcTransaction, tx2.Hash())
} else {
assert.Equal(t, ux.Body.SrcTransaction, tx.Hash())
}
}
assert.Equal(t, ux.Body.Address, txOuts[i].Address)
assert.Equal(t, ux.Body.Coins, txOuts[i].Coins)
assert.Equal(t, ux.Body.Hours, txOuts[i].Hours)
assert.Equal(t, ux.Head.BkSeq, b.Head.BkSeq)
assert.Equal(t, ux.Head.Time, b.Head.Time)
assert.True(t, bc.GetUnspent().Has(ux.Hash()))
}
// Check that all spends are no longer in the pool
txIns := []cipher.SHA256{}
txIns = append(txIns, tx.In...)
txIns = append(txIns, tx2.In...)
for _, ux := range txIns {
assert.False(t, bc.GetUnspent().Has(ux))
}
}