Bitcoin Prep Work: Whitepaper

What I Read

I read the Bitcoin whitepaper. It has been a long time since I’ve read the Bitcoin whitepaper, and this time I actually understood it! I should have re-read it a while ago.

Notes

Definition of A Bitcoin

A bitcoin is defined as a chain of digital signatures. Specifically, you sign the previous hash and the public key of the next owner. When the next owner receives this coin, he can verify the signatures in order to know that the chain of ownership is valid.

Merkle Tree in Bitcoin

You can hash all the transactions, and come up with a root. This root is then used in the service string, which is used to generate the proof of work.

If we change any elements of the transactions, it will invalidate the root. This will further invalidate elements down the chain, specifically the previousBlockHash header that we generate for every block. So, you will have to recalculate the given block hash header, include it in the next block, and then recalculate the next header, since we use the previousBlockHash within every block.

You can see where this will be very time-consuming and not worthwhile to pursue, given the costs of proof of work.

Calculations

I didn’t understand the math behind the calculations, but I found this great article that broke down, in very simple terms, what this section meant.

Essentially, we are calculating the probability of an attacker to to alter the blockchain. The more hashpower he has, the easier it will be.

We can calculate, given an attacker chain and honest chain, how difficult it will be to overtake our chain. To quote the article,

“These numbers tell us the that the more CPU power an attacker has (q) the more confirmations we have to wait (5, 8, …) to know that the probability of the attacker catching up with the chain will be < 0.1%.”

Bitcoin white paper explained (PART 3/3)

This helped make it very clear to me what we were calculating in this section.

Conclusion

It was very beneficial to re-read the Bitcoin whitepaper. I felt like I learned a lot, and that I missed a lot by not reading it earlier.

I am a bit more technical now, so it definitely would have been more beneficial to tackle this sooner rather than later, but at any rate, I enjoyed how simple and straightforward this paper was.

Even the stuff I struggled with, I found simple explanations online about, that I could easily understand.

Building Bitcoin: Testnet Compatibility and Failing

Since the last post, I’ve done close to nothing. My main focus has been trying to make this half-done thing into a testnet ready environment.

My first focus is trying to get these addresses to be testnet compatible. That has NOT gone as well as I anticipated. I’m screwing something up, but I have no idea what.

The problem with this project is that once I get started on it, it’s hard to spend any other time on anything else throughout the day. This is difficult to do, especially with work deadlines.

At any rate – hopefully tomorrow brings us a much more optimistic update.

Building Bitcoin: Change of Focus

The overall intent of my focus when I started was to build a crap-coin, using a Bitcoin-like blockchain in order to do it. But as I kept writing code, I realized I would learn much more by building a testnet wallet and testnet related elements. So, it would probably be better to be focused on that.

I didn’t get the chance to write any code today. Tomorrow hopefully I will be able to get more stuff done.

Building Bitcoin: Wallet import format in Ruby

Today I got nowhere near as much done as I wanted. Still have client work! So I knocked out an easy element – built the WIF encoding part.

This was fairly straightforward, since I restructured the code from yesterday and used a lot of the code to help generate encoding.

This is the basic code.

class BitcoinAddress
  ...

  def wif_conversion
    pk = "80" + @private_key
    sha_hash = sha256_hash(sha256_hash(pk))
    checksum = return_checksum(sha256_hash(sha256_hash(pk)))
    sha_hash = sha_hash + checksum
    return generate_base58_address(sha_hash)
  end

  ...
end

Honestly, I just followed this guide from the Wiki. The wiki is so amazing! Very helpful.

Overall code that I wrote:

