Integrate transactions into the blockchain

This commit is contained in:
Ivan Kuznetsov 2017-09-03 09:45:49 +07:00
parent 2ba0f1bfdd
commit 08a211be41
4 changed files with 45 additions and 11 deletions

View File

@ -10,7 +10,7 @@ import (
// Block keeps block headers // Block keeps block headers
type Block struct { type Block struct {
Timestamp int64 Timestamp int64
Data []byte Transactions []*Transaction
PrevBlockHash []byte PrevBlockHash []byte
Hash []byte Hash []byte
Nonce int Nonce int
@ -30,8 +30,8 @@ func (b *Block) Serialize() []byte {
} }
// NewBlock creates and returns Block // NewBlock creates and returns Block
func NewBlock(data string, prevBlockHash []byte) *Block { func NewBlock(transactions []*Transaction, prevBlockHash []byte) *Block {
block := &Block{time.Now().Unix(), []byte(data), prevBlockHash, []byte{}, 0} block := &Block{time.Now().Unix(), transactions, prevBlockHash, []byte{}, 0}
pow := NewProofOfWork(block) pow := NewProofOfWork(block)
nonce, hash := pow.Run() nonce, hash := pow.Run()
@ -42,8 +42,8 @@ func NewBlock(data string, prevBlockHash []byte) *Block {
} }
// NewGenesisBlock creates and returns genesis Block // NewGenesisBlock creates and returns genesis Block
func NewGenesisBlock() *Block { func NewGenesisBlock(coinbase *Transaction) *Block {
return NewBlock("Genesis Block", []byte{}) return NewBlock([]*Transaction{coinbase}, []byte{})
} }
// DeserializeBlock deserializes a block // DeserializeBlock deserializes a block

View File

@ -9,6 +9,7 @@ import (
const dbFile = "blockchain.db" const dbFile = "blockchain.db"
const blocksBucket = "blocks" const blocksBucket = "blocks"
const genesisCoinbase = "The Times 03/Jan/2009 Chancellor on brink of second bailout for banks"
// Blockchain keeps a sequence of Blocks // Blockchain keeps a sequence of Blocks
type Blockchain struct { type Blockchain struct {
@ -86,7 +87,7 @@ func (i *BlockchainIterator) Next() *Block {
} }
// NewBlockchain creates a new Blockchain with genesis Block // NewBlockchain creates a new Blockchain with genesis Block
func NewBlockchain() *Blockchain { func NewBlockchain(address string) *Blockchain {
var tip []byte var tip []byte
db, err := bolt.Open(dbFile, 0600, nil) db, err := bolt.Open(dbFile, 0600, nil)
if err != nil { if err != nil {
@ -98,7 +99,8 @@ func NewBlockchain() *Blockchain {
if b == nil { if b == nil {
fmt.Println("No existing blockchain found. Creating a new one...") 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)) b, err := tx.CreateBucket([]byte(blocksBucket))
if err != nil { if err != nil {

View File

@ -31,10 +31,18 @@ func NewProofOfWork(b *Block) *ProofOfWork {
} }
func (pow *ProofOfWork) prepareData(nonce int) []byte { 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( data := bytes.Join(
[][]byte{ [][]byte{
pow.block.PrevBlockHash, pow.block.PrevBlockHash,
pow.block.Data, txHash[:],
IntToHex(pow.block.Timestamp), IntToHex(pow.block.Timestamp),
IntToHex(int64(targetBits)), IntToHex(int64(targetBits)),
IntToHex(int64(nonce)), IntToHex(int64(nonce)),

View File

@ -1,6 +1,11 @@
package main package main
import "log" import (
"bytes"
"crypto/sha256"
"encoding/gob"
"log"
)
const subsidy = 10 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 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 // TXInput represents a transaction input
type TXInput struct { type TXInput struct {
Txid int Txid int
@ -34,8 +54,12 @@ func (out *TXOutput) Unlock(unlockingData string) bool {
} }
// NewCoinbaseTX creates a new coinbase transaction // NewCoinbaseTX creates a new coinbase transaction
func NewCoinbaseTX(to string) *Transaction { func NewCoinbaseTX(to, data string) *Transaction {
txin := TXInput{-1, -1, "The Times 03/Jan/2009 Chancellor on brink of second bailout for banks"} if data == "" {
data = "Coinbase"
}
txin := TXInput{-1, -1, data}
txout := TXOutput{subsidy, to} txout := TXOutput{subsidy, to}
tx := Transaction{[]TXInput{txin}, []TXOutput{txout}} tx := Transaction{[]TXInput{txin}, []TXOutput{txout}}