/
blockchain.go
111 lines (94 loc) · 2.88 KB
/
blockchain.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
package account
import (
"blokchain/keypair"
"errors"
"fmt"
)
type Blockchain struct {
CoinDatabase map[string]uint64
BlockHistory []Block
Coins uint64
}
func InitBlockchain(Coins uint64) (Blockchain, Account, error) {
var output Blockchain
output.CoinDatabase = make(map[string]uint64)
var depositoryKeyPair keypair.KeyPair
err := depositoryKeyPair.GenerateKeyPair()
if err != nil {
return output, Account{}, err
}
genesisDepository := NewDepository(depositoryKeyPair, Coins)
depositoryId := fmt.Sprintf("%x", genesisDepository.Identifier)
output.CoinDatabase[depositoryId] = Coins
var genesisKeyPair keypair.KeyPair
err = genesisKeyPair.GenerateKeyPair()
if err != nil {
return output, Account{}, err
}
genesisAccount := output.NewAccount(genesisKeyPair)
genesisId := fmt.Sprintf("%x", genesisAccount.Identifier)
output.CoinDatabase[genesisId] = 0
//send 0.01% of all coins to the first account
operation, err := genesisDepository.SendInterests(genesisAccount.Identifier, Coins/10000)
if err != nil {
return output, Account{}, err
}
setOfOperations := make([]Operation, 1)
setOfOperations[0] = operation
tx, err := output.CreateTransaction(setOfOperations)
if err != nil {
return output, Account{}, err
}
setOfTransactions := make([]Transaction, 1)
setOfTransactions[0] = tx
block, err := CreateBlock(nil, setOfTransactions)
if err != nil {
return output, Account{}, err
}
err = output.AddBlock(block)
if err != nil {
return output, Account{}, err
}
output.Coins = Coins
return output, genesisAccount, nil
}
func (bch *Blockchain) AddBlock(b Block) error {
if bch.validateBlock(b) == false {
return errors.New("invalid block")
}
for _, tx := range b.Transactions {
for _, op := range tx.SetOfOperations {
sender := fmt.Sprintf("%x", op.Sender)
receiver := fmt.Sprintf("%x", op.Receiver)
bch.CoinDatabase[sender] -= op.Amount
bch.CoinDatabase[receiver] += op.Amount
}
}
bch.BlockHistory = append(bch.BlockHistory, b)
return nil
}
func (bch Blockchain) validateBlock(b Block) bool {
if len(bch.BlockHistory) != 0 {
if b.PrevHash != bch.BlockHistory[len(bch.BlockHistory)-1].BlockId {
return false
}
}
for _, tx := range b.Transactions {
for _, op := range tx.SetOfOperations {
if bch.Verify(op) == false {
return false
}
}
}
return true
}
func (bch Blockchain) String() string {
var output string
for id, balance := range bch.CoinDatabase {
output += id + ": " + fmt.Sprintf("%d", balance) + "\n"
}
for _, b := range bch.BlockHistory {
output += b.String()
}
return output
}