loomnetwork / plasma-cash Goto Github PK
View Code? Open in Web Editor NEWPlasma Cash Contract & Client. ERC721, ERC20, and ETH compatible
Home Page: https://loomx.io/developers
License: Other
Plasma Cash Contract & Client. ERC721, ERC20, and ETH compatible
Home Page: https://loomx.io/developers
License: Other
Helper utilities for tests should be in the same directory with them: 2c) https://github.com/loomnetwork/plasma-cash/blob/master/loom_test/src/client/token_contract.go, https://github.com/loomnetwork/plasma-cash/blob/master/loom_test/src/client/setup.go#L155-L210
The functionality from here https://github.com/loomnetwork/plasma-cash/blob/master/loom_test/src/client/setup.go#L39-L153 should be part of the Client class. The goal here is to mimic the User.createOfflineUser
functionality from loom-js, where createOfflineUser
is a static method of the class (https://github.com/loomnetwork/loom-js/blob/master/src/plasma-cash/user.ts)
E2E Tests under https://github.com/loomnetwork/plasma-cash/tree/master/loom_test/src/cmd should move to go-loom or loomchain (no preference, not sure which is best, probably loomchain)
Why do we need a denomination
parameter in the send_transaction
function? Do we want to be be consistent with non-erc721 applications?
This should be noted in the README
$ FLASK_APP=./child_chain FLASK_ENV=development flask run --port=8546
Usage: flask run [OPTIONS]
Error: The file/path provided (./child_chain) does not appear to exist. Please verify the path is correct. If app is not on PYTHONPATH, ensure the extension is .py
$ ls ./child_chain
__init__.py block.py exceptions.py transaction.py
__pycache__ child_chain.py server.py
As per the refactor in #72 startExit
and challengeBefore
now accept an array of blocks as an argument (uint256[2] blocks
), contrary to accepting 2 separate blocks (uint256 prevTxIncBlock, uint256 exitingTxIncBlock
). 686d447#diff-a86cc287181229fc5e3c3796977ed768L181
This breaks the golang interface and as a result new Plasma Cash contract go-bindings need to be generated via abigen in https://github.com/loomnetwork/plasma-erc721/blob/master/loom_test/src/ethcontract/root_chain.go
Hi.
I'm trying to figure out why the bond amount of 0.1 ETH was chosen. Is there any theory on this?
In submitBlock, there is no check to see if a block in childChain
already exists.
This allows for previously saved blocks to be overwritten.
Optimization: Now that all challenges accept the same parameters we can merge them in 1 type.
RSA Accumulators vs STARKs
Depends on #19
After being able to monitor for events, the callback on each of the events should implement an automatic challenge to a fraudulent exit or response to a bad challenge. The events in the following lines should be made more verbose to give enough information for the client to determine what action it needs to take.
Additionally, once #31 is implemented, we should make it that when a user launches their client, the client automatically fetches all new events since last login (we can do that by saving the latest block that was checked for events), and challenges or responds accordingly.
If Alice decides to send the same signed tx to both Bob and Charlie, what determines which one goes through?
Is the first one that's settled on the main chain?
Does the side chain have to make periodic updates to the main chain? And if so doesn't that hurt the speed of transactions on the side chain?
This is NOT possible to install python3 into /usr/bin/python3.x on Mac OS X El Capitan anymore as from then on System Integrity Protection prevents that.
my solution is to use the library frameworks path
$ which python3
/Library/Frameworks/Python.framework/Versions/3.5/bin/python3
then run below
mkvirtualenv erc721plasma --python=/Library/Frameworks/Python.framework/Versions/3.6/bin/python3
Currently, many values in both the Python and JS test suites are hard-coded. For example, in demo.py
we see lines like:
38 utxo_id = 2
39 blk_num = 3
40 alice_to_bob = alice.send_transaction(utxo_id, blk_num, 1,
41 bob.token_contract.account.address)
42 random_tx = alice.send_transaction(utxo_id-1, blk_num-1, 1,
43 charlie.token_contract.account.address)
44 authority.submit_block()
This makes the tests very fragile and it requires larges changes to the tests when block-numbering or utxo-assignment changes. Making all the changes necessary to test a new non-sequential UTXO scheme would take many hours and would be error prone.
The tests should be able to fill in the necessary values for block numbers and utxo ids automatically.
Implement a benchmark which illustrates the advantages of using Plasma over transacting on chain. We model the "happy-case" to find the upper bound limits of scalability in terms of throughput and gas costs.
Demo will include:
RootChain.sol
We want to obtain data on:
O(t * N)
PER COIN RECEIVED, where t
the number of blocks in the coin's history and N the depth of the tree, i.e. 64 in our case300 blocks * 2000 transfers / block = 600k transactions
. 1 safeTransferFrom
costs ~120k gas, so we get about 72 BILLION gas required for everything to happen on chain.
Notes: finalizeExits
needs to be modified to have a number of iterations, since if many exits are to be initiated, it may require too much gas to finalize them all.
Debit Spec: https://hackmd.io/6DVYwXtQSM6LEub2LCq9Kg?edit
Cashflow Spec: https://hackmd.io/DgzmJIRjSzCYvl4lUjZXNQ?view
Ben's thoughts on cashflow https://ethresear.ch/t/plasma-cash-was-a-transaction-format/4261
Old Debit impl: #115
Firstly need to evaluate which approach is simpler to implement. Debit is probably easier but has limts in features, however it may be worth it if it can be deployed within a week.
Allowing the Merkle Tree Depth to be dynamic in SparseMerkleTree.sol
and in the Plasma Chain sparse_merkle_tree.py
implementation will allow us to customize and accommodate bigger trees for more heavy on traffic chains or smaller trees to have even more compact proofs.
Issue created from discussion in PR #20:
shouldn't always have 8 bytes of proof data in SMT impl if we allow depth to be dynamic
True, if depth is dynamic, the number of bytes should always be
allowing depth to be dynamic means that we have to check that all uids used in tree are less than 2**(depth-1)
So currently there is 1 thing which is an issue in all Plasma constructions that want to work without confirmation signatures, and involves 'in-flight' transactions:
This can be solved by confirmation signatures, i.e. in order for a tx to be considered valid, the receiver has to sign on it and give the sig back to the sender, like a handshake. Alternatively, hash preimages can be used, which is a similar technique but requires less data (https://ethresear.ch/t/plasma-cash-plasma-with-much-less-per-user-data-checking/1298/28). This has UX issues, the receiver can withhold the sig etc. A possible solution is whats' being coined as 'limbo exits' (https://ethresear.ch/t/resolving-limbo-transactions-via-exit-priority-modification/2127) and is being further developed in https://ethresear.ch/t/more-viable-plasma/2160, for Plasma MVP. I'm looking further into that currently.
Additional info: https://ethresear.ch/t/limbo-exits-and-challenging-fraudulent-exits/2015
Currently when creating a deposit transaction, we require that the user has to also formulate the UTXO and submit it as the extra data
field in the safeTransferFrom
function in ERC721. One of the parameters which can be raced across participants is the slot of the UTXO in the merkle tree, which is currently user supplied.
If two users want to deposit at the same time and they create deposit UTXOs with the same UTXO slot, only one of their transactions will get included, and the other will be invalid.
I can see 2 solutions for this:
createTx
in Transaction.solkeccak256(slot)
. Since each coin is unique this should not pose any risk.I'm working on a PoC for the second method.
My discussion in the plasma
slack channel:
As I was reviewing @gakonst’s PR I realized there is a slight issue with sig-checking as currently implemented. In
challengeAfter
ofRootChain.sol
there is a checkrequire(txHash.ecverify(signature, coins[slot].exit.owner), "Invalid sig");
. This fails if the spent-coin exiter Eve sends the spent coin to Mallory who then tries to exit. This is why we were checking for any subsequent transactions in the past, because the person exiting the coin may not be the double spender.I'll make an issue about this, the full solution will be more complicated than what we have now or what we had before.
The problem is that
Transaction
does not store information about the previous owner, rather we only know who sent the transaction based on the ecrecover'ing using the signature. We could solve a lot of issues by adding a field toTransaction
. I think this makes a lot of sense in the case of Plasma where the operator may be untrustworthy.
Hi there,
For example, Alice deposits 3 ERC721 Tokens to RootChain
. There are 3 coins: coin1, coin2, coin3 in RootChain now.
Suppose that Alice wants to send the coin3 to Bob. I read the source code and I perceive that Alice creates a Transaction object with input parameters:
uid = deposit3_utxo,
prev_block = deposit3_block_number
new_owner = Bob’s address
Alice signs the transaction with her private key and then she encodes the transaction
object using RLP encoding method.
Next, Alice calls the Plasma Chain’s API send_transaction through the HTTP endpoint '/send_tx'. Upon receiving the request from Alice, Plasma Chain decodes the serialized transaction object and validate it. If the transaction object is valid, it gets added to the current block on Plasma Chain.
At this point, how does Bob get notified about the UTXO which Alice sent him? How can Bob spend that UTXO?
Specify & implement a protocol for N-coin atomic swaps. https://hackmd.io/DgzmJIRjSzCYvl4lUjZXNQ?view# provides some info on this. Probably a multi-step protocol with preimages and reveals needed.
This is a prerequisite for both Plasma Debit and for protocol variants which require fragmentation.
https://ethresear.ch/t/state-channels-and-plasma-cash/1515
https://ethresear.ch/t/plasma-cash-minimal-atomic-swap/3409
https://ethresear.ch/t/plasma-cash-defragmentation/3410
https://ethresear.ch/t/plasma-cash-defragmentation-take-2/3515
https://ethresear.ch/t/plasma-cash-defragmentation-take-3/3737
Hi, I have a question about implementation about invalid history challenge.
I think users have to be online once a week in Plasma Cash.
But it seems like that users have to be online once a half week in this implementation. Is it right?
https://github.com/loomnetwork/plasma-cash/blob/master/server/contracts/Core/RootChain.sol#L644
Optimization
Currently challengeBefore
requires providing the parent coin along with the coin that we're challenging with. This is not required and can be removed.
we require the parent during exits so that it can be challenged as a double spend, but here the only response is later so the parent has no impact
Add a database to have persistent state for clients.
Reference from OmiseGo repo:
omgnetwork/plasma-cash@e314ad9
omgnetwork/plasma-cash@1a25d17
The db should maintain the list of coins currently owned by a user. This will allow a user to watch and filter Challenge and Exit type events for the coins that they own.
Investigate https://github.com/lorenzb/libsubmarine/ as a future solution for avoiding challenge frontrunning.
Optionally, to better evaluate the scheme also provide a frontrunner of challenges to stress why it is important
So currently we are missing 1 key feature from the sidechain client:
In order for a user to know that their coin is valid, they need:
- all the transactions since the time the coin was deposited that represent that coin's history
- a proof of non-inclusion for every block that does not contain a transaction spending the coin, to verify that the coin was not double spent.
Essentially if a coin was transferred in:
3 -> 1000 -> 3000 -> 5000 and we want to send it somewhere we need:
So in pseudocode:
blocks = [ 3, 1000, 2000, 3000, 4000, 5000]
spent_blocks = [ 1000, 3000, 5000]
for block in blocks:
if block in spent_blocks: check_inclusion
else: check_exclusion
so yeah, 6 merkle branches, 3 for inclusion which expect to find the tx hash at the leaf, 3 for exclusion which expect the default hash at the leaf
Dan robinson: The proof of non-spend in each block is a Merkle path to the empty slot. That Merkle path, by its nature, shows the location of that slot in the Merkle tree.
The suggestion from https://ethresear.ch/t/plasma-cash-with-sparse-merkle-trees-bloom-filters-and-probabilistic-transfers/2006 is to use bloom filters instead to prove the non-spend. need to look into how it would work.
Note that to add this functionality to our client we need to somehow 'notify' the receiver.
Depends on #31 and #18
Work on #123.
Material from https://ethresear.ch/t/optimistic-cheap-multi-exit-for-plasma-cash-or-mvp/1893/2
needed for automatic generation of addresses / privKeys
Currently the slot for each new coin is determined by an incrementing ID which is the number of coins numCoins
. This can be replaced by keccak256(numCoins)
to enforce sparseness on the coin slots. We can additionally add a contractAddress
field and the deposited coin's owner (i.e. the original owner) coinOwner
in the hash calculation in order to support coin deposits from multiple contracts
We truncate all hashes to tree_depth-bits, 64-bits. As per Joseph Poon's comment, if a collision is found during slot creation we can recalculate it slightly mutated, e.g. via an incrementing nonce.
calculateCoinSlot(uint64 numCoins, address coinAddress, address coinOwner, uint nonce)
uint64 slot = calculateCoinSlot(uint64 numCoins, address coinAddress, address coinOwner, uint nonce)
while slot exists --> calculateCoinSlot with incremented nonce.
It is to be expected that the increased gas costs won't be significant from the recalculation process.
When challenging an invalid history (challengeBefore), a challenger has to submit a bond.
When finalizing the exit and it is still in CHALLENGED state, the bond of the exitor is transferred to the challenger, but the combined bond is never freed?
Shouldn't it be freed for posting the challenge?
Additionally, if it's the case the bond should be freed, doesn't this introduce a griefing vector? Anyone can challenge any exit JUST before the challenge period is over without providing enough time to respond, resulting the exitor's bond being slash and the challenger just collecting the exitor's bond for "free"?
finalizeExits()
with finalizeExits(uint64[] slots)
which will call finalizeExit
on each slot. This allows a user to finalize the exit of multiple of their coins. Allows us to simplify the cleanupExit
modifier, and reduce gas costs. Will also omit the getExitIndex
function.getExit
cancelExit(uint64 slot)
and cancelExits(uint64[] slots)
functions. This must check if there is an exit for the specified coin. If yes, it will reset the coin's state to DEPOSITING
and free the exitor's bond.challengeBefore
.@gakonst writes:
Regarding the p2p thing, we can implement it so that when a client receives a coin, they automatically poll the operator for the needed proofs for that coin, and validate the proofs and the coin's history. If they all check out, the receiver accepts the coin and saves the proofs for later in local storage, in case they want to exit the coin. Otherwise they reject the transaction. When they send the coin to another user, they no longer need to hold the proofs so they can safely delete it from their local storage.
We fixed the depth bug in the SMT impl, now we have to fix the tests.
@gakonst writes:
We should also add a filter watcher for Challenge and Exit type events so that a user is notified when an exit happens on a coin they own so that they challenge, or when a challengeBefore happens on their exit so that they know that they have to respond.
When will ERC20 support be announced?
Now that the contracts support multiple challenges, if an exit has N challenges, and X bond, the first challenge will get the whole bond, and potentially the slashBond
function in line 390 during the finalization of an exit will revert.
1 possible countermeasure is to just split the slash in N equal parts and award the challengers.
Other approach is to just reward the first challenger
(need to write a test that illustrates this potential exploit to verify its existence, and then a countermeasure).
As title. Will add what we need to do in order to gather data regarding how big of a transaction throughput increase we can have.
Since we have a PR that enforces linting for a build to go through, I suggest that we use https://github.com/ambv/black as black --line-length 79
for our formatting reasons and https://github.com/timothycrosley/isort for import ordering, what do you think?
Use https://github.com/projectchicago/gastoken/tree/master/contract mint/burn to mint gastoken during low periods, store it in the contract, and allow the operator to make cheap (free) submitBlock calls
https://github.com/projectchicago/gastoken/blob/master/contract/GST1.sol#L97
https://blog.polymath.network/turning-smart-contracts-into-gastoken-factories-3e947f664e8b
Add mint
, freeStorage
function. freeStorage
will be called in SubmitBlock
to pay for gas. Add test which shows that the gas cost of SubmitBlock
was 0.
This article mentions token splitting and merging:
https://medium.com/loom-network/plasma-cash-initial-release-plasma-backed-nfts-now-available-on-loom-network-sidechains-37976d0cfccd
Next Steps — Token Splitting and Merging
Our next steps are to add support for ERC20 tokens and ETH.
Now that Plasma Cash for ETH, ERC20 has been released, does it support token splitting/merging?
Running on Lubuntu 16.04.
The latest common python3.6 release is 3.6.5
.
Running pip install -r requirements.txt
results in:
error: command 'x86_64-linux-gnu-gcc' failed with exit status 1
Searching online shows that this error is related specifically to 3.6.5.
Updating python minor version (manually compiling 3.6.6 from source) resolved this and allowed pip install to run its course.
There was still a warning:
eth-utils 1.2.1 has requirement eth-typing<2.0.0,>=1.3.0, but you'll have eth-typing 2.0.0 which is incompatible
But perhaps one can ignore it in the meantime.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.