Chapter 5. Lighthouse

Mike Hearn was a Bitcoin core developer for over five years and has gained a lot of respect in the community for the work he’s done with BitcoinJ (a Java-based Bitcoin SDK) and his Bitcoin talks worldwide. His latest project is called Lighthouse; it aims to decentralize crowdfunding. Hearn felt that crowdfunding sites like Kickstarter and Indiegogo take too large a cut of project funding for their work in server maintenance, advertising, hosting, and moderation of crowdfunding projects submitted to them. Add on additional payment processing fees like Stripe or Amazon Payments, and up to 10 percent of whatever money you’ve raised is gone. Lighthouse is an attempt to cut out the middleman so that fundraisers can get all of the money their supporters intend to give them.

Furthermore, there are geographic limitations on Kickstarter. On that site, project creation is currently only available to people in North America, New Zealand, and Europe. This means project creation on Kickstarter is impossible for the vast majority of the planet. As a practical matter, jurisdictions that don’t allow crowdfunding can ban sites like Kickstarter because they are IP addressed.

On top of that, there are certain projects that are impossible to create on Kickstarter because of the rules that the site imposes as a central authority in the name of community standards. This is not limited to centralized funding sites: though controversial, decentralized moderation is possible by embedding blacklists into the blockchain via majority or delegated votes by nodes that all nodes must accept.

Allowing for crowdfunding without taking deposits was another motivation because deposits taken in a decentralized app are a very risky proposition. A lot of security issues can arise but theoretically the Bitcoin protocol allows for a middle ground of revocability, and Lighthouse was perhaps the first app to implement a little-known feature in the protocol that allowed for just that.

Lighthouse is a good case study in smart contracts, as well. It probably isn’t considered a killer app, but it is approaching that vicinity of actual utility because you get more money in your pocket as a fundraiser. It also features speedier payments because of how lightweight Bitcoin is compared to other payment processors. The barrier to entry for any fundraiser goes to zero and payments move at the speed of the protocol without requiring the approval of banks in the middle.

Functionality

The easiest way to test out Lighthouse is to just go to the website, and download the binary correlating with your specific operating system. Next, double-click the lighthouse icon to open the introduction page, as shown in Figure 5-1.

Figure 5-1. Lighthouse main page

On the the introduction page, you can choose between creating a project or importing one. There is no app discovery page (we’ll explain why later). You can drag an existing project onto the page and it will show up in its full layout format so that you can add funds to it (Figure 5-2).

Or, you can go ahead and pledge your own amount of money to the project, as depicted in Figure 5-3.

You can add your Bitcoin balance to Lighthouse and fund projects with it. You can get your deposit refunded at any time without risk of losing your money if the project hasn’t reached its goals and the creator hasn’t collected the funds. You can also start your own project and advertise it yourself on social media. Other people will download your project file and fund it themselves.

Figure 5-2. An example of a lighthouse crowdsource fund
Figure 5-3. Create new project

The first thought you might have is how inefficient it is to be forced to import and export project files instead of having a discovery page in the app, kind of like the Mikro app from Chapter 3. Lighthouse’s creator decided to avoid it, simply because it’s too difficult to do. It adds complexity and bugs and he didn’t have enough money or time to do that. Decentralized system development is difficult, and bugs arise that would never come up in centralized systems. Bugs related to UI synchronization and state management are very difficult to debug; for example, “I clicked a button and now I see all pledges twice, and then I restarted the app and now it’s fixed.” UI synchronization bugs happen in Lighthouse despite not even sharing data in a P2P network.

IPFS would’ve been great here, had Hearn known about it. It could’ve been used as a module to share files between nodes. It isn’t as expensive as Bitcoin and it has the speed of BitTorrent, the versioning of Git, and the reliability that comes with having a content-addressed system where data is replicated by everyone who requests it. Even if IPFS wasn’t used, any Kademlia-based DHT would’ve been great, but again we come up against the problem that has historically plagued decentralized software development: lack of funds. An internal currency would help solve this problem, but we can talk about that at the end of the chapter.

Instead, users have the option to utilize a server to transfer files. They can host files on a network of federated servers that run Lighthouse nodes and can store the files. They can use their own personal storage solution like Dropbox or Google Drive and give people links to those files over social media. Most recently, a service called Lightlist has popped up; it acts as a server to host all Lighthouse projects. There will likely be a lot of competition in the space, and this is good because there won’t be one server to rule them all; rather, there will be several options, and that means more decentralization.

An interesting part of Lighthouse is that it uses a Bitcoin feature that has been available since Bitcoin 0.1 but seems to have been entirely overlooked: SIGHASH_ANYONECANPAY. Lighthouse was perhaps the first project to ever implement this feature, which allows users to tag their signatures with an annotation that says it’s OK for other people to take part in this payment. SIGHASH_ANYONECANPAY lets you merge transactions together into one big transaction.

