Comparing Major Mining Algorithms

Overview

As it stands, all of the top cryptocurrencies (Bitcoin Cash, Ethereum, Litecoin, and Bitcoin) use proof-of-work mining to secure their networks. With proof-of-work, special nodes on the network called miners use their computing power to try and solve a mathematical problem. This problem is designed so that a miner has to do a bunch of guessing to get the answer, but anyone else can verify that answer very quickly.

The general idea across proof-of-work variations is the same: miners have to guess a bunch to get an answer, essentially proving that they’ve done some amount of work. And the collective amount of computing power on the network makes pulling off fraud impossibly hard. However, there are some different variations of these proof-of-work algorithms used in different cryptocurrencies. Let’s take a high-level look at these variations and how they achieve the same goal in different ways.

Mining Algorithm Variations

Bitcoin Cash/Bitcoin Mining with SHA-256

The original mining algorithm used in a cryptocurrency is the fairly straightforward SHA-256 used by Bitcoin. This mining algorithm solves a simple problem: given some block data, add a random number called a “nonce”, and run that through the SHA-256 hashing algorithm. This one way cryptographic hash outputs a very large number (256 bits if you’re curious), and that number has to be less than a difficulty target number for the problem to be “solved” with that nonce. With a simple toy algorithm (8 bits) – a solution might look something like this:

0 0 1 0 0 0 0 0 - Difficulty target value

1 0 0 1 1 1 1 1 - Guess #1 is not valid - greater than target
...
...
...
...
0 0 0 0 1 0 1 0 - Guess N is a valid hash - less than target

This algorithm is a clean and simple one. Guess a number, hash the data, and hope the resulting block hash is less than the difficulty target.

However, a disadvantage of this algorithm is in the equipment needed to contribute to mining on the network. SHA-256 mining is a hard computing problem, but that’s all its limited by. As the Bitcoin network has adjusted the difficulty target over time, profitable mining has become limited to specialized computing devices called ASICS – Application Specific Integrated Circuits. It’s not profitable or feasible for a single user like you or I to mine Bitcoin on a single device like a PC anymore – it’s the world of specialized companies and mining pools. This can be considered a problem of centralization, as less everyday users can participate in this part of securing the network.

Litecoin Mining with Scrypt

One of the first major forks of the Bitcoin codebase resulted in the popular currency Litecoin, which made changes to the mining algorithm in an attempt to solve this problem of a high barrier of entry for mining. Litecoin uses an alternative hashing algorithm called Scrypt in place of SHA-256. Scrypt is actually considered a key-derivation function rather than a pure hashing function, although the end goal is roughly the same: a one-way function that takes some data and outputs some bits that are the same every time for a particular input.

The different with a key-derivation function or specialized hashing algorithm like this is that they’re designed to be more computationally difficult that algorithms like SHA-256. Scrypt is memory hard, meaning that the algorithm is more limited by the available memory in the system than by the computing power.

For key derivation, this is great because it’s hard to do brute force attacks on a database of keys – in other words, it’s hard to guess what the original password was. For our mining algorithm, it’s great because ASICs don’t really give miners an advantage. This makes mining easier for folks that only have access to devices like GPUs, and prevents some of the mining centralization and barrier to entry that’s seen with SHA-256 mining.

Ethereum Mining with Ethash

Ethereum mining follows a similar model to Litecoin – it was designed to prevent mining centralization. However, Ethereum goes further than simply using a memory-hard key derivation function or something of that nature. Ethereum uses its own memory-hard algorithm for mining called Ethash, custom designed by its creators.

Ethash is based on an algorithm called Dagger-Hashimoto used to make mining a memory-hard problem. Every N blocks or so, a large dataset is generated using the block data as a “seed”. The Dagger part of the algorithm was designed by Ethereum’s creator Vitalik Buterin to make mining memory hard, but make verifying the answer relatively easy for non-mining nodes on the network. The Hashimoto part was designed by Thaddeus Dryja to make a memory-hard hashing problem. Combining these concepts into Ethash makes a mining algorithm that’s less prone to requiring specialized hardware over time than SHA-256 mining.

Mining Variations – Same Idea, Different Requirements

The overall problem in proof-of-work mining is the same across currencies and algorithm variations – a mining node must expend resources to guess a bunch and find an answer to the problem. However, there are a variety of ways in which problem those miners solve can be constructed.

Some variations like SHA-256 are simple, but prone to centralization and specialized hardware requirements over time. Other like Litecoin and Ethereum take a different approach, desiring to make mining a more equitable process across the network at the expense of some complexity.

Regardless of the approach, proof-of-work mining allows lots of individuals to come together and create a peer-to-peer network of money, without the need to trust any one central “clearing house” to process transactions. Proof-of-work mining makes pulling off fraud a difficult or impossible endeavor, so that these currencies remain globally decentralized and secure.

Bitcoin is Not (Just) for Rich People

Overview

At a recent event at Duquesne University, a student asked me to explain what Bitcoin is. And as an addendum to her question, she stated that her impression is that Bitcoin is only for rich people…

As an educator in the space and a strong believer in the power of cryptocurrencies to change the fabric of finance, I can’t stand that Bitcoin and its culture has devolved into memes about hodling (holding) and buying Lamborghinis when the price goes up. Let’s discuss why I think the true value of this technology goes so far beyond price speculation.

Getting Past “Number Go Up”

