Skip to content

Instantly share code, notes, and snippets.

@AdamISZ
Last active November 17, 2023 02:31
Show Gist options
  • Save AdamISZ/b462838cbc8cc06aae0c15610502e4da to your computer and use it in GitHub Desktop.
Save AdamISZ/b462838cbc8cc06aae0c15610502e4da to your computer and use it in GitHub Desktop.
PathCoin

PathCoin

Caveat

Before we begin: this post describes a very limited protocol idea. It's possible that what we describe here is a start towards, or a component of, something genuinely useful, but in itself it's really more of a toy, albeit it's fun.

Non-interactive digital cash

Since the 90s, there was a dream that cash could be sent online just like email. We've basically been experimenting with tradeoffs against this pure vision ever since. Sometimes the tradeoff is: there's a central party we have to trust (either with our privacy or our money or the management or inflation or..), but otherwise we get the goal. Often the tradeoff includes: we have to interact with the receiver. In pretty much every case there's an online-ness requirement: we have to exchange messages with a p2p network of active nodes (bitcoin) or a central server and our counterparty, or at least, directly with our counterparty (e.g. Lightning) in the payment transaction.

What we want is something closer to: I come up to your lunch cart on the street, buy a hotdog by "handing over" "digital cash", you don't have to trust me but can accept it as money, I walk off with the hotdog and both people forget the other. And of course, we want that to work the same in an internet payment (especially the 'forget' part).

Nice dream.

How far, though, could you go, if you doggedly insisted, in a Bitcoin context, that the actual act of payment, was simply the handing over of some data or text.

