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

+ 7
- 4
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

+ 11
- 9
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
}

+ 5
- 6
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{})

+ 2
- 2
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()

+ 1
- 1
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,

+ 3
- 3
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
}

+ 24
- 5
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
}

+ 37
- 2
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{})
//
// }
// }

Loading…
Cancel
Save