Bonds on Stellar

Setting up this smart contract in Stellar will involve some of the more advanced features of the Stellar protocol. So before you dig in please first read: time bounds on transactions, accounts with multiple signers, and batched operations.


Imagine it is December 2016… Yoyodyne wants to issue a bond to raise money for “research.” It will sell this bond at an auction. The bond will pay $1000 every month for a year. After getting approval from appropriate regulatory bodies, Yoyodyne wisely decides to issue the bond on the Stellar distributed network.

Yoyodyne has a publicly known Stellar account, yoyoAccount with signing key keyA.
To issue the bond, it also creates a new bondAccount.

Yoyodyne adds yoyoKey as a signer on bondAccount. It sets the weight of the bondAccount master key to 0. Now only yoyoKey can sign transactions for bondAccount.

Yoyodyne now creates 12 transactions that look like this:

  • Source Account ID : bondAccount
  • Sequence Number: 1
  • Time Bounds: anytime after 1st Jan 2016
  • Operations: yoyoAccount sends $1000 to bondAccount
  • Source Account ID : bondAccount
  • Sequence Number: 2
  • Time Bounds: anytime after 1st Feb 2016
  • Operations: yoyoAccount sends $1000 to bondAccount
  • Source Account ID : bondAccount
  • Sequence Number: 3
  • Time Bounds: anytime after 1st Mar 2016
  • Operations: yoyoAccount sends $1000 to bondAccount

Yoyodyne signs all these transactions with keyA and makes them publicly available. None of the transactions are valid yet: They need to be signed by bondAccount, and the time bounds haven’t been reached yet.

Now Yoyodyne starts its bond auction. It requests transactions from bidders of the form:

  • AccountID: accountBuyer
  • Operations:
    • bondAccount addSigner(keyBuyer,1)
    • bondAccount addSigner(yoyoKey,0)
    • accountBuyer sends $X to yoyoAccount
  • Signers: keyBuyer

Yoyodyne collects these transactions from people for the duration of the auction. Once the auction is over, it signs the transaction with the highest value of $X and submits it to the Stellar network.

Let’s say Veronica is the highest bidder and buys the bond for $10,000. Yoyodyne receives $10,000 dollars and Veronica is now the only signer on the bondAccount. Veronica also has the transactions that were pre-signed by Yoyodyne. When a coupon date passes, Veronica can add her signature to the appropriate transaction and issue it into the Stellar network.

If Veronica wants to, she can also resell the bond using a similar transaction as above:

  • AccountID: accountBuyer
  • Operations:
    • bondAccount addSigner(keyBuyer,1)
    • bondAccount addSigner(keyVeronica,0)
    • accountBuyer sends $X to accountVeronica
  • Signers: keyBuyer, keyVeronica

Summary

The interesting thing is that bondAccount itself becomes an asset that can be traded between accounts and it will continue to issue the bond interests payments to whatever the current account that owns it is.
It is obviously possible to make more complicated schemes. This should just give you some ideas about what is possible.

My Settlement Victory

February is shaping up to be a winning month for me and Stellar.org. Not only was my birthday last week, we also had two great pieces of news. Poetically, one represents the start of a new exciting chapter and the other the end of a longstanding issue.

First, we announced an integration that will bring free money transfer to 200 villages in Nigeria and reach over 300,000 people. This has the potential to massively impact lives. And it is the first real-world example of the Stellar protocol (or I believe any blockchain technology) being used for humanitarian purposes at scale. This also starts to show what the Stellar network can do and how it will benefit people. We are very excited about the rest of 2016.

