https://www.blunderingcode.com/https://www.blunderingcode.com/favicon.pngBlundering Codehttps://www.blunderingcode.com/Ghost 2.22Fri, 24 May 2019 13:07:58 GMT60A somewhat overlooked way to scale small transfers is probabilistic payments. To pay you ten cents, I can give you a ticket with a 1% chance of paying ten dollars, and it only goes on chain if it pays out.

To make this work, we need a good source of

]]>https://www.blunderingcode.com/fliptip/5c0d55e0afaab400cc3a30f6Sun, 09 Dec 2018 17:52:33 GMTA somewhat overlooked way to scale small transfers is probabilistic payments. To pay you ten cents, I can give you a ticket with a 1% chance of paying ten dollars, and it only goes on chain if it pays out.

To make this work, we need a good source of randomness, and protection against replays. One method is to use block hashes and target particular blocks, though this will require us to record blockhashes in a more persistent way. If we assume users post a "current" hash to a contract, indexed by the hash of their email address, then we can use a hash onion per recipient. The sender signs sha3(receiver, targetHash, randomNumber) where targetHash is the current hash. The receiver takes the preimage of the targetHash, hashes it with the sender's random number, and if the result is below a threshold then he submits the signed message and preimage to the contract and gets paid. The contract sets the preimage as the new "current" hash.

Vitalik posted in 2014 that it's easy to doublespend against something like this, and suggested a large penalty bond, payable if the sender's funds are insufficient upon redemption. We can do without that for some applications, like voluntary tips. In that situation a doublespend isn't necessarily malicious; if the tip has a 1% chance of paying off, the user can reasonably deposit only enough funds to pay off a single tip while sending two concurrently, ignoring the 1/10,000 chance that both pay out.

For spam protection, we can make the doublespend problem go away entirely. Clients can require a probabilistic payment from unknown senders; let's assume a penny per email makes spam unprofitable, and use a 1/1000 chance of getting $10.

A spammer may attempt to get around this by depositing only $10 and sending a million emails referencing that deposit. Naive recipients would have no way to tell.

But there's an easy way to counter this: have the email client attempt to redeem the payment immediately, but wait an hour before showing the unsolicited email to the user. If most recipients do this, the spammer's deposit is likely to go to zero in that hour. In that case, discard the email. This means the only person who reads the email is the one who got paid $10 to do so.

There's no happy medium that helps the spammer. Even if he deposits $10,000, there's an almost 50% chance that too many redemption attempts will succeed; then he reaches only a thousand people, paying $10 for each. To be confident of reaching a large number of people he needs a deposit large enough that it's unlikely to run out. Thus the best he can do is pay an expected penny per email.

Here's some code, using the hash onion method, plus a nonce allowing the users to start a new hash onion. (I called it "fliptip" since it's a tip that flips a coin.)

Basically it's a way to post a bond, such that a doublespend results in the loss of the bond. It detects doublespends by reuse of UTXO inputs. Anyone (presumably miners) can submit the two transactions and collect

]]>https://www.blunderingcode.com/safe-instant-transactions-on-todays-ethereum/5bf02545f1f4fe00ccb6b2b6Sat, 17 Nov 2018 14:28:52 GMTRecently I came across a proposal for safe zero-confirmation transactions on Bitcoin-style chains.

Basically it's a way to post a bond, such that a doublespend results in the loss of the bond. It detects doublespends by reuse of UTXO inputs. Anyone (presumably miners) can submit the two transactions and collect the bond.

We could build this into a Plasma chain, letting the operators collect the bonds. But by tweaking the idea we can do something similar on the main chain today.

Instead of UTXOs, we just look for reuse of the same nonce from the same sender. We can write a contract that accepts two complete signed transactions, checks their senders and nonces, and if they match, awards a bond to msg.sender.

The merchant has to do a few simple checks to accept a zeroconf transaction:

The sender must have adequate funds

The transaction must have the sender's current nonce, not a later one

The sender cannot be a contract, since a multisig wallet could allow a different address to withdraw the funds

The sender must have a deposit in the zeroconf contract, which is larger than the purchase amount

If all of these things are true, the merchant can safely accept a zeroconf payment. The transaction can be faster than a credit card approval if the merchant uses a full node, which can be stripped down to maintain only the necessary state: just the current balance and nonce of all addresses, and all the current zeroconf deposits. Then it's a local lookup to approve the transaction. In a busy shop, this would be much better than waiting for a block, even with Ethereum's fast blocks.

The merchant can monitor for doublespends and attempt to collect bonds, in case the miners fail to do it. But if the miners find it worthwhile, the merchant can simply enjoy fast transactions with low fraud rates and not worry about it.

Implementing the zeroconf contract would be reasonably simple. There are Solidity libraries for RLP but we don't need them; the nonce is the first data field (aside from length indicators) and the signature is at the end. On each transaction check signature and nonce, and if the transactions match, award their signer's bond to msg.sender.

Obviously this doesn't work so easily with signature abstraction, but if the existing transaction format is still supported, the merchant can simply restrict zeroconf approvals to old-style transactions.

]]>A lot of people don't quite get how Bancor works, which isn't surprising because their whitepaper (pdf) doesn't explain it very well. Last year I spent a lot of time figuring it out, and it's really cool. Their implementation leaves a lot to be desired (more on that below) but]]>https://www.blunderingcode.com/how-bancor-works/5b578b8e491c0b00bfac2514Tue, 24 Jul 2018 20:53:51 GMTA lot of people don't quite get how Bancor works, which isn't surprising because their whitepaper (pdf) doesn't explain it very well. Last year I spent a lot of time figuring it out, and it's really cool. Their implementation leaves a lot to be desired (more on that below) but the core idea is beautiful.

A basic Bancor-style contract functions as both an exchange, and a self-balancing ETF. If it contains four tokens, you can exchange those tokens for each other, and you can hold shares in another token representing the whole thing.

Let's call the contract a "basket." This basket is going to hold four assets: Ether, Gold, Silver, and Platinum, in equal-valued proportions.

Each asset has a "reserve ratio," which in this case we're setting to .25 for each. All this means is that Ether represents one quarter of the value of the whole basket, and so do the others.

You can deposit any of these assets into the basket, and get back shares of the basket. You can also redeem shares of the basket, and get back your choice of underlying tokens.

If you hold the basket token, you're invested in all four of the underlying tokens, with an equal dollar amount of each. If you want to exchange gold for silver, you deposit gold, get the basket, deposit the basket, and take out silver. (You could also do this in one step, for convenience, with the same steps underneath.)

The exchange rate depends on how much of each token is deposited. Let's say the basket holds twice as many silver tokens as gold. If you deposit one gold token, you get back two silver tokens.

Setting Prices

But how does this happen? Is there some centralized price feed? No! It happens automatically, because of arbitrage.

Let's say one gold token is really worth three silver tokens, but our basket still has only two silvers for each gold. I can make a profit: deposit two silvers, get one gold, then go on some other exchange and get three silvers.

But look what happened: there's more silver in the basket, and less gold. We're closer to the correct pricing now.

Do you want an ETF that holds equal weightings of ETH, gold, silver, and platinum? Just hold this basket token. Every time the prices change, it will automatically rebalance for you.

The Math

So the ratio before our transaction is different than the ratio afterwards. If we just use the initial ratio for our exchange rate, then using a bunch of little transactions nets me a different amount than one big transaction.

