From c5893128ac06fc511cd176787c01c63b3e029a3c Mon Sep 17 00:00:00 2001 From: arnaucube Date: Wed, 10 Apr 2019 16:43:04 +0200 Subject: [PATCH] CreateGenesisBlock make tx, continue node test --- core/blockchain.go | 15 +++++++++- core/tx.go | 25 +++++++++++++++-- node/node.go | 38 +++++++++++++++++++++++-- node/node_test.go | 69 ++++++++++++++++++++++++++++++++++++++++++---- 4 files changed, 137 insertions(+), 10 deletions(-) diff --git a/core/blockchain.go b/core/blockchain.go index 05466ee..7791d39 100644 --- a/core/blockchain.go +++ b/core/blockchain.go @@ -143,7 +143,20 @@ func (bc *Blockchain) VerifyBlock(block *Block) bool { return false } - // verify block transactions + // verify block transactions (not if the block is the genesis block) + if !bytes.Equal(block.Txs[0].TxId[:], GenesisHashTxInput[:]) { + for _, tx := range block.Txs { + txVerified := CheckTx(&tx) + if !txVerified { + fmt.Println("tx could not be verified") + return false + } + } + } + + // TODO in --> out0 + // -> out1 + // -> ... return true } diff --git a/core/tx.go b/core/tx.go index e329b23..ad43bc8 100644 --- a/core/tx.go +++ b/core/tx.go @@ -1,6 +1,12 @@ package core -import "crypto/ecdsa" +import ( + "crypto/ecdsa" + "encoding/json" + "fmt" +) + +var GenesisHashTxInput = HashBytes([]byte("genesis")) type Input struct { TxId Hash @@ -14,6 +20,7 @@ type Output struct { // Tx holds the data structure of a transaction type Tx struct { + TxId Hash From *ecdsa.PublicKey To *ecdsa.PublicKey InputCount uint64 @@ -22,6 +29,17 @@ type Tx struct { Signature []byte } +func (tx *Tx) Bytes() []byte { + // TODO add parser, to use minimum amount of bytes + b, _ := json.Marshal(tx) + return b +} + +func (tx *Tx) CalculateTxId() { + h := HashBytes(tx.Bytes()) + tx.TxId = h +} + func NewTx(from, to *ecdsa.PublicKey, in []Input, out []Output) *Tx { tx := &Tx{ From: from, @@ -29,7 +47,9 @@ func NewTx(from, to *ecdsa.PublicKey, in []Input, out []Output) *Tx { InputCount: uint64(len(in)), Inputs: in, Outputs: out, + Signature: []byte{}, } + tx.CalculateTxId() return tx } @@ -46,7 +66,8 @@ func CheckTx(tx *Tx) bool { for _, out := range tx.Outputs { totalOut = totalOut + int(out.Value) } - if totalIn < totalOut { + if totalIn != totalOut { + fmt.Println("totalIn != totalOut") return false } diff --git a/node/node.go b/node/node.go index efa771d..0c70e11 100644 --- a/node/node.go +++ b/node/node.go @@ -85,11 +85,45 @@ func (node *Node) NewBlock(txs []core.Tx) (*core.Block, error) { return block, nil } -func (node *Node) CreateGenesis() (*core.Block, error) { +func (node *Node) CreateGenesis(pubK *ecdsa.PublicKey, amount uint64) (*core.Block, error) { + // pubK is the wallet where the first coins will be created + // amount is the amount of coins that will be created + + in := core.Input{ + TxId: core.GenesisHashTxInput, + Vout: 0, + Value: amount, + } + var ins []core.Input + ins = append(ins, in) + + out := core.Output{ + Value: amount, + } + var outs []core.Output + outs = append(outs, out) + + tx := core.Tx{ + From: &ecdsa.PublicKey{}, + To: pubK, + InputCount: uint64(0), + Inputs: []core.Input{}, + Outputs: outs, + Signature: []byte{}, + } + + // calculate TxId + // tx.CalculateTxId() + tx.TxId = core.GenesisHashTxInput + // sign transaction + + var txs []core.Tx + txs = append(txs, tx) + block := &core.Block{ Height: node.Bc.LastBlock.Height + 1, PrevHash: node.Bc.LastBlock.Hash, - Txs: []core.Tx{}, + Txs: txs, Miner: node.Addr, MinerPubK: &node.PrivK.PublicKey, Timestamp: time.Now(), diff --git a/node/node_test.go b/node/node_test.go index 6d03880..1af916b 100644 --- a/node/node_test.go +++ b/node/node_test.go @@ -122,22 +122,81 @@ func TestFromGenesisToTenBlocks(t *testing.T) { assert.Nil(t, err) // create the genesis block - genesisBlock, err := node.CreateGenesis() + genesisBlock, err := node.CreateGenesis(&privK.PublicKey, uint64(100)) assert.Nil(t, err) assert.NotEqual(t, genesisBlock.Signature, core.Signature{}) assert.NotEqual(t, genesisBlock.Hash, core.Hash{}) - assert.True(t, node.Bc.VerifyBlock(genesisBlock)) + // add the genesis block into the blockchain err = node.Bc.AddBlock(genesisBlock) assert.Nil(t, err) assert.NotEqual(t, genesisBlock.Hash, core.Hash{}) assert.Equal(t, genesisBlock.Hash, node.Bc.LastBlock.Hash) - // TODO add another block - block, err := node.NewBlock([]core.Tx{}) + // add another tx sending coins to the pubK0 + privK0, err := core.NewKey() + assert.Nil(t, err) + pubK0 := privK0.PublicKey + + var ins []core.Input + in := core.Input{ + TxId: genesisBlock.Txs[0].TxId, + Vout: 0, + Value: 100, + } + ins = append(ins, in) + var outs []core.Output + out0 := core.Output{ + Value: 10, + } + out1 := core.Output{ + Value: 90, + } + outs = append(outs, out0) + outs = append(outs, out1) + tx := core.NewTx(&privK.PublicKey, &pubK0, ins, outs) + + // verify tx + txVerified := core.CheckTx(tx) + assert.True(t, txVerified) + + // then create a new block with the tx and add it to the blockchain + var txs []core.Tx + txs = append(txs, *tx) + block, err := node.NewBlock(txs) + assert.Nil(t, err) + err = node.Bc.AddBlock(block) + assert.Nil(t, err) + + // add another tx sending coins to the pubK1 + privK1, err := core.NewKey() + assert.Nil(t, err) + pubK1 := privK1.PublicKey + + ins = []core.Input{} + in = core.Input{ + TxId: block.Txs[0].TxId, + Vout: 0, + Value: 10, + } + ins = append(ins, in) + outs = []core.Output{} + out0 = core.Output{ + Value: 10, + } + outs = append(outs, out0) + tx = core.NewTx(&pubK0, &pubK1, ins, outs) + + // verify tx + txVerified = core.CheckTx(tx) + assert.True(t, txVerified) + + // then create a new block with the tx and add it to the blockchain + txs = []core.Tx{} + txs = append(txs, *tx) + block, err = node.NewBlock(txs) assert.Nil(t, err) - block.Print() err = node.Bc.AddBlock(block) assert.Nil(t, err) }