Skip to content

Commit

Permalink
added pending functions
Browse files Browse the repository at this point in the history
  • Loading branch information
chadlagore committed Aug 12, 2017
1 parent e8c8e72 commit 90e8ccc
Show file tree
Hide file tree
Showing 5 changed files with 124 additions and 25 deletions.
10 changes: 8 additions & 2 deletions app/app.go
Original file line number Diff line number Diff line change
Expand Up @@ -251,11 +251,17 @@ func (a *App) HandleBlock(blk *blockchain.Block) {
// the next block so that the block
// numbers make sense.
a.Chain.AppendBlock(blk)
address := a.CurrentUser.Wallet.Public()
blk := a.Pool.NextBlock(a.Chain, address, a.CurrentUser.BlockSize)

// Drop pending transactions (if they occur in this block).
a.CurrentUser.Wallet.DropAllPending(blk.Transactions)

// Handle miner behaviour (set up a new block).
if miner.IsMining() {
address := a.CurrentUser.Wallet.Public()
blk := a.Pool.NextBlock(a.Chain, address, a.CurrentUser.BlockSize)
miner.RestartMiner(a.Chain, blk)
}

log.Debug("added blk number %d to chain", blk.BlockNumber)
}
}
9 changes: 9 additions & 0 deletions blockchain/transaction.go
Original file line number Diff line number Diff line change
Expand Up @@ -103,3 +103,12 @@ func (t *Transaction) InputsEqualOutputs(other ...*Transaction) bool {

return (int(outAmount) - int(inAmount)) == 0
}

// GetTotalOutput sums the output amounts from the transaction.
func (t *Transaction) GetTotalOutput() uint64 {
result := uint64(0)
for _, out := range t.Outputs {
result += out.Amount
}
return result
}
11 changes: 11 additions & 0 deletions blockchain/transaction_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,3 +26,14 @@ func TestTransactionLen(t *testing.T) {

assert.Equal(t, tx.Len(), txLen)
}

func TestTransactionGetTotalOutput(t *testing.T) {
tx := NewTestTransaction()
tx.Outputs = []TxOutput{
TxOutput{
Recipient: tx.Outputs[0].Recipient,
Amount: 5,
},
}
assert.Equal(t, tx.GetTotalOutput(), uint64(5))
}
76 changes: 53 additions & 23 deletions blockchain/wallet.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,10 @@ import (
crand "crypto/rand"
"crypto/sha256"
"encoding/hex"
"errors"
"io"
"math"
"math/big"

log "github.com/Sirupsen/logrus"
c "github.com/ubclaunchpad/cumulus/common/constants"
"github.com/ubclaunchpad/cumulus/moj"
)
Expand Down Expand Up @@ -167,39 +166,70 @@ func NewWallet() *Wallet {
}
}

// Debit attempts to spend some coin from the wallet.
func (w *Wallet) Debit(amount uint64) error {
if amount >= w.GetEffectiveBalance() {
return errors.New("wallet does not have a high enough balance to satisfy the request")
} else if amount < 0 {
return errors.New("debit amounts may not be negative")
// SetAllPending appends transactions to the pending set of transactions.
func (w *Wallet) SetAllPending(txns []*Transaction) {
for _, t := range txns {
w.SetPending(t)
}
w.Balance -= amount
return nil
}

// Credit attempts to add count to the wallet.
func (w *Wallet) Credit(amount uint64) error {
if amount >= math.MaxUint64 {
return errors.New("wallet cannot hold this amount")
} else if amount < 0 {
return errors.New("credit amounts may not be negative")
// SetPending appends one transaction to the pending set of transaction
// if the wallet effective balance is high enough to accomodate.
func (w *Wallet) SetPending(txn *Transaction) {
bal := w.GetEffectiveBalance()
spend := txn.GetTotalOutput()
if bal >= spend {
w.PendingTxns = append(w.PendingTxns, txn)
} else {
log.Printf("wallet balance is too low %v < %v", bal, spend)
}
w.Balance += amount
return nil
}

// SetPending appends a transaction to the pending set of transactions.
func (w *Wallet) SetPending(t *Transaction) {
w.PendingTxns = append(w.PendingTxns, t)
// DropAllPending drops pending transactions if they apper in txns.
func (w *Wallet) DropAllPending(txns []*Transaction) {
for _, t := range txns {
if p, i := w.IsPending(t); p {
w.DropPending(i)
}
}
}

// DropPending a single pending transaction by index in the pending list.
func (w *Wallet) DropPending(i int) {
if i < len(w.PendingTxns) && i >= 0 {
log.Info("dropping transaction with hash %s", w.PendingTxns[i].Input.Hash)
w.PendingTxns = append(w.PendingTxns[:i], w.PendingTxns[i+1:]...)
}
}

// IsPending returns true if the transaction exists in the pending list.
// If true, it also returns the integer index of the transaction.
func (w *Wallet) IsPending(txn *Transaction) (bool, int) {
for i, t := range w.PendingTxns {
if t.Input.Hash == txn.Input.Hash {
return true, i
}
}
return false, -1
}

// GetEffectiveBalance returns the wallet balance less the sum of the pending
// transactions in the wallet.
func (w *Wallet) GetEffectiveBalance() uint64 {
r := uint64(0)
r := w.Balance
for _, t := range w.PendingTxns {
r += t.Outputs[0].Amount
r -= t.Outputs[0].Amount
}
return r
}

// GetBalance returns the raw balance without calculating pending transactions.
func (w *Wallet) GetBalance() uint64 {
// TODO: Get historical wallet activity, cache and update block by block.
return w.Balance
}

// SetBalance idempotently sets the account balance.
func (w *Wallet) SetBalance(b uint64) {
w.Balance = b
}
43 changes: 43 additions & 0 deletions blockchain/wallet_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
package blockchain

import (
"testing"

"github.com/stretchr/testify/assert"
)

func TestNewWallet(t *testing.T) {
w := NewWallet()
assert.Equal(t, w.GetEffectiveBalance(), uint64(0))
assert.Equal(t, len(w.PendingTxns), 0)
}

func TestSetAllPending(t *testing.T) {
w := NewWallet()
txn := NewTestTransaction()

// Set the balance approprately to handle the txn.
w.SetBalance(txn.GetTotalOutput())

// Set and check.
w.SetAllPending([]*Transaction{txn})
result, i := w.IsPending(txn)

// Make sure transaction is actually pending.
assert.True(t, result)
assert.Equal(t, i, 0)
}

func TestDropAllPending(t *testing.T) {
w := NewWallet()
txn := NewTestTransaction()
w.SetBalance(txn.GetTotalOutput())
w.SetAllPending([]*Transaction{txn})

// Drop all pending
result, _ := w.IsPending(txn)
assert.True(t, result)
w.DropAllPending([]*Transaction{txn})
result, _ = w.IsPending(txn)
assert.False(t, result)
}

0 comments on commit 90e8ccc

Please sign in to comment.