Browse Source

updated data structures, moved NewBlock under Node functions

master
arnaucube 5 years ago
parent
commit
16f99b279a
8 changed files with 182 additions and 58 deletions
  1. +2
    -11
      core/block.go
  2. +0
    -2
      core/block_test.go
  3. +53
    -16
      core/blockchain.go
  4. +75
    -10
      core/blockchain_test.go
  5. +0
    -1
      core/keys.go
  6. +2
    -0
      core/tx.go
  7. +24
    -12
      node/node.go
  8. +26
    -6
      node/node_test.go

+ 2
- 11
core/block.go

@ -10,9 +10,9 @@ import (
type Block struct {
Height uint64
PrevHash Hash
NextHash Hash
Txs []Tx
Miner Address
MinerPubK *ecdsa.PublicKey // tmp meanwhile no ecrecover function
Timestamp time.Time
Nonce uint64
Hash Hash
@ -23,9 +23,9 @@ func (block Block) Copy() *Block {
return &Block{
Height: block.Height,
PrevHash: block.PrevHash,
NextHash: block.NextHash,
Txs: block.Txs,
Miner: block.Miner,
MinerPubK: block.MinerPubK,
Timestamp: block.Timestamp,
Nonce: block.Nonce,
Hash: block.Hash,
@ -67,15 +67,6 @@ func CheckBlockPoW(block *Block, difficulty uint64) bool {
return CheckPoW(HashBytes(blockCopy.Bytes()), difficulty)
}
func VerifyBlockSignature(pubK *ecdsa.PublicKey, block *Block) bool {
sig, err := SignatureFromBytes(block.Signature)
if err != nil {
return false
}
return VerifySignature(pubK, block.Hash[:], *sig)
}
func BlockFromBytes(b []byte) (*Block, error) {
var block *Block
err := json.Unmarshal(b, &block)

+ 0
- 2
core/block_test.go

@ -10,7 +10,6 @@ import (
func TestBlock(t *testing.T) {
block := &Block{
PrevHash: HashBytes([]byte("prevhash")),
NextHash: HashBytes([]byte("nextHash")),
Txs: []Tx{},
Miner: Address(HashBytes([]byte("addrfromminer"))),
Timestamp: time.Now(),
@ -38,7 +37,6 @@ func TestBlock(t *testing.T) {
func TestNewBlock(t *testing.T) {
block := &Block{
PrevHash: HashBytes([]byte("prevhash")),
NextHash: HashBytes([]byte("nextHash")),
Txs: []Tx{},
Miner: Address(HashBytes([]byte("addrfromminer"))),
Timestamp: time.Now(),

+ 53
- 16
core/blockchain.go

@ -1,18 +1,25 @@
package core
import (
"bytes"
"crypto/ecdsa"
"errors"
"time"
"github.com/arnaucube/slowlorisdb/db"
)
type PoA struct {
AuthMiners []*ecdsa.PublicKey
}
type Blockchain struct {
Id []byte // Id allows to have multiple blockchains
Difficulty uint64
Genesis Hash
LastBlock *Block
db *db.Db
blockdb *db.Db
txdb *db.Db
PoA PoA
}
func NewBlockchain(database *db.Db, dif uint64) *Blockchain {
@ -21,23 +28,25 @@ func NewBlockchain(database *db.Db, dif uint64) *Blockchain {
Difficulty: dif,
Genesis: HashBytes([]byte("genesis")),
LastBlock: &Block{},
db: database,
blockdb: database,
PoA: PoA{},
}
return blockchain
}
func (bc *Blockchain) NewBlock(txs []Tx) *Block {
block := &Block{
Height: bc.GetHeight() + 1,
PrevHash: bc.LastBlock.Hash,
Txs: txs,
Miner: Address{}, // TODO put the node address
Timestamp: time.Now(),
Nonce: 0,
Hash: Hash{},
Signature: []byte{},
func NewPoABlockchain(database *db.Db, authNodes []*ecdsa.PublicKey) *Blockchain {
poa := PoA{
AuthMiners: authNodes,
}
blockchain := &Blockchain{
Id: []byte{},
Difficulty: uint64(0),
Genesis: HashBytes([]byte("genesis")), // tmp
LastBlock: &Block{},
blockdb: database,
PoA: poa,
}
return block
return blockchain
}
func (bc *Blockchain) GetHeight() uint64 {
@ -50,12 +59,12 @@ func (bc *Blockchain) GetLastBlock() *Block {
func (bc *Blockchain) AddBlock(block *Block) error {
bc.LastBlock = block
err := bc.db.Put(block.Hash[:], block.Bytes())
err := bc.blockdb.Put(block.Hash[:], block.Bytes())
return err
}
func (bc *Blockchain) GetBlock(hash Hash) (*Block, error) {
v, err := bc.db.Get(hash[:])
v, err := bc.blockdb.Get(hash[:])
if err != nil {
return nil, err
}
@ -81,3 +90,31 @@ func (bc *Blockchain) GetPrevBlock(hash Hash) (*Block, error) {
return prevBlock, nil
}
func (bc *Blockchain) VerifyBlockSignature(block *Block) bool {
// check if the signer is one of the blockchain.AuthMiners
signerIsMiner := false
for _, pubK := range bc.PoA.AuthMiners {
if bytes.Equal(PackPubK(pubK), block.Miner[:]) {
signerIsMiner = true
}
}
if !signerIsMiner && len(bc.PoA.AuthMiners) > 0 {
return false
}
// get the signature
sig, err := SignatureFromBytes(block.Signature)
if err != nil {
return false
}
// check if the signature is by the miner
return VerifySignature(block.MinerPubK, block.Hash[:], *sig)
}
// func (bc *Blockchain) Mint(toAddr Address, amount uint64) error {
// fromAddr := Address(HashBytes([]byte("mint")))
// out :=
// tx := NewTx(fromAddr, toAddr, []Input, )
// }

+ 75
- 10
core/blockchain_test.go

@ -3,19 +3,27 @@ package core
import (
"io/ioutil"
"testing"
"time"
"github.com/arnaucube/slowlorisdb/db"
"github.com/stretchr/testify/assert"
)
func TestBlockchainDataStructure(t *testing.T) {
dir, err := ioutil.TempDir("", "db")
assert.Nil(t, err)
db, err := db.New(dir)
assert.Nil(t, err)
bc := NewBlockchain(db, uint64(1))
block := bc.NewBlock([]Tx{})
// dir, err := ioutil.TempDir("", "db")
// assert.Nil(t, err)
// db, err := db.New(dir)
// assert.Nil(t, err)
//
// bc := NewBlockchain(db, uint64(1))
block := &Block{
PrevHash: Hash{},
Txs: []Tx{},
Miner: Address{},
Timestamp: time.Now(),
Nonce: 0,
Hash: HashBytes([]byte("blockhash")),
}
block2, err := BlockFromBytes(block.Bytes())
assert.Nil(t, err)
@ -30,7 +38,15 @@ func TestGetBlock(t *testing.T) {
bc := NewBlockchain(db, uint64(1))
block := bc.NewBlock([]Tx{})
block := &Block{
Height: uint64(1),
PrevHash: Hash{},
Txs: []Tx{},
Miner: Address{},
Timestamp: time.Now(),
Nonce: 0,
Hash: HashBytes([]byte("blockhash")),
}
assert.Equal(t, block.Height, uint64(1))
err = bc.AddBlock(block)
@ -49,10 +65,20 @@ func TestGetPrevBlock(t *testing.T) {
bc := NewBlockchain(db, uint64(1))
var prevHash Hash
for i := 0; i < 10; i++ {
block := bc.NewBlock([]Tx{})
block := &Block{
Height: uint64(i + 1),
PrevHash: prevHash,
Txs: []Tx{},
Miner: Address{},
Timestamp: time.Now(),
Nonce: 0,
Hash: Hash{},
}
block.CalculatePoW(bc.Difficulty)
assert.Equal(t, block.Height, uint64(i+1))
prevHash = block.Hash
err = bc.AddBlock(block)
assert.Nil(t, err)
@ -73,6 +99,7 @@ func TestGetPrevBlock(t *testing.T) {
assert.Equal(t, err.Error(), "This was the oldest block")
}
/*
func TestAddBlockWithTx(t *testing.T) {
addr0 := Address(HashBytes([]byte("addr0")))
addr1 := Address(HashBytes([]byte("addr1")))
@ -87,9 +114,47 @@ func TestAddBlockWithTx(t *testing.T) {
var txs []Tx
tx := NewTx(addr0, addr1, []Input{}, []Output{})
txs = append(txs, *tx)
block := bc.NewBlock(txs)
block := &Block{
PrevHash: Hash{},
NextHash: Hash{},
Txs: txs,
Miner: Address{},
Timestamp: time.Now(),
Nonce: 0,
Hash: HashBytes([]byte("blockhash")),
}
block2, err := BlockFromBytes(block.Bytes())
assert.Nil(t, err)
assert.Equal(t, block2.Bytes(), block.Bytes())
}
func TestPoABlockchainDataStructure(t *testing.T) {
dir, err := ioutil.TempDir("", "db")
assert.Nil(t, err)
db, err := db.New(dir)
assert.Nil(t, err)
var authNodesPubK []*ecdsa.PublicKey
for i := 0; i < 3; i++ {
privK, err := NewKey()
assert.Nil(t, err)
authNodesPubK = append(authNodesPubK, &privK.PublicKey)
}
bc := NewPoABlockchain(db, authNodesPubK)
block := &Block{
PrevHash: Hash{},
NextHash: Hash{},
Txs: []Tx{},
Miner: Address{},
Timestamp: time.Now(),
Nonce: 0,
Hash: HashBytes([]byte("blockhash")),
}
block2, err := BlockFromBytes(block.Bytes())
assert.Nil(t, err)
assert.Equal(t, block2.Bytes(), block.Bytes())
}
*/

+ 0
- 1
core/keys.go

@ -94,7 +94,6 @@ func Sign(privK *ecdsa.PrivateKey, m []byte) (*Signature, error) {
func VerifySignature(pubK *ecdsa.PublicKey, m []byte, sig Signature) bool {
hashMsg := HashBytes(m)
verified := ecdsa.Verify(pubK, hashMsg[:], sig.R, sig.S)
return verified
}

+ 2
- 0
core/tx.go

@ -46,5 +46,7 @@ func CheckTx(tx *Tx) bool {
if totalIn < totalOut {
return false
}
// TODO check signature
return true
}

+ 24
- 12
node/node.go

@ -2,31 +2,28 @@ package node
import (
"crypto/ecdsa"
"time"
"github.com/arnaucube/slowlorisdb/core"
"github.com/arnaucube/slowlorisdb/db"
)
type Node struct {
PrivK *ecdsa.PrivateKey
Addr core.Address
Bc *core.Blockchain
Miner bool // indicates if the node is running as a miner
PendingTxs []core.Tx
}
func NewNode(db *db.Db, dif uint64) (*Node, error) {
privK, err := core.NewKey()
if err != nil {
return nil, err
}
func NewNode(privK *ecdsa.PrivateKey, bc *core.Blockchain, isMiner bool) (*Node, error) {
addr := core.AddressFromPrivK(privK)
bc := core.NewBlockchain(db, dif)
node := &Node{
PrivK: privK,
Addr: addr,
Bc: bc,
PrivK: privK,
Addr: addr,
Bc: bc,
Miner: isMiner,
PendingTxs: []core.Tx{},
}
return node, nil
}
@ -44,7 +41,7 @@ func (node *Node) AddToPendingTxs(tx core.Tx) {
}
func (node *Node) BlockFromPendingTxs() (*core.Block, error) {
block := node.Bc.NewBlock(node.PendingTxs)
block := node.NewBlock(node.PendingTxs)
err := block.CalculatePoW(node.Bc.Difficulty)
if err != nil {
return nil, err
@ -56,3 +53,18 @@ func (node *Node) BlockFromPendingTxs() (*core.Block, error) {
block.Signature = sig.Bytes()
return block, nil
}
func (node *Node) NewBlock(txs []core.Tx) *core.Block {
block := &core.Block{
Height: node.Bc.GetHeight() + 1,
PrevHash: node.Bc.LastBlock.Hash,
Txs: txs,
Miner: core.Address{},
MinerPubK: &node.PrivK.PublicKey,
Timestamp: time.Now(),
Nonce: 0,
Hash: core.Hash{},
Signature: []byte{},
}
return block
}

+ 26
- 6
node/node_test.go

@ -15,7 +15,12 @@ func TestNode(t *testing.T) {
db, err := db.New(dir)
assert.Nil(t, err)
node, err := NewNode(db, uint64(1))
privK, err := core.NewKey()
assert.Nil(t, err)
dif := uint64(1)
bc := core.NewBlockchain(db, dif)
node, err := NewNode(privK, bc, true)
assert.Nil(t, err)
assert.Equal(t, node.Addr, core.AddressFromPrivK(node.PrivK))
@ -27,7 +32,12 @@ func TestNodeSignature(t *testing.T) {
db, err := db.New(dir)
assert.Nil(t, err)
node, err := NewNode(db, uint64(1))
privK, err := core.NewKey()
assert.Nil(t, err)
dif := uint64(1)
bc := core.NewBlockchain(db, dif)
node, err := NewNode(privK, bc, true)
assert.Nil(t, err)
m := []byte("test")
@ -43,7 +53,12 @@ func TestBlockFromPendingTxs(t *testing.T) {
db, err := db.New(dir)
assert.Nil(t, err)
node, err := NewNode(db, uint64(1))
privK, err := core.NewKey()
assert.Nil(t, err)
dif := uint64(1)
bc := core.NewBlockchain(db, dif)
node, err := NewNode(privK, bc, true)
assert.Nil(t, err)
addr0 := core.Address(core.HashBytes([]byte("addr0")))
@ -53,7 +68,7 @@ func TestBlockFromPendingTxs(t *testing.T) {
block, err := node.BlockFromPendingTxs()
assert.Nil(t, err)
assert.True(t, core.CheckBlockPoW(block, node.Bc.Difficulty))
assert.True(t, core.VerifyBlockSignature(&node.PrivK.PublicKey, block))
assert.True(t, node.Bc.VerifyBlockSignature(block))
}
func TestBlockFromPendingTxsIteration(t *testing.T) {
@ -62,7 +77,12 @@ func TestBlockFromPendingTxsIteration(t *testing.T) {
db, err := db.New(dir)
assert.Nil(t, err)
node, err := NewNode(db, uint64(1))
privK, err := core.NewKey()
assert.Nil(t, err)
dif := uint64(1)
bc := core.NewBlockchain(db, dif)
node, err := NewNode(privK, bc, true)
assert.Nil(t, err)
addr0 := core.Address(core.HashBytes([]byte("addr0")))
@ -74,5 +94,5 @@ func TestBlockFromPendingTxsIteration(t *testing.T) {
block, err := node.BlockFromPendingTxs()
assert.Nil(t, err)
assert.True(t, core.CheckBlockPoW(block, node.Bc.Difficulty))
assert.True(t, core.VerifyBlockSignature(&node.PrivK.PublicKey, block))
assert.True(t, node.Bc.VerifyBlockSignature(block))
}

Loading…
Cancel
Save