Documentation
¶
Index ¶
- func Base58Decode(input []byte) []byte
- func Base58Encode(input []byte) []byte
- func DBExists() bool
- func HashPubKey(pubKey []byte) []byte
- func IntToHex(n int64) []byte
- func ReverseBytes(data []byte)
- func ValidateAddress(address string) bool
- type Block
- type Blockchain
- func (bc *Blockchain) FindTransaction(ID []byte) (Transaction, error)
- func (bc *Blockchain) FindUTXO() map[string]TXOutputs
- func (bc *Blockchain) Iterator() *BlockchainIterator
- func (bc *Blockchain) MineBlock(transactions []*Transaction) *Block
- func (bc *Blockchain) SignTransaction(tx *Transaction, privKey ecdsa.PrivateKey)
- func (bc *Blockchain) VerifyTransaction(tx *Transaction) bool
- type BlockchainIterator
- type MerkleNode
- type MerkleTree
- type ProofOfWork
- type TXInput
- type TXOutput
- type TXOutputs
- type Transaction
- func (tx *Transaction) Hash() []byte
- func (tx Transaction) IsCoinbase() bool
- func (tx Transaction) Serialize() []byte
- func (tx *Transaction) Sign(privateKey ecdsa.PrivateKey, prevTXs map[string]Transaction)
- func (tx *Transaction) TrimmedCopy() Transaction
- func (tx *Transaction) Verify(prevTXs map[string]Transaction) bool
- type UTXOSet
- type Wallet
- type Wallets
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
func Base58Encode ¶
Base58Encode encodes a byte array to Base58
func DBExists ¶
func DBExists() bool
DBExists checks whether bolt has a db created. If yes that means there is a blockchain already created
func HashPubKey ¶
HashPubKey takes in a public key slice. It first hashes with SHA256, and then hashes it again with RIPEMD160
func IntToHex ¶
IntToHex takes in an int64 and returns a byte slice of that int64 formatted to base16
func ValidateAddress ¶
Types ¶
type Block ¶
type Block struct { Timestamp int64 Transactions []*Transaction PrevBlockHash []byte Hash []byte Nonce int }
Block represents a single block withing a blockchain. A block contains headers, and the body (transactions). A block always references the previous block in a chain.
func DeserializeBlock ¶
Deserialize decodes a serialized block
func NewBlock ¶
func NewBlock(transactions []*Transaction, prevBlockHash []byte) *Block
NewBlock takes in a list of transactions, and the previous blocks hash, and creates a new block.
func NewGenesisBlock ¶
func NewGenesisBlock(coinbase *Transaction) *Block
NewGenesisBlock creates a new genesis block. The genesis block is the initial block created when a blockchain is created.
func (*Block) HashTransactions ¶
HashTransactions joins together a slice of transaction ID's, and hashes them together. Used when preparing a blocks data. Notice the merkle tree. Instead of saving all transactions and hashing them together, we use a merkle tree instead.
type Blockchain ¶
type Blockchain struct { Tip []byte // Tip is the hash of the latest block added to the blockchain DB *bolt.DB // DB is a reference to a boltDB connection }
Blockchain represents an entire blockchain. It stores the tip/tail/(hash of the last block) in a blockchain.
func CreateBlockchain ¶
func CreateBlockchain(address string) *Blockchain
CreateBlockchain creates a blockchain. It first creates a genesis block, and signs the output with the address of the creator.
func NewBlockChain ¶
func NewBlockChain(address string) *Blockchain
NewBlockChain doesn't create a blockchain, instead it identifies the tail of a previous blockchain, and that becomes the starting point of the new blockchain.
func (*Blockchain) FindTransaction ¶
func (bc *Blockchain) FindTransaction(ID []byte) (Transaction, error)
FindTransaction finds a specific transaction across the entire blockchain by its ID.
func (*Blockchain) FindUTXO ¶
func (bc *Blockchain) FindUTXO() map[string]TXOutputs
FindUnspentTransactions loops over every block in a blockchain. For every transaction, it checks for unspent transactions. For every Output in a transaction, check if that output was already "spent"/referenced by an input. The first/tail block will always be nil since no outputs have been referenced. Then add the transaction to the UTXOs map if unreferenced. The next time the loops runs, when it looks for free outputs, if they are on that map they are definitely not free.
func (*Blockchain) Iterator ¶
func (bc *Blockchain) Iterator() *BlockchainIterator
Iterator returns an iterator for a Blockchain
func (*Blockchain) MineBlock ¶
func (bc *Blockchain) MineBlock(transactions []*Transaction) *Block
MineBlock takes in a list of transactions, finds the last hash of a blockchain, and creates a new block with the transactions and last hash. Then it updates the db and inserts the block, and updates the tail to be the hash of this new block.
func (*Blockchain) SignTransaction ¶
func (bc *Blockchain) SignTransaction(tx *Transaction, privKey ecdsa.PrivateKey)
SignTransaction signs a transaction using the Sign method. It takes in the transaction to be signed and the private key to sign with.
func (*Blockchain) VerifyTransaction ¶
func (bc *Blockchain) VerifyTransaction(tx *Transaction) bool
Verify transaction verifies a transaction by using the Verify method. It uses the signature and public key stored in the input to verify the entire transaction.
type BlockchainIterator ¶
type BlockchainIterator struct { DB *bolt.DB // DB is a reference to a boltDB connection // contains filtered or unexported fields }
BlockchainIterator stores the current hash of the block you are about to iterate over
func (*BlockchainIterator) Next ¶
func (i *BlockchainIterator) Next() *Block
Next is a method of BlockchainIterator that grabs the next block based on a hash. I.e, block A has a hash "abcd" and a lastHash of "wxyz". Iterator has currentHash as "abcd", it first finds the block with hash "abcd", which is block A, and then sets currentHash to the lastHash of block A, which is "wxyz". The next time iterator is callled, it searches for "wxyz", and stores that blocks lastHash in currentHash.
type MerkleNode ¶
type MerkleNode struct { Left *MerkleNode Right *MerkleNode Data []byte }
MerkleNode is an instance of a MerkleNode. It can contain two other MerkleNode(s), each one corresponding to the left and right of this MerkleNode. It also contains some data, which is a sha256 hash.
func NewMerkleNode ¶
func NewMerkleNode(left, right *MerkleNode, data []byte) *MerkleNode
NewMerkleNode takes in a left and right node, and some data. The data is used when creating the initial leaf nodes, and it's a serialized transaction. If it's a lead node, i.e: left and right are nil, then hash the data and store is as nMode.Data. If it's not a leaf node, concatenate the left and right, which are just the two nodes below this new node that actually form this node, and then hash them and then that's your new node's data.
type MerkleTree ¶
type MerkleTree struct {
RootNode *MerkleNode // RootNode is the top most node of a MerkleTree.
}
MerkleTree is an instance of a MerkleTree.
func NewMerkleTree ¶
func NewMerkleTree(data [][]byte) *MerkleTree
NewMerkleTree creates a new merkle tree. The data passed is a slice of serialized transactions. Before anything, if the amount of tx is odd, duplicate the last one. The merkle tree afterwards creates a leaf node for every transaction, and those leaf nodes contain a hash of the transaction as their data. Next, we run a loop for half the amount of transactions.
type ProofOfWork ¶
type ProofOfWork struct {
// contains filtered or unexported fields
}
ProofOfWork represent a single ProofOfWork instance.
func NewProofOfWork ¶
func NewProofOfWork(b *Block) *ProofOfWork
NewProofOfWork takes in a block and returns a ProofOfWork. the PoW target is set to the largest number allowed. For example, if we only want to allow hashes smaller than 1000, only if the hash is 999 or less will it pass. The target is 256 - targetBits. 256 since the hashing algorithm returns maximum 256 bits. Which is 32 bytes. If targetBits is 24, then the maximum number of bits is 232 which is 29 bytes. Any hash smaller than 29 bytes will be accepted. The smaller targetBits is, the easier it is to mine a new block.
func (*ProofOfWork) PrepareData ¶
func (pow *ProofOfWork) PrepareData(nonce int) []byte
PrepareData takes in nonce, and returns a byte slice. The nonce is an int, that when added to the blocks hash, returns a hash that meets the requirement of the target. The byte slice returned is a slice of a blocks previous hash, transactions, timestamp, targetBits, and nonce.
func (*ProofOfWork) Run ¶
func (pow *ProofOfWork) Run() (int, []byte)
Run is a method of ProofOfWork. Run is the method that actually does what we call "mine". It's an incredibly memory intensive task, since it runs, checks if true, and if not, keeps running until true. The maximum value it can run until, is until the largest number an int64 can be. Every time the hash is greater than the target, the for loop increases nonce by 1. Each time it runs it first gets a byte slice of all the data, by calling PrepareData, then it hashes it using sha256, then checks to see if it satisfies the target.
func (*ProofOfWork) Validate ¶
func (pow *ProofOfWork) Validate() bool
Validate is a method that verifies that the hash of a block is actual less than its target.
type TXInput ¶
type TXInput struct { Txid []byte // the id of the transaction that contains the output this input is referencing Vout int // index of the output it is referencing Signature []byte // signature is propagated when the transaction is signed, and it's a concatenated key pair generated using a private key and a trimmed transaction hash PubKey []byte // the public key of the sender. i.e: the one who owns the output }
TXInput represents a single input. An input must always reference an output. The input contains an id of which transaction it references, and the index of which output within that referenced transaction. It also contains the address/signature of who spent the coins. An input means that coins were spent/send/transferred.
type TXOutput ¶
type TXOutput struct { Value int // amount of "coins" on the outputs PubKeyHash []byte // this hash is the public key hash of the guy who owns the output }
TXOutput represents a single transaction output. TXOutputs store "coins", and are locked by a public key. The key can only be unlocked by the coins owner. Outputs that are referenced are spent and can't be used. Unreferenced outputs are open to being sent/spent/transferred.
func NewTXOutput ¶
NewTXOutput takes in a value and address, and creates a new TX output. It locks the transaction output to the address inputted.
func (*TXOutput) IsLockedWithKey ¶
IsLockedWithKey checks if the output was locked with the public key it's being tested against. pubKey is the hashed public key without version or checksum
func (*TXOutput) Lock ¶
Lock takes in an address, decodes it, removes the version and checksum, and then assigns it to the outputs public key. Only this address can now unlock the output. address here is the base58 encoded version+hash+checksum, part of the functions logic is to decode, and remove the version and checksum
type TXOutputs ¶
type TXOutputs struct {
Outputs []TXOutput // slice of TX Outputs.
}
TXOutputs is an instance of a slice of transaction outputs.
func DeserializeOutputs ¶
DeserializeOutputs takes in a byte slice of serialized outputs, and returns the decoded outputs as TXOutputs.
type Transaction ¶
type Transaction struct { ID []byte // ID of the transaction. It's how its identified. Vin []TXInput // list of inputs // inputs always reference an output Vout []TXOutput // list of outputs // outputs that are referenced are "taken", unreferenced outputs have a value that can be spent }
Transaction represents a single transaction
func NewCoinbaseTX ¶
func NewCoinbaseTX(to, data string) *Transaction
NewCoinbaseTX creates a new transaction for the initial genesis block
func NewUTXOTransaction ¶
func NewUTXOTransaction(from, to string, amount int, UTXOSet *UTXOSet) *Transaction
New UTXOTransaction makes a transaction from address a to address b. It first gets a list of which outputs have address a's coins. If there aren't enough coins to satisfy the amount that address a would like to send, return an error that address a needs more coins. Otherwise, create an input that references the output that has address a's coins. Then create an output that has the amount being transferred, and lock it to address b. If there are too many coins on the output, i.e address a wants to send 5 and the output has 10, create another output locked to address a, and store the remainder of the coins on that new output. Finally, using the newly created input and output(s), return a transaction that can then be stored in a block.
func (*Transaction) Hash ¶
func (tx *Transaction) Hash() []byte
Hash hashes a transaction, to be used for setting a transaction's ID.
func (Transaction) IsCoinbase ¶
func (tx Transaction) IsCoinbase() bool
IsCoinbase checks if it's the outputs from the genesis block
func (Transaction) Serialize ¶
func (tx Transaction) Serialize() []byte
Serialize serializes an entire transaction. Used when inserting a transaction into a boltDB bucket, or when hashing.
func (*Transaction) Sign ¶
func (tx *Transaction) Sign(privateKey ecdsa.PrivateKey, prevTXs map[string]Transaction)
Sign takes in a private key and a list of previous transactions, and signs the transaction it was called with. The private key is used to do the signing, while the prevTXs is map holding transactions that contain outputs. Those outputs are the outputs that the transaction you are calling this method from has referenced.
func (*Transaction) TrimmedCopy ¶
func (tx *Transaction) TrimmedCopy() Transaction
TrimmedCopy removes the Signature and PubKey from a transaction and sets them to nil. We don't need to sign the input keys, only the output keys
func (*Transaction) Verify ¶
func (tx *Transaction) Verify(prevTXs map[string]Transaction) bool
Verify is used to verify a transactions signature is valid. Like Sign, prevTXs is a map of transactions that contain the outputs that THE transaction's inputs referenced.
type UTXOSet ¶
type UTXOSet struct {
Blockchain *Blockchain
}
UTXOSet is a struct that contains only a reference to a blockchain instance.
func (UTXOSet) FindSpendableOutputs ¶
FindSpendableOutputs runs through the utxo bucket, and checks if there are any UTXO's that are owned by the address requesting them.
func (UTXOSet) FindUTXO ¶
FindUTXO is a method of UTXOSet, not to be confused with the Blockchain method of the same name. This FindUTXO is used to get the balance of an address. FindSpendableOutputs finds the first x amount of outputs that contain enough coins to satisfy the transfer. This function checks through every output.
func (UTXOSet) Reindex ¶
func (u UTXOSet) Reindex()
Reindex is used to reindex the chainstate. This is a pretty intensive task, so use wisely.
func (UTXOSet) Update ¶
Update is used to update the utxoBucket when there are newly referenced or created outputs. Pretty much every time a transaction is made, and also when a new block is added to the chain. Find the outputs on a TX that an input references, and then if they don't match the index in the input, that output is free.
type Wallet ¶
type Wallet struct { PrivateKey ecdsa.PrivateKey // this private key is a struct containing both a private and public key. A private key is never stored in a database, it should remain... private. PublicKey []byte // this public key is not hashed. It's generated when you create a private key, and really consists of two parts that are concatenated }
Wallet represents a single wallet instance. A wallet contains a private key and a public key
func NewWallet ¶
func NewWallet() *Wallet
NewWallet returns a wallet struct, with a private and public key
func (Wallet) GetAddress ¶
GetAddress is responsible for getting an address for a wallet. It first runs the public key though a RIPEMD160 hash of a SHA256 hash of the public key. Then it appends the version to the head of the public key. Next, a checksum 4 bytes long is created, by double hashing the version+publicKey. The full payload is then created by appending the checksum to the end of the version+publicKey. Finally that value is base58 encoded and returned as the address.
type Wallets ¶
Wallets is an instance of multiple Wallet('s). More specifically it is a map of a wallets address to a Wallet struct. i.e : [197QdQzchU4aMF3pTryySADwCsSC6cpj4A:*Wallet]
func NewWallets ¶
NewWallets loads in all the wallets stored in the wallet.dat file
func (*Wallets) CreateWallet ¶
CreateWallet creates a new wallet, gets its address using GetAddress, and then sets the wallet to be included in the the Wallets struct, and finally returns the address
func (Wallets) GetWallet ¶
GetWallet gets a specific wallet within a map of wallets. It takes in the wallet address, and returns the wallet
func (*Wallets) LoadFromFile ¶
LoadFromFile checks if wallet.dat exists, and reads in the contents. The wallets are gob encoded, so it first decodes them.
func (Wallets) SaveToFile ¶
func (ws Wallets) SaveToFile()
SaveToFile saves a map of wallets to wallet.dat file. It firsts encodes them and then saves them to file.