Skip to content

Commit

Permalink
Add blockchain models and implement marshalling
Browse files Browse the repository at this point in the history
  • Loading branch information
jordanschalm committed May 8, 2017
1 parent 8fb32b0 commit 4ca1ad4
Show file tree
Hide file tree
Showing 4 changed files with 164 additions and 0 deletions.
44 changes: 44 additions & 0 deletions blockchain/blockchain.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
package blockchain

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

type BlockHeader struct {
blockNumber uint32
lastBlock Hash
miner Wallet
}

func (bh *BlockHeader) Marshal() []byte {
buf := []byte{}
binary.LittleEndian.PutUint32(buf, bh.blockNumber)
buf = append(buf, bh.lastBlock...)
buf = append(buf, bh.miner.Marshal()...)
return buf
}

type Block struct {
BlockHeader
transactions []Transaction
}

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

func (b *Block) Hash() []byte {
sum := sha256.Sum256(b.Marshal())
return sum[:]
}

type BlockChain []Block

func (bc BlockChain) Verify(b *Block) {

}
50 changes: 50 additions & 0 deletions blockchain/transaction.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
package blockchain

import (
"encoding/binary"
)

// TxHashPointer is a reference to a transaction on the blockchain.
type TxHashPointer struct {
blockNumber uint32
hash []byte
}

func (thp TxHashPointer) Marshal() []byte {
buf := []byte{}
binary.LittleEndian.PutUint32(buf, thp.blockNumber)
return append(buf, thp.hash...)
}

// TxBody contains all relevant information about a transaction.
type TxBody struct {
sender Wallet
inputs []TxHashPointer
outputs []TxHashPointer
}

func (tb *TxBody) Marshal() []byte {
buf := tb.sender.Marshal()
for _, input := range tb.inputs {
buf = append(buf, input.Marshal()...)
}
for _, output := range tb.outputs {
buf = append(buf, output.Marshal()...)
}
return buf
}

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

func (t *Transaction) Marshal() []byte {
buf := t.TxBody.Marshal()
buf = append(buf, t.hash...)
buf = append(buf, t.sig.X.Bytes()...)
buf = append(buf, t.sig.Y.Bytes()...)
return buf
}
50 changes: 50 additions & 0 deletions blockchain/wallet.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
package blockchain

import (
"crypto/ecdsa"
"crypto/elliptic"
"crypto/rand"
"fmt"
"math/big"
)

var curve = elliptic.P256()

// Wallet represents a Cumulus wallet address in the blockchain.
type Wallet ecdsa.PublicKey

// Hash represents a hash of a transaction.
type Hash []byte

// Signature represents a signature of a transaction.
type Signature struct {
X big.Int
Y big.Int
}

// 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)
if err != nil {
return nil, err
}
pk := Wallet(k.PublicKey)
return &pk, nil
}

func (w *Wallet) String() string {
return fmt.Sprintf("%x-%x", w.X, w.Y)
}

func (w *Wallet) Marshal() []byte {
return elliptic.Marshal(curve, w.X, w.Y)
}

func (w *Wallet) Equals(other *Wallet) bool {
return w.X.Cmp(other.X) == 0 && w.Y.Cmp(other.Y) == 0
}

func Unmarshal(wallet []byte) *Wallet {
x, y := elliptic.Unmarshal(curve, wallet)
return &Wallet{curve, x, y}
}
20 changes: 20 additions & 0 deletions blockchain/wallet_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
package blockchain

import (
"fmt"
"testing"
)

func TestUnmarshal(t *testing.T) {
w, err := NewWallet()
if err != nil {
t.Fail()
}

unmarshalled := Unmarshal(w.Marshal())
fmt.Println("w", w.X, w.Y)
fmt.Println("u", unmarshalled.X, unmarshalled.Y)
if !w.Equals(unmarshalled) {
t.Fatal("Unmarshal produced a different wallet")
}
}

0 comments on commit 4ca1ad4

Please sign in to comment.