Block chain API design for a “Micropayments channel” with Bitcoin

Block chain API design for a “Micropayments channel” with Bitcoin

Blockchain Companies Applying Distributed Ledger Technology 

Third Key Solutions provides consulting and cryptographic key management solutions for companies using decentralized digital currencies, distributed blockchains and asset-tokens. Chainalysis allows to spot connections between digital identities. The company’s product allows financial institutions to develop trust lines between them as well as identify malicious actors. The company states as its mission to create tools that respect user privacy and prevent abuse of the financial system. Tradle is using a blockchain to bridge internal and external financial networks to achieve user-controlled KYC portability. Open-source mobile framework combined with the business app development and integration platform allow Tradle to build full-stack sophisticated blockchain apps. Vogogo specializes in providing leading verification tools for optimal risk management and payment processing, all from a simple JSON REST API. Elliptic is the world’s first company to secure insurance for blockchain assets. It is also the world’s first company of a type to achieve accreditation from a Big Four audit firm, KPMG. The company offers a real-time AML protection forbitcoinCivic is a blockchain-based identity solution which aims to tackle the problem of consumer identity theft and reducing online identity fraud. The company is a free identity protection platform which is going to be launched in the month of May. Coinalytics enables enterprises to derive real-time intelligence and risk assessment from blockchains and decentralized applications. The platform employs advanced pattern recognition methodologies and real-time online learning to mine pseudonymous data with sparse features. Sig3’s multi-sig technology provides an additional layer of security for bitcoin transactions. Instead of needing only one signature or key to make a transaction, the user can setup a multi-sig wallet that requires the signature from two of three keys before a transaction is finalized and broadcasted to the network. Sig3 is an independent, third-party automated cosigner. As an independent party, Sig3 can be integrated with any multi-sig wallet while keeping an arm’s length from the wallet, ensuring there isn’t a single point of failure. BlockSeer‘s mission is to build a unified foundation of transparency for the public bitcoin ecosystem. By providing transparency of the bitcoin blockchain and its participants, BlockSeer aims to reduce the level of disorder and chaos and increase the level of knowledge and analysis of the publicly accessible blockchain network. CryptoCorp is a security startup focused on improving the bitcoin ecosystem. CryptoCorp offers a security service called the Digital Oracle that can participate in multi-signature transactions originating in any bitcoin wallet. Blockverify offers a blockchain-based, anti-counterfeit solution that can be applied to pharmaceuticals, luxury items, electronics and diamonds. With Blockverify companies can create their own register of products and monitor the supply chains.

And now moving on to the real stuff.....

Introduction

Bitcoin has great potential as a platform for enabling micropayments, payments much smaller than what the traditional financial system can handle. Indeed, you can send a very tiny amount of value in a Bitcoin transaction without doing anything special and it will work, even if what you’re sending is only a fraction of a (dollar) cent. But doing so is subject to a few significant caveats.

  • If you send too many transactions too fast, they will get down-prioritised or not relayed by various anti flooding algorithms built into the Bitcoin network.
  • There is a minimum amount of value a single transaction can send, determined by the number of bytes required to send and claim it along with the fees charged.
  • The recipient of the micropayments ends up with a wallet full of “dust” which can be expensive to spend, fee-wise. This is a rough equivalent of the same problem you’d have with metal coins, if you charged lots of people a penny, repeatedly. You’d end up with a bag full of tiny metal coins that most merchants would refuse to accept as payment, because the overhead of the transaction would be larger than what the money was worth.

Sometimes these restrictions don’t matter - you only wish to make a single, very small payment and the recipient won’t be receiving a lot of them anyway. But other times these restrictions are too limiting and we must search for an alternative approach.

This POC attempts to explain how to use payment channels, a way to set up a pending transfer of value from one wallet to another such that the amount that will be transferred is incrementable at high speed and by very small amounts.

Whilst this does not allow you to send micropayments at high speed to different recipients each time, many applications can fit within this framework - typically anything that involves micro-billing for a metered service.

Protocol overview

 A distributed contract is a method of using Bitcoin to form agreements with people via the block chain. 