This week also sees the end of a longstanding issue. Stellar and I have finally reached a settlement with Ripple in the ongoing dispute between the parties. The settlement shows that Ripple’s claims were entirely baseless. Ripple has conceded in exchange for Stellar and I agreeing to settle the litigation.   

  • Stellar receives all the funds Ripple had inappropriately frozen in Bitstamp, proving all their claims against us were frivolous. When I left Ripple, I agreed to (and Ripple’s lawyer sent an email confirming) sale limitations applied to XRP held by me or in the name of my children. But then Ripple — in direct contradiction of its prior confirmation — claimed sales by other people violated my agreement, and caused Bitstamp to freeze $1 MM that belonged to Stellar. As a result of this settlement, the entire $1 MM was released to Stellar — proving we are correct.    
  • Ripple pays all of Bitstamp legal fees and is responsible for all financial settlement with certain other parties.  This also shows that the entire basis for Ripple’s and Bitstamp’s lawsuit against me was frivolous.
  • I fully complied with the previous agreement but now I have better terms for the amount of XRP I’m able to sell. The new rate is a percent of daily volume. This results in a higher limit given recent trading volume and allows for significant increases in my selling ability as volume increases, something that was not possible before with the prior agreement’s flat dollar limit. To effectuate this, I have escrowed my XRP.
  • I can finally donate 2B of my XRP to charitable causes, something I was unable to do under the prior agreement. This allows me to continue to fund more charities like Give Directly and MIRI which has been something I was actively doing prior to the previous agreement.  
  • As part of this settlement, I finally sold the rest of my Ripple equity. Ripple was required to find a buyer for me at a great price.

The results of this settlement agreement show that I fully complied with the terms of the previous agreement. Personally, I am excited to see the conclusion of these baseless allegations.

The announcement of integration with rural communities and end of the Ripple baseless allegations means that Stellar can continue to move forward on its humanitarian mission unencumbered by Ripple-related legal woes. And I am happy to say Stellar will be using the funds to continue its rural financial access programs. I wish the Ripple community the very best and it is time to refocus all my energies on bringing Stellar to those who need it to change their economic lives.

Bitcoin Magazine: Exploring the Upgraded Stellar Network

Bitcoin Magazine published my guest post on What’s New on the Upgraded Stellar Network:

One of the key principles that facilitated organic growth of the Internet was its low-level simplicity. With this in mind, we designed the upgraded network with complexity moved to the edges. With simple primitives that can be composed in different ways, the system is robust and maintainable, yet still expressive and powerful.

Head over to Bitcoin Magazine to learn more about the Stellar network’s design, the community-run ethos, and what Stellar.org is working on next.

Jed McCaleb Stellar guest post for Bitcoin Magazine

Implementing the Bitcoin Lightning Network on Stellar

I’ve been thinking about how to expand support for smart contracts on Stellar, looking at use cases to learn what we need to make them viable. One of the most compelling things I’ve found is my friends Joseph Poon and Thaddeus Dryja’s smart contract-based proposal for bitcoin. It’s called Lightning Networks.  

Lightning allows you to set up a channel to send transactions securely between two parties, off blockchain. Neither party needs to trust the other—they only go to the blockchain to settle a dispute or to close the channel. Theoretically, any given channel could stay open for years and have millions of transactions flow across it without ever settling to the public ledger.

The two parties involved in the channel exchange pre-signed transactions without introducing them to the network. These transactions vary the fraction of the escrow amount sent to each end of the channel, a setup that is effectively equivalent to sending money between the two ends. Only the latest signed transaction should be valid between the two parties, but the network doesn’t know that—every transaction seems valid to the network. The trick is to set the channel up so that if either party introduces an old transaction, the malfeasor is penalized. Read the Lightning paper for a more thorough description.

A Lightning-like system is possible on Stellar today. Here’s one way you could set it up:

What’s involved

Setting up the channel will involve some of the more advanced features of the Stellar protocol: time bounds on transactions, accounts with multiple signers, and batched operations.  

Accounts

  • A: Account of one participant in the channel, (Alice, Adrian, Arkon, …)
  • B: Account of one participant in the channel, (Bob, Brody, Bevis, …)
  • Escrow: Account that holds the funds moved between A and B and the malfeasor insurance posted by each participant.
  • Helper: Account controlled by A and B that issues the assets needed by the channel. The helper account holds no funds.

