Browse Source

add node create blocks from pending txs

master
arnaucube 5 years ago
parent
commit
e122822151
9 changed files with 117 additions and 36 deletions
  1. +27
    -4
      core/block.go
  2. +7
    -4
      core/block_test.go
  3. +11
    -9
      core/blockchain.go
  4. +5
    -6
      core/blockchain_test.go
  5. +2
    -2
      core/common.go
  6. +1
    -1
      core/common_test.go
  7. +3
    -3
      core/keys.go
  8. +24
    -5
      node/node.go
  9. +37
    -2
      node/node_test.go

+ 27
- 4
core/block.go

@ -43,6 +43,20 @@ type Block struct {
Signature []byte 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 // Bytes outputs a byte array containing the data of the Block
func (blk Block) Bytes() []byte { func (blk Block) Bytes() []byte {
b, _ := json.Marshal(blk) b, _ := json.Marshal(blk)
@ -56,16 +70,25 @@ func (blk *Block) GetNonce() uint64 {
func (blk *Block) IncrementNonce() { func (blk *Block) IncrementNonce() {
blk.Nonce++ 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) { for !CheckPoW(hash, difficulty) {
block.IncrementNonce()
hash = HashBytes(block.Bytes())
blockCopy.IncrementNonce()
hash = HashBytes(blockCopy.Bytes())
} }
block.Hash = hash block.Hash = hash
return nil 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) { func BlockFromBytes(b []byte) (*Block, error) {
var block *Block var block *Block
err := json.Unmarshal(b, &block) err := json.Unmarshal(b, &block)

+ 7
- 4
core/block_test.go

@ -18,11 +18,14 @@ func TestBlock(t *testing.T) {
Hash: HashBytes([]byte("blockhash")), Hash: HashBytes([]byte("blockhash")),
} }
block, err := BlockFromBytes(block.Bytes())
blockParsed, err := BlockFromBytes(block.Bytes())
assert.Nil(t, err) 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) nonce, err := CalculatePoW(block, difficulty)
assert.Nil(t, err) assert.Nil(t, err)
block.Nonce = nonce block.Nonce = nonce
@ -47,7 +50,7 @@ func TestNewBlock(t *testing.T) {
assert.Nil(t, err) assert.Nil(t, err)
assert.Equal(t, block2.Bytes(), block.Bytes()) assert.Equal(t, block2.Bytes(), block.Bytes())
difficulty := 2
difficulty := uint64(2)
nonce, err := CalculatePoW(block, difficulty) nonce, err := CalculatePoW(block, difficulty)
assert.Nil(t, err) assert.Nil(t, err)
block.Nonce = nonce block.Nonce = nonce

+ 11
- 9
core/blockchain.go

@ -8,18 +8,20 @@ import (
) )
type Blockchain struct { 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{ blockchain := &Blockchain{
Id: []byte{},
Genesis: Hash{},
LastBlock: &Block{},
db: database,
Id: []byte{},
Difficulty: dif,
Genesis: HashBytes([]byte("genesis")),
LastBlock: &Block{},
db: database,
} }
return blockchain return blockchain
} }

+ 5
- 6
core/blockchain_test.go

@ -14,7 +14,7 @@ func TestBlockchainDataStructure(t *testing.T) {
db, err := db.New(dir) db, err := db.New(dir)
assert.Nil(t, err) assert.Nil(t, err)
bc := NewBlockchain(db)
bc := NewBlockchain(db, uint64(1))
block := bc.NewBlock([]Tx{}) block := bc.NewBlock([]Tx{})
block2, err := BlockFromBytes(block.Bytes()) block2, err := BlockFromBytes(block.Bytes())
@ -28,7 +28,7 @@ func TestGetBlock(t *testing.T) {
db, err := db.New(dir) db, err := db.New(dir)
assert.Nil(t, err) assert.Nil(t, err)
bc := NewBlockchain(db)
bc := NewBlockchain(db, uint64(1))
block := bc.NewBlock([]Tx{}) block := bc.NewBlock([]Tx{})
assert.Equal(t, block.Height, uint64(1)) assert.Equal(t, block.Height, uint64(1))
@ -47,12 +47,11 @@ func TestGetPrevBlock(t *testing.T) {
db, err := db.New(dir) db, err := db.New(dir)
assert.Nil(t, err) assert.Nil(t, err)
difficulty := 1
bc := NewBlockchain(db)
bc := NewBlockchain(db, uint64(1))
for i := 0; i < 10; i++ { for i := 0; i < 10; i++ {
block := bc.NewBlock([]Tx{}) block := bc.NewBlock([]Tx{})
block.CalculatePoW(difficulty)
block.CalculatePoW(bc.Difficulty)
assert.Equal(t, block.Height, uint64(i+1)) assert.Equal(t, block.Height, uint64(i+1))
err = bc.AddBlock(block) err = bc.AddBlock(block)
@ -83,7 +82,7 @@ func TestAddBlockWithTx(t *testing.T) {
db, err := db.New(dir) db, err := db.New(dir)
assert.Nil(t, err) assert.Nil(t, err)
bc := NewBlockchain(db)
bc := NewBlockchain(db, uint64(1))
var txs []Tx var txs []Tx
tx := NewTx(addr0, addr1, []Input{}, []Output{}) tx := NewTx(addr0, addr1, []Input{}, []Output{})

+ 2
- 2
core/common.go

@ -31,7 +31,7 @@ type PoWData interface {
} }
// CheckPoW verifies the PoW difficulty of a Hash // 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 var empty [32]byte
if !bytes.Equal(hash[:][0:difficulty], empty[0:difficulty]) { if !bytes.Equal(hash[:][0:difficulty], empty[0:difficulty]) {
return false 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 // 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()) hash := HashBytes(data.Bytes())
for !CheckPoW(hash, difficulty) { for !CheckPoW(hash, difficulty) {
data.IncrementNonce() data.IncrementNonce()

+ 1
- 1
core/common_test.go

@ -36,7 +36,7 @@ func (d *testData) IncrementNonce() {
} }
func TestPoW(t *testing.T) { func TestPoW(t *testing.T) {
difficulty := 2
difficulty := uint64(2)
data := &testData{ data := &testData{
Data: []byte("test"), Data: []byte("test"),
Nonce: 0, Nonce: 0,

+ 3
- 3
core/keys.go

@ -45,9 +45,9 @@ func AddressFromPrivK(privK *ecdsa.PrivateKey) Address {
return Address(h) 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 return b
} }

+ 24
- 5
node/node.go

@ -8,19 +8,20 @@ import (
) )
type Node struct { 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() privK, err := core.NewKey()
if err != nil { if err != nil {
return nil, err return nil, err
} }
addr := core.AddressFromPrivK(privK) addr := core.AddressFromPrivK(privK)
bc := core.NewBlockchain(db)
bc := core.NewBlockchain(db, dif)
node := &Node{ node := &Node{
PrivK: privK, PrivK: privK,
@ -33,3 +34,21 @@ func NewNode(db *db.Db) (*Node, error) {
func (node *Node) Sign(m []byte) (*core.Signature, error) { func (node *Node) Sign(m []byte) (*core.Signature, error) {
return core.Sign(node.PrivK, m) 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
}

+ 37
- 2
node/node_test.go

@ -15,7 +15,7 @@ func TestNode(t *testing.T) {
db, err := db.New(dir) db, err := db.New(dir)
assert.Nil(t, err) assert.Nil(t, err)
node, err := NewNode(db)
node, err := NewNode(db, uint64(1))
assert.Nil(t, err) assert.Nil(t, err)
assert.Equal(t, node.Addr, core.AddressFromPrivK(node.PrivK)) assert.Equal(t, node.Addr, core.AddressFromPrivK(node.PrivK))
@ -27,7 +27,7 @@ func TestNodeSignature(t *testing.T) {
db, err := db.New(dir) db, err := db.New(dir)
assert.Nil(t, err) assert.Nil(t, err)
node, err := NewNode(db)
node, err := NewNode(db, uint64(1))
assert.Nil(t, err) assert.Nil(t, err)
m := []byte("test") m := []byte("test")
@ -36,3 +36,38 @@ func TestNodeSignature(t *testing.T) {
pubK := node.PrivK.PublicKey pubK := node.PrivK.PublicKey
assert.True(t, core.VerifySignature(&pubK, m, *sig)) 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{})
//
// }
// }

Loading…
Cancel
Save