Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Single-Funder DLC for Crowdfunding #117

Open
carlaKC opened this issue Dec 4, 2020 · 3 comments
Open

Single-Funder DLC for Crowdfunding #117

carlaKC opened this issue Dec 4, 2020 · 3 comments
Labels

Comments

@carlaKC
Copy link

carlaKC commented Dec 4, 2020

Hi dlc-spec!

I've been thinking about another form of DLC that could have some interesting applications - a single funded DLC used specifically for crowdsourcing funding in a trustless manner. This is a very rough idea, and may not work at all, but I just wanted to put it out there for discussion.

Problem

Crowd-funding with Bitcoin (so far) requires trust. Gross. Typically this would take two forms:

  1. A trusted custodian collects all the BTC, then funds/refunds accordingly - third party risk
  2. Individuals pledge to fund a project, but the recipient has no guarantee of receiving the funds - trusted funder

Idea

A simplified, single-funded DLC could be used to setup trust-minimized crowdsourcing for projects, depending only on an oracle that signs the outcome of the conditions for funding. I'm not a script-wizard, but the paths for the contract could be as follows:

  • If condition met, payout to funding recipient
  • If condition not met, refund to funder
  • Timeout clause so that funds are not indefinitely locked

Examples

Traditional Crowd Funding

  • Projects that want to receive funding advertise somewhere, providing a funding target in BTC, a block height by which the funding goal should be met, and an xpub
  • Funders can create dlcs paying to the funder and register their dlc on the funding site (txid + script so amount can be checked)
  • Oracle will sign goal_met or goal_not_met by examining all registered txns to calculate total committed amt at the decided upon block
  • Parties claim accordingly

h/t to BitcoinACKs PR pledges, which gave me this idea.

Motivation

  • Reduced interactivity simplifies setup, lower barriers to integration etc
  • Trust minimized funding, yay!

There are likely some trust issues with the oracle knowing the amount pledged, perhaps there is some zero knowledge magic that one could do, but even without that I think this takes a step in the direction of less trusted funding models?

@nkohen
Copy link
Contributor

nkohen commented Dec 4, 2020

Welcome @carlaKC !

Some thoughts:

Neat use case :) I like it

TLDR; This can definitely be solved using DLC oracles! Not all too much has to be done (on paper anyway, in terms of building server code there is a non-trivial amount of work involved but nothing too crazy). PTLCs using DLC oracles might be a better solution compared to DLCs, noting that both can be supported simultaneously if that would be beneficial.

I think there are two ways this could work:

  1. Funders enter into a single-funded DLC with the (potential) receiver with a Contract Execution Transaction (CET) for the two cases goal_met paying exclusively to the receiver, and goal_not_met paying exclusively to the funder. (There is also a refund transaction as usual). The benefit for this way of doing it is that you don't have to worry about registration separate from the DLC (although the receiver will still have to publish information about it somewhere publicly for you), and that you can release funds on goal_not_met instead of relying on a timeout. The cost of doing it this way is that DLC-protocol-level interaction is required between the funder and receiver and the receiver has to have a DLC-enabled wallet. The interaction consists of 1.5 round trips. The main down-side of requiring this interaction is that new contracts cannot be put on-chain if the receiver's server goes down, whereas the next way of doing this would still allow new contracts to be added to the funding pool without relying on the receiver's servers (assuming that the registration isn't happening on these servers that have gone down, at least not exclusively)

  2. Without requiring any interaction with the receiver, the funder could unilaterally setup a Point Time Lock Contract (PTLC) corresponding to the signature of the message goal_met. If that signature is released, then the receiver can claim the funds in the PTLC via the point-lock. If the signature is not released by some predetermined block, then the funder can reclaim the funds in the PTLC via the time-lock. The benefit for this way of doing it is that you don't have to have any interaction with the receiver in order to broadcast the contract on-chain, but you probably still need to register your PTLC someplace publicly so that it can be audited and added to the count. This approach is also, technically speaking, much much simpler: A couple other friends and I implemented PTLC functionality from scratch over a weekend for a hack-day back in April (https://youtu.be/w9o4v7Idjno), and that included all of the new cryptography in the library secp256k1, which can now be re-used without doing that work again.

It just so happens that these two approaches are fully compatible! That means that assuming some sane registry of relevant PTLCs and DLCs, the receiver could support both kinds and have oracles count funds from both. The resulting signature from the oracle could then be used to unlock both kinds of contracts.

From a general privacy perspective DLCs have a lighter on-chain footprint than PTLCs but for this use case, contracts must be publicly revealed in order to be counted towards the total so I don't think it is a significant consideration.