Bancor solves this by saying: for any transaction, let's split it into an infinite number of tiny transactions, one after another, and run them all. This is what calculus is for. They do a little calculus to figure out what the result of that would be, and that's the Bancor formula. (Emin Gün Sirer wrote a critique of Bancor in which he wondered (point 15) why they couldn't use some other formula; well, this is the reason.)

In Bancor's terms, the various tokens held in the basket are "Reserve Tokens," and the tokens issued by the basket contract are "Smart Tokens." For each token there's a "Reserve Ratio," which is normally constant; if the reserve ratio is 0.25, then arbitrage will keep enough of that token to make up 25% of the total value held.

Not that "smart token supply" varies. When you deposit gold, the contract mints new smart tokens for you. When you redeem smart tokens, they're destroyed, and the contract transfers to you the reserve tokens of your choice.

If you trade in some silver to get smart tokens, the number of smart tokens you get is calculated with this formula:

T = S((1 + E/R)ˆF - 1)

If you trade in some smart tokens to get silver, the amount of silver you get is calculated with this formula:

E = R(1 - (1 - T/S)ˆ(1/F))

If you look at the Bancor contracts you'll see some horribly complicated stuff, because you need logarithms and non-integer exponentials to actually work those out. But if we use equal weighting, the formulas are simpler; we just need roots, along with fixed-point muliplication and division. With only two reserve tokens, our formulas are:

T = S(sqrt(1 + E/R) - 1)
E = R(1 - (1 - T/S)ˆ2)

With three reserve tokens we'll use a cube and cube root, and so on.

Slippage

Because of the changing ratios, you always have slippage. You'll get a worse price than the initial ratio in the basket. The bigger your transaction, the worse the slippage.

This is a familiar situation for anyone trading on normal exchanges. The more liquidity on the exchange, the less price slippage you have. On a Bancor basket, the more assets held in the basket, the less slippage you have for a given trade.

This means there's a network effect. For any given asset pair, you want to trade them on the contract holding the largest amount of them.

If we want to launch a new basket, this is a problem for us; we're probably starting out with small amounts. Bancor solves this by talking to projects directly, presumably getting them to contribute lots of tokens and ETH from their ICO stashes. (The projects would get basket tokens in return, so they can always get their tokens and ETH back.)

But we could also do it in a decentralized way: just have people put tokens in an escrow contract, and if we reach a threshold, then launch the basket and award contributors with the appropriate amount of basket tokens.

Front Running

Because of slippage, front running is a serious issue. Let's say silver is slighly overvalued, and I send in a trade of silver for gold. Somebody else sees my transaction, and issues their own with a higher gas price. They trade silver for gold, correcting the price. My transaction goes through, and now there's too much silver and too little gold in the contract; silver is now undervalued. The attacker sends another transaction, correcting the price again, thus profiting in both directions.

To fix this, you put a minimum return on your order. If you're not going to get at least that many tokens back out, your order doesn't go through.

Reserve Ratio Madness

In the above examples, our reserve ratios sum up to one. When that's the case, the total value of the smart token supply is equal to the total value of all the reserve tokens held in the basket.

You can also set the reserve ratios so they sum to less than one. When you do that, you get somewhat ponzi-like economics. The more reserve tokens in the basket, the more valuable the smart tokens relative to the reserve tokens. Now, the value of your basket tokens doesn't just depend on the value of the underlying reserves; it also depends on the popularity of the basket. If a lot of people exit, you lose money. On the other hand, if you're already the biggest, then since you've got the least slippage you'll probably keep collecting assets, and your basket holders will do well.

Bancor's BNT token is a basket that contains nothing but ETH, with the reserve ratio less than one. The more ETH in the basket, the more ETH you have to spend to get a BNT token; conversely, the more ETH you get for redeeming a BNT token.

Bancor includes the BNT token in every basket they set up. Their theory is that by doing this, they'll end up with more and more ETH in the BNT basket, thus boosting the price of BNT due to the low reserve ratio.

For the ICO, Bancor set the reserve ratio in BNT very low. If you had immediately withdrawn ETH from the BNT contract, you would have done well, as long as you were one of the first to withdraw. If everybody tried to withdraw, then the earliest to withdraw would be subsidized by the latest.

But as long as this bank run didn't happen, it looked like BNT was worth more than the underlying ETH, so Bancor could get away with siphoning away some of the contributed ETH. Some of it went to fund Bancor the company, and some went into a reserve fund; if the value of BNT on exchanges went too low, then ETH from the reserve fund got pumped into the BNT contract.

This worked for a while, but it was another arbitrage opportunity. If BNT tokens on the exchange were cheaper than the price floor Bancor was trying to maintain on BNT itself, then buy BNT on the exchange, redeem it in the contract, and get a nice ETH profit, paid for by the reserve fund. It didn't take long for the reserve fund to get emptied.

The Hack

Bancor of course has been in the news lately, because they got hacked. Apparently the reason for the hack was that they lost control of an admin key.

The reason for the admin key: the actual Bancor contracts lets admins change reserve ratios on the fly, or even add and remove tokens. Personally, that doesn't make me want to hold a smart token. It certainly complicates the contracts.

Where do the arb profits come from?

Reddit user _dredge asked a critical question: where do those arbitrage profits come from? At first glance it appears the answer is: basket token holders.

Let's say we have a basket with 2000 Silver worth $10 each, and 1000 Gold worth $20 each. We have 1000 basket tokens.

Now silver goes up to $22.52. In the basket it's still available at the old cheap price, so you see an opportunity for profit: just buy some gold on some other exchange, deposit it to the basket, pull out silver, and sell it for sweet gainz.

The contract gives you 668 silver, subtracted from the 2000 it held. Now the contract has:

1500 gold at $20 = $30,000
1332 silver at $22.52 = $29,996.64

Thus it holds a total value of $59,996.64

But if the basket holders had just been holding the underlying reserve tokens, they would have 2000 silver at $22.52 and 1000 gold at $20, for a total value of $65,040. They would have had $5,043.36 more.

Meanwhile, for your arbitrage you got $15,043.36 in silver, purchased for $10,000 in gold, for a profit of $5,043.36. Your profit is exactly equal to the loss of value for the basket holders.

So you might think that basket holders are much better off holding the underlying reserve tokens directly, and just occasionally rebalancing on regular exchanges.

But wait, there's more!

Suppose after all that happens, silver suddenly goes back down to $10. You have another arb opportunity! This time you'll buy that $10 silver on some other market, sell it for $22.52 (initially) in the basket contract, and take out gold. Let's try it with 668 silver tokens:

Now there's 1000 gold and 2000 silver in the contract, so the basket's silver price is $10 and the basket has its original value of $40,000.

What happened?

When silver went up, basket holders paid traders to rebalance the basket. But when silver went down, the traders still got paid, and the basket holders got all of their money back. Where did the other money come from?

There's a simple answer: it came from silver sellers on other exchanges, who sold their silver for less than they could have gotten by selling to the basket. In general, whoever's selling you tokens at a worse price is paying you to arb; sometimes that's basket holders, sometimes it's external markets.

So it appears the model works after all. Sometimes you're better off holding tokens directly, other times you're better off holding the basket, but neither side has an advantage.

You might think that, if token prices go up over time, then the basket works against you. But remember that what matters here is relative prices. If gold and silver go up by equal percentages, then no rebalancing is necessary, and there's no arb opportunity. If just one token goes up, then you're worse off holding the basket, but if you expect that to happen then you should just hold that one token in the first place.

Let's try the other direction

Silver goes to $5. You buy 828 silver at $5 from somewhere else and deposit it:

Now we have 2828 silver at $5 = $14140, plus 707 gold worth $14,140, totaling $28,280. But if we'd just held the assets directly we'd still have $20,000 gold plus $10,000 silver. We're short $1,720, equal to the arb profit.

So back the other way, silver to $10, and we'll put that 293 gold back in:

This might seem a little weird. When silver went up from $10 to $20, we lost money compared to direct holders, and got it back on the way down. When silver went down from $10 to $5, we also lost money compared to direct holders, and gained it back on the way up. How did we lose money in both directions?

What's happening here is that a portfolio that starts out equal-weighted and doesn't rebalance has an advantage over the basket contract:

If an asset goes down in price, the basket keeps buying more of it as it goes down. That's a money-losing trade.

If an asset goes up in price, the basket keeps selling more of it as it goes up. We make more more by just hanging on.

But what if we start out with an unbalanced portfolio? Say we had an equal-weighted portfolio with silver at $10, and didn't rebalance when it went down to $5. Now the basket contract has 4000 silver but we only have 2000 silver. When silver doubles in price, we've got less silver to start with, so we make less money than the basket.

The basket will always lose against an equally-weighted portfolio that doesn't rebalance, if we start at the beginning when that portfolio really is equally-weighted. But if we're not rebalancing, then after a while that portfolio won't have equal weights anymore. It might have twice as much silver, half as much, whatever. At that point it might do better or worse than the basket.

The more frequently we rebalance, the more closely we'll approximate the performance of the basket, which rebalances continuously. I think that more frequent rebalancing damps down returns, but also damps down volatility; I'm tempted to dig into this more and see what has the best risk-adjusted performance.

I suspect the answer is good for basket holders, but if not, a way to tweak it is to add a small transaction fee on trades, and hold that fee in the basket to incentivize basket holders. This could even be good for traders, if greater holdings reduce slippage by more than the fee. (Reddit user Eyul mentioned that Bancor has a 0.2% fee on trades, but I don't know the details.)

The future

Bancor keeps making new partnerships, and that's great for BNT holders. If you want your token in their network, you fill out a form, and maybe they set it up for you, if it's not a security token or something else they're not comfortable with.

But if we wanted to, we could make our own basket tokens, and skip BNT entirely. Keep the ratios fixed and equal-weighted, and it's not even that complicated.

As far as I can tell from their interface, Bancor's baskets are just pairs, each with some token plus their ETH-backed BNT. They're not building bigger, diversified ETFs. We could do that, with any asset mix we like. We could make them for tiny, illiquid tokens, or security tokens that exchanges and Bancor won't touch. It's not only a nice alternative to regular decentralized exchanges, it's a neat way to hold a portfolio.

And I'll say this for Bancor: they don't seem to mind. I've talked with them, while implementing a stripped-down version of their system for a client, and they were totally cool with it.

What I love about all this is that it's an entirely new kind of financial instrument, and a new way to trade assets, and the whole thing only takes a few pages of Solidity. Imagine how difficult it would be to launch something like this in the legacy financial world.

I'll likely post some code in a future article.

]]>Everybody's up in arms about Parity's proposal to fork the whole blockchain so they get back the money they dropped. Let's say for the sake of argument that we don't fork. What else could we do to help?