Above is pictured a different way of trading off to achieve the goal; the opendime, which is a very cool cypherpunk idea (a spiritual cousin of, if not technically related to, Hal Finney's RPOW idea of the early 00s). If you trust that the hardware is not hackable (enough), you can accept the device as being == the coin.

A reminder, in case these ideas are not front of mind: I can't give you money by "handing over my private key", because that's really sharing data, not transferring it. You have no way of knowing whether I remember it; and if I remember it I have as much control over the coin as you do. So private key transfer is generally not a useful idea. There are big caveats - see Mercury wallet and perhaps even Intel SGX, but see also: opendime, as mentioned - the private key cannot be accessed without physically (and demonstrably) "breaking" the opendime; before that time people can transfer it physically, and treat it as physical transfer of ownership of the signing key.

The limitation of this meaning a "fixed denomination" coin is interesting; statechains, of which the above-mentioned Mercury is an implementation, in general, have this kind of limitation too.

Statechains make one of the various tradeoffs we already discussed, in that they have a trust in a third party (more particularly they are trusting in absence of collusion, something we're going to discuss at length here!). We're going to see how far we can get without that trust element.

So: can we make this kind of construction, without trust, in software, not hardware? Let's try! What is presented next as "PathCoin" is based on that idea. As we said at the start, it is VERY limited compared to what we would like to do in the "dream" explained above. But maybe it's the start of something?

Basic idea

First of all, let's consider shared ownership of a single utxo, in a taproot and Schnorr and MuSig2 world.

It's already pretty nice. There can be 100 people owning a multisig together and because of the above tech, it can look the same as one person, to the outside world (I won't discuss MuSig further in this doc, as it's kind of orthogonal. Simpler multisig exists, in taproot, if we need it).

For the rest of this description, though, let's have it be 5 people Alice, Bob, Carol, David, Eve. Just to keep things manageable.

So if they make a 5 of 5 multisig they can control funds together.

With taproot, they can create multiple spending paths with different spending conditions, when they set up this address, such as:

1 coin -> (Alice and Carol) OR (all 5) OR ( Bob and Carol after 1000 blocks OR (all 5)) OR (David and Eve after 2000 blocks)

So that convoluted script logic was just made up, but the point is we can use the 'script path spend' in taproot to make lots and lots of different spending paths that don't end up abusing the blockchain space limitation; only one of the spending paths ends up getting satisfied, and displayed, in the spending transaction. Great, simple so far, just taproot.

Now if all we really want to do is "use taproot to share and transfer money", we may well be better off with the kind of model explored in payment pools (that link is only one of several disparate discussions on this topic, I think). In that scenario, there is unilateral withdrawal available, but payments are cooperative, updating the contract inside the taproot output. It's a very promising direction, but here we're, again, insisting on no further interaction to make payments, in line with the 'cypherpunk dream'.

From here we'll build up the PathCoin idea in stages, starting with the most restrictive and slowly dragging it closer to useable, with more elements.

So, continuing from taproot: we could deliberately create several different paths with the same condition, like this:

Person Alice Bob Carol David Eve
multisig script 1 A1 B1 C1 D1 E1 -> TXA
multisig script 2 A2 B2 C2 D2 E2 -> TXB
multisig script 3 A3 B3 C3 D3 E3 -> TXC
multisig script 4 A4 B4 C4 D4 E4 -> TXD
multisig script 5 A5 B5 C5 D5 E5 -> TXE

These are all 5/5 multisigs. Each list of 5 is different keys (see number suffixes), but the letter denotes which person owns the private key for that key. So this is just a 5 x 5 matrix of keys. The 'scripts' are just a single pubkey spending script, which happens to be a MuSig2 aggregated key.

Alternatively, and more simply, we could just define one 5/5 MuSig multisig, use the key-path spending in taproot, and simply perform 5 separate signing sessions on the same key (each session signing different transaction messages). So:

Person Alice Bob Carol David Eve
musig session 1 A1 B1 C1 D1 E1 -> TXA
musig session 2 A1 B1 C1 D1 E1 -> TXB
musig session 3 A1 B1 C1 D1 E1 -> TXC
musig session 4 A1 B1 C1 D1 E1 -> TXD
musig session 5 A1 B1 C1 D1 E1 -> TXE

Functionally, this is not different; each signing session requires all 5 participants to agree on the outcome in both cases. We will use the latter, though, because it's simpler, and key path spending is more efficient and more private.

Now notice what happens if, let's say, Alice is the one who funds the output containing this 5 of 5 MuSig taproot output, and demands that she be provided signatures so as to be able to spend it, thusly:

Person Alice Bob Carol David Eve
Session 1 σA1 σB1 ✔️ σC1 ✔️ σD1 ✔️ σE1 ✔️
Session 2 σA2 σB2 σC2 ✔️ σD2 ✔️ σE2 ✔️
Session 3 σA3 σB3 σC3 σD3 ✔️ σE3 ✔️
Session 4 σA4 σB4 σC4 σD4 σE4 ✔️
Session 5 σA5 σB5 σC5 σD5 σE5

(The coin value is U from now on).

If at the time we set up the address (and we of course all have to interact to do this - just like with any multisig), we have the signatures marked with checkmarks all be shared (amongst everybody to keep it simple), then you'll notice that Alice is the unconditional owner of the coin. She has 4 signatures given to her, meaning she can spend using path 1 at any time. While crucially none of the other parties (including Bob, who doesn't have Alice's signature on path 2) can spend the coin, and Alice knows that - she hasn't shared her signatures for other paths. So far so good.

Alice transfers to Bob

As we explained earlier, transferring a private key does not transfer ownership. Similarly, if Alice gives her signature σA2 to Bob, so that he is now able to spend from Path 2, it sadly is not a functional payment, since Alice can still use Path 1, any time. How to get round this?

Naive penalties don't work

One thought that might spring to mind is: in Lightning, they have a penalty mechanism, to punish a cheater on one side of a channel, who spends an old state, by giving all the money to the other side of the channel. If we tried to apply that idea here it wouldn't work. Here's why, concretely:

  • We set everything up. Alice owns the coin.
  • Alice transfers to Bob by giving her signature σA2, but also gives a 'promise' that if she ever spends using Path 1 (σA1), then Bob can claim a penalty (more than the coin being spent). This stops her being incented to spend using Path 1.
  • Bob now transfers to Carol. What is Carol's assurance that Bob won't spend, now, using Path 2? The same - there would be a penalty payment from Bob to Carol. BUT! What is Carol's assurance that Alice won't spend the coin using Path 1?

The problem isn't that there's not a penalty (Bob could even send proof to Carol that the penalty existed). The problem is where it goes. If it goes to Bob, how does Carol know that Bob and Alice are not colluding, or are not both called Sybil? If they work together, then a penalty from Alice to Bob is meaningless and so Carol actually has no defence at all, and so this scheme fails.

This applies to any number of parties greater than two. It will never be enough to be safe from the misbehaviour of one party, you need to be safe from the misbehaviour of all.

Not feeling the burn.

One way to try to solve it is with burned funds. I claim that this could be viable, but it is very problematic, to the point I would not pursue it. An honest party attacked with a double spend of U, when the defence against it is burned funds, does not gain from the burned funds, thus an additional positive incentive as well as the burn, is required. Moreover, whether that extra incentive helps is very dependent on how much the attacker could bribe you to not execute the burn. If you look into it, you find that this approach is too game theoretically fragile.

Everyone wins (a little bit)?

We might conclude, from this line of reasoning, that every other party must benefit whenever one cheats, so that even if there is only one honest actor, they always have a defence. For example, with 5 parties as described, we can imagine that Alice might have to forfeit, to all of Bob, Carol, David and Eve, an amount strictly larger than U; thus her fidelity bond would be roughly 4 x (U + δ). This wouldn't be great, but we'll address this point later. Before we do, let's at least sketch out one way we could create such a forfeit or penalty.

Covenants, bonds, penalties: the inefficient first version

The fidelity bond concept is widely enough known; in its traditional sense it exists to be used as a penalty in a contract violation, and that's how we'd use it here.

Participants put up a certain amount of money in a 'fixed' location (fixed by a timelock). Let's say Alice pays to an output with a script like this:

EITHER (to Alice after 100 days) OR (to key TA AND CTV <hash of tx1>)

, where tx1 is fixed to have 4 outputs, one each for Bob, Carol, David, Eve, each have amount U + δ.

(The use of δ here is of course just to create a negative incentive to cheat, even in the worst case.)

Here CTV refers to the currently-under-discussion (Jan 2022) covenant op code which may be added to Bitcoin (see CHECKTEMPLATEVERIFY). Any similar scheme that allows us to constrain where an output can be spent, rather than who can spend it, could play that role, in the following.

So this type of fidelity bond has a get-out clause, instead of just 'lock your funds for time 100 days', but: that get-out clause can only pay out to Alice's counterparties. In the normal case she'll lose more than 4 time the value of U, so that's a disaster for her; but even in the most adversarial case, where Alice colludes with 3 others (Bob, David, Eve) in an attempt to attack one victim (Carol), she (they) will still lose more than they gain (δ), and more important than that: Carol will gain more than she loses.

Now, when Alice creates this "fidelity bond", she'll need to actually know the private key tA corresponding to the pubkey TA (we'll see why shortly), but she won't ever want to use it! Nor to publish it such that anyone else could immediately destroy her funds.

Signature adaptors and toxic waste signatures

Before we fix up the inefficiency of that fidelity bond, let's flesh out how the transfer of value happens.

Given the above setup created at the same time as the set of 5x5 paths in the taproot output (we'll now call it the pathcoin output, value U), we can force a cryptographic linkage between that, and the fidelity bond outputs. When Alice sends σA2, she will actually send, to Bob, this full list:

σA1' , (σA2, ... σA5) The ' is for a signature adaptor rather than an actual signature. For the basics of signature adaptors and how they can be used to tie the revealing of a secret to the broadcast of a signature, see here and here. They require Schnorr signatures, which is one reason that this is only realizable in taproot.

Giving rise to this situation:

Person Alice Bob Carol David Eve
Session 1 σA1 σB1 ✔️ σC1 ✔️ σD1 ✔️ σE1 ✔️
Session 2 σA2 ✔️ σB2 σC2 ✔️ σD2 ✔️ σE2 ✔️
Session 3 σA3 ✔️ σB3 σC3 σD3 ✔️ σE3 ✔️
Session 4 σA4 ✔️ σB4 σC4 σD4 σE4 ✔️
Session 5 σA5 ✔️ σB5 σC5 σD5 σE5

This short list of values she sends (should be around 320 bytes(?), in this toy case, with TA implicit if it was shared upfront), we're claiming here that Alice has effectively entirely transferred control of the pathcoin utxo to Bob. (And it does mean full control - he can spend it immediately or at any time before some long fidelity bond timeout).

It could be sent in a simple format via email or text or literally anything. Not requiring a p2p network or an interactive exchange (Bob can be asleep when you send it, he can pick it up on a third party server etc. etc., you get the idea). Obviously there is a liveness requirement of Bob - check for a cheating transaction, so the advance here isn't so much "offline" transactions, it's non-interactive and off-chain transactions.

But first, what exactly are we claiming happened here? By sending the signature adaptor σA1', on point TA, for the signature σA1, which is the signature Alice would have to broadcast to spend the pathcoin output herself, it means that if she ever does so, Bob would learn tA (the formula is just tA = σA1 - σA1'), the private key of TA, and as discussed above, could use the fidelity bond (at least before the timeout) to claim an amount as penalty, greater than U.

The necessity to create this adaptor is why Alice must actually know the value tA.

A sane Alice will actually therefore be much more likely to want to delete the signature σA1 than use it, and perhaps the value tA also, but there is a finesse in there that we'll get to later.

But for now, let's follow the logic down the chain:

Third, fourth, .. recipients

After Alice has paid Bob as per above, the situation looks like the previous table.

Bob has 100% ownership. He can either spend the coin outside, or, pay Carol by repeating the process. He will send a longer list of items:

σA1'(TA), σB2'(TB), (σA3, ... σA5), (σB3, ... σB5)

Basically, he's sending Alice's revocation of her own claim, Alice's authorization of future payments in the path, and also his own revocation of his own claim, and his own authorization of future payments on the path.

Though it's a slightly longer list, it's still something you can trivially email. (It's crudely an O(N2) scaling in this simple model, but we hit other limitations before that matters!).

After this second transfer the table looks like this:

Person Alice Bob Carol David Eve
Session 1 σA1 σB1 ✔️ σC1 ✔️ σD1 ✔️ σA2 ✔️
Session 2 σA2 ✔️ σB2 σC2 ✔️ σD2 ✔️ σA2 ✔️
Session 3 σA3 ✔️ σB3 ✔️ σC3 σD3 ✔️ σA2 ✔️
Session 4 σA4 ✔️ σB4 ✔️ σC4 σD4 σA2 ✔️
Session 5 σA5 ✔️ σB5 ✔️ σC5 σD5 σA2

At this point, like Alice, Bob would rationally immediately delete his σB2 value so as not to accidentally get his fidelity bond destroyed by revealing tB .

The crucial point is of course, that here, Carol is defended against any collusion between Alice and Bob. If either of them (or both) tried to spend the pathcoin utxo, they would be revealing to Carol their adaptor secrets which would allow an immediate and uncontested penalty transaction, taking from the attacker more than they lost. Notice that in a case where the attacker is more than one step up the path, it doesn't matter who uses the adaptor to claim the punishment; everyone except the attacker gets it.

This latter asymmetry (not only the stolen-from gets rewarded) could incentivise malicious attempts to reveal the adaptor, which is why I said earlier: the rational thing to do is to indeed delete the full signature as soon as the adaptor has been revealed. They are indeed toxic waste.

Anyway, just for completion, here is what Carol would send to David:

σA1'(TA), σB2'(TB), σC3'(TC), (σA4, σA5), (σB4, σB5), (σC4, σC5),

And David to Eve:

σA1'(TA), σB2'(TB), σC3'(TC), σD4'(TD), (σA5), (σB5), (σC5), (σD5)

Now we've laid out the general idea, let's address the main limitations to the construction:

  1. This is a single coin with a single denomination U.
  2. This is only allowing payment along one path (any person can cut the path short of course, by spending the coin, but the most that can happen is A->B->C->D->E). This is such a huge limitation that it makes the construction as-is nearly 100% impractical (you could find a use-case where this is viable, but .. you'll struggle).
  3. This requires allocation of capital to an FB of value approximately N x U, where N is the length of the path.

All three of these limitations are best described as 'very very big' :)

In the rest of this document I'm going to propose a solution to (3), but I have only some unclear ideas about (2), and no particular ideas right now about (1).

Constant size bonds of U + δ

As discussed, (3) is a deal breaker, as presented, to doing long paths. Nobody would reasonably lock up 100 times the value of a coin to spend it.

Can we make it so that each participant only has to put up a bond of U + δ, not N x (U + δ)? I claim we can.

Let's define some terms: FA means the utxo which represents a fidelity bond for A. CTV(tA)-> means a script condition that forces the spending to the output indicated by the forwards arrow, but where the signature requires knowledge of the secret tA (as discussed above, this secret will usually be revealed with reference to an adaptor signature on another, now illegal, spending event). H(SC)-> is as for CTV(tA)-> except the condition is just the knowledge of a secret S, in this case owned by C.

Our goal will be that the fidelity bond, before the timeouts indicated as TLX, of party 1 will be claimable only by party 2, who is the aggrieved party, i.e. specifically the current holder of the pathcoin utxo, and we want this to be the case even though there is only forwards transfer of data as outlined above, i.e. we don't want to renegotiate contracts with everyone during payment events.

Let's start with Alice, making this chain of spends for her fidelity bond:

FA script:

(A and TLA) OR (CTV(tA) -> (B and TLB) OR (CTV(tA) AND H(SB) -> (C and TLC) OR (CTV(tA) AND H(SC) -> (D and TLD) OR (CTV(tA) AND H(SD) -> E))))) ;

tA <-> σA1'

Unpacking: rather than Alice just locking a penalty to her adaptor σA1', she's pre-creating a chain of payouts of the penalty. When she pays Bob, he'll get the adaptor and know that he can wait on the TL_B before claiming the coin via that utxo. He'll know that Carol will not be able to cheat (colluding with Alice) by pulling it forwards into the third utxo, because it's locked to a secret S_B) that only he controls. Those S secrets block all similar forms of collusive attack.

Then if later Bob pays Carol, he'll transfer (σA1') and also transfer SB, (as well as the signatures as described above). That means that Carol will be assured that if Alice spends, she'll be able to use CTV signatures to push it forwards to the third utxo, but as before, she knows it won't go any further due to her keeping hold of SC, and wait for the TL_C. And so on.

