Skip to content

Commit

Permalink
Merge 90e8ccc into b6d5e37
Browse files Browse the repository at this point in the history
  • Loading branch information
chadlagore committed Aug 12, 2017
2 parents b6d5e37 + 90e8ccc commit badd701
Show file tree
Hide file tree
Showing 14 changed files with 260 additions and 78 deletions.
2 changes: 1 addition & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ run-console: cumulus
deps:
glide install

clean:
clean: cumulus
rm cumulus

install-glide:
Expand Down
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)
}
}
58 changes: 34 additions & 24 deletions app/console.go
Original file line number Diff line number Diff line change
Expand Up @@ -65,22 +65,9 @@ func create(ctx *ishell.Context, app *App) {
"Transaction",
}, "What would you like to create?")
if choice == 0 {
createHotWallet(ctx, app)
createWallet(ctx, app)
} else {
shell.Print("Sender wallet ID: ")
senderID := shell.ReadLine()
shell.Print("Recipient wallet ID: ")
recipientID := shell.ReadLine()
shell.Print("Amount to send: ")
amount, err := strconv.ParseFloat(shell.ReadLine(), 64)
if err != nil {
shell.Println("Invalid number format. Please enter an amount in decimal format.")
return
}

// TODO: make transaction, add it to the pool, broadcast it
ctx.Printf(`\nNew Transaction: \nSenderID: %s \nRecipiendID: %s\nAmount: %f"`,
senderID, recipientID, amount)
createTransaction(ctx, app)
}
}

Expand Down Expand Up @@ -119,13 +106,36 @@ func connect(ctx *ishell.Context, a *App) {
}
}