Transactions

  • SetupTx: Created and submitted to the network once to establish the channel.
  • CloseTxA & CloseTxB: These txs close the channel and return the correct balance to each participant. Creating a new closeTx is also how the balance between the two participants is changed while the channel is open. An A and B version of the closeTx make it clear who closed the channel.
  • RefundTx: This transaction finishes closing the channel and returns the insurance to the participants if there hasn’t been any bad acting. It can only be introduced a few days after a closeTx to give people time to submit a penaltyTx if there has been cheating.
  • PenaltyTxA & PenaltyTxB: For each pair of closeTx’s, there is a corresponding pair of penaltyTx’s. These transactions are only valid if one participant introduces an old closeTx. This action allows the other participant to introduce the penaltyTx and claim the entire insurance amount held in escrow.  

 

Information to track

Each participant must individually keep track of the following information outside of the Stellar ledger:

  • refundCounter: How many times the refundTx has been bumped.
  • txCounter: How many off-ledger transactions have occurred over this channel.
  • maxCloseTxTime: All closeTxs must be limited to execution before this time, allowing enough time for a penaltyTx to be introduced before the refundTx.
  • current balance between the two parties
  • latest refundTx
  • latest closeTx
  • latest penaltyTx

 

How it works

To make a Lightning-like system work, we use assets in a novel way. They act as a counter, relying on the fact that payment operations (and thus the entire transaction) will fail if the account doesn’t have the necessary funds.

The channel needs 3 assets: `AEND`, `BEND`, and `TIME`. What these assets are used for should become clear below.

To close a channel, either A or B must introduce a closeTx. These closeTx’s send a decreasing amount of either `AEND` or `BEND` to the escrow account. The penaltyTx that corresponds to a given closeTx requires escrow to hold more of the `AEND` or `BEND` then that closeTx sends to escrow. Thus the penaltyTx will only be valid if an old closeTx was introduced.

For example, if A closes the channel correctly:

  • A introduces the current closeTxA.
  • Escrow now holds X `AEND`, where X=(MAX_INT-txCounter).
  • But penaltyTxA needs to send X + 1 `AEND` so it fails and B cannot submit it.

But if A cheats:

  • A introduces an old closeTxA.
  • Escrow now holds Y `AEND`, where Y=(MAX_INT-old_lower_txCounter).
  • penaltyTxA is now valid since Y>X. In other words, escrow does hold enough `AEND` to send back to the helper account.

This logic should become clearer when you look at the actual transactions below.

The `TIME` asset works in a similar way for the refundTx’s.

 

Setup

Assume you have two parties, A and B. They want to create a lightning channel between themselves. A and B agree that the maximum either wants to pay the other is $100. They will each need to escrow $200: $50 for float to pay the other and $150 to post to ensure that neither can cheat.

A and B create, sign, and exchange the first closeTxB, closeTxA, and refundTx defined below. Then they create, sign, and submit the setupTx to the network.

 SetupTx
Source account A
Operations
  1. A creates escrow account
  2. B creates helper account
  3. A sends escrow $200 ($50 for float to pay B. $150 to provide malfeasor insurance.)
  4. B sends escrow $200 ($50 for float to pay A. $150 to provide malfeasor insurance.)
  5. Escrow trusts helper for `AEND` (asset we are using to know when A sends a closeTx out of order)
  6. Escrow trusts helper for `BEND` (asset we are using to know when B sends a closeTx out of order)
  7. Escrow trusts helper for `TIME` (asset we are using to make sure old refundTxs aren’t valid)
  8. Escrow account sets A and B as the only signers
  9. Helper account sets A and B as the only signers
Signers A,B,Escrow,Helper

This transaction sets up the Escrow and Helper accounts and makes it so that any transaction from either requires A and B to sign.

 

RefundTx
Source account Escrow
Sequence number current+1  (so isn’t valid until after some closeTx is submitted)
Time bounds valid between: { now + 1 month, now + 2 months}
Operations
  1. Escrow sends {asset: `TIME`  amount: MAX_INT-refundCounter} to Helper
  2. Escrow sends $150 to A (*refunding the malfeasor insurance*)
  3. Escrow sends $150 to B (*refunding the malfeasor insurance*)
Signers A,B

A makes, signs, and sends the refundTx to B. B signs it and returns it to A. Both A and B hold on to the latest refundTx but don’t submit it to the network until after a closeTx is submitted.

Whenever a new refundTx is created, maxCloseTxTime is set to (now + 1 month – 1 day).

 

CloseTxB
Source account Escrow
Sequence number current
Time bounds valid between: { dawn of time, maxCloseTxTime }
Operations
  1. Escrow sends A  As_fraction_of_$100
  2. Escrow sends B  Bs_fraction_of_$100
  3. Helper sends {asset: `BEND` amount: MAX_INT-txCounter} to Escrow
  4. Helper sends {asset: `TIME`  amount: MAX_INT-refundCounter} to Escrow
Signers A

A creates, signs, and sends the closeTxB to B.

 

CloseTxA
Source account Escrow
Sequence number current
Time bounds valid between: { dawn of time, maxCloseTxTime }
Operations
  1. Escrow sends A  As_fraction_of_$100
  2. Escrow sends B  Bs_fraction_of_$100
  3. Helper sends {asset: `AEND` amount: MAX_INT-txCounter} to Escrow
  4. Helper sends {asset: `TIME`  amount: MAX_INT-refundCounter} to Escrow
Signers B

B creates, signs, and sends the closeTxA to A.

 

PenaltyTxA
Source account Escrow
Sequence number current + 1 (so isn’t valid until after some closeTx is submitted)
Operations
  1. Escrow sends {asset: `AEND` amount: (MAX_INT-txCounter)+1 } to Helper
  2. Escrow sends $300 to B
Signers A

A creates, signs, and sends the penaltyTxA to B.

 

PenaltyTxB
Source account Escrow
Sequence number current + 1 (so isn’t valid until after some closeTx is submitted)
Operations
  1. Escrow sends {asset: `BEND` amount: (MAX_INT-txCounter)+1 } to Helper
  2. Escrow sends $300 to A
Signers B

B creates, signs, and sends the penaltyTxB to A.

 

Process

Anytime A wants to send a transaction, they create and sign a new closeTxB with the updated balance between the two parties. B replies with the corresponding closeTxA and the penaltyTxB. A then sends penaltyTxA and the off-chain transaction is considered complete.

As time inevitably marches forward and gets close to maxCloseTxTime, the parties can increment the refundCounter and generate a new RefundTx. Future closeTx’s will be created with the updated refundCounter and maxCloseTxTime.

 

Scenarios

Happy path

A and B merrily exchange closeTx’s until they no longer want to maintain the channel. At that point, one of them introduces the latest closeTx and then both sign a transaction dividing up the insurance.

 

A cheats and introduces an old closeTxA

Let’s say that at some point there was a closeTx that sent $70 to A and $30 to B, but then A sent $45 to B over the channel. As a result, the current closeTx sends $25 to A and $75 to B.

A might be tempted to introduce the old closeTx. However, if A does that, B can submit the latest PenaltyTxA, which will succeed: Because of the old closeTxA, the escrow account now holds too much `AEND`. A can’t submit the refundTx before B has a chance to submit the penaltyTx. The current refundTx isn’t valid until sometime in the future. Since closeTxA is time-bound, it must have sent the current amount of `TIME` asset to escrow. Thus an old refundTx will fail because escrow doesn’t have enough `TIME` asset to send to helper.

time 0

time 1

time 2

time 3

 

 

 

 

Channel closes but B is a jerk

If the channel was closed correctly but B decides not to sign a transaction dividing up the insurance, A must wait for the pre-signed refund transaction to be valid and then submit it to the network.

 

Note: The channel in this example is for USD, but it could work with any currency or asset. There’s a bit of extra work I left off to ensure that A or B don’t remove their trust of the channel asset, which would prevent the close and refund transactions from working. But it’s possible to set up in a safe way, which I’ll leave as an exercise for the reader. (If the channel is for lumens you don’t have this issue.)

 

Going Further

Setting up a payment channel between two parties is just the first step in creating a full-fledged lightning network. The network becomes even more powerful when you can chain parties together and chain channels between totally different ledgers or blockchains. But more on how to do that later…