-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathblockchain.go
103 lines (92 loc) · 3.14 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
package main
import (
)
const DIFFICULTY int = 17 // Constraint on the hash (used in mining)
// Blockchain implements interactions with a DB
type Blockchain struct {
GHash []byte // Hash of the Genesis Block
Chain []Block// Slice of blocks
}
// AddBlock adds a new block with the provided transactions, the block
// is mined before addition
func (bc *Blockchain) AddBlock(transactions []*Transaction) {
if len(bc.GHash) == 0 {
// Chain is empty
// Adding a the Genisis block
GBlock := NewGBlock(transactions, DIFFICULTY)
bc.GHash = GBlock.Hash
bc.Chain = append(bc.Chain, *GBlock)
} else {
// Chain is not empty
block := NewBlock(transactions, bc.Chain[len(bc.Chain)-1].Hash, true, DIFFICULTY)
bc.Chain = append(bc.Chain, *block)
}
}
// NewSendTransaction creates a set of transactions to transfert the
// amount from sender to receiver. If the sender has not the required
// amount, an error is returned
func (bc *Blockchain) NewTransfertTX(from, to string, amount int) (*Transaction,error) {
if bc.GetBalance(from) < amount {
return nil, ErrInsufficientFunds
}
txin := TXInput{[]byte{}, -1, from}
txout := TXOutput{amount, to}
transaction := NewTransaction([]byte{}, []TXInput{txin}, []TXOutput{txout})
transaction.Hash = transaction.ComputeHash()
return transaction, nil
}
// CreateBlockchain creates a new blockchain, evey adress in adresses
// is given the initial
func NewBlockchain(addresses []string) *Blockchain {
var txs []*Transaction
for _, address := range addresses {
tx := NewCoinbaseTX(address, "Reward for " + address)
txs = append(txs, tx)
}
GBlock := NewGBlock(txs, DIFFICULTY)
bc := NewBlockchainFromGB(GBlock)
return bc
}
// creates a new blockchain given a valid genesis block
func NewBlockchainFromGB(genesis *Block) *Blockchain {
return &Blockchain{nil, []Block{*genesis}}
}
func (bc *Blockchain) GetBalance(address string) int {
balance := 0
// 1. Calculating the amount credited (and adding it)
for _, block := range bc.Chain {
for _, transaction := range block.Transactions {
for _, txOut := range transaction.TxOuts {
if txOut.ScriptPubKey == address {
balance += txOut.Value
}
}
}
}
// 2. Caluating the amount debited (and substracting it)
// - Get all transacations ids from which it (the current address) has credited money from
outputTransactions := bc.getAllTransactionsByInputScriptSig(address)
// - For each transaction id, loop for all transactions where this transaction id is the input's "scriptSig", and substract the value of the txIutput from the balance
for _, transaction := range outputTransactions {
for _, txOutput := range transaction.TxOuts {
balance -= txOutput.Value
}
}
return balance
}
/**
Return all transactions that have the given scriptSig in their input
*/
func (bc *Blockchain) getAllTransactionsByInputScriptSig(scriptSig string) []*Transaction {
var transactions []*Transaction
for _, block := range bc.Chain {
for _, transaction := range block.Transactions {
for _, txInput := range transaction.TxIns {
if txInput.ScriptSig == scriptSig {
transactions = append(transactions, transaction)
}
}
}
}
return transactions
}