Skip to content

Plasma Fraud Proof Challenge

Johann Barbie edited this page Jul 19, 2018 · 18 revisions

At Parsec Labs we ❤️ fraud proofs! Fraud proofs power the security of our Plasma chain and keep the validators in check. We have set up a chain on the Rinkeby testnet, but some malicious validators have submitted invalid blocks or withheld block data! 😱 Help us to invalidate the blocks and slash the validators' stakes. 💪 Participate with the following steps:

  1. Review blocks.
  2. Submit 3 different fraud proofs.
  3. Submit next block.

Each successful transaction will receive one of the crypto-kitties shown in the Plasma presentation.

sidechain overview

Setup:

1. Install Fraud Proof Library:

npm install parsec-lib

also check out the repository.

2. Get Rinkeby Ether:

rinkeby faucet

3. Bind to contract:

Parsec Bridge Address:0xc119429d57b4b5b46d17cc4277b35e222989d5a4

Hint: use Remix for simplicity of reading and writing to contract.

Parsec Bridge Interface:

pragma solidity ^0.4.24;

contract ParsecBridge {
    
  struct Period {
    bytes32 parent; // the id of the parent node
    uint32 height;  // the height of last block in period
    uint32 parentIndex; //  the position of this node in the Parent's children list
    uint8 slot;
    uint32 timestamp;
    uint64 reward;
    bytes32[] children; // unordered list of children below this node
  }
  mapping(bytes32 => Period) public periods;

  struct Deposit {
    uint64 height;
    uint16 color;
    address owner;
    uint256 amount;
  }
  mapping(uint32 => Deposit) public deposits;

  uint256 public epochLength; // length of epoch in periods (32 blocks)
  bytes32 public tipHash;

  // return (slot.eventCounter, slot.owner, slot.stake, slot.signer, slot.tendermint, slot.activationEpoch, slot.newOwner, slot. newStake, slot.newSigner, slot.newTendermint);
  function getSlot(uint256 _slotId) constant public returns (uint32, address, uint64, address, bytes32, uint32, address, uint64, address, bytes32);

  function bet(uint256 _slotId, uint256 _value, address _signerAddr, bytes32 _tenderAddr, address _owner) public;
  
  function submitPeriod(uint256 _slotId, bytes32 _prevHash, bytes32 _root, uint256 _sigs) public;

  function reportDoubleSpend(bytes32[] _proof, bytes32[] _prevProof) public;

  function challengeExit(bytes32[] _proof, bytes32[] _prevProof, uint256 _oIndex, uint256 _inputIndex) public;

  function slashDoubleSig(uint256 _slotId, bytes32 _root1, uint8 _v1, bytes32 _r1, bytes32 _s1, bytes32 _root2, uint8 _v2, bytes32 _r2, bytes32 _s2) public;

  function getTip() public constant returns (bytes32, uint256);
}

Also check the latest code.

Proof Data

Genesis Block:

blockHash: 0x4920616d207665727920616e6772792c20627574206974207761732066756e21
height: 0
txList: -

Block 0xcd:

blockHash: 0xcd4389364d24815a27b3427da939a886585126fa99c4fc4297e33229280ad1e6
height: 1
txList: const tx1 = Tx.fromRaw('0x0211000000010000000005e69ec00000f3beac30c498d9e26865f34fcaa57dbb935b0d74');, const tx2 = Tx.fromRaw('0x0311846e4f732fd1c80e0a6d608cb0c732cfbe5cbf0efe1397c3d9a44f24170fd2f500d5275e033eb32583b0bdb0e0ef8c8164c43066868ad01eafc4491a980c4d84506d308f7995d30a855d9e5bafc73ed6ca4a6bebcf54569d161a774e64354c0ac11b0000000005e69ec00000e10f3d125e5f4c753a6456fc37123cf17c6900f2')

Block 0x7e:

blockHash: 0x7ea11ec101e7e5ed3786a4c1bec1b04f667f3c70f342094a44ec3a2cd7037274
height: 2
txList: const tx3 = Tx.fromRaw('0x0311846e4f732fd1c80e0a6d608cb0c732cfbe5cbf0efe1397c3d9a44f24170fd2f500d5275e033eb32583b0bdb0e0ef8c8164c43066868ad01eafc4491a980c4d84506d308f7995d30a855d9e5bafc73ed6ca4a6bebcf54569d161a774e64354c0ac11b0000000005e69ec00000e10f3d125e5f4c753a6456fc37123cf17c6900f2')

Block 0xa3:

blockHash: 0xa380889bc821e85122f8d96ffb7d980bb86a0336f4d93888005b38a8b9fcc65a
height: 2
txList: const tx4 = Tx.fromRaw('0x0311efcb630956a7b3c52eb6cda0ee11be33936562bf60214cd67794dc812353a0a200505d7bb19f0ac44a6e4c3715755c74a467ae385750b950c7d870bc77a4aa24bd2d41ea9b733b5290d08eae142233f3e546c5010abe50b843074a961547567f101c0000000005e69ec00000e10f3d125e5f4c753a6456fc37123cf17c6900f2')

Block 0xce:

blockHash: 0xce935f92e6289b0bc532303f146c8de98e16a6986a054ce8c7f33ae19bb45edf
height: 3
CAS by slot 1 v: 27
CAS by slot 1 r: 0x683d0aa2f36723c6990a3199485e61a6be612f8283d450d7ca905675e55d25ea
CAS by slot 1 s: 0x24cf29ec1f0cc39211b8a8eb9bb73d0adfb35d40ac38f6874c26d804ddac6e6e
txList: const tx5= Tx.fromRaw('0x0211000000020000000005e69ec00000e10f3d125e5f4c753a6456fc37123cf17c6900f2')

Block 0xd0:

blockHash: 0xd02867920f8c3928666d3aaa7f39515fb4e5ec945e83908920208b9f565a3121
height: 3
CAS by slot 1 v: 27
CAS by slot 1 r: 0x63fa9769b60e4e7c723f9c2e5c1134c7ba88662d6170276699bbb29875d31836
CAS by slot 1 s: 0x47390f65031f15a9738cd111daa138d0ac7bf0518fafdff2a563ae6eda533b5d
txList: const tx6= Tx.fromRaw('0x0311f1afcb6eb68a85e2cedad832798a9d402557c85199a5cd8861948a1a279ebc0200e52762194a99e0afa59337fd512979b0e575b5025929a1149b38cd50f096883d25b874d0f7d69321085ea17f789fdb245583f217f84ca14eef5a2b4b8f0e145c1b0000000005e69ec00000e10f3d125e5f4c753a6456fc37123cf17c6900f2')

Proof Hints:

Constructing a block:

  import { Block, Tx } from 'parsec-lib';    // import the lib
  let block = new Block(1);                  // height = 1
  const tx1 = Tx.fromRaw('hex data here');   // TODO: replace with hex data form previous section
  const tx2 = Tx.fromRaw('hex data here');   // TODO: replace with hex data form previous section
  block.addTx(tx1);
  block.addTx(tx2);
  // done

Generating a proof:

  const proof = block.proof(tx1);
  console.log(proof);                        // TODO: submit the output to the contract

Submitting Block Hints:

To become a validator, you need the staking token (PSC). Check out our PSC faucet.

Once you have tokens, you can user the staking interface to auction a slot.

Use the submitPeriod(yourSlotId, previousRoot, newRoot) function from the ABI to submit a new Block.

Clone this wiki locally