As I mentioned, in either way of this being done, the oracle signing goal_met or goal_not_met must only commit to a 32-byte R value and then later sign (after auditing the funding contract registry) and broadcast this signature and nothing else is required from them. What is better, it is encouraged that there be multiple trustworthy auditor oracles (preferably not all controlled by the receiver :P) which do this signing, and in this case, some EC point math can be done to make the DLCs/PTLCs in to 2-of-3 oracles claim goal_met or 3-of-5 or etc.

So long as 3 or 5 or whatever number of truly trustworthy oracles exist this vastly reduces the chances that you were accidentally wrong in trusting an oracle and that they've been bribed or compromised.

In either approach, using a threshold of multiple oracles (chosen by the user, different funders can use different oracles according to their preferences) maximizes trust-minimization (i.e. minimizes trust the most that can be done on BTC) and all trust is placed solely in the threshold set of oracles (of each funders choosing) with no trust resting on the funder or receiver.

To the best of my knowledge, there is no easy way to hide much at all about individual funders' contracts from the oracle. With ZKPs it is possible to prove that some amount has been met in some set of blocks but not only does this require a lot of extra work on the receiver's end but it also trusts the receiver not to reveal this information, and worst of all the complexity of such a ZKP is super duper HUGE. Probably not worth it, at least in the current state of the crypto libraries I'm familiar with. Might be a fun project for some PhD student someday though haha

@nkohen
Copy link
Contributor

nkohen commented Dec 4, 2020

In terms of practically implementing software to support this use case, I believe the following is what is required:

  • A registry server (preferably open-source so that it can be easily used by anyone who wants to raise funds). This would need to be able to take as input a transaction, funding amount, and some public keys as well as proof the tx was included in a block, and as a result add to its publicly query-able database of funding contracts (after validating the transaction is included in a known valid block). I am having trouble ball-parking how much work this is. It is not trivial but not overly complicated either. I will note that this will take longer to implement for the DLC approach than the PTLC approach because there's more stuff that needs to be validated in the latter, but not by a large margin. My best guess is that this could be hacked together pretty quickly but might take a bit longer to do in a nice maintainable way.

  • Auditor Oracles. Most of this functionality is already done in multiple implementations as it is not very different from a normal DLC oracle. The only new thing is that the data on the registry would need to be validated against the chain, unless the oracle maintains the registry and has already done this validation.

If the DLC approach is taken:

  • A DLC accepting server (preferably open source). This would essentially just handle public keys and some temporal private keys (which do not really store funds) and it would have endpoints for users to enter into DLCs, so this would likely use as a library or just plain fork an existing DLC implementation and add some specialized, not too complicated server functionality. Ideally this server would also contact the registry server for the client when a new contract is broadcast. Most of this work is covered by existing DLC code so I don't think this would be too hard to build.

If the PTLC approach is taken:

  • PTLC support in the funder's wallet. This can either be done directly (for example, I think it would take me less than a day to integrate this into the bitcoin-s wallet, where I'm a maintainer) or it can be done by making a separate application which creates the scripts and such and then all the wallet needs to support is signing transactions, and adaptor signing transactions (noting that the crypto for that exists in a branch off of secp256k1 and that again, the application for creating the scripts is not very much work, probably a day's worth or less).

@nkohen nkohen added the use case label Dec 4, 2020
@ariard
Copy link
Contributor

ariard commented Dec 4, 2020

Welcome to the spec @carlaKC :)

Crowdfunding is a really interesting use-case for the Bitcoin ecosystem and AFAIK it hasn't been
solved yet, at least in a scalable, cheap, privacy-preserving way.

Let's discuss more the problem before to examine potential solutions.

Crowdfunding as a Trustless Multi-Payer-Single-Payee (MPSP) Payment Scheme

Let's say you have Alice, Bob and Caroll making the pledge between them to pay Dave 0.1 BTC, at
the blocking condition that every other funder respect its commitment. At the difference of
other MPSP payment schemes like a group of friends splitting a bill, we can't assume social
trust between Alice, Bob and Caroll, it's really likely they're complete strangers for each other.

