diff --git a/block.go b/block.go index 4656080..1d04b4f 100644 --- a/block.go +++ b/block.go @@ -10,7 +10,7 @@ import ( // Block keeps block headers type Block struct { Timestamp int64 - Data []byte + Transactions []*Transaction PrevBlockHash []byte Hash []byte Nonce int @@ -30,8 +30,8 @@ func (b *Block) Serialize() []byte { } // NewBlock creates and returns Block -func NewBlock(data string, prevBlockHash []byte) *Block { - block := &Block{time.Now().Unix(), []byte(data), prevBlockHash, []byte{}, 0} +func NewBlock(transactions []*Transaction, prevBlockHash []byte) *Block { + block := &Block{time.Now().Unix(), transactions, prevBlockHash, []byte{}, 0} pow := NewProofOfWork(block) nonce, hash := pow.Run() @@ -42,8 +42,8 @@ func NewBlock(data string, prevBlockHash []byte) *Block { } // NewGenesisBlock creates and returns genesis Block -func NewGenesisBlock() *Block { - return NewBlock("Genesis Block", []byte{}) +func NewGenesisBlock(coinbase *Transaction) *Block { + return NewBlock([]*Transaction{coinbase}, []byte{}) } // DeserializeBlock deserializes a block diff --git a/blockchain.go b/blockchain.go index edc29df..2290318 100644 --- a/blockchain.go +++ b/blockchain.go @@ -9,6 +9,7 @@ import ( const dbFile = "blockchain.db" const blocksBucket = "blocks" +const genesisCoinbase = "The Times 03/Jan/2009 Chancellor on brink of second bailout for banks" // Blockchain keeps a sequence of Blocks type Blockchain struct { @@ -86,7 +87,7 @@ func (i *BlockchainIterator) Next() *Block { } // NewBlockchain creates a new Blockchain with genesis Block -func NewBlockchain() *Blockchain { +func NewBlockchain(address string) *Blockchain { var tip []byte db, err := bolt.Open(dbFile, 0600, nil) if err != nil { @@ -98,7 +99,8 @@ func NewBlockchain() *Blockchain { if b == nil { fmt.Println("No existing blockchain found. Creating a new one...") - genesis := NewGenesisBlock() + cbtx := NewCoinbaseTX(address, genesisCoinbase) + genesis := NewGenesisBlock(cbtx) b, err := tx.CreateBucket([]byte(blocksBucket)) if err != nil { diff --git a/proofofwork.go b/proofofwork.go index 57127bb..05de09b 100644 --- a/proofofwork.go +++ b/proofofwork.go @@ -31,10 +31,18 @@ func NewProofOfWork(b *Block) *ProofOfWork { } func (pow *ProofOfWork) prepareData(nonce int) []byte { + var txHashes [][]byte + var txHash [32]byte + + for _, tx := range pow.block.Transactions { + txHashes = append(txHashes, tx.GetHash()) + } + txHash = sha256.Sum256(bytes.Join(txHashes, []byte{})) + data := bytes.Join( [][]byte{ pow.block.PrevBlockHash, - pow.block.Data, + txHash[:], IntToHex(pow.block.Timestamp), IntToHex(int64(targetBits)), IntToHex(int64(nonce)), diff --git a/transaction.go b/transaction.go index 4c116f4..61fcf45 100644 --- a/transaction.go +++ b/transaction.go @@ -1,6 +1,11 @@ package main -import "log" +import ( + "bytes" + "crypto/sha256" + "encoding/gob" + "log" +) const subsidy = 10 @@ -15,6 +20,21 @@ func (tx Transaction) IsCoinbase() bool { return len(tx.Vin) == 1 && tx.Vin[0].Txid == -1 && tx.Vin[0].Vout == -1 } +// GetHash hashes the transaction and returns the hash +func (tx Transaction) GetHash() []byte { + var encoded bytes.Buffer + var hash [32]byte + + enc := gob.NewEncoder(&encoded) + err := enc.Encode(tx) + if err != nil { + log.Panic(err) + } + hash = sha256.Sum256(encoded.Bytes()) + + return hash[:] +} + // TXInput represents a transaction input type TXInput struct { Txid int @@ -34,8 +54,12 @@ func (out *TXOutput) Unlock(unlockingData string) bool { } // NewCoinbaseTX creates a new coinbase transaction -func NewCoinbaseTX(to string) *Transaction { - txin := TXInput{-1, -1, "The Times 03/Jan/2009 Chancellor on brink of second bailout for banks"} +func NewCoinbaseTX(to, data string) *Transaction { + if data == "" { + data = "Coinbase" + } + + txin := TXInput{-1, -1, data} txout := TXOutput{subsidy, to} tx := Transaction{[]TXInput{txin}, []TXOutput{txout}}