Is it possibly good for the community and adoption when the price of cryptocurrencies go up, relative to the United States Dollar? Probably. After all, a medium of exchange must have some value for it to be worth accepting for goods and services. However, the value must be fundamentally derived from the currency’s utility! Bitcoin Cash, Litecoin, Ethereum, et. all are first and foremost cryptocurrencies. Bitcoin should be, but its loudest proponents in the last several years have argued it’s only major use is as a store of value, so I’ll leave that up to you to decide.

But why is this distinction so important to me, and to many others working in the space? I so strongly believe in Bitcoin as peer to peer cash because its unique properties enable everyone in society to have more sovereignty over their finances.

The cryptocurrencies I study and tech about are decentralized. No central banks or corporate institutions control these forms of money, meaning there is no central point of failure. It’s peer to peer money – just the sender and receiver, no corporation in the middle deciding which transactions are valid and allowed to proceed. This leads to the property of censorship resistance, meaning that no one can arbitrarily stop you from transacting with another party. And of course, these currencies are truly global and borderless – no silly geopolitics here. Send money to anyone, anywhere.

Peer to Peer Cash for Everyone

These properties are pretty interesting for those of us in the modern world, yes. We can all benefit from increased security and economic freedom, undoubtedly. However, our judgement on the true value of these properties is often clouded by our wealth and access to privileged banking.

Imagine for a second that you’re a migrant worker, thousands of miles from your family. Your hard work is your family’s lifeline, but Western Union will steal 30% in fees to send your money back home. If you’re allowed to send money back to where home is. But with Bitcoin Cash or Litecoin, you’ll pay less than a penny in fees and your funds will arrive in a near instant. That is powerful.

Imagine you’re a dissident or journalist whose bank accounts are frozen in an attempt to shut you up. You can’t use your debit card anyone, but you can use Bitcoin Cash, Ethereum, and other currencies anywhere, any time. It costs you less in fees than banking does, and donations to your cause can never be censored.

Imagine you live in a part of the world where the nearest bank branch is 100 or more miles away, but you have access to a cell phone with a data connection. This happens in many parts of the world. The student I spoke with is a native of Kenya, where the M-pesa is a completely digital version of cash in the common use. Cryptocurrencies can easily become a totally free medium of exchange in those places, allowed the unbanked to hold a secure bank account in their pocket.

We, the rich and privileged can benefit from crypto adoption. But we cannot allow the properties that make these currencies so powerful to be eroded, for those that truly need them.

Common Address Encoding Formats

Overview

When sending money to someone else using Bitcoin, Bitcoin Cash, Ethereum, or another cryptocurrency, you send funds to the other user’s address. This unique identifier for the other user’s wallet may look like a “random” string of letters and numbers, like this: 13GuDW2Km8TR6iCYP8E5QGhNky2ne7T17r. (Note: this is just a random address; don’t use it!). But there’s actually quite a bit more going on behind the scenes when it comes to address encoding.

Different cryptocurrencies use different schemes to turn raw address data into what you would actually copy and paste, type, or scan into a wallet for sending. In some cases, one cryptocurrency may support multiple encoding formats. Let’s take a look at some of the most common formats used by major blockchains.

Common Encoding Formats

The OG Encoding format: base58check

The first major encoding format to appear is used most commonly in Bitcoin and Litecoin, the first major derivative of Bitcoin. This encoding format is known as base58check, and addresses look like this:

13GuDW2Km8TR6iCYP8E5QGhNky2ne7T17r

Base58check encoded addresses are generally derived using the same process (at least in the case of Bitcoin & Litecoin). First, the raw address is derived using a two-step cryptographic hash – first SHA-256, and then RIPEMD160. This gives us a 160 bit (20 byte) “pay to public key hash” address.

To encode the address, a version byte is added to the front of the raw hash. For Bitcoin, this version byte (in hexadecimal format) is 0x0, and Litecoin uses 0x3. Next, a checksum is generated, in order to help with error detection. The address including the version byte is hashed using SHA-256 twice. The first 32 bits (4 bytes) of the resulting hash is added to the end of the raw address.

Finally, the raw data is converted to base58. Base58 is a number system, just like what we’re used to with base 10. But instead of digits 0-9, base58 uses this alphabet: 123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz . It’s overall quite similar to the popular base64 encoding, but omits certain characters that are difficult to distinguish when writing or reading. There’s no 0, uppercase O, lowercase l, uppercase I, or non alphanumeric characters.

Base32-based: CashAddr and bech32

Over the last few years, base32 based encoding schemes have become more popular to deal with some of the issues base58check addresses are known to have. base58check addresses are shorter, but the mixing of uppercase and lowercase letters can make critical address data ambiguous and hard to read and write. Base32-based schemes solve this problem by only using non-ambiguous lowercase letters and numbers.

The first major currency to commonly use a base32-based system is Bitcoin Cash. BCH uses a special system called CashAddr for distinguishing BTC and BCH addresses. Cashaddr, like base58check, prepends a version byte to the public key hash. Version bytes for CashAddr can vary, as defined by the specification. The checksum uses a special algorithm to generate an error-detecting code called a BCH (Bose–Chaudhuri–Hocquenghem) code. The BCH code is the last 40 bits (5 bytes) of the final address. The address often includes a prefix to indicate the blockchain it’s used on as well, such as bitcoincash. A CashAddr address looks like this:

bitcoincash:qqv0y9qvkwxcyjdwcm9f5zgelf8aapndhuc2u24x9n

Bitcoin (BTC) has introduced a similar system for segwit addresses only, called bech32. All of these addresses, when encoded, start with bc for mainnet addresses, and also end with a BCH code for error detection.

Hexadecimal

The final encoding type we’ll discuss is the one used most commonly in Ethereum: hexadecimal. Hexadecimal encoding (often referred to as “hex”) is used very frequently in computer science outside of cryptocurrency. The hex number system is base16 and uses numbers and a few letters for its alphabet: 0123456789abcdef.

Ethereum address derivation and encoding is quite simple compared to other common cryptocurrencies. There’s no version byte, and no checksum (although a checksumming system has been introduced more recently, it’s not covered here). The public key hash is simply encoded as hex, and 0x is added to the front. This is a common indicator for hex format outside of cryptocurrency. An ethereum address looks like this:

0xc257274276a4e539741ca11b590b9447b26a8051 

The advantage to base16 is simplicity. There’s only 16 characters, all very easy to distinguish from one another! That makes it a more hardy format for reading and writing. However, it ends up creating rather lengthy addresses – for every 1 byte of data, you end up with two characters in hex.

Encoding – Because People Aren’t Computers

These encoding systems all exist for one simple reason – us meatbags aren’t particularly adept at reading and writing raw binary data. So instead of long chains of binary data, we send each other encoded addresses. Each of these common formats has its pros and cons when it comes to length, ease of use, and error detection. But in general, all of them are designed to make it easier for us to transact with these currencies without having to deal with raw binary data – thank goodness!

Hex Encoding, Version Prefixes, and Keccak (uBitAddr Code Companion Update)

Overview

In a previous tutorial, I shared the first published version of my uBitAddr project. This software and hardware project is a totally open source, open hardware, DIY offline address generator. It allows the user to generate a private key and the associated address for long-term storage, in something like a paper or metal wallet.

Since developing the original version, I’ve added several new features to the project and faced some interesting challenges along the way. Let’s take a look at some of the new features and complications I had to tackle.

Expanding Currency Support to my “Big 4”

Why add new currencies?

Personally, I am not a maximalist when it comes to Bitcoin or any other cryptocurrency. There are several I find interesting to study and use, and for my own personal preference those currencies are Bitcoin Cash, Ethereum, Litecoin, and Bitcoin.

The original version supported standard Bitcoin addresses (base58check encoded, no segwit support) and by extension supported Bitcoin Cash. However, BCH has long moved to a different address format, and Litecoin and Ethereum require an address derivation scheme that’s a bit different. I decided to take this project to it’s full potential (for my interests, at least) and add module and API support for all those currencies and formats.

Generating an Ethereum keypair totally offline!

Adding BCH cashaddr support

Thankfully, adding Bitcoin Cash support was fairly straightforward. The Trezor crypto libraries I use for cryptographic primitives/encoding already support cashaddr. I created a separate “address_from_pubkey” function in the module __init__.c code that derives the address from the pubkey and uses Trezor’s cashaddr encoding:

// Add the version specifier
unsigned char raw_address_nocheck[RAW_ADDRESS_NOCHECK_LENGTH];
raw_address_nocheck[0] = CASHADDR_P2PKH_BITS | CASHADDR_RIPEMD160_BITS;
memcpy(raw_address_nocheck + 1, round_2, RIPEMD160_DIGEST_LENGTH);

// Cashaddr  encode
cash_addr_encode((char*) address, "bitcoincash", raw_address_nocheck, RAW_ADDRESS_NOCHECK_LENGTH);

There’s a slightly different version specifier that has to be used with cashaddr, and that’s really it. Trezor’s cash_addr_encode takes care of the special cashaddr checksum, so there was no need to compute that manually like I do in the base58check code.

For the API, I simply added an optional flag in the constructor to allow cashaddr encoding instead of the legacy base58check:

uba = uBitAddr(output=uBitAddr.OUTPUT_DISPLAY, bch=True)

Litecoin Support

Litecoin support was again, fairly straightforward. The address derivation process is largely the same, but LTC uses different version specifiers for the WIF encoded key and the base58check address. Instead of using unsigned char BTC_ADDR_PREFIX = 0x0; for the address, LTC uses unsigned char LTC_ADDR_PREFIX = 0x30;. Likewise, the private key prefix is slightly different: unsigned char LTC_WIF_PREFIX = 0xB0; vs. Bitcoin’s unsigned char BTC_WIF_PREFIX = 0x80;. Otherwise, the derivation process is the same.

On the API side, at this point I added the ability to specify the desired currency as a optional argument when constructing the uBitAddr object:

uba = uBitAddr(output=uBitAddr.OUTPUT_DISPLAY, currency=uBitAddr.LTC)

Ethereum Support

Adding support for Ethereum was the most challenging. First, Ethereum requires a different hashing algorithm for deriving the address from the public key. It uses the Keccak version of SHA3, which outputs a 256 bit hash. However, Keccak is different than the final version of SHA3 accepted as the NIST standard. Fortunately, once again, Trezor has us covered. Their hardware wallet supports Ethereum and therefore has Keccak primitives in the crypto code. Another difference is that the address derivation scheme removes the 04 byte from the front of the pubkey (the byte that indicates the key is uncompressed) before the single round of Keccak hashing:

	// First, hash the public key without the 04 uncompressed pubkey indicator byte at the front
	unsigned char round_1[SHA3_256_DIGEST_LENGTH];

	keccak_256(pubkey + 1, ETH_PUBKEY_LENGTH, round_1);

	unsigned char raw_address[RAW_ETH_ADDRESS_LENGTH];
	memcpy(raw_address, round_1 + 12, RIPEMD160_DIGEST_LENGTH);

