Clean up blockchain.go; improve TXInput and TXOutput

This commit is contained in:
Ivan Kuznetsov 2017-09-10 12:45:15 +07:00
parent 942120679b
commit bb70b4924b
3 changed files with 26 additions and 31 deletions

View File

@ -30,15 +30,16 @@ func CreateBlockchain(address string) *Blockchain {
} }
var tip []byte var tip []byte
cbtx := NewCoinbaseTX(address, genesisCoinbaseData)
genesis := NewGenesisBlock(cbtx)
db, err := bolt.Open(dbFile, 0600, nil) db, err := bolt.Open(dbFile, 0600, nil)
if err != nil { if err != nil {
log.Panic(err) log.Panic(err)
} }
err = db.Update(func(tx *bolt.Tx) error { err = db.Update(func(tx *bolt.Tx) error {
cbtx := NewCoinbaseTX(address, genesisCoinbaseData)
genesis := NewGenesisBlock(cbtx)
b, err := tx.CreateBucket([]byte(blocksBucket)) b, err := tx.CreateBucket([]byte(blocksBucket))
if err != nil { if err != nil {
log.Panic(err) log.Panic(err)
@ -57,7 +58,6 @@ func CreateBlockchain(address string) *Blockchain {
return nil return nil
}) })
if err != nil { if err != nil {
log.Panic(err) log.Panic(err)
} }
@ -86,7 +86,6 @@ func NewBlockchain(address string) *Blockchain {
return nil return nil
}) })
if err != nil { if err != nil {
log.Panic(err) log.Panic(err)
} }
@ -107,7 +106,7 @@ Work:
txID := hex.EncodeToString(tx.ID) txID := hex.EncodeToString(tx.ID)
for outIdx, out := range tx.Vout { for outIdx, out := range tx.Vout {
if out.Unlock(pubKeyHash) && accumulated < amount { if out.IsLockedWithKey(pubKeyHash) && accumulated < amount {
accumulated += out.Value accumulated += out.Value
unspentOutputs[txID] = append(unspentOutputs[txID], outIdx) unspentOutputs[txID] = append(unspentOutputs[txID], outIdx)
@ -158,21 +157,21 @@ func (bc *Blockchain) FindUnspentTransactions(pubKeyHash []byte) []Transaction {
for outIdx, out := range tx.Vout { for outIdx, out := range tx.Vout {
// Was the output spent? // Was the output spent?
if spentTXOs[txID] != nil { if spentTXOs[txID] != nil {
for _, spentOut := range spentTXOs[txID] { for _, spentOutIdx := range spentTXOs[txID] {
if spentOut == outIdx { if spentOutIdx == outIdx {
continue Outputs continue Outputs
} }
} }
} }
if out.Unlock(pubKeyHash) { if out.IsLockedWithKey(pubKeyHash) {
unspentTXs = append(unspentTXs, *tx) unspentTXs = append(unspentTXs, *tx)
} }
} }
if tx.IsCoinbase() == false { if tx.IsCoinbase() == false {
for _, in := range tx.Vin { for _, in := range tx.Vin {
if in.UnlocksOutputWith(pubKeyHash) { if in.UsesKey(pubKeyHash) {
inTxID := hex.EncodeToString(in.Txid) inTxID := hex.EncodeToString(in.Txid)
spentTXOs[inTxID] = append(spentTXOs[inTxID], in.Vout) spentTXOs[inTxID] = append(spentTXOs[inTxID], in.Vout)
} }
@ -195,7 +194,7 @@ func (bc *Blockchain) FindUTXO(pubKeyHash []byte) []TXOutput {
for _, tx := range unspentTransactions { for _, tx := range unspentTransactions {
for _, out := range tx.Vout { for _, out := range tx.Vout {
if out.Unlock(pubKeyHash) { if out.IsLockedWithKey(pubKeyHash) {
UTXOs = append(UTXOs, out) UTXOs = append(UTXOs, out)
} }
} }
@ -204,6 +203,13 @@ func (bc *Blockchain) FindUTXO(pubKeyHash []byte) []TXOutput {
return UTXOs return UTXOs
} }
// Iterator returns a BlockchainIterat
func (bc *Blockchain) Iterator() *BlockchainIterator {
bci := &BlockchainIterator{bc.tip, bc.db}
return bci
}
// MineBlock mines a new block with the provided transactions // MineBlock mines a new block with the provided transactions
func (bc *Blockchain) MineBlock(transactions []*Transaction) { func (bc *Blockchain) MineBlock(transactions []*Transaction) {
var lastHash []byte var lastHash []byte
@ -220,7 +226,6 @@ func (bc *Blockchain) MineBlock(transactions []*Transaction) {
return nil return nil
}) })
if err != nil { if err != nil {
log.Panic(err) log.Panic(err)
} }
@ -243,9 +248,12 @@ func (bc *Blockchain) MineBlock(transactions []*Transaction) {
return nil return nil
}) })
if err != nil {
log.Panic(err)
}
} }
// SignTransaction signs a Transaction // SignTransaction signs inputs of a Transaction
func (bc *Blockchain) SignTransaction(tx *Transaction, privKey ecdsa.PrivateKey) { func (bc *Blockchain) SignTransaction(tx *Transaction, privKey ecdsa.PrivateKey) {
prevTXs := make(map[string]Transaction) prevTXs := make(map[string]Transaction)
@ -260,7 +268,7 @@ func (bc *Blockchain) SignTransaction(tx *Transaction, privKey ecdsa.PrivateKey)
tx.Sign(privKey, prevTXs) tx.Sign(privKey, prevTXs)
} }
// VerifyTransaction verifies transaction // VerifyTransaction verifies transaction input signatures
func (bc *Blockchain) VerifyTransaction(tx *Transaction) bool { func (bc *Blockchain) VerifyTransaction(tx *Transaction) bool {
prevTXs := make(map[string]Transaction) prevTXs := make(map[string]Transaction)
@ -272,22 +280,9 @@ func (bc *Blockchain) VerifyTransaction(tx *Transaction) bool {
prevTXs[hex.EncodeToString(prevTX.ID)] = prevTX prevTXs[hex.EncodeToString(prevTX.ID)] = prevTX
} }
for _, tx := range prevTXs {
fmt.Println(tx)
}
// fmt.Println()
// fmt.Println(tx)
return tx.Verify(prevTXs) return tx.Verify(prevTXs)
} }
// Iterator returns a BlockchainIterat
func (bc *Blockchain) Iterator() *BlockchainIterator {
bci := &BlockchainIterator{bc.tip, bc.db}
return bci
}
func dbExists() bool { func dbExists() bool {
if _, err := os.Stat(dbFile); os.IsNotExist(err) { if _, err := os.Stat(dbFile); os.IsNotExist(err) {
return false return false

View File

@ -9,8 +9,8 @@ type TXInput struct {
ScriptSig []byte ScriptSig []byte
} }
// UnlocksOutputWith checks whether the address initiated the transaction // UsesKey checks whether the address initiated the transaction
func (in *TXInput) UnlocksOutputWith(pubKeyHash []byte) bool { func (in *TXInput) UsesKey(pubKeyHash []byte) bool {
sigLen := 64 sigLen := 64
pubKey := in.ScriptSig[sigLen:] pubKey := in.ScriptSig[sigLen:]
lockingHash := HashPubKey(pubKey) lockingHash := HashPubKey(pubKey)

View File

@ -15,8 +15,8 @@ func (out *TXOutput) Lock(address []byte) {
out.ScriptPubKey = pubKeyHash out.ScriptPubKey = pubKeyHash
} }
// Unlock checks if the output can be used by the owner of the pubkey // IsLockedWithKey checks if the output can be used by the owner of the pubkey
func (out *TXOutput) Unlock(pubKeyHash []byte) bool { func (out *TXOutput) IsLockedWithKey(pubKeyHash []byte) bool {
return bytes.Compare(out.ScriptPubKey, pubKeyHash) == 0 return bytes.Compare(out.ScriptPubKey, pubKeyHash) == 0
} }