Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

bl1 #46

Open
wants to merge 125 commits into
base: part_1
Choose a base branch
from
Open

bl1 #46

Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
125 commits
Select commit Hold shift + click to select a range
0f23d64
Implement Proof-of-Work
Jeiwan Aug 21, 2017
94f3654
Output mining progress
Jeiwan Aug 21, 2017
35449eb
Clean up and refactor proofofwork.go
Jeiwan Aug 21, 2017
f94bbb4
Improve ConfirmProof and print it out in main()
Jeiwan Aug 22, 2017
d379fde
Simplify 'target'
Jeiwan Aug 22, 2017
2a9385d
Rename ConfirmProof function to Validate
Jeiwan Aug 24, 2017
fec88e3
Remove a comment
Jeiwan Aug 24, 2017
56cb2de
Add README
Jeiwan Aug 27, 2017
8502225
Implement serialization and deserialization of a block
Jeiwan Aug 28, 2017
fdccadf
Implement DB persistence
Jeiwan Aug 28, 2017
e6cf54a
Refactor NewBlockchain
Jeiwan Aug 28, 2017
a93e1e9
Store a DB connection in Blockchain
Jeiwan Aug 28, 2017
d99bbc1
Add .gitignore
Jeiwan Aug 28, 2017
5247717
Implement basic CLI
Jeiwan Aug 28, 2017
b0791af
Improve command line arguments processing
Jeiwan Aug 28, 2017
5b46248
Rework the CLI using 'flag'
Jeiwan Aug 29, 2017
54b6c07
Add an information print when there's no blockchain
Jeiwan Aug 29, 2017
d3b2c5c
Update README
Jeiwan Aug 29, 2017
2ba0f1b
Implement transactions
Jeiwan Sep 3, 2017
08a211b
Integrate transactions into the blockchain
Jeiwan Sep 3, 2017
206f87e
Improve block transactions hashing
Jeiwan Sep 3, 2017
46a1654
Fix blocks adding to the blockchain
Jeiwan Sep 3, 2017
8e66369
Fix printChain
Jeiwan Sep 3, 2017
6941c5f
Replace 'addblock' command with 'spend'
Jeiwan Sep 3, 2017
95d3f69
Implement Blockchain.FindUTXOs
Jeiwan Sep 3, 2017
f83ccd7
Rework Blockchain.FindUTXOs
Jeiwan Sep 3, 2017
87eb17b
Implement 'getbalance' command
Jeiwan Sep 3, 2017
751d791
Implement 'createblockchain' command
Jeiwan Sep 3, 2017
6388b20
Fix unspent transactions finding
Jeiwan Sep 3, 2017
78dbfc6
Minor improvements
Jeiwan Sep 4, 2017
326ecb8
Rename TXInput.LockedBy and TXOutput.Unlock methods
Jeiwan Sep 4, 2017
32dd771
Rename Transaction.GetHash to SetID; add Transaction.ID field
Jeiwan Sep 4, 2017
7904009
Set PoW target to 24
Jeiwan Sep 4, 2017
c748768
genesisCoinbase → genesisCoinbaseData
Jeiwan Sep 5, 2017
f4ae516
Minor improvements
Jeiwan Sep 5, 2017
e89846d
Rework UTXO related functions
Jeiwan Sep 5, 2017
d107d92
Final fixes
Jeiwan Sep 5, 2017
373a09b
Add a link to the README
Jeiwan Sep 5, 2017
70c04fa
Implement address generation and wallets
Jeiwan Sep 7, 2017
24b1938
Rename address.go to wallet.go
Jeiwan Sep 7, 2017
8d7f945
Save wallet to a file
Jeiwan Sep 7, 2017
5a1e6f7
Don't create a wallet when wallet.dat already exists
Jeiwan Sep 7, 2017
caf7174
Use crypto/ecdsa to generate ECDSA key pair
Jeiwan Sep 7, 2017
4805ce1
Implement Base58Decode
Jeiwan Sep 7, 2017
5b0e4ec
Allow to create multiple wallets
Jeiwan Sep 8, 2017
deb7e2c
Implement 'listaddresses' CLI command
Jeiwan Sep 8, 2017
7510598
Update usage
Jeiwan Sep 8, 2017
2b0619e
Improve NewWallets and fix comments
Jeiwan Sep 8, 2017
6b40010
In the 'printchain' command, print transactions as well
Jeiwan Sep 8, 2017
e6eed11
Fix Transaction.SetID
Jeiwan Sep 8, 2017
484d0bb
Extract public key hashing into a separate function
Jeiwan Sep 8, 2017
cb17762
Store public key as a byte array
Jeiwan Sep 8, 2017
92be537
Use public key in transactions
Jeiwan Sep 8, 2017
7e8c888
Implement Transaction.Sign and Transaction.Verify
Jeiwan Sep 8, 2017
2ce04f8
Implement transactions signing and verification
Jeiwan Sep 10, 2017
fc0c819
Extract some structs into separate files
Jeiwan Sep 10, 2017
843858d
Fix TXInput.UnlocksOutputWith
Jeiwan Sep 10, 2017
80e320a
Clean up base58.go
Jeiwan Sep 10, 2017
9421206
Clean up block.go; rework transaction hashing
Jeiwan Sep 10, 2017
bb70b49
Clean up blockchain.go; improve TXInput and TXOutput
Jeiwan Sep 10, 2017
5f9e6c0
Extract CLI commands into separate files
Jeiwan Sep 10, 2017
7290aaa
Use Hash funcion to set transaction ID
Jeiwan Sep 10, 2017
a436da6
Implement ValidateAddress
Jeiwan Sep 10, 2017
bf8c5d2
Store input sig and key in different fields; rename TXInput.ScriptPub…
Jeiwan Sep 10, 2017
7b6d569
Fix some initializations
Jeiwan Sep 10, 2017
c0b4d6d
Improve the printchain command
Jeiwan Sep 10, 2017
465b85d
Fix the 'checksum' function
Jeiwan Sep 12, 2017
b6f7626
Fix Signature resetting
Jeiwan Sep 12, 2017
a6394c7
Fix PubKey resetting
Jeiwan Sep 12, 2017
402b298
Update README
Jeiwan Sep 12, 2017
56ccd7c
Implement rewards
Jeiwan Sep 17, 2017
01b9dd2
Implement Blockchain.FindAllUTXO
Jeiwan Sep 17, 2017
2f54328
Implement TXOutputs
Jeiwan Sep 17, 2017
249b7f4
Implement UTXOSet
Jeiwan Sep 17, 2017
7eda539
Improve UTXOSet
Jeiwan Sep 17, 2017
cb78220
Remove the 'address' argument from NewBlockchain, since it's not used…
Jeiwan Sep 17, 2017
b15e111
Implement DeserializeOutputs
Jeiwan Sep 17, 2017
c3aa678
Implment UTXOSet.FindUTXO
Jeiwan Sep 17, 2017
e3739ac
Use the UTXO set to get balance
Jeiwan Sep 17, 2017
0b7d2ac
Remove Blockchain.FindUTXO
Jeiwan Sep 17, 2017
3e491be
Use the UTXO set to send coins
Jeiwan Sep 17, 2017
fe34c88
Implement UTXOSet.Update
Jeiwan Sep 17, 2017
99d1134
Update the UTXO set after mining a new block
Jeiwan Sep 17, 2017
4f0e04f
Reindex the UTXO set after creating a new blockchain
Jeiwan Sep 17, 2017
47737a2
FindAllUTXO → FindUTXO
Jeiwan Sep 17, 2017
8ef0f2c
Add a newline
Jeiwan Sep 17, 2017
337a637
Rename UTXOSet.GetCount to UTXOSet.CountTransactions
Jeiwan Sep 18, 2017
827f124
Refactor something in UTXOSet
Jeiwan Sep 18, 2017
668d209
Implement Merkle tree
Jeiwan Sep 18, 2017
8cafc0e
Use Merkle root hash in proof-of-work
Jeiwan Sep 18, 2017
74cbac4
Revert "Fix the 'checksum' function"
Jeiwan Sep 19, 2017
ffac3de
Lower the difficulty of PoW
Jeiwan Sep 19, 2017
9b9b571
Fill coinbase transaction data with random bytes
Jeiwan Sep 19, 2017
2e06c0a
Update the README
Jeiwan Sep 19, 2017
60a1386
Implement 'startnode' CLI command
Jeiwan Oct 1, 2017
1c5bc46
Implement 'version' command
Jeiwan Oct 1, 2017
7935589
Send 'vrack' in response to 'version'
Jeiwan Oct 1, 2017
4a9f7be
Implement 'addr' command
Jeiwan Oct 1, 2017
504b6c8
Set node ID via an env. var
Jeiwan Oct 1, 2017
57f3680
Blockchain file name must depend on node ID
Jeiwan Oct 1, 2017
0c91da0
Wallet file name must depend on node ID
Jeiwan Oct 1, 2017
4acc3ae
Update .gitignore
Jeiwan Oct 1, 2017
130cf66
Fix wallet file name
Jeiwan Oct 1, 2017
2734285
Implement block height
Jeiwan Oct 1, 2017
0c59d8c
Show block height in 'printchain' command
Jeiwan Oct 1, 2017
9adb5fc
Implement 'getblocks' command
Jeiwan Oct 1, 2017
470adef
Implement 'block' and 'getdata' commands
Jeiwan Oct 1, 2017
a79d78a
Implement Blockchain.AddBlock
Jeiwan Oct 1, 2017
c753df2
Implement the correct way of synchronizing a blockchain
Jeiwan Oct 1, 2017
3cb93b5
Implement 'tx' command (WIP)
Jeiwan Oct 3, 2017
9de40a9
Fix 'version' message exhanging
Jeiwan Oct 3, 2017
150778f
Add -mine option to the 'send' command
Jeiwan Oct 3, 2017
13f22d2
Update UTXOSet after adding a new block
Jeiwan Oct 3, 2017
5c4340f
Add -miner flag to 'startnode' command
Jeiwan Oct 3, 2017
64d1cc5
When a new block is mined, let everyone know
Jeiwan Oct 6, 2017
a96a5bc
Fix the main scenario
Jeiwan Oct 6, 2017
58f9eb7
Update README
Jeiwan Oct 6, 2017
cb32e7c
Fix ranging in Base58Encode and Base58Decode
Jeiwan Oct 6, 2017
989569c
Don't output every hash onto console, its too slow
denispeplin Oct 18, 2017
28de847
:shirt: Fixes crypto/ecdsa.PublicKey composite literal uses unkeyed f…
bigUNO Oct 19, 2017
0557058
Merge pull request #5 from bigUNO/master
Jeiwan Oct 28, 2017
c5c21fd
Merge pull request #4 from denispeplin/patch-1
Jeiwan Oct 28, 2017
fee9bfd
Fix address version processing in Base58 encoding/decoding
Jeiwan Jan 29, 2018
5dbf357
readme: Fix urls
evaporei Jun 18, 2021
ff40835
Merge pull request #76 from otaviopace/fix-readme-urls
Jeiwan Jun 26, 2021
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
*.db
*.dat
11 changes: 11 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
# Blockchain in Go