An interesting feature of this situation is that the most sophisticated players

]]>https://www.blunderingcode.com/baby-spoon/5adb5a9b583fb10022113089Sun, 22 Apr 2018 22:36:41 GMTEverybody's up in arms about Parity's proposal to fork the whole blockchain so they get back the money they dropped. Let's say for the sake of argument that we don't fork. What else could we do to help?

An interesting feature of this situation is that the most sophisticated players had the biggest losses, and are most able to recover.

The biggest loss is to Parity's Web3 Foundation. Web3's main project is Polkadot, and Parity said they have enough money left to continue developing it without any great difficulty; if that money is still held as ETH, then the gains since the hack leave them even stronger.

Web3 had planned to use a chunk of the lost funds to fund projects like Swarm and Whisper. Shortly after the hack I checked with the Swarm community; the people I talked with weren't official, but for what it's worth they didn't know about the donations on the way from Web3, and said they had plenty of funding from Ethereum Foundation and Status, had just hired more people, and were full steam ahead. I'm sure the Web3 money would help but Swarm at least seems to be doing fine.

Next in line are the ICOs, which generally hire professionals to write and audit their contracts. These are people who would have known that the Parity multisig had recently been hacked, and could have checked and seen that the latest version of the multisig still had no public audit. These projects may also be able to recover; they have demonstrated some fundraising capability already and, probably in some cases at least, could do it again by expanding their token supply (even if that means replacing their contracts). Their current holders will eat some dilution but may prefer that to the project going broke. (Polkadot could do something like this too, of course, and there are some other interesting ideas at r/FriendsOfParity, like this).

The real victims

The real victims here are the innocent noobs who just downloaded the Parity client and used its built-in features, and ended up losing money when the fancy multisig froze up on them. Can we do anything for them?

I'm thinking this is a lot less money, and maybe we can cover a lot of it with donations. Not that this is anyone's moral obligation or anything, but maybe some people would feel like pitching in.

The people who lost the least are probably the least sophisticated, and the easiest to make whole. So we could make a simple contract that pays them first. Just send ETH to the contract, and it forwards to the victims, starting with the smallest and working its way up.

Normally I would hold the ETH in the contract, and have people withdraw their balances. But in this case, we'll have a whitelist of known recipients. It seems best to skip the withdraw pattern and just immediately transfer the funds instead of holding them.

When building the whitelist, we'll need the owners of these multisigs to tell us what addresses should receive the funds; we can't just pick one of the owners and call it good. We can require the recipients to be either external addresses or known good multisigs, and set up everything off chain.

A large donation might span several small recipients, so we may need to loop a bit. Due to gas limits we can't do much of that. In this code I limit it to five loops and refund whatever's left to the sender.

So with those assumptions in mind, here's a stab at a contract. So far it's barely tested, and not audited at all. At this point it's just a rough idea.

There'd have to be a fair amount of community agreement to actually do this. It'd be unfortunate if, say, several competing donation contracts were in use at the same time, or if one were used and then a hard fork happened after all.

And of course the list of recipients would have to be very carefully reviewed by the community. The list in my sample code is obviously made up.

]]>I just read The Divide by Matt Taibbi. Among many other horrors, he describes in chapter eight the collections process on delinquent credit cards, focusing in particular on abuses revealed by a whistleblower at Chase.

Banks looking to raise quick cash will often sell delinquent accounts to a company that

]]>https://www.blunderingcode.com/ethereum-credit-cards/5a848244b5d28500188c835dTue, 03 Jan 2017 03:03:55 GMTI just read The Divide by Matt Taibbi. Among many other horrors, he describes in chapter eight the collections process on delinquent credit cards, focusing in particular on abuses revealed by a whistleblower at Chase.

Banks looking to raise quick cash will often sell delinquent accounts to a company that will attempt to collect. The buyer wants accounts with actual judgements against them, meaning the bank took the borrower to court and a judge said the money was actually owed. The whistleblower found that many of the "judgements" sold by Chase were not actually valid. In some cases the cardholders weren't even delinquent. In others, Chase actually owed the cardholders.

Of the valid judgements, many were never contested by the cardholder, because they never knew they were being taken to court. As you've seen in the movies, you're supposed to be "served." The banks were serving people by, for example, sending postcards to old addresses. They pay bulk rates to companies that do the crappiest job they can get away with, because if banks had to actually pay lawyers to take every debtor to court, credit cards wouldn't be a profitable business. It's better for the banks if debtors never show up. In some cases, the process servers even throw away the summonses they're supposed to serve, but swear that they properly served the debtor.

Debtors who don't show up to court lose by "default judgement." If they get the summons, they often just assume the bank is correct and pay the supposed balance. If they show up in court, they often don't bring evidence.

But if they actually contest the case, the bank has to dig up old documents; or, if the bank has already sold the debt, the collector is in trouble, because the banks intentionally don't include all the documentation. If the collector needs more paperwork, the bank sells it to them. Often at this point the collector will simply drop the case.

But it seldom gets that far. According to Taibbi, "the bulk of the credit card collection business is conducted without any supporting documentation showing up or being seen by human eyes at any part of the process....in the overwhelmed modern court system, simply attesting to having the right documentation works just as well as really having it."

According to one judge, "On a regular basis this court encounters defendants being sued on the same debt by more than one creditor alleging it is the assignee of the original credit card obligation."

Once there's a real judgement, collectors can do just about anything: attach salaries, put liens on property, or even confiscate cars and furniture. Some people don't even know they have a judgemnt against them, until they try to sell their house.

Fixing This

To anyone familiar with blockchains, all this has to seem completely insane. We have immutable public records now. We don't have to put up with this nonsense.

Put credit cards in a smart contract. Pay out loans through the contract, and take payments through it. Anyone can check and see whether payments are due. Put a nice UI on it and a judge can just check all the records on a laptop. We ensure accuracy, but we also make court less expensive.

Of course, we can't put people's names, birthdates, and SSNs on the blockchain. Instead, the bank puts that stuff plus a random salt in an identity document, and hashes it. The hash goes on chain. To take a borrower to court, the bank reveals the preimage in closed session; the court checks that it matches the hash, and takes that as evidence that the account matches the real-world identity.

The bank would also need to produce the original paper application, signed by the borrower, giving the bank the right to collect. If the preimage doesn't match this document, the debt is invalid. The borrower could write is Ethereum address on the application, using a BIP39 list of words. Alternatively, the borrower could import the identity hash into an app, and associate it with an address by sending the hash to the lender contract.

We can add events for summonses and judgments, publishing hashes of documents hosted on Swarm. As long as the borrower is still monitoring the contract, he'll be informed of legal actions.

There's an interesting side effect of all this. To avoid losing money, the lender has to do sufficient identify verification of borrowers. This means any address in the Lender contract can be generally trusted to have some kind of real-world identity. You can even get a rough estimate of the lender's confidence, by looking at the credit limit. It's not impossible for someone to have more than one account with the lender, but the lender is probably going to limit that too. They could have accounts with multiple lenders, but the lenders have an incentive to share identity documents so they can see how much debt a person has.

I always thought we'd need good identity verification before we can have loans on the blockchain. But actually, by putting loans on the blockchain we can get identities.

Having mostly sybil-proof identities would let us do all sorts of other cool stuff, like voting systems that really give us one vote per person, instead of having to weight votes by account balances all the time.

Purchasing

The above contract just pays money directly to the borrower, who has to initiate a separate transfer to make a purchase. We don't actually need two transfers; we can add a function that lets the user send money directly from the lender contract to a merchant.

