Bitcoin-Accelerated Computing

Posted by John Granata

Bitcoin-Accelerated Computing

Overview

This tutorial will introduce you to the concept of bitcoin-accelerated computing. You'll learn how a client can use bitcoin to outsource a large computation to a server, and build your first intelligent agent. Specifically, here are the steps you will follow:

  • First, you will set up a bitcoin-payable API server
  • Then, you will set up a client with some bitcoin
  • Your client will then spend bitcoin to buy an API call from the server, speeding up a local computation
  • You will then set up a second bitcoin-payable API server at a different price, and modify your client to buy from the lowest-priced bidder in realtime - thus creating an intelligent agent.

Once you’ve gone through those steps, you will start to see how bitcoin can be used as a lubricant for machine-to-machine transactions and a powerful way to monetize spare computer time.

Prerequisites

Install 21

You will need the following first:

  • Either a 21 Bitcoin Computer or 21
  • The latest version of the 21 software, obtained by running 21 update

If you've got all the prerequisites, you are ready to go. Let's get started!

Step 1: Set up a bitcoin-payable API server

Open up a new terminal window. If you use a 21 Bitcoin Computer, ssh into it:

## Only necessary if you use a 21 Bitcoin Computer
ssh twenty@IP_ADDRESS

Then create a folder to house the server project:

mkdir bitcoin-aware-computing-server1 && cd bitcoin-aware-computing-server1

Go to this directory and open a file named server1.py in your text editor. Add the following code to it:

#!/usr/bin/env python3
import json

from flask import Flask, request

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

app = Flask(__name__)
wallet = Wallet()
payment = Payment(app, wallet)


# sort method w/out delay simulates faster computation server
def fast_get_element(arr, prop, val):
    for elem in arr:
        if elem[prop] == val:
            return elem


def get_array_to_sort(request):
    return json.loads(request.form.getlist("array")[0])


@app.route('/fastfind', methods=['GET', 'POST'])
@payment.required(3000)
def fast_get_elem():
    arr = get_array_to_sort(request)
    prop = request.form.getlist("property")[0]
    value = int(request.form.getlist("value")[0])
    res = fast_get_element(arr, prop, value)
    return json.dumps({"elem": str(res)})

# set up and run the server
if __name__ == '__main__':
    app.run(host='::')

Start your micropayments server:

python3 server1.py

Your bitcoin-payable API is up and running!

Step 2: Use the client's bitcoin to buy API calls from the server

Leave that terminal open and open a new terminal window. If you use a 21 Bitcoin Computer, ssh into it:

## Only necessary if you use a 21 Bitcoin Computer
ssh twenty@IP_ADDRESS

Create a folder to house the client project:

mkdir bitcoin-aware-computing-client && cd bitcoin-aware-computing-client

Open up a file named client.py and type in the following code:

import json
import time

import two1
import two1.commands.status
from two1.server import rest_client
from two1.commands.config import Config
from two1.wallet import Wallet
from two1.server.machine_auth_wallet import MachineAuthWallet
from two1.bitrequests import BitTransferRequests

# set up wallet proxy
wallet = Wallet()

# read local user account data
config = Config()
username = Config().username

# initialize rest client to communicate with 21.co API
client = rest_client.TwentyOneRestClient(two1.TWO1_HOST, MachineAuthWallet(wallet), username)

# set up bitrequests client using BitTransfer payment method for managing 402 requests
requests = BitTransferRequests(wallet)


# slow local method
def get_element(arr, prop, val):
    for elem in arr:
        if elem[prop] == val:
            return elem
        time.sleep(1)


# fast bitcoin-aware api NOx
def fast_get_element(arr, prop, val):
    body = {
        'array': json.dumps(arr),
        'property': prop,
        'value': val
    }
    res = requests.post(url='http://[::1]:5000/fastfind', data=body)
    return json.loads(res.text)['elem']

# sample data
data1 = [
    {'height': 4},
    {'height': 3},
    {'height': 6},
    {'height': 4},
    {'height': 3},
    {'height': 6},
    {'height': 4},
    {'height': 3},
    {'height': 6},
    {'height': 10},
]

# larger sample data
data2 = [
    {'height': 4},
    {'height': 3},
    {'height': 6},
    {'height': 7},
    {'height': 2},
    {'height': 4},
    {'height': 4},
    {'height': 3},
    {'height': 6},
    {'height': 7},
    {'height': 2},
    {'height': 4},
    {'height': 10}
]


def main():
    # check the spot price for our api call
    response = requests.get_402_info(url='http://[::1]:5000/fastfind')
    endpoint_info = dict(response)
    price = int(endpoint_info['price'])
    print(endpoint_info)
if __name__ == '__main__':
    main()

If you run this code with python3 client.py you will see something like this (the exact values will be different):