Next, ETH addresses use hex encoding rather than base58 or cashaddr. This would seem to be the simplest form of encoding, but once again the world of microcontroller programming threw me for a loop! Typically, one can format output data as hex in C using sprintf(%02x). However, I was not able to compile the CircuitPython module with that function call included.

So, I searched StackOverflow for solutions. Most of the sample code didn’t make immediate sense, but a user mentioned “using bit masking and shifting” and I was able to work out the solution on the whiteboard. I added a function that does hex encoding by masking off 4 bits at a time (a “nibble”), and for the leftmost nibble, using a 4 bit right shift. This gives a number that can be used as an index on the set of hex characters, hence giving us the two characters we need for encoding a single byte as hex.

// Convert a byte to hex format and write directly to the buffer
// This is a substitute for sprintf on a microcontroller platform
void byte_to_hex(unsigned char byte, unsigned char* buffer)
{
	char hex_chars[16] = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f' };
	unsigned char left_mask = 0xF0;
	unsigned char right_mask = 0xF;

	// First, calculate the character for the first nibble (4 bits)
	// Mask off the last 4 bits, then right shift 4 bytes
	// This will be the index used to get the right character from hex_chars
	unsigned char left_index = byte & left_mask;
	left_index = left_index >> 4;
	*buffer = hex_chars[left_index];

	unsigned char right_index = byte & right_mask;
	*(buffer + 1) = hex_chars[right_index];
}
Whiteboarding up a homebrew hex encoding function

Homebrew Offline Address Generation, Achieved!

The end result of this work is, in my opinion, a pretty sweet little project. A Reddit user called this project “cypherpunk” and I have to agree – there’s nothing more nerdy and paranoid than writing your own code for address generation. This is a very fun, challenging, and constantly evolving project.

Some final thoughts are, of course on security, This code is experimental, so play with it and use it at your own risk. I am a security-conscious engineer but I am NOT a cryptography expert. As well, there are pitfalls to dealing with raw keypairs compared to mnemonic seeds. As long as they’re generated with sufficient entropy they are secure, but there are pitfalls when it comes to writing down and storing the keys as well as sweeping the funds properly for future spending. Always do your research and ask questions before dealing with serious money!

Beginning Bitcoin – Sending Funds From Your Wallet

Overview

Getting started with Bitcoin isn’t as intimidating as it would seem. In another tutorial, we discussed how to get started with a mobile wallet, using Bitcoin.com’s app or the Coinomi wallet. We learned how to install the wallet, safely back up our funds using the seed phrase, and get an address for loading up funds.

But the real use of Bitcoin isn’t simply funding a wallet and watching the price bounce up and down. Cryptocurrencies are currencies after all, so they can be spent! Sending Bitcoin is fairly straightforward, but it’s a bit of a different mechanism than using a credit card online. Let’s learn how to send funds to someone else using the Bitcoin.com mobile wallet, and learn about what makes these transactions different that traditional online payments.

Creating Cryptocurrency Transactions

Sending funds with the Bitcoin.com wallet

Let’s donate a dollar to our friends at Eat BCH using the Bitcoin.com wallet. To do this, first open up the wallet with some funds in it, and click on the Send button. You’ll see this screen with options to enter a Bitcoin Cash address manually (or copy/paste), or to scan a QR code. I find that scanning a QR code is often the easiest way to get an address, and Eat BCH has one on the website.

It’s always a good idea to double check the address that actually ends up in the transaction preview. Make sure you didn’t accidentally copy/paste an incorrect address, or scan the wrong QR code. It happens, and there’s also malware out there that has fudged copy/pasted addresses.

Just take a second to make sure you have the destination you actually want. There are no do-overs with cryptocurrency transactions – once they are sent there is no reversal!

Once everything is verified, slide the Bitcoin logo at the bottom to send. Your transaction will be created, and is on it’s way.

Bitcoin vs. Traditional Online Payments

It’s simple to create Bitcoin, Ethereum, and other cryptocurrency transactions with a nice wallet user interface. But these transactions work a bit different than traditional monetary transfers, and it’s good to understand how they work at a high level.

The major difference between a cryptocurrency transaction and a traditional credit card/debit card payment is the mechanism. Traditional credit card payments are pull transactions. You give a merchant your credit card information, which is private information you are entrusting to them. They use that number to request funds be pulled from your account, via the Visa/Mastercard/etc. network.

Bitcoin transactions are push transactions. Instead of giving away private information, the merchant has to give you their public address that you push funds to in a transaction. You’re in charge of the sending, and no private information is every exchanged.

The true beauty of this system is the increased security you get with this model! You can publish a Bitcoin transaction on a billboard and everything is safe. Try putting your credit card number in a public space and see how long it takes to have major problems!

Bitcoin Transactions – Simple and Secure!

All you need to send money is a wallet with a network connection, some cryptocurrency of your choice, and a recipient address. With a modern mobile wallet, this process is a simple as scanning a QR code and hitting send. Thanks to Bitcoin’s security model, you don’t have to trust an intermediary like a payment company to process the transaction – it’s entirely peer-to-peer. And even more novel and important, there’s no need for anyone to reveal private numbers.

If you haven’t already, try sending your first transaction! Grab some Bitcoin or Bitcoin Cash, or maybe some Litecoin. Use a few dollars to introduce a friend to cryptocurrency, buy something fun, or donate to a good cause. Adoption is important, and it’s easy!

Learn Hashing, Binary, and Proof-of-Work with MicroProver (Code Companion #2)

Note: This article focuses on the development of MicroProver. See my slides for the full BTC2019 talk

Overview

Proof-of-work is a Bitcoin and blockchain topic of vital importance, as it allows transactions to occur without trusting an intermediary. However, understanding this concept also requires some computer science background. One needs to know about hashing algorithms, binary numbers, and a bit of probability to “get” proof-of-work.

I wanted to do a better job of explaining the concept of proof-of-work to individuals without a computer science background – so I came up with the idea of visualizing hashing and binary numbers with a cool little microcontroller I received at PyCon 2019. This code companion will dive into the development of MicroProver, and how I turned this project into a session at the 2019 Blockchain Training Conference!

MicroProver (running on the Adafruit Circuit Playground Express) displays a final “block hash”

How MicroProver Works

Toy Hashing Algorithm

The first thing needed to make simulated proof-of-work operate is a hashing algorithm. Bitcoin uses the cryptographically secure SHA-256 for its mining operations, among other things. However, these cryptographic algorithms are not readily available on microcontroller platforms such as the Circuit Playground. It took extensive effort to get cryptographic primitives working for my offline address generation project, and required a more powerful line of processor than the CPX’s M0.

However, for the purposes of this project, a cryptographically secure hash algorithm is not needed! This project is designed for visualization and learning, and has no security requirements. So in order to create the 8 bit hashes I wanted, I simply used the simplest form of hash function one might use for creating a basic hash table. All of the code in this article can be found in src/core/MicroProver.py

    # Settings for "cryptography"
    self.HASH_MOD = 256

...

    # Return a really simple 8 bit hash
    # This is for educational purposes, so we don't need a
    # cryptographically secure hash, we just need one that works
    def hash_8bit(self, data):
        hash8 = data % self.HASH_MOD

        return hash8

For an 8 bit hash, we use the 8 bit number space that contains 256 total possible numbers (0-255). This algorithm takes the modulus of the data and 256, giving us a reasonable hash for our purposes.

Binary Representation

The other important concept needed to address proof-of-work is understanding binary numbers. In daily life, most of us are used to base 10, and working in other bases is a rather foreign concept. In order to make this easier to understanding in the context of proof-of-work, I decided to use the built in CPX LED lights, with red representing 0 and green representing 1.

The code takes the data (the hash output) and converts it from a raw number to an array of binary values, either True/False (used by the LED function) or 1/0 for string representation. The data is turned into binary using a technique called bitmasking, where one single bit of a byte is isolated using the & binary operator.

    # Convert a byte of data (8 bit hash, etc.) into
    # an array of bits represented by True (1) and False (0)
    # (with default mode bool)
    # Specify optional mode "bit" for 0/1 representation
    def byte_to_bitarr(self, byte, mode="bool"):

        # Define some bitmasks for each spot in the byte
        # We'll create the array using bitmasking
        masks = [ 0x80, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01 ]
        byte = int(byte)

        bitarr = []
        for i in range(0, 8):
            if mode == "bit":
                masked = byte & masks[i]
                bit = "1" if masked > 0 else "0"
            else:
                bit = bool(byte & masks[i])
            bitarr.append(bit)

        return bitarr

The LED display function then takes that array and lights up individual LEDs on the board to represent each bit:

    # This function displays an LED representation of a byte
    # It lights up 8 LEDs on the Playground Express board
    # Green represents a 1 bit
    # Red represents a 0 bit
    def display_byte_led(self, byte):

        bitarr = self.byte_to_bitarr(byte)
        for i in range(0, 8):
            if bitarr[i]:
                color = self.GREEN
            else:
                color = self.RED

            # Load the pixels from 1 - 9 so they
            # fill evenly on each side of the board
            cpx.pixels[i + 1] = color
        cpx.pixels.show()

Tying It Together for Proof-of-Work

Using these nifty little hash concepts, binary operators, and LEDs, it becomes bit easier to visualize the binary number comparisons needed by proof of work. Proof-of-work requires comparing a hash output to a difficulty target, and both can be thought of as binary numbers. For this toy visualization, we use small 8 bit numbers.

For example, say we have a difficulty target of 00100000. This value (32 in decimal) has two leading zeroes represented as an 8 bit, unsigned integer. Therefore, the final hash output must have at least 3 leading zeroes to be less than the target. For example, 00010100 is a valid block hash. Because the probability of finding this “block hash” decreases as the difficulty target decreases numerically, we “proved work” by doing a lot of guesses to get a solution.

In MicroProver, the user gets to program the difficulty level from 1-7, with the level being the number of leading zeroes in the target. This way, it is easy for the user to visualize the algorithm as attempts and the final solution are displayed on the board. They can look for the red “leading zeroes” as the algorithm works, and get a better feel for how difficulty affects the computing power/time needed to prove work.

Extra Visual Help – Data Visualization Script

As an addition to the board itself, I created a data visualization script in src/dataviz/graph_pow.py. This script takes an optional log generated by the CPX simulation and graphs targets/vs. attempts, breaking down how difficulty affects the probability of finding a solution:

Proof of Work difficulty target vs attempts to find a solution. It’s probability!

Proof-of-Work, Made Accessible

When I got the Circuit Playground, I knew I had to use it to create an interesting chaintuts project! After getting oriented with programming basic utilities on the board, I decided its features would be great for an educational assistant.

Fortunately, I have had the opportunity to take this project further and teach at the 2019 Blockchain Training Conference in Denver, CO! For this session, I’ll be breaking down proof-of-work and using MicroProver for interactive simulations and data visualization.

By using LEDs to visualize hashing, binary numbers, and a bit of probability, we can make understanding this critical blockchain security topic more accessible to those without a computer science background. And the more folks that understand decentralization and trustless software, the more we can drive adoption of these technologies.

Offline Address Generation with uBitAddr (Code Companion #1)

This is a new series I’m introducing called “Code Companion”. These articles and videos highlight code projects of mine that are related to Bitcoin & cryptocurrencies. These projects can be helpful in understanding technical blockchain concepts. Explore and enjoy!

Overview

One of the most secure ways to store Bitcoin and other cryptocurrencies for the long term is to use was is called cold storage. This means storing the private keys that secure your funds in some manner that doesn’t allow access by a networked computer. A popular method of implementing cold storage is to use a technology that long predates computing and the Bitcoin network – paper. A paper wallet is simply a Bitcoin address and it’s private key written down on paper, usually in an exportable format such as WIF (Wallet Import Format).

An even more secure way to approach offline storage is to generate the private key and address offline. Generating and storing keys offline protects the owner from malware that might snoop the keys and send them off to a thief.

My project uBitAddr (pronounced MicroBitAddr) allows the generation of private keys and addresses completely offline using Adafruit M4 microprocessors wired up to an LCD screen or mini thermal receipt printer.

ubitaddr_display
uBitAddr running on the Adafruit ItsyBitsy M4 with a character LCD & backpack as the output
uBitAddr running on the Adafruit Grand Central M4 with a mini thermal receipt printer as the output

How uBitAddr Works

Custom CircuitPython Module

The first big challenge in this project was getting access to the required cryptographic primitives on a microcontroller platform. Generating a basic Bitcoin address requires elliptic curve cryptography (secp256k1 specifically), and two different hashing algorithms (SHA-256 and RIPEMD160). Good implementations of these algorithms are widely available on desktop PC’s and mobile phones for a variety of programming languages, but aren’t readily available for microprocessors like this.

I needed to get access to good cryptographic implementations to make this work! Since I wanted to do the bulk of coding in CircuitPython, I could have found pure-Python implementations of these algorithms. However, I felt this was resource inefficient and wouldn’t work on all but the most robust boards. Instead, I opted to write custom extension for CircuitPython itself using this guide from Dave Astels and some help from ladyada and Dan on Github. – thanks everyone!

For my project, I needed to use the M4 line of microcontrollers from Adafruit (using the Atmel Samd51 processor). I needed to use a processor at least this powerful to fit the compiled CircuitPython distribution, as the M0’s are simply too small to support these cryptographic algorithms. Fortunately, my goal of supporting a few different controllers and not just one big powerful one still worked out – the M4 line features a bunch of different shapes and sizes, from the ItsyBitsy to the Grand Central!

For cryptographic primitives, I ended up porting over code from the popular open-source hardware wallet Trezor. The Trezor crypto libraries had everything I needed to do efficient elliptic curve crypto and hashing, and even base58 encoding for the final address and WIF private key. This code is designed to be efficient and lightweight for embedded platforms. A big thanks to Trezor’s contributors for this code!

In terms of the my implementation, the most important code in this extension is features in src/module/shared-module/bitaddr/__init__.c. This code follows several steps to generate an address and exportable private key from start to finish:

  • Take entropy from the Python side (could be any good source, that’s up to the module user)
  • Hash the entropy and generate the raw private key
  • Calculate the uncompressed public key from the private key
  • Use the Bitcoin base58 check algorithm to hash and encode the address from the public key
  • Use the WIF algorithm to encode an exportable private key

As of this writing, that function looks like this. I try to keep projects moving forward so this may change slightly in the future:

 // Define functions that implement the Python API
void shared_modules_bitaddr_get_address_privkey(unsigned char* address, unsigned char* privkey, const char* entropy_privkey, const char* entropy_ecdsa)
{
	// Init the random32 for rand.h and ecdsa.h functions
	// The random function is only needed for curve_to_jacobian - needs a random k value
	// It will only be called once for address generation, so we'll use true entropy
	// To "seed" random32's PRNG without causing problems
	unsigned char seed_entropy[SHA256_DIGEST_LENGTH];
	sha256_Raw((uint8_t*) entropy_ecdsa, strlen(entropy_ecdsa), (uint8_t*) seed_entropy);
	init_random32(seed_entropy);


	// Generate the private key from some entropy
	// Then generate the public key from the private key
	unsigned char privkey_raw[SHA256_DIGEST_LENGTH];
	privkey_from_entropy(entropy_privkey, privkey_raw);

	unsigned char pubkey[PUBKEY_65_LENGTH];
	pubkey_from_privkey(privkey_raw, pubkey);

	// Generate the address from the public key
	// This address will use the legacy base58check encoding valid
	// in both BTC and BCH
	address_from_pubkey(pubkey, address);

	// Convert the private key to WIF format for export
	privkey_wif_from_raw(privkey_raw, privkey);
}

The next major component of this is creating a binding to the Python side in src/module/shared-bindings/bitaddr/__init__.c. This is a bit more complicated but the general idea is to take two sources of entropy (randomness) from the module user for the private key and ECDSA k value. I did this to allow flexibility – the module user can use a built in CRNG, accelerometer, diceware, etc. to generate randomness as they choose. Right now the Python code I wrote uses the convenient CRNG built in to all M4 boards.

Next, the C function shared_modules_bitaddr_get_address_privkey from shared-module/__init__.c is called. The return values (passed in to the function as pointers) are placed in a Python tuple and returned to the caller on the Python side.

//| .. function:: get_address
//|
//|   Returns a Bitcoin or Bitcoin Cash Legacy Address
//|
const size_t ADDRESS_STR_LENGTH = 40;
const size_t PRIVKEY_STR_LENGTH = 70;

STATIC mp_obj_t bitaddr_get_address(mp_obj_t entropy_privkey, mp_obj_t entropy_ecdsa) {

	// Convert entropy args needed for secure address generation
	const char* entropy_privkey_char = mp_obj_str_get_str(entropy_privkey);
	const char* entropy_ecdsa_char = mp_obj_str_get_str(entropy_ecdsa);

	// Create an address cstring long enough to fit any Bitcoin address
	unsigned char address[ADDRESS_STR_LENGTH];
	unsigned char privkey[PRIVKEY_STR_LENGTH];
 	shared_modules_bitaddr_get_address_privkey(address, privkey, entropy_privkey_char, entropy_ecdsa_char);

    	// make the return value
    	mp_obj_tuple_t *addr_key= MP_OBJ_TO_PTR(mp_obj_new_tuple(2, NULL));
    	addr_key -> items[0] = mp_obj_new_str((char*) address, ADDRESS_STR_LENGTH);
    	addr_key -> items[1] = mp_obj_new_str((char*) privkey, PRIVKEY_STR_LENGTH);

	return addr_key;
}
STATIC MP_DEFINE_CONST_FUN_OBJ_2(bitaddr_get_address_obj, bitaddr_get_address);

Finally, I built this for at least a few of the boards I wanted to support. I tested this code on an ItsyBitsy M4 and Grand Central M4, but it should also work on the Metro M4 or other releases. They’re all the same processor and seem to all have built in cryptographic number generation. So cool!

The Core CircuitPython Code

Thanks to this module, generating an address on the Python side ends up super simple! I generate a new address and private key on demand by specifying some entropy from the built in CRNG and store the results from the returned tuple:

    # Get entropy based on the desired source
    def get_entropy_str(self):

        if self.entropy_source == self.ENTROPY_CRNG:
            return str(os.urandom(32))
        else:
            raise Exception("No sufficient entropy source specified")

    # Generate address and private key
    def generate_address_privkey(self):

        address, privkey = bitaddr.get_address(self.get_entropy_str(), self.get_entropy_str())

        return (address, privkey)

In the future it may be possible to get entropy from another source – like an accelerometer wired to the board, or a keypad input for diceware key generation.

Wiring up Outputs

The final step was to offer a few options for viewing the generated address and private key. I have an option for serial import, so it’s of course possible to send your address and private key directly to a computer. However, since the whole purpose of this project is offline generation and storage, it’s obvious I needed some offline output options! I opted for character LCD display and thermal printing.

The first option is wiring up a thermal receipt printer. This uses an Adafruit mini printer that costs about $60, and it’s so cool to play with. To use this peripheral, I had to wire it to an external power source that came with the kit. The printer was then wired to ground and serial tx on the processor.

    # Print a paper wallet with the thermal receipt printer
    def print_address_privkey(self, address, privkey, print_privkey=True):

        # Intialize the printer
        uart = busio.UART(board.TX, board.RX, baudrate=19200)
        ThermalPrinter = adafruit_thermal_printer.get_printer_class(2.69)
        printer = ThermalPrinter(uart)

        printer.bold = True

        # Warm up and wait so we get the best print quality
        printer.warm_up()
        time.sleep(2)

        # Print the address information
        printer.feed(3)
        printer.print("Address:")
        printer.print(address)

        if print_privkey:
            printer.feed(3)
            printer.print("Private Key (WIF):")
            printer.print(privkey)

        printer.feed(3)

The next option (slightly more complex, actually) is the character LCD display. For this, I got to solder for the first time since high school! Thankfully my friend and engineer Nathan Schomer taught me well back in the day. I soldered the I2C backpack to the character LCD, and wired it to scl and sda on the board for data. Power requires either 5v or USB depending on the board, and a ground.

    # Prepare the data for display on the character screen
    def prep_data(self, data, colmax):

        prepped_data = ""
        for i in range(0, len(data)):
            if i != 0 and i % colmax == 0:
                prepped_data = prepped_data + "\n"

            if data[i] in self.BASE58_ALPHABET:
                prepped_data = prepped_data + data[i]

        return prepped_data

    # Display the address or private key on a character LCD
    def display_address_privkey(self, address, privkey):

        # Initialize the board
        i2c = busio.I2C(board.SCL, board.SDA)
        cols = 20
        rows = 4
        lcd = character_lcd.Character_LCD_I2C(i2c, cols, rows)
        lcd.backlight = True

        # Prep the address and display, wait N seconds,
        # then display the private key
        while True:
            lcd.clear()
            address = self.prep_data(address, cols)
            lcd.message = "Address:\n" + address

            time.sleep(self.DISPLAY_INTERVAL)

            lcd.clear()
            privkey = self.prep_data(privkey, cols)
            lcd.message = "Private Key (WIF):\n" + privkey

            time.sleep(self.DISPLAY_INTERVAL)
The thermal printer wired up to the ItsyBitsy M4
The character LCD wired up to the Grand Central M4.

Easy Offline Address Generation with uBitAddr

I was extremely excited to get this project working from start to finish, as it was certainly a challenge. Now that it’s done, it’s easy to generate addresses completely offline and keep them secure. All I have to do is boot up a board with an output, and make sure the key and address are safely written down and backed up.

This project has plenty of interesting potential features as well – as I improve on it I can add things like different entropy sources, persistent storage of keys/addresses on the board or a micro SD, different outputs, newer address formats, and more.

I encourage you all to go out and try building things like these as well! Try running your own uBitAddr setup if you have some knowledge of microcontrollers, or get started with your own address generation software built on a platform you’re familiar with. If you’ve never used an Arduino or CircuitPython controller before, try making something fun – they are more accessible than you think. Happy tinkering!

Token-Ize Me – The Basics of ERC20 Tokens

Overview

One of the most interesting and powerful capabilities of the Ethereum network is the ability to create new currencies that operate on top of the base network. By using smart contracts, it’s possible to create a currency called a token without having to fork an existing currency’s code and create a new decentralized network. Coins such as Litecoin follow the latter approach – Litecoin exists as its own network that runs on a modified version of Bitcoin’s code. However, tokens such as 0x (ZRX), Basic Attention Token (BAT), and Paxos (PAX) exist by leveraging the existing Ethereum network’s smart contract capability.

However, there are so many tokens out there that it would be nearly impossible for wallet creators and exchanges to keep up with each individual token’s smart contract API. In order to make it easier to create and support Ethereum tokens, the ERC20 standard was introduced. This standard specifies a common set of smart contract functions and events for a token. Let’s take a look at this standard smart contract interface and how it works.

ERC20 Contracts

The Standard Contract Format

The ERC20 standard defines a set of functions and events that a token smart contract should define. The functions are:

function totalSupply() public view returns (uint);
function balanceOf(address tokenOwner) public view returns (uint balance);
function allowance(address tokenOwner, address spender) public view returns (uint remaining);
function transfer(address to, uint tokens) public returns (bool success);
function approve(address spender, uint tokens) public returns (bool success);
function transferFrom(address from, address to, uint tokens) public returns (bool success);

There are two events associated with the contract as well:

event Transfer(address indexed from, address indexed to, uint tokens);
event Approval(address indexed tokenOwner, address indexed spender, uint tokens

The list of required fields is fairly simple, but let’s break down more how a contract like this works and summarize what each function does.

Token Contract Creation

Any time a smart contract is deployed on the Ethereum network, it becomes a permanent part of the blockchain that others can interact with by sending a transaction to the contract address with a function call in the data section of the transaction.

When a fixed-supply token contract is created (a common and simple type of token), the first thing it does is assign the total supply balance to the contract address owner, so the total amount of tokens is accounted for. Different types of tokens might allow a mining process where when a new Ethereum block is found, that miner also gets some of the tokens. But we’re focused on simple fixed-supply contracts here, so assume when the contract is created the owner of the Ethereum contract address now owns the full supply of this token.

At any time, another user can see the total supply of tokens by creating a tx that calls totalSupply, and balances can be checked by calling balanceOf with an address.

Token Transactions

There are now two types of token transactions our smart contract interface allows. The first is pretty simple: it’s the transfer functionality from the contract address owner to another recepient. Ethereum tokens use Ethereum addresses for sending and receiving, so it’s simple in that regard. So to do a transfer, the owner creates a transaction on Ethereum that calls the transfer function, specifying an amount and the new owner.

The second type of transfer is a little more interesting and complex. The ERC20 standard allows a withdrawal type mechanism. First, the contract address owner must call approve in a transaction, specifying a new address that is allowed to withdraw and what the maximum withdrawal amount is. Then, the withdrawal address owner can call allowance to see their “account balance” and use transferFrom to withdraw from the approved account to a new address.

Finally, most contracts will emit an event on Transfer or Approval so that other contracts can listen and do something when the event is fired off. For example, we may have a contract that waits for approval to conduct a withdrawal of a token.

Tokens Made Simple

There’s a lot going on when it comes to understanding Ethereum smart contract execution, but thankfully the ERC20 interface can be understood at a high level by discussing the basic functionality of each defined function and event.

With ERC20, we can create a token, and easily retrieve the total supply or an address balance. We can do a simple transfer out of an address we own, or approve withdrawals by another account that will transfer from the approved account. Finally, other contracts can listen for approval and transfer events so they can do something interesting.

For further reading, the Ethereum Wiki has a section on the ERC20 standard with a code example that may be useful. There are tons of tokens out there you may be interested in exploring as well.