We can even add a bytes32 field to this method, so we can integrate with serverless shopping carts. This means we have to change the shopping cart contract in the last post, so it can accept a purchaser address as a parameter, instead of just using msg.sender directly. Otherwise, the "purchaser" will just be the lender contract.

The Future

For now, we aren't at credit card scale, but we might be soon. The first version of sharding is supposed to handle 1,000 to 10,000 transactions per second. VISA only does about 4,000 on a normal day (though an order of magnitude more during holidays).

By the time we actually achieve that level of usage, courts should be more familiar with the concept of evidence on the blockchain, and consumers should be relatively unintimidated by the technology.

To make it all work, we need better privacy on payments. Just because you pay someone with a credit card, doesn't mean you want them to see your credit limit, outstanding balance, and entire payment history. Luckily, better privacy is on the way too.

]]>So far we don't have a convenient shopping cart so merchants can take payment in ether. We could build one the old way: put it on a server, use a database to hold cart data, create a new address to receive each payment, etc. But on Ethereum we don't need]]>https://www.blunderingcode.com/shopping-without-servers/5a848243b5d28500188c835cSun, 01 Jan 2017 22:51:16 GMTSo far we don't have a convenient shopping cart so merchants can take payment in ether. We could build one the old way: put it on a server, use a database to hold cart data, create a new address to receive each payment, etc. But on Ethereum we don't need all that. We don't even need a server.

One way would be to store all the items and quantities in the contract, but that's a bit heavyweight. Worse, we also need shipping data, so we need better privacy for that if nothing else.

So let's hold all that off-chain, in the browser's local storage, using some kind of well-defined data format. When it's time to check out, we take a hash of that data, and post it to the contract along with the total ether cost.

Then, we use some kind of communication channel (like Whisper) to send the cart data to the merchant, who can hash it and check the contract to see that payment was made for that order.

We can also make the merchant prove he received the order, before he can withdraw funds. All we have to do is hash our order like this:

outerhash = sha1(sha1(order))

Post the outerhash to the contract upon making payment. To get the money, the merchant submits sha1(order) to the contract, which calculates the outerhash, checks how much ether was sent with it, and forwards to the merchant. If the merchant doesn't submit the innerhash within, say, one week, then the purchaser can get a refund.

We can have an online store hosted nothing more than a static web page, plus something that takes posted data and forwards it to the merchant (maybe even by email). Once we have Swarm and Whisper fully up and running, we don't need a server at all, and all the merchant needs is a standard client on a laptop.

To save storage, in the payout function we could zero out the payment data. On the other hand, it might be nice if we had some sort of reputation system, and for that we might want to keep the data around.

Efficiency

I saw a post by a large merchant accepting Bitcoin, complaining about a $75 fee on a single transaction. It got so high because he made a single withdraw transaction, with inputs from over a hundred purchases.

I posted that Ethereum eliminates the problem, by using simple account balances instead of UTXOs. Then I realized my store contract destroys that advantage by requiring a separate withdrawal for every purchase.

We don't necessarily have to do it that way. The purchaser will want a receipt, but it doesn't have to be on chain. It can just be messaged directly to the purchaser. That makes the contract really simple:

There's no refund function this way, but if the merchant wants to cheat someone, the original contract doesn't keep him from claiming the money anyway. The original does, however, prove on-chain that the merchant had to have received the order. We don't want a situation where the merchant can claim he didn't get the information he needed to fill the order.

One way to handle it would be to give the buyer a short time to change his mind, if the merchant doesn't send a receipt. A more rigorous approach, which is also simpler, is to send the order to the merchant first. The merchant makes a digital signature on the hash of your order, and sends that back to you. Then you post to the contract the order hash, the merchant's signature, and your ether payment. Here's our new purchase function:

Now the purchaser can't deposit money at all until he gets a receipt back from the merchant. Just by looking at the purchases in the contract we know for sure that the merchant saw them all. But the merchant can still consolidate his payouts.

This does mean the merchant has to be more on top of things; he needs a machine online that can receive messages, sign them, and immediately send the back. But that's the only infrastructure he needs.

Ratings

Good online commerce needs reputations. That's hard on Ethereum without some kind of Sybil-resistant identities; positive ratings can be faked at will by the merchant, who can pay ether to himself from as many addresses as he likes.

Negative ratings are another matter. In social psych experiments, it's turned out that people who've been wronged are willing to pay money to punish the offender, even if they gain no personal advantage in doing so. So we can add a simple complaint function, which lets people burn ether to complain about a merchant. The ether just gets deposited in the contract with no way for anyone to retrieve it.

It's still not perfect; a shady merchant could make a store contract, avoid telling anyone about it, make a bunch of "sales" to himself over time, and eventually appear to be a solid merchant free of complaints. A competitor willing to spend money could pay for lots of complaints. But it's not like reputation systems on the Web are perfect either.

We can make the rating system separate from the cart contract; so we can have several competing reputation schemes. Here's a simple contract that lets you complain about any address on Ethereum:

We might prefer to allow only verified purchasers to make complaints. That makes the complaint system a little less general; it can only complain about addresses which implement the Cart interface. It also means we can let registered purchasers complain without necessarily sending ether (though their complaint won't show as much commitment).

Do we really have to burn the ether? It can't go to charity, because maybe the user wants to donate to the charity anyway, so their complaint shows more emphasis than it really deserves. It has to be a little annoying to spend complaint money, so people only do it when they really mean it.

I haven't noticed that people especially want to donate money to me, so how about I get all the complaint money? Tempting, but then I could make unlimited complaints at zero cost (besides gas). So I think there's no alternative, the complaint funds have to be destroyed, or stranded in the contract forever. (Or maybe I could take just a small percentage. That'd make the complaint process extra annoying, which is perfect! But maybe I shouldn't have an incentive to make contracts that people complain about :)

]]>Let's say we want register copyright for all the new pages on the web, in real time as they're posted. Every article, blog post, and comment. Maybe we're going to store them all in Swarm now. How do we do it?

We could use a contract like this:

contract Registrar

]]>https://www.blunderingcode.com/scaling-copyright/5a848243b5d28500188c835bFri, 30 Dec 2016 02:21:50 GMTLet's say we want register copyright for all the new pages on the web, in real time as they're posted. Every article, blog post, and comment. Maybe we're going to store them all in Swarm now. How do we do it?

That's a little better (though it has the same security flaw). We save about 19K gas. There's nothing to prevent multiple registrations of the same hash but we can do a search and find the oldest. Events barely add to the blockchain size; the transactions are in the blockchain anyway, and if you store an event, all Ethereum does is squish it down into a bloom filter. You can query the bloom filter to see whether the data's there (with some risk of false positives, which are fine), and if the bloom filter says yes, the node just reruns the transactions and calculates the event data from scratch. Indexes add a little but still, it's pretty cheap.

If we want to look up any hashed data and find its owner, that's pretty much the best we can do. Find the oldest event registering the hash and see who claimed it.

But it doesn't really prevent plagiarism. Anyone can get a new hash by altering a single bit in the source file. To check for plagiarism we need some kind of approximate hashing to find near-matches of content. If you download a song and want to see who owns it, you can't just hash it and look it up. You need perceptual hashing to see whether someone else registered similar content.

Since plagiarism is so easy, we're just pretending we can look up the real owner of the content from the hash, using the blockchain alone. We can get even cheaper registrations if we don't pretend. Instead of doing lookups on chain, let the copyright owner (or supposed owner) hang onto the proof. He can present us a document saying "I registered a hash of X on block Y" and we can verify that that's true. That's all the consensus we really need; plagiarism detection can be off-chain.

With that approach, here's our registrar contract:

contract Registrar {}

Seriously, that's it.

If you want to register a copyright, you send a transaction to this contract, with a hash in the transaction data. You could just send sha3(content), but we still have the security flaw mentioned above; namely, anyone could copy your transaction and maybe get theirs in the blockchain first, with themselves as sender. So instead we use this:

sha3(ownerAddress, sha3(content))

Paste the result into the data field of any client, send the transaction. Get back the transaction hash.

Now publish the following on your website, Swarm, whatever:

the transaction hash

the owner address

the content

Anyone can run the content and address through the hashing formula, then look up the transaction hash on the blockchain with this javascript:

the data sent along with the transaction (in this case just the sha3 hash)

Now you've really got minimal registration. You're sending 32 bytes of message data to the network, and you're not even logging it. You're not adding anything to blockchain storage other than the transaction itself.