class BitcoinAddress
  attr_accessor :private_key
  @private_key

  def initialize()
    @private_key = self.generate_private_key
  end

  def generate_private_key
    key = OpenSSL::PKey::EC.new("secp256k1").generate_key.private_key.to_s(16)
    @private_key = key
  end

  def wif_conversion
    pk = "80" + @private_key
    sha_hash = sha256_hash(sha256_hash(pk))
    checksum = return_checksum(sha256_hash(sha256_hash(pk)))
    sha_hash = sha_hash + checksum
    return generate_base58_address(sha_hash)
  end

  def generate_public_key(private_key)
    public_key = private_key.public_key.to_bn.to_s(16)
    return public_key
  end

  def generate_address
    public_key = generate_public_key(@private_key)
    ripmd_hash = ripmd160_hash((sha256_hash(public_key)))
    rip_generate_address = ripmd160_hash((sha256_hash(public_key)))

    ripmd_hash = "00" + ripmd_hash
    rip_generate_address = "00" + rip_generate_address

    ripmd_hash = return_checksum(sha256_hash(sha256_hash(ripmd_hash)))
    return "1" + generate_base58_address(rip_generate_address + ripmd_hash)
  end

  def sha256_hash(key)
    return Digest::SHA2.new(256).hexdigest([key].pack("H*"))
  end

  def ripmd160_hash(key)
    return Digest::RMD160.new.hexdigest([key].pack("H*"))
  end

  def return_checksum(data)
    return data[0..7]
  end

  def generate_base58_address(key)
    return Base58.encode(key.hex(), :bitcoin)
  end

end

That’s all for today. I think tomorrow I will attempt to actually build some critical part of the code. So far, all I have an eighth of a wallet. If I keep it up, I’ll just have built a Bitcoin wallet.

Building Bitcoin: Generating Bitcoin Addresses

At first I was going to build this in PHP. I write code the most in PHP and I just figured, “Eh, what the heck?”

I spent 2 hrs trying to figure out how to generate private keys in PHP. I wanted to do it, but it was weird and really obfuscated.

Instead, I looked up how to do it in Ruby. It took me 10 seconds, and three lines of code. This isn’t the first time this has happened with me and PHP. I really think Ruby is a much better ecosystem than PHP.

At any rate, lets get into the actual code.

Generating Bitcoin Addresses with Ruby

There were a couple tools I used in order to help me build this code. I’ll refactor it tomorrow probably, this is just a proof of concept to get the ball rolling.

The first tool is reading this wiki entry. It enabled me to understand the technical backside of generating Bitcoin addresses.

Also, I used this online tool that allows you to compare each step in the process to your output, to make sure you have it right. (Just hard code the private key and public key after you generate them).

Anyways, this is my code that I wrote for the first step.

require 'openssl'
require 'base58'
require 'digest'
#how do i create a transaction?
#generate private key
#generate public key
#hask public key
#A bitcoin address is a 160-bit has of the public portion of a public/private key ECDSA keypair

key = OpenSSL::PKey::EC.new("secp256k1").generate_key
#string encoding

#STEP 0: generate private key
#to big number, to string representation
private_key = key.private_key.to_s(16)

#STEP 1: generate public key
public_key = key.public_key.to_bn.to_s(16)

#STEP 2: SHA-256 hash public key
sha_256_hash_first = Digest::SHA2.new(256).hexdigest([public_key].pack("H*"))

#STEP 3: RIPMD 160 hash on hashed public key
sha256_RIPMD = Digest::RMD160.new.hexdigest([sha_256_hash_first].pack("H*"))

#STEP 4: Append Version
ripMD = "00" + sha256_RIPMD
public_key = "00" + sha256_RIPMD

#STEP 5: Append Version
public_key =  Digest::SHA2.new(256).hexdigest([public_key].pack("H*"))

#STEP 6: SHA-256 hash again
public_key = Digest::SHA2.new(256).hexdigest([public_key].pack("H*"))

#STEP 7: Take checksum
checksum = public_key[0..7]

#STEP 8:  Add 5 checksum
public_key = ripMD + checksum

#puts "ripMD + checksum: " + public_key
#STEP 9:
address = Base58.encode(public_key.hex(), :bitcoin)

puts "My Bitcoin Address: " + 1.to_s + address

This will output a valid Bitcoin address.

There are some obvious refactors we need to take:

  1. Break it into functions/class
  2. Take out the hard-coded elements
  3. Build out custom base58check encode to append the 1

Those are things I will hopefully implement by tomorrow, then push a refactored version, then build a way to create and send transactions.

Updated Code

