slowlorisdb/core/blockchain.go
core/blockchain.goRaw
1package core
2
3import (
4 "bytes"
5 "crypto/ecdsa"
6 "errors"
7
8 "github.com/arnaucube/slowlorisdb/db"
9)
10
11type PoA struct {
12 AuthMiners []*ecdsa.PublicKey
13}
14
15type Blockchain struct {
16 Id []byte // Id allows to have multiple blockchains
17 Difficulty uint64
18 Genesis Hash
19 LastBlock *Block
20 blockdb *db.Db
21 txdb *db.Db
22 PoA PoA
23}
24
25func NewBlockchain(database *db.Db, dif uint64) *Blockchain {
26 blockchain := &Blockchain{
27 Id: []byte{},
28 Difficulty: dif,
29 Genesis: HashBytes([]byte("genesis")),
30 LastBlock: &Block{},
31 blockdb: database,
32 PoA: PoA{},
33 }
34 return blockchain
35}
36
37func NewPoABlockchain(database *db.Db, authNodes []*ecdsa.PublicKey) *Blockchain {
38 poa := PoA{
39 AuthMiners: authNodes,
40 }
41 blockchain := &Blockchain{
42 Id: []byte{},
43 Difficulty: uint64(0),
44 Genesis: HashBytes([]byte("genesis")), // tmp
45 LastBlock: &Block{},
46 blockdb: database,
47 PoA: poa,
48 }
49 return blockchain
50}
51
52func (bc *Blockchain) GetHeight() uint64 {
53 return bc.LastBlock.Height
54}
55
56func (bc *Blockchain) GetLastBlock() *Block {
57 return bc.LastBlock
58}
59
60func (bc *Blockchain) AddBlock(block *Block) error {
61 bc.LastBlock = block
62 err := bc.blockdb.Put(block.Hash[:], block.Bytes())
63 return err
64}
65
66func (bc *Blockchain) GetBlock(hash Hash) (*Block, error) {
67 v, err := bc.blockdb.Get(hash[:])
68 if err != nil {
69 return nil, err
70 }
71 block, err := BlockFromBytes(v)
72 if err != nil {
73 return nil, err
74 }
75 return block, nil
76}
77
78func (bc *Blockchain) GetPrevBlock(hash Hash) (*Block, error) {
79 currentBlock, err := bc.GetBlock(hash)
80 if err != nil {
81 return nil, err
82 }
83 if currentBlock.PrevHash.IsZero() {
84 return nil, errors.New("This was the oldest block")
85 }
86 prevBlock, err := bc.GetBlock(currentBlock.PrevHash)
87 if err != nil {
88 return nil, err
89 }
90
91 return prevBlock, nil
92}
93
94func (bc *Blockchain) VerifyBlockSignature(block *Block) bool {
95 // check if the signer is one of the blockchain.AuthMiners
96 signerIsMiner := false
97 for _, pubK := range bc.PoA.AuthMiners {
98 if bytes.Equal(PackPubK(pubK), block.Miner[:]) {
99 signerIsMiner = true
100 }
101 }
102 if !signerIsMiner && len(bc.PoA.AuthMiners) > 0 {
103 return false
104 }
105
106 // get the signature
107 sig, err := SignatureFromBytes(block.Signature)
108 if err != nil {
109 return false
110 }
111
112 // check if the signature is by the miner
113 return VerifySignature(block.MinerPubK, block.Hash[:], *sig)
114}
115
116// func (bc *Blockchain) Mint(toAddr Address, amount uint64) error {
117// fromAddr := Address(HashBytes([]byte("mint")))
118// out :=
119// tx := NewTx(fromAddr, toAddr, []Input, )
120// }