But...we're still not there yet. We still have one transaction per article. That might be ok when we've got massive sharding and we're doing 100,000 tx/sec but right now, 10 tx/sec is more our speed. We can't copyright all the pages that way.

If you're copyrighting a batch of your own stuff, it's easy. Say you're copyrighting three pages, send this hash in your transaction message:

sha3(signerAddress, sha3(page1), sha3(page2), sha3(page3))

Same process, but with just one transaction, anyone can verify that you registered all three pages. You just have to publish the list of pages

But remember, because the hashed data includes your address, it's ok to publish that hash before it's in the blockchain. It's not actually registered with a timestamp before it's in the chain, but nobody can steal so long as you don't publish the content before it's timestamped.

So you can just publish the outer hash on your website, Swarm, Whisper, whatever. Maybe you've got some friends or collaborators who are doing the same. Any of you can scarf up all these hashes and publish them to the blockchain in one fell swoop.

So Alice publishes a hash:

aliceHash = sha3(aliceAddress, sha3(page1), sha3(page2), sha3(page3))

She just publishes aliceHash, not the data that made it. Now Bob publishes another hash:

Now all three of you are free to reveal how you made your hashes. You could have collectively registered a thousand pages and it all went into a transaction with 32 bytes of msg.data.

Of course, there needs to be some incentive to get people to publish each other's hashes. But as long as they publish on a regular basis, that's free. It's just a tit-for-tat; you scratch my back, I'll scratch yours. Keep track of who posts your hashes, and occasionally post theirs in return. Sometimes do a favor for someone new, and if they return the favor, do it some more. This is pretty much how BitTorrent works.

]]>In a previous article I wrote about various security flaws that can show up in Solidity, with some rules for avoiding them. There's another whole class of vulnerabilities based on manipulating the underlying platform. It can be pretty easy for these to sneak in.

For example, a while back I

]]>https://www.blunderingcode.com/security-beyond-solidity/5a848243b5d28500188c835aWed, 28 Dec 2016 01:29:30 GMTIn a previous article I wrote about various security flaws that can show up in Solidity, with some rules for avoiding them. There's another whole class of vulnerabilities based on manipulating the underlying platform. It can be pretty easy for these to sneak in.

For example, a while back I was sad that so far, if you do offline transactions in MyEtherWallet, you don't get a nice interface for calling contract functions. I came up with something I briefly thought was clever: just make a contract that can be controlled by simple ether sends.

So I made this 2-of-3 multisig wallet. To withdraw funds, send a small amount of ether from one of your addresses; that address becomes the recipient, and the contract will be set up to withdraw a million times as much ether to that recipient. Then do another send from one of the other addresses, and the transfer completes. Here's the horrible code I made:

I posted this abomination on reddit, and people made minor stylistic suggestions. The next day I realized it's completely insecure. It seems like you might be able to keep one key in a convenient but less-secure location, because your funds are locked by the other keys...but in fact, an attacker with just one key can steal all your funds!

All the attacker has to do is monitor network traffic, waiting for you to send ether to this contract using one of the uncompromised keys. Then the attacker can quickly send his own transaction, using the compromised key. If the attacker's transaction gets into the blockchain first, then that key becomes the recipient, and the transaction you sent will authorize the transfer. And since it's the attacker who sets the value, the attacker can take everything.

You could sorta fix this, by canceling the transfer if the second transaction includes any ether. But you wouldn't want to trust your funds to that; if you accidentally send your first transaction with zero ether, you're toast. You could require both keys to send matching ether amounts, so at least an attacker can't steal everything, but that's not exactly ideal either.

You won't find problems like this by calling Solidity functions in the online compiler, or by running unit tests. What happens on the blockchain might be just fine. You have to think about what might happen before the code even runs on the blockchain. You have to assume that attackers can see your transactions before the blockchain does, and issue their own transactions, which may get to the chain before yours.

Copyright Registration

A nifty little idea is to register copyright on the blockchain. Submit a hash and you register yourself as the owner of the hash. At various times I've seen code like this:

Once again, an attacker can take your stuff. He can listen for hashes submitted to the registrar, submit the hash himself, and sometimes his transaction will get in first and he'll own that hash for the rest of time...or at least, for as long as anyone pays attention to this silly contract.

To fix this one, you have to get a little fancier. Don't submit sha3(yourContent), submit sha3(yourAddress, sha3(yourContent)).

Now the attacker can't do any harm. If he repeats step one, he's just saved a hash of a statement giving you ownership. If he takes the innerhash from step two and submits his own transaction making himself the owner, it'll fail because it won't match the hash saved in step one.

Oyente

There's actually a tool that can alert you to problems like this, called Oyente. Here's their github and paper (pdf). It tries to find several other problems too. It's not perfect; when I tested the above contracts, it warned of a time dependency problem in HorribleMultisig, but HorribleRegistrar got through without warnings. If Oyente does throw warnings, it's not that easy to interpret them.

Still, it might find stuff you missed. They recommend using it with docker:

Install:

docker pull hrishioa/oyente

Run:

docker run -it hrishioa/oyente

Get the docker container name you need:

docker ps

(Look in the Names column. An example is "modest_sinoussi")

Copy the contract you want to test into the docker container (ignore wraparound, this is all one line):

Without that second line you won't have the dependencies, so oyente won't run. The last line can be repeated at will to run more tests. If your solidity doesn't compile, oyente will just terminate without output. (When I downloaded it, their image came with solc version 0.4.2, and the latest solc was 0.4.6.)

Finally, to shut the docker container back down, go back to your regular terminal and:

docker stop modest_sinoussi

...or whatever name docker gave you.

]]>Token sales have a quandary: if they don't set a cap, or set a very high cap, then people might go overboard and send way more money than required, even enough to be a global risk like TheDAO. But if a sale sets a low cap, the tokens can sell]]>https://www.blunderingcode.com/fairtokensales/5a848243b5d28500188c8359Thu, 13 Oct 2016 20:44:13 GMTToken sales have a quandary: if they don't set a cap, or set a very high cap, then people might go overboard and send way more money than required, even enough to be a global risk like TheDAO. But if a sale sets a low cap, the tokens can sell out fast and people get locked out.

I think I have a solution. Nobody gets locked out and everyone gets tokens in proportion to their contribution, but the cap can be set as low as desired.

All you do is let people contribute as much as they like, then give refunds in proportion to how much you exceed the cap. E.g. if your cap is $1 million and you collect $2 million, then everybody gets half their contribution back. If you collect $3 million then everyone gets 2/3 back, and so on.

You still might temporarily collect a lot of ether, which isn't ideal. But the contract is simple enough to be thoroughly reviewed and tested. I haven't yet done that for the following code but here's how simple it is:

If you really want to make sure you don't collect excess ether even temporarily, it's possible, but there are tradeoffs. An idea I came up with is to have people just pledge, do the calculations based on the pledges, and let them donate the calculated amount. But then anyone who doesn't follow through can lower the total amount raised, even if there's plenty of excess demand. You can mitigate this a bit by at least checking that pledger addresses have the funds available, and setting the cap a little high to compensate for losses, but an angry whale could still do damage.

Along with a bunch of other interesting ideas, reddit user Dunning_Krugerrands suggested a neat compromise: require a deposit of, say, 5% of the pledge. If someone doesn't follow through before a deadline, they at least lose the deposit. The deposit percentage could be any amount, for whatever balance of risks you prefer.

]]>One downside of cryptocurrencies is their volatility. Businesses accepting crypto tend to immediately exchange it for fiat, to make sure they don't sell their products at a loss. But with smart contracts we have ways to protect against loss.

One way is with subcurrencies backed by real-world assets, like gold

]]>https://www.blunderingcode.com/options-without-price-feeds/5a848243b5d28500188c8358Tue, 04 Oct 2016 18:07:13 GMTOne downside of cryptocurrencies is their volatility. Businesses accepting crypto tend to immediately exchange it for fiat, to make sure they don't sell their products at a loss. But with smart contracts we have ways to protect against loss.

One way is with subcurrencies backed by real-world assets, like gold or fiat. But then you're open to counterparty risk, perhaps due to government shutdown on accusations of money laundering. It happened to e-gold and it took six years for depositors to get their money back.

Another way is with a contract for difference. You want stable value, I want to double my sweet ether gains. We both put $100 worth of ether in a contract, which accepts a price feed we both trust. If the ether value goes up, you can still only withdraw $100 worth, and I get the extra. If the ether price goes down, you still get $100 worth and the extra ether comes out of my stash.

The difficulty with this contract is the need for a trusted price feed. But if our main concern is just protecting the downside for ether holders, instead of making a stable coin for them to use instead, then there's an easier way that doesn't require a price feed at all.

