From aj at erisian.com.au Mon Jan 25 11:34:30 2021 From: aj at erisian.com.au (Anthony Towns) Date: Mon, 25 Jan 2021 21:34:30 +1000 Subject: [Lightning-dev] Lightning dice Message-ID: <20210125113430.s2y3kvttcz7qsy75@erisian.com.au> Hey all, Here's a rough design for doing something like satoshi dice (ie, gambling on "guess the number I'm thinking of" but provably fair after the fact [0]) on lighting, at least once PTLCs exist. [0] https://bitcoin.stackexchange.com/questions/4609/how-can-a-wager-with-satoshidice-be-proven-to-be-fair The security model is that if the casino cheats, you can prove they cheated, but turning that proof into a way of getting your just rewards is out of scope. (You could use the proof to discourage other people from losing their money at the casino, or perhaps use it as evidence to get a court or the police to act in your favour) That we don't try to cryptographically guarantee the payout means we can send both bets over lightning, but don't need to reserve the funds for the bet payout for the lifetime of the bet. The idea is that's much friendlier to the lightning network (you're not holding up funds of the intermediary routing nodes) and it requires less capital to run the casino than other approaches. So the first thing to do is to set up a wager, between Bob the better and Carol the casino, say. Carol offers a standard bet to anyone, say 1.8% chance of winning and a 50x payout, with up to 200 satoshi stake (so 10k satoshi max payout). We assume the bet is implemented as Bob and Carol both picking random numbers (b and c, respectively), and who wins being decided based on the relationship between those numbers. We start off with two messages: m1: "C owes B ${amount}, provided values b and c are given where 0 <= (b+c)%500 < 9 and b*G = ${Pb} and c*G = ${Pc}" m2: "C has paid B ${amount} for the ${b} ${c} bet" The first message, if signed by C, and accompanied by consisent values for b and c, serves as proof that Bob took the bet and won. The second message, if signed by B, serves as proof that Carol didn't cheat Bob. So the idea then is that Bob should get a signature for the first message as soon as he pays the lightning invoice for the bet, and Carol should get a signature for the latter, as soon as she's gotten the payout after winning. PTLCs make this possible, because when verifying a Schnorr signature, you want: s*G = R + H(R,P,m)*P but if you provide (R,P,m) initially, then you can calculate the right hand side of the equation as the point, and then use a PTLC on that point to pay for its preimage "s", at which point you have both s,R which is the signature you were hoping for. But you want to be even cleverer than this -- because as soon as Bob pays Carol, Bob needs to not only have the signature but also have Carol's "c". He can't have "c" before he pays, because that would allow him to cheat (he could choose to bet only when the value of c guarantees he wins). We can do that by making it an adaptor signature conditional on c. That is, provide R,(s-c) as the adaptor signature instead of R,s. Bob can verify "s-c" is correct, by verifying: (s-c)*G = R + H(R,P,m)*P - C So the protocol becomes: 1 -- Setup) Bob has a pubkey B; picks random number b, calculates Pb = b*G. Sends bet, B, Pb to Carol. Carol decides she wants to accept the bet. Carol picks c, calculates Pc = c*G. Carol calculates m1(amount=50*bet, C, B, Pb, Pc), and generates a signature R1,s1 for it. Carol sends Pc,R1,(s1-c) to Bob, and a PTLC invoice for (bet,Pc) Bob checks the adaptor signature -- (s1-c)*G = R1 + H(C,R1,m1)*C - Pc 2 -- Bet) Bob pays the invoice, receiving "c". Bob checks if (b+c)%500 < 9, and if it isn't stops, having lost the bet. Bob calculates m2(amount=50*bet, b, c) and produces a signature for it, namely R2,s2. Bob calculates S2=s2*G. Bob sends b, R2 to Carol, and a PTLC invoice for (50*bet, S2) 3 -- Payout) Carol checks b,c complies with the bet parameters. Carol checks the signature -- S2 = R2 + H(R2,B,m2)*B Carol pays the invoice, receiving s2 I think it's pretty straightforward to see how this meets the goals: as soon as Bob puts up the bet money, he can prove to anyone whether or not he won the bet; and as soon as Carol pays, she has proof that she paid. Note that Bob could abort the protocol with a winning bet before requesting the payout from Carol -- he already has enough info to prove he's won and claim Carol isn't paying him out at this point. One way of dealing with this is to vet Bob's claim by sending b,R2 and a PTLC invoice of (50*bet,S2) to Carol with yourself as the recipient -- you can construct all that info from Bob's claim that Carol is cheating. If Carol isn't cheating, she won't be able to tell you're not Bob and will try paying the PTLC; at which point you know Carol's not cheating. This protocol does't work without better spam defenses in lightning -- PTLC payments have to be serialised or Carol risks sending the payout to Bob multiple times, and if many people want to verify Carol is(n't) cheating, they can be delayed by just one verifier forcing Carol to wait for the PTLC timeout to be reached. Another way of dealing with it, at least for large payouts, is to just put the payout on the blockchain in a way that's claimable by Bob with the same signature, for some reasonable period of time. It might be useful to add a third payment: when Bob *loses* the bet, it may make sene for Carol to pay back a small fraction of the original bet for Bob to reveal their losing guess "b" -- that allows Carol to stop storing old values of c/Hb/B that won't be claimed later, and it lets Bob gain confidence that he can receive funds even when he loses a bet, rather than discovering that there's mysterious network issue blocking payments only when he's won big. I think this should scale pretty well: small bets are coming in over lightning, and the payouts are going out over lightning, so this should lead to fairly balanced channels (depending on how low the profits are). And there's no particular carrying cost, so I think this could work with bets that aren't resolved instantly, though I'm also pretty sure there's some potential traps there too. It should also generalise pretty well -- the rules are all in message "m1", but that doesn't ever go on the blockchain, so you could invent an arbitrarily complicated language for m1 -- eg, you could construct a lotto-like system where you guess multiple numbers and the more you get correct, the higher the payout. But more interestingly, I think you could also add in oracles in a straightforward manner, and thus do sports gambling or prediction markets on top of it, and maybe some sorts of derivatives more generally? I think it's got some drawbacks that prevent it from being a 100% DeFi killer -- you can't atomically combine bets against different casinos and guarantee a riskless win in the same way you can do arbitrage with blockchain-based DeFi (modulo MEV concerns). I believe it should be possible to do PTLCs over lightning in practice already via: https://suredbits.com/ptlc-proof-of-concept/ and, of course, if anyone's running lightning on signet, you should be able to implement schnorr/taproot-based PTLCs there as well, since taproot is already enabled on signet. Cheers, aj