Thus, we're aiming for this trustless property, each payment to Dave isn't only atomic on its own
but also atomic as a whole, you're looking to establish circular dependencies between each funder's
payment. As of today, you have different logics to achieve such circular dependency : economic incentives
(e.g Barrier Escrow, third-party external observer (e.g an oracle), onchain scripting (e.g malleability flags).

We're also aiming to make this crowdfunding application scalable. Let's examine BitcoinACKs as an
onchain example, pledges are in the 10 000 - 100 000 order of magnitude. If you assume onchain fees
in the 1000 - 10000 sat range (i.e current sat/byte level), and a funders set size of 10 to achieve
crowdfunding target, it means they will spend almost as much in fees than in crowdfunding reward.
Further, you will also have a cost for the payee to spend O(n) onchain outputs where n is the number
of onchain transaction gathered to reach the target. If you aim for massive, scalable crowdfunding
with thousands of participants involved, I would say onchain might not be the best direction...

Lastly, about privacy, you have different viewpoints to consider. Funders would like to hide their
identity and amounts given from any other protocol participant. Funder would lile to hide their
identity and likely amounts collected from any other protocol participants, including oracle if
involved. Also, you may want to hide the existence of the crowdfundign contract from the transaction
log itself, which is the DLC OG privacy assumption. You might have to consider side privacy leaks
like a public website advertising the crowdfunding with a well-known blockheight...

A first onchain solution : Trustless SIGHASH_ANYONECANPAY transaction

There is a old-known solution to enable crowdfunding, which is relying on SIGHASH_ANYONECANPAY
permissivemalleability to interactively build a onchain crowdfunding transaction among multiple participants.

It's nicely trustless, as the transaction will be valid only if the fundee gathered enough inputs
to reach the output target as committed by SIGHASH_ALL participant signatures. Though it doesn't
scale and fundee will learn the set of utxos involved in the crowdfunding, even assuming you blind
them a la CoinShuffle to break the input
ordering announced by the fundee to each funder. And the only way to securely exit a non-successful
crowdfunding for a funder is to double-spend the pledged input ("costly timeout").

In fact, some folks tried to build a bitcoin crowdfunding platform few years ago but it never reached momentum.

A second offchain solution : Accumulative MPP

MPP are cool and at the protocol-level, there is no requirement that all the chunk are coming from
the same payer, if chunks are tagged with the same payment_secret. MPP can be leveraged as a
interactive crowdfunding scheme :

  • Alice, the fundee, display an MPP invoice inviting to a crowdfund
  • Bob downloads the invoice and send a MPP-chunk to Alice LN node, locked with point X
  • Alice displays channel funding utxo and commitment transaction with PTLC X on her website
  • Caroll downloads the invoice and send a MPP-chunk to Alice LN node, locked with point X + Y
  • Bob can swap his PTLC X with a new PTLC X + Y, thus making settlement of his PTLC by Alice conditional
    on the adjacent settlement of Caroll's PTLC
  • ...
  • When the crowdfunding is reached, every funders is releasing out-of-band its secret scalar, thus
    enabling Alice to fetch all PTLC atomically, if one of them fails, the whole crowdfunding payment
    fails

I think this scheme is correct but it comes at least with 2 strong weaknesses, a) the fundee has to
display its channel funding utxo and commitment transaction (and likely to prove the valid commitment tx
in a zero-knowledge way to avoid verifiers closing channels they're not involved with...) and b)
funder have a strong liveliness requirement to update their PTLC with point of participants entering
in the crowdfunding after them...

A third offchain solution : PTLCs with Arbiter Oracles

The whole interactivity and public provability of the crowdfunding state can be removed by relying
on a DLC oracle to achieve these functions. Involved oracles are named Arbiter (as arbiter resolving disputes outside the courts, contrary to the
onchain blockchain-as-a-judge model).

Let's sketch such protocol.

  • Alice, the fundee, register a crowdfunding invoice with a bitcoin target of T towards Olivia
  • Olivia gives back to Alice a crowdfunding point X, it's displayed with invoice on Alice website
  • Bob discovers the invoice and crowdfunding point, send a PTLC X to Alice LN node timelocked to block B
  • At PTLC reception, Alice sends a channel utxo ownership proof + balance state proof to Olivia
  • ...
  • When Alice proved that she has enough PTLCs pending to satisfy the crowdfunding target T and block B
    hasn't been reached, Olivia releases scalar for T
  • Alice fetches the PTLC, the crowdfunding is a success !

I think this protocol is quite nice because it's scalable and quite good about privacy, funder
identities aren't disclosed. You might also keep privacy for the funder if the proofs towards the
oracle are privacy-preserving. The fundee can add crowdfunding amount noise by sending dumb PTLCs to
itself. Funder-interactivity is limited at sending a PTLC, no action is required for settlement.
The protocol is trust-minimized in the bounds of the DLC security model, the oracles can't steal
the stakes, even with collusion of the whole set of funders. They can only halt the crowdfunding.

W.r.t to the proof systems requirement, AFAICT, you don't need general statement ZKPs. Those ones
are effectively complex, what you're looking is a zero-knowledge set membership system. And it turns
out there is already a post-taproot PoC candidate. The balance state proof can be cooperatively built with your channel counterparty, built as a proof-of-reserve to avoid state onchain usage by the verifier.

Hopefully, this would help you to clarify the crowdfunding properties you're aiming for before to
hack an application. Bear in mind low-value crowdfunding when deciding for onchain or offchain. My
intuition, the bitcoin primitives to build a really cool crowdfunding protocol still need to mature
a bit (beginning with taproot/schnorr to activate)

Lastly, if you understand off-chain you understand onchain too, we're using the same transactions :p

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

4 participants
@nkohen @ariard @carlaKC and others