func createHotWallet(ctx *ishell.Context, app *App) {
shell.Print("Enter wallet name: ")
walletName := shell.ReadLine()
wallet := HotWallet{walletName, blockchain.NewWallet()}
app.CurrentUser.HotWallet = wallet
emoji.Println(":credit_card: New hot wallet created!")
emoji.Println(":raising_hand: Name: " + wallet.Name)
emoji.Println(":mailbox: Address: " + wallet.Wallet.Public().Repr())
emoji.Println(":fist: Emoji Address: " + wallet.Wallet.Public().Emoji())
func createWallet(ctx *ishell.Context, app *App) {
wallet := blockchain.NewWallet()
app.CurrentUser.Wallet = wallet
emoji.Println(":credit_card: New wallet created!")
emoji.Print(":mailbox:")
ctx.Println(" Address: " + wallet.Public().Repr())
emoji.Println(":fist: Emoji Address: " + wallet.Public().Emoji())
ctx.Println("")
}

func createTransaction(ctx *ishell.Context, app *App) {
emoji.Print(":credit_card:")
ctx.Println(" Enter recipient wallet address")
toAddress := shell.ReadLine()
// TODO: Error handling address input.

emoji.Print(":dollar:")
ctx.Println(" Enter amount to send: ")
amount, err := strconv.ParseUint(shell.ReadLine(), 10, 64)
if err != nil {
emoji.Println(":disappointed: Invalid number format. Please enter an amount in decimal format.")
return
}

// TODO: Check if we have enough coins to make the purchase.
err = app.Pay(toAddress, amount)
if err != nil {
emoji.Println(":disappointed: Transaction failed!")
ctx.Println(err.Error)
} else {
emoji.Println(":mailbox_with_mail: Its in the mail!")
}
}
51 changes: 38 additions & 13 deletions app/user.go
Original file line number Diff line number Diff line change
@@ -1,33 +1,58 @@
package app

import "github.com/ubclaunchpad/cumulus/blockchain"
import (
"github.com/ubclaunchpad/cumulus/blockchain"
"github.com/ubclaunchpad/cumulus/msg"

crand "crypto/rand"
)

// User holds basic user information.
type User struct {
HotWallet
*blockchain.Wallet
BlockSize uint32
}

// HotWallet is a representation of the users wallet.
type HotWallet struct {
Name string
blockchain.Wallet
}

// NewUser creates a new user
func NewUser() *User {
return &User{
HotWallet: HotWallet{
Wallet: blockchain.NewWallet(),
Name: "default",
},
Wallet: blockchain.NewWallet(),
BlockSize: blockchain.DefaultBlockSize,
}
}

// getCurrentUser gets the current user.
// getCurrentUser gets the current user function only used for app initalization.
func getCurrentUser() *User {
// TODO: Check for local user information on disk,
// If doesnt exist, create new user.
return NewUser()
}

// Pay pays an amount of coin to an address `to`.
func (a *App) Pay(to string, amount uint64) error {
// Two atomic steps must occur.

// 1. A legitimate transaction must be built.
tbody := blockchain.TxBody{
Sender: getCurrentUser().Wallet.Public(),
Outputs: []blockchain.TxOutput{
blockchain.TxOutput{
Recipient: to,
Amount: amount,
},
},
}

// 2. The transaction must be signed and broadcasted.
if txn, err := tbody.Sign(*a.CurrentUser.Wallet, crand.Reader); err != nil {
a.PeerStore.Broadcast(msg.Push{
ResourceType: msg.ResourceTransaction,
Resource: txn,
})
a.CurrentUser.Wallet.SetPending(txn)
} else {
return err
}

return nil
}
2 changes: 1 addition & 1 deletion blockchain/genesis.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ func Genesis(miner Address, target Hash, blockReward uint64, extraData []byte) *

cbReward := TxOutput{
Amount: blockReward,
Recipient: miner,
Recipient: miner.Repr(),
}

cbTx := &Transaction{
Expand Down
20 changes: 10 additions & 10 deletions blockchain/test_utils.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ func NewTestTxHashPointer() TxHashPointer {
func NewTestTxOutput() TxOutput {
return TxOutput{
Amount: uint64(mrand.Int63()),
Recipient: NewWallet().Public(),
Recipient: NewWallet().Public().Repr(),
}
}

Expand All @@ -53,7 +53,7 @@ func NewTestTxBody() TxBody {
func NewTestTransaction() *Transaction {
sender := NewWallet()
tbody := NewTestTxBody()
t, _ := tbody.Sign(sender, crand.Reader)
t, _ := tbody.Sign(*sender, crand.Reader)
return t
}

Expand Down Expand Up @@ -124,7 +124,7 @@ func NewTestOutputBlock(t []*Transaction, input *Block) *Block {
}

// NewTestTransactionValue creates a new transaction with specific value a.
func NewTestTransactionValue(s, r Wallet, a uint64, i uint32) (*Transaction, error) {
func NewTestTransactionValue(s, r *Wallet, a uint64, i uint32) (*Transaction, error) {
tbody := TxBody{
Sender: s.Public(),
Input: TxHashPointer{
Expand All @@ -136,9 +136,9 @@ func NewTestTransactionValue(s, r Wallet, a uint64, i uint32) (*Transaction, err
}
tbody.Outputs[0] = TxOutput{
Amount: a,
Recipient: r.Public(),
Recipient: r.Public().Repr(),
}
return tbody.Sign(s, crand.Reader)
return tbody.Sign(*s, crand.Reader)
}

// NewValidBlockChainFixture creates a valid blockchain of two blocks.
Expand All @@ -150,13 +150,13 @@ func NewValidBlockChainFixture() (*BlockChain, Wallet) {
trA, _ := NewTestTransactionValue(original, sender, 2, 1)
trA.Outputs = append(trA.Outputs, TxOutput{
Amount: 2,
Recipient: sender.Public(),
Recipient: sender.Public().Repr(),
})

trB, _ := NewTestTransactionValue(sender, recipient, 4, 1)
trB.Input.Hash = HashSum(trA)

trB, _ = trB.TxBody.Sign(sender, crand.Reader)
trB, _ = trB.TxBody.Sign(*sender, crand.Reader)

cbA, _ := NewValidCloudBaseTestTransaction()
cbB, _ := NewValidCloudBaseTestTransaction()
Expand All @@ -169,7 +169,7 @@ func NewValidBlockChainFixture() (*BlockChain, Wallet) {
return &BlockChain{
Blocks: []*Block{inputBlock, outputBlock},
Head: NewTestHash(),
}, recipient
}, *recipient
}

// NewValidTestChainAndBlock creates a valid BlockChain and a Block that is valid
Expand All @@ -192,7 +192,7 @@ func NewValidTestChainAndBlock() (*BlockChain, *Block) {
}
tbody.Outputs[0] = TxOutput{
Amount: a,
Recipient: NewWallet().Public(),
Recipient: NewWallet().Public().Repr(),
}

tr, _ := tbody.Sign(s, crand.Reader)
Expand Down Expand Up @@ -223,7 +223,7 @@ func NewValidCloudBaseTestTransaction() (*Transaction, Address) {
}
cbReward := TxOutput{
Amount: 25,
Recipient: w.Public(),
Recipient: w.Public().Repr(),
}
cbTxBody := TxBody{
Sender: NilAddr,
Expand Down
13 changes: 11 additions & 2 deletions blockchain/transaction.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,14 +26,14 @@ func (thp TxHashPointer) Marshal() []byte {
// TxOutput defines an output to a transaction
type TxOutput struct {
Amount uint64
Recipient Address
Recipient string
}

// Marshal converts a TxOutput to a byte slice
func (to TxOutput) Marshal() []byte {
buf := make([]byte, 8)
binary.LittleEndian.PutUint64(buf, to.Amount)
buf = append(buf, to.Recipient.Marshal()...)
buf = append(buf, []byte(to.Recipient)...)
return buf
}

Expand Down 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
}
23 changes: 16 additions & 7 deletions blockchain/transaction_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,29 +2,38 @@ package blockchain

import (
"testing"

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

func TestTxBodyLen(t *testing.T) {
txBody := NewTestTxBody()
senderLen := AddrLen
inputLen := 2*(32/8) + HashLen
outputLen := len(txBody.Outputs) * (64/8 + AddrLen)
outputLen := len(txBody.Outputs) * (64/8 + ReprLen)
txBodyLen := senderLen + inputLen + outputLen

if txBody.Len() != txBodyLen {
t.Fail()
}
assert.Equal(t, txBody.Len(), txBodyLen)
}

func TestTransactionLen(t *testing.T) {
tx := NewTestTransaction()
senderLen := AddrLen
inputLen := 2*(32/8) + HashLen
outputLen := len(tx.TxBody.Outputs) * (64/8 + AddrLen)
outputLen := len(tx.TxBody.Outputs) * (64/8 + ReprLen)
txBodyLen := senderLen + inputLen + outputLen
txLen := txBodyLen + SigLen

if tx.Len() != txLen {
t.Fail()
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))
}
Loading

0 comments on commit badd701

Please sign in to comment.