https://en.bitcoin.it/wiki/Contract#Example_7:_Rapidly-adjusted_.28micro.29payments_to_a_pre-determined_party

The aforementioned protocol / contract allow one party (the client) to make repeated micropayments to another party (the server). It works in two stages. Firstly, some value is locked up with a multi-signature transaction that places it under the control of both parties. The parties collaborate to create a signed refund transaction that spends all the value back to the client, but is time locked using the nLockTime feature of the Bitcoin protocol. This ensures that the refund won’t become valid until some period of time has passed (currently, one day).

The refund transaction is prepared in such a way that the client gets a fully signed copy before the initial multi-signature transaction (the Contract) is sent to the server. In this way, we avoid a potential crash/attack that could cause the client to lose money - once the client receives the refund transaction, only then is the money locked to both parties control. If the server halts at any point in the protocol, the client can always get their money back.

Once the refund transaction has been obtained by the client, it transmits the multi-signature contract to the server which then signs it and broadcasts it, thus locking in the money and opening the channel. To make a payment the client prepares and signs a new copy of the refund transaction that refunds slightly less money than before. The signature is sent to the server, which then verifies the signature is correct and stores it. The signature uses fairly lax SIGHASH modes so the server has a lot of leeway to modify the refund transaction as it wishes, but normally it will just add an output that sends back to its own wallet.

In this way once the payment channel is established, a micropayment can be made with just one signature operation by the client and one verify by the server.

Eventually the client will decide that it is done. At this point it sends a message to the server asking it to close the channel. The server then signs the final version of the contract with its own key and broadcasts it, resulting in the final state of the channel being confirmed in the block chain. If the server doesn’t co-operate or has vanished before the client gets a chance to cleanly close the channel then the client must wait 24 hours until the initial refund transaction becomes valid.

As you can see, because the refund transaction lets the client take back all its money if the channel is still in use as it approaches the expiry time, the server must close the channel and a new one must be built from scratch.

API Design

The API will provide a series of objects that implement the client and server parts of the above arrangement. The wire protocol uses TCP to send uint-length-prefixed protocol buffers, but the system is designed to be embeddable so you can easily bind micropayments into other protocols, like HTTP or XMPP. At the heart of the API are two state objects, PaymentChannelClientState and PaymentChannelServerState. These classes operate independently of any particular network protocol and provide a state machine in which you’re responsible for providing and retrieving the correct objects at the right times. For example, when calling theincrementPaymentBy method, what you get back is a byte array containing a signature, but the state objects won’t do any transmission of that data for you. Normally though you want to serialize these state machine transitions into byte arrays, ready for network transmission. Also, you want to persist that state machine to disk such that you can resume micropayments across application restarts or network connectivity interruptions. This is implemented by PaymentChannelClient and PaymentChannelServer. These objects take the basic channel parameters and an object that implements a client/server specific interface. They construct the state machines, serialize the transitions to protocol buffer based messages, and use a wallet extension (see third point) to ensure data on the channel is stored inside the wallet file. They also do error checking of the protocol to ensure a malicious client or server can’t do anything strange. The protocol requires certain actions to be taken at certain times, where time is defined by the time fields in the block chain. The StoredPaymentChannel {Client/Server} States act as wallet extensions and watch the block chain to take the right actions at the right times. That means if you drive the state machine classes directly, refund transactions won’t be broadcast at the right time for you and you’ll have to implement that logic yourself. Although getting/providing protocol buffers is a big step up over raw Java objects, it’s still not quite enough as we have to handle reading and writing them to the network. Often the micropayment protocol will be embedded inside another protocol. But if you want it to run standalone (e.g. for testing), we provide 

thePaymentChannelClientConnection and PaymentChannelServerListener classes.

They take host/port pairs and the channel parameters then construct and glue together the rest of the objects. They delegate the actual network handling code to a separate package which simply reads/writes length prefixed protocol buffers over a TCP connection. Although this may seem like a lot of objects, the abstractions have a purpose. Imagine building a protocol that lets you pay for not seeing display ads on the web by making private micropayments to ad networks at the time the ad is going to be served. A separate TCP connection is probably not the right tool to be used here. Instead it would make more sense to extend HTTP with some special headers and link the browser to your wallet app, so the micropayments protocol flows over those inline HTTP headers. In that case you’d want to use the state machine and possibly protobuf serialization, but the network code itself might not be that useful. Going even further, if you’re embedding the protocol into something that already has its own serialization mechanism you might want to reuse the core state machines but avoid protocol buffers entirely. All these use cases are possible.

