// Creates an unconfirmed transaction func (self *UnconfirmedTxnPool) createUnconfirmedTxn(bcUnsp *coin.UnspentPool, t coin.Transaction, addrs map[coin.Address]byte) UnconfirmedTxn { now := util.Now() ut := UnconfirmedTxn{ Txn: t, Received: now, Checked: now, Announced: util.ZeroTime(), IsOurReceive: false, IsOurSpend: false, } // Check if this unspent is related to us if addrs != nil { // Check if this is one of our receiving txns for i, _ := range t.Out { if _, ok := addrs[t.Out[i].Address]; ok { ut.IsOurReceive = true break } } // Check if this is one of our spending txns for i, _ := range t.In { if ux, ok := bcUnsp.Get(t.In[i]); ok { if _, ok := addrs[ux.Body.Address]; ok { ut.IsOurSpend = true break } } } } return ut }
func assertValidUnspent(t *testing.T, bc *coin.Blockchain, unspent *coin.UnspentPool, tx coin.Transaction) { expect := bc.TxUxOut(tx, coin.BlockHeader{}) assert.NotEqual(t, len(expect), 0) assert.Equal(t, len(expect), len(unspent.Arr)) for _, ux := range expect { assert.True(t, unspent.Has(ux.Hash())) } }
func assertValidUnspent(t *testing.T, bc *coin.Blockchain, unspent *coin.UnspentPool, tx coin.Transaction) { expect := coin.CreateExpectedUnspents(tx) assert.NotEqual(t, len(expect), 0) assert.Equal(t, len(expect), len(unspent.Pool)) for _, ux := range expect { assert.True(t, unspent.Has(ux.Hash())) } }
// Creates a Transaction spending coins and hours from our coins func CreateSpendingTransaction(wlt wallet.Wallet, unconfirmed *UnconfirmedTxnPool, unspent *coin.UnspentPool, headTime uint64, amt wallet.Balance, fee, burnFactor uint64, dest cipher.Address) (coin.Transaction, error) { txn := coin.Transaction{} auxs := unspent.AllForAddresses(wlt.GetAddresses()) // Subtract pending spends from available puxs := unconfirmed.SpendsForAddresses(unspent, wlt.GetAddressSet()) auxs = auxs.Sub(puxs) // Determine which unspents to spend spends, err := createSpends(headTime, auxs.Flatten(), amt, fee, burnFactor) if err != nil { return txn, err } // Add these unspents as tx inputs toSign := make([]cipher.SecKey, len(spends)) spending := wallet.Balance{0, 0} for i, au := range spends { entry, exists := wlt.GetEntry(au.Body.Address) if !exists { log.Panic("On second thought, the wallet entry does not exist") } txn.PushInput(au.Hash()) toSign[i] = entry.Secret spending.Coins += au.Body.Coins spending.Hours += au.CoinHours(headTime) } // Determine how much change we get back, if any _, changeHours, err := calculateBurnAndChange(spending.Hours, amt.Hours, fee, burnFactor) if err != nil { // This should not occur, else createSpends is broken return txn, err } change := wallet.NewBalance(spending.Coins-amt.Coins, changeHours) // TODO -- send change to a new address changeAddr := spends[0].Body.Address if change.Coins == 0 { if change.Hours > 0 { msg := ("Have enough coins, but not enough to send coin hours " + "change back. Would spend %d more hours than requested.") return txn, fmt.Errorf(msg, change.Hours) } } else { txn.PushOutput(changeAddr, change.Coins, change.Hours) } // Finalize the the transaction txn.PushOutput(dest, amt.Coins, amt.Hours) txn.SignInputs(toSign) txn.UpdateHeader() return txn, nil }
// AllSpendsOutputs returns all spending outputs in unconfirmed tx pool. func (utp *UnconfirmedTxnPool) AllSpendsOutputs(bcUnspent *coin.UnspentPool) []ReadableOutput { outs := []ReadableOutput{} for _, tx := range utp.Txns { for _, in := range tx.Txn.In { if ux, ok := bcUnspent.Get(in); ok { outs = append(outs, NewReadableOutput(ux)) } } } return outs }
//DEPRECATE //deprecate dependency on wallet // Creates a Transaction spending coins and hours from our coins //MOVE SOMEWHERE ELSE //Move to wallet or move to ??? func CreateSpendingTransaction(wlt wallet.Wallet, unconfirmed *UnconfirmedTxnPool, unspent *coin.UnspentPool, headTime uint64, amt wallet.Balance, dest cipher.Address) (coin.Transaction, error) { txn := coin.Transaction{} auxs := unspent.AllForAddresses(wlt.GetAddresses()) // Subtract pending spends from available puxs := unconfirmed.SpendsForAddresses(unspent, wlt.GetAddressSet()) auxs = auxs.Sub(puxs) // Determine which unspents to spend spends, err := createSpends(headTime, auxs.Flatten(), amt) if err != nil { return txn, err } // Add these unspents as tx inputs toSign := make([]cipher.SecKey, len(spends)) spending := wallet.Balance{0, 0} for i, au := range spends { entry, exists := wlt.GetEntry(au.Body.Address) if !exists { log.Panic("On second thought, the wallet entry does not exist") } txn.PushInput(au.Hash()) toSign[i] = entry.Secret spending.Coins += au.Body.Coins spending.Hours += au.CoinHours(headTime) } //keep 1/4th of hours as change //send half to each address var changeHours uint64 = spending.Hours / 4 if amt.Coins == spending.Coins { txn.PushOutput(dest, amt.Coins, changeHours/2) txn.SignInputs(toSign) txn.UpdateHeader() return txn, nil } change := wallet.NewBalance(spending.Coins-amt.Coins, changeHours/2) // TODO -- send change to a new address changeAddr := spends[0].Body.Address //create transaction txn.PushOutput(changeAddr, change.Coins, change.Hours) txn.PushOutput(dest, amt.Coins, changeHours/2) txn.SignInputs(toSign) txn.UpdateHeader() return txn, nil }
// Returns all unconfirmed coin.UxOut spends for addresses // Looks at all inputs for unconfirmed txns, gets their source UxOut from the // blockchain's unspent pool, and returns as coin.AddressUxOuts // TODO -- optimize or cache func (self *UnconfirmedTxnPool) SpendsForAddresses(bcUnspent *coin.UnspentPool, a map[coin.Address]byte) coin.AddressUxOuts { auxs := make(coin.AddressUxOuts, len(a)) for _, utx := range self.Txns { for _, h := range utx.Txn.In { if ux, ok := bcUnspent.Get(h); ok { if _, ok := a[ux.Body.Address]; ok { auxs[ux.Body.Address] = append(auxs[ux.Body.Address], ux) } } } } return auxs }
func addUxArrayToUnspentPool(u *coin.UnspentPool, uxs coin.UxArray) { for _, ux := range uxs { u.Add(ux) } }