When you sign your Bitcoin transaction with your private key, nothing can be edited. And that’s why it’s safe to broadcast that transaction to everyone on the network, because no one can edit your transaction in any way. A Lighthouse pledge is thus an incomplete Bitcoin transaction that takes money from your wallet and puts it into the fundraiser’s wallet. Because a transaction that creates money out of thin air breaks the rules of Bitcoin (only miners can create money out of thin air), it won’t be complete until everyone pays. With SIGHASH_ANYONECANPAY, if you get enough of these pledges, it will merge them all together and you’ll end up with a valid payment that will be merged into the blockchain.

Let’s take a look at how Lighthouse is doing this programmatically. We’re going to use the Lighthouse repo on GitHub as a programmatic guide; we don’t need to clone it and build it from source. We know what it does, so we should dive into how it does it.

Let’s first look under the file PledgingWallet.java:

public PendingPledge createPledge(Project project, Coin value, @Nullable
KeyParameter aesKey,                                       LHProtos.PledgeDetails
details) throws InsufficientMoneyException {

This is the function for making a pledge: it encompasses using the SIGHASH_ANYONECANPAY OP code as well as the first smart contract that we are going to deal with:

TransactionOutput stub = findAvailableStub(value);

The method takes as a parameter the project in question, its credentials, and the amount that you want to pledge to the project. The code attempts to find a single output that can satisfy the pledge given as a parameter.

Submitting multiple inputs is unfriendly because it increases the fees paid by the pledge claimer. The pledged output is called the stub and the tx that spends it using the SIGHASH_ANYONECANPAY is the pledge. The template tx outputs are the contract:

Coin totalFees = Coin.ZERO;
Transaction dependency = null;
if (stub == null) {
final Address stubAddr = currentReceiveKey().toAddress(getParams());
SendRequest req;
if (value.equals(getBalance(BalanceType.AVAILABLE_SPENDABLE)))                req
= SendRequest.emptyWallet(stubAddr);
else
req = SendRequest.to(stubAddr, value);
if (params == UnitTestParams.get())
req.shuffleOutputs = false;
req.aesKey = aesKey;
completeTx(req);
dependency = req.tx;
totalFees = req.fee; 
log.info("Created dependency tx {}", dependency.getHash());
 // The change is in a random output position so we have to search for it. It's
possible that there are             // two outputs of the same size, in that case
it doesn't matter which we use.
stub = findOutputOfValue(value, dependency.getOutputs());             if (stub ==
null) {
// We created a dependency tx to make a stub, and now we can't find it. This can 
// only happen if we are sending the entire balance and thus had to subtract the
// miner fee from the value.
checkState(req.emptyWallet);
checkState(dependency.getOutputs().size() == 1);
stub = dependency.getOutput(0);
}
}

If there is no output like that, then the app tries to create an output of the right size and try again.

It then creates the assurance contract pledge by adding the SIGHASH_ANYONECANPAY OP code to the transaction:

Transaction pledge = new Transaction(getParams());
// TODO: Support submitting multiple inputs in a single pledge tx here.
TransactionInput input = pledge.addInput(stub);
project.getOutputs().forEach(pledge::addOutput);
ECKey key = input.getOutpoint().getConnectedKey(this);         checkNotNull(key);
Script script = stub.getScriptPubKey();
if (aesKey != null)
key = key.maybeDecrypt(aesKey);
TransactionSignature signature = pledge.calculateSignature(0, key, script,
Transaction.SigHash.ALL, true /* anyone can pay! */);
if (script.isSentToAddress()) {
input.setScriptSig(ScriptBuilder.createInputScript(signature, key));         }
else if (script.isSentToRawPubKey()) {
// This branch will never be taken with the current design of the app because the 
// only way to get money in is via an address, but in future we might support 
// direct-to-key payments via the payment protocol.
input.setScriptSig(ScriptBuilder.createInputScript(signature));         }
input.setScriptSig(ScriptBuilder.createInputScript(signature,  key));
pledge.setPurpose(Transaction.Purpose.ASSURANCE_CONTRACT_PLEDGE);
log.info("Paid {} satoshis in fees to create pledge tx {}", totalFees, pledge);

And that’s how the creator implemented his smart contract using the raw Bitcoin protocol. Ugly way of doing things, isn’t it? The raw Bitcoin protocol just isn’t developer friendly. If you’ve ever tried using it, you know what I mean. That’s why services like chain.com and SDKs that wrap its ugliness will lead the way in terms of developer engagement.

Thus, the money doesn’t actually leave your wallet when you make a pledge. It’s just part of a signed transaction that hasn’t become a valid transaction on the network.

When a user decides to create a project, a BIP70 payment request message is formatted. The outputs are specified normally, and there are only a few things different from the regular payment flow:

  • A field labeled title is added. This field sums up the project in a few concise, descriptive words.

  • A field labeled image is added. This image contains serialized image bytes that add individuality to the project in the user interface. Hearn had the images be the same aspect ratio as Facebook cover photos so that they are easy to reuse.

  • In the case that a payment_url is specified, it should speak an extended protocol that permits querying the project status (the current pledges).

  • The payment message itself must contain an invalid transaction that only has SIGHASH_ANYONECANPAYcode> signatures. Only public, known UTXOs can be spent by the pledge to be considered valid for the project. The memo field can also contain a message from the user (commending the project). Additional fields for contact details are permissible.

After being formatted, the payment message can either be POSTed to the payment_URL for collection and eventual merging with other pledges, or it can be transferred to the project owner in another way (for example, email). When the owner has it, he can load it into his Lighthouse client. The client provides a GUI for merging pledges and sending the final transaction off to the P2P network.

Bitcoin’s scripting language has become more powerful over the years, thanks in large part to the innovations in blockchain technology and Turing-complete smart contract technology coming out of the Ethereum project. It’s well suited for most smart contracts, but Turing-complete contracts on the Bitcoin blockchain are an area that is still emerging. Counterparty allows for it, but Counterparty is quite bloated with other unnecessary features. There is, of course, Ethereum itself, but the sidechain code still hasn’t been implemented to let you use the Ethereum blockchain with the security of Bitcoin.

Lighthouse is a great case study into the politics that have begun to sink into the Bitcoin protocol. Bitcoin is seven years old and Mike Hearn has been a core developer for almost as long. He submitted about 44 lines of code as a pull request to the Bitcoin core and it was rejected. It was then accepted. Then, later on, it was unmerged after much serious debate. Even with his credentials, he wasn’t able to get a simple fix that would build on OP_SIGHASH_ANYONECANPAY.

The core developers are very protective of the codebase, and with right purpose—Bitcoin is important fiduciary code and billions of dollars depends on its stability. In that sense, it’s the most valuable standalone open source project in existence. There were a total of 167 comments by developers on Hearn’s 44-line merge request. He decided instead to create a patch list to implement his “getuxtxo message queries UTXO set, used to check pledges.” Hearn even went on to say that Simplified Payment Verification (SPV) wouldn’t be possible at this stage in the game because of how much politicking is necessary to make any changes to the core protocol.

This is a good and bad thing: it’s good because too many changes could break everything if not carefully analyzed and debated; it’s bad because it prevents great changes from becoming part of the core. Sidechains will hopefully solve this problem by allowing for new blockchains for experimentation while still scaffolding the Bitcoin blockchain’s security.

Hearn went on to create a protocol called Bitcoin TX for Lighthouse with the patch set that currently has about 16 active nodes.

SPV Wallets

Recall that in the Mikro dapp, we used a third-party API to create and send coins between addresses. Kerala wrapped all the signing and pushing necessary. This is only partially decentralized but a good start. A more decentralized solution is obviously to run the node locally, but the problem with running a Bitcoin node locally is that the blockchain has grown too much. After seven years, downloading and synchronizing the blockchain takes at least four hours and many gigabytes of space. The alternative to this that keeps things decentralized and light is SPV wallets, which is what Hearn implemented using BitcoinJ.

It’s possible to build a Bitcoin implementation that does not verify everything, but instead relies on either connecting to a trusted node, or puts its faith in high difficulty as a proxy for proof of validity. BitcoinJ is an implementation of this mode.

In SPV mode, clients can connect to full nodes and download only the block headers. Satoshi described this in his original Bitcoin white paper. Clients can verify that the chain headers connect together properly and that the difficulty is sufficiently high. After that, they request transactions that match certain patterns from a remote node like transactions to your address. This provides copies of those transactions via a Merkle branch linking them to the block in which they appeared. The protocol lets us use the Merkle tree structure to allow for proof of inclusion without needing the entire contents of the block.

SPV allows for even further optimization by discarding block headers that are buried very deep (that is, storage can exclude blocks lower than X headers). If a node is known to be trustworthy, the difficulty no longer matters. If you just want to pick a node at random, the cost to mine a block sequence that has a bogus transaction by an attacker should be higher than the value gained by defrauding you. By changing how low the block has to be, we can exchange confirmation time versus cost of an attack.

Identity

public String signAsOwner(PledgingWallet wallet, String message, @Nullable
KeyParameter aesKey)
{
DeterministicKey realKey = 
  wallet.getAuthKeyFromIndexOrPubKey(authKey, authKeyIndex);
 if (realKey == null || (aesKey == null && realKey.isEncrypted()))
return null;
return realKey.signMessage(message, aesKey);
}

Each project gets its own auth key. The auth key is just a regular Bitcoin secp256k1 key. It’s stored in the user’s wallet and derived from their HD key hierarchy. Currently, the project uses it solely to prove to the server that the user is the original project creator. The key could also be used to provide messages signed by the creator and prove that a newer version of the project file is legitimate in the future.

The author also has a BitcoinJ template that he’s created that’s pretty easy to use. You can find it on GitHub.

Figure 5-4 is a great example of a well-designed wallet interface. Basically, it’s an SPV wallet written by using BitcoinJ with a default HTML/CSS template scheme setup that you can build on to create your own decentralized application. It’s not ideal, because it’s not using a metacoin, so it will be difficult if not impossible for you to make money off of whatever you create, but it’s a start. There also exists an SPV colored coins wallet called ChromaWallet, but it doesn’t have the pretty starter template that this BitcoinJ template has. Combining the template element of BitcoinJ with it would be a really useful tool to have, and I predict someone is going to create it sooner or later.

Figure 5-4. Your wallet balance
..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.22.242.118