Ok, I couldn’t wait until tomorrow, so I rewrote it into a neat little class that generates a Bitcoin address. Honestly, I’m not 100% sure how this all fits into grand scheme of everything, but I was pumped that I was able to knock this out real quick.

require 'openssl'
require 'base58'
require 'digest'
#how do i create a transaction?
#generate private key
#generate public key
#hask public key
#A bitcoin address is a 160-bit has of the public portion of a public/private key ECDSA keypair

class BitcoinAddress

  def self.generate_private_key
    key = OpenSSL::PKey::EC.new("secp256k1").generate_key
    return key
  end

  def self.generate_public_key(private_key)
    public_key = private_key.public_key.to_bn.to_s(16)
    return public_key
  end

  def self.generate_address
    private_key = generate_private_key
    public_key = generate_public_key(private_key)
    ripmd_hash = ripmd160_hash((sha256_hash(public_key)))
    rip_generate_address = ripmd160_hash((sha256_hash(public_key)))

    ripmd_hash = "00" + ripmd_hash
    rip_generate_address = "00" + rip_generate_address

    ripmd_hash = return_checksum(sha256_hash(sha256_hash(ripmd_hash)))
    return "1" + generate_base58_address(rip_generate_address + ripmd_hash)
  end

  def self.sha256_hash(key)
    return Digest::SHA2.new(256).hexdigest([key].pack("H*"))
  end

  def self.ripmd160_hash(key)
    return Digest::RMD160.new.hexdigest([key].pack("H*"))
  end

  def self.return_checksum(data)
    return data[0..7]
  end

  def self.generate_base58_address(key)
    return Base58.encode(key.hex(), :bitcoin)
  end
end

bitcoin = BitcoinAddress
puts bitcoin.generate_address

Building My Own Bitcoin

I’ve wanted to this a while, but today I really got a hankering to do it. I want to build my own “bitcoin”.

Obviously it won’t be a real bitcoin. I just need to understand Bitcoin at a deeper level, and I want to write code while I do it.

I understand that I should probably read all the books and tutorials, but that seems just so boring to me right now. I want to hack at a project, build my own skills and learn what Bitcoin is at a protocol level.

So let’s start. I am going to hack on this for the remainder of December and try and update as frequently as I can, for just a learning experience.

Judges, Kings and God

A notable difference between kings and judges exist in the Bible.

There were many kings who committed many wrongdoings. There were few judges who sinned so greatly, as David, for example.

The difference between judges and kings were the roles they fulfilled.

A judge acted as a conduit between God and the people. Moses led and judged the people, by God’s actions. Whatever power Moses had, was pushed to serve the people of God better.

God used Moses to speak to the people, set laws for the people, and dealt out judgement through Moses. God was acting through Moses, in order to lead the people.

In 1 Samuel, the people moved away from this methodology of leadership. They had a king chosen for them, to represent them.

The king had all power, and the people listened. Consequently, God’s relationship with man changed. God spoke to the king, through the prophets.

The people no longer received the word of the Lord directly, but had to be led, through the actions of the king, in order to serve God.

We notice that God never spoke to David directly. Instead, David would enquire of the Lord, through the priest. God had set up a differentiation between him and the king. A direct line, would have made the king believe that they were on equal footing.

God spoke to David through Samuel and Nathan, Ahab through Elijah and Hezekiah, through Isaiah.

The only notable exception that I have found, was when God appeared to Solomon. This is very notable, as I believe it was the only time God revealed himself to a king.

And Solomon loved the LORD, walking in the statutes of David his father: only he sacrificed and burnt incense in high places. 
And the king went to Gibeon to sacrifice there; for that was the great high place: a thousand burnt offerings did Solomon offer upon that altar. 
In Gibeon the LORD appeared to Solomon in a dream by night: and God said, Ask what I shall give thee. 

1 King 3:3-5

This is so incredibly noteworthy to me. God regarded Solomon so highly, that he revealed himself to him. This placed him on equal footing with Abraham, Isaac, Jacob, Moses as people who had met with God.

