arnaucube
arnaucube/slowlorisdbPublic Self-hosted repository
updated data structures, moved NewBlock under Node functions
arnaucube arnaucube@gmail.com
Sun, 07 Apr 2019 23:19:06 +0200
commit

16f99b279a1448bff65184882bbb84be24ba6136

parent

701731ea679ac33c13dfbd1b9e88ed7c9fbb09c3

M core/block.go → core/block.go

@@ -10,9 +10,9 @@ // Block holds the data structure for the block

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,

@@ -65,15 +65,6 @@ blockCopy := block.Copy()

blockCopy.Hash = Hash{} blockCopy.Signature = []byte{} 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) {
M core/block_test.go → core/block_test.go

@@ -10,7 +10,6 @@

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 TestNewBlock(t *testing.T) { block := &Block{ PrevHash: HashBytes([]byte("prevhash")), - NextHash: HashBytes([]byte("nextHash")), Txs: []Tx{}, Miner: Address(HashBytes([]byte("addrfromminer"))), Timestamp: time.Now(),
M core/blockchain.go → 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 @@ Id: []byte{},

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) 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 @@ }

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, ) +// }
M core/blockchain_test.go → core/blockchain_test.go

@@ -3,19 +3,27 @@

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 @@ assert.Nil(t, err)

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 @@ assert.Nil(t, err)

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 @@ }

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 @@

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()) +} +*/
M core/keys.go → core/keys.go

@@ -94,7 +94,6 @@ }

func VerifySignature(pubK *ecdsa.PublicKey, m []byte, sig Signature) bool { hashMsg := HashBytes(m) - verified := ecdsa.Verify(pubK, hashMsg[:], sig.R, sig.S) return verified }
M core/tx.go → core/tx.go

@@ -46,5 +46,7 @@ }

if totalIn < totalOut { return false } + + // TODO check signature return true }
M node/node.go → 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 @@ node.PendingTxs = append(node.PendingTxs, 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 @@ }

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 +}
M node/node_test.go → node/node_test.go

@@ -15,7 +15,12 @@ assert.Nil(t, err)

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 @@ assert.Nil(t, err)

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 @@ assert.Nil(t, err)

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 @@ node.AddToPendingTxs(*tx)

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 @@ assert.Nil(t, err)

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 @@ }

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)) }