Introduction to Bitcoin Computing

Posted by Balaji Srinivasan

Introduction to Bitcoin Computing

This tutorial follows up from the Introduction to Bitcoin to give a brief introduction to Bitcoin Computing. You will learn how to get bitcoin, set up a bitcoin-payable API server for micropayments, and buy and sell digital goods for bitcoin. You will then do a few exercises that give you a sense of what can be done with bitcoin-payable APIs. Let’s get started!

Requirements

What is Bitcoin Computing?

We use the term “Bitcoin Computing” to refer to computation that is paid for by bitcoin. But what do we mean by a computation? It can refer to:

  • An English-to-Chinese machine translation algorithm that takes bitcoin and English text and returns the Chinese translation

  • An English-to-Chinese machine translation service that takes bitcoin and English text and returns the translation - even if there’s a human in the loop

  • A file server that receives bitcoin and returns a digital good

  • A game of skill that you can enter by paying bitcoin, which may pay out bitcoin if you’re successful in answering the questions (“Who wants to be a millionaire”)

As you can see, in this definition, “computation” is used holistically to encapsulate anything that can be put behind an API, including both obviously computational things (machine translation), computer-mediated things (translation microtasks), and even ecommerce (digital goods).

In this lab we’re going to learn how to work with Bitcoin computing under the aegis of the “Bitcoin-payable API”. Here are the steps we’ll follow in the lab:

  • Step 1: First, get some bitcoin and flush it to the blockchain

  • Step 2: Next, learn how to programmatically buy digital goods with bitcoin

  • Step 3: Now sell digital goods for Bitcoin

  • Step 4: Learn how to work with the bitcoin library

Note that during this process we’ve abstracted away much of the mechanics of using Bitcoin, such that you can just focus on setting up servers and clients that can transact with Bitcoin.

Step 1: Get some bitcoin

To get some initial liquidity let’s get Bitcoin:

21 sell

The command line interface abstracts away the complexity of getting bitcoin so that you can start using bitcoin as a system resource in your applications.

Once you’ve received your bitcoin , you can start using it to pay for digital goods and services.

Step 2: Buy a digital service with Bitcoin

Now that you have some bitcoin let’s use it to purchase a digital service! To view your current balance, please run the following command:

21 status

This shows you the amount of bitcoin that you have available for spending both “on-chain” and “off-chain”. Your spendable balance with 21 (“off-chain”) is a way to spend your bitcoin without relying directly on the Bitcoin blockchain (“on-chain”). Instead it uses a ledger managed by 21 to track transfers between 21 customers in much the same way that Chase Bank manages a ledger to track transfers between Chase customers. This is often desired as every Bitcoin transaction has a non-trivial fee associated with it.

The downside of the off-chain approach is that you give (temporary) control over those bitcoins to the centralized service. For micropayments, this isn't such a big deal as you'll probably only have fractions of a dollar on deposit. If you start earning lots of satoshis and want to withdraw them to the safety of your personal wallet, you can do that with a single command:

## Withdraw 20,000 satoshis
21 flush 20000

Let’s use our bitcoin to purchase a very common digital service. Again, the CLI has abstracted away much of the complexity and enables us to buy a digital service directly in exchange for bitcoin:

21 buy "https://mkt.21.co/21dotco/zip_code_data/zipdata/collect?zip_code=94109" --maxprice 2750

Under the hood this actually uses a remote API to look up the zipcode data. What’s interesting is that the amount of Bitcoin per purchase charged at the command line can be at or above the USD equivalent rate that the API charges. For a developer, this abstracts away the complexity of API authentication and the fixed time cost of signing up for the Twilio API and management of credit card details.

Step 3: Sell a digital service for Bitcoin

Now let’s take a look and see how we can sell a digital service for Bitcoin. To keep things simple, we’ll walk through a simple "hello world" app to give you a better sense of how easy it is to create a digital service. Let’s jump right into setting up the service (you may need to run sudo pip3 install flask twilio first):

import flask
from two1.wallet import Wallet
from two1.bitserv.flask import Payment
import yaml
import json

app = flask.Flask(__name__)
payment = Payment(app, Wallet())


@app.route('/hello')
@payment.required(5000)
def hello():
    return 'Hello, world'

@app.route('/manifest')
def manifest():
    """Provide the app manifest to the 21 crawler.
    """
    with open('./manifest.yaml', 'r') as f:
        manifest = yaml.load(f)
    return json.dumps(manifest)

if __name__ == "__main__":
    app.run(host="::", port=5000)

Let’s save the file as hello-world.py. Now to deploy our digital service which accepts bitcoin to send print a short message, all we have to do is run it on our Bitcoin Computer:

python3 hello-world.py

Let’s test to make sure the digital service is working. We can use the 21 buy command to do this fairly easily:

21 buy http://[::1]:5000/hello

It’s as simple as that!

Step 4: Learn to use the 21 libraries

  • Bitcoin library The Bitcoin module in the 21 Bitcoin Library includes code for working with key Bitcoin datastructures, like transactions and scripts.

  • Blockchain library The Blockchain module in the 21 Bitcoin Library provides information about the blockchain.

  • Crypto library The Crypto module in the 21 Bitcoin Library provides low-level access to essential Bitcoin-related cryptographic functions.

  • Wallet library The wallet module in the 21 Bitcoin Library includes an HD machine wallet which integrates with the 21 mining chip.

Demo: Fine-grained SAAS at the command line

What you will learn

Taking it a step further, we can now create a command line utility that uses bitcoin as a system resource to pay for digital services in the cloud. Here’s the syntax of how it will work:

map21 "jordan hall stanford ca”

After you get this set up (instructions in the next section), this command line invocation will pay a little bitcoin to a server and take in a string (“jordan hall stanford ca”), and print out the latitude and longitude of the lecture hall.

In more detail, the command is making a cloud call to a server running locally -- although if you were to run something like this in production, it could pay a server anywhere on the Internet.

What this does is abstract away the complexity of making a Google Maps API call to geocode the address (although you can easily imagine how it is called directly in this simple example). What’s revolutionary about this is that each call is accompanied by a micropayment that eliminates the need for API keys, subscriptions, and other time-sucking inconveniences.

How to build it

To get the map21 command working on your Bitcoin Computer, run through the following steps:

Grab a Google Maps Geocoding API Key and run the following command to set it as an environmental variable:

export GOOGLE_MAPS_API_KEY=1234xyz

Create a geocode folder:

mkdir geocode && cd geocode

Install the googlemaps library by running:

sudo pip3 install googlemaps

Create a geocodeserver.py file within the folder and populate it with the following code:

#!/usr/bin/env python3

import os
import json
import googlemaps
from flask import Flask, request

# import from the 21 Developer Library
from two1.wallet import Wallet
from two1.bitserv.flask import Payment

# set up server side wallet
app = Flask(__name__)
wallet = Wallet()
payment = Payment(app, wallet)

# create a developer account on Google and obtain a API key for the
# maps-geocode app at developers.google.com/maps
gmaps = googlemaps.Client(key=os.environ.get('GOOGLE_MAPS_API_KEY'))


# create a 402 endpoint that accepts a user's input address and returns the lat/long
@app.route('/geocode')
@payment.required(3000)
def geo():
    """Map input address given as a string to (latitude, longitude)."""

    # Define a dict variable to store latitude & longitude
    coords = {}

    # Get user's input address
    address = request.args.get('address')

    # Send a request to Google's Map-Geocode REST API using your API credentials defined above
    geocode_result = gmaps.geocode(address)

    # Check to see if the result is valid
    if geocode_result.__len__() == 0:
        return "The input address is invalid."
    else:
        # Obtain Lat & Long from result
        coords['latitude'] = geocode_result[0]['geometry']['location']['lat']
        coords['longitude'] = geocode_result[0]['geometry']['location']['lng']

        # Return co-ordinates back to the user
        return json.dumps(coords)

if __name__ == '__main__':
    app.run(host='::', debug=True)

Now start the server by running this command:

python3 geocodeserver.py

Now that you have the server-side component running, open a separate shell (you need to leave the geocode server running!) and create the command line tool:

First install click:

sudo pip3 install click

Now create a file named map21.py and open it in an editor. Populate the file with the following code:

#!/usr/bin/env python3

import json
import click

# import from the 21 Developer Library
from two1.commands.config import Config
from two1.wallet import Wallet
from two1.bitrequests import BitTransferRequests

# set up bitrequest client for BitTransfer requests
wallet = Wallet()
username = Config().username
requests = BitTransferRequests(wallet, username)

# server address
server_url = 'http://[::1]:5000/'


@click.command()
@click.argument('address')
def cli(address):
    """Call the geocode api hosted on the micropayments server"""

    sel_url = server_url+'geocode?address={}'
    response = requests.get(url=sel_url.format(address))
    if response.text == "The input address is invalid.":
        click.echo(response.text)
    else:
        coords = json.loads(response.text)
        click.echo(coords)

Create a setup.py file containing the following info:

from setuptools import setup

setup(
    name='map21',
    version='0.1',
    py_modules=['map21'],
    install_requires=[
        'Click',
    ],
    entry_points='''
        [console_scripts]
        map21=map21:cli
    ''',
)

Save and close the setup.py file and run:

sudo pip3 install --editable .

Now try running the map21 command:

map21 "jordan hall stanford ca"

If everything worked you should have received the coordinates of Jordan Hall!