Just to sum up this mess of notes:

  • Israel moving away from a theocracy, to a monarchy, hurt the people, by cutting them off from God, and having to rely on a man as a source of direction.
  • Kings are distinct from judges, as the power of the judge resided in God, and the king relied on the power of state.
  • Kings (almost) never met with God, prophets were used in this capacity.
  • Prophets emerged as mouthpieces for God, and played critical roles in the late Old Testament.

What is Bitcoin?

People will ask, “What is Bitcoin?”.

The answer depends on who you are.

If you are an anarcho-capitalist, maybe you see Bitcoin as a step to overthrowing the government.

If you are an economist, you see Bitcoin as a hedge against the cabal of banks who ruthlessly print money, backed by the promises of the government.

If you are a developer, Bitcoin is the greatest open-source project of our times.

If you are a game theorist, you see Bitcoin as a novel attempt to solving the Byzantine General’s Problem.

Anything I understand, I only understand as an extension of myself.

What is a Schelling Point?

Sometimes when listening to Bitcoin related podcasts, you will hear this term “Schelling point”.

I’ve heard this phrase before, but it seems to be one of those concepts that you understand implicitly, without being able to explain explicitly.

A Schelling point refers to a focal point, that people will use to coordinate, without communicating explicitly.

It is a game theory concept, explained by this quote from Wikipedia, very well.

In a simple example, two people unable to communicate with each other are each shown a panel of four squares and asked to select one; if and only if they both select the same one, they will each receive a prize. Three of the squares are blue and one is red. Assuming they each know nothing about the other player, but that they each do want to win the prize, then they will, reasonably, both choose the red square.

Wikipedia

I think the clearest explanation is from Naval Ravikant. He says, “(Shelling Points allow us to) … Use social norms to cooperate when you can’t communicate”.

Bitcoin Core vs Bitcoin Network

The Bitcoin Network is different from Bitcoin Core.

Bitcoin Core is an implementation of the Bitcoin network rules.

Other implementations of the Bitcoin network:

Anyone who downloads and runs a node from these projects, is running a node on the Bitcoin Network.

What is the Bitcoin Network?

How do we determine what rules make up the Bitcoin network?

We can see rules of the network are documented here. The interesting sentence here is this:

This is all based on a fairly literal reading of the source code.

Bitcoin Wiki

Does the code determine the rules? No! People do. The code reflects what people want.

How do we determine what people want? We can determine what people want, through consensus.

We have a formal process for finding consensus. When we achieve consensus, we are able to change the rules of the Bitcoin network.

Changing the Bitcoin Network

There is a formal process called “BIP”, which stands for Bitcoin Improvement Process.

Through this process anyone can submit a proposed change to the network.

This article details the steps needed to make a change final for soft forks:

In order for a BIP to become accepted and labeled as Final, each of the following conditions must be met:

  • Follows the correct format as specified by BIP-1
  • Includes code implementations of the proposed changes to the protocol
  • Has 95% support from the last 2,016 miners (~14 days worth of mining with 10 min blocks)
Alex Galea

A hard fork requires a completely different set of standards. Reading BIP 02, it states:

A hard-fork BIP requires adoption from the entire Bitcoin economy, particularly including those selling desirable goods and services in exchange for bitcoin payments, as well as Bitcoin holders who wish to spend or would spend their bitcoins (including selling for other currencies) differently in the event of such a hard-fork. Adoption must be expressed by de facto usage of the hard-fork in practice (ie, not merely expressing public support, although that is a good step to establish agreement before adoption of the BIP). This economic adoption cannot be established merely by a super-majority, except by literally forcing the minority to accept the hard-fork (whether this is viable or not is outside the scope of this document).

Luke Dashjr

Essentially it states that all hard-forks must be unanimously accepted by the network, and everyone who supports the network. Because this is so difficult, it has never been done.

Why is it more important to get unanimous adoption for hard-forks? Hard-forks break the network protocol, and create two blockchains through adoption. There is no backwards compatibility.

Soft-forks keep backward compatibility, allowing old nodes on the network to keep mining. Additionally, the same blockchain is being mined on,

Conclusion

Now you should understand the difference between the Bitcoin Network and Bitcoin Core, how to propose changes to the network,

Additional Reading