You could just have the parent chain broadcast the hash of the merkle tree and wait a period of time, allowing others to withdraw, before it commits.
Yeah, this seems like a potential attack even if there is a maxBlockNumber in the transaction. The chain operator could create (but withhold data for) a block, thus griefing everyone sending or receiving coins in that block. If the spent coins eventually attempts to exit, the operator could challenge the exit by revealing the path for the transaction spending that coin.
So maybe you need to restore confirm signatures?
Then you get dramatically worse latency for transaction finality; you have to wait a week or whatever or the previous coinholder is free to withdraw them.
Ok, thats fair.
If A gives a proof till the current block it is universally accepted.
A can still give a proof of coin till t, which can be overridden by B if he has a proof of the coin at t+1.
Well, all the proofs considered by the parent chain for exit transactions are interactive (except the one that just identifies the coin being withdrawn). So that’s always the protocol. But I don’t think it helps the griefing attack I describe above, where the plasma chain operator can force users to make invalid withdrawal attempts (and thus lose whatever security deposit you require for those). The only solution for that I see would be to bring back confirm signatures.
That’s not a problem. If the operator challenges the exit, in that process they reveal the Merkle branch that then allows the recipient to exit with the funds unimpeded.
(And I’m not assuming that there are large penalties for attempting an exit that gets challenged here)
All right, although then there’s a griefing/deanonymization/YOLO attack where you make spurious withdrawal attempts on large deposits to force a challenge. But maybe the numbers work out OK.
Along with Vitalik’s suggestion: you can actually include security deposits, but modify the protocol to avoid the griefing attack. Suppose A wants to transfer to B- the idea of the protocol is to give A a way to burn her ownership of a coin once a transfer has been made. A will only burn her coin if data of her transaction is made available from the operator. Let me know your thoughts:
So, A makes a transaction to B. A also sends the operator a signed hash of a random number that is to be included in the leaf node of her coin along with all the other stuff mentioned.
To prove ownership of a coin: B must now also prove that he has the random number that hashes to that value. Now, A will wait until data is available before she gives B the pre-image. As soon as Bob gets the pre-image he broadcasts it to the rest of the network.
If A attempts to exit, we only slash her deposit if the pre-image of her committed hash is revealed by someone.
What’s nice about this scheme is also that no one else can generate a proof of ownership if A is still the real owner, even if the operator misbehaves. A is in complete control of her coin, regardless of the operator’s actions. We can still disincentivise dishonest withdrawals by slashing balances.
This seems equivalent to what I call a “confirm message” in minimal viable plasma; though there is an important optimization here: you just need to reveal a hash preimage instead of verifying a signature.
Has anyone written about how operators of Plasma Cash take fees? I immediately see a few possibilities:
- Fees are paid as some small Plasma Cash coin. Users still don’t need to check the entire chain, but this is (potentially) poor UX if we require users to hold a cache of low value coins. However, this is the most “Plasma Cash”-like approach.
- Fees are paid as a “fee token.” Fee Tokens are indivisible/non-mergeable tokens that can be validated in the same manner as Plasma Cash (imagine ERC721). Transactions always cost 1 FT. This is similar to (1), except that FT value is determined by some market. Some assumptions are being made there that FTs will typically flow to operators, who will sell them back to users to keep the system running. Wouldn’t want any users to hoard FTs to stall the system. Has the unfortunate side-effect that transactions can’t be given priority based on fee. I need to consider the economics of this one more thoroughly.
- Fees are paid in some fungible coin/token alongside the Plasma Cash coins. I couldn’t find a way to make this desirable because you’d inevitably have to verify the entire set of fee transactions. You might be able to separate this from the Plasma Cash chain by creating a “fee chain” where each fee tx necessarily references some Plasma Cash txid. A lot of issues with this construction, not considering complexity.
Here’s a very simple proposal:
Every transaction must include a “total fee” in its body. The Plasma chain operator only accepts transactions if their total fee exceeds that of their parent tx, and prioritizes by
total_fee - parent_total_fee. When a coin is withdrawn, the amount that can be withdrawn is equal to
deposit_size - total_fee.
Though this certainly would ruin nice clean exact-denomination coins.
Another missing alternative here is transaction fees through channel payments.
One potential complexity I see with this construction is the realization of fees. Operators could “exit” on a fee by referencing a specific coin. We’d have to also maintain a mapping on the root chain of coin IDs to total fee claimed. The owner of that coin could then challenge if they prove that latest
total_fee - total_fee_claimed is less than sum of all fees claimed on that coin by the operator.
This works for a single operator but becomes more complex if the chain is operated in some way that different operators claim fees individually.
But it definitely does ruin clean exact-denomination coins.
Another possibility is accepting a fee from a separate “fee balance” on the root chain. You’d deposit X ETH (or whatever) into the root contract specifically to be used for fees. Each Plasma Cash tx would specify a fee. Users can then only ever withdraw the fee balance minus the total fees they’ve specified on each transaction. This is never more than what they’ve deposited initially.
A withdrawal from the fee balance would be followed by a challenge period where anyone can prove that the total fees specified by the user is greater than the total fees the user claims to have specified. Operators are the only ones harmed if a user tries to withdraw more than they’re allowed to withdraw because withdrawals can never exceed the current fee balance. Operators already have to validate the entire chain, so they’d have the information required to challenge. Operators just wouldn’t accept a transaction if the user tries to specify a fee that’s greater than their current available fee balance.
- Plasma chain operator charges for deposits, then executes transactions for free, using conventional methods to prevent denial of service attacks. This doesn’t really change the trust model because the chain operator can censor whatever they want anyway.
- Plasma chain operator also runs a “change service” for which they maintain many very-small-denomination coins (as @kfichter suggested way above); the transaction fee is withheld as part of this.
I think payment channels and cross-chain atomic swaps are pretty difficult on Plasma Cash (even if the spending conditions supported time locks and hash locks) because the channel operator has the power to both censor transactions and withhold data (i.e. a revealed preimage). But I guess you could use a regular ETH payment channel and forget atomicity because the fee amounts are so small.
A lot of this discussion is assuming the possibility of atomic transactions that simultaneously transfer multiple coins.
- Where do these more complex transactions fit in the tree? I guess the transaction would have to be included in the tree N times, once under each coin being spent, and would only be valid if it was included in all of them.
- To prove validity of one output, would you need to prove the history of all of the transaction’s inputs, or just the one corresponding to the output? I think you only need the one corresponding to the output; the confirm preimages/signatures from all the parties should ensure that none of them cheated any of the others by double-spending their input before the transaction was included.
- The holdout problem when you have multi-input transactions and confirm signatures/preimages (what happens when the owners of one of the transaction inputs refuses to provide a confirm signature?) is something that must have been figured out in the context of MVP, but is new to me. Do all the other parties just have to attempt to withdraw the spent coins?
Does the operator even need to maintain connections with every coinholder? Could we put the storage burden on the chain operator, and have it provide the history validity proof to the recipient after a transaction is confirmed, at the same time it provides the Merkle path to the new coin? (Or on request of the coinholder, if they just need to prove possession to someone.) Then the only burden on the coinholder would be to verify their coin’s history at the time that they receive it, and to monitor the parent chain for attempted withdrawals of that coin.
Could we put the storage burden on the chain operator, and have it provide the history validity proof to the recipient after a transaction is confirmed, at the same time it provides the proof of the new coin?
I suppose that can work. Though the storage burden could be large, so operators may want to forget it after some short period of time.
Here is another version of plasma cash: plasma root verification.
Plasma cash is great because the operator can no longer turn the plasma contract on the main chain into a fractional reserve, but he has to steal coins. This is archived by introducing coinIds and requiring the operator to steal a unique coin. Here I want to describe that this can also be archived without the introduction of a coinId, we just need to link every transaction output to its initial deposit into the plasma chain. Instead of requiring the users to check the validity of all transactions, we just require them to ensure that the initial deposit linked to their transaction output, does not turn into a fractional reserve. Hence, the trade-off is that you do no longer need to watch only your coinId, as in plasma cash, but all transaction outputs, which do originate in your initial deposits. If you hold several transaction outputs belonging to initial deposits you need to watch all the transactions shifting a ownership of outputs from these initial deposits.
Here are the details.
Everytime funds are deposited into the plasma contract into the rootchain, we generate a unique depositID and a transaction output relating to this depositID in the plasma chain. These outputs can be split as people wish to, but they can never be merged together.
The transactions for a block of the plasma chain have to be ordered by the depositID of the spend output. If there are several transactions for a unique Id, all of these transactions are next to each other in the tree, but their order does not matter.
If a user wants to send a transaction, he needs to send for all blocks in the past (1) new outputs related to the depositID and (2) Merkle proofs of all outputs and (3) Merkle proof that these are really all transaction outputs belonging to this depositID.
Now if someone wants to leave the plasma chain, he needs to submit the
(1) transaction output [TOW] from a block n in the plasma chain, which he wants to withdraw
(2) the depositID belonging to this transaction output
(3) the transaction outputs [TOW/2] on a block close to n/2, which is one parent transaction output of TOW.
Now every user, who has also an output with the same depositID must check whether this is a legitimate withdraw. There are two ways to challenge it: (1) providing a proof that this output was already spend (2) challenging in a trueBit style, that the transaction output does not belong to the depositID.
The second challenge is a little bit more complex. If there is not such a link between the transaction output and the depositID, somewhere this link needs to break and we can find this with a trueBit style in log(blockheight). Either the user sees that the link breaks between [depositID] <=> [TOW/2] or [TOW/2] <=> [TOW]. Depending on where the link breaks, he can challenge the withdrawer to provide a parent transaction output close to the height n/4 or n/2+n/4 and the challenge game starts again. This way we can prove whether an output belongs to a depositID or not. At the end of the challenge game, we should have two consecutive outputs [TOWn], [TOWn+1], where [TOWn+1] uses [TOWn]’s output and spends it somewhere. If this is not the case, the challenger has won the game. Otherwise, the challenger has lost, if he can not provide a [TOWn+1]’, which spends the output [TOWn] before [TOWn+1] does it. (And thereby proofing a double spend of the chain operator.)
I like this solution since it does not need these change machines from plasma cash. But the drawback is that we need to transfer more data per transaction.
So am I right that the capability that this adds to Plasma Cash is that coins can be split? I think there are ways to add coinsplitting to Plasma Cash without making as many changes… for example, every time a coin is split, its ID could accumulate an additional hex digit (so each transaction could split a coin up to 16 times). You would then only have to monitor withdrawals of your own coin and its descendants (i.e. coins whose leading digits match your coin’s ID), rather than all of its cousins.
Additionally, unlike in your scheme, you would not have to keep up to date with all of the transactions involving the “cousin” coins. As soon as you saw any withdrawal claiming to be a descendant of the coin you currently hold, you would immediately know it was invalid, and could challenge it just by revealing your coin and challenging them to provide its immediate child (which they couldn’t, because you never authorized a transaction from your coin).
Here’s a new blog post from Karl Floersch describing an in-progress specification of Plasma Cash. (It has diagrams!)
Thanks for reviewing my proposal. Yes, your solution for coin splitting seems a lot simpler. Will there be any restriction on how often an output can be split with the solution you mentioned? Because if we enlarge the ID with every split, the ID’s might become quite long. Is that an issue?
You could also implement this with decimals, i.e. all coin IDs must initially end with X 0s, and we simply increment the trailing 0s until they hit some max after which they can no longer be split. In this case the coin IDs aren’t being lengthened after each tx.