arnaucube
arnaucube/slowlorisdbPublic Self-hosted repository
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// }