-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathblockchain.go
102 lines (88 loc) · 2.09 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
package blockchain
import (
"math"
"time"
)
// Blockchain is accessed through
// public methods
type Blockchain struct {
chain []Block
pendingTxs []Transaction
targetBits int
}
// NewBlockchain creates a blockchain
// with 25 coins given to satoshi
func NewBlockchain() *Blockchain {
txs := []Transaction{
{From: "0000", To: "Satoshi", Amount: 25},
}
genesis := Block{
Header: {
Timestamp: time.Now(),
MerkleRoot: MerkleRoot(txs),
Nonce: 0000,
HashPrevBlock: "0000",
TargetBits: 24,
},
Transactions: txs,
}
return &Blockchain{
chain: []Block{{genesis}},
}
}
// GetBlockchain returns a copy of the blockchain
func (bc Blockchain) Blockchain() []Block {
return m.chain
}
func (bc Blockchain) PendingTxs() []Transaction {
return m.pendingTxs
}
// NewTransaction appends a transaction to
// the pending transactions
func (bc *Blockchain) NewTransaction(tx Transaction) {
bc.pendingTxs = append(bc.pendingTxs, tx)
}
// AppendBlock adds the block to the chain
// if it's valid
func (bc *Blockchain) AppendBlock(b Block) {
if
hdrPrevBlock := bc.chain[len(bc.chain)-1].Header
b.HashPrevBlock = hash(hdrPrevBlock)
m.chain = append(m.chain, b)
}
// Halve payout every 5 blocks
func (bc Blockchain) payout() int {
return 50 / math.Ceil(len(bc.Chain)/5)
}
// Get balance calculates the balance from an address
func (bc Blockchain) GetBalance(address string) int {
balance := 0
for _, b := range m.Blockchain.Chain {
for _, t := range b.Transactions {
if t.From == address {
balance -= t.Amount
}
if t.To == address {
balance += t.Amount
}
}
}
return balance
}
// ShouldMine decides when next block should be mined
func (bc Blockchain) ShouldMine() bool {
return len(bc.pendingTxs) >= 3
}
// ShouldReplace decides if a blockchain is more valid
func (bc Blockchain) ShouldReplace(rbc Blockcain) bool {
return ValidateBlockchain(rbc) && len(rbc.Chain) <= len(bc.Chain)
}
// Validate validates a blockchain
func ValidateBlockchain(bc Blockchain) error {
for _, b := range bc.Chain[1:] {
if !b.Validate() {
return false
}
}
return true
}