Skip to content

Commit d5fa0d2

Browse files
committed
Merge pull request #1 from dqx0/dev
digital sig
2 parents d7b4adf + 00c8af4 commit d5fa0d2

File tree

4 files changed

+80
-28
lines changed

4 files changed

+80
-28
lines changed

blockchain/blockchain.go

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -192,7 +192,7 @@ func (chain *BlockChain) Next() *Block {
192192
return block
193193
}
194194

195-
func (chain *BlockChain) FindUnspentTransactions(address string) []Transaction {
195+
func (chain *BlockChain) FindUnspentTransactions(pubKeyHash []byte) []Transaction {
196196
var unspentTxs []Transaction
197197

198198
spentTXOs := make(map[string][]int)
@@ -212,13 +212,13 @@ func (chain *BlockChain) FindUnspentTransactions(address string) []Transaction {
212212
}
213213
}
214214
}
215-
if out.CanBeUnlocked(address) {
215+
if out.IsLockedWithKey(pubKeyHash) {
216216
unspentTxs = append(unspentTxs, *tx)
217217
}
218218
}
219219
if !tx.IsCoinbase() {
220220
for _, in := range tx.Inputs {
221-
if in.CanUnlock(address) {
221+
if in.UsesKey(pubKeyHash) {
222222
inTxID := hex.EncodeToString(in.ID)
223223
spentTXOs[inTxID] = append(spentTXOs[inTxID], in.Out)
224224
}
@@ -232,13 +232,13 @@ func (chain *BlockChain) FindUnspentTransactions(address string) []Transaction {
232232
return unspentTxs
233233
}
234234

235-
func (chain *BlockChain) FindUTXO(address string) []TxOutput {
235+
func (chain *BlockChain) FindUTXO(pubKeyHash []byte) []TxOutput {
236236
var UTXOs []TxOutput
237-
unspentTransactions := chain.FindUnspentTransactions(address)
237+
unspentTransactions := chain.FindUnspentTransactions(pubKeyHash)
238238

239239
for _, tx := range unspentTransactions {
240240
for _, out := range tx.Outputs {
241-
if out.CanBeUnlocked(address) {
241+
if out.IsLockedWithKey(pubKeyHash) {
242242
UTXOs = append(UTXOs, out)
243243
}
244244
}
@@ -256,17 +256,17 @@ func (chain *BlockChain) FindUTXO(address string) []TxOutput {
256256
// returns:
257257
// - int: 見つかった未使用出力の合計金額
258258
// - map[string][]int: トランザクションIDをキーとし、使用可能な出力インデックスの配列を値とするマップ
259-
func (chain *BlockChain) FindSpendableOutputs(address string, amount int) (int, map[string][]int) {
259+
func (chain *BlockChain) FindSpendableOutputs(pubKeyHash []byte, amount int) (int, map[string][]int) {
260260
unspentOutputs := make(map[string][]int)
261-
unspentTxs := chain.FindUnspentTransactions(address)
261+
unspentTxs := chain.FindUnspentTransactions(pubKeyHash)
262262
accumulated := 0
263263

264264
Work:
265265
for _, tx := range unspentTxs {
266266
txID := hex.EncodeToString(tx.ID)
267267

268268
for outIdx, out := range tx.Outputs {
269-
if out.CanBeUnlocked(address) && accumulated < amount {
269+
if out.IsLockedWithKey(pubKeyHash) && accumulated < amount {
270270
accumulated += out.Value
271271
unspentOutputs[txID] = append(unspentOutputs[txID], outIdx)
272272

blockchain/transaction.go

Lines changed: 37 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,8 @@ import (
77
"encoding/hex"
88
"fmt"
99
"log"
10+
11+
"github.com/dqx0/blockchain/wallet"
1012
)
1113

1214
type Transaction struct {
@@ -15,6 +17,29 @@ type Transaction struct {
1517
Outputs []TxOutput // 出力トランザクションのリスト
1618
}
1719

20+
func (tx *Transaction) Hash() []byte {
21+
var hash [32]byte
22+
23+
txCopy := *tx
24+
txCopy.ID = []byte{}
25+
26+
hash = sha256.Sum256(txCopy.Serialize())
27+
28+
return hash[:]
29+
}
30+
31+
func (tx Transaction) Serialize() []byte {
32+
var encoded bytes.Buffer
33+
34+
enc := gob.NewEncoder(&encoded)
35+
err := enc.Encode(tx)
36+
if err != nil {
37+
log.Panic(err)
38+
}
39+
40+
return encoded.Bytes()
41+
}
42+
1843
// トランザクションのハッシュIDを生成
1944
// トランザクションの内容をgobでエンコードし、SHA-256ハッシュを計算
2045
func (tx *Transaction) SetID() {
@@ -40,10 +65,10 @@ func CoinbaseTx(to, data string) *Transaction {
4065
}
4166

4267
// コインベーストランザクションは過去の参照を持たない特殊なインプット
43-
txin := TxInput{[]byte{}, -1, data}
68+
txin := TxInput{[]byte{}, -1, nil, []byte(data)}
4469
// 報酬として100コインを設定
45-
txout := TxOutput{100, to}
46-
tx := Transaction{nil, []TxInput{txin}, []TxOutput{txout}}
70+
txout := NewTXOutput(100, to)
71+
tx := Transaction{nil, []TxInput{txin}, []TxOutput{*txout}}
4772
tx.SetID()
4873

4974
return &tx
@@ -59,8 +84,13 @@ func CoinbaseTx(to, data string) *Transaction {
5984
func NewTransaction(from, to string, amount int, bc *BlockChain) *Transaction {
6085
var inputs []TxInput
6186
var outputs []TxOutput
87+
88+
wallets, err := wallet.CreateWallets()
89+
Handle(err)
90+
w := wallets.GetWallet(from)
91+
pubKeyHash := wallet.PublicKeyHash(w.PublicKey)
6292
// 利用可能なUTXOを検索
63-
acc, validOutputs := bc.FindSpendableOutputs(from, amount)
93+
acc, validOutputs := bc.FindSpendableOutputs(pubKeyHash, amount)
6494

6595
if acc < amount {
6696
log.Panic("Error: Not enough funds")
@@ -72,16 +102,16 @@ func NewTransaction(from, to string, amount int, bc *BlockChain) *Transaction {
72102
Handle(err)
73103

74104
for _, out := range outs {
75-
input := TxInput{txID, out, from}
105+
input := TxInput{txID, out, nil, w.PublicKey}
76106
inputs = append(inputs, input)
77107
}
78108
}
79109

80110
// 出力トランザクションの作成
81-
outputs = append(outputs, TxOutput{amount, to})
111+
outputs = append(outputs, *NewTXOutput(amount, to))
82112
// おつりがある場合は送金元に返す
83113
if acc > amount {
84-
outputs = append(outputs, TxOutput{acc - amount, from})
114+
outputs = append(outputs, *NewTXOutput(acc-amount, from))
85115
}
86116

87117
tx := Transaction{nil, inputs, outputs}

blockchain/tx.go

Lines changed: 31 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,42 @@
11
package blockchain
22

3+
import (
4+
"bytes"
5+
6+
"github.com/dqx0/blockchain/wallet"
7+
)
8+
39
type TxOutput struct {
4-
Value int // 送金額
5-
PubKey string // 受取人の公開鍵
10+
Value int // 送金額
11+
PubKeyHash []byte // 受取人の公開鍵
612
}
713

814
type TxInput struct {
9-
ID []byte // 参照する過去のトランザクションID
10-
Out int // 参照する出力インデックス
11-
Sig string // 送信者の署名
15+
ID []byte // 参照する過去のトランザクションID
16+
Out int // 参照する出力インデックス
17+
Sig []byte // 送信者の署名
18+
PubKey []byte // 送信者の公開鍵
19+
}
20+
21+
func (in *TxInput) UsesKey(pubKeyHash []byte) bool {
22+
lockingHash := wallet.PublicKeyHash(in.PubKey)
23+
24+
return bytes.Compare(lockingHash, pubKeyHash) == 0
25+
}
26+
27+
func (out *TxOutput) Lock(address []byte) {
28+
pubKeyHash := wallet.Base58Decode(address)
29+
pubKeyHash = pubKeyHash[1 : len(pubKeyHash)-4]
30+
out.PubKeyHash = pubKeyHash
1231
}
1332

14-
// 指定されたデータで入力トランザクションがアンロック可能か検証
15-
func (in *TxInput) CanUnlock(data string) bool {
16-
return in.Sig == data
33+
func (out *TxOutput) IsLockedWithKey(pubKeyHash []byte) bool {
34+
return bytes.Compare(out.PubKeyHash, pubKeyHash) == 0
1735
}
1836

19-
// 指定されたデータで出力トランザクションが使用可能か検証
20-
func (out *TxOutput) CanBeUnlocked(data string) bool {
21-
return out.PubKey == data
37+
func NewTXOutput(value int, address string) *TxOutput {
38+
txo := &TxOutput{value, nil}
39+
txo.Lock([]byte(address))
40+
41+
return txo
2242
}

cmd/cmd.go

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -76,7 +76,9 @@ func (cli *CommandLine) getBalance(address string) {
7676
defer chain.Database.Close()
7777

7878
balance := 0
79-
UTXOs := chain.FindUTXO(address)
79+
pubKeyHash := wallet.Base58Decode([]byte(address))
80+
pubKeyHash = pubKeyHash[1 : len(pubKeyHash)-4]
81+
UTXOs := chain.FindUTXO(pubKeyHash)
8082

8183
for _, out := range UTXOs {
8284
balance += out.Value

0 commit comments

Comments
 (0)