And of course it doesn't stop there. Bob will need to do something similar:

FB script:

(B and TLB) OR (CTV(tB) -> (C and TLC) OR (CTV(tB) AND H(SC2) -> (D and TLD) OR (CTV(tB) AND H(SD2) -> E))))) ;

tB <-> σB2'

At the point where Carol receives the coin, Bob has rescinded all control of the funds, so he has no need for a penalty tx vs Alice. So Carol will have effective control of the coin in both the above paths, in the event that either of them illegally spends the pathcoin utxo. They can't both do it, of course (although they could both stupidly reveal the signature), because only one gets onto the bitcoin network.

Repeating this all the way down the path gives us another "triangular matrix" type situation (i.e. there are ~ NxN/2 of these FBX outputs). The end result is that every honest owner can claim exactly one of these outputs as penalty, after a time delay which needn't be very long.

For this reason, in this (admittedly complex!) construction, each participant will only have to fund their FBX output with an amount somewhat larger than the pathcoin utxo, i.e. U + δ, not N times that amount.

With this preparation in advance, we could reasonably consider constructing paths of length such that the O(N2) scaling of the initial setup signature transfer does not become overwhelming. I would tentatively suggest numbers N between 100 and 1000 are at least reasonable, depending on .... things.

What I certainly can't claim is that this construction is particularly useful. Remember that the root cause of the inflexibility is: we want each party to be able to pay forwards without any contract renegotiation, which means we have to 'expand out' all the possible future changes of ownership at the start.