{'bitcoin-address': '14MrUbDsHZmpVUUsN2s8zzy4KzRjy3Hhnp', 'price': '5000', 'username': 'testuser1'}

Now let's compute something. First, let's write a program that accelerates our computation if we have enough bitcoin to pay for the call. We'll define a local method that returns the first object with a certain property from an array, and we'll also define a bitcoin-aware version of this method that sends the data to the cloud for faster processing. Add the following to the main() function in client.py

# first let's try the slow local method
    t0 = time.time()
    a = get_element(data1, 'height', 10)
    t1 = time.time()

    # print results of local call
    print(a)
    print("Execution time: " + str(t1-t0))

Example Output:

{'height': 10}
Execution time: 9.02669906616212

Now, let's accelerate the computation if we have enough BTC to afford it:

# get user's 21.co buffer
    bal = client.get_earnings()
    twentyone_buffer = bal["total_earnings"]

    t0 = time.time()
    if twentyone_buffer > price:
        a = fast_get_element(data1, 'height', 10)  # buy the api call
    else:
        a = get_element(data1, 'height', 10)  # locally execute the method

    t1 = time.time()
    print(a)
    print("Execution time: " + str(t1-t0))

Example Output:

{'height': 10}
Execution time: 5.5479278564453125

We can check our buffer to see if we were debited the amount we paid:

bal = client.get_earnings()
    print(bal["total_earnings"])

Now, our program will call the local method or the machine-payable api based on the dataset size. First we'll pass in the smaller dataset (data1) from earlier.

# accelerate computation as a function of dataset size
    data = data1
    t0 = time.time()
    if len(data) <= 10:
        a = get_element(data, 'height', 10)
    else:
        a = fast_get_element(data, 'height', 10)

    t1 = time.time()
    print(a)
    print("Execution time: " + str(t1-t0))

Example Output:

{'height': 10}
Execution time: 9.02669906616211

Now we'll pass in the larger dataset, which will trigger the bitcoin-powered api call:

data = data2
    t0 = time.time()
    if len(data) <= 10:
        a = get_element(data, 'height', 10)
    else:
        a = fast_get_element(data, 'height', 10)

    t1 = time.time()
    print(a)
    print("Execution time: " + str(t1-t0))

Example Output:

{'height': 10}
Execution time: 5.5479278564453126

In this simple example, the bitcoin-aware code saves several seconds over the local function call.

Next Steps

To recap, this tutorial explained the concept of bitcoin-accelerated computing.

As background, one of the key concepts in mobile development is the concept of "power-aware computing". In a power-constrained environment, power is a scarce resource. You can spend more power to run an algorithm quickly, or you can spend less power to run an algorithm more slowly.

In the same way, 21 introduces the idea of "bitcoin-accelerated computing". A typical computer has no bitcoin. But if you do have some bitcoin, you can choose whether to spend more bitcoin to run an algorithm quickly on a remote server, or spend less (or 0) bitcoin to run the algorithm more slowly on a local server.

The key concept is that once you have both a client that generates bitcoin and a server that accepts bitcoin, the client can send bitcoin to the server to perform computations remotely, thereby spending digital currency to save time. We dub this a "cloud call" or "bitcoin-accelerated computing".

Because this process is fully programmable, you can do it conditionally. For example, you can choose whether or not to outsource a particular problem for bitcoin based on the size of the input data set, your expected future workload, or the spot price of the remote server.

Perhaps most interestingly, you can do it based on the spot price of multiple remote servers -- thereby developing a simple intelligent agent that chooses which endpoint provider to purchase from based on their current bitcoin price.

And that's the next step. Now that you've finished this tutorial, you can learn how to build an intelligent agent with bitcoin.


How to send your Bitcoin to the Blockchain

Just as a reminder, you can send bitcoin mined or earned in your 21.co balance to the blockchain at any time by running 21 flush . A transaction will be created within 10 minutes, and you can view the transaction id with 21 log. Once the transaction has been confirmed, you can check the balance in your bitcoin wallet from the command line with wallet balance, and you can send bitcoin from your wallet to another address with wallet sendto $BITCOIN_ADDRESS --satoshis $SATOSHI_AMOUNT --use-unconfirmed. The --satoshis flag allows you to specify the amount in satoshis; without it the sendto amount is in BTC, but this behavior is deprecated and will be removed soon. The --use-unconfirmed flag ensures that you can send even if you have unconfirmed transactions in your wallet.


Ready to sell your endpoint? Go to slack.21.co

Ready to try out your bitcoin-payable server in the wild? Or simply want to browse and purchase from other bitcoin-enabled servers? Head over to the 21 Developer Community at slack.21.co to join the bitcoin machine-payable marketplace hosted on the 21 peer-to-peer network.