Building Bitcoin in JavaScript

How I did it

  • The block chain
  • The block reward, and block reward schedule
  • The block difficulty, and block difficulty adjustments
  • The mempool of pending transactions
  • The structure of a completed block
  • Communicating new transactions and blocks over the network
  • It wouldn’t be production-ready
  • It wouldn’t be identical to Bitcoin in every way
  • It wouldn’t be secure in any way
  • It wouldn’t be especially performant

Some Basic Principles

  • Bitcoin is powered by a ‘block chain’
  • A ‘block’ is just like an object containing various data, which is propagated across the Bitcoin network so everyone has the same state and source of truth, including the same transactions.
  • Each block is cryptographically tied to the previous block, forming a long chain of blocks each with new data and new transactions.
  • Each block contains transactions, which means coins can be transferred between different actors on the network. Bob sends Jane 5 coins, Jane sends Harry 3 coins, and so on. We can keep track of the balances by looking at all of the historical blocks.
  • Blocks need to be ‘mined’ to be generated, which takes a certain amount of computational power and luck. This secures the network: to hack or attack Bitcoin, you need more computational power than everyone else on the network.
  • Anyone who successfully mines a block, earns a reward of a fixed number of coins. This encourages miners to keep mining.
  • Transactions are also sent with optional fees. These fees are also collected by the miner of a block, along with the block reward. So there is a double incentive to mine new blocks.
  • Mining blocks gets incrementally harder or easier over time, to make sure each new block is mined at an approximately constant rate over time. Keeping the block rate constant is important: too high a block time, and the network will be unusable. Too low a block time, and the network can easily be spammed with conflicting blocks.
  • Each node and miner in the network agrees on all of these rules, and on the format of the blocks. This makes it extremely difficult to create fake blocks, or to send transactions which spend the same coins multiple times — even if you do have a vast amount of computing power.

The Block Chain Interface

  • Transactions, which require a sender, receiver, amount, and a user-defined fee. The fee will determine the priority for the transaction on the network.
  • Blocks, which will have a bunch of important fields.
  • An id, to identify the current block
  • A miner id (public key), to identify who gets the reward for each block
  • A parent block id, to allow the blocks to form a linear chain
  • An index, to easily keep count of the blocks
  • A time, to represent when the block was mined
  • An elapsed time, to represent the time between this block and the last
  • An array of transactions, to track sending and receiving coins
  • A difficulty setting, to keep the block time constant
  • A block reward, to incentivize miners.

Defining the rules

  • BLOCK_TIME is the time we’re aiming for between each block being generated. Bitcoin aims for 10 minutes between each block; we’re going to go for 1 second, so we can quickly run this locally and try it out.
  • INITIAL_REWARD is the reward of coins, for each block. This reward goes to whoever mined the block. This reward will halve over time, and will encourage more miners to try to mine blocks, process transactions, and keep the network secure and immune from double-spends or other attacks.
  • REWARD_HALVING_SCHEDULE is the number of blocks before this reward halves. Bitcoin typically halves every four years. We’ll aim for every twenty blocks, equivalent to every 20 seconds.
  • BLOCK_SIZE_LIMIT is the maximum number of transactions that can be included in any block. We’ll set this to 10, but the real limit in Bitcoin is much larger and is based around the MB size of the block.
  • GENESIS_BLOCK defines the initial hard-coded block. All other blocks will have this genesis block as their ancestor. We’ll award this block to SATOSHI for now, and we’ll define a default difficulty and the initial block reward.

Stubbing out the block chain

Mining Blocks

  1. The existing blockchain, represented here as root. We need to call getLongestBranchNode() here to find the current ‘true’ block chain, which we want to mine another block on top of.
  2. The publicKey of the miner. This needs to be part of the block, so everyone else on the network knows who will get the reward for mining the block.
  3. A list of transactions. There’s not much point in mining a block if we don’t have any transactions to publish to the network.
  • If the block took too long to generate, we lower the difficulty by 1.
  • If the block took too little time to generate, we increase the difficulty by 1.
  • A small number of miners, and a low hash rate, with a low difficulty
  • A large number of miners, and a high hash rate, with a large difficulty

Adding the block to the block chain

Calculating Balances

  • Transactions
  • Fees
  • Block Rewards
  • The miner gets the block reward for each block
  • The miner gets the fee for each transaction
  • The receiver gets the amount of the transaction
  • The sender loses the amount of the transaction
  • The sender loses the fee of the transaction

Done with the block chain!

Getting started with the Node

  • We want the ability to send Bitcoins from our wallet to another receiver address
  • And we want the ability to continually mine new blocks and earn block rewards

Blockchain, Credentials, and Network Access

  • We need a cryptographic key pair. We’ll use the public key to identify the node/wallet/miner, and the private key to sign any new transactions. Each miner, node, wallet, or any other actor uses this public key to identify themselves on the network. The private key helps them prove their identity.
  • We need to connect to a peer-to-peer network of other nodes. We’ve used a fake Network here for convenience, so we can broadcast and listen for events. In reality, Bitcoin will connect to a real peer-to-peer network of nodes across the internet, without any centralized servers required.
  • Of course we need the block-chain itself, which we already implemented above. We’ll instantiate that block-chain here, so the node can use it to store new blocks and mine new blocks and get current wallet balances.
  • We need a mempool. This is going to store incoming transactions, until they can be added to a block — since it will take some time to generate a block, we need somewhere to keep the transactions in the mean time.

Listening for new transactions

Sending a new transaction

Listening for new blocks

Running the node and mining new blocks

And that’s it!

Thanks!

--

--

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store