It's certainly possible to try to construct a (yet more complex) version of PathCoin that allows multiple different paths amongst the same set of participants, but note that the number of paths is factorial in N, hence this is only even worth considering for very small numbers of participants (<=10 probably).

Whether there is a smart usage of other opcodes/signature constructions (for example, ANYPREVOUT) that would extend this out to be usable for different paths in some ways is .. an exercise for the reader!

Path chaining

This is more just musing about (2) than really attempting to solve it, for now.

One could imagine taking a current owner (say: David) who wants to then move the coin in a different direction than to Eve, taking the existing set of data (signature adaptors, signatures, hash secrets) that constitute his defence against malicious spending, and therefore constitute his current unconditional ownership, and using that as a starting point for the creation of a new path. This approach is obviously nontrivial, because: all the previous owners remain "in play" (and this can only done before the timelock that prevents them swiping out their FBs and then illegally spending). Also, David would have to convice a new bunch of potential owners (Fred, Grace, Harry, Ivy perhaps) that they do not have a threat from the earlier owners. I haven't yet figured out if that is possible, but perhaps it is, and if it or something similar could work, then chaining such paths almost gets it to the point of being practically useful (though still a bit too clunky, really, even given the wow factor of 'send money like email, without hitting the chain'; you have fixed denominations and you still have to decide upfront who to pay next, or otherwise rejig).