A blockchain implementation in Go, as described in these articles:

1. [Basic Prototype](https://jeiwan.net/posts/building-blockchain-in-go-part-1/)
2. [Proof-of-Work](https://jeiwan.net/posts/building-blockchain-in-go-part-2/)
3. [Persistence and CLI](https://jeiwan.net/posts/building-blockchain-in-go-part-3/)
4. [Transactions 1](https://jeiwan.net/posts/building-blockchain-in-go-part-4/)
5. [Addresses](https://jeiwan.net/posts/building-blockchain-in-go-part-5/)
6. [Transactions 2](https://jeiwan.net/posts/building-blockchain-in-go-part-6/)
7. [Network](https://jeiwan.net/posts/building-blockchain-in-go-part-7/)
52 changes: 52 additions & 0 deletions base58.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
package main

import (
"bytes"
"math/big"
)

var b58Alphabet = []byte("123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz")

// Base58Encode encodes a byte array to Base58
func Base58Encode(input []byte) []byte {
var result []byte

x := big.NewInt(0).SetBytes(input)

base := big.NewInt(int64(len(b58Alphabet)))
zero := big.NewInt(0)
mod := &big.Int{}

for x.Cmp(zero) != 0 {
x.DivMod(x, base, mod)
result = append(result, b58Alphabet[mod.Int64()])
}

// https://en.bitcoin.it/wiki/Base58Check_encoding#Version_bytes
if input[0] == 0x00 {
result = append(result, b58Alphabet[0])
}

ReverseBytes(result)

return result
}

// Base58Decode decodes Base58-encoded data
func Base58Decode(input []byte) []byte {
result := big.NewInt(0)

for _, b := range input {
charIndex := bytes.IndexByte(b58Alphabet, b)
result.Mul(result, big.NewInt(58))
result.Add(result, big.NewInt(int64(charIndex)))
}

decoded := result.Bytes()

if input[0] == b58Alphabet[0] {
decoded = append([]byte{0x00}, decoded...)
}

return decoded
}
24 changes: 24 additions & 0 deletions base58_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
package main

import (
"encoding/hex"
"log"
"strings"
"testing"

"github.com/stretchr/testify/assert"
)

func TestBase58(t *testing.T) {
rawHash := "00010966776006953D5567439E5E39F86A0D273BEED61967F6"
hash, err := hex.DecodeString(rawHash)
if err != nil {
log.Fatal(err)
}

encoded := Base58Encode(hash)
assert.Equal(t, "16UwLL9Risc3QfPqBUvKofHmBQ7wMtjvM", string(encoded))

decoded := Base58Decode([]byte("16UwLL9Risc3QfPqBUvKofHmBQ7wMtjvM"))
assert.Equal(t, strings.ToLower("00010966776006953D5567439E5E39F86A0D273BEED61967F6"), hex.EncodeToString(decoded))
}
70 changes: 53 additions & 17 deletions block.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,36 +2,72 @@ package main

import (
"bytes"
"crypto/sha256"
"strconv"
"encoding/gob"
"log"
"time"
)

// Block keeps block headers
// Block represents a block in the blockchain
type Block struct {
Timestamp int64
Data []byte
Transactions []*Transaction
PrevBlockHash []byte
Hash []byte
Nonce int
Height int
}

// SetHash calculates and sets block hash
func (b *Block) SetHash() {
timestamp := []byte(strconv.FormatInt(b.Timestamp, 10))
headers := bytes.Join([][]byte{b.PrevBlockHash, b.Data, timestamp}, []byte{})
hash := sha256.Sum256(headers)
// NewBlock creates and returns Block
func NewBlock(transactions []*Transaction, prevBlockHash []byte, height int) *Block {
block := &Block{time.Now().Unix(), transactions, prevBlockHash, []byte{}, 0, height}
pow := NewProofOfWork(block)
nonce, hash := pow.Run()

b.Hash = hash[:]
}
block.Hash = hash[:]
block.Nonce = nonce

// NewBlock creates and returns Block
func NewBlock(data string, prevBlockHash []byte) *Block {
block := &Block{time.Now().Unix(), []byte(data), prevBlockHash, []byte{}}
block.SetHash()
return block
}

// NewGenesisBlock creates and returns genesis Block
func NewGenesisBlock() *Block {
return NewBlock("Genesis Block", []byte{})
func NewGenesisBlock(coinbase *Transaction) *Block {
return NewBlock([]*Transaction{coinbase}, []byte{}, 0)
}

// HashTransactions returns a hash of the transactions in the block
func (b *Block) HashTransactions() []byte {
var transactions [][]byte

for _, tx := range b.Transactions {
transactions = append(transactions, tx.Serialize())
}
mTree := NewMerkleTree(transactions)

return mTree.RootNode.Data
}

// Serialize serializes the block
func (b *Block) Serialize() []byte {
var result bytes.Buffer
encoder := gob.NewEncoder(&result)

err := encoder.Encode(b)
if err != nil {
log.Panic(err)
}

return result.Bytes()
}

// DeserializeBlock deserializes a block
func DeserializeBlock(d []byte) *Block {
var block Block

decoder := gob.NewDecoder(bytes.NewReader(d))
err := decoder.Decode(&block)
if err != nil {
log.Panic(err)
}

return &block
}
Loading