slowlorisdb/node/node.go
node/node.goRaw
1package node
2
3import (
4 "crypto/ecdsa"
5 "time"
6
7 "github.com/arnaucube/slowlorisdb/core"
8)
9
10// Node
11type Node struct {
12 PrivK *ecdsa.PrivateKey
13 Addr core.Address
14 Bc *core.Blockchain
15 Miner bool // indicates if the node is running as a miner
16 PendingTxs []core.Tx
17}
18
19// NewNode creates a new node
20func NewNode(privK *ecdsa.PrivateKey, bc *core.Blockchain, isMiner bool) (*Node, error) {
21 addr := core.AddressFromPrivK(privK)
22
23 node := &Node{
24 PrivK: privK,
25 Addr: addr,
26 Bc: bc,
27 Miner: isMiner,
28 PendingTxs: []core.Tx{},
29 }
30 return node, nil
31}
32
33// SignBlock performs a signature of a byte array with the node private key
34func (node *Node) Sign(m []byte) (*core.Signature, error) {
35 return core.Sign(node.PrivK, m)
36}
37
38// SignBlock performs a signature of a block with the node private key
39func (node *Node) SignBlock(block *core.Block) error {
40 block.CalculateHash()
41 sig, err := core.Sign(node.PrivK, block.Hash[:])
42 if err != nil {
43 return err
44 }
45 block.Signature = sig.Bytes()
46 return nil
47}
48
49// AddToPendingTxs adds a transaction the the node.PendingTxs
50func (node *Node) AddToPendingTxs(tx core.Tx) {
51 node.PendingTxs = append(node.PendingTxs, tx)
52}
53
54// BlockFromPendingTxs creates a new block from the pending transactions
55func (node *Node) BlockFromPendingTxs() (*core.Block, error) {
56 block, err := node.NewBlock(node.PendingTxs)
57 if err != nil {
58 return nil, err
59 }
60 block.PrevHash = node.Bc.LastBlock.Hash
61 err = block.CalculatePoW(node.Bc.Difficulty)
62 if err != nil {
63 return nil, err
64 }
65 err = node.SignBlock(block)
66 if err != nil {
67 return nil, err
68 }
69 block.CalculateHash()
70
71 return block, nil
72}
73
74// NewBlock creates a new block with the given txs
75func (node *Node) NewBlock(txs []core.Tx) (*core.Block, error) {
76 block := &core.Block{
77 Height: node.Bc.GetHeight() + 1,
78 PrevHash: node.Bc.LastBlock.Hash,
79 Txs: txs,
80 Miner: core.Address{},
81 MinerPubK: &node.PrivK.PublicKey,
82 Timestamp: time.Now(),
83 Nonce: 0,
84 Hash: core.Hash{},
85 Signature: []byte{},
86 }
87 block.CalculateHash()
88 err := node.SignBlock(block)
89 if err != nil {
90 return nil, err
91 }
92 return block, nil
93}
94
95// CreateGenesis creates the genesis block
96// pubK is the wallet where the first coins will be created
97// amount is the amount of coins that will be created
98func (node *Node) CreateGenesis(pubK *ecdsa.PublicKey, amount uint64) (*core.Block, error) {
99 in := core.Input{
100 TxId: core.GenesisHashTxInput,
101 Vout: 0,
102 Value: amount,
103 }
104 var ins []core.Input
105 ins = append(ins, in)
106
107 out := core.Output{
108 Value: amount,
109 }
110 var outs []core.Output
111 outs = append(outs, out)
112
113 tx := core.Tx{
114 From: &ecdsa.PublicKey{},
115 To: pubK,
116 InputCount: uint64(0),
117 Inputs: []core.Input{},
118 Outputs: outs,
119 Signature: []byte{},
120 }
121
122 // calculate TxId
123 // tx.CalculateTxId()
124 tx.TxId = core.GenesisHashTxInput
125 // sign transaction
126
127 var txs []core.Tx
128 txs = append(txs, tx)
129
130 block := &core.Block{
131 Height: node.Bc.LastBlock.Height + 1,
132 PrevHash: node.Bc.LastBlock.Hash,
133 Txs: txs,
134 Miner: node.Addr,
135 MinerPubK: &node.PrivK.PublicKey,
136 Timestamp: time.Now(),
137 Nonce: uint64(0),
138 Hash: core.Hash{},
139 Signature: []byte{},
140 }
141
142 block.CalculateHash()
143 err := node.SignBlock(block)
144 if err != nil {
145 return nil, err
146 }
147 return block, nil
148}
149
150// ParseReceivedBlock is just a caller of node.Bc.AddBlock() at the Node level
151func (node *Node) ParseReceivedBlock(block *core.Block) error {
152 err := node.Bc.AddBlock(block)
153 return err
154}