@VzxPLnHqr
Copy link

@AdamISZ

The cycling infinitely idea - while enormously appealing of course - I haven't yet seen a way of making that kind of thing work. .... Certainly not saying it's not possible, but it will require something else, so not discouraging people to think about it...

Understood. Thank you for clarifying.

So the sequence of payments that can happen has to be defined in advance

Right. So, as you indicated, an obvious way to form a finite cycle would be to enumerate and encode a path A --> B -->A --> .... ---> A --> B --> A. It still seems like it could be useful/interesting. I suppose at that point it is basically a deterministic lightning channel if such a thing exists?

@AdamISZ
Copy link
Author

AdamISZ commented Feb 19, 2022

Right. So, as you indicated, an obvious way to form a finite cycle would be to enumerate and encode a path A --> B -->A --> .... ---> A --> B --> A. It still seems like it could be useful/interesting. I suppose at that point it is basically a deterministic lightning channel if such a thing exists?

I don't think there's much value in it, because it's just swapping ownership of one coin, rather than updating balances as in the Poon-Dryja payment channel. This denomination limitation is very severe (see the same issue in statechains - it's useful if it can be scaled up to thousands of instances, or for special situations (privacy protocols, perhaps) but it can be very limiting unless you can bolt things on, like Lightning channels out of a fixed denomination utxo) (and more specifically, this existing 'PathCoin' construction can't scale up massively due to the fidelity bond).

@AdamISZ
Copy link
Author

AdamISZ commented Oct 19, 2023

In the process of coding this, came up with the following concept, and want to write it down before I forget:

Resetting, and maybe netting?:

One of a few ways to bring this construct to being closer to practically useful, would be to be able to revert or pay back payments along a path. This could extend to netting out transfers ("netting" is the common term in traditional finance, but "transaction cut through" is a very similar idea that bitcoin developers will have heard of). But resetting is already a meaty enough topic here, so I'll focus on that :)

Concretely, imagine a pathcoin PC1(A, B, C, D, E), where the parentheses indicate the fixed direction of transfers between the participants.

How could C "give back" (reset) PC1 to A? I now believe something like that is possible (a bit contrary to what I said in earlier comments), with limitations:

To reset the state so that A can spend, you need to restart the whole signing session. The keys of each participant are P_A, P_B, P_C, P_D, P_E, and we still use them, so we are still using the same address/scriptpubkey for PC1, call it sPK_1. If we make a new MuSig signing session (so new nonces), and partial-sign transactions spending out, as before, to destinations for A, B, C, D, E respectively, then we can do the same pathcoin partial signature sharing, on the same sPK_1 as before, with A "owning the coin" because they have partial sigs already for B, C, D, E.

"owning the coin" is in scare quotes there of course, because the previous signing session still exists. C can still spend PC1. But C could give the adaptor signature on her own part of the original signing session, to A. The original fidelity bond design doesn't work for this though:

(C and TLC) OR (CTV(tC) AND H(SC) -> (D and TLD) OR (CTV(tC) AND H(SD) -> E)))))