Server

We select our network parameters, the testnet in this case, and then construct a WalletAppKit which gives us everything we need to do business with Bitcoin. The only unusual thing here is that we subclass the app kit and override one of its methods, addWalletExtensions.

Wallet extensions are a plug-in mechanism that lets you persist arbitrary data inside a custom wallet file (which is basically a large protocol buffer). They are Java objects implementing a specific interface and the payment channels code provides an extension so channel state can be saved automatically. The extension object has to be added to the wallet object before it’s loaded from disk however, to ensure that the saved extension data is deserialized correctly. We do that here by using a hook that WalletAppKit provides for us. All apps that use micropayment channels need to do this.

It’s important to note that the wallet extension takes a PeerGroup as an argument. The reason is so that as a channel approaches its expiry time, the server knows to close it and broadcast the final state before the client has a chance to use its refund transaction. If the server is only running intermittently then it’s possible for it to lose all the money that was accumulated so far, so if your server is transient make sure the operating system wakes it up at the right times! Once we have brought up our connections to the Bitcoin network and synced the chain, we bind and start the server object. We give a timeout that is used for network communications (this is distinct from the max lifetime of the channel, which is currently hard coded). It is given “this” as a parameter - the reason is that thePaymentChannelServerListener class will call us back when a new inbound connection is made. We’re expected to return from that global callback an object that will receive callbacks for that specific connection. So let’s do that.

The interface is simple - we’re informed when a channel is successfully opened, along with a “channel ID” which identifies it in a way independent of the network layer. Once we have the channelId, we can query the wallet extension that we created earlier to get the canonical state object, which we can get more detailed information about the channel from. For most use cases, this is likely not necessary, as the wallet extension deals with channel expiration for you and channel maximum value is not a particularly useful statistic (a minimum is already specified in the server listener constructor, which most clients will default to). After the channelOpen callback, we’re told when we received a new payment, and, finally we’re told when the channel is closed, and why.

Client

On the client side, the first part looks much the same, except in the wallet we add a StoredPaymentChannelClientStates - note Client instead of Server. Next up, we pick some channel parameters and then try to construct a PaymentChannelClientConnection object. This might resume a previous payment channel if we have one available with the same channel ID. The channel ID is just an opaque string that is sent as a hash to the server. In this case we set it to be the hostname, so talking to the same server will always use the same channel even if both sides are restarted or their IP address changes. We then start a loop where we try and construct the channel, but if we don’t have enough money in our wallet yet we wait until we do and then try again.

The waitForSufficientBalance method is simple and not specific to micropayments, but we include it here for completeness:

Once we have a successfully constructed PaymentChannelClientConnection we wait for it to newly open (or resume):

Because it involves some network chatter, this process is asynchronous and we get back a future that lets us know when it’s done or failed. We can of course chain these futures together with others and do all the usual operations on them.

In our onSuccess method we have this:

So we send 1 bit cent every half a second, and then when we’re done we close the channel.

Choosing channel parameters

To build a payment channel you have to choose a few parameters, notably, how much money you should lock up. Note that on the client side you specify a maximum, and then the server requests the actual amount it is willing to accept in a single channel, so there’s no guarantee the total amount the client side specifies will end up in a multi-signature contract. There’s no hard and fast rule around what to pick here, it depends on what your app’s users are willing to tolerate.

Note that the expiry period for channels is currently unconfigurable - it’s always a day.

Amazing article with great detail Nabendu Misra, blockchain is a passion of mine. Can it ever be used for everything, or will it be niche?

Vishal Kumar

Technology, APIs, Cloud, Architecture, Microservices, Security, Management

7y

Nice Article

To view or add a comment, sign in

Insights from the community

Others also viewed

Explore topics