I might create an option contract into which I deposit UNI. I set a price in ETH at which I'm willing to sell that UNI to you, at any time before the expiration. In exchange for the right to buy my UNI for that much ETH, you pay me the option price up front.

Let's pretend that 1 UNI is worth 4 ETH. You deposit 10 UNI, worth 40 ETH, and sell me the right to buy it for 50 ETH. In exchange for that you charge me 5 ETH.

As long as ETH stays valuable enough so it takes less than 50 ETH to buy your 10 UNI, nothing happens. You just collect an extra 5 ETH.

But if the value of ETH drops, so the same 10 UNI is worth 60 ETH, then I can exercise the option and buy your 10 UNI for only 50 ETH. My loss is 15 ETH instead of 20 ETH, since my effective price is 10 ETH plus the 5 ETH I paid for the option. You have a loss of 5 ETH, since you're getting only 50 ETH for UNI that's worth 60, but that's partially offset by the 5 I paid up front. We've transferred a loss of 5 ETH from me to you.

This could be considered a call option on UNI, or a put option on ETH...i.e. you could think of yourself as coming out ahead when UNI goes up, or when ETH goes down.

The contract is quite easy to write (though don't use this yet, it's not tested or audited):

We can also go the other direction. I could deposit ETH when I set up the contract, and you could buy an option to sell me UNI for the ETH. In that case, by buying the option you're actually protecting from UNI going down, or conversely, hoping to multiply gains from ETH going up. This contract is even simpler:

Obviously, instead of using two-party contracts we could make a contract that handles lots of options, buyers, and sellers. There's more than one way to approach that; I might post more on it later.

]]>Gambling on a blockchain has one big UI problem: it's too slow. If you have to wait for the next block, it's boring.

SatoshiDice fixed that by using Bitcoin's UTXO model. You sent a transaction to the SatoshiDice address, and if you won it sent back a transaction that gave

]]>https://www.blunderingcode.com/gamble-channels-fast-verifiable-off-chain-gambling/5a848243b5d28500188c8357Tue, 04 Oct 2016 17:18:19 GMTGambling on a blockchain has one big UI problem: it's too slow. If you have to wait for the next block, it's boring.

SatoshiDice fixed that by using Bitcoin's UTXO model. You sent a transaction to the SatoshiDice address, and if you won it sent back a transaction that gave you your winnings. That was safe for SatoshiDice to do, since the payout transaction wasn't valid without your bet transaction. You got instant results.

SatoshiDice wasn't perfect. It was a centralized service, you had to trust it to generate fair random numbers (though you could check its historical win rate), it had a house edge, and every bet had to go on the blockchain. Despite all this it was hugely popular for a while.

But what if we could fix those problems? Instant gambling, between any two people, with verifiable fairness and no house edge at all? What if we could do all our bets off-chain until we're ready to cash out?

The solution is state channels. They're like the payment channels I described in the Lightning post, but track arbitrary state.

Signatures

Just like with payment channels, we sign data offline, like this:

web3.eth.sign(address, dataToSign);

A solidity contract can verify a signature like this:

address signer = ecrecover(sha3(data), v, r, s);

In a simple payment channel, we just keep sending the recipient signed data with a transfer amount, with a slightly bigger total each time, with a contract that only allows a single redemption. The recipient gets the most money by sending the latest one to the contract.

We did pretty much the same thing with the duplex channels in our Lightning implementation, and with blind auctions.

But for a game, we can't rely on users having a built-in economic incentive to submit the most recent transaction. Instead, we'll need to increment a nonce with each step of gameplay. Each player only accepts transactions that properly increment the nonce. When closing the channel, the contract accepts the submitted state with the highest nonce; either player can submit, and the other player has an opportunity to submit a state with a higher nonce.

Using a nonce gets a little tricky in a duplex payment channel, where each party can send transactions at any time. But in a game, we can enforce a particular sequence of moves. For a basic gamble channel, we'll have the two players simply take turns.

State

Since the players take turns, we have a simple way to handle arbitrary state. Just have each player sign a statement which includes:

The current state, including the current nonce n

The other player's signature over the previous state, including the nonce n-1.

Players don't sign without a valid transition. A player closing the channel can submit his own signed statement, and the signed statement he most recently received from his opponent; the contract can verify that both players agreed on the n-1 state, and that the transition from n-1 to n was a valid transition.

Random Numbers

Random numbers are famously tricky for Ethereum gambling contracts. If all our bets were on-chain we could use block hashes to get our random numbers. We'd be vulnerable to miner manipulation, but it'd work ok if our bets were small. Another option is BTCRelay, which pulls random numbers from Bitcoin block headers, but those show up only every ten minutes or so. Or we could trust a random source from Oraclize, but those can be manipulated too; a miner could just get lots of random numbers from them and discard the ones he doesn't like.

But here's the trick that makes Gamble Channels possible:

When two players start a game, each generates a chain of, say, 10,000 sha3 hashes. Each is the hash of the previous hash, all the way back to an initial random number.

Players initiate the game by sending each other the final hash in their chains.

They place their bets, then send the preimage of the current hash. Each player verifies that the preimage hashes to the current hash. The two preimages are XOR'd together, and there's your random number.

If a player runs out of hashes, the channel has to close. But a chain of 10,000 hashes takes less than a second to make, only 320K to store, and at 2 seconds per round is good for over five hours of play.

A Basic Gamble Channel

The game is simple: each generated random number pays Alice if it's below the median, and Bob if it's above the median. Players start by generating a random number and a sequence of hashes on top, depositing funds, and agreeing on a standard bet size.

Here's a rough draft of the contract. This version only handles two players; every new game will have to start by publishing a new contract. This isn't tested or audited and may well have security issues.

Instead of making a new contract for every game, it might be nice to have a single contract hosting lots of games. Of course that means we have to make sure that a hacker can't withdraw ether from games other than his own!

Just flipping a coin might get boring after a while. More complex games might be more fun. Dice games, roulette, or blackjack are all possibilities. For blackjack, eliminate card counting by just pretending we have an infinite number of decks, so the odds of any particular card coming up don't vary depending on what's already turned up. (Casinos already try to approximate this by using at least six decks.)

Poker is a hard problem. It's difficult to deal a card secretly to Alice, and make sure Bob doesn't get the same card without revealing to Bob that Alice has it. The wikipedia entry on mental poker has more information. But we could manage other games with hidden information.

]]>Right now the big idea for scaling Bitcoin is the Lightning network, which lets people do most of their transactions off-chain and only occasionally settle the balances on the actual blockchain. Like the vault I described earlier, it turns out to be way easier on Ethereum.

The basic idea is

]]>https://www.blunderingcode.com/a-lightning-network-in-two-pages-of-solidity/5a848243b5d28500188c8356Tue, 19 Jul 2016 19:15:59 GMTRight now the big idea for scaling Bitcoin is the Lightning network, which lets people do most of their transactions off-chain and only occasionally settle the balances on the actual blockchain. Like the vault I described earlier, it turns out to be way easier on Ethereum.

The basic idea is called a payment channel. Let's say Alice wants to make a lot of payments to Bob, without paying gas fees for every transaction. She sets up a contract and deposits some ether. For each payment, she sends Bob a signed message, saying "I agree to give $X to Bob." At any time, Bob can post one of Alice's message to the contract, which will check the signature and send Bob the money.

The trick is, Bob can only do this once. After he does it, the contract remembers it's done, and refunds the remaining money to Alice. So Alice can send Bob a series of messages, each with a higher payment. If she's already sent Bob a message that pays 10 ether, she can pay him another ether by sending a message that pays 11 ether.

We can also add an expiration date, after which Alice can retrieve any money she deposited that's not already paid out. Until then, her funds are locked. Before the deadline, Bob is perfectly safe keeping everything offline. He just has to check the balance and deadline, and be sure to post the message with the highest value before the deadline expires.

There's sample code at a project on github. This version uses Whisper, which is Ethereum's built-in messaging system. That's basically working but not enabled by default, so it's not quite fully usable. But any communications channel can work. In fact, this sample was made by EtherAPIs, which plans to use similar code to let people send micropayments over HTTP for API calls.

The actual smart contract code is here. I've excerpted the part with the magic, and simplified it slightly:

The verify function starts by taking a hash of the channel id, recipient, and value. The sha3 function can take any number of parameters, and it'll just mash them together and hash it all:

sha3(channel, recipient, value)

To verify the signature we use the ecrecover function, which takes a hash and the signature (v, r, s), and returns the address that produced that signature. We just check that to make sure the signature was made by the channel owner:

ch.owner == ecrecover(sha3(channel, recipient, value), v, r, s);

Make sure the channel is still active and the deadline hasn't passed, and we're done verifying. The claim function first calls verify, and if that returns true, sends the money to Bob and sets channel.valid to false so Bob can't make withdraw any more funds.

If Alice overdraws her funds, it's up to Bob to stop accepting her payments. In case he screws up, we check for that; if funds are overdrawn we reduce the payment to what's available in the channel.

A unidirectional channel like this works a lot like the blind auction. Only Bob is allowed to call claim(), and his incentive is to claim the most money he can, which is exactly what we want to happen.

Duplex channels

Suppose Alice and Bob want to make frequent small payments to each other. They could use two channels, but that means closing out each channel when it runs out of funds, even if their net balances haven't changed much. It'd be better if we had duplex channels, where payments flow both directions.

One method is for one party to submit the current state (i.e. balances for both parties), and allow time for the other party to submit a more recent state. This works for any sort of state channel, but it gets a little complicated. We have to include a nonce that increments with each message; what if Alice and Bob send messages to each other at the same time?

For simple value transfers there's an easier way. Instead of including a net balance, have messages just add to the total funds sent so far by the message sender. The contract figures net balances when the channel closes. This keeps us from having to worry about message ordering. We can trust both parties to send their most recent receipt, since that will be the one that pays them the most.

To calculate the net payment to Alice, we take Alice's balance, add Alice's total receivable, and subtract Bob's total receivable. It's ok if the receivables exceed the balances, it just means the money's gone back and forth a lot. As before, we adjust receivables downward if someone overdraws.

To make this work we remove the immediate ether transfer from the claim function, and let each party withdraw after both claims are submitted. If one party doesn't submit a claim before the deadline, we assume they received no money. An attacker could attempt to spam the network to prevent the other party from submitting its receipt; to mitigate this we'll need to make sure the channel stays open for some minimum time period after the first claim.

A network of channels

But Lightning is more than two-party payment channels. It'd be pretty hard on cash flow if you had to deposit a bunch of money in a payment channel for everyone you might want to pay a few times. Lightning is supposed to let you route payments through intermediaries. With a network of payment channels, you can route your payment anywhere you want it to go, as long as you can find a path through the network to your payee.

The Lightning paper (pdf) is hard to understand in detail if you don't know Bitcoin opcodes, which I don't. But recently I found a wonderful little article that described the basic concept, which is really quite simple and elegant, and realized it's easy to implement on Ethereum.

Let's say Alice wants to pay 10 ether to Carol. She doesn't have a channel to Carol but she does have a channel to Bob, who has a channel to Carol. So the payment needs to flow from Alice to Bob to Carol.

Carol makes a random number, which we'll call Secret, and hashes it to make HashedSecret. She gives HashedSecret to Alice.

Alice sends a message to Bob, which is just like the two-party payment channel message, but adds the HashedSecret. To claim the money, Bob has to submit this message to the contract along with the matching Secret. He has to get that secret from Carol.

So he sends a similar message to Carol, with the same payment value minus his service fee. Service fees don't have to be implemented in the contract; each node just sends a slightly smaller payment to the next node.

Carol of course already has the Secret, so she can immediately claim her funds from Bob. If she does, then Bob will see the Secret on the blockchain, and be able to claim his funds from Alice.

But instead of doing that, she can just send the Secret to Bob. Now Bob can retrieve his money from Alice, even if Carol never touches the blockchain again.

So at this point:

Carol is able to claim funds from Bob by submitting his signed statement and the matching secret.

Bob has the secret too, so he's able to claim his money from Alice

Bob sends the secret to Alice so she has verification that Carol got the payment

As we make new payments, we do the same as two-party channels, just updating the total. This means the recipient only has to keep the most recent secret.

To make all this work, all we have to do is slightly modify our verify and claim functions:

Now the signature is over the sha3 of the channel, recipient, hashedSecret, and value. And we're passing in the secret, and verifying that it hashes to what's in the signature.

Early Shutdown

Imagine that Alice want to pay Dave, and routes the payment through Bob and then Carol. So this is payment ABCD. Let's say this is the first payment in the BC channel, so Bob's total accumulated payment balance to Carol is just the ABCD amount. But Dave never reveals the secret.

Now Eddie wants to pay Fred, also through Bob and Carol, making payment EBCF.

To process EBCF, Bob has to add Eddie's payment amount on top of Carol's, so the total accumulated payment on BC is ABCD + EBCF. But Carol can redeem that balance with just the secret from Fred.

Bob can use Fred's secret to claim the money from Eddie. But without Dave's secret, he can't claim the money from Alice, so he eats a loss in the amount of the ABCD payment.

So Bob has to avoid putting new payments on the BC channel while there's an unrevealed secret. (It's tempting to think he could issue EBCF with a total that assumes ABCD didn't exist, but what if the secret's revealed later?)

This means we should let nodes shut down their channels early, so they can restart if they stall. Over time, people will settle on reliable partners.

This also means that channels are completely synchronous, which isn't ideal for a scalability solution. Fast webservers don't process one request at a time; they can accept lots of requests and send each response whenever it's ready. But a Lightning channel has to go through a complete request-response before it can accept another request. I think this is also the case with Bitcoin's Lightning. Still, compared to putting every transaction on chain, we can do pretty well.

Maybe these synchronous channels help avoid centralization. Since each channel has limited throughput, users are better off routing through low-traffic channels.

Routing

Speaking of routing, it's really easy because we can do it all locally on the client. All the channels are set up on chain, so the client can just read them all into memory and use whatever routing algorithm it likes. Then it can send the complete route in the off-chain message. This also lets the sender figure out the total transaction fees that will be charged by all the intermediaries.

To make this easy, we can just use events to log each new channel. The javascript API can query up to three indexed properties, so we index on the two endpoint addresses and the expiration. We'll also log the off-chain contact info for each address; it could be http, email, whatever. The javascript queries the channels, asks the endpoints how much funds they have available, and constructs a route.

The Contract

As far as I know, what I've described pretty much does what Lightning does, and we can implement it with a contract that's two pages long. We'll need client code to handle the routing and messaging, but the on-chain infrastructure is really simple and works without any changes to Ethereum. Here's some totally untested code for the whole contract.

The code above does everything with ether. But it wouldn't be hard to extend it to use other tokens. Set the token address when creating a channel, change the deposit and withdraw functions, and you're done.

Further reading

The Raiden Network is a well-known implementation of a lightning-style network on Ethereum. Its Solidity code is significantly more complicated; compared to Sparky, it uses ERC20 tokens instead of ether, has a different settlement mechanism, and uses some assembly for performance optimization. The project includes all the off-chain infrastructure too.

Here's an article about payment channel networks on Ethereum and Bitcoin, with some interesting ideas.

]]>The solidity docs have one way to make blind auctions: everybody submits a hash of their bid, and when the auction's over the bidders reveal the preimages of their hashes to show their bids.

But a blind auction doesn't really need to reveal all the bids. Everybody can just privately

]]>https://www.blunderingcode.com/blind-auctions/5a848243b5d28500188c8355Mon, 11 Jul 2016 23:44:06 GMTThe solidity docs have one way to make blind auctions: everybody submits a hash of their bid, and when the auction's over the bidders reveal the preimages of their hashes to show their bids.

But a blind auction doesn't really need to reveal all the bids. Everybody can just privately send their bids to the auctioneer. The auctioneer's incentive is to publish the highest bid, which is exactly what we want.

So everybody starts out by putting up a deposit, sends their signed messages to the auctioneer, and when the time's up the auctioneer picks a bid to post to the contract, which verifies the bidder's signature and pays the auctioneer.

The Solidity code to verify a signature is pretty simple:

address bidder = ecrecover(sha3(bidvalue), v, r, s);

You can put as many items as you want in the inner section (where bidvalue is), delimited by commas. Take the hash of that, and pass into ecrecover along with v, r, and s, which together make up the digital signature. Then if the signature is valid, ecrecover returns the address that made it.

This gives you a string containing v,r,s which you can send to the auctioneer, who parses it out as documented here. The signing address has to be unlocked, but since you're sending the signature off-chain anyway, you can do it from an offline computer.

Climate change is a public goods problem, which is generally thought near-impossible to solve on a purely voluntary

]]>https://www.blunderingcode.com/climatecoin/5a848243b5d28500188c8354Mon, 11 Jul 2016 14:17:47 GMTMIT's Center for Collective Intelligence has a project called ClimateColab, which attempts to crowdsource solutions to climate change via an annual contest. I just made finalist with a proposal I call Climatecoin.

Climate change is a public goods problem, which is generally thought near-impossible to solve on a purely voluntary basis. But here's another public good, which we do provide at large scale on a purely voluntary basis: cryptocurrency consensus. Satoshi figured out he could pay for all the required work by inflating the money supply.

So my basic idea is to make a currency on Ethereum which is "mined" by offsetting carbon. There are already organizations that let you pay for voluntary carbon offsets, with third-party auditing and certification. We simply get them to publish addresses for ether donations, and mint new coins to anyone who donates ether to the offsetters via our contract. Then, like any coin, we encourage merchants to accept them as payment, starting with the sort of merchants interested in showing off their "green" credentials.

The offsetters set an ether price per ton of carbon, and we mint a certain number of coins per ton. We also give the donor a certain number of votes per ton, and store the total number of actual tons carbon the donor has offset. (The donor can use the tonnage number for "bragging rights," which in itself helps a bit for solving public goods problems.)

Since the sooner you reduce carbon, the more effective it is, we have the coins per ton decrease over time. This also means early donors get more reward, which is good for speculative value. And exponential decay seems appropriate, but I don't think it has to be exact; one way to approximate it with cheap gas costs is an linear interpolation between each halving of the reward. Something like this:

A tricky part is maintaining the list of approved offsetters. A central adminstrator could do it, but that'd require a lot of trust; a corrupt adminstrator could approve his own address and mint climatecoins for free. A set of admins in a multisig, if they're well-trusted climate experts, might be viable.

But can we decentralize the decision? This is a tricky problem; it's similar to the problem of making a friendly AI with a stable goal system; i.e. if we make a superintelligent AI and give it a value system that makes it want to keep humans happy, but it's able to modify its own value system, how do we know it will keep placing a high value on human happiness?

One answer is just to observe that if you were able to modify your own brain to turn yourself into a serial killer, you probably wouldn't do that, because under your current value system you don't like the idea of being a serial killer. Similarly, in Climatecoin if we start with a set of voters who place a high value on a healthy climate, then we can have some confidence that they'll keep voting accordingly.

To seed our climate-friendly voters we can use admins at first, who select reputable offsetters, and award votes based on the number of actual tons carbon people pay to offset. The voters presumably include lots of people who care enough about the climate to bother offsetting (although there's also some purely speculative interest). Once there's enough accumulated tonnage to prevent cheap attack, turn it over to the voters.

It might be a good idea to weight recent offsets more heavily. An easy method is to simply increase votesPerTon over time, the same way we decrease coinsPerTon. Unlike coins, the votes are not transferable; decisions are made by people who actually offset carbon. With luck, though our collective intelligence will have the ability to change its value system, it won't want to; it'll be like a stable-value FriendlyAI.

In the following code, an offsetter's status can change when a quorum votes with a 2/3 majority.

We probably want the users to be able to change their votes. To do that we'll need to store the vote per user, so we can see how many votes to remove when we store the new vote.

We have a couple backstops in case voting fails to maintain legitimate offsetters. For one, donors can choose the offsetter when they donate; this helps but doesn't completely defend the overall legitimacy of Climatecoin. For extreme cases, another option is to fork the contract. Simply copy all the data to a new contract, but remove the bad offsetters and the voting power of everyone who voted for them. Then the market can determine which is more valuable. If Climatecoin is used by merchants to signal their "green credentials," the merchants are likely to switch to the more reputable fork.

It would be nice if a purely voluntary solution like this could completely solve climate change. Unfortunately, it would have to be absurdly successful to accomplish that. Even if Climatecoin attained a market cap of $1 trillion, and inflated 10% per year, it would only be spending $100 billion annually on carbon offsets. Carbon offsets are currently selling at $12 per ton CO2, so that'd be under 10 billion tons offset. Our current emissions are over 30 billion tons annually. And that price is on the low side because of low demand in the voluntary market. At scale, the cost could be significantly higher (depending on what sort of innovations people come up with). The offsets which are least vulnerable to manipulation are those that directly absorb CO2 from the atmosphere in measurable ways; at least some of those are relatively expensive.

But if, someday, government imposes a price on emissions, it may sometimes be more economical to offset the carbon you emit instead of paying the fee. To encourage this, the government could let you pay with climatecoins, which it burns, awarding you a tonnage credit based on the current coinsPerTon. A more direct method is to burn the coins yourself, and just provide a proof that you did it:

This way, we could reach a maximum number of Climatecoins, and only issue new coins when we dip below the maximum because people burned coins. Our total offsets would no longer be limited by inflation.

If we assume this is the endgame, and that its prospect is a major source of climatecoin value, then there's another voting method we could try: let people vote on offsetters by locking up their coins for some period of time, as suggested by /u/avsa for the DAO fork debate, and mentioned by Vitalik for more general use. The more coins and the longer the time, the more weight for the vote. The more reputable the offsetters, the more likely that governments will accept climatecoins; hence people will have more confidence in Climatecoin's long-term value if the offsetters are reputable.

Therefore, we could have users vote by vaulting their coins. We weight the votes and set the offsetter's active bits accordingly. The users' coins are locked only if the vote goes their way.

In this case we can easily let users change their votes; it's automatic whenever they unvault their funds.

This voting system doesn't give any particular weight to people who actually offset carbon, rather than just buying coins on the open market; it simply assumes that reliable offsetters will be thought best for coin value (due to potential government recognition). If we're not confident in that assumption, we could make a hybrid voting system, by changing the calculateVote function to also take the voters' accumulated tonnage into account.

]]>I still see people occasionally asking what smart contracts are good for. All the attention goes to really ambitious projects, but people underestimate the usefulness of a page of code.

For example...here's an article by a Bitcoin researcher, talking about an anti-theft scheme he and his colleagues invented. He

]]>https://www.blunderingcode.com/ether-vaults/5a848243b5d28500188c8353Tue, 05 Jul 2016 23:43:04 GMTI still see people occasionally asking what smart contracts are good for. All the attention goes to really ambitious projects, but people underestimate the usefulness of a page of code.

For example...here's an article by a Bitcoin researcher, talking about an anti-theft scheme he and his colleagues invented. He says it would be "easy" to implement; all it requires is a hard fork of the blockchain, adding a new opcode.

I guess that's easy for some definition of easy. On Ethereum I implemented the same thing in a smart contract.

The basic idea is to have a hot wallet account, plus a contract which holds the bulk of your ether, and stores a vault key and recovery key. Most of the money is vaulted and inaccessible. To unvault some of it, use the vault key. After a delay the vault key can send the money to your hotwallet.

The recovery key can reverse the vault key, putting the ether back in long-term storage. In my version, the recovery key can also change the hotwallet, since the vault key is useless to an attacker who doesn't also have the hotwallet.

If both vault key and recovery key are compromised, the owner and attacker can keep reversing each other, indefinitely. But there's another twist: the recovery key can also lock the ether forever. So if all three of your keys are compromised (hot wallet, vault, recovery), you still lose your ether, but you can at least prevent the attacker from getting it. The idea is that this reduces the incentive to attack in the first place.

Here's the code. (Don't put a large amount of ether in this just yet.)

When you put a modifier on a function, the function body pastes into the _ of the modifier. So, for example, only_vaultkey adds the line "if (msg.sender != vaultkey) throw;" to the beginning of the function.

Events are cheap ways to record information on the blockchain. They're stored in a way that's not accessible to contracts, but can be easily queried by client code. For example, "event Redeem();" declares the Redeem event, then just calling Redeem() actually writes the event to the chain.

It's not a perfect security solution. An attacker with the recovery key could hold your money hostage, saying he'll destroy your ether unless you send him half. At least that requires him to contact you instead of just silently burglarizing your funds. If you generate your recovery key offline and keep it in a safe deposit box, the situation isn't likely to come up.

You might want to make further changes. With the recovery key in a safe deposit box, maybe you'd rather not have the destroy function at all. The point is, it's easy to build whatever solution works for you.

The whole thing took me 20 minutes to write, and a little more to make minor changes in response to reddit comments. One reason it's so much easier than on Bitcoin is that Ethereum scripts are stateful and use account balances instead of Bitcoin's UTXOs. Vitalik wrote an nice article about that, and I was stoked to see he linked my reddit post of this contract as an example (ctrl-f "20").

The reddit version is older; here's I've updated it to follow the rules, changed the UI slightly, and added the "not_destroyed" modifier so people can't send ether to a destroyed vault.