Skip to content

Commit

Permalink
Add TxOutput struct, some Marshal/Hash functions and skeleton validit…
Browse files Browse the repository at this point in the history
…y logic
  • Loading branch information
jordanschalm committed May 11, 2017
1 parent b39465a commit 4475112
Show file tree
Hide file tree
Showing 4 changed files with 121 additions and 70 deletions.
57 changes: 57 additions & 0 deletions blockchain/block.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
package blockchain

// BlockHeader contains metadata about a block
import (
"crypto/sha256"
"encoding/binary"
"encoding/gob"
"io"
)

// BlockHeader contains metadata about a block
type BlockHeader struct {
blockNumber uint32
lastBlock Hash
miner Wallet
}

// Marshal converts a BlockHeader to a byte slice
func (bh *BlockHeader) Marshal() []byte {
buf := []byte{}
binary.LittleEndian.PutUint32(buf, bh.blockNumber)
for _, b := range bh.lastBlock {
buf = append(buf, b)
}
buf = append(buf, bh.miner.Marshal()...)
return buf
}

// Block represents a block in the blockchain. Contains transactions and header metadata.
type Block struct {
BlockHeader
transactions []*Transaction
}

// Marshal converts a Block to a byte slice
func (b *Block) Marshal() []byte {
buf := b.BlockHeader.Marshal()
for _, t := range b.transactions {
buf = append(buf, t.Marshal()...)
}
return buf
}

// Encode writes the marshalled block to the given io.Writer
func (b *Block) Encode(w io.Writer) {
gob.NewEncoder(w).Encode(b)
}

// Decode reads the marshalled block from the given io.Reader
func (b *Block) Decode(r io.Reader) {
gob.NewDecoder(r).Decode(b)
}

// Hash computes and returns the SHA256 hash of the block
func (b *Block) Hash() Hash {
return sha256.Sum256(b.Marshal())
}
82 changes: 26 additions & 56 deletions blockchain/blockchain.go
Original file line number Diff line number Diff line change
@@ -1,75 +1,45 @@
package blockchain

import (
"crypto/sha256"
"encoding/binary"
"encoding/gob"
"io"
)

// Hash represents a hash of a block or transaction
// Hash represents a 256-bit hash of a block or transaction
type Hash [32]byte

// BlockHeader contains metadata about a block
type BlockHeader struct {
blockNumber uint32
lastBlock Hash
miner Wallet
}

// Marshal converts a BlockHeader to a byte slice
func (bh *BlockHeader) Marshal() []byte {
buf := []byte{}
binary.LittleEndian.PutUint32(buf, bh.blockNumber)
for _, b := range bh.lastBlock {
buf = append(buf, b)
}
buf = append(buf, bh.miner.Marshal()...)
return buf
}

// Block represents a block in the blockchain. Contains transactions and header metadata.
type Block struct {
BlockHeader
transactions []*Transaction
}

// Marshal converts a Block to a byte slice
func (b *Block) Marshal() []byte {
buf := b.BlockHeader.Marshal()
for _, t := range b.transactions {
buf = append(buf, t.Marshal()...)
}
return buf
}

// Encode writes the marshalled block to the given io.Writer
func (b *Block) Encode(w io.Writer) {
gob.NewEncoder(w).Encode(b)
}

// Encode reads the marshalled block from the given io.Reader
func (b *Block) Decode(r io.Reader) {
gob.NewDecoder(r).Decode(b)
}

// Hash computes and returns the SHA256 hash of the block
func (b *Block) Hash() Hash {
return sha256.Sum256(b.Marshal())
}

// BlockChain represents a linked list of blocks
type BlockChain struct {
blocks []*Block
head Hash
}

// Encode writes the marshalled blockchain to the given io.Writer
func (b *BlockChain) Encode(w io.Writer) {
gob.NewEncoder(w).Encode(b)
func (bc *BlockChain) Encode(w io.Writer) {
gob.NewEncoder(w).Encode(bc)
}

// Encode reads the marshalled blockchain from the given io.Reader
func (b *BlockChain) Decode(r io.Reader) {
gob.NewDecoder(r).Decode(b)
// Decode reads the marshalled blockchain from the given io.Reader
func (bc *BlockChain) Decode(r io.Reader) {
gob.NewDecoder(r).Decode(bc)
}

// ValidTransaction checks whether a transaction is valid, assuming the blockchain is valid.
func (bc *BlockChain) ValidTransaction(t *Transaction) bool {
// Find the transaction input (I) in the chain (by hash)
// Check that output to sender in I is equal to outputs in T
// Verify signature of T
return false
}

// ValidBlock checks whether a block is valid
func (bc *BlockChain) ValidBlock(b *Block) bool {
for _, t := range b.transactions {
if !bc.ValidTransaction(t) {
return false
}
}
// Check that block number is one greater than last block
// Check that hash of last block is correct
return false
}
47 changes: 33 additions & 14 deletions blockchain/transaction.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
package blockchain

import "encoding/binary"
import (
"crypto/sha256"
"encoding/binary"
)

// TxHashPointer is a reference to a transaction on the blockchain.
type TxHashPointer struct {
Expand All @@ -18,35 +21,51 @@ func (thp TxHashPointer) Marshal() []byte {
return buf
}

// TxBody contains all relevant information about a transaction.
// TxOutput defines an output to a transaction
type TxOutput struct {
amount uint64
recipient Wallet
}

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

// TxBody contains all relevant information about a transaction
type TxBody struct {
sender Wallet
input TxHashPointer
output TxHashPointer
sender Wallet
input TxHashPointer
outputs []TxOutput
}

// Marshal converts a TxBody to a byte slice
func (tb TxBody) Marshal() []byte {
buf := tb.sender.Marshal()
buf = append(buf, tb.input.Marshal()...)
buf = append(buf, tb.output.Marshal()...)
for _, out := range tb.outputs {
buf = append(buf, out.Marshal()...)
}
return buf
}

// Transaction contains a TxBody and a signature verifying it.
// Transaction contains a TxBody and a signature verifying it
type Transaction struct {
TxBody
hash Hash
sig Signature
sig Signature
}

// Marshal converts a Transaction to a byte slice
func (t *Transaction) Marshal() []byte {
buf := t.TxBody.Marshal()
for _, b := range t.hash {
buf = append(buf, b)
}
buf = append(buf, t.sig.X.Bytes()...)
buf = append(buf, t.sig.Y.Bytes()...)
buf = append(buf, t.sig.Marshal()...)
return buf
}

// Hash returns the SHA256 hash of a transaction
func (t *Transaction) Hash() Hash {
return sha256.Sum256(t.Marshal())
}
5 changes: 5 additions & 0 deletions blockchain/wallet.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,11 @@ type Signature struct {
Y big.Int
}

// Marshal converts a signature to a byte slice
func (s *Signature) Marshal() []byte {
return append(s.X.Bytes(), s.Y.Bytes()...)
}

// New creates a new Wallet backed by a ECC key pair. Uses system entropy.
func newWallet() (*Wallet, error) {
k, err := ecdsa.GenerateKey(curve, rand.Reader)
Expand Down

0 comments on commit 4475112

Please sign in to comment.