Browse Source

Add core blockchain

rust-port
garritfra 6 years ago
parent
commit
1c815a67a3
  1. 4
      .gitignore
  2. 4
      Cargo.lock
  3. 6
      Cargo.toml
  4. 14
      core/Block.go
  5. 67
      core/Blockchain.go
  6. 9
      core/Transaction.go
  7. 18
      core/block_test.go
  8. 32
      core/blockchain_test.go
  9. 23
      crypto/crypto.go
  10. 9
      main.go
  11. 66
      server/webserver.go
  12. 27
      src/core/blockchain.rs
  13. 1
      src/core/mod.rs
  14. 11
      src/main.rs

4
.gitignore vendored

@ -1,3 +1,5 @@
blockchain-project
.vscode/
core/core
core/core
/target
**/*.rs.bk

4
Cargo.lock generated

@ -0,0 +1,4 @@
[[package]]
name = "blockchain-project"
version = "0.1.0"

6
Cargo.toml

@ -0,0 +1,6 @@
[package]
name = "blockchain-project"
version = "0.1.0"
authors = ["garritfra <garritfranke@gmail.com>"]
[dependencies]

14
core/Block.go

@ -1,14 +0,0 @@
package core
import (
"time"
)
// Block Struct
type Block struct {
Timestamp time.Time
Hash string
PreviousHash string
Data []Transaction
Nonce int
}

67
core/Blockchain.go

@ -1,67 +0,0 @@
package core
import (
"log"
"strings"
"time"
"github.com/garritfra/blockchain-project/crypto"
)
// Blockchain struct
type Blockchain struct {
Blocks []Block
PendingTransactions []Transaction
}
// MineBlock adds a block to the chain
func (bc *Blockchain) MineBlock() Block {
block := Block{}
block.Data = bc.PendingTransactions
block.Timestamp = time.Now()
block.PreviousHash = bc.GetLastHash()
// Mine Block
log.Print("Mining Block...")
for {
hash := crypto.CalculateHash(block)
if strings.HasPrefix(hash, "00000") {
block.Hash = hash
bc.Blocks = append(bc.Blocks, block)
bc.PendingTransactions = []Transaction{}
log.Print("Block Added: ", block.Hash)
return block
}
block.Nonce++
}
}
// NewBlockchain creates a new Blockchain
func NewBlockchain() Blockchain {
log.Print("Creating Blockchain...")
blockchain := Blockchain{Blocks: make([]Block, 0), PendingTransactions: make([]Transaction, 0)}
// Mine Genesis Block
blockchain.MineBlock()
return blockchain
}
// AddTransaction takes in a transaction and adds it to the block
func (bc *Blockchain) AddTransaction(transaction Transaction) error {
bc.PendingTransactions = append(bc.PendingTransactions, transaction)
return nil
}
// GetLastHash returns the hash of the latest block on the chain
func (bc *Blockchain) GetLastHash() string {
bcLength := len(bc.Blocks)
if bcLength == 0 {
return "0"
}
return bc.Blocks[len(bc.Blocks)-1].Hash
}

9
core/Transaction.go

@ -1,9 +0,0 @@
package core
// Transaction struct
type Transaction struct {
Sender string
Receiver string
Amount int
Message string
}

18
core/block_test.go

@ -1,18 +0,0 @@
package core
import (
"testing"
)
func TestBlock_AddTransaction(t *testing.T) {
block := Block{}
transaction := Transaction{Sender: "foo", Receiver: "bar", Message: "Test", Amount: 100}
block.AddTransaction(transaction)
want := transaction
got := block.Data[0]
if want != got {
t.Errorf("Want: %v, but got %v", want, got)
}
}

32
core/blockchain_test.go

@ -1,32 +0,0 @@
package core
import (
"testing"
)
func Test_generateGenesisBlock(t *testing.T) {
genesisBlock := generateGenesisBlock()
if len(genesisBlock.PreviousHash) > 1 {
t.Errorf("Previous hash of Genesis Block is not empty!")
}
}
func TestNewBlockchain(t *testing.T) {
blockchain := NewBlockchain()
if len(blockchain.Blocks) != 1 {
t.Errorf("New Blockchain has too many Blocks (Besides Genesis)")
}
}
func TestBlockchain_GetLastHash(t *testing.T) {
blockchain := NewBlockchain()
blockchain.MineBlock(Block{})
want := blockchain.Blocks[1].Hash
got := blockchain.GetLastHash()
if got != want {
t.Errorf("Want: %v, but got %v", want, got)
}
}

23
crypto/crypto.go

@ -1,23 +0,0 @@
package crypto
import (
"bytes"
"crypto/sha256"
"encoding/gob"
"encoding/hex"
)
func CalculateHash(obj interface{}) string {
var buffer bytes.Buffer
encoder := gob.NewEncoder(&buffer)
if err := encoder.Encode(obj); err != nil {
panic(err)
}
hasher := sha256.New()
bytes := buffer.Bytes()
hasher.Write(bytes)
sum := hex.EncodeToString(hasher.Sum(nil))
return string(sum)
}

9
main.go

@ -1,9 +0,0 @@
package main
import (
"github.com/garritfra/blockchain-project/server"
)
func main() {
server.ServeHTTP(":42000")
}

66
server/webserver.go

@ -1,66 +0,0 @@
package server
import (
"encoding/gob"
"encoding/json"
"log"
"net/http"
"github.com/garritfra/blockchain-project/core"
)
var blockchain core.Blockchain
// ServeHTTP serves a http server on a given port with format ":PORT"
func ServeHTTP(port string) {
gob.Register(core.Block{})
gob.Register(core.Transaction{})
gob.Register(core.Blockchain{})
blockchain = core.NewBlockchain()
registerRouteHandlers()
log.Print("Listening on port ", port)
if err := http.ListenAndServe(port, nil); err != nil {
panic(err)
}
}
func registerRouteHandlers() {
http.HandleFunc("/", handleListBlocks)
http.HandleFunc("/mine_block", handleMineBlock)
http.HandleFunc("/pending_transactions", handleListPendingTransactions)
http.HandleFunc("/add_transaction", handleAddTransaction)
}
func handleError(err error, w http.ResponseWriter, r *http.Request) {
w.Write([]byte("Error: " + err.Error()))
log.Print(err.Error())
}
func handleListBlocks(w http.ResponseWriter, r *http.Request) {
json.NewEncoder(w).Encode(blockchain.Blocks)
}
func handleAddTransaction(w http.ResponseWriter, r *http.Request) {
decoder := json.NewDecoder(r.Body)
var receivedTransaction core.Transaction
err := decoder.Decode(&receivedTransaction)
if err == nil {
log.Println("Transaction from", receivedTransaction.Sender, "to", receivedTransaction.Receiver, "received")
go blockchain.AddTransaction(receivedTransaction)
} else {
handleError(err, w, r)
}
}
func handleMineBlock(w http.ResponseWriter, r *http.Request) {
block := blockchain.MineBlock()
json.NewEncoder(w).Encode(block)
}
func handleListPendingTransactions(w http.ResponseWriter, r *http.Request) {
json.NewEncoder(w).Encode(blockchain.PendingTransactions)
}

27
src/core/blockchain.rs

@ -0,0 +1,27 @@
pub struct Block {
pub data: i32,
}
pub struct Blockchain {
blocks: Vec<Block>,
}
pub fn new() -> Blockchain {
println!("New blockchain\n");
let genesis = Block { data: 32 };
let blockchain = Blockchain {
blocks: vec![genesis],
};
return blockchain;
}
impl Blockchain {
pub fn addBlock(&mut self, block: Block) {
self.blocks.push(block);
}
pub fn getBlocks(&mut self) -> &Vec<Block> {
&self.blocks
}
}

1
src/core/mod.rs

@ -0,0 +1 @@
pub mod blockchain;

11
src/main.rs

@ -0,0 +1,11 @@
mod core;
fn main() {
let mut blockchain = core::blockchain::new();
let block = core::blockchain::Block { data: 42 };
blockchain.addBlock(block);
for block in blockchain.getBlocks() {
println!("{}", block.data);
}
}
Loading…
Cancel
Save