Code Monkey home page Code Monkey logo

plasma-cash's Introduction

Plasma Cash - ERC721/ERC20/ETH Supported

Installation and Loom SDK integration

To see the integrations run against the Loom SDK you must download the loom SDK, refer to https://loomx.io/developers/docs/en/basic-install-osx.html.

Under the loom_test directory there are all the samples in Go, that directly interact with Loom SDK. If you have cloned the repo and go dependencies are not found, in loom_test try:

export GOPATH=$GOPATH:`pwd`

Demo Flow

  1. Alice registers and is given coins 1-5 from the token contract
  2. Alice deposits Coin 1, Coin 2, Coin 3 in the plasma chain
  3. 3 Deposit Blocks have been generated in the child chain, each one having 1 UTXO at slots 0,1,2 respectively
  4. Alice sends Coin 1 to Bob, adding the transaction to the current block.
  5. Operator calls submitBlock, checkpointing the block merkle root which includes the transaction that gives ownership to Charlie - At this point, both the child chain and the root chain, have checkpointed Alice's transaction at block number 1000.
  6. Bob transfers the previous UTXO to Charlie and the operator submits that block as well
  7. Charlie tries to exit Coin 1, Alice & Bob do not challenge
  8. After the challenge period passes, Charlie is able to withdraw his coin

Loom integration tests

cd server
npm install
npm run test
cd .. 

cd loom_test
make clean
make deps
make demos
make contracts
make test
cd ..

cd loom_js_test
yarn
yarn build
yarn copy-contracts
cd ..

LOOM_BIN=<ABSOLUTE_PATH_TO_LOOM> ./loom_integration_test.sh

License info

Please note different directories have different licenses. Please see license file in each folder respectively

All derivitive works of this code must incluse this copyright header on every file

// Copyright Loom Network 2018 - All rights reserved, Dual licensed on GPLV3
// Learn more about Loom DappChains at https://loomx.io
// All derivitive works of this code must incluse this copyright header on every file 
  • server directory -> GPLv3 License
  • loom_test directory -> Loom Public License License

plasma-cash's People

Contributors

adyromantika avatar aupiff avatar eduardonunesp avatar enlight avatar gakonst avatar lukezhangstudio avatar mattkanwisher avatar parthdesai avatar shogochiai avatar tstxni97 avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

plasma-cash's Issues

Cache coin proofs in local storage

@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.

GasToken Integration

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.

Atomic Swap Protocol

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

Limbo Exits / Operator Griefing by Block Withholding

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:

  1. Alice broadcasts a transaction to Bob. That transaction is included in a block but is withheld. Alice notices the block withholding and tries to exit (submits a security deposit).
  2. The operator challenges the exit by revealing proof of inclusion of the transaction at a latter block. This slashes Alice's deposit and cancels the exit
  3. The transaction is now revealed and as a result Bob can accept it (note that bob can be colluding with the operator too).
  4. As a result, the tx was actually confirmed, but the operator was able to 'rob' alice of her security deposit.

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

run child_chain error

$ 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

What happens to bond of challenger if there's no response?

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"?

Benchmarking Plasma Cash

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:

  1. Register 1k players (hereafter referred to as players array)
  2. Each player gets 20 coins.
  3. Each player deposits 2 of their coins to RootChain.sol
  4. Each player gives their 2 coins to the next player in the players array (i.e. 2000 coins change hands per block)
  5. This repeats for 300 blocks (finalizeExits period will be adjusted for demo purposes to be every 300 blocks).
  6. After 300 transactions happen for each coin, each player initiates an exit. Note that while this may sound like a "mass exit" as defined in the context of Plasma MVP for a malicious operator, this is just many users exiting and is not considered a case which needs to be modelled separately for gas costs etc - (can be optimized by using aggregate signatures?)
  7. Exit period time passes, finalizeExits(iters) gets called, until all coins can be exited.
  8. All 2000 finalized coins get withdrawn.

We want to obtain data on:

  1. how does it scale with number of blocks (linearly? more?)
  2. how much memory / storage is used by operator?
  3. How much storage will each client need to maintain in proofs? We expect 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 case
  4. How much bandwith is required to realistically send a transaction to the receiver along with all the necessary proofs?
  5. How much gas is saved? Throughput? With some napkin math, for 300 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.
    • We consider that a block can hold ~8m gas (which is slowly going up). This means that 9000 blocks are required to do that many transactions. The throughput gain for this is ~30 which further scales with the amount of coins that are being transferred.
    • In order for a coin to be transferred on chain 300 times, it requires 300 * 125k gas = 36m gas. In order for a coin to be transferred off-chain, a call to the following functions needs to be made: deposit / startExit / finalizeExit / withdraw, which is ~300k gas (need to check numbers), + the waiting period --> 120fold gas cost reduction. This gets further amortized as the number of coin transfers increases.

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.

Installation issues with python3.6.5

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.

The path /usr/bin/python3.6 (from --python=/usr/bin/python3.6) does not exist

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

Benchmark Throughput gains

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.

Modify Coin slot generation

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.

Bond Amounts?

Hi.

I'm trying to figure out why the bond amount of 0.1 ETH was chosen. Is there any theory on this?

Cleanup repository

After we finish benchmarking #50, any extra features to be added should be considered enhancements. We should do a wide cleanup of the repository as well as finish with #34

Update golang startExit

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

Coin history validation upon receipt

This is partially solved by #38. Still need to figure out how we do the receiver notification part

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:

  1. deposit proof (trivial)
  2. merkle proof of inclusion in block 1000, 3000, 5000.
  3. non inclusion proof for block 2000 and 4000. a non inclusion proof can be a merkle proof which proves that the leaf at the coin's slot is hash(0), i.e default value

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

What prevents double spends?

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?

UX Improvements / Optimizations

  • Replace 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.
  • Add timestamp to getExit
  • Add 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.
  • Add max value to be held by the chain (as a safety measure)
    Notes to self:
  • Investigate if it's safe to remove parent coin from challengeBefore.
  • Investigate if returning to sequential coin numbering is better

Bob cannot spend Plasma Cash Token which Alice sent him

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?

Multiple challenges and bonds

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).

`challengeAfter` signature complication

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 of RootChain.sol there is a check require(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 to Transaction. I think this makes a lot of sense in the case of Plasma where the operator may be untrustworthy.

Automatically Challenge/Respond to Exits/Challenges

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.

https://github.com/loomnetwork/plasma-erc721/blob/5a12e3744f1e63670945617cc69b54890290a419/server/contracts/Core/RootChain.sol#L20-L23

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.

Remove parent from invalid history challenge

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

Improve code docs

  • Update contracts to have correct natspec docs
  • Ensure python client has correct documentation everywhere
  • Ensure js tests have correct documentation everywhere
  • Ensure setting up and getting a working local environment is well documented

UX Issue with multiple deposits at the same time

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:

  1. Create the deposit UTXO on chain. This would require some kind of RLP method createTx in Transaction.sol
  2. Make it so that the hash of the Deposit transactions is keccak256(slot). Since each coin is unique this should not pose any risk.

I'm working on a PoC for the second method.

Dynamic SMT Depth

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 $depth/8$.

allowing depth to be dynamic means that we have to check that all uids used in tree are less than 2**(depth-1)

improve tests to automatically accommodate simple code changes

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.

Combine the 3 challenges

Optimization: Now that all challenges accept the same parameters we can merge them in 1 type.

Move loom go tests to go-loom

  1. 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

  2. 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)

  3. 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)

Add filters for Challenge and Exit events

@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.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.