From e12282215190cf100af506c7956c8352a6edf016 Mon Sep 17 00:00:00 2001 From: arnaucube Date: Sun, 7 Apr 2019 13:56:27 +0200 Subject: [PATCH] add node create blocks from pending txs --- core/block.go | 31 +++++++++++++++++++++++++++---- core/block_test.go | 11 +++++++---- core/blockchain.go | 20 +++++++++++--------- core/blockchain_test.go | 11 +++++------ core/common.go | 4 ++-- core/common_test.go | 2 +- core/keys.go | 6 +++--- node/node.go | 29 ++++++++++++++++++++++++----- node/node_test.go | 39 +++++++++++++++++++++++++++++++++++++-- 9 files changed, 117 insertions(+), 36 deletions(-) diff --git a/core/block.go b/core/block.go index fa3233e..068e373 100644 --- a/core/block.go +++ b/core/block.go @@ -43,6 +43,20 @@ type Block struct { Signature []byte } +func (block Block) Copy() *Block { + return &Block{ + Height: block.Height, + PrevHash: block.PrevHash, + NextHash: block.NextHash, + Txs: block.Txs, + Miner: block.Miner, + Timestamp: block.Timestamp, + Nonce: block.Nonce, + Hash: block.Hash, + Signature: block.Signature, + } +} + // Bytes outputs a byte array containing the data of the Block func (blk Block) Bytes() []byte { b, _ := json.Marshal(blk) @@ -56,16 +70,25 @@ func (blk *Block) GetNonce() uint64 { func (blk *Block) IncrementNonce() { blk.Nonce++ } -func (block *Block) CalculatePoW(difficulty int) error { - hash := HashBytes(block.Bytes()) +func (block *Block) CalculatePoW(difficulty uint64) error { + blockCopy := block.Copy() + blockCopy.Hash = Hash{} + + hash := HashBytes(blockCopy.Bytes()) for !CheckPoW(hash, difficulty) { - block.IncrementNonce() - hash = HashBytes(block.Bytes()) + blockCopy.IncrementNonce() + hash = HashBytes(blockCopy.Bytes()) } block.Hash = hash return nil } +func CheckBlockPoW(block *Block, difficulty uint64) bool { + blockCopy := block.Copy() + blockCopy.Hash = Hash{} + return CheckPoW(HashBytes(blockCopy.Bytes()), difficulty) +} + func BlockFromBytes(b []byte) (*Block, error) { var block *Block err := json.Unmarshal(b, &block) diff --git a/core/block_test.go b/core/block_test.go index 357766a..59c2274 100644 --- a/core/block_test.go +++ b/core/block_test.go @@ -18,11 +18,14 @@ func TestBlock(t *testing.T) { Hash: HashBytes([]byte("blockhash")), } - block, err := BlockFromBytes(block.Bytes()) + blockParsed, err := BlockFromBytes(block.Bytes()) assert.Nil(t, err) - assert.Equal(t, block.Bytes(), block.Bytes()) + assert.Equal(t, blockParsed.Bytes(), block.Bytes()) - difficulty := 2 + blockCopy := block.Copy() + assert.Equal(t, blockCopy.Bytes(), block.Bytes()) + + difficulty := uint64(2) nonce, err := CalculatePoW(block, difficulty) assert.Nil(t, err) block.Nonce = nonce @@ -47,7 +50,7 @@ func TestNewBlock(t *testing.T) { assert.Nil(t, err) assert.Equal(t, block2.Bytes(), block.Bytes()) - difficulty := 2 + difficulty := uint64(2) nonce, err := CalculatePoW(block, difficulty) assert.Nil(t, err) block.Nonce = nonce diff --git a/core/blockchain.go b/core/blockchain.go index ec15b8e..22f0e23 100644 --- a/core/blockchain.go +++ b/core/blockchain.go @@ -8,18 +8,20 @@ import ( ) type Blockchain struct { - Id []byte // Id allows to have multiple blockchains - Genesis Hash - LastBlock *Block - db *db.Db + Id []byte // Id allows to have multiple blockchains + Difficulty uint64 + Genesis Hash + LastBlock *Block + db *db.Db } -func NewBlockchain(database *db.Db) *Blockchain { +func NewBlockchain(database *db.Db, dif uint64) *Blockchain { blockchain := &Blockchain{ - Id: []byte{}, - Genesis: Hash{}, - LastBlock: &Block{}, - db: database, + Id: []byte{}, + Difficulty: dif, + Genesis: HashBytes([]byte("genesis")), + LastBlock: &Block{}, + db: database, } return blockchain } diff --git a/core/blockchain_test.go b/core/blockchain_test.go index 480aed3..667f6cf 100644 --- a/core/blockchain_test.go +++ b/core/blockchain_test.go @@ -14,7 +14,7 @@ func TestBlockchainDataStructure(t *testing.T) { db, err := db.New(dir) assert.Nil(t, err) - bc := NewBlockchain(db) + bc := NewBlockchain(db, uint64(1)) block := bc.NewBlock([]Tx{}) block2, err := BlockFromBytes(block.Bytes()) @@ -28,7 +28,7 @@ func TestGetBlock(t *testing.T) { db, err := db.New(dir) assert.Nil(t, err) - bc := NewBlockchain(db) + bc := NewBlockchain(db, uint64(1)) block := bc.NewBlock([]Tx{}) assert.Equal(t, block.Height, uint64(1)) @@ -47,12 +47,11 @@ func TestGetPrevBlock(t *testing.T) { db, err := db.New(dir) assert.Nil(t, err) - difficulty := 1 - bc := NewBlockchain(db) + bc := NewBlockchain(db, uint64(1)) for i := 0; i < 10; i++ { block := bc.NewBlock([]Tx{}) - block.CalculatePoW(difficulty) + block.CalculatePoW(bc.Difficulty) assert.Equal(t, block.Height, uint64(i+1)) err = bc.AddBlock(block) @@ -83,7 +82,7 @@ func TestAddBlockWithTx(t *testing.T) { db, err := db.New(dir) assert.Nil(t, err) - bc := NewBlockchain(db) + bc := NewBlockchain(db, uint64(1)) var txs []Tx tx := NewTx(addr0, addr1, []Input{}, []Output{}) diff --git a/core/common.go b/core/common.go index 183b5f6..dbf2242 100644 --- a/core/common.go +++ b/core/common.go @@ -31,7 +31,7 @@ type PoWData interface { } // CheckPoW verifies the PoW difficulty of a Hash -func CheckPoW(hash Hash, difficulty int) bool { +func CheckPoW(hash Hash, difficulty uint64) bool { var empty [32]byte if !bytes.Equal(hash[:][0:difficulty], empty[0:difficulty]) { return false @@ -40,7 +40,7 @@ func CheckPoW(hash Hash, difficulty int) bool { } // CalculatePoW calculates the nonce for the given data in order to fit in the current Proof of Work difficulty -func CalculatePoW(data PoWData, difficulty int) (uint64, error) { +func CalculatePoW(data PoWData, difficulty uint64) (uint64, error) { hash := HashBytes(data.Bytes()) for !CheckPoW(hash, difficulty) { data.IncrementNonce() diff --git a/core/common_test.go b/core/common_test.go index f47f808..27821e2 100644 --- a/core/common_test.go +++ b/core/common_test.go @@ -36,7 +36,7 @@ func (d *testData) IncrementNonce() { } func TestPoW(t *testing.T) { - difficulty := 2 + difficulty := uint64(2) data := &testData{ Data: []byte("test"), Nonce: 0, diff --git a/core/keys.go b/core/keys.go index 755a746..5f6b91f 100644 --- a/core/keys.go +++ b/core/keys.go @@ -45,9 +45,9 @@ func AddressFromPrivK(privK *ecdsa.PrivateKey) Address { return Address(h) } -func (sig *Signature) Bytes(r, s *big.Int) []byte { - b := r.Bytes() - b = append(b, s.Bytes()...) +func (sig *Signature) Bytes() []byte { + b := sig.R.Bytes() + b = append(b, sig.S.Bytes()...) return b } diff --git a/node/node.go b/node/node.go index e843663..8fbc9ca 100644 --- a/node/node.go +++ b/node/node.go @@ -8,19 +8,20 @@ import ( ) type Node struct { - PrivK *ecdsa.PrivateKey - Addr core.Address - Bc *core.Blockchain + PrivK *ecdsa.PrivateKey + Addr core.Address + Bc *core.Blockchain + PendingTxs []core.Tx } -func NewNode(db *db.Db) (*Node, error) { +func NewNode(db *db.Db, dif uint64) (*Node, error) { privK, err := core.NewKey() if err != nil { return nil, err } addr := core.AddressFromPrivK(privK) - bc := core.NewBlockchain(db) + bc := core.NewBlockchain(db, dif) node := &Node{ PrivK: privK, @@ -33,3 +34,21 @@ func NewNode(db *db.Db) (*Node, error) { func (node *Node) Sign(m []byte) (*core.Signature, error) { return core.Sign(node.PrivK, m) } + +func (node *Node) AddToPendingTxs(tx core.Tx) { + node.PendingTxs = append(node.PendingTxs, tx) +} + +func (node *Node) BlockFromPendingTxs() (*core.Block, error) { + block := node.Bc.NewBlock(node.PendingTxs) + err := block.CalculatePoW(node.Bc.Difficulty) + if err != nil { + return nil, err + } + sig, err := node.Sign(block.Bytes()) + if err != nil { + return nil, err + } + block.Signature = sig.Bytes() + return block, nil +} diff --git a/node/node_test.go b/node/node_test.go index 3e354c2..7eec9ec 100644 --- a/node/node_test.go +++ b/node/node_test.go @@ -15,7 +15,7 @@ func TestNode(t *testing.T) { db, err := db.New(dir) assert.Nil(t, err) - node, err := NewNode(db) + node, err := NewNode(db, uint64(1)) assert.Nil(t, err) assert.Equal(t, node.Addr, core.AddressFromPrivK(node.PrivK)) @@ -27,7 +27,7 @@ func TestNodeSignature(t *testing.T) { db, err := db.New(dir) assert.Nil(t, err) - node, err := NewNode(db) + node, err := NewNode(db, uint64(1)) assert.Nil(t, err) m := []byte("test") @@ -36,3 +36,38 @@ func TestNodeSignature(t *testing.T) { pubK := node.PrivK.PublicKey assert.True(t, core.VerifySignature(&pubK, m, *sig)) } + +func TestBlockFromPendingTxs(t *testing.T) { + dir, err := ioutil.TempDir("", "db") + assert.Nil(t, err) + db, err := db.New(dir) + assert.Nil(t, err) + + node, err := NewNode(db, uint64(1)) + assert.Nil(t, err) + + addr0 := core.Address(core.HashBytes([]byte("addr0"))) + addr1 := core.Address(core.HashBytes([]byte("addr1"))) + tx := core.NewTx(addr0, addr1, []core.Input{}, []core.Output{}) + node.AddToPendingTxs(*tx) + block, err := node.BlockFromPendingTxs() + assert.True(t, core.CheckBlockPoW(block, node.Bc.Difficulty)) + // TODO add VerifyBlockSignature +} + +// func TestBlockFromPendingTxsIteration(t *testing.T) { +// dir, err := ioutil.TempDir("", "db") +// assert.Nil(t, err) +// db, err := db.New(dir) +// assert.Nil(t, err) +// +// node, err := NewNode(db, uint64(1)) +// assert.Nil(t, err) +// +// addr0 := core.Address(core.HashBytes([]byte("addr0"))) +// addr1 := core.Address(core.HashBytes([]byte("addr1"))) +// for i := 0; i < 10; i++ { +// tx := core.NewTx(addr0, addr1, []core.Input{}, []core.Output{}) +// +// } +// }