This only allows C's fidelity bond to be claimed by participants further along the path (D or E), not by A. It would be wrong to just say "add a clause for A which is spendable immediately with some cancellation secret" because this reintroduces collusion risk during normal (pre-reset) operation. The purpose of that structure was to say "if C illegally spends, let the coin move forward through the airlocks, to the exact current owner", so to speak. It can't just go to anyone with a secret, because that person could be colluding with C.

However if we are renegotiating a whole signing session, we can also all share more secrets to invalidate that first signing session. The simplest solution I can think of is to add an extra clause up front to the fidelity bond, that allows the fidelity bond to be claimed back to its original owner, only on condition that all (other) counterparties agree:

(C and TLC) OR (A and H(B_cancel) and H(C_cancel) and H(D_cancel) and H(E_cancel) and T_C) OR (CTV(tC) AND H(SC) -> (D and TLD) OR (CTV(tC) AND H(SD) -> E)))))

In words, the extra OR clause here says "pay out C's fidelity bond to any destination (no CTV), with no timelock restriction, to the owner of A, if they also have the adaptor secret t_C, and they have received cancellation secrets from all other parties in the pathcoin".

Notice that this clause has to have time preference over all the others.

The preimage corresponding to these X_cancel hashes could be handed over only in event of a reset. During normal operation, i.e. pre-reset, each party is protected from collusion by others, by not handing over this preimage. But if, after reset, the owner of the pathcoin PC1 from the first signing session (which is C) chooses to illegally spend it, they reveal t_C and thus A fulfills all of that OR clause and gets the fidelity bond immediately (before all timelocks).

The actions in summary:

  • C holds PC1, wants to give it back to A.
  • Everyone has to get back together (a big coordination issue, but we assume the event is not the normal one).
  • Make a whole new MuSig signing session (on the same musig pubkey) reassigning ownership to A.
  • C hands over adaptor to A.
  • Everyone else apart from A hands over the cancellation secret.
  • A can now consider themselves owner of the coin again, on the new signing session, as long as we stay before the original timelocks.

... but we note the following limitations:

  • The "cancellation clause" has to be set in the original fidelity bond. i.e. we have to anticipate that this might happen, perhaps not a big deal.
  • The new coin has to honour the same timelocks (does CSV usage change that? my suspicion is no)
  • Everyone has to re-coordinate to do a new signing session. Thus resets are not just some spontaneous thing.
  • State accumulates as we add more signing sessions.

Just briefly at the end, to state the hopefully obvious: that if such resetting is possible, it dramatically increases the extent to which this construct could be useful, as you could pay back and not only pay forward, in a single coin.

(Netting: imagine that A funds PC1 with 1btc and C funds PC2 with 1btc. Then, during normal usage, A pays B and B pays C in PC1, so the state is that C holds PC1 (value 1). And similarly in PC2 C pays B who then pays A, so that A holds PC2 (value 1).

An interesting efficiency is to "net out" these two transfers as their aggregate cancels out; A is owed nothing and C is owed nothing.)

@VzxPLnHqr
Copy link

Happy to see that you are still thinking about pathcoin (and even coding it up?), and this seems to be an exciting step forward!

With some of the latest bitvm developments, such as using op_codeseparator to allow for reprogrammable tapleaf logic gates, I am now wondering if there is some way we can improve the pathcoin fidelity bond situation too. Then again, maybe there is no way around each participant needing to post a FB of amount slightly greater than U, at least not without losing incentive compatibility.

@AdamISZ
Copy link
Author

AdamISZ commented Oct 29, 2023

Made some edits to the introduction to change to "keypath spending on 5 of 5 MuSig, in 5 different signing sessions" instead of "script path spending on 5 possible taproot leaves with 5 of 5 with different keys" because the former is way easier and more practical and, also, this is the model I used here:

https://github.com/AdamISZ/pathcoin-poc

May well make a few more minor edits, based on that coding writeup.

@AdamISZ
Copy link
Author

AdamISZ commented Nov 3, 2023

I've rather substantially changed my view of this whole construction over the last few days. I see now, more of a spectrum of possibilities here:

  1. Describe a general script template like "(PA and CLTV) OR (SA and CTV)" as a "covenant time locked contract" or CTLC. The various setups are all using that as the root primitive ("S_A" is shorthand the image of any secret preimage initially created/owned by A, not limited to adaptor secrets).

  2. The simplest version of the idea is that A can on-the-fly create a chain of CTLCs paying a path A,B,C,D,E say - but with a small caveat that A has to be able to define the secret-unlock image S_X for all participants X, to construct the scripts. That seems pretty trivial if they have some existing key e.g. P_C for C, that you can tweak, using various mechanisms, so I'll treat that as unimportant for now). Let's call this "Optimistic Pathcoin". With no collateral/penalty requirement, A can set up a PathCoin to B, C, D, E and each can send their secret S_X to participant S_{X+1} to effect transfer. Some commentary on that setup:

    2a. In case it isn't clear, this explicitly means, not MuSig, but A directly paying into a script:

(A AND CLTV) OR (SA AND CTV ->)
(B AND CLTV) OR (SB AND CTV ->)
(C AND CLTV) OR (SC AND CTV ->)
(D AND CLTV) OR (SD AND CTV ->)
E

(as before, the arrows mean "the CTV enforces payment into the next script". Each scriptPubKey here has only one "A or B" structure, there are 5 scriptPubKeys here, including the plain "E" at the end).

2b. "Optimistic PathCoin" comments: this structure is maximally flexible to setup, but, in itself, fails to remove on-chain footprint, so it's at best a "L1.5", certainly not an L2. It allows immediate and off-chain p2p transfer between participants in the path, but it doesn't get more privacy, really, nor save on fees. Moving the funds on chain is also timelocked. It's instructive to compare it with Rubin's "congestion control" structure. There, there isn't optionality of paying, all payments are defined, there is just finesse on when they happen. Here we have optionality on whether each transfer occurs. Additionally, while congestion control can take great benefit from using script trees instead of single paths, here we cannot do that because we have an off-chain double spend problem if there are multiple paths which can be traversed with p2p secret transfers.

  1. The most complex version of the idea is the one originally laid out in this gist, which I'd call "Private PathCoin". It puts all the CTLCs into side-transactions "fidelity"/"penalty" bonds. This means that the main pathcoin, controlled with MuSig and adaptors for linkage to the side transactions, behaves like pure p2tr keypath spends, and it also means that we don't need timelocks for that coin. But the (more than) 100% collateral requirement for this "Private PathCoin" makes it less likely to be appealing in practice, and also, this "non-optimistic" variant requires everyone to do a coordinated signing step in setup (as described here and in the POC code).

  2. At least one hybrid might make sense: have 5 signing sessions as in PrivatePathCoin, but have the transaction being signed in each case, pay to the chained CTLC construct illustrated above. So here we might regain the privacy (finessing presigning timelocks), and we definitely get the removal of onchain footprint, and we can claim to have removed the nasty collateral requirement again, but we have a thorny incentive problem: an enforcement by traversing e.g. three CTV clauses, must of necessity require more fees, so an illegal spender higher up the path, while they cannot steal the money (because the real owner will claim it via the CTLC chain), can grief the current real owner, forcing them to pay more fees. A way to prevent the honest holder from being punished by others' bad behaviour is required.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment