[
  {
    "path": ".gitignore",
    "content": "# Logs\nlogs\n*.log\nnpm-debug.log*\nyarn-debug.log*\nyarn-error.log*\n\n# Runtime data\npids\n*.pid\n*.seed\n*.pid.lock\n\n# Directory for instrumented libs generated by jscoverage/JSCover\nlib-cov\n\n# Coverage directory used by tools like istanbul\ncoverage\n\n# nyc test coverage\n.nyc_output\n\n# Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files)\n.grunt\n\n# Bower dependency directory (https://bower.io/)\nbower_components\n\n# node-waf configuration\n.lock-wscript\n\n# Compiled binary addons (http://nodejs.org/api/addons.html)\nbuild/Release\n\n# Dependency directories\nnode_modules/\njspm_packages/\n\n# Typescript v1 declaration files\ntypings/\n\n# Optional npm cache directory\n.npm\n\n# Optional eslint cache\n.eslintcache\n\n# Optional REPL history\n.node_repl_history\n\n# Output of 'npm pack'\n*.tgz\n\n# Yarn Integrity file\n.yarn-integrity\n\n# dotenv environment variables file\n.env\n\n#VSCode settings\n.vscode\n\ndb/\ndocker-compose.yml\n\nprivatekey.*\ncertificate.*\nbuild/*\nbuild/**\nbuild"
  },
  {
    "path": "CODE_OF_CONDUCT.md",
    "content": "# Code of Conduct\n\n## 1. Purpose\n\nA primary goal of Plasma ETHexchange is to be inclusive to the largest number of contributors, with the most varied and diverse backgrounds possible. As such, we are committed to providing a friendly, safe and welcoming environment for all, regardless of gender, sexual orientation, ability, ethnicity, socioeconomic status, and religion (or lack thereof).\n\nThis code of conduct outlines our expectations for all those who participate in our community, as well as the consequences for unacceptable behavior.\n\nWe invite all those who participate in Plasma ETHexchange to help us create safe and positive experiences for everyone.\n\n## 2. Open Source Citizenship\n\nA supplemental goal of this Code of Conduct is to increase open source citizenship by encouraging participants to recognize and strengthen the relationships between our actions and their effects on our community.\n\nCommunities mirror the societies in which they exist and positive action is essential to counteract the many forms of inequality and abuses of power that exist in society.\n\nIf you see someone who is making an extra effort to ensure our community is welcoming, friendly, and encourages all participants to contribute to the fullest extent, we want to know.\n\n## 3. Expected Behavior\n\nThe following behaviors are expected and requested of all community members:\n\n*   Participate in an authentic and active way. In doing so, you contribute to the health and longevity of this community.\n*   Exercise consideration and respect in your speech and actions.\n*   Attempt collaboration before conflict.\n*   Refrain from demeaning, discriminatory, or harassing behavior and speech.\n*   Be mindful of your surroundings and of your fellow participants. Alert community leaders if you notice a dangerous situation, someone in distress, or violations of this Code of Conduct, even if they seem inconsequential.\n*   Remember that community event venues may be shared with members of the public; please be respectful to all patrons of these locations.\n\n## 4. Unacceptable Behavior\n\nThe following behaviors are considered harassment and are unacceptable within our community:\n\n*   Violence, threats of violence or violent language directed against another person.\n*   Sexist, racist, homophobic, transphobic, ableist or otherwise discriminatory jokes and language.\n*   Posting or displaying sexually explicit or violent material.\n*   Posting or threatening to post other people’s personally identifying information (\"doxing\").\n*   Personal insults, particularly those related to gender, sexual orientation, race, religion, or disability.\n*   Inappropriate photography or recording.\n*   Inappropriate physical contact. You should have someone’s consent before touching them.\n*   Unwelcome sexual attention. This includes, sexualized comments or jokes; inappropriate touching, groping, and unwelcomed sexual advances.\n*   Deliberate intimidation, stalking or following (online or in person).\n*   Advocating for, or encouraging, any of the above behavior.\n*   Sustained disruption of community events, including talks and presentations.\n\n## 5. Consequences of Unacceptable Behavior\n\nUnacceptable behavior from any community member, including sponsors and those with decision-making authority, will not be tolerated.\n\nAnyone asked to stop unacceptable behavior is expected to comply immediately.\n\nIf a community member engages in unacceptable behavior, the community organizers may take any action they deem appropriate, up to and including a temporary ban or permanent expulsion from the community without warning (and without refund in the case of a paid event).\n\n## 6. Reporting Guidelines\n\nIf you are subject to or witness unacceptable behavior, or have any other concerns, please notify a community organizer as soon as possible. pk@bankex.com.\n\n[Reporting Guidelines](https://github.com/BankEx/PlasmaETHexchange/issues)\n\nAdditionally, community organizers are available to help community members engage with local law enforcement or to otherwise help those experiencing unacceptable behavior feel safe. In the context of in-person events, organizers will also provide escorts as desired by the person experiencing distress.\n\n## 7. Addressing Grievances\n\nIf you feel you have been falsely or unfairly accused of violating this Code of Conduct, you should notify BankEx with a concise description of your grievance. Your grievance will be handled in accordance with our existing governing policies.\n\n[Policy](https://bankex.com/en/docs_terms-and-conditions)\n\n## 8. Scope\n\nWe expect all community participants (contributors, paid or otherwise; sponsors; and other guests) to abide by this Code of Conduct in all community venues–online and in-person–as well as in all one-on-one communications pertaining to community business.\n\nThis code of conduct and its related procedures also applies to unacceptable behavior occurring outside the scope of community activities when such behavior has the potential to adversely affect the safety and well-being of community members.\n\n## 9. Contact info\n\npk@bankex.com\n\n## 10. License and attribution\n\nThis Code of Conduct is distributed under a [Creative Commons Attribution-ShareAlike license](http://creativecommons.org/licenses/by-sa/3.0/).\n\nPortions of text derived from the [Django Code of Conduct](https://www.djangoproject.com/conduct/) and the [Geek Feminism Anti-Harassment Policy](http://geekfeminism.wikia.com/wiki/Conference_anti-harassment/Policy).\n\nRetrieved on November 22, 2016 from [http://citizencodeofconduct.org/](http://citizencodeofconduct.org/)\n"
  },
  {
    "path": "CONTRIBUTING.md",
    "content": "# How to contribute\n\nBug reports and pull requests from users is what keeps this project working.\n\n## Basics\n\n1. Create an issue and describe your idea\n2. [Fork it](https://github.com/skywinder/github-changelog-generator/fork)\n3. Create your feature branch (`git checkout -b my-new-feature`)\n4. Commit your changes (`git commit -am 'Add some feature'`)\n5. Publish the branch (`git push origin my-new-feature`)\n6. Create a new Pull Request\n\n## Checking your work\n\n\n## Write documentation\n\nThis project has documentation in a few places:\n\n### Introduction and usage\n\nA friendly `README.md` written for many audiences.\n\n###  API documentation\n"
  },
  {
    "path": "ISSUE_TEMPLATE.md",
    "content": "To help us debug your issue please explain:\n- What you were trying to do (and why)\n- What happened (include command output)\n- What you expected to happen\n- Step-by-step reproduction instructions\n\n# Features\nPlease replace this section with:\n- a detailed description of your proposed feature\n- the motivation for the feature\n- how the feature would be relevant to at least 90% of Plasma users\n"
  },
  {
    "path": "Insomnia.json",
    "content": "{\n\t\"_type\": \"export\",\n\t\"__export_format\": 3,\n\t\"__export_date\": \"2017-11-10T15:02:45.828Z\",\n\t\"__export_source\": \"insomnia.desktop.app:v5.10.1\",\n\t\"resources\": [\n\t\t{\n\t\t\t\"_id\": \"wrk_72161b99e8634d158bc3b1e56cafd7e1\",\n\t\t\t\"parentId\": null,\n\t\t\t\"modified\": 1510041196483,\n\t\t\t\"created\": 1508971278767,\n\t\t\t\"name\": \"Plasma\",\n\t\t\t\"description\": \"\",\n\t\t\t\"_type\": \"workspace\"\n\t\t},\n\t\t{\n\t\t\t\"_id\": \"env_0f55f98b561842268c9408cfd8671a2d\",\n\t\t\t\"parentId\": \"wrk_72161b99e8634d158bc3b1e56cafd7e1\",\n\t\t\t\"modified\": 1508971278770,\n\t\t\t\"created\": 1508971278770,\n\t\t\t\"name\": \"Base Environment\",\n\t\t\t\"data\": {},\n\t\t\t\"color\": null,\n\t\t\t\"isPrivate\": false,\n\t\t\t\"_type\": \"environment\"\n\t\t},\n\t\t{\n\t\t\t\"_id\": \"fld_5cd6b9f637bd450180501c351f45b0f6\",\n\t\t\t\"parentId\": \"wrk_72161b99e8634d158bc3b1e56cafd7e1\",\n\t\t\t\"modified\": 1510070686707,\n\t\t\t\"created\": 1510070686707,\n\t\t\t\"name\": \"Plasma\",\n\t\t\t\"description\": \"\",\n\t\t\t\"environment\": {},\n\t\t\t\"metaSortKey\": -1510070686707,\n\t\t\t\"_type\": \"request_group\"\n\t\t},\n\t\t{\n\t\t\t\"_id\": \"req_496880772a9a4bda9ab99e49a97c95d8\",\n\t\t\t\"parentId\": \"fld_5cd6b9f637bd450180501c351f45b0f6\",\n\t\t\t\"modified\": 1510183267403,\n\t\t\t\"created\": 1510070694280,\n\t\t\t\"url\": \"http://127.0.0.1:8000/fundPlasma\",\n\t\t\t\"name\": \"Fund Plasma\",\n\t\t\t\"description\": \"\",\n\t\t\t\"method\": \"POST\",\n\t\t\t\"body\": {\n\t\t\t\t\"mimeType\": \"application/json\",\n\t\t\t\t\"text\": \"{\\n\\t\\\"toAddress\\\" : \\\"0xf62803ffaddda373d44b10bf6bb404909be0e66b\\\"\\n}\"\n\t\t\t},\n\t\t\t\"parameters\": [],\n\t\t\t\"headers\": [\n\t\t\t\t{\n\t\t\t\t\t\"name\": \"Content-Type\",\n\t\t\t\t\t\"value\": \"application/json\",\n\t\t\t\t\t\"id\": \"pair_5175b94eb4d646a2a547812d2bf19ef4\"\n\t\t\t\t}\n\t\t\t],\n\t\t\t\"authentication\": {},\n\t\t\t\"metaSortKey\": -1510070694280,\n\t\t\t\"settingStoreCookies\": true,\n\t\t\t\"settingSendCookies\": true,\n\t\t\t\"settingDisableRenderRequestBody\": false,\n\t\t\t\"settingEncodeUrl\": true,\n\t\t\t\"_type\": \"request\"\n\t\t},\n\t\t{\n\t\t\t\"_id\": \"req_e42979a812a34f7a807fbe86041bc175\",\n\t\t\t\"parentId\": \"fld_5cd6b9f637bd450180501c351f45b0f6\",\n\t\t\t\"modified\": 1510305375257,\n\t\t\t\"created\": 1510184784598,\n\t\t\t\"url\": \"http://127.0.0.1:8000/plasmaBlock/1\",\n\t\t\t\"name\": \"Get block by number\",\n\t\t\t\"description\": \"\",\n\t\t\t\"method\": \"GET\",\n\t\t\t\"body\": {\n\t\t\t\t\"mimeType\": \"application/json\",\n\t\t\t\t\"text\": \"\"\n\t\t\t},\n\t\t\t\"parameters\": [],\n\t\t\t\"headers\": [\n\t\t\t\t{\n\t\t\t\t\t\"name\": \"Content-Type\",\n\t\t\t\t\t\"value\": \"application/json\",\n\t\t\t\t\t\"id\": \"pair_5175b94eb4d646a2a547812d2bf19ef4\"\n\t\t\t\t}\n\t\t\t],\n\t\t\t\"authentication\": {},\n\t\t\t\"metaSortKey\": -1509885060592.5,\n\t\t\t\"settingStoreCookies\": true,\n\t\t\t\"settingSendCookies\": true,\n\t\t\t\"settingDisableRenderRequestBody\": false,\n\t\t\t\"settingEncodeUrl\": true,\n\t\t\t\"_type\": \"request\"\n\t\t},\n\t\t{\n\t\t\t\"_id\": \"req_a33f04b400e74ce2a9aad20c85d71129\",\n\t\t\t\"parentId\": \"fld_5cd6b9f637bd450180501c351f45b0f6\",\n\t\t\t\"modified\": 1510214454668,\n\t\t\t\"created\": 1510189145263,\n\t\t\t\"url\": \"http://127.0.0.1:8000/sendAndSign\",\n\t\t\t\"name\": \"Create and sign transaction\",\n\t\t\t\"description\": \"\",\n\t\t\t\"method\": \"POST\",\n\t\t\t\"body\": {\n\t\t\t\t\"mimeType\": \"application/json\",\n\t\t\t\t\"text\": \"{\\n    \\\"from\\\": \\\"0xf62803ffaddda373d44b10bf6bb404909be0e66b\\\",\\n    \\\"txType\\\" : 1,\\n    \\\"inputs\\\": [\\n\\t\\t\\t{\\n            \\\"blockNumber\\\": 1,\\n            \\\"txNumber\\\": 0,\\n            \\\"outputNumber\\\" : 1\\n\\t\\t\\t}\\n\\t\\t],\\n    \\\"outputs\\\": [{\\n            \\\"to\\\": \\\"0xcf78f18299eac0e0a238db7f4742ef433f98c85e\\\",\\n            \\\"amount\\\": \\\"50000000000000000\\\"\\n            },\\n\\t\\t\\t\\t\\t\\t\\t {\\n            \\\"to\\\": \\\"0xf62803ffaddda373d44b10bf6bb404909be0e66b\\\",\\n            \\\"amount\\\": \\\"50000000000000000\\\"\\n            }]\\n}\"\n\t\t\t},\n\t\t\t\"parameters\": [],\n\t\t\t\"headers\": [\n\t\t\t\t{\n\t\t\t\t\t\"name\": \"Content-Type\",\n\t\t\t\t\t\"value\": \"application/json\",\n\t\t\t\t\t\"id\": \"pair_5175b94eb4d646a2a547812d2bf19ef4\"\n\t\t\t\t}\n\t\t\t],\n\t\t\t\"authentication\": {},\n\t\t\t\"metaSortKey\": -1509977877436.25,\n\t\t\t\"settingStoreCookies\": true,\n\t\t\t\"settingSendCookies\": true,\n\t\t\t\"settingDisableRenderRequestBody\": false,\n\t\t\t\"settingEncodeUrl\": true,\n\t\t\t\"_type\": \"request\"\n\t\t},\n\t\t{\n\t\t\t\"_id\": \"req_84350a0776b6480587e064f4acf83887\",\n\t\t\t\"parentId\": \"fld_5cd6b9f637bd450180501c351f45b0f6\",\n\t\t\t\"modified\": 1510215077681,\n\t\t\t\"created\": 1510215037642,\n\t\t\t\"url\": \"http://127.0.0.1:8000/utxos/0xf62803ffaddda373d44b10bf6bb404909be0e66b\",\n\t\t\t\"name\": \"Get UTXOs for address\",\n\t\t\t\"description\": \"\",\n\t\t\t\"method\": \"GET\",\n\t\t\t\"body\": {\n\t\t\t\t\"mimeType\": \"application/json\",\n\t\t\t\t\"text\": \"\"\n\t\t\t},\n\t\t\t\"parameters\": [],\n\t\t\t\"headers\": [\n\t\t\t\t{\n\t\t\t\t\t\"name\": \"Content-Type\",\n\t\t\t\t\t\"value\": \"application/json\",\n\t\t\t\t\t\"id\": \"pair_5175b94eb4d646a2a547812d2bf19ef4\"\n\t\t\t\t}\n\t\t\t],\n\t\t\t\"authentication\": {},\n\t\t\t\"metaSortKey\": -1509792243748.75,\n\t\t\t\"settingStoreCookies\": true,\n\t\t\t\"settingSendCookies\": true,\n\t\t\t\"settingDisableRenderRequestBody\": false,\n\t\t\t\"settingEncodeUrl\": true,\n\t\t\t\"_type\": \"request\"\n\t\t},\n\t\t{\n\t\t\t\"_id\": \"req_04f8cc0c61f64bb38274c8ace0142ddc\",\n\t\t\t\"parentId\": \"fld_5cd6b9f637bd450180501c351f45b0f6\",\n\t\t\t\"modified\": 1510215703043,\n\t\t\t\"created\": 1510215690740,\n\t\t\t\"url\": \"http://127.0.0.1:8000/utxos/0xcf78f18299eac0e0a238db7f4742ef433f98c85e\",\n\t\t\t\"name\": \"Get UTXOs for address 2\",\n\t\t\t\"description\": \"\",\n\t\t\t\"method\": \"GET\",\n\t\t\t\"body\": {\n\t\t\t\t\"mimeType\": \"application/json\",\n\t\t\t\t\"text\": \"\"\n\t\t\t},\n\t\t\t\"parameters\": [],\n\t\t\t\"headers\": [\n\t\t\t\t{\n\t\t\t\t\t\"name\": \"Content-Type\",\n\t\t\t\t\t\"value\": \"application/json\",\n\t\t\t\t\t\"id\": \"pair_5175b94eb4d646a2a547812d2bf19ef4\"\n\t\t\t\t}\n\t\t\t],\n\t\t\t\"authentication\": {},\n\t\t\t\"metaSortKey\": -1509745835326.875,\n\t\t\t\"settingStoreCookies\": true,\n\t\t\t\"settingSendCookies\": true,\n\t\t\t\"settingDisableRenderRequestBody\": false,\n\t\t\t\"settingEncodeUrl\": true,\n\t\t\t\"_type\": \"request\"\n\t\t},\n\t\t{\n\t\t\t\"_id\": \"req_c0df9f648f0b4e388b33c0b798486941\",\n\t\t\t\"parentId\": \"fld_5cd6b9f637bd450180501c351f45b0f6\",\n\t\t\t\"modified\": 1510267092689,\n\t\t\t\"created\": 1510244074849,\n\t\t\t\"url\": \"http://127.0.0.1:8000/sendAndSign\",\n\t\t\t\"name\": \"Create and sign withdraw\",\n\t\t\t\"description\": \"\",\n\t\t\t\"method\": \"POST\",\n\t\t\t\"body\": {\n\t\t\t\t\"mimeType\": \"application/json\",\n\t\t\t\t\"text\": \"{\\n    \\\"from\\\": \\\"0xf62803ffaddda373d44b10bf6bb404909be0e66b\\\",\\n    \\\"txType\\\" : 3,\\n    \\\"inputs\\\": [\\n\\t\\t\\t{\\n            \\\"blockNumber\\\": 1,\\n            \\\"txNumber\\\": 0,\\n            \\\"outputNumber\\\" : 1\\n\\t\\t\\t}\\n\\t\\t],\\n    \\\"outputs\\\": [{\\n            \\\"to\\\": \\\"0x0000000000000000000000000000000000000000\\\",\\n            \\\"amount\\\": \\\"100000000000000000\\\"\\n            }]\\n}\"\n\t\t\t},\n\t\t\t\"parameters\": [],\n\t\t\t\"headers\": [\n\t\t\t\t{\n\t\t\t\t\t\"name\": \"Content-Type\",\n\t\t\t\t\t\"value\": \"application/json\",\n\t\t\t\t\t\"id\": \"pair_5175b94eb4d646a2a547812d2bf19ef4\"\n\t\t\t\t}\n\t\t\t],\n\t\t\t\"authentication\": {},\n\t\t\t\"metaSortKey\": -1509931469014.375,\n\t\t\t\"settingStoreCookies\": true,\n\t\t\t\"settingSendCookies\": true,\n\t\t\t\"settingDisableRenderRequestBody\": false,\n\t\t\t\"settingEncodeUrl\": true,\n\t\t\t\"_type\": \"request\"\n\t\t},\n\t\t{\n\t\t\t\"_id\": \"req_7cb4be30021041cd9f72c3bf0f569d68\",\n\t\t\t\"parentId\": \"fld_5cd6b9f637bd450180501c351f45b0f6\",\n\t\t\t\"modified\": 1510305541259,\n\t\t\t\"created\": 1510244291999,\n\t\t\t\"url\": \"http://127.0.0.1:8000/startWithdraw\",\n\t\t\t\"name\": \"Start withdraw\",\n\t\t\t\"description\": \"\",\n\t\t\t\"method\": \"POST\",\n\t\t\t\"body\": {\n\t\t\t\t\"mimeType\": \"application/json\",\n\t\t\t\t\"text\": \"{\\n    \\\"from\\\": \\\"0xf62803ffaddda373d44b10bf6bb404909be0e66b\\\",\\n\\t\\t\\\"blockNumber\\\": 1,\\n\\t\\t\\\"txNumber\\\": 0,\\n\\t\\t\\\"txOutputNumber\\\":1\\n}\"\n\t\t\t},\n\t\t\t\"parameters\": [],\n\t\t\t\"headers\": [\n\t\t\t\t{\n\t\t\t\t\t\"name\": \"Content-Type\",\n\t\t\t\t\t\"value\": \"application/json\",\n\t\t\t\t\t\"id\": \"pair_5175b94eb4d646a2a547812d2bf19ef4\"\n\t\t\t\t}\n\t\t\t],\n\t\t\t\"authentication\": {},\n\t\t\t\"metaSortKey\": -1509908264803.4375,\n\t\t\t\"settingStoreCookies\": true,\n\t\t\t\"settingSendCookies\": true,\n\t\t\t\"settingDisableRenderRequestBody\": false,\n\t\t\t\"settingEncodeUrl\": true,\n\t\t\t\"_type\": \"request\"\n\t\t},\n\t\t{\n\t\t\t\"_id\": \"req_299420c3887845f2a89f177d291ec288\",\n\t\t\t\"parentId\": \"fld_5cd6b9f637bd450180501c351f45b0f6\",\n\t\t\t\"modified\": 1510267464215,\n\t\t\t\"created\": 1510267369128,\n\t\t\t\"url\": \"http://127.0.0.1:8000/plasmaParent/blockHeader/1\",\n\t\t\t\"name\": \"Get header by number\",\n\t\t\t\"description\": \"\",\n\t\t\t\"method\": \"GET\",\n\t\t\t\"body\": {\n\t\t\t\t\"mimeType\": \"application/json\",\n\t\t\t\t\"text\": \"\"\n\t\t\t},\n\t\t\t\"parameters\": [],\n\t\t\t\"headers\": [\n\t\t\t\t{\n\t\t\t\t\t\"name\": \"Content-Type\",\n\t\t\t\t\t\"value\": \"application/json\",\n\t\t\t\t\t\"id\": \"pair_5175b94eb4d646a2a547812d2bf19ef4\"\n\t\t\t\t}\n\t\t\t],\n\t\t\t\"authentication\": {},\n\t\t\t\"metaSortKey\": -1509838652170.625,\n\t\t\t\"settingStoreCookies\": true,\n\t\t\t\"settingSendCookies\": true,\n\t\t\t\"settingDisableRenderRequestBody\": false,\n\t\t\t\"settingEncodeUrl\": true,\n\t\t\t\"_type\": \"request\"\n\t\t},\n\t\t{\n\t\t\t\"_id\": \"req_a0b739936b654841a59b89ac29b1629b\",\n\t\t\t\"parentId\": \"fld_5cd6b9f637bd450180501c351f45b0f6\",\n\t\t\t\"modified\": 1510303494213,\n\t\t\t\"created\": 1510267382301,\n\t\t\t\"url\": \"http://127.0.0.1:8000/plasmaParent/withdrawRecord/8589934592\",\n\t\t\t\"name\": \"Get withdraw record by index\",\n\t\t\t\"description\": \"\",\n\t\t\t\"method\": \"GET\",\n\t\t\t\"body\": {\n\t\t\t\t\"mimeType\": \"application/json\",\n\t\t\t\t\"text\": \"\"\n\t\t\t},\n\t\t\t\"parameters\": [],\n\t\t\t\"headers\": [\n\t\t\t\t{\n\t\t\t\t\t\"name\": \"Content-Type\",\n\t\t\t\t\t\"value\": \"application/json\",\n\t\t\t\t\t\"id\": \"pair_5175b94eb4d646a2a547812d2bf19ef4\"\n\t\t\t\t}\n\t\t\t],\n\t\t\t\"authentication\": {},\n\t\t\t\"metaSortKey\": -1509815447959.6875,\n\t\t\t\"settingStoreCookies\": true,\n\t\t\t\"settingSendCookies\": true,\n\t\t\t\"settingDisableRenderRequestBody\": false,\n\t\t\t\"settingEncodeUrl\": true,\n\t\t\t\"_type\": \"request\"\n\t\t},\n\t\t{\n\t\t\t\"_id\": \"req_c372e3e5120345718c276deaf2f21d4c\",\n\t\t\t\"parentId\": \"fld_5cd6b9f637bd450180501c351f45b0f6\",\n\t\t\t\"modified\": 1510267625322,\n\t\t\t\"created\": 1510267588233,\n\t\t\t\"url\": \"http://127.0.0.1:8000/ethereumBalance/0xf62803ffaddda373d44b10bf6bb404909be0e66b\",\n\t\t\t\"name\": \"Get balance for address\",\n\t\t\t\"description\": \"\",\n\t\t\t\"method\": \"GET\",\n\t\t\t\"body\": {\n\t\t\t\t\"mimeType\": \"application/json\",\n\t\t\t\t\"text\": \"\"\n\t\t\t},\n\t\t\t\"parameters\": [],\n\t\t\t\"headers\": [\n\t\t\t\t{\n\t\t\t\t\t\"name\": \"Content-Type\",\n\t\t\t\t\t\"value\": \"application/json\",\n\t\t\t\t\t\"id\": \"pair_5175b94eb4d646a2a547812d2bf19ef4\"\n\t\t\t\t}\n\t\t\t],\n\t\t\t\"authentication\": {},\n\t\t\t\"metaSortKey\": -1509803845854.2188,\n\t\t\t\"settingStoreCookies\": true,\n\t\t\t\"settingSendCookies\": true,\n\t\t\t\"settingDisableRenderRequestBody\": false,\n\t\t\t\"settingEncodeUrl\": true,\n\t\t\t\"_type\": \"request\"\n\t\t},\n\t\t{\n\t\t\t\"_id\": \"req_48d2d185224348bfa5007499e46aae0a\",\n\t\t\t\"parentId\": \"fld_5cd6b9f637bd450180501c351f45b0f6\",\n\t\t\t\"modified\": 1510267853919,\n\t\t\t\"created\": 1510267804004,\n\t\t\t\"url\": \"http://127.0.0.1:8000/ethereumBalance/0x8C05d5F202e9cab29a48b2DcBc2050bC3E20ae9c\",\n\t\t\t\"name\": \"Get balance for contract\",\n\t\t\t\"description\": \"\",\n\t\t\t\"method\": \"GET\",\n\t\t\t\"body\": {\n\t\t\t\t\"mimeType\": \"application/json\",\n\t\t\t\t\"text\": \"\"\n\t\t\t},\n\t\t\t\"parameters\": [],\n\t\t\t\"headers\": [\n\t\t\t\t{\n\t\t\t\t\t\"name\": \"Content-Type\",\n\t\t\t\t\t\"value\": \"application/json\",\n\t\t\t\t\t\"id\": \"pair_5175b94eb4d646a2a547812d2bf19ef4\"\n\t\t\t\t}\n\t\t\t],\n\t\t\t\"authentication\": {},\n\t\t\t\"metaSortKey\": -1509798044801.4844,\n\t\t\t\"settingStoreCookies\": true,\n\t\t\t\"settingSendCookies\": true,\n\t\t\t\"settingDisableRenderRequestBody\": false,\n\t\t\t\"settingEncodeUrl\": true,\n\t\t\t\"_type\": \"request\"\n\t\t},\n\t\t{\n\t\t\t\"_id\": \"req_8714811c360f449d8f1273b6e096aeda\",\n\t\t\t\"parentId\": \"fld_5cd6b9f637bd450180501c351f45b0f6\",\n\t\t\t\"modified\": 1510306797552,\n\t\t\t\"created\": 1510306761757,\n\t\t\t\"url\": \"http://127.0.0.1:8000/finalizeWithdrawExpress\",\n\t\t\t\"name\": \"Finalize withdraw express\",\n\t\t\t\"description\": \"\",\n\t\t\t\"method\": \"POST\",\n\t\t\t\"body\": {\n\t\t\t\t\"mimeType\": \"application/json\",\n\t\t\t\t\"text\": \"{\\n    \\\"from\\\": \\\"0xf62803ffaddda373d44b10bf6bb404909be0e66b\\\",\\n\\t\\t\\\"blockNumber\\\": 2,\\n\\t\\t\\\"txNumber\\\": 0,\\n\\t\\t\\\"txOutputNumber\\\":1\\n}\"\n\t\t\t},\n\t\t\t\"parameters\": [],\n\t\t\t\"headers\": [\n\t\t\t\t{\n\t\t\t\t\t\"name\": \"Content-Type\",\n\t\t\t\t\t\"value\": \"application/json\",\n\t\t\t\t\t\"id\": \"pair_5175b94eb4d646a2a547812d2bf19ef4\"\n\t\t\t\t}\n\t\t\t],\n\t\t\t\"authentication\": {},\n\t\t\t\"metaSortKey\": -1509896662697.9688,\n\t\t\t\"settingStoreCookies\": true,\n\t\t\t\"settingSendCookies\": true,\n\t\t\t\"settingDisableRenderRequestBody\": false,\n\t\t\t\"settingEncodeUrl\": true,\n\t\t\t\"_type\": \"request\"\n\t\t},\n\t\t{\n\t\t\t\"_id\": \"req_37bf10316d7d4417b97f4eb9413309e4\",\n\t\t\t\"parentId\": \"fld_5cd6b9f637bd450180501c351f45b0f6\",\n\t\t\t\"modified\": 1510323439429,\n\t\t\t\"created\": 1510323286024,\n\t\t\t\"url\": \"http://127.0.0.1:8000/plasmaParent/depositRecord/0x0000000000000000000000000000000000000000000000000000000200000000\",\n\t\t\t\"name\": \"Get deposit record by index\",\n\t\t\t\"description\": \"\",\n\t\t\t\"method\": \"GET\",\n\t\t\t\"body\": {\n\t\t\t\t\"mimeType\": \"application/json\",\n\t\t\t\t\"text\": \"\"\n\t\t\t},\n\t\t\t\"parameters\": [],\n\t\t\t\"headers\": [\n\t\t\t\t{\n\t\t\t\t\t\"name\": \"Content-Type\",\n\t\t\t\t\t\"value\": \"application/json\",\n\t\t\t\t\t\"id\": \"pair_5175b94eb4d646a2a547812d2bf19ef4\"\n\t\t\t\t}\n\t\t\t],\n\t\t\t\"authentication\": {},\n\t\t\t\"metaSortKey\": -1509809646906.9531,\n\t\t\t\"settingStoreCookies\": true,\n\t\t\t\"settingSendCookies\": true,\n\t\t\t\"settingDisableRenderRequestBody\": false,\n\t\t\t\"settingEncodeUrl\": true,\n\t\t\t\"_type\": \"request\"\n\t\t},\n\t\t{\n\t\t\t\"_id\": \"req_e7393b9c2f83435998ebf7c37b93241a\",\n\t\t\t\"parentId\": \"fld_5cd6b9f637bd450180501c351f45b0f6\",\n\t\t\t\"modified\": 1510323871557,\n\t\t\t\"created\": 1510323821224,\n\t\t\t\"url\": \"http://127.0.0.1:8000/startDepositWithdraw\",\n\t\t\t\"name\": \"Start deposit withdraw\",\n\t\t\t\"description\": \"\",\n\t\t\t\"method\": \"POST\",\n\t\t\t\"body\": {\n\t\t\t\t\"mimeType\": \"application/json\",\n\t\t\t\t\"text\": \"{\\n    \\\"from\\\": \\\"0xf62803ffaddda373d44b10bf6bb404909be0e66b\\\",\\n\\t\\t\\\"depositIndex\\\" : \\\"0x0000000000000000000000000000000000000000000000000000000200000000\\\"\\n}\"\n\t\t\t},\n\t\t\t\"parameters\": [],\n\t\t\t\"headers\": [\n\t\t\t\t{\n\t\t\t\t\t\"name\": \"Content-Type\",\n\t\t\t\t\t\"value\": \"application/json\",\n\t\t\t\t\t\"id\": \"pair_5175b94eb4d646a2a547812d2bf19ef4\"\n\t\t\t\t}\n\t\t\t],\n\t\t\t\"authentication\": {},\n\t\t\t\"metaSortKey\": -1509902463750.7031,\n\t\t\t\"settingStoreCookies\": true,\n\t\t\t\"settingSendCookies\": true,\n\t\t\t\"settingDisableRenderRequestBody\": false,\n\t\t\t\"settingEncodeUrl\": true,\n\t\t\t\"_type\": \"request\"\n\t\t},\n\t\t{\n\t\t\t\"_id\": \"req_7a1691fbd1bb4a59ba7008b64a39af3d\",\n\t\t\t\"parentId\": \"fld_5cd6b9f637bd450180501c351f45b0f6\",\n\t\t\t\"modified\": 1510324284338,\n\t\t\t\"created\": 1510324254548,\n\t\t\t\"url\": \"http://127.0.0.1:8000/challengeDepositWithdraw\",\n\t\t\t\"name\": \"Challenge deposit withdraw\",\n\t\t\t\"description\": \"\",\n\t\t\t\"method\": \"POST\",\n\t\t\t\"body\": {\n\t\t\t\t\"mimeType\": \"application/json\",\n\t\t\t\t\"text\": \"{\\n    \\\"blockNumber\\\": 1,\\n\\t\\t\\\"txNumber\\\": 0,\\n\\t\\t\\\"depositIndex\\\" : \\\"0x0000000000000000000000000000000000000000000000000000000200000000\\\"\\n}\"\n\t\t\t},\n\t\t\t\"parameters\": [],\n\t\t\t\"headers\": [\n\t\t\t\t{\n\t\t\t\t\t\"name\": \"Content-Type\",\n\t\t\t\t\t\"value\": \"application/json\",\n\t\t\t\t\t\"id\": \"pair_5175b94eb4d646a2a547812d2bf19ef4\"\n\t\t\t\t}\n\t\t\t],\n\t\t\t\"authentication\": {},\n\t\t\t\"metaSortKey\": -1509899563224.336,\n\t\t\t\"settingStoreCookies\": true,\n\t\t\t\"settingSendCookies\": true,\n\t\t\t\"settingDisableRenderRequestBody\": false,\n\t\t\t\"settingEncodeUrl\": true,\n\t\t\t\"_type\": \"request\"\n\t\t}\n\t]\n}"
  },
  {
    "path": "LICENSE",
    "content": "MIT License\n\nCopyright (c) 2017 BANKEX - Proof-of-Asset Protocol\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\nSOFTWARE.\n"
  },
  {
    "path": "README.md",
    "content": "![bkx-plasma-github 2](https://user-images.githubusercontent.com/3356474/34122937-0c1e8f34-e43f-11e7-987c-0fb382751eaa.png)\n\n# Plasma protocol compatible ETH Exchange Platform\n\nThis is a wrapper and demo page. \nPlasma like implementation and Parent smart contract [placed in BANKEX/PlasmaParentContract](https://github.com/BANKEX/PlasmaParentContract)*\n\n\n### Plasma protocol DEMO:\nhttps://plasma.bankex.com\n### Source-code :octocat:\nhttps://github.com/BankEx/plasma_client\n\n# Public beta 1 features\n\nThe public beta will be deployed on Rinkeby network. Link: TBA\n\nFor Beta 1 only basic functions are enabled with non-optimized UI:\n1. Deposit on the main chain\n2. Transact in Plasma chain - split, merge, transfer, express withdraw\n3. Only express withdraw is allowed for user experience - it's a two-step process: \n    \n    Burn ETH in Plasma by submitting output to address 0x0\n\n    Submit proof of such transaction to the smart contract on the main chain to withdraw on the main chain\n\n## Important features and limitations\n- The function of Web3 to sign arbitrary data is used to proof your ownership of the address.\n- #### Signature format is different from the signature format of Ethereum transactions, and any derived transaction can not be used to make fraudulent transaction on the main chain\n\n- Sum of the outputs is strictly equal to the sum of the inputs\n\n- As there is no standalone client to download and verify blocks, so there is no functionality to proof invalid transactions using the smart contract on the main chain. Wait until Beta 2\n\n- UTXOs are not automatically merged into Beta 1\n\n\n# Clarification\n\nInitial implementation of a single server-side \"Operator\" service (with some extra functionality for testing) and v0.1 smart contract for Ethereum blockchain that can be used to enforce proper behavior in case of disputes.\n\n### At the moment the groundwork is done (convenience functions + cryptography) in smart contract to continue writing required processes \"Start -> (Challenge?) -> Complete\".\n\n#### Implemented challenges:\n\n1. Deposit -> No deposit published in Plasma chain? -> Start withdrawing for deposit? -> Challenge deposit withdraw? -> Finalize\n2. Deposit -> Do few transactions -> Start UTXO withdraw -> Express withdraw / Normal withdraw\n3. Prove double spending on Plasma chain\n4. Prove spending the same output on Plasma and successfully withdrawing it\n5. Prove funding without deposit event or double funding TX of the same deposit\n\n#### Required challenges:\n1. Proof of incorrect TX: signature doesn't correspond to spent UTXOs, or amount is invalid. Special check for trying to spend auxiliary transaction output of funding transaction.\n\n## What?\n\nThe task is to make blockchain transactions as fast as they can be applied virtually to any application.\n\n## How?\n\nOne of the possible solutions is Plasma - the prominent upgrade to Ethereum blockchain. Our approach is based on this conception.\n\n## Plasma Network Technical Concept\n\nFrom a technical point of view Plasma blockchain - is just another blockchain, that can be efficiently settled to parent Ethereum chain and is well protected from the misbehavior of both Plasma operator and Plasma blockchain participants by smart-contract on Ethereum network.\n\nPlasma chain itself has a straightforward structure with assets being undividable and transferred in full from the previous owner to the next one. The transaction has inputs and outputs, with few different types of transactions depending on the required function. For example, we propose type \"Merge\" to connect two inputs into one output in order to reduce the number of UTXOs that will be followed by the client. Full description will be given when the design is more stable. All chain logic is made using Ethereum crypto primitives - sha3, secp256k1 and 65-byte signatures allowing the use of ecrecover.\n\nBlock in Plasma network has a structure of Header: ```[BlockNumber, NumberOfTransactions, ParentHash, MerkleTreeRoot, PlasmaOperatorSignature]```, where\n\n- `ParentHash` references to the previous block (by number)\n- `MerkleTreeRoot` is root hash of a Merkle tree\n- `NumberOfTransactions` transactions in this Plasma block and an array of transactions.\n\nThe header is submitted by Plasma network operator to the smart-contract on Ethereum chain. Blocks can only be sent one by one, with sequence numbering is enforced by contract. Any user of Ethereum network can deposit ETH to contract that will trigger, event and will allow Plasma network operator to make a funding transaction in a Plasma chain. Then users can freely transact in Plasma chain, with headers pushed to a parent contract in Ethereum.\n\nWhen a user wants to settle one of his transactions to the main network, he initiates a withdraw on Ethereum network by providing the reference to the transaction (in the form of `BlockNumber`, `TxNumberInBlock`, `OutputNumberInTX`), full transaction and Merkle proof that this transaction was indeed included in that block. Parent contract checks a proof versus submitted root hash for this block. If validation was successful the process of withdrawing starts. After 24 hours it can be finalized. There is a particular kind of transaction in Plasma network that can speed up a process by efficiently burning the input (sending it to `0x0`). If this block is not published by the operator, withdrawing can go as usual.\n\n\n## Technology in PoC\n\nThe concept is implemented using JS with conjunction on [Web3](https://github.com/ethereum/web3.js/) and [ethereumjs/testrpc](https://github.com/ethereumjs/testrpc) on a backend. For the sake of simplicity, all necessary functions are wrapped in REST API calls doing signatures on behalf of a predefined set of the address on a server. Further work will allow users to use wallet apps such as Metamask to initiate transactions in a Plasma network by making a signature on a client side and interacting with a parent contract on Ethereum network as usual.\n\n## Why Plasma?\n\nHere at BankEx, we believe in the efficiency of offloading of some transactions from Ethereum blockchain to Plasma chains especially if the proper incentive is present for Plasma operators to behave appropriately (such incentive can be presented in the form of competing with other operators for obtaining end-users). Another advantage is flexibility of Plasma chain implementation as long as it can be effectively cross-checked by contract on a parent chain. With the new cryptographic primitive added in Metropolis fork, one can extend our PoC implementation with transactions utilizing ring signatures of **zkSNARK**s for the privacy of end user.\n\n## Getting Started\n\n### Prerequisites\n\n* Ubuntu or similar is preferable but can also be run on Mac OS X or Windows as well\n* NodeJS version >= 8.9. Tested on 9.0\n\n### Installing\n\n#### Repository Cloning\n\n```bash\ngit clone https://github.com/BankEx/PlasmaETHexchange.git\ncd PlasmaETHexchange\n```\n\n#### Running\n\n```bash\nnpm install\nnpm run server\n```\n\n### Usage\n\nBackend ```localhost:8000/```\n\n`Insomnia.json` is an Insomnia workspace file with various testing functions, play with it.\n\n**!! May require some parameter changes in existing requests to comply with new output numbering.**\n\n#### Addresses:\n\nUser 1: `0xf62803ffaddda373d44b10bf6bb404909be0e66b`\n\nUser 2: `0xcf78f18299eac0e0a238db7f4742ef433f98c85e`\n\nOperator (oracle): `0x405aaaa4bdcda14a0af295f3669459b6b0fc8104`\n\n### Basic Plasma API description\n\n> Will be filled later\n\n## Running the tests\n\n> TBD\n\n## Code of Conduct\n\nTo have a more open and welcoming community, BankEx adheres to a\n[code of conduct](CODE_OF_CONDUCT.md).\n\n## Communication :speaker:\n\nBug reports, feature requests, patches, well-wishes are always welcome!\n\n- If you need help, [open an issue](https://github.com/BankEx/PlasmaETHexchange/issues/new).\n- If you found a bug, [open an issue](https://github.com/BankEx/PlasmaETHexchange/issues/new).\n- If you have a feature request, [open an issue](https://github.com/BankEx/PlasmaETHexchange/issues/new).\n- If you want to contribute, see [Contributing](https://github.com/BankEx/PlasmaETHexchange#contributing-octocat) section.\n\n## Contributing :octocat:\n\nI'd love to see your ideas for improving this library!\n\n* The best way to contribute is by submitting a pull request.\n* Take an inspiration at [Plasma Official page](https://plasma.io/)\n* [Fork](https://github.com/BankEx/PlasmaETHexchange/fork)\n* Please read [CONTRIBUTING.md](https://github.com/BankEx/PlasmaETHexchange/CONTRIBUTING.md) for details on our code of conduct, and the process for submitting pull requests to us.\n\n## Authors\n\n* **Alex Vlasov** - *Initial work* - [shamatar](https://github.com/shamatar)\n\nSee also the list of [contributors](https://github.com/BankEx/PlasmaETHexchange/contributors) who participated in this project.\n\n## Acknowledgments\n\n* Inspired by [Plasma protocol](https://plasma.io/)\n* Given a push to our team on [ETHWaterloo - World's Largest Ethereum Hackathon](https://ethwaterloo.com/)\n\n## License\n\nPlasmaETHexchange is available under the MIT license. See the LICENSE file for more info.\n"
  },
  {
    "path": "app/config/config.js",
    "content": "module.exports = {\n    utxoPrefix : Buffer.from('utxo'),\n    blockPrefix : Buffer.from('blk'),\n    headerPrefix : Buffer.from('hdr'),\n    transactionPrefix :Buffer.from('tx'),\n    utxoIncludingAddressPrefix:Buffer.from('utxoaddr'),\n    txForAddressIndexPrefix:Buffer.from('txsaddr'),\n    withdrawsForAddressPrefix:Buffer.from('addrwithdraws'),\n    lastEventProcessedBlockPrefix:Buffer.from('lastEthBlock'),\n    lastSubmittedHeaderPrefix:Buffer.from('lastSubmHeader'),\n    depositIndexPrefix:Buffer.from(\"deps\"),\n    makeAddressIndex: true,\n    makeTransactionIndexForAddress : true, \n    testOnRinkeby: true,\n    useSSL: false,\n    get port() {\n        if (this.useSSL) {\n            return 443\n        }\n        return 8000\n    },\n    get provider() {\n        if (this.testOnRinkeby){\n            return \"http://127.0.0.1:8545\"\n        } return \"\";\n    },\n    get deployedPlasmaContract(){\n        if (this.testOnRinkeby){\n            return \"0xd8AC480331870c5764b5430F854926b1cfd1d8B1\"\n            // return \"0x158cb5485ea2e7fe03845d45c40c63469814bd9a\"\n            return \"\"\n        } return \"\";\n    },\n    get plasmaOperatorAddress() {\n        if (this.testOnRinkeby){\n            return \"0xe6877a4d8806e9a9f12eb2e8561ea6c1db19978d\"\n        } return \"0x405aaaa4bdcda14a0af295f3669459b6b0fc8104\";\n    },\n    get plasmaOperatorPassword () {\n        if (this.testOnRinkeby){\n            return \"plasmaTest\"\n        } return \"\";\n    },\n    // plasmaOperatorPrivKeyHex: \"0x4786e8e8cc2f7b6a5504add93505553010409a49fbc626001f2f34fd194ecfef\",\n    // plasmaOperatorAddress: \"0x405aaaa4bdcda14a0af295f3669459b6b0fc8104\",\n    testAccounts: [\"0xf62803ffaddda373d44b10bf6bb404909be0e66b\", \"0xcf78f18299eac0e0a238db7f4742ef433f98c85e\"],\n    testPrivKeys: [Buffer.from(\"7e2abf9c3bcd5c08c6d2156f0d55764602aed7b584c4e95fa01578e605d4cd32\", \"hex\"),\n    Buffer.from(\"0a201a3eb00242401c2d9fffefb0ed8a126281eeae98b4225fdc7265513285a2\", \"hex\")],\n    blockTime: 30000\n}"
  },
  {
    "path": "app/endpoints/acceptAndSignTransaction.js",
    "content": "// For demo purposes only\nconst Web3 = require('web3');\nconst validateSchema = require('jsonschema').validate;\nconst config = require(\"../config/config\");\nconst testPrivKeys = config.testPrivKeys;\nconst testAccounts = config.testAccounts;\nconst ethUtil = require('ethereumjs-util'); \n\nconst transactionSchema = \n{\n    \"from\": {\"type\": \"string\", \"minLength\": 40, \"maxLength\": 42},\n    \"txType\" : {\"type\" : \"integer\", \"minimum\" : 1, \"maximum\" : 5},\n    \"inputs\": {\n        \"type\": \"array\",\n        \"items\": {\"type\": \"object\",\n            \"properties\": {\n            \"blockNumber\": {\"type\": \"integer\", \"minimum\": 1},\n            \"txNumber\": {\"type\": \"integer\", \"minimum\": 1},\n            \"outputNumber\" : {\"type\": \"integer\", \"minimum\": 1}\n            }\n        }\n    },\n    \"outputs\": {\n        \"type\": \"array\",\n        \"items\": {\"type\": \"object\",\n            \"properties\": {\n            \"to\": {\"type\": \"string\", \"minLength\": 40, \"maxLength\": 42},\n            \"amount\": {\"type\": \"string\", \"minLength\": 1},  \n            }\n        }\n    }\n}\nmodule.exports = function(app, levelDB, web3) {\n    const createTxFromJSON = require('../helpers/createTxFromJson')(levelDB);\n    app.post('/sendAndSign', 'sendAndSignPlasmaTransaction', async function(req, res){\n        try{ \n            if (!validateSchema(req.body, transactionSchema).valid) {\n                return res.json({error: true, reason: \"invalid transaction\"});\n            }\n            const from = ethUtil.addHexPrefix(req.body.from);\n            const idxInKeys = testAccounts.indexOf(from);\n            if (idxInKeys != 1 && idxInKeys != 0){\n                return res.json({error: true, reason: \"invalid transaction\"});\n            } \n            const tx = await createTxFromJSON(req.body);\n            let txRaw = ethUtil.bufferToHex(Buffer.concat(tx.clearRaw(false, false)));\n            let txHash = ethUtil.bufferToHex(tx.hash(false,false));\n            const signature = await web3.eth.sign(txRaw, from);\n            const signature2 = await web3.eth.sign(txHash, from);\n            tx.serializeSignature(signature);\n            if (!tx.validate()){\n                return res.json({error: true, reason: \"invalid transaction\"});\n            }\n            app.txQueueArray.push(tx);\n            console.log(\"Pushed new TX\")\n            return res.json({error: false, status: \"accepted\"});\n        }\n        catch(error){\n            res.json({error: true, reason: \"invalid transaction\"});\n        }\n    });\n}"
  },
  {
    "path": "app/endpoints/acceptSignedTX.js",
    "content": "// For demo purposes only\nconst Web3 = require('web3');\nconst validateSchema = require('jsonschema').validate;\nconst config = require(\"../config/config\");\nconst ethUtil = require('ethereumjs-util'); \nconst lengthConstants = require(\"../../lib/dataStructureLengths\");\nconst assert = require('assert');\n\nconst {PlasmaTransaction,\n    TxTypeFund, \n    TxTypeMerge, \n    TxTypeSplit, \n    TxTypeWithdraw, \n    TxTypeTransfer,\n    TxLengthForType,\n    NumInputsForType, \n    NumOutputsForType} = require(\"../../lib/Tx/tx\");\n\nconst transactionSchema = \n{\n    // \"from\": {\"type\": \"string\", \"minLength\": 40, \"maxLength\": 42},\n    \"txType\" : {\"type\" : \"integer\", \"minimum\" : 1, \"maximum\" : 5},\n    \"inputs\": {\n        \"type\": \"array\",\n        \"items\": {\"type\": \"object\",\n            \"properties\": {\n            \"blockNumber\": {\"type\": \"integer\", \"minimum\": 1},\n            \"txNumber\": {\"type\": \"integer\", \"minimum\": 1},\n            \"outputNumber\" : {\"type\": \"integer\", \"minimum\": 1}\n            }\n        }\n    },\n    \"outputs\": {\n        \"type\": \"array\",\n        \"items\": {\"type\": \"object\",\n            \"properties\": {\n            \"to\": {\"type\": \"string\", \"minLength\": 40, \"maxLength\": 42},\n            \"amount\": {\"type\": \"string\", \"minLength\": 1},  \n            }\n        }\n    },\n    \"signature\" : {\"type\" : \"string\", \"minLength\" :130, \"maxLength\" : 132},\n    \"required\": [\"txType\", \"inputs\", \"signature\"]\n}\nmodule.exports = function(app, levelDB, web3) {\n    const createTxFromJSON = require('../helpers/createTxFromJson')(levelDB);\n    const createWithdrawTxFromJSON = require('../helpers/createWithdrawTxFromJson')(levelDB);\n    const checkSpendingTX = require('../helpers/checkSpendingTX')(levelDB);\n    app.post('/sendSignedTX', 'endSignedTX', async function(req, res){\n        try{ \n            if (!validateSchema(req.body, transactionSchema).valid) {\n                return res.json({error: true, reason: \"invalid transaction\"});\n            }\n            const txParams = req.body;\n            const signature = req.body.signature;\n            delete txParams.signature;\n            let tx;\n            if (req.body.txType == TxTypeMerge || req.body.txType == TxTypeSplit || req.body.txType == TxTypeTransfer) {\n                tx = await createTxFromJSON(req.body);\n            } else {\n                tx = await createWithdrawTxFromJSON(req.body);\n            }\n            tx.serializeSignature(signature);\n            const validSpending = await checkSpendingTX(tx);\n            assert(validSpending);\n            const txHash = tx.hash(false, false);\n            const pubKey = ethUtil.ecrecover(txHash, ethUtil.bufferToInt(tx.v), tx.r, tx.s);\n            const signedFromAddress = ethUtil.publicToAddress(pubKey).toString('hex');\n            console.log(\"Accepted TX from address 0x\" + signedFromAddress);\n            const txIsValid = tx.validate(false);\n            assert(txIsValid);\n            app.txQueueArray.push(tx);\n            console.log(\"Pushed new TX\")\n            const txJSONrepresentation = tx.toFullJSON(true);\n            return res.json({error: false, \n                tx: txJSONrepresentation});\n        }\n        catch(error){\n            res.json({error: true, reason: \"invalid transaction\"});\n        }\n    });\n}"
  },
  {
    "path": "app/endpoints/acceptTransaction.js",
    "content": "const Web3 = require('web3');\nmodule.exports = function(app, levelDB, web3) {\n    app.post('/sendPlasmaTransaction', 'sendPlasmaTransaction', async function(req, res){\n        try{ \n            const {blockNumber, txInBlock, assetId, to, v, r, s} = req.body\n            if (!blockNumber || !txInBlock || !assetId || !to || !v || !r || !s) {\n                return res.json({error: true, reason: \"invalid transation\"});\n                // next()\n            }\n            const tx = new PlasmaTransaction({blockNumber, txInBlock, assetId, to, v, r, s})\n            if (!tx.validate()){\n                return res.json({error: true, reason: \"invalid transation\"});\n            }\n            var unspentTxRaw\n            try{\n                const keyForUtxo = Buffer.concat([utxoPrefix, tx.blockNumber, tx.txInBlock]);\n                unspentTxRaw = await levelDB.get(keyForUtxo);\n            } \n            catch(err){\n                return res.json({error: true, reason: \"invalid transation\"});\n            }\n            const unspentTx = new PlasmaTransaction(sliceRawBufferForTx(unspentTxRaw))\n            if (!unspentTx.validate()){\n                return res.json({error: true, reason: \"invalid transation\"});\n            }\n            if (!unspentTx.to.equals(tx.getSenderAddress())){\n                return res.json({error: true, reason: \"invalid transation\"});\n            }\n            txParamsFIFO.push(tx);\n            console.log(\"Pushed new TX\")\n            return res.json({error: false, status: \"accepted\"});\n        }\n        catch(error){\n            res.json({error: true, reason: \"invalid transation\"});\n    \n        }\n    })\n}"
  },
  {
    "path": "app/endpoints/auxilary.js",
    "content": "const Web3 = require('web3');\nconst BN = Web3.utils.BN;\nconst validateSchema = require('jsonschema').validate;\nconst config = require(\"../config/config\");\nconst ethUtil = require('ethereumjs-util'); \nconst assert = require('assert');\n// const testPrivKeys = config.testPrivKeys;\n// const testAccounts = config.testAccounts;\n// const plasmaOperatorPrivKeyHex = config.plasmaOperatorPrivKeyHex;\n// const plasmaOperatorPrivKey = ethUtil.toBuffer(plasmaOperatorPrivKeyHex);\nconst plasmaOperatorAddress = config.plasmaOperatorAddress;\n\n\nmodule.exports = function(app, levelDB, web3) {\n    app.get('/ethereumBalance/:address', 'balanceForAddress', async function(req, res){\n        try{ \n            let addressString = req.params.address\n            addressString = ethUtil.addHexPrefix(addressString)\n            assert(ethUtil.isValidAddress(addressString))\n            const bal = await web3.eth.getBalance(addressString);\n            return res.json({balanceInWei:bal});\n        }\n        catch(error){\n            return res.json({error: true, reason: \"invalid address\"});\n        }\n    });\n\n    app.get('/plasmaParent/depositIndexes/:address', 'getDepositRecordsForAddress', async function(req, res){\n        try{ \n            let addressString = req.params.address\n            addressString = ethUtil.addHexPrefix(addressString)\n            assert(ethUtil.isValidAddress(addressString))\n            const recordIndexes = await app.DeployedPlasmaContract.methods.depositRecordsForUser(addressString).call();\n            return res.json({depositIndexes:recordIndexes});\n        }\n        catch(error){\n            return res.json({error: true, reason: \"invalid address\"});\n        }\n    });\n\n    app.get('/plasmaParent/allDeposits/:address', 'getDepositRecordsForAddress', async function(req, res){\n        try{ \n            let addressString = req.params.address\n            addressString = ethUtil.addHexPrefix(addressString)\n            assert(ethUtil.isValidAddress(addressString))\n            const recordIndexes = await app.DeployedPlasmaContract.methods.depositRecordsForUser(addressString).call();\n            const requests = recordIndexes.map((idx) => {\n                const index = Web3.utils.toBN(idx)\n                return app.DeployedPlasmaContract.methods.depositRecords(0,index).call();\n            })\n            let results = await Promise.all(requests)\n            return res.json({error: false, depositRecords:results});\n        }\n        catch(error){\n            return res.json({error: true, reason: \"invalid address\"});\n        }\n    });\n\n    app.get('/plasmaParent/depositRecord/:recordID', 'getDepositRecord', async function(req, res){\n        try{ \n            let index = Web3.utils.toBN(req.params.recordID);\n            if (!index){\n                return res.json({error: true, reason: \"invalid record index number\"});\n            }\n            const record = await app.DeployedPlasmaContract.methods.depositRecords(0,index).call();\n            return res.json({error: false, record})\n        }\n        catch(error){\n            res.json({error: true, reason: \"invalid address\"});\n        }\n    });\n\n    app.get('/plasmaParent/lastSubmittedHeader', 'lastSubmittedHeader', async function(req, res){\n        try{ \n            const headerNumber = await app.DeployedPlasmaContract.methods.lastBlockNumber().call();\n            return res.json({error: false, lastSubmittedHeader:headerNumber});\n        }\n        catch(error){\n             return res.json({error: true, reason: \"invalid request\"});\n        }\n    });\n\n    app.get('/plasmaParent/blockHeader/:blockNumber', 'getParentContractHeader', async function(req, res){\n        try{ \n            const blockNumber = Web3.utils.toBN(req.params.blockNumber);\n            if (!blockNumber){\n                return res.json({error: true, reason: \"invalid block number\"});\n            }\n            var header = await app.DeployedPlasmaContract.methods.headers(blockNumber).call();\n            return res.json({error: false, header})\n        }\n        catch(error){\n            res.json({error: true, reason: \"invalid address\"});\n        }\n    });\n\n    app.get('/plasmaParent/withdrawIndexes/:address', 'getWithdrawRecordsForAddress', async function(req, res){\n        try{ \n            let addressString = req.params.address\n            addressString = ethUtil.addHexPrefix(addressString)\n            assert(ethUtil.isValidAddress(addressString))\n            const recordIndexes = await app.DeployedPlasmaContract.methods.withdrawRecordsForUser(addressString).call();\n            return res.json({error: false, withdrawIndexes: recordIndexes});\n        }\n        catch(error){\n            return res.json({error: true, reason: \"invalid address\"});\n        }\n    });\n    app.get('/plasmaParent/withdrawRecord/:withdrawIndex', 'getParentContractHeader', async function(req, res){\n        try{ \n            const withdrawIndex = Web3.utils.toBN(req.params.withdrawIndex);\n            if (!withdrawIndex){\n                return res.json({error: true, reason: \"invalid withdraw index number\"});\n            }\n            const record = await app.DeployedPlasmaContract.methods.withdrawRecords(0,withdrawIndex).call();\n            return res.json({error: false, withdrawRecord: record})\n        }\n        catch(error){\n            res.json({error: true, reason: \"invalid address\"});\n        }\n    });\n\n    app.get('/plasmaParent/allWithdraws/:address', 'getWithdrawRecordsForAddress', async function(req, res){\n        try{ \n            let addressString = req.params.address\n            addressString = ethUtil.addHexPrefix(addressString)\n            assert(ethUtil.isValidAddress(addressString))\n            const recordIndexes = await app.DeployedPlasmaContract.methods.withdrawRecordsForUser(addressString).call();\n            const requests = recordIndexes.map((idx) => {\n                const index = Web3.utils.toBN(idx)\n                return app.DeployedPlasmaContract.methods.withdrawRecords(0,index).call();\n            })\n            let results = await Promise.all(requests)\n            return res.json({error: false, withdrawRecords:results});\n        }\n        catch(error){\n            return res.json({error: true, reason: \"invalid address\"});\n        }\n    });\n\n}"
  },
  {
    "path": "app/endpoints/createTransactionToSign.js",
    "content": "// For demo purposes only\nconst Web3 = require('web3');\nconst validateSchema = require('jsonschema').validate;\nconst config = require(\"../config/config\");\nconst ethUtil = require('ethereumjs-util'); \nconst lengthConstants = require(\"../../lib/dataStructureLengths\");\nconst assert = require('assert');\n\nconst {PlasmaTransaction,\n    TxTypeFund, \n    TxTypeMerge, \n    TxTypeSplit, \n    TxTypeWithdraw, \n    TxTypeTransfer,\n    TxLengthForType,\n    NumInputsForType, \n    NumOutputsForType} = require(\"../../lib/Tx/tx\");\n\nconst transactionSchema = \n{\n    // \"from\": {\"type\": \"string\", \"minLength\": 40, \"maxLength\": 42},\n    \"txType\" : {\"type\" : \"integer\", \"minimum\" : 1, \"maximum\" : 5},\n    \"inputs\": {\n        \"type\": \"array\",\n        \"items\": {\"type\": \"object\",\n            \"properties\": {\n            \"blockNumber\": {\"type\": \"integer\", \"minimum\": 1},\n            \"txNumber\": {\"type\": \"integer\", \"minimum\": 1},\n            \"outputNumber\" : {\"type\": \"integer\", \"minimum\": 1}\n            }\n        }\n    },\n    \"outputs\": {\n        \"type\": \"array\",\n        \"items\": {\"type\": \"object\",\n            \"properties\": {\n            \"to\": {\"type\": \"string\", \"minLength\": 40, \"maxLength\": 42},\n            \"amount\": {\"type\": \"string\", \"minLength\": 1},  \n            }\n        }\n    },\n    \"required\": [\"txType\", \"inputs\"]\n}\nmodule.exports = function(app, levelDB, web3) {\n    const createTxFromJSON = require('../helpers/createTxFromJson')(levelDB);\n    const createWithdrawTxFromJSON = require('../helpers/createWithdrawTxFromJson')(levelDB);\n    app.post('/createTX', 'createTX', async function(req, res){\n        try{ \n            if (!validateSchema(req.body, transactionSchema).valid) {\n                return res.json({error: true, reason: \"invalid transaction\"});\n            }\n            let tx;\n            if (req.body.txType == TxTypeMerge || req.body.txType == TxTypeSplit || req.body.txType == TxTypeTransfer) {\n                tx = await createTxFromJSON(req.body);\n            } else {\n                tx = await createWithdrawTxFromJSON(req.body);\n            }\n            const txErrors = tx.validate(true);\n            assert(txErrors=='Invalid Signature');\n            const txRawNoNumber = Buffer.concat(tx.clearRaw(false, false));\n            const txJSONrepresentation = tx.toFullJSON(true);\n            const prefix = ethUtil.toBuffer(\"\\x19Ethereum Signed Message:\\n\" + txRawNoNumber.length)\n            const stringToSign = prefix.toString('hex') + txRawNoNumber.toString('hex');\n            const txPersonalHash = tx.hash(false, false);\n            return res.json({error: false, \n                tx: txJSONrepresentation, \n                txHex: \"0x\"+txRawNoNumber.toString('hex'),\n                txPersonalHash: \"0x\"+txPersonalHash.toString('hex'),\n                txPersonalMessage: \"0x\"+stringToSign});\n        }\n        catch(error){\n            res.json({error: true, reason: \"invalid transaction\"});\n        }\n    });\n}"
  },
  {
    "path": "app/endpoints/fundPlasma.js",
    "content": "const Web3 = require('web3');\nconst BN = Web3.utils.BN;\nconst ethUtil = require('ethereumjs-util');\nconst config = require('../config/config');\nconst plasmaOperatorAddress = config.plasmaOperatorAddress;\nconst assert = require('assert');\nconst {PlasmaTransaction,\n    TxTypeFund, \n    TxTypeMerge, \n    TxTypeSplit, \n    TxTypeWithdraw, \n    TxTypeTransfer, \n    TxLengthForType,\n    NumInputsForType,\n    NumOutputsForType} = require('../../lib/Tx/tx');\n\nmodule.exports = function(app, levelDB, web3) {\n    const DeployedPlasmaContract = app.DeployedPlasmaContract;\n    const processDepositEvent = require('../helpers/processDepositEvent')(app.txQueueArray);\n    const getBlockByNumber = require('../helpers/getBlock')(levelDB);\n    const prepareProofsForWithdraw = require('../helpers/prepareProofForTX')(levelDB);\n    const getTX = require('../helpers/getTX')(levelDB);\n    app.post('/fundPlasma', 'fundPlasma', async function(req, res){\n        try{ \n            const {toAddress} = req.body\n            if (!toAddress) {\n                return res.json({error: true, reason: \"invalid transaction\"});\n            }\n            var result = await DeployedPlasmaContract.methods.deposit().send({from: toAddress, value: Web3.utils.toWei(0.1, 'ether'), gas: 3000000});\n            if (!result) {\n                return res.json({error: true, reason: \"invalid transaction\"});\n            }\n            const depositEvent = result.events.DepositEvent\n            // processDepositEvent(depositEvent)\n            return res.json({error: false, depositEvent});\n        }\n        catch(error){\n             res.json({error: true, reason: \"invalid transaction\"});\n        }\n    });\n\n\n    app.post('/startDepositWithdraw', 'fundPlasma', async function(req, res){\n        try{ \n            const {from, depositIndex} = req.body\n            if (!from || !depositIndex) {\n                return res.json({error: true, reason: \"invalid transaction\"});\n            }\n            const index = Web3.utils.toBN(depositIndex);\n            var result = await DeployedPlasmaContract.methods.startDepositWithdraw(index).send({from: from, gas: 3000000});\n            if (!result) {\n                return res.json({error: true, reason: \"invalid transaction\"});\n            }\n            const depositWithdrawStartedEvent = result.events.DepositWithdrawStartedEvent;\n            return res.json({error: false, depositWithdrawStartedEvent});\n        }\n        catch(error){\n             res.json({error: true, reason: \"invalid transaction\"});\n        }\n    });\n\n    app.post('/challengeDepositWithdraw', 'fundPlasma', async function(req, res){\n        try{ \n            const {blockNumber, txNumber, depositIndex} = req.body\n            if (!blockNumber || !depositIndex) {\n                return res.json({error: true, reason: \"invalid transaction\"});\n            }\n            const index = Web3.utils.toBN(depositIndex);\n            const txNumberInBlock = txNumber;\n            const tx = await getTX(blockNumber, txNumberInBlock);\n            if (!tx) {\n                return res.json({error: true, reason: \"invalid transaction\"});\n            }\n            assert(tx.transactionTypeUInt() == TxTypeFund)\n            const preparedProof = await prepareProofsForWithdraw(blockNumber, txNumberInBlock);\n            const result = await app.DeployedPlasmaContract.methods.challengeDepositWithdraw(index, preparedProof.blockNumber, \n                // preparedProof.txNumberInBlock, \n                preparedProof.tx, preparedProof.merkleProof ).send({from:plasmaOperatorAddress, gas: 3.6e6});\n            const depositWithdrawChallengedEvent = result.events.DepositWithdrawChallengedEvent;\n            const response = {error: false, depositWithdrawChallengedEvent};\n            return res.json(response);\n        }\n        catch(error){\n            res.json({error: true, reason: \"invalid transaction\"});\n        }\n    });\n\n}\n"
  },
  {
    "path": "app/endpoints/getBlockByNumber.js",
    "content": "const Web3 = require('web3');\nmodule.exports = function(app, levelDB, web3) {\n    const getBlockByNumber = require('../helpers/getBlock')(levelDB);\n    app.get('/plasmaBlock/:id', 'getBlockByNumber', async function(req, res){\n        try{ \n            const blockNumber = parseInt(req.params.id);\n            if (!blockNumber){\n                return res.json({error: true, reason: \"invalid block number\"});\n            }\n            const block = await getBlockByNumber(blockNumber);\n            return res.json(block.toFullJSON(true))\n        }\n        catch(error){\n            return res.json({error: true, reason: \"invalid block number\"});\n        }\n    });\n}"
  },
  {
    "path": "app/endpoints/getTXsForAddress.js",
    "content": "const Web3 = require('web3');\nconst ethUtil = require('ethereumjs-util'); \nconst assert = require('assert')\n\nmodule.exports = function(app, levelDB, web3) {\n    const getTXsforAddress = require('../helpers/getAllTXsForAddress')(levelDB);\n    app.get('/txs/:address', 'getTXsByAddress', async function(req, res, next) {\n        try{ \n            addressString = req.params.address\n            assert(ethUtil.isValidAddress(addressString))\n            addressString = ethUtil.addHexPrefix(addressString)\n            getTXsforAddress(addressString, function(err, txs) {\n                if (err){\n                    console.log(err)\n                    res.json({error: true, reason: \"invalid address\"});\n                    next()\n                }\n                res.json({error: false, address: addressString, txs})\n                next()\n                return\n            })\n        }\n        catch(error) {\n            res.json({error: true, reason: \"invalid address\"});\n            next()\n        }\n    });\n}"
  },
  {
    "path": "app/endpoints/getTxByNumber.js",
    "content": "const Web3 = require('web3');\nmodule.exports = function(app, levelDB, web3) {\n    const getTX = require('../helpers/getTX')(levelDB);\n    app.get('/plasmaTX/:blockNumber/:txNumberInBlock', 'getBlockByNumber', async function(req, res){\n        try{ \n            const blockNumber = parseInt(req.params.blockNumber);\n            const txNumberInBlock = parseInt(req.params.txNumberInBlock);\n            if (blockNumber == undefined || txNumberInBlock == undefined){\n                return res.json({error: true, reason: \"invalid transaction number\"});\n            }\n            let tx = await getTX(blockNumber, txNumberInBlock);\n            tx = tx.toFullJSON(true)\n            tx.header['blockNumber'] = blockNumber;\n            return res.json(tx)\n        }\n        catch(error){\n            return res.json({error: true, reason: \"invalid block number\"});\n        }\n    });\n}"
  },
  {
    "path": "app/endpoints/getUTXOsForAddress.js",
    "content": "const Web3 = require('web3');\nconst ethUtil = require('ethereumjs-util'); \nconst assert = require('assert')\n\nmodule.exports = function(app, levelDB, web3) {\n    const getUTXOforAddress = require('../helpers/getAllUTXOsForAddress')(levelDB);\n    app.get('/utxos/:address', 'getUtxosByAddress', async function(req, res, next) {\n        try{ \n            addressString = req.params.address\n            assert(ethUtil.isValidAddress(addressString))\n            addressString = ethUtil.addHexPrefix(addressString)\n            getUTXOforAddress(addressString, function(err, utxos) {\n                if (err){\n                    console.log(err)\n                    res.json({error: true, reason: \"invalid address\"});\n                    next()\n                }\n                res.json({error: false, address: addressString, utxos})\n                next()\n                return\n            })\n        }\n        catch(error) {\n            res.json({error: true, reason: \"invalid address\"});\n            next()\n        }\n    });\n}"
  },
  {
    "path": "app/endpoints/getWithdrawsForAddress.js",
    "content": "const Web3 = require('web3');\nconst ethUtil = require('ethereumjs-util'); \nconst assert = require('assert')\n\nmodule.exports = function(app, levelDB, web3) {\n    const getWithdrawsforAddress = require('../helpers/getAllWithdrawsForAddress')(levelDB);\n    app.get('/withdraws/:address', 'getWithdrawssByAddress', async function(req, res, next) {\n        try{ \n            addressString = req.params.address\n            assert(ethUtil.isValidAddress(addressString))\n            addressString = ethUtil.addHexPrefix(addressString)\n            getWithdrawsforAddress(addressString, function(err, txs) {\n                if (err){\n                    console.log(err)\n                    res.json({error: true, reason: \"invalid address\"});\n                    next()\n                }\n                res.json({error: false, address: addressString, txs})\n                next()\n                return\n            })\n        }\n        catch(error) {\n            res.json({error: true, reason: \"invalid address\"});\n            next()\n        }\n    });\n}"
  },
  {
    "path": "app/endpoints/prepareProofForExpressWithdraw.js",
    "content": "//demo purposes only\nconst Web3 = require('web3');\nconst ethUtil = require('ethereumjs-util'); \nconst BN = ethUtil.BN;\nconst assert = require('assert');\nconst {PlasmaTransaction,\n    TxTypeFund, \n    TxTypeMerge, \n    TxTypeSplit, \n    TxTypeWithdraw, \n    TxTypeTransfer, \n    TxLengthForType,\n    NumInputsForType,\n    NumOutputsForType} = require('../../lib/Tx/tx');\n\nconst encodeForRemix = require(\"../helpers/hexDataToEncodedBytes\");\n\nmodule.exports = function(app, levelDB, web3) {\n    const getBlockByNumber = require('../helpers/getBlock')(levelDB);\n    const getTX = require('../helpers/getTX')(levelDB);\n    const prepareProofsForWithdraw = require('../helpers/prepareProofForTX')(levelDB);\n\n    app.post('/prepareProofForExpressWithdraw', 'prepareProofForExpressWithdraw', async function(req, res){\n        try{ \n            const {blockNumber, txNumber} = req.body\n            if (!blockNumber || txNumber==undefined) {\n                return res.json({error: true, reason: \"invalid transaction\"});\n            }\n            const txNumberInBlock = txNumber;\n            const blockNumberBuffer = ethUtil.toBuffer(blockNumber)\n            const txNumberInBlockBuffer = ethUtil.toBuffer(txNumberInBlock)\n            const tx = await getTX(blockNumber, txNumberInBlock);\n            if (!tx) {\n                return res.json({error: true, reason: \"invalid transaction\"});\n            }\n            assert(tx.transactionTypeUInt() == TxTypeWithdraw)\n            const preparedProof = await prepareProofsForWithdraw(blockNumber, txNumberInBlock);\n            return res.json({error: false, \n                proof: {\n                    blockNumber: preparedProof.blockNumber,\n                    txNumber:preparedProof.txNumberInBlock, \n                    tx: preparedProof.tx, \n                    merkleProof: preparedProof.merkleProof\n                }\n            })\n        }\n        catch(error){\n            res.json({error: true, reason: \"invalid transaction\"});\n    \n        }\n    });\n}"
  },
  {
    "path": "app/endpoints/withdraw.js",
    "content": "//demo purposes only\nconst Web3 = require('web3');\nconst ethUtil = require('ethereumjs-util'); \nconst BN = ethUtil.BN;\nconst assert = require('assert');\nconst {PlasmaTransaction,\n    TxTypeFund, \n    TxTypeMerge, \n    TxTypeSplit, \n    TxTypeWithdraw, \n    TxTypeTransfer, \n    TxLengthForType,\n    NumInputsForType,\n    NumOutputsForType} = require('../../lib/Tx/tx');\n\nconst encodeForRemix = require(\"../helpers/hexDataToEncodedBytes\");\n\nmodule.exports = function(app, levelDB, web3) {\n    const getBlockByNumber = require('../helpers/getBlock')(levelDB);\n    const getTX = require('../helpers/getTX')(levelDB);\n    const prepareProofsForWithdraw = require('../helpers/prepareProofForTX')(levelDB);\n\n\n\n    app.post('/startWithdraw', 'startWithdraw', async function(req, res){\n        try{ \n            const {blockNumber, txNumber, txOutputNumber, from} = req.body\n            if (!blockNumber || !from) {\n                return res.json({error: true, reason: \"invalid transaction\"});\n            }\n            const txNumberInBlock = txNumber;\n            const tx = await getTX(blockNumber, txNumberInBlock);\n            if (!tx) {\n                return res.json({error: true, reason: \"invalid transaction\"});\n            }\n            assert(tx.transactionTypeUInt() == TxTypeSplit || \n                tx.transactionTypeUInt() == TxTypeMerge || \n                tx.transactionTypeUInt() == TxTypeTransfer ||\n                tx.transactionTypeUInt() == TxTypeFund)\n            const preparedProof = await prepareProofsForWithdraw(blockNumber, txNumberInBlock);\n            const result = await app.DeployedPlasmaContract.methods.startWithdraw(preparedProof.blockNumber, \n                preparedProof.txNumberInBlock, req.body.txOutputNumber, preparedProof.tx, preparedProof.merkleProof ).send({from:from, gas: 3.6e6});\n            const acceptanceEvent = result.events.WithdrawRequestAcceptedEvent; \n            const withdrawStartedEvent = result.events.WithdrawStartedEvent;\n            console.log(acceptanceEvent);\n            console.log(withdrawStartedEvent);\n            const response =  {error: false, status: \"accepted\",\n                    withdrawIndex: acceptanceEvent.returnValues._withdrawIndex, \n                    acceptanceEvent,\n                    withdrawStartedEvent}\n            return res.json(response);\n        }\n        catch(error){\n            res.json({error: true, reason: \"invalid transaction\"});\n        }\n    });\n\n    app.post('/finalizeWithdrawExpress', 'finalizeWithdrawExpress', async function(req, res){\n        try{ \n            const {blockNumber, txNumber, from} = req.body\n            if (!blockNumber || !from) {\n                return res.json({error: true, reason: \"invalid transaction\"});\n            }\n            const txNumberInBlock = txNumber;\n            const blockNumberBuffer = ethUtil.toBuffer(blockNumber)\n            const txNumberInBlockBuffer = ethUtil.toBuffer(txNumberInBlock)\n            const tx = await getTX(blockNumber, txNumberInBlock);\n            if (!tx) {\n                return res.json({error: true, reason: \"invalid transaction\"});\n            }\n            assert(tx.transactionTypeUInt() == TxTypeWithdraw)\n            const preparedProof = await prepareProofsForWithdraw(blockNumber, txNumberInBlock);\n            const result = await app.DeployedPlasmaContract.methods.makeWithdrawExpress(preparedProof.blockNumber, \n                preparedProof.txNumberInBlock, preparedProof.tx, preparedProof.merkleProof ).send({from:from, gas: 3.6e6});\n            const withdrawFinalizedEvent = result.events.WithdrawFinalizedEvent;\n            console.log(withdrawFinalizedEvent);\n            const response =  {error: false, status: \"accepted\", \n                    withdrawIndex: withdrawFinalizedEvent.returnValues._withdrawIndex,\n                withdrawFinalizedEvent}\n            return res.json(response);\n        }\n        catch(error){\n            res.json({error: true, reason: \"invalid transaction\"});\n        }\n    });\n\n    app.post('/finalizeWithdraw', 'finalizeWithdraw', async function(req, res){\n        try{ \n            const {withdrawIndex, from} = req.body\n            if (!from || !withdrawIndex) {\n                return res.json({error: true, reason: \"invalid request\"});\n            }\n            await app.jump(\"2 days\")();\n            var result = await DeployedPlasmaContract.methods.finalizeWithdraw(inEthereumBlock, withdrawIndex).send({from: from, gas: 3.6e6});\n            const finalizationEvent = result.events.WithdrawFinalizedEvent; \n            const response =  {error: false, status: \"accepted\", \n                    withdrawIndex: withdrawFinalizedEvent.returnValues._withdrawIndex,\n                withdrawFinalizedEvent}\n            return res.json(response);\n        }\n        catch(error){\n             res.json({error: true, reason: \"invalid request\"});\n     \n        }\n    });\n}"
  },
  {
    "path": "app/helpers/checkSpendingTX.js",
    "content": "const config = require(\"../config/config\");\nconst blockPrefix = config.blockPrefix;\nconst utxoPrefix = config.utxoPrefix;\nconst utxoIncludingAddressPrefix = config.utxoIncludingAddressPrefix;\nconst makeAddressIndex = config.makeAddressIndex;\nconst headerPrefix = config.headerPrefix;\nconst transactionPrefix=config.transactionPrefix;\nconst blockTime = config.blockTime;\n\nconst {blockNumberLength,\n    txNumberLength,\n    txTypeLength, \n    signatureVlength,\n    signatureRlength,\n    signatureSlength,\n    merkleRootLength,\n    previousHashLength,\n    txOutputNumberLength,\n    txAmountLength,\n    txToAddressLength} = require('../../lib/dataStructureLengths');\n\nconst Web3 = require('web3');\nconst Block = require('../../lib/Block/block');\nconst ethUtil = require('ethereumjs-util'); \nconst BN = ethUtil.BN;\nconst plasmaOperatorAddress = config.plasmaOperatorAddress;\nconst assert = require('assert');\nconst {PlasmaTransaction,\n    TxTypeFund, \n    TxTypeMerge, \n    TxTypeSplit, \n    TxTypeWithdraw,\n    TxTypeTransfer, \n    TxLengthForType,\n    NumInputsForType,\n    NumOutputsForType} = require('../../lib/Tx/tx');\n\nconst {TransactionInput} = require('../../lib/Tx/input');\nconst {TransactionOutput} = require('../../lib/Tx/output');\n\nmodule.exports = function(levelDB) {\n    return async function checkSpendingTX(spendingTx) {    \n        if (spendingTx.getKey() == \"000000000000000000\") {\n            return config.plasmaOperatorAddress === ethUtil.bufferToHex(spendingTx.getSenderAddress());\n        } else {\n            try{\n                const senderAddress = spendingTx.getSenderAddress();\n                var amountFromInputs = new BN(0)\n                var amountFromOutputs = new BN(0)\n                for (let inpIndex of [0,1]) {\n                    const input = spendingTx.getTransactionInput(inpIndex)\n                    if (input && typeof input != \"undefined\") {\n                        const keyForUTXO = Buffer.concat([utxoPrefix, input.blockNumber, input.txNumberInBlock, input.outputNumberInTransaction]);\n                        const unspentTxRaw = await levelDB.get(keyForUTXO)\n                        const unspentTx = TransactionOutput.prototype.initFromBinaryBlob(unspentTxRaw);\n                        if (!unspentTx){\n                            return false\n                        }\n                        if (spendingTx.transactionTypeUInt() == TxTypeMerge) {\n                            if (!unspentTx.to.equals(senderAddress)) {\n                                if (!senderAddress.equals(ethUtil.toBuffer(config.plasmaOperatorAddress))) {\n                                    return false\n                                }\n                            }\n                        } else {\n                            if (!unspentTx.to.equals(senderAddress)){\n                                return false\n                            }\n                        }\n                        amountFromInputs = amountFromInputs.add(unspentTx.value)\n                    }\n                }\n                for (let outIndex of [0,1]) {\n                    const output = spendingTx.getTransactionOutput(outIndex);\n                    if (output && typeof output != \"undefined\" && !(output.outputNumberInTransaction.equals(Buffer.from('ff', 'hex'))) ) {\n                        amountFromOutputs = amountFromOutputs.add(output.value)\n                    }\n                }\n                return amountFromInputs.eq(amountFromOutputs);\n            }\n            catch(error){\n                return false;\n            }\n        }\n        return false;\n    }\n}"
  },
  {
    "path": "app/helpers/createFundingTransaction.js",
    "content": "const config = require(\"../config/config\");\nconst ethUtil = require('ethereumjs-util'); \nconst BN = ethUtil.BN;\n\nconst {blockNumberLength,\n    txNumberLength,\n    txTypeLength, \n    signatureVlength,\n    signatureRlength,\n    signatureSlength,\n    merkleRootLength,\n    previousHashLength,\n    txOutputNumberLength,\n    txAmountLength,\n    txToAddressLength} = require('../../lib/dataStructureLengths');\n\n// const plasmaOperatorPrivKeyHex = config.plasmaOperatorPrivKeyHex;\n// const plasmaOperatorPrivKey = ethUtil.toBuffer(plasmaOperatorPrivKeyHex);\nconst {PlasmaTransaction,\n    TxTypeFund, \n    TxTypeMerge, \n    TxTypeSplit, \n    TxTypeWithdraw, \n    TxTypeTransfer,\n    TxLengthForTypes} = require(\"../../lib/Tx/tx\");\n\nconst {TransactionInput, TransactionInputLength} = require(\"../../lib/Tx/input\");\nconst {TransactionOutput, TransactionOutputLength} = require(\"../../lib/Tx/output\");\nconst dummyInput = new TransactionInput();\nconst dummyOutput = new TransactionOutput();\n\nmodule.exports = function createFundingTransaction(toAddressString, amountBN, depositIndexBN) {\n    const amountBuffer = ethUtil.setLengthLeft(ethUtil.toBuffer(amountBN),txAmountLength)\n    const inputParams = {\n        blockNumber: '0x' + '00'.repeat(blockNumberLength),\n        txNumberInBlock: '0x' +'00'.repeat(txNumberLength),\n        // assetID: ethUtil.setLengthLeft(ethUtil.bufferToHex(ethUtil.toBuffer(asset)), 4),\n        outputNumberInTransaction: '0x00',\n        amountBuffer\n    }\n    const input = new TransactionInput(inputParams);\n    const outputParams = {\n        to: ethUtil.addHexPrefix(toAddressString),\n        // assetID: ethUtil.setLengthLeft(ethUtil.bufferToHex(ethUtil.toBuffer(asset)), 4),\n        outputNumberInTransaction: '0x00',\n        amountBuffer\n    }\n    const output = new TransactionOutput(outputParams);\n    const txTypeBuffer = ethUtil.setLengthLeft(ethUtil.toBuffer(new BN(TxTypeFund)),txTypeLength)\n\n    const depositRecordParams = {\n        to: ethUtil.addHexPrefix(toAddressString),\n        outputNumberInTransaction: '0xff',\n        amountBuffer: ethUtil.setLengthLeft(ethUtil.toBuffer(depositIndexBN),txAmountLength)\n    }\n    const auxOutput = new TransactionOutput(depositRecordParams);\n\n    const txParams = {\n        transactionType: txTypeBuffer,\n        inputNum0: Buffer.concat(input.raw),\n        outputNum0: Buffer.concat(output.raw),\n        outputNum1: Buffer.concat(auxOutput.raw)\n    }\n    const tx = new PlasmaTransaction(txParams);\n    return tx;\n\n    // tx.sign(plasmaOperatorPrivKey); \n    // return tx;\n}"
  },
  {
    "path": "app/helpers/createTxFromJson.js",
    "content": "const {blockNumberLength,\n    txNumberLength,\n    txTypeLength, \n    signatureVlength,\n    signatureRlength,\n    signatureSlength,\n    merkleRootLength,\n    previousHashLength,\n    txOutputNumberLength,\n    txAmountLength,\n    txToAddressLength} = require('../../lib/dataStructureLengths');\n\nconst config = require(\"../config/config\");\nconst ethUtil = require('ethereumjs-util'); \nconst plasmaOperatorPrivKeyHex = config.plasmaOperatorPrivKeyHex;\nconst plasmaOperatorPrivKey = ethUtil.toBuffer(plasmaOperatorPrivKeyHex);\nconst Web3 = require('web3');\nconst BN = Web3.utils.BN;\nconst validateSchema = require('jsonschema').validate;\nconst {PlasmaTransaction,\n    TxTypeFund, \n    TxTypeMerge, \n    TxTypeSplit, \n    TxTypeWithdraw, \n    TxTypeTransfer,\n    TxLengthForType,\n    NumInputsForType, \n    NumOutputsForType} = require(\"../../lib/Tx/tx\");\n\nconst {TransactionInput, TransactionInputLength} = require(\"../../lib/Tx/input\");\nconst {TransactionOutput, TransactionOutputLength} = require(\"../../lib/Tx/output\");\n\nconst dummyInput = new TransactionInput();\nconst dummyOutput = new TransactionOutput();\n\nconst transactionSchemaNoSignature = \n{\n    \"txType\" : {\"type\" : \"integer\", \"minimum\" : 1, \"maximum\" : 5},\n    \"inputs\": {\n        \"type\": \"array\",\n        \"items\": {\"type\": \"object\",\n            \"properties\": {\n            \"blockNumber\": {\"type\": \"integer\", \"minimum\": 1},\n            \"txNumber\": {\"type\": \"integer\", \"minimum\": 1},\n            \"outputNumber\" : {\"type\": \"integer\", \"minimum\": 1}\n            }\n        }\n    },\n    \"outputs\": {\n        \"type\": \"array\",\n        \"items\": {\"type\": \"object\",\n            \"properties\": {\n            \"to\": {\"type\": \"string\", \"minLength\": 40, \"maxLength\": 42},\n            \"amount\": {\"type\": \"string\", \"minLength\": 1},  \n            }\n        }\n    },\n    \"required\": [\"txType\", \"inputs\", \"outputs\"]\n}\n\nconst transactionSchemaWithSignature = {\n        \"txType\" : {\"type\" : \"integer\", \"minimum\" : 1, \"maximum\" : 5},\n        \"inputs\": {\n            \"type\": \"array\",\n            \"items\": {\"type\": \"object\",\n                \"properties\": {\n                \"blockNumber\": {\"type\": \"integer\", \"minimum\": 1},\n                \"txNumber\": {\"type\": \"integer\", \"minimum\": 1},\n                \"outputNumber\" : {\"type\": \"integer\", \"minimum\": 1}\n                }\n            }\n        },\n        \"outputs\": {\n            \"type\": \"array\",\n            \"items\": {\"type\": \"object\",\n                \"properties\": {\n                \"to\": {\"type\": \"string\", \"minLength\": 40, \"maxLength\": 42},\n                \"amount\": {\"type\": \"string\", \"minLength\": 1},  \n                }\n            }\n        },\n        \"v\": {\"type\": \"string\", \"minLength\": 2, \"maxLength\": 2},\n        \"r\": {\"type\": \"string\", \"minLength\": 44, \"maxLength\": 44},\n        \"s\": {\"type\": \"string\", \"minLength\": 44, \"maxLength\": 44},\n        \"required\": [\"txType\", \"inputs\", \"outputs\", \"v\", \"r\", \"s\"]\n}\nmodule.exports = function (levelDB) {\n    const getUTXO = require('./getUTXO')(levelDB);\n    const getTX = require('./getTX')(levelDB);\n    return async function (transactionJSON) {\n        try{\n            if (!validateSchema(transactionJSON, transactionSchemaNoSignature).valid) {\n                return null\n            }\n            const txType = transactionJSON.txType;\n            const numInputs = transactionJSON.inputs.length;\n            const numOutputs = transactionJSON.outputs.length\n            if (numInputs != NumInputsForType[txType] || numOutputs != NumOutputsForType[txType]){\n                return null;\n            }\n            let inputsTotalValue = new BN(0);\n            let outputsTotalValue = new BN(0);\n            const txParams = {}\n            let inputCounter = 0;\n            // const inputs = []\n            for (let inputJSON of transactionJSON.inputs) {\n                const unspentOutput = await getUTXO(inputJSON.blockNumber, inputJSON.txNumber, inputJSON.outputNumber);\n                if (!unspentOutput) {\n                    return null;\n                }\n                const blockNumberBuffer = ethUtil.setLengthLeft(ethUtil.toBuffer(new BN(inputJSON.blockNumber)),blockNumberLength)\n                const txNumberBuffer = ethUtil.setLengthLeft(ethUtil.toBuffer(new BN(inputJSON.txNumber)),txNumberLength)\n                const txOutputNumberBuffer = ethUtil.setLengthLeft(ethUtil.toBuffer(new BN(inputJSON.outputNumber)),txOutputNumberLength)\n                const inputParams = {\n                    blockNumber: blockNumberBuffer,\n                    txNumberInBlock: txNumberBuffer,\n                    outputNumberInTransaction: txOutputNumberBuffer,\n                    amountBuffer: unspentOutput.amountBuffer\n                }\n                const input = new TransactionInput(inputParams);\n                // inputs.push(input)\n                inputsTotalValue = inputsTotalValue.add(unspentOutput.value);\n                txParams[\"inputNum\"+inputCounter]=Buffer.concat(input.raw);\n                inputCounter++;\n            }\n            let outputCounter = 0;\n            for (let outputJSON of transactionJSON.outputs) {\n                const outputNumberBuffer = ethUtil.setLengthLeft(ethUtil.toBuffer(new BN(outputCounter)),txOutputNumberLength)\n                const outputValue = new BN(outputJSON.amount);\n                if (outputValue.lte(0)) {\n                    return null;\n                }\n                outputsTotalValue = outputsTotalValue.add(outputValue);\n                const addr = ethUtil.addHexPrefix(outputJSON.to.toLowerCase());\n                if (addr == undefined) {\n                    return null;\n                }\n                const outputParams = {\n                    to: addr,\n                    // assetID: ethUtil.setLengthLeft(ethUtil.bufferToHex(ethUtil.toBuffer(asset)), 4),\n                    outputNumberInTransaction: outputNumberBuffer,\n                    amountBuffer: ethUtil.setLengthLeft(ethUtil.toBuffer(outputValue),txAmountLength)\n                }\n                const transactionOutput = new TransactionOutput(outputParams);\n                txParams[\"outputNum\"+outputCounter] = Buffer.concat(transactionOutput.raw);\n                outputCounter++\n            }\n            if (!outputsTotalValue.eq(inputsTotalValue)) {\n                return null;\n            }\n            // if (txType == TxTypeMerge) {\n            //     if (! inputs[0].to.equals(inputs[1].to)){\n            //         return null;\n            //     }\n            // }\n            const txTypeBuffer = ethUtil.setLengthLeft(ethUtil.toBuffer(new BN(txType)), txTypeLength)\n            txParams.transactionType = txTypeBuffer;\n            const tx = new PlasmaTransaction(txParams);\n            return tx;\n        }\n        catch(err){\n            return null;\n        }\n    }\n}"
  },
  {
    "path": "app/helpers/createWithdrawTxFromJson.js",
    "content": "const {blockNumberLength,\n    txNumberLength,\n    txTypeLength, \n    signatureVlength,\n    signatureRlength,\n    signatureSlength,\n    merkleRootLength,\n    previousHashLength,\n    txOutputNumberLength,\n    txAmountLength,\n    txToAddressLength} = require('../../lib/dataStructureLengths');\n\nconst config = require(\"../config/config\");\nconst ethUtil = require('ethereumjs-util'); \nconst plasmaOperatorPrivKeyHex = config.plasmaOperatorPrivKeyHex;\nconst plasmaOperatorPrivKey = ethUtil.toBuffer(plasmaOperatorPrivKeyHex);\nconst Web3 = require('web3');\nconst BN = Web3.utils.BN;\nconst validateSchema = require('jsonschema').validate;\nconst assert = require('assert');\nconst {PlasmaTransaction,\n    TxTypeFund, \n    TxTypeMerge, \n    TxTypeSplit, \n    TxTypeWithdraw, \n    TxTypeTransfer,\n    TxLengthForType,\n    NumInputsForType, \n    NumOutputsForType} = require(\"../../lib/Tx/tx\");\n\nconst {TransactionInput, TransactionInputLength} = require(\"../../lib/Tx/input\");\nconst {TransactionOutput, TransactionOutputLength} = require(\"../../lib/Tx/output\");\n\nconst dummyInput = new TransactionInput();\nconst dummyOutput = new TransactionOutput();\n\nconst transactionSchemaNoSignature = \n{\n    \"txType\" : {\"type\" : \"integer\", \"minimum\" : TxTypeWithdraw, \"maximum\" : TxTypeWithdraw},\n    \"inputs\": {\n        \"type\": \"array\",\n        \"items\": {\"type\": \"object\",\n            \"properties\": {\n            \"blockNumber\": {\"type\": \"integer\", \"minimum\": 1},\n            \"txNumber\": {\"type\": \"integer\", \"minimum\": 1},\n            \"outputNumber\" : {\"type\": \"integer\", \"minimum\": 1}\n            }\n        }\n    },\n    \"required\": [\"txType\", \"inputs\"]\n}\n\nconst transactionSchemaWithSignature = {\n        \"txType\" : {\"type\" : \"integer\", \"minimum\" : TxTypeWithdraw, \"maximum\" : TxTypeWithdraw},\n        \"inputs\": {\n            \"type\": \"array\",\n            \"items\": {\"type\": \"object\",\n                \"properties\": {\n                \"blockNumber\": {\"type\": \"integer\", \"minimum\": 1},\n                \"txNumber\": {\"type\": \"integer\", \"minimum\": 1},\n                \"outputNumber\" : {\"type\": \"integer\", \"minimum\": 1}\n                }\n            }\n        },\n        \"v\": {\"type\": \"string\", \"minLength\": 2, \"maxLength\": 2},\n        \"r\": {\"type\": \"string\", \"minLength\": 44, \"maxLength\": 44},\n        \"s\": {\"type\": \"string\", \"minLength\": 44, \"maxLength\": 44},\n        \"required\": [\"txType\", \"inputs\", \"v\", \"r\", \"s\"]\n}\nmodule.exports = function (levelDB) {\n    const getUTXO = require('./getUTXO')(levelDB);\n    const getTX = require('./getTX')(levelDB);\n    return async function (transactionJSON) {\n        try{\n            if (!validateSchema(transactionJSON, transactionSchemaNoSignature).valid) {\n                return null\n            }\n            const txType = transactionJSON.txType;\n            assert(txType == TxTypeWithdraw);\n            const numInputs = transactionJSON.inputs.length;\n            if (numInputs != NumInputsForType[txType]){\n                return null;\n            }\n            let inputsTotalValue = new BN(0);\n            let outputsTotalValue = new BN(0);\n            const txParams = {}\n            let inputCounter = 0;\n            const inputs = []\n            for (let inputJSON of transactionJSON.inputs) {\n                const unspentOutput = await getUTXO(inputJSON.blockNumber, inputJSON.txNumber, inputJSON.outputNumber);\n                if (!unspentOutput) {\n                    return null;\n                }\n                const blockNumberBuffer = ethUtil.setLengthLeft(ethUtil.toBuffer(new BN(inputJSON.blockNumber)),blockNumberLength)\n                const txNumberBuffer = ethUtil.setLengthLeft(ethUtil.toBuffer(new BN(inputJSON.txNumber)),txNumberLength)\n                const txOutputNumberBuffer = ethUtil.setLengthLeft(ethUtil.toBuffer(new BN(inputJSON.outputNumber)),txOutputNumberLength)\n                const inputParams = {\n                    blockNumber: blockNumberBuffer,\n                    txNumberInBlock: txNumberBuffer,\n                    outputNumberInTransaction: txOutputNumberBuffer,\n                    amountBuffer: unspentOutput.amountBuffer\n                }\n                const input = new TransactionInput(inputParams);\n                inputs.push(input)\n                inputsTotalValue = inputsTotalValue.add(unspentOutput.value);\n                txParams[\"inputNum\"+inputCounter]=Buffer.concat(input.raw);\n                inputCounter++;\n            }\n            let outputCounter = 0;\n            const outputNumberBuffer = ethUtil.setLengthLeft(ethUtil.toBuffer(new BN(outputCounter)),txOutputNumberLength)\n            const outputValue = inputsTotalValue;\n            if (outputValue.lte(0)) {\n                return null;\n            }\n            outputsTotalValue = outputsTotalValue.add(outputValue);\n            const outputParams = {\n                to: ethUtil.setLengthLeft(ethUtil.toBuffer(\"0x00\"),txToAddressLength),\n                // assetID: ethUtil.setLengthLeft(ethUtil.bufferToHex(ethUtil.toBuffer(asset)), 4),\n                outputNumberInTransaction: outputNumberBuffer,\n                amountBuffer: ethUtil.setLengthLeft(ethUtil.toBuffer(outputValue),txAmountLength)\n            }\n            const transactionOutput = new TransactionOutput(outputParams);\n            txParams[\"outputNum\"+outputCounter] = Buffer.concat(transactionOutput.raw);\n            if (!outputsTotalValue.eq(inputsTotalValue)) {\n                return null;\n            }\n            const txTypeBuffer = ethUtil.setLengthLeft(ethUtil.toBuffer(new BN(txType)), txTypeLength)\n            txParams.transactionType = txTypeBuffer;\n            const tx = new PlasmaTransaction(txParams);\n            return tx;\n        }\n        catch(err){\n            return null;\n        }\n    }\n}"
  },
  {
    "path": "app/helpers/getAllTXsForAddress.js",
    "content": "const config = require(\"../config/config\");\nconst ethUtil = require('ethereumjs-util'); \nconst {blockPrefix, \n    utxoIncludingAddressPrefix, \n    utxoPrefix, \n    makeAddressIndex,\n    txForAddressIndexPrefix} = config;\n\nconst {TransactionOutput} = require(\"../../lib/Tx/output\");\nconst {TransactionInput} = require(\"../../lib/Tx/input\");\nconst {BlockHeader} = require(\"../../lib/Block/blockHeader\");\nconst assert = require('assert');\n\nconst {blockNumberLength,\n    txNumberLength,\n    txTypeLength, \n    signatureVlength,\n    signatureRlength,\n    signatureSlength,\n    merkleRootLength,\n    previousHashLength,\n    txOutputNumberLength,\n    txAmountLength,\n    txToAddressLength} = require('../../lib/dataStructureLengths');\n\nmodule.exports = function(levelDB) {\n\n    if (config.makeTransactionIndexForAddress) {\n        return getTXsAddressWithIndex;\n    } else {\n        return getTXsforAddress;\n    }\n\n    async function getTXsforAddress(addressString, cb) {\n        addressString = ethUtil.addHexPrefix(addressString)\n        if (!ethUtil.isValidAddress(addressString)){\n            cb(true, null);\n        }\n        address = ethUtil.toBuffer(addressString);\n        const utxos = [];\n        const start = Buffer.concat([utxoPrefix,\n            Buffer.alloc(blockNumberLength), \n            Buffer.alloc(txNumberLength), \n            Buffer.alloc(txOutputNumberLength)])\n        const stop = Buffer.concat([utxoPrefix,\n            Buffer.from(\"ff\".repeat(blockNumberLength), 'hex'), \n            Buffer.from(\"ff\".repeat(txNumberLength), 'hex'),\n            Buffer.from(\"ff\".repeat(txOutputNumberLength), 'hex')])\n        const sliceStart = utxoPrefix.length;\n        levelDB.createReadStream({gte: start,\n                                    lte: stop,\n                                    reversed:true})\n        .on('data', function (data) {\n            if (data.value.slice(0,txToAddressLength).equals(address)) {\n                const out = TransactionOutput.prototype.initFromBinaryBlob(data.value);\n                toReturn = {};\n                toReturn[\"blockNumber\"] = ethUtil.bufferToInt(data.key.slice(sliceStart, sliceStart + blockNumberLength))\n                toReturn[\"txNumberInBlock\"] = ethUtil.bufferToInt(data.key.slice(sliceStart + blockNumberLength, sliceStart + blockNumberLength + txNumberLength))\n                toReturn[\"outputNumberInTransaction\"] = ethUtil.bufferToInt(data.key.slice(sliceStart + blockNumberLength + txNumberLength, sliceStart + blockNumberLength + txNumberLength + txOutputNumberLength))\n                toReturn[\"value\"] = out.value.toString(10);\n                toReturn['output'] = out;\n                utxos.push(toReturn);\n            }\n        })\n        .on('error', function (err) {\n            console.log('Oh my!', err)\n            cb(err, null)\n        })\n        .on('close', function () {\n            // cb(null, utxos)\n            // console.log('Stream closed')\n        })\n        .on('end', function () {\n            cb(null, utxos)\n            // console.log('Stream ended')\n        })\n    }\n\n    async function getTXsAddressWithIndex(addressString, cb) {\n        addressString = ethUtil.addHexPrefix(addressString)\n        if (!ethUtil.isValidAddress(addressString)){\n            cb(true, null);\n        }\n        address = ethUtil.toBuffer(addressString);\n        const utxos = [];\n        const start = Buffer.concat([txForAddressIndexPrefix,\n            address,\n            Buffer.alloc(blockNumberLength), \n            Buffer.alloc(txNumberLength)])\n        const stop = Buffer.concat([txForAddressIndexPrefix,\n            address,\n            Buffer.from(\"ff\".repeat(blockNumberLength), 'hex'), \n            Buffer.from(\"ff\".repeat(txNumberLength), 'hex'),])\n        const sliceStart = txForAddressIndexPrefix.length + address.length;\n        levelDB.createReadStream({gte: start,\n                                    lte: stop,\n                                    reversed:true})\n        .on('data', function (data) {\n            toReturn = {};\n            toReturn[\"blockNumber\"] = ethUtil.bufferToInt(data.key.slice(sliceStart, sliceStart + blockNumberLength))\n            toReturn[\"txNumberInBlock\"] = ethUtil.bufferToInt(data.key.slice(sliceStart + blockNumberLength, sliceStart + blockNumberLength + txNumberLength))\n            utxos.push(toReturn);\n        })\n        .on('error', function (err) {\n            console.log('Oh my!', err)\n            cb(err, null)\n        })\n        .on('close', function () {\n            // cb(null, utxos)\n            // console.log('Stream closed')\n        })\n        .on('end', function () {\n            cb(null, utxos)\n            // console.log('Stream ended')\n        })\n    }\n}"
  },
  {
    "path": "app/helpers/getAllUTXOsForAddress.js",
    "content": "const config = require(\"../config/config\");\nconst ethUtil = require('ethereumjs-util'); \nconst blockPrefix = config.blockPrefix;\nconst utxoIncludingAddressPrefix = config.utxoIncludingAddressPrefix;\nconst utxoPrefix = config.utxoPrefix;\nconst makeAddressIndex = config.makeAddressIndex;\nconst {TransactionOutput} = require(\"../../lib/Tx/output\");\nconst {TransactionInput} = require(\"../../lib/Tx/input\");\nconst {BlockHeader} = require(\"../../lib/Block/blockHeader\");\nconst assert = require('assert');\n\nconst {blockNumberLength,\n    txNumberLength,\n    txTypeLength, \n    signatureVlength,\n    signatureRlength,\n    signatureSlength,\n    merkleRootLength,\n    previousHashLength,\n    txOutputNumberLength,\n    txAmountLength,\n    txToAddressLength} = require('../../lib/dataStructureLengths');\n\nmodule.exports = function(levelDB) {\n\n    if (makeAddressIndex) {\n        return getUTXOforAddressWithIndex;\n    } else {\n        return getUTXOforAddress;\n    }\n\n    async function getUTXOforAddress(addressString, cb) {\n        addressString = ethUtil.addHexPrefix(addressString)\n        if (!ethUtil.isValidAddress(addressString)){\n            cb(true, null);\n        }\n        address = ethUtil.toBuffer(addressString);\n        const utxos = [];\n        const start = Buffer.concat([utxoPrefix,\n            Buffer.alloc(blockNumberLength), \n            Buffer.alloc(txNumberLength), \n            Buffer.alloc(txOutputNumberLength)])\n        const stop = Buffer.concat([utxoPrefix,\n            Buffer.from(\"ff\".repeat(blockNumberLength), 'hex'), \n            Buffer.from(\"ff\".repeat(txNumberLength), 'hex'),\n            Buffer.from(\"ff\".repeat(txOutputNumberLength), 'hex')])\n        const sliceStart = utxoPrefix.length;\n        levelDB.createReadStream({gte: start,\n                                    lte: stop,\n                                    reversed:true})\n        .on('data', function (data) {\n            if (data.value.slice(0,txToAddressLength).equals(address)) {\n                const out = TransactionOutput.prototype.initFromBinaryBlob(data.value);\n                toReturn = {};\n                toReturn[\"blockNumber\"] = ethUtil.bufferToInt(data.key.slice(sliceStart, sliceStart + blockNumberLength))\n                toReturn[\"txNumberInBlock\"] = ethUtil.bufferToInt(data.key.slice(sliceStart + blockNumberLength, sliceStart + blockNumberLength + txNumberLength))\n                toReturn[\"outputNumberInTransaction\"] = ethUtil.bufferToInt(data.key.slice(sliceStart + blockNumberLength + txNumberLength, sliceStart + blockNumberLength + txNumberLength + txOutputNumberLength))\n                toReturn[\"to\"] = ethUtil.toChecksumAddress(ethUtil.bufferToHex(out.to))\n                toReturn[\"value\"] = out.value.toString(10);\n                // toReturn[\"to\"] = ethUtil.toChecksumAddress(ethUtil.bufferToHex(out.to))\n                // toReturn['output'] = out;\n                utxos.push(toReturn);\n            }\n        })\n        .on('error', function (err) {\n            console.log('Oh my!', err)\n            cb(err, null)\n        })\n        .on('close', function () {\n            // cb(null, utxos)\n            // console.log('Stream closed')\n        })\n        .on('end', function () {\n            cb(null, utxos)\n            // console.log('Stream ended')\n        })\n    }\n\n    async function getUTXOforAddressWithIndex(addressString, cb) {\n        addressString = ethUtil.addHexPrefix(addressString)\n        if (!ethUtil.isValidAddress(addressString)){\n            cb(true, null);\n        }\n        address = ethUtil.toBuffer(addressString);\n        const utxos = [];\n        const start = Buffer.concat([utxoIncludingAddressPrefix,\n            address,\n            Buffer.alloc(blockNumberLength), \n            Buffer.alloc(txNumberLength), \n            Buffer.alloc(txOutputNumberLength)])\n        const stop = Buffer.concat([utxoIncludingAddressPrefix,\n            address,\n            Buffer.from(\"ff\".repeat(blockNumberLength), 'hex'), \n            Buffer.from(\"ff\".repeat(txNumberLength), 'hex'),\n            Buffer.from(\"ff\".repeat(txOutputNumberLength), 'hex')])\n        const sliceStart = utxoIncludingAddressPrefix.length + address.length;\n        levelDB.createReadStream({gte: start,\n                                    lte: stop,\n                                    reversed:true})\n        .on('data', function (data) {\n            const out = TransactionOutput.prototype.initFromBinaryBlob(data.value);\n            toReturn = {};\n            toReturn[\"blockNumber\"] = ethUtil.bufferToInt(data.key.slice(sliceStart, sliceStart + blockNumberLength))\n            toReturn[\"txNumberInBlock\"] = ethUtil.bufferToInt(data.key.slice(sliceStart + blockNumberLength, sliceStart + blockNumberLength + txNumberLength))\n            toReturn[\"outputNumberInTransaction\"] = ethUtil.bufferToInt(data.key.slice(sliceStart + blockNumberLength + txNumberLength, sliceStart + blockNumberLength + txNumberLength + txOutputNumberLength))\n            toReturn[\"to\"] = ethUtil.toChecksumAddress(ethUtil.bufferToHex(out.to))\n            toReturn[\"value\"] = out.value.toString(10);\n            // toReturn['output'] = out;\n            utxos.push(toReturn);\n        })\n        .on('error', function (err) {\n            console.log('Oh my!', err)\n            cb(err, null)\n        })\n        .on('close', function () {\n            // cb(null, utxos)\n            // console.log('Stream closed')\n        })\n        .on('end', function () {\n            cb(null, utxos)\n            // console.log('Stream ended')\n        })\n    }\n}"
  },
  {
    "path": "app/helpers/getAllWithdrawsForAddress.js",
    "content": "const config = require(\"../config/config\");\nconst ethUtil = require('ethereumjs-util'); \nconst {blockPrefix, \n    utxoIncludingAddressPrefix, \n    utxoPrefix, \n    makeAddressIndex,\n    withdrawsForAddressPrefix} = config;\n\nconst {TransactionOutput} = require(\"../../lib/Tx/output\");\nconst {TransactionInput} = require(\"../../lib/Tx/input\");\nconst {BlockHeader} = require(\"../../lib/Block/blockHeader\");\nconst assert = require('assert');\n\nconst {blockNumberLength,\n    txNumberLength,\n    txTypeLength, \n    signatureVlength,\n    signatureRlength,\n    signatureSlength,\n    merkleRootLength,\n    previousHashLength,\n    txOutputNumberLength,\n    txAmountLength,\n    txToAddressLength} = require('../../lib/dataStructureLengths');\n\nmodule.exports = function(levelDB) {\n    return getWithdrawsForAddress\n\n    // if (config.makeTransactionIndexForAddress) {\n    //     return getWithdrawsAddressWithIndex;\n    // } else {\n    //     return getTXsforAddress;\n    // }\n\n    async function getTXsforAddress(addressString, cb) {\n        addressString = ethUtil.addHexPrefix(addressString)\n        if (!ethUtil.isValidAddress(addressString)){\n            cb(true, null);\n        }\n        address = ethUtil.toBuffer(addressString);\n        const utxos = [];\n        const start = Buffer.concat([utxoPrefix,\n            Buffer.alloc(blockNumberLength), \n            Buffer.alloc(txNumberLength), \n            Buffer.alloc(txOutputNumberLength)])\n        const stop = Buffer.concat([utxoPrefix,\n            Buffer.from(\"ff\".repeat(blockNumberLength), 'hex'), \n            Buffer.from(\"ff\".repeat(txNumberLength), 'hex'),\n            Buffer.from(\"ff\".repeat(txOutputNumberLength), 'hex')])\n        const sliceStart = utxoPrefix.length;\n        levelDB.createReadStream({gte: start,\n                                    lte: stop,\n                                    reversed:true})\n        .on('data', function (data) {\n            if (data.value.slice(0,txToAddressLength).equals(address)) {\n                const out = TransactionOutput.prototype.initFromBinaryBlob(data.value);\n                toReturn = {};\n                toReturn[\"blockNumber\"] = ethUtil.bufferToInt(data.key.slice(sliceStart, sliceStart + blockNumberLength))\n                toReturn[\"txNumberInBlock\"] = ethUtil.bufferToInt(data.key.slice(sliceStart + blockNumberLength, sliceStart + blockNumberLength + txNumberLength))\n                toReturn[\"outputNumberInTransaction\"] = ethUtil.bufferToInt(data.key.slice(sliceStart + blockNumberLength + txNumberLength, sliceStart + blockNumberLength + txNumberLength + txOutputNumberLength))\n                toReturn[\"value\"] = out.value.toString(10);\n                toReturn['output'] = out;\n                utxos.push(toReturn);\n            }\n        })\n        .on('error', function (err) {\n            console.log('Oh my!', err)\n            cb(err, null)\n        })\n        .on('close', function () {\n            // cb(null, utxos)\n            // console.log('Stream closed')\n        })\n        .on('end', function () {\n            cb(null, utxos)\n            // console.log('Stream ended')\n        })\n    }\n\n    async function getWithdrawsForAddress(addressString, cb) {\n        addressString = ethUtil.addHexPrefix(addressString)\n        if (!ethUtil.isValidAddress(addressString)){\n            cb(true, null);\n        }\n        address = ethUtil.toBuffer(addressString);\n        const utxos = [];\n        const start = Buffer.concat([withdrawsForAddressPrefix,\n            address,\n            Buffer.alloc(blockNumberLength), \n            Buffer.alloc(txNumberLength)])\n        const stop = Buffer.concat([withdrawsForAddressPrefix,\n            address,\n            Buffer.from(\"ff\".repeat(blockNumberLength), 'hex'), \n            Buffer.from(\"ff\".repeat(txNumberLength), 'hex'),])\n        const sliceStart = withdrawsForAddressPrefix.length + address.length;\n        levelDB.createReadStream({gte: start,\n                                    lte: stop,\n                                    reversed:true})\n        .on('data', function (data) {\n            toReturn = {};\n            toReturn[\"blockNumber\"] = ethUtil.bufferToInt(data.key.slice(sliceStart, sliceStart + blockNumberLength))\n            toReturn[\"txNumberInBlock\"] = ethUtil.bufferToInt(data.key.slice(sliceStart + blockNumberLength, sliceStart + blockNumberLength + txNumberLength))\n            utxos.push(toReturn);\n        })\n        .on('error', function (err) {\n            console.log('Oh my!', err)\n            cb(err, null)\n        })\n        .on('close', function () {\n            // cb(null, utxos)\n            // console.log('Stream closed')\n        })\n        .on('end', function () {\n            cb(null, utxos)\n            // console.log('Stream ended')\n        })\n    }\n}"
  },
  {
    "path": "app/helpers/getBlock.js",
    "content": "const config = require(\"../config/config\");\nconst blockPrefix = config.blockPrefix;\nconst Block = require(\"../../lib/Block/block\");\nconst {blockNumberLength,\n    txNumberLength,\n    txTypeLength, \n    signatureVlength,\n    signatureRlength,\n    signatureSlength,\n    merkleRootLength,\n    previousHashLength,\n    txOutputNumberLength,\n    txAmountLength,\n    txToAddressLength} = require('../../lib/dataStructureLengths');\nconst ethUtil = require('ethereumjs-util');\nconst BN = ethUtil.BN;\n\nmodule.exports = function(levelDB) {\n    return async function getBlockByNumber(blockNumber) {\n        const blockNumberBuffer = ethUtil.setLengthLeft(ethUtil.toBuffer(new BN(blockNumber)),blockNumberLength)\n        const key = Buffer.concat([blockPrefix, blockNumberBuffer]);\n        const blockBin = await levelDB.get(key);\n        const block = new Block(blockBin);\n        return block;\n    } \n}\n\n"
  },
  {
    "path": "app/helpers/getTX.js",
    "content": "const config = require(\"../config/config\");\nconst blockPrefix = config.blockPrefix;\nconst utxoPrefix = config.utxoPrefix;\nconst transactionPrefix = config.transactionPrefix;\nconst {TransactionOutput} = require(\"../../lib/Tx/output\");\nconst {TransactionInput} = require(\"../../lib/Tx/input\");\nconst {PlasmaTransaction, TxLengthForType} = require(\"../../lib/Tx/tx\");\nconst {BlockHeader} = require(\"../../lib/Block/blockHeader\");\nconst ethUtil = require('ethereumjs-util');\nconst BN = ethUtil.BN;\n\nconst {blockNumberLength,\n    txNumberLength,\n    txTypeLength, \n    signatureVlength,\n    signatureRlength,\n    signatureSlength,\n    merkleRootLength,\n    previousHashLength,\n    txOutputNumberLength,\n    txAmountLength,\n    txToAddressLength} = require('../../lib/dataStructureLengths');\n\nmodule.exports = function(levelDB) {\n\n    return async function getTX(blockNumber, txNumber) {\n        const blockNumberBuffer = ethUtil.setLengthLeft(ethUtil.toBuffer(new BN(blockNumber)),blockNumberLength)\n        const txNumberBuffer = ethUtil.setLengthLeft(ethUtil.toBuffer(new BN(txNumber)),txNumberLength)\n        const query = Buffer.concat([transactionPrefix, \n            blockNumberBuffer, \n            txNumberBuffer])\n        try {\n            const data = await levelDB.get(query);\n            const txType = ethUtil.bufferToInt(data.slice(txNumberLength,txNumberLength+txOutputNumberLength))\n            const txBin = data.slice(0, TxLengthForType[txType]);\n            const TX = PlasmaTransaction.prototype.initTxForTypeFromBinary(txType, txBin);\n            return TX\n        }\n        catch(err) {\n            return null;\n        }\n    }\n}"
  },
  {
    "path": "app/helpers/getUTXO.js",
    "content": "const config = require(\"../config/config\");\nconst blockPrefix = config.blockPrefix;\nconst utxoPrefix = config.utxoPrefix;\nconst {TransactionOutput} = require(\"../../lib/Tx/output\");\nconst {TransactionInput} = require(\"../../lib/Tx/input\");\nconst {BlockHeader} = require(\"../../lib/Block/blockHeader\");\nconst ethUtil = require('ethereumjs-util');\nconst BN = ethUtil.BN;\n\nconst {blockNumberLength,\n    txNumberLength,\n    txTypeLength, \n    signatureVlength,\n    signatureRlength,\n    signatureSlength,\n    merkleRootLength,\n    previousHashLength,\n    txOutputNumberLength,\n    txAmountLength,\n    txToAddressLength} = require('../../lib/dataStructureLengths');\n\nmodule.exports = function(levelDB) {\n\n    return async function getUTXO(blockNumber, txNumber, outputNumber) {\n        const blockNumberBuffer = ethUtil.setLengthLeft(ethUtil.toBuffer(new BN(blockNumber)),blockNumberLength)\n        const txNumberBuffer = ethUtil.setLengthLeft(ethUtil.toBuffer(new BN(txNumber)),txNumberLength)\n        const txOutputNumberBuffer = ethUtil.setLengthLeft(ethUtil.toBuffer(new BN(outputNumber)),txOutputNumberLength)\n        const query = Buffer.concat([utxoPrefix, \n            blockNumberBuffer, \n            txNumberBuffer,\n            txOutputNumberBuffer])\n        try {\n            const data = await levelDB.get(query);\n            return TransactionOutput.prototype.initFromBinaryBlob(data);\n        }\n        catch(err) {\n            return null;\n        }\n    }\n}"
  },
  {
    "path": "app/helpers/hexDataToEncodedBytes.js",
    "content": "const ethUtil = require('ethereumjs-util'); \nmodule.exports = function convertForRemix(hexString){\n    const hex = ethUtil.addHexPrefix(hexString);\n    const bArray = ethUtil.toBuffer(hex);\n    const encodedArray = [];\n    for (var i=0; i<bArray.length; i++) {\n        const b = bArray.slice(i, i+1);\n        const h = ethUtil.addHexPrefix(ethUtil.bufferToHex(b));\n        encodedArray.push(h);\n    }\n    return encodedArray;\n}"
  },
  {
    "path": "app/helpers/prepareProofForTX.js",
    "content": "//demo purposes only\nconst Web3 = require('web3');\nconst ethUtil = require('ethereumjs-util'); \nconst assert = require('assert');\nconst {PlasmaTransaction,\n    TxTypeFund, \n    TxTypeMerge, \n    TxTypeSplit, \n    TxTypeWithdraw, \n    TxTypeTransfer, \n    TxLengthForType,\n    NumInputsForType,\n    NumOutputsForType} = require('../../lib/Tx/tx');\n\nconst encodeForRemix = require(\"./hexDataToEncodedBytes\");\n\nmodule.exports = function(levelDB) {\n    const getBlockByNumber = require('./getBlock')(levelDB);\n    const getTX = require('./getTX')(levelDB);\n\n    return  async function prepareProofsForTX(blockNumber, txNumberInBlock) {\n        const block = await getBlockByNumber(blockNumber);\n        const tx = block.transactions[txNumberInBlock];\n        let proof = ethUtil.bufferToHex(Buffer.concat(block.merkleTree.getProof(txNumberInBlock, true)));\n        const raw = tx.raw.filter((r) => {\n            return r != undefined;\n        })\n        const encodedTx = ethUtil.bufferToHex(Buffer.concat(raw))\n        // if (proof == \"0x\") {\n        //     proof = \"0x00\"\n        // }\n        // console.log(block.header.merkleRootHash.toString('hex'));\n        // console.log(JSON.stringify(encodeForRemix(proof)));\n        // console.log(JSON.stringify(encodeForRemix(encodedTx)));\n        return {\n            blockNumber: blockNumber,\n            txNumberInBlock: txNumberInBlock,\n            merkleProof: proof,\n            tx: encodedTx\n        }\n    }\n}\n"
  },
  {
    "path": "app/helpers/processDepositEvent.js",
    "content": "const createFundingTransaction = require('./createFundingTransaction');\nconst Web3 = require('web3');\nconst BN = Web3.utils.BN;\nconst config = require('../config/config');\nconst ethUtil = require('ethereumjs-util');\nmodule.exports = function(app, levelDB, web3) {\n    return async function processDepositEvent(event){\n        const {_from, _amount, _depositIndex} = event.returnValues;\n        let depositIndexBN = new BN(_depositIndex);\n        const depositIndexKey = Buffer.concat([config.depositIndexPrefix, ethUtil.toBuffer(depositIndexBN)]);\n        try{\n            const existingKey = await levelDB.get(depositIndexKey);\n            return\n        }\n        catch(error) {\n            if (error.type !== \"NotFoundError\"){\n                throw error\n            }\n            await levelDB.put(depositIndexKey, Buffer.alloc(1, \"0x01\", \"hex\"))\n        }\n        const tx = createFundingTransaction(_from, new Web3.utils.BN(_amount), depositIndexBN);\n        let txRaw = ethUtil.bufferToHex(Buffer.concat(tx.clearRaw(false, false)));\n        const txHash = tx.hash(false,false).toString('hex');\n        const signature = await web3.eth.sign(txRaw, config.plasmaOperatorAddress);\n        tx.serializeSignature(signature);\n        // const pubKey = ethUtil.ecrecover(txHash, ethUtil.bufferToInt(tx.v), tx.r, tx.s);\n        // const signedFromAddress = ethUtil.publicToAddress(pubKey).toString('hex');\n        if (tx.validate()) {\n            app.txQueueArray.push(tx);\n            // console.log(\"Pushed new TX\")\n            console.log(event);\n        }\n        else {\n            // console.log(\"Invalid funding TX\");\n        }\n    }\n}"
  },
  {
    "path": "app/helpers/processExpressWithdrawMadeEvent.js",
    "content": "const createFundingTransaction = require('./createFundingTransaction');\nconst Web3 = require('web3');\nconst BN = Web3.utils.BN;\nconst config = require('../config/config');\nconst ethUtil = require('ethereumjs-util');\n\nconst {blockNumberLength,\n    txNumberLength,\n    txTypeLength, \n    signatureVlength,\n    signatureRlength,\n    signatureSlength,\n    merkleRootLength,\n    previousHashLength,\n    txOutputNumberLength,\n    txAmountLength,\n    txToAddressLength} = require('../../lib/dataStructureLengths');\n    \n\nmodule.exports = function(app, levelDB, web3) {\n    return async function processExpressWithdrawMakeEvent(event){\n        const {_withdrawTxBlockNumber, _withdrawTxNumberInBlock, _from} = event.returnValues;\n        let txBlockNumberBN = new BN(_withdrawTxBlockNumber);\n        let txNumberInBlockBN =  new BN(_withdrawTxNumberInBlock);\n        let senderAddress = ethUtil.toBuffer(_from);\n        const keyForWithdrawalIndex = Buffer.concat([config.withdrawsForAddressPrefix,\n            senderAddress,\n            ethUtil.setLengthLeft(ethUtil.toBuffer(txBlockNumberBN),blockNumberLength), \n            ethUtil.setLengthLeft(ethUtil.toBuffer(txNumberInBlockBN),txNumberLength)])\n        await levelDB.del(keyForWithdrawalIndex);\n    }\n}"
  },
  {
    "path": "app/helpers/processWithdrawFinalazedEvent.js",
    "content": "const createFundingTransaction = require('./createFundingTransaction');\nconst Web3 = require('web3');\nconst BN = Web3.utils.BN;\nconst config = require('../config/config');\nconst ethUtil = require('ethereumjs-util');\nmodule.exports = function(app, web3) {\n    return async function processWithdrawFinalizedEvent(event){\n        const {_blockNumber, _txNumberInBlock, _outputNumberInTX} = event.returnValues;\n        const keyForWithdrawalIndex = Buffer.concat([config.withdrawsForAddressPrefix,\n            senderAddress,\n            ethutil.blockNumber, \n            tx.transactionNumberInBlock])\n        let depositIndexBN = new BN(_depositIndex);\n        const tx = createFundingTransaction(_from, new Web3.utils.BN(_amount), depositIndexBN);\n        let txRaw = ethUtil.bufferToHex(Buffer.concat(tx.clearRaw(false, false)));\n        const txHash = tx.hash(false,false).toString('hex');\n        const signature = await web3.eth.sign(txRaw, config.plasmaOperatorAddress);\n        tx.serializeSignature(signature);\n        // const pubKey = ethUtil.ecrecover(txHash, ethUtil.bufferToInt(tx.v), tx.r, tx.s);\n        // const signedFromAddress = ethUtil.publicToAddress(pubKey).toString('hex');\n        if (tx.validate()) {\n            app.txQueueArray.push(tx);\n            console.log(\"Pushed new TX\")\n            console.log(event);\n        }\n        else {\n            console.log(\"Invalid funding TX\");\n        }\n    }\n}"
  },
  {
    "path": "app/helpers/processWithdrawStartedEvent.js",
    "content": ""
  },
  {
    "path": "app/helpers/signatureChecks.js",
    "content": "const ethUtil = require('ethereumjs-util'); \n\nfunction signForECRECOVER(dataBuffer, privKeyBuffer) {\n    const hash = ethUtil.hashPersonalMessage(dataBuffer);\n    const signatureObject = ethUtil.ecsign(hash, privKeyBuffer);\n    return {hash, signatureObject};\n}\n\nfunction checkSender(dataBuffer, signatureObject, address) {\n    const hash = ethUtil.hashPersonalMessage(dataBuffer);\n    const pubKey = ethUtil.ecrecover(hash, signatureObject.v, signatureObject.r, signatureObject.s);\n    const signedFromAddress = ethUtil.publicToAddress(pubKey).toString('hex');\n    return signedFromAddress == address;\n}\n\nfunction testSignature() {\n    const data = \"test\";\n    const dataBuffer = Buffer.from(data);\n    const {hash, signatureObject} = signForECRECOVER(dataBuffer, privKeys[0]);\n    const valid = checkSender(dataBuffer, signatureObject, ethUtil.privateToAddress(privKeys[0]).toString('hex'));\n    assert(valid);\n}\n\nmodule.exports = {\n    signForECRECOVER,\n    checkSender,\n}"
  },
  {
    "path": "app/miner.js",
    "content": "const config = require(\"./config/config\");\nconst blockPrefix = config.blockPrefix;\nconst utxoPrefix = config.utxoPrefix;\nconst utxoIncludingAddressPrefix = config.utxoIncludingAddressPrefix;\nconst makeAddressIndex = config.makeAddressIndex;\nconst headerPrefix = config.headerPrefix;\nconst transactionPrefix=config.transactionPrefix;\nconst blockTime = config.blockTime;\n\nconst {blockNumberLength,\n    txNumberLength,\n    txTypeLength, \n    signatureVlength,\n    signatureRlength,\n    signatureSlength,\n    merkleRootLength,\n    previousHashLength,\n    txOutputNumberLength,\n    txAmountLength,\n    txToAddressLength} = require('../lib/dataStructureLengths');\n\nconst Web3 = require('web3');\nconst Block = require('../lib/Block/block');\nconst ethUtil = require('ethereumjs-util'); \nconst BN = ethUtil.BN;\nconst plasmaOperatorAddress = config.plasmaOperatorAddress;\nconst assert = require('assert');\nconst {PlasmaTransaction,\n    TxTypeFund, \n    TxTypeMerge, \n    TxTypeSplit, \n    TxTypeWithdraw,\n    TxTypeTransfer, \n    TxLengthForType,\n    NumInputsForType,\n    NumOutputsForType} = require('../lib/Tx/tx');\n    \nconst encodeForRemix = require('./helpers/hexDataToEncodedBytes');\n\nmodule.exports = function(app, levelDB, web3) {\n    const checkSpendingTX = require('./helpers/checkSpendingTX')(levelDB);\n    const getBlockByNumber = require('./helpers/getBlock')(levelDB);\n    function startBlockProcessing(app, fromBlock) {\n        processBlockForDepositEvents(fromBlock)().then((_dispose) => {\n            console.log(\"Started block processing loop\");\n        })\n    \n        function processBlockForDepositEvents(previousBlockNumber) {\n            return async function() {\n                try{\n                    let lastblock = await web3.eth.getBlockNumber();\n                    if (previousBlockNumber == -1) {\n                        previousBlockNumber = lastblock-1;\n                    }  \n                    if (lastblock > previousBlockNumber) {\n                        lastblock = previousBlockNumber + 1;\n                        // lastProcessedBlock = lastblock;\n                        console.log(\"Started at block \" + lastblock);\n                        await processBlock(lastblock)();\n                        setTimeout(processBlockForDepositEvents(lastblock), 100);\n                        return;\n                    } else {\n                        setTimeout(processBlockForDepositEvents(lastblock), 1000);\n                        return;\n                    }\n                }\n                catch(error) {\n                    console.log(\"Error processing block for events : \" + error);\n                    if (error.name == \"Submitting too far in future\") {\n                        setImmediate(processBlockForDepositEvents(error.message));\n                        return;\n                    }\n                    setImmediate(processBlockForDepositEvents(previousBlockNumber));\n                }\n            }\n        }\n    \n        function processBlock(blockNumber) {\n            return async function() {\n                const expressWithdrawEventsInBlock = await app.DeployedPlasmaContract.getPastEvents(\"ExpressWithdrawMadeEvent\",{\n                    fromBlock: blockNumber,\n                    toBlock: blockNumber\n                });\n\n                if (expressWithdrawEventsInBlock.length > 0) {\n                    for (let i = 0; i< expressWithdrawEventsInBlock.length; i++){\n                        await app.processExpressWithdrawMakeEvent(expressWithdrawEventsInBlock[i]);\n                    }\n                }\n\n\n                const depositEventsInBlock = await app.DeployedPlasmaContract.getPastEvents(\"DepositEvent\",{\n                    fromBlock: blockNumber,\n                    toBlock: blockNumber\n                });\n\n                if (depositEventsInBlock.length > 0) {\n                    for (let i = 0; i< depositEventsInBlock.length; i++){\n                        await app.processDepositEvent(depositEventsInBlock[i]);\n                    }\n                }\n                const blockNumberBN = Web3.utils.toBN(blockNumber);\n                const newBlockNumberBuffer = ethUtil.setLengthLeft(ethUtil.toBuffer(blockNumberBN), blockNumberLength);\n                await levelDB.put(config.lastEventProcessedBlockPrefix, newBlockNumberBuffer);\n\n\n            }\n        } \n    }\n\n\n    async function createBlock() {\n        try{\n            try{\n                lastBlock = await levelDB.get('lastBlockNumber');\n            }\n            catch(error) {\n                lastBlock = ethUtil.setLengthLeft(ethUtil.toBuffer(new BN(0)),blockNumberLength)\n                await levelDB.put('lastBlockNumber', lastBlock);\n            }\n            try{\n                lastBlockHash = await levelDB.get('lastBlockHash');\n            }\n            catch(error) {\n                lastBlockHash = ethUtil.sha3('bankex.com')\n                await levelDB.put('lastBlockHash', lastBlockHash);\n            }\n\n            let sliceLen;\n            let TXs;\n            console.log(\"Mining a block\")\n            console.log(\"Queue length = \" + app.txQueueArray.length);\n            if (app.txQueueArray.length == 0) {\n                return false;\n            }\n            if (app.txQueueArray.length > 2**16){\n                // TXs = app.txQueueArray.splice(0, 2**16);\n                TXs = app.txQueueArray.slice(0, 2**16);\n                sliceLen = 2**16\n            } else {\n                // TXs = app.txQueueArray.splice(0, app.txQueueArray.length);\n                TXs = app.txQueueArray.slice(0, app.txQueueArray.length);\n                sliceLen = app.txQueueArray.length\n            }\n            if (TXs.length == 0) {\n                return false;\n            }\n            const allReferencedInputs = {};\n            TXs = TXs.filter((tx) => {\n                const key = tx.getKey();\n                if (key === \"000000000000000000\") {\n                    return true;\n                }\n                if (!allReferencedInputs[key]) {\n                    allReferencedInputs.key = true;\n                    return true;\n                }\n                return false;\n            })\n            let TXsWithValidInputs = [];\n            for (let i=0; i<TXs.length; i++) {\n                const valid = await checkSpendingTX(TXs[i]);\n                if (valid) {\n                    TXsWithValidInputs.push(TXs[i]);\n                }\n            }\n            TXs = TXsWithValidInputs\n            for (let i=0; i<TXs.length; i++) {\n                TXs[i].assignNumber(i);\n            }\n            if (TXs.length == 0) {\n                return true;\n            }\n            const lastBlockNumber = Web3.utils.toBN(ethUtil.addHexPrefix(lastBlock.toString('hex')));\n            const newBlockNumber = lastBlockNumber.add(new BN(1));\n            const newBlockNumberBuffer = ethUtil.setLengthLeft(ethUtil.toBuffer(newBlockNumber), blockNumberLength);\n            const blockParams = {\n                blockNumber:  newBlockNumberBuffer,\n                parentHash: lastBlockHash,\n                transactions: TXs\n            }\n            const block = new Block(blockParams); \n            let blockRaw = block.clearRaw(false);\n            blockRaw = ethUtil.bufferToHex(Buffer.concat(blockRaw));\n            const signature = await web3.eth.sign(blockRaw, config.plasmaOperatorAddress);\n            const blockHash = block.hash(false).toString('hex');\n            console.log(\"Block hash = \" + blockHash);\n            console.log(\"Block signature = \" + signature);\n            block.serializeSignature(signature);\n            assert(block.validate());\n            await writeBlock(block);\n            console.log(\"Created block \" + newBlockNumber);\n            app.txQueueArray = app.txQueueArray.slice(sliceLen);\n            // const submitted = await submitBlockHeader(block)();\n            // if (!submitted) {\n            //     throw(\"Couldn't submit\");\n            // }\n            // console.log(\"Submitted header for block \"+newBlockNumber)\n            return true;\n                \n        }\n        catch(err){\n            console.log(err);\n        }\n    } \n\n    async function writeBlock(block) {\n        var writeRequest =  levelDB.batch()\n                        .put('lastBlockNumber', block.header.blockNumber)\n                        .put('lastBlockHash', block.hash(true))\n                        .put(Buffer.concat([blockPrefix,block.header.blockNumber]),Buffer.concat(block.raw))\n                        .put(Buffer.concat([headerPrefix,block.header.blockNumber]),Buffer.concat(block.header.raw))\n        block.transactions.forEach((tx, i)=>{\n            const senderAddress = tx.getSenderAddress();\n            for (let inpIndex of [0,1]) {\n                const input = tx.getTransactionInput(inpIndex)\n                if (input && typeof input != \"undefined\") {\n                    const keyForUTXO = Buffer.concat([utxoPrefix, input.blockNumber, input.txNumberInBlock, input.outputNumberInTransaction]);\n                    writeRequest.del(keyForUTXO)\n                    if (makeAddressIndex) {\n                        const keyForAddressUTXO = Buffer.concat([utxoIncludingAddressPrefix, senderAddress, input.blockNumber, input.txNumberInBlock, input.outputNumberInTransaction]);\n                        writeRequest.del(keyForAddressUTXO)\n                    }\n                }\n            }\n            for (let outIndex of [0,1]) {\n                const output = tx.getTransactionOutput(outIndex);\n                if (output && typeof output != \"undefined\" && !(output.outputNumberInTransaction.equals(Buffer.from('ff', 'hex'))) ) {\n                    const keyForUTXO = Buffer.concat([utxoPrefix, block.header.blockNumber, tx.transactionNumberInBlock, output.outputNumberInTransaction]);\n                    writeRequest.put(keyForUTXO, Buffer.concat(output.raw))\n                    if (makeAddressIndex) {\n                        const recipientAddress = output.to;\n                        const keyForAddressUTXO = Buffer.concat([utxoIncludingAddressPrefix, recipientAddress, block.header.blockNumber, tx.transactionNumberInBlock, output.outputNumberInTransaction]);\n                        writeRequest.put(keyForAddressUTXO, Buffer.concat(output.raw))\n                    }\n                }\n            }\n\n            if (tx.transactionTypeUInt() == TxTypeWithdraw) {\n                const keyForWithdrawalIndex = Buffer.concat([config.withdrawsForAddressPrefix,senderAddress,block.header.blockNumber, tx.transactionNumberInBlock])\n                writeRequest.put(keyForWithdrawalIndex, Buffer.alloc(1, \"0x01\", \"hex\"))\n            }\n\n            if (config.makeTransactionIndexForAddress) {\n                // if (ethUtil.bufferToHex(senderAddress).toLowerCase() != config.plasmaOperatorAddress.toLowerCase()) {\n                    const transactionIndexKey = Buffer.concat([config.txForAddressIndexPrefix, senderAddress, block.header.blockNumber, tx.transactionNumberInBlock])\n                    writeRequest.put(transactionIndexKey, Buffer.alloc(1, \"0x01\", \"hex\"))\n                // }\n            }\n\n            const r = tx.clearRaw(true, true);\n            writeRequest.put(Buffer.concat([transactionPrefix, block.header.blockNumber, tx.transactionNumberInBlock]), Buffer.concat(r))\n        })\n\n        await writeRequest.write();\n    }\n\n    function startHeadersSubmission(app, fromBlock) {\n        processBlockNumberForSubmission(fromBlock)().then((_dispose) => {\n            console.log(\"Started header submission loop\");\n        })\n    \n        function processBlockNumberForSubmission(previousBlockNumber) {\n            return async function() {\n                try{\n                    let lastblock = await levelDB.get(\"lastBlockNumber\");\n                    lastblock = ethUtil.bufferToInt(lastblock);\n                    if (lastblock == 0) {\n                        setTimeout(processBlockNumberForSubmission(lastblock), 1000);\n                        return;\n                    }\n                    if (previousBlockNumber == -1) {\n                        previousBlockNumber = lastblock-1;\n                    }  \n                    if (lastblock > previousBlockNumber) {\n                        lastblock = previousBlockNumber + 1;\n                        console.log(\"Started header submission \" + lastblock);\n                        await processBlockForSubmission(lastblock)();\n                        setTimeout(processBlockNumberForSubmission(lastblock), 100);\n                        return;\n                    } else {\n                        setTimeout(processBlockNumberForSubmission(lastblock), 1000);\n                        return;\n                    }\n                }\n                catch(error) {\n                    console.log(\"Error processing block header : \" + error);\n                    setImmediate(processBlockNumberForSubmission(previousBlockNumber));\n                }\n            }\n        }\n    \n        function processBlockForSubmission(blockNumber) {\n            return async function() {\n                const block = await getBlockByNumber(blockNumber)\n                const submitted = await submitBlockHeader(block)();\n                if (!submitted) {\n                    throw(\"Couldn't submit\");\n                }\n                console.log(\"Submitted header for block \"+blockNumber)\n                const blockNumberBN = Web3.utils.toBN(blockNumber);\n                const newBlockNumberBuffer = ethUtil.setLengthLeft(ethUtil.toBuffer(blockNumberBN), blockNumberLength);\n                await levelDB.put(config.lastSubmittedHeaderPrefix, newBlockNumberBuffer);\n            }\n        } \n    }\n\n    function submitBlockHeader(block){\n        return async function() {\n            const hexData = ethUtil.addHexPrefix(Buffer.concat(block.header.raw).toString('hex'));\n            const blockNumber = Web3.utils.toBN(ethUtil.bufferToInt(block.header.blockNumber));\n            console.log(\"Submitting header = \" + hexData);\n            let lastSubmitted;\n            // console.log(JSON.stringify(encodeForRemix(hexData)));\n            try{\n                lastSubmitted = await app.DeployedPlasmaContract.methods.lastBlockNumber().call();\n                lastSubmitted = Web3.utils.toBN(lastSubmitted)\n                if (lastSubmitted.gte(blockNumber)) {\n                    return true;\n                }\n                const distance = blockNumber.sub(lastSubmitted);\n                const ONE = Web3.utils.toBN(1);\n                if (distance.gt(ONE)) {\n                    throw {name: \"Submitting too far in future\", message: lastSubmitted.toNumber()}\n                }\n                const gasCost = await app.DeployedPlasmaContract.methods.submitBlockHeader(hexData).estimateGas({from: config.plasmaOperatorAddress, gas: 1e6})\n                const res = await app.DeployedPlasmaContract.methods.submitBlockHeader(hexData).send({from: config.plasmaOperatorAddress, gas: gasCost});\n                const submissionEvent = res.events.HeaderSubmittedEvent.returnValues;\n                console.log(submissionEvent);\n                assert(submissionEvent._blockNumber == blockNumber.toString(10));\n                return true;\n            }\n            catch(err){ \n                console.log(err)\n                if (err.name == \"Submitting too far in future\"){\n                    throw err;\n                }\n                if (err.message == \"Returned error: gas required exceeds allowance or always failing transaction\") {\n\n                }\n            }\n            return false\n        }\n    }\n\n\n    async function tryToMine() {\n        const mined = await createBlock();\n        setTimeout(tryToMine, blockTime)\n        return true\n    }\n\n    function sleep(ms) {\n        return new Promise(resolve => setTimeout(resolve, ms));\n      }\n    tryToMine().then((res) => {\n        console.log(\"Started mining loop\")\n    })\n    levelDB.get(config.lastEventProcessedBlockPrefix)\n        .then((res) => {\n            const lastProcessedBlock = Web3.utils.toBN(ethUtil.addHexPrefix(res.toString('hex'))).toNumber();\n            // const lastProcessedBlock = 1408111 - 1;\n            startBlockProcessing(app, lastProcessedBlock);\n        })\n        .catch((e) => {\n            const lastProcessedBlock = -1;\n            // const lastProcessedBlock = 1345677;\n            startBlockProcessing(app, lastProcessedBlock);\n    });\n\n    levelDB.get(config.lastSubmittedHeaderPrefix)\n    .then((res) => {\n        const lastProcessedHeader = Web3.utils.toBN(ethUtil.addHexPrefix(res.toString('hex'))).toNumber();\n        // const lastProcessedBlock = 1372150;\n        startHeadersSubmission(app, lastProcessedHeader);\n    })\n    .catch((e) => {\n        const lastProcessedHeader = -1;\n        // const lastProcessedBlock = 1345677;\n        startHeadersSubmission(app, lastProcessedHeader);\n});\n    \n}"
  },
  {
    "path": "compile.js",
    "content": "const assert = require('assert');\nvar fs = require(\"fs\");\nvar solc = require('solc');\nvar rimraf = require('rimraf');\nrimraf.sync('./build/contracts');\n \nconst Artifactor = require(\"truffle-artifactor\"); \nconst TruffleContract = require('truffle-contract');\n\nconst Web3 = require(\"web3\");\nconst util = require('util');\n\nconst artifactor = new Artifactor(\"./build/contracts\");\nfunction sleep(ms) {\n  return new Promise(resolve => setTimeout(resolve, ms));\n}\n\nconst Contracts = {\n  \"PlasmaParent\" : [\"PlasmaParent\"]\n}\n\n\nfunction findImports (path) {\n  try{\n    var input = fs.readFileSync(\"./contracts/\"+path);\n    var ret = {contents: input.toString()};\n    // ret[path] = input.toString();\n    return ret;\n  }\n  catch(error){\n    return { error: 'File not found' }\n  }\n}\n\nasync function main() {\n  console.log(\"Compiling contracts...\");\n  let inputs = {}; \n  let output;\n    for (let contract in Contracts){\n      inputs[contract+'.sol'] =  fs.readFileSync(\"./contracts/\" + contract + '.sol', 'utf8');\n    }\n    try{ \n      output = solc.compile({ sources: inputs }, 1, findImports)\n    }\n    catch(error){\n      console.log(error);\n    }\n    for (err in output.errors){\n      console.log(output.errors[err]);\n    }\n    if (!output.contracts || Object.keys(output.contracts).length == 0){\n      throw(\"Didn't compile\");\n    }\n    const libraryRE = new RegExp('__([a-zA-Z.:]+)[_]*', 'g');\n    for (let property in output.contracts) {\n      let inList = false;\n      for (let c in Contracts) {\n        for (let cName of Contracts[c]){\n          let fullName = c+\".sol:\"+cName;\n\n          if (property === fullName){\n            inList = true;\n            break;\n          }\n        }\n        if (inList){\n          break;\n        }\n      }\n      if (!inList){\n        continue;\n      }\n      if (output.contracts.hasOwnProperty(property)) {\n        let cont = output.contracts[property];\n        let bytecode = cont.bytecode;\n        if (libraryRE.test(bytecode)){\n          console.log(\"Linking is necessary!\");\n          var m;\n          m = libraryRE.exec(bytecode);\n          while ((m = libraryRE.exec(bytecode)) !== null) {\n            if (m.index === libraryRE.lastIndex) {\n              libraryRE.lastIndex++;\n            }\n            const libName = m[1];\n            const libObject = {};\n            libObject[libName] = output.contracts[libName].bytecode;\n          }\n        }\n        if (bytecode == \"\"){\n          console.log(\"Bytecode is empty!\");\n        }\n        try{\n          var abi = JSON.parse(cont.interface);\n        }\n        catch(e){\n          console.log(e);\n        }\n        const p = property.split(':');\n        await artifactor.save({contract_name: p[p.length-1],  abi: abi, unlinked_binary: bytecode});\n      }\n  }\n    console.log(\"Done compiling\");\n}  \n\nmodule.exports = main;\n\n "
  },
  {
    "path": "contracts/PlasmaParent.sol",
    "content": "pragma solidity ^0.4.18;\n\nlibrary ByteSlice {\n\n    struct Slice {\n        uint _unsafe_memPtr;   // Memory address of the first byte.\n        uint _unsafe_length;   // Length.\n    }\n\n    /// @dev Converts bytes to a slice.\n    /// @param self The bytes.\n    /// @return A slice.\n    function slice(bytes memory self) internal pure returns (Slice memory newSlice) {\n        assembly {\n            let length := mload(self)\n            let memPtr := add(self, 0x20)\n            mstore(newSlice, mul(memPtr, iszero(iszero(length))))\n            mstore(add(newSlice, 0x20), length)\n        }\n    }\n\n    /// @dev Converts bytes to a slice from the given starting position.\n    /// 'startpos' <= 'len(slice)'\n    /// @param self The bytes.\n    /// @param startpos The starting position.\n    /// @return A slice.\n    function slice(bytes memory self, uint startpos) internal pure returns (Slice memory) {\n        return slice(slice(self), startpos);\n    }\n\n    /// @dev Converts bytes to a slice from the given starting position.\n    /// -len(slice) <= 'startpos' <= 'len(slice)'\n    /// @param self The bytes.\n    /// @param startpos The starting position.\n    /// @return A slice.\n    function slice(bytes memory self, int startpos) internal pure returns (Slice memory) {\n        return slice(slice(self), startpos);\n    }\n\n    /// @dev Converts bytes to a slice from the given starting-position, and end-position.\n    /// 'startpos <= len(slice) and startpos <= endpos'\n    /// 'endpos <= len(slice)'\n    /// @param self The bytes.\n    /// @param startpos The starting position.\n    /// @param endpos The end position.\n    /// @return A slice.\n    function slice(bytes memory self, uint startpos, uint endpos) internal view returns (Slice memory) {\n        return slice(slice(self), startpos, endpos);\n    }\n\n    /// @dev Converts bytes to a slice from the given starting-position, and end-position.\n    /// Warning: higher cost then using unsigned integers.\n    /// @param self The bytes.\n    /// @param startpos The starting position.\n    /// @param endpos The end position.\n    /// @return A slice.\n    function slice(bytes memory self, int startpos, int endpos) internal view returns (Slice memory) {\n        return slice(slice(self), startpos, endpos);\n    }\n\n    /// @dev Get the length of the slice (in bytes).\n    /// @param self The slice.\n    /// @return the length.\n    function len(Slice memory self) internal pure returns (uint) {\n        return self._unsafe_length;\n    }\n\n    /// @dev Returns the byte from the backing array at a given index.\n    /// The function will throw unless 'index < len(slice)'\n    /// @param self The slice.\n    /// @param index The index.\n    /// @return The byte at that index.\n    function at(Slice memory self, uint index) internal pure returns (byte b) {\n        if (index >= self._unsafe_length)\n            revert();\n        uint bb;\n        assembly {\n            // Get byte at index, and format to 'byte' variable.\n            bb := byte(0, mload(add(mload(self), index)))\n        }\n        b = byte(bb);\n    }\n\n    /// @dev Returns the byte from the backing array at a given index.\n    /// The function will throw unless '-len(self) <= index < len(self)'.\n    /// @param self The slice.\n    /// @param index The index.\n    /// @return The byte at that index.\n    function at(Slice memory self, int index) internal pure returns (byte b) {\n        if (index >= 0)\n            return at(self, uint(index));\n        uint iAbs = uint(-index);\n        if (iAbs > self._unsafe_length)\n            revert();\n        return at(self, self._unsafe_length - iAbs);\n    }\n\n    /// @dev Set the byte at the given index.\n    /// The function will throw unless 'index < len(slice)'\n    /// @param self The slice.\n    /// @param index The index.\n    /// @return The byte at that index.\n    function set(Slice memory self, uint index, byte b) internal pure {\n        if (index >= self._unsafe_length)\n            revert();\n        assembly {\n            mstore8(add(mload(self), index), byte(0, b))\n        }\n    }\n\n    /// @dev Set the byte at the given index.\n    /// The function will throw unless '-len(self) <= index < len(self)'.\n    /// @param self The slice.\n    /// @param index The index.\n    /// @return The byte at that index.\n    function set(Slice memory self, int index, byte b) internal pure {\n        if (index >= 0)\n            return set(self, uint(index), b);\n        uint iAbs = uint(-index);\n        if (iAbs > self._unsafe_length)\n            revert();\n        return set(self, self._unsafe_length - iAbs, b);\n    }\n\n    /// @dev Creates a copy of the slice.\n    /// @param self The slice.\n    /// @return the new reference.\n    function slice(Slice memory self) internal pure returns (Slice memory newSlice) {\n        newSlice._unsafe_memPtr = self._unsafe_memPtr;\n        newSlice._unsafe_length = self._unsafe_length;\n    }\n\n    /// @dev Create a new slice from the given starting position.\n    /// 'startpos' <= 'len(slice)'\n    /// @param self The slice.\n    /// @param startpos The starting position.\n    /// @return The new slice.\n    function slice(Slice memory self, uint startpos) internal pure returns (Slice memory newSlice) {\n        uint length = self._unsafe_length;\n        if (startpos > length)\n            revert();\n        assembly {\n            length := sub(length, startpos)\n            let newMemPtr := mul(add(mload(self), startpos), iszero(iszero(length)))\n            mstore(newSlice, newMemPtr)\n            mstore(add(newSlice, 0x20), length)\n        }\n    }\n\n    /// @dev Create a new slice from the given starting position.\n    /// -len(slice) <= 'startpos' <= 'len(slice)'\n    /// @param self The slice.\n    /// @param startpos The starting position.\n    /// @return The new slice.\n    function slice(Slice memory self, int startpos) internal pure returns (Slice memory newSlice) {\n        uint startpos_;\n        uint length = self._unsafe_length;\n        if (startpos >= 0) {\n            startpos_ = uint(startpos);\n            if (startpos_ > length)\n                revert();\n        } else {\n            startpos_ = uint(-startpos);\n            if (startpos_ > length)\n                revert();\n            startpos_ = length - startpos_;\n        }\n        assembly {\n            length := sub(length, startpos_)\n            let newMemPtr := mul(add(mload(self), startpos_), iszero(iszero(length)))\n            mstore(newSlice, newMemPtr)\n            mstore(add(newSlice, 0x20), length)\n        }\n    }\n\n    /// @dev Create a new slice from a given slice, starting-position, and end-position.\n    /// 'startpos <= len(slice) and startpos <= endpos'\n    /// 'endpos <= len(slice)'\n    /// @param self The slice.\n    /// @param startpos The starting position.\n    /// @param endpos The end position.\n    /// @return the new slice.\n    function slice(Slice memory self, uint startpos, uint endpos) internal pure returns (Slice memory newSlice) {\n        uint length = self._unsafe_length;\n        if (startpos > length || endpos > length || startpos > endpos)\n            revert();\n        assembly {\n            length := sub(endpos, startpos)\n            let newMemPtr := mul(add(mload(self), startpos), iszero(iszero(length)))\n            mstore(newSlice, newMemPtr)\n            mstore(add(newSlice, 0x20), length)\n        }\n    }\n\n    /// Same as new(Slice memory, uint, uint) but allows for negative indices.\n    /// Warning: higher cost then using unsigned integers.\n    /// @param self The slice.\n    /// @param startpos The starting position.\n    /// @param endpos The end position.\n    /// @return The new slice.\n    function slice(Slice memory self, int startpos, int endpos) internal pure returns (Slice memory newSlice) {\n       // Don't allow slice on bytes of length 0.\n        uint startpos_;\n        uint endpos_;\n        uint length = self._unsafe_length;\n        if (startpos < 0) {\n            startpos_ = uint(-startpos);\n            if (startpos_ > length)\n                revert();\n            startpos_ = length - startpos_;\n        }\n        else {\n            startpos_ = uint(startpos);\n            if (startpos_ > length)\n                revert();\n        }\n        if (endpos < 0) {\n            endpos_ = uint(-endpos);\n            if (endpos_ > length)\n                revert();\n            endpos_ = length - endpos_;\n        }\n        else {\n            endpos_ = uint(endpos);\n            if (endpos_ > length)\n                revert();\n        }\n        if(startpos_ > endpos_)\n            revert();\n        assembly {\n            length := sub(endpos_, startpos_)\n            let newMemPtr := mul(add(mload(self), startpos_), iszero(iszero(length)))\n            mstore(newSlice, newMemPtr)\n            mstore(add(newSlice, 0x20), length)\n        }\n    }\n\n    /// @dev Creates a 'bytes memory' variable from a slice, copying the data.\n    /// Bytes are copied from the memory address 'self._unsafe_memPtr'.\n    /// The number of bytes copied is 'self._unsafe_length'.\n    /// @param self The slice.\n    /// @return The bytes variable.\n    function toBytes(Slice memory self) internal constant returns (bytes memory bts) {\n        uint length = self._unsafe_length;\n        if (length == 0)\n            return;\n        uint memPtr = self._unsafe_memPtr;\n        bts = new bytes(length);\n        // We can do word-by-word copying since 'bts' was the last thing to be\n        // allocated. Just overwrite any excess bytes at the end with zeroes.\n        assembly {\n                let i := 0\n                let btsOffset := add(bts, 0x20)\n                let words := div(add(length, 31), 32)\n            tag_loop:\n                jumpi(end, gt(i, words))\n                {\n                    let offset := mul(i, 32)\n                    mstore(add(btsOffset, offset), mload(add(memPtr, offset)))\n                    i := add(i, 1)\n                }\n                jump(tag_loop)\n            end:\n                mstore(add(add(bts, length), 0x20), 0)\n        }\n    }\n\n    /// @dev Creates an ascii-encoded 'string' variable from a slice, copying the data.\n    /// Bytes are copied from the memory address 'self._unsafe_memPtr'.\n    /// The number of bytes copied is 'self._unsafe_length'.\n    /// @param self The slice.\n    /// @return The bytes variable.\n    function toAscii(Slice memory self) internal view returns (string memory str) {\n        return string(toBytes(self));\n    }\n\n    /// @dev Check if two slices are equal.\n    /// @param self The slice.\n    /// @param other The other slice.\n    /// @return True if both slices point to the same memory address, and has the same length.\n    function equals(Slice memory self, Slice memory other) internal pure returns (bool) {\n        return (\n            self._unsafe_length == other._unsafe_length &&\n            self._unsafe_memPtr == other._unsafe_memPtr\n        );\n    }\n\n}\n\nlibrary Bytes {\n\n    function concat(bytes memory self, bytes memory bts) internal view returns (bytes memory newBts) {\n        uint totLen = self.length + bts.length;\n        if (totLen == 0)\n            return;\n        newBts = new bytes(totLen);\n        assembly {\n                let i := 0\n                let inOffset := 0\n                let outOffset := add(newBts, 0x20)\n                let words := 0\n                let tag := tag_bts\n            tag_self:\n                inOffset := add(self, 0x20)\n                words := div(add(mload(self), 31), 32)\n                jump(tag_loop)\n            tag_bts:\n                i := 0\n                inOffset := add(bts, 0x20)\n                outOffset := add(newBts, add(0x20, mload(self)))\n                words := div(add(mload(bts), 31), 32)\n                tag := tag_end\n            tag_loop:\n                jumpi(tag, gt(i, words))\n                {\n                    let offset := mul(i, 32)\n                    outOffset := add(outOffset, offset)\n                    mstore(outOffset, mload(add(inOffset, offset)))\n                    i := add(i, 1)\n                }\n                jump(tag_loop)\n            tag_end:\n                mstore(add(newBts, add(totLen, 0x20)), 0)\n        }\n    }\n\n    function uintToBytes(uint self) internal pure returns (bytes memory s) {\n        uint maxlength = 100;\n        bytes memory reversed = new bytes(maxlength);\n        uint i = 0;\n        while (self != 0) {\n            uint remainder = self % 10;\n            self = self / 10;\n            reversed[i++] = byte(48 + remainder);\n        }\n        s = new bytes(i);\n        for (uint j = 0; j < i; j++) {\n            s[j] = reversed[i - 1 - j];\n        }\n        return s;\n    }\n}\n\ncontract PlasmaParent {\n    using Bytes for *;\n    using ByteSlice for *;\n    address public owner = msg.sender;\n    mapping(address => bool) public operators;\n    uint32 public blockHeaderLength = 137;\n    \n    uint256 public lastBlockNumber = 0;\n    uint256 public lastEthBlockNumber = block.number;\n    uint256 public depositCounterInBlock = 0;\n    \n    struct Header {\n        uint32 blockNumber;\n        uint32 numTransactions;\n        uint8 v;\n        bytes32 previousBlockHash;\n        bytes32 merkleRootHash;\n        bytes32 r;\n        bytes32 s;\n    }\n    \n    struct TransactionInput {\n        uint32 blockNumber;\n        uint32 txNumberInBlock;\n        uint8 outputNumberInTX;\n        uint256 amount;\n    }\n\n    \n    struct TransactionOutput {\n        address recipient;\n        uint8 outputNumberInTX;\n        uint256 amount;\n    }\n\n    struct PlasmaTransaction {\n        uint32 txNumberInBlock;\n        uint8 txType;\n        TransactionInput[] inputs;\n        TransactionOutput[] outputs;\n        uint8 v;\n        bytes32 r;\n        bytes32 s;\n    }\n\n    uint256 constant TxTypeNull = 0;\n    uint256 constant TxTypeSplit = 1;\n    uint256 constant TxTypeMerge = 2;\n    uint256 constant TxTypeWithdraw = 3;\n    uint256 constant TxTypeFund = 4;\n    uint256 constant TxTypeTransfer = 5;\n\n    uint256[6] NumInputsForType = [0, 1, 2, 1, 1, 1];\n    uint256[6] NumOutputsForType = [0, 2, 1, 1, 2, 1];\n\n    uint256 constant SignatureLength = 65;\n    uint256 constant BlockNumberLength = 4;\n    uint256 constant TxNumberLength = 4;\n    uint256 constant TxTypeLength = 1;\n    uint256 constant TxOutputNumberLength = 1;\n    uint256 constant PreviousHashLength = 32;\n    uint256 constant MerkleRootHashLength = 32;\n    uint256 constant TxAmountLength = 32;\n    bytes constant PersonalMessagePrefixBytes = \"\\x19Ethereum Signed Message:\\n\";\n    uint256 constant PreviousBlockPersonalHashLength = BlockNumberLength + \n                                                    TxNumberLength + \n                                                    PreviousHashLength + \n                                                    MerkleRootHashLength + \n                                                    SignatureLength;\n    uint256 constant NewBlockPersonalHashLength = BlockNumberLength + \n                                                    TxNumberLength + \n                                                    PreviousHashLength + \n                                                    MerkleRootHashLength;\n\n    uint256 TransactionOutputLength = 20 + TxOutputNumberLength + TxAmountLength;\n    uint256 TransactionInputLength = BlockNumberLength + TxNumberLength + TxOutputNumberLength + TxAmountLength;\n    uint256 TxMainLength = TxNumberLength + TxTypeLength + SignatureLength;\n\n    uint256[6] TxLengthForType = [0,\n        TxMainLength + 1*TransactionInputLength + 2*TransactionOutputLength,\n        TxMainLength + 2*TransactionInputLength + 1*TransactionOutputLength,\n        TxMainLength + 1*TransactionInputLength + 1*TransactionOutputLength,\n        TxMainLength + 1*TransactionInputLength + 2*TransactionOutputLength,\n        TxMainLength + 1*TransactionInputLength + 1*TransactionOutputLength];\n\n    mapping (uint256 => Header) public headers;\n\n    event Debug(bool indexed _success, bytes32 indexed _b, address indexed _signer);\n    event DebugUint(uint256 indexed _1, uint256 indexed _2, uint256 indexed _3);\n    event SigEvent(address indexed _signer, bytes32 indexed _r, bytes32 indexed _s);\n\n    function extract32(bytes data, uint pos) pure internal returns (bytes32 result) { \n        for (uint256 i = 0; i < 32; i++) {\n            result ^= (bytes32(0xff00000000000000000000000000000000000000000000000000000000000000)&data[i+pos])>>(i*8);\n        }   \n    }\n    \n    function extract20(bytes data, uint pos) pure internal returns (bytes20 result) { \n        for (uint256 i = 0; i < 20; i++) {\n            result ^= (bytes20(0xff00000000000000000000000000000000000000)&data[i+pos])>>(i*8);\n        }\n    }\n    \n   function extract4(bytes data, uint pos) pure internal returns (bytes4 result) { \n        for (uint256 i = 0; i < 4; i++) {\n            result ^= (bytes4(0xff000000)&data[i+pos])>>(i*8);\n        }\n    }\n\n    function extract2(bytes data, uint pos) pure internal returns (bytes2  result) { \n        for (uint256 i = 0; i < 2; i++) {\n            result ^= (bytes2(0xff00)&data[i+pos])>>(i*8);\n        }\n    }\n\n    function extract1(bytes data, uint pos) pure internal returns (bytes1  result) { \n        for (uint256 i = 0; i < 1; i++) {\n            result ^= (bytes1(0xff)&data[i+pos])>>(i*8);\n        }\n    }    \n    \n    function PlasmaParent() public {\n        operators[msg.sender] = true;\n    }\n    \n    function setOperator(address _op, bool _status) public returns (bool success) {\n        require(msg.sender == owner);\n        operators[_op] = _status;\n        return true;\n    }\n\n    event HeaderSubmittedEvent(address indexed _signer, uint32 indexed _blockNumber, bytes32 indexed _blockHash);\n\n    function submitBlockHeader(bytes header) public returns (bool success) {\n        require(operators[msg.sender]);\n        require(header.length == blockHeaderLength);\n        uint32 blockNumber = uint32(extract4(header, 0));\n        uint32 numTransactions = uint32(extract4(header, BlockNumberLength));\n        bytes32 previousBlockHash = extract32(header, BlockNumberLength + TxNumberLength);\n        bytes32 merkleRootHash = extract32(header, BlockNumberLength + TxNumberLength + PreviousHashLength);\n        uint8 v = uint8(extract1(header, BlockNumberLength + TxNumberLength + PreviousHashLength + MerkleRootHashLength));\n        bytes32 r = extract32(header, BlockNumberLength + TxNumberLength + PreviousHashLength + MerkleRootHashLength + 1);\n        bytes32 s = extract32(header, BlockNumberLength + TxNumberLength + PreviousHashLength + MerkleRootHashLength + 33);\n        uint256 newBlockNumber = uint256(uint32(blockNumber));\n \n        require(newBlockNumber == lastBlockNumber+1);\n        if (lastBlockNumber != 0) {\n            Header storage previousHeader = headers[lastBlockNumber];\n            bytes32 previousHash = keccak256(PersonalMessagePrefixBytes, PreviousBlockPersonalHashLength.uintToBytes(), previousHeader.blockNumber, previousHeader.numTransactions, previousHeader.previousBlockHash, previousHeader.merkleRootHash,\n                                                previousHeader.v, previousHeader.r,previousHeader.s);\n            require(previousHash == previousBlockHash);\n        }\n        bytes32 newBlockHash = keccak256(PersonalMessagePrefixBytes, NewBlockPersonalHashLength.uintToBytes(), blockNumber, numTransactions, previousBlockHash, merkleRootHash);\n        if (v < 27) {\n            v = v+27; \n        }\n        address signer = ecrecover(newBlockHash, v, r, s);\n        require(operators[signer]);\n        Header memory newHeader = Header({\n            blockNumber: blockNumber,\n            numTransactions: numTransactions,\n            previousBlockHash: previousBlockHash,\n            merkleRootHash: merkleRootHash,\n            v: v,\n            r: r,\n            s: s\n        });\n        lastBlockNumber = lastBlockNumber+1;\n        headers[lastBlockNumber] = newHeader;\n        HeaderSubmittedEvent(signer, blockNumber, newBlockHash);\n        return true;\n    }\n    \n\n// ----------------------------------\n// Deposit related functions\n\n    enum DepositStatus {\n        NoRecord,\n        Deposited,\n        WithdrawStarted,\n        WithdrawChallenged,\n        WithdrawCompleted,\n        DepositConfirmed\n    }\n\n    struct DepositRecord {\n        address from; \n        DepositStatus status;\n        uint256 amount; \n        uint256 index;\n        uint256 withdrawStartedTime;\n    } \n\n    event DepositEvent(address indexed _from, uint256 indexed _amount, uint256 indexed _depositIndex);\n    event DepositWithdrawStartedEvent(uint256 indexed _depositIndex);\n    event DepositWithdrawChallengedEvent(uint256 indexed _depositIndex);\n    event DepositWithdrawCompletedEvent(uint256 indexed _depositIndex);\n    \n    mapping (address => uint256[]) userDepositRecords;\n    mapping (uint256 => mapping(uint256 => DepositRecord)) public depositRecords;\n\n    function () payable external {\n        deposit();\n    }\n\n    function depositRecordsForUser(address _user) public view returns (uint256[]) {\n        return userDepositRecords[_user];\n    }\n\n    function deposit() payable public returns (uint256 idx) {\n        if (block.number != lastEthBlockNumber) {\n            depositCounterInBlock = 0;\n        }\n        uint256 depositIndex = block.number << 32 + depositCounterInBlock;\n        DepositRecord storage record = depositRecords[0][depositIndex];\n        require(record.index == 0);\n        require(record.status == DepositStatus.NoRecord);\n        record.index = depositIndex;\n        record.from = msg.sender;\n        record.amount = msg.value;\n        record.status = DepositStatus.Deposited;\n        depositCounterInBlock = depositCounterInBlock + 1;\n        userDepositRecords[msg.sender].push(depositIndex);\n        DepositEvent(msg.sender, msg.value, depositIndex);\n        return depositIndex;\n    }\n\n    // function startDepositWithdraw(uint256 depositIndex) public returns (bool success) {\n    //     DepositRecord storage record = depositRecords[0][depositIndex];\n    //     require(record.index == depositIndex);\n    //     require(record.status == DepositStatus.Deposited);\n    //     require(record.from == msg.sender);\n    //     record.status = DepositStatus.WithdrawStarted;\n    //     record.withdrawStartedTime = now;\n    //     DepositWithdrawStartedEvent(depositIndex);\n    //     return true;\n    // }\n\n    // function finalizeDepositWithdraw(uint256 depositIndex) public returns (bool success) {\n    //     DepositRecord storage record = depositRecords[0][depositIndex];\n    //     require(record.index == depositIndex);\n    //     require(record.status == DepositStatus.WithdrawStarted);\n    //     require(now >= record.withdrawStartedTime + (24 hours));\n    //     record.status = DepositStatus.WithdrawCompleted;\n    //     DepositWithdrawCompletedEvent(depositIndex);\n    //     record.from.transfer(record.amount);\n    //     return true;\n    // }\n\n    // function challengeDepositWithdraw(uint256 depositIndex,\n    //                         uint32 _plasmaBlockNumber, \n    //                         bytes _plasmaTransaction, \n    //                         bytes _merkleProof) public returns (bool success) {\n    //     DepositRecord storage record = depositRecords[0][depositIndex];\n    //     require(record.index == depositIndex);\n    //     require(record.status == DepositStatus.WithdrawStarted);\n    //     record.status = DepositStatus.WithdrawChallenged;\n    //     Header storage header = headers[uint256(_plasmaBlockNumber)];\n    //     require(uint32(header.blockNumber) > 0);\n    //     bool validProof = checkProof(header.merkleRootHash, _plasmaTransaction, _merkleProof, true);\n    //     require(validProof);\n    //     PlasmaTransaction memory TX = plasmaTransactionFromBytes(_plasmaTransaction);\n    //     require(TX.txType == TxTypeFund);\n    //     address signer = recoverTXsigner(_plasmaTransaction, TX.v, TX.r, TX.s, TX.txType);\n    //     require(operators[signer]);\n    //     TransactionOutput memory output0 = TX.outputs[0];\n    //     TransactionOutput memory output1 = TX.outputs[1];\n    //     require(output0.recipient == record.from);\n    //     require(output0.amount == record.amount);\n    //     require(output1.outputNumberInTX == 255);\n    //     require(output1.amount == depositIndex);\n    //     record.status = DepositStatus.DepositConfirmed;\n    //     DepositWithdrawChallengedEvent(depositIndex);\n    //     return true;\n    // }\n    \n// ----------------------------------\n// Withdrawrelated functions\n\n    enum WithdrawStatus {\n        NoRecord,\n        Started,\n        Challenged,\n        Completed,\n        Rejected\n    }\n\n    struct WithdrawRecord {\n        uint256 index;\n        uint32 blockNumber;\n        uint32 txNumberInBlock;\n        uint8 outputNumberInTX;\n        address beneficiary;\n        bool isExpress;\n        WithdrawStatus status;\n        uint256 amount;\n        uint256 timeStarted;\n        uint256 timeEnded;\n    }\n\n    event WithdrawStartedEvent(uint32 indexed _blockNumber,\n                                uint32 indexed _txNumberInBlock,\n                                uint8 indexed _outputNumberInTX);\n    event WithdrawRequestAcceptedEvent(address indexed _from,\n                                uint256 indexed _withdrawIndex);\n    event WithdrawFinalizedEvent(uint32 indexed _blockNumber,\n                                uint32 indexed _txNumberInBlock,\n                                uint8 indexed _outputNumberInTX);  \n    event ExpressWithdrawMadeEvent(uint32 indexed _withdrawTxBlockNumber,\n                                uint32 indexed _withdrawTxNumberInBlock,\n                                address indexed _from);\n\n    mapping (address => uint256[]) userWithdrawRecords;\n    mapping (uint256 => mapping(uint256 => WithdrawRecord)) public withdrawRecords;\n\n\n    function withdrawRecordsForUser(address _user) public view returns (uint256[]) {\n        return userWithdrawRecords[_user];\n    }\n\n    // function startWithdraw(uint32 _plasmaBlockNumber, //references and proves ownership on output of original transaction\n    //                         uint32 _plasmaTxNumInBlock, \n    //                         uint8 _outputNumber,\n    //                         bytes _plasmaTransaction, \n    //                         bytes _merkleProof) \n    // public returns(bool success, uint256 withdrawIndex) {\n    //     Header storage header = headers[uint256(_plasmaBlockNumber)];\n    //     require(uint32(header.blockNumber) > 0);\n    //     bool validProof = checkProof(header.merkleRootHash, _plasmaTransaction, _merkleProof, true);\n    //     require(validProof);\n    //     PlasmaTransaction memory TX = plasmaTransactionFromBytes(_plasmaTransaction);\n    //     require(TX.txType != TxTypeWithdraw);\n    //     address signer = recoverTXsigner(_plasmaTransaction, TX.v, TX.r, TX.s, TX.txType);\n    //     require(signer != address(0));\n    //     TransactionOutput memory output = TX.outputs[_outputNumber];\n    //     require(output.recipient == msg.sender);\n    //     require(output.outputNumberInTX != 255);\n    //     WithdrawRecord storage record = populateWithdrawRecordFromOutput(output, _plasmaBlockNumber, _plasmaTxNumInBlock, _outputNumber);\n    //     record.beneficiary = output.recipient;\n    //     record.timeEnded = now;\n    //     WithdrawRequestAcceptedEvent(output.recipient, record.index);\n    //     WithdrawStartedEvent(_plasmaBlockNumber, _plasmaTxNumInBlock, _outputNumber);\n    //     userWithdrawRecords[msg.sender].push(record.index);\n    //     return (true, withdrawIndex);\n    // } \n\n\n    function makeWithdrawExpress(uint32 _plasmaBlockNumber, //references and proves ownership on withdraw transaction\n                            uint32 _plasmaTxNumInBlock, \n                            bytes _plasmaTransaction, \n                            bytes _merkleProof) \n    public returns(bool success, uint256 withdrawIndex) {\n        Header storage header = headers[uint256(_plasmaBlockNumber)];\n        require(uint32(header.blockNumber) > 0);\n        bool validProof = checkProof(header.merkleRootHash, _plasmaTransaction, _merkleProof, true);\n        require(validProof);\n        PlasmaTransaction memory TX = plasmaTransactionFromBytes(_plasmaTransaction);\n        require(TX.txType == TxTypeWithdraw);\n        require(TX.txNumberInBlock == _plasmaTxNumInBlock);\n        address signer = recoverTXsigner(_plasmaTransaction, TX.v, TX.r, TX.s, TX.txType);\n        require(signer == msg.sender);\n        TransactionInput memory input = TX.inputs[0];\n        WithdrawRecord storage record = populateWithdrawRecordForInput(input);\n        record.beneficiary = signer;\n        require(record.status == WithdrawStatus.Started);\n        record.status = WithdrawStatus.Completed;\n        record.isExpress = true;\n        record.timeEnded = now;\n        WithdrawRequestAcceptedEvent(record.beneficiary, record.index);\n        WithdrawStartedEvent(input.blockNumber, input.txNumberInBlock, input.outputNumberInTX);\n        WithdrawFinalizedEvent(input.blockNumber, input.txNumberInBlock, input.outputNumberInTX);\n        ExpressWithdrawMadeEvent(_plasmaBlockNumber, TX.txNumberInBlock, record.beneficiary);\n        userWithdrawRecords[msg.sender].push(record.index);\n        signer.transfer(record.amount);\n        return (true, withdrawIndex);\n    } \n\n    // function getWithdrawRecordForInput(TransactionInput memory _input) internal view returns (WithdrawRecord storage record) {\n    //     uint256 withdrawIndex = makeTransactionIndex(_input.blockNumber, _input.txNumberInBlock, _input.outputNumberInTX);\n        // withdrawIndex = withdrawIndex + (block.number << 128);\n    //     record = withdrawRecords[0][withdrawIndex];\n    //     require(record.index == withdrawIndex);\n    //     require(record.blockNumber == _input.blockNumber);\n    //     require(record.txNumberInBlock == _input.txNumberInBlock);\n    //     require(record.outputNumberInTX == _input.outputNumberInTX);\n    //     require(record.amount == _input.amount);\n    //     return record;\n    // }\n\n    function populateWithdrawRecordForInput(TransactionInput memory _input) internal returns (WithdrawRecord storage record) {\n        uint256 withdrawIndex = makeTransactionIndex(_input.blockNumber, _input.txNumberInBlock, _input.outputNumberInTX);\n        // withdrawIndex = withdrawIndex + (block.number << 128);\n        record = withdrawRecords[0][withdrawIndex];\n        require(record.status == WithdrawStatus.NoRecord);\n        record.index = withdrawIndex;\n        record.blockNumber = _input.blockNumber;\n        record.txNumberInBlock = _input.txNumberInBlock;\n        record.outputNumberInTX = _input.outputNumberInTX;\n        record.status = WithdrawStatus.Started;\n        record.amount = _input.amount;\n        record.timeStarted = now;\n        return record;\n    }\n\n    function populateWithdrawRecordFromOutput(TransactionOutput memory _output, uint32 _blockNumber, uint32 _txNumberInBlock, uint8 _outputNumberInTX) internal returns (WithdrawRecord storage record) {\n        uint256 withdrawIndex = makeTransactionIndex(_blockNumber, _txNumberInBlock, _outputNumberInTX);\n        // withdrawIndex = withdrawIndex + (block.number << 128);\n        record = withdrawRecords[0][withdrawIndex];\n        require(record.status == WithdrawStatus.NoRecord);\n        record.index = withdrawIndex;\n        record.status = WithdrawStatus.Started;\n        record.amount = _output.amount;\n        record.timeStarted = now;\n        record.blockNumber = _blockNumber;\n        record.txNumberInBlock = _txNumberInBlock;\n        record.outputNumberInTX = _outputNumberInTX;\n        return record;\n    }\n\n    // function finalizeWithdraw(uint256 withdrawIndex) public returns(bool success) {\n    //     WithdrawRecord storage record = withdrawRecords[0][withdrawIndex];\n    //     require(record.status == WithdrawStatus.Started);\n    //     require(now >= record.timeStarted + (24 hours));\n    //     address to = record.beneficiary;\n    //     record.status = WithdrawStatus.Completed;\n    //     record.timeEnded = now;\n    //     WithdrawFinalizedEvent(record.blockNumber, record.txNumberInBlock, record.outputNumberInTX);\n    //     to.transfer(record.amount);\n    //     return true;\n    // } \n\n// ----------------------------------\n// Double-spend related functions\n\n    struct DoubleSpendRecord {\n        bool prooved;\n    }\n\n    struct SpendAndWithdrawRecord {\n        bool prooved;\n    }\n\n    event DoubleSpendProovedEvent(uint256 indexed _txIndex1, uint256 indexed _txIndex2);\n    event SpendAndWithdrawProovedEvent(uint256 indexed _txIndex, uint256 indexed _withdrawIndex);\n\n    mapping (uint256 => mapping(uint256 => DoubleSpendRecord)) public doubleSpendRecords;\n    mapping (uint256 => mapping(uint256 => SpendAndWithdrawRecord)) public spendAndWithdrawRecords;\n\n\n// two transactions spend the same output\n    function proveDoubleSpend(uint32 _plasmaBlockNumber1, //references and proves transaction number 1\n                            uint32 _plasmaTxNumInBlock1, \n                            uint8 _inputNumber1,\n                            bytes _plasmaTransaction1, \n                            bytes _merkleProof1,\n                            uint32 _plasmaBlockNumber2, //references and proves transaction number 2\n                            uint32 _plasmaTxNumInBlock2, \n                            uint8 _inputNumber2,\n                            bytes _plasmaTransaction2, \n                            bytes _merkleProof2) public returns (bool success) {\n        uint256 index1 = makeTransactionIndex(_plasmaBlockNumber1, _plasmaTxNumInBlock1, _inputNumber1);\n        uint256 index2 = makeTransactionIndex(_plasmaBlockNumber2, _plasmaTxNumInBlock2, _inputNumber2);\n        require(index1 != index2);\n        require(!doubleSpendRecords[index1][index2].prooved);\n        require(!doubleSpendRecords[index2][index1].prooved);\n        require(checkActualDoubleSpendProof(_plasmaBlockNumber1,\n                            _plasmaTxNumInBlock1, \n                            _inputNumber1,\n                            _plasmaTransaction1, \n                            _merkleProof1,\n                            _plasmaBlockNumber2, \n                            _plasmaTxNumInBlock2, \n                            _inputNumber2,\n                            _plasmaTransaction2, \n                            _merkleProof2));\n        doubleSpendRecords[index1][index2].prooved = true;\n        doubleSpendRecords[index2][index1].prooved = true;\n        return true;\n    }\n\n    function checkActualDoubleSpendProof (uint32 _plasmaBlockNumber1, //references and proves transaction number 1\n                            uint32 _plasmaTxNumInBlock1, \n                            uint8 _inputNumber1,\n                            bytes _plasmaTransaction1, \n                            bytes _merkleProof1,\n                            uint32 _plasmaBlockNumber2, //references and proves transaction number 2\n                            uint32 _plasmaTxNumInBlock2, \n                            uint8 _inputNumber2,\n                            bytes _plasmaTransaction2, \n                            bytes _merkleProof2) public view returns (bool success) {\n        var (signer1, input1) = getTXinputDetailsFromProof(_plasmaBlockNumber1, _plasmaTxNumInBlock1, _inputNumber1, _plasmaTransaction1, _merkleProof1);\n        var (signer2, input2) = getTXinputDetailsFromProof(_plasmaBlockNumber2, _plasmaTxNumInBlock2, _inputNumber2, _plasmaTransaction2, _merkleProof2);\n        require(signer1 != address(0));\n        require(signer2 != address(0));\n        require(signer1 == signer2);\n        require(input1.blockNumber == input2.blockNumber);\n        require(input1.txNumberInBlock == input2.txNumberInBlock);\n        require(input1.outputNumberInTX == input2.outputNumberInTX);\n        return true;\n    }\n\n// transaction output is withdrawn (witthout express process) and spent in Plasma chain\n    function proveSpendAndWithdraw(uint32 _plasmaBlockNumber, //references and proves transaction\n                            uint32 _plasmaTxNumInBlock, \n                            uint8 _inputNumber,\n                            bytes _plasmaTransaction, \n                            bytes _merkleProof,\n                            uint256 _withdrawIndex //references withdraw\n                            ) public returns (bool success) {\n        uint256 txIndex = makeTransactionIndex(_plasmaBlockNumber, _plasmaTxNumInBlock, _inputNumber);\n        require(!spendAndWithdrawRecords[txIndex][_withdrawIndex].prooved);\n        WithdrawRecord storage record = withdrawRecords[0][_withdrawIndex];\n        var (signer, input) = getTXinputDetailsFromProof(_plasmaBlockNumber, _plasmaTxNumInBlock, _inputNumber, _plasmaTransaction, _merkleProof);\n        require(signer != address(0));\n        require(input.blockNumber == record.blockNumber);\n        require(input.txNumberInBlock == record.txNumberInBlock);\n        require(input.outputNumberInTX == record.outputNumberInTX);\n        if (record.status == WithdrawStatus.Completed) {\n            spendAndWithdrawRecords[txIndex][_withdrawIndex].prooved = true;\n            SpendAndWithdrawProovedEvent(txIndex, _withdrawIndex);\n        } else if (record.status == WithdrawStatus.Started) {\n            record.status = WithdrawStatus.Challenged;\n            spendAndWithdrawRecords[txIndex][_withdrawIndex].prooved = true;\n            SpendAndWithdrawProovedEvent(txIndex, _withdrawIndex);    \n        }\n        return true;\n    }\n \n// ----------------------------------\n// Prove unlawful funding transactions on Plasma\n\n    struct FundingWithoutDepositRecord {\n        bool prooved;\n    }\n\n    struct DoubleFundingRecord {\n        bool prooved;\n    }\n\n    mapping (uint256 => mapping(uint256 => FundingWithoutDepositRecord)) public fundingWithoutDepositRecords;\n    mapping (uint256 => mapping(uint256 => DoubleFundingRecord)) public doubleFundingRecords;\n\n    event FundingWithoutDepositEvent(uint256 indexed _txIndex, uint256 indexed _depositIndex);                 \n    event DoubleFundingEvent(uint256 indexed _txIndex1, uint256 indexed _txIndex2);\n\nfunction proveFundingWithoutDeposit(uint32 _plasmaBlockNumber, //references and proves transaction\n                            uint32 _plasmaTxNumInBlock, \n                            bytes _plasmaTransaction, \n                            bytes _merkleProof) public returns (bool success) {\n        Header storage header = headers[uint256(_plasmaBlockNumber)];\n        require(uint32(header.blockNumber) > 0);\n        bool validProof = checkProof(header.merkleRootHash, _plasmaTransaction, _merkleProof, true);\n        require(validProof);\n        PlasmaTransaction memory TX = plasmaTransactionFromBytes(_plasmaTransaction);\n        require(TX.txType == TxTypeFund);\n        address signer = recoverTXsigner(_plasmaTransaction, TX.v, TX.r, TX.s, TX.txType);\n        require(operators[signer]);\n        TransactionOutput memory output = TX.outputs[0];\n        TransactionOutput memory outputAux = TX.outputs[1];\n        require(outputAux.outputNumberInTX == 255);\n        require(TX.txNumberInBlock == _plasmaTxNumInBlock);\n        uint256 depositIndex = output.amount;\n        uint256 transactionIndex = makeTransactionIndex(_plasmaBlockNumber, TX.txNumberInBlock, 0);\n        require(!fundingWithoutDepositRecords[transactionIndex][depositIndex].prooved);\n        DepositRecord storage record = depositRecords[0][depositIndex];\n        if (record.status == DepositStatus.NoRecord) {\n            FundingWithoutDepositEvent(transactionIndex, depositIndex);\n            fundingWithoutDepositRecords[transactionIndex][depositIndex].prooved = true;\n            return true;\n        } else if (record.amount != output.amount || record.from != output.recipient) {\n            FundingWithoutDepositEvent(transactionIndex, depositIndex);\n            fundingWithoutDepositRecords[transactionIndex][depositIndex].prooved = true;\n            return true;\n        }\n        revert();\n        return false;\n    }\n\n    //prove double funding of the same \n\n    function proveDoubleFunding(uint32 _plasmaBlockNumber1, //references and proves transaction number 1\n                            uint32 _plasmaTxNumInBlock1, \n                            bytes _plasmaTransaction1, \n                            bytes _merkleProof1,\n                            uint32 _plasmaBlockNumber2, //references and proves transaction number 2\n                            uint32 _plasmaTxNumInBlock2, \n                            bytes _plasmaTransaction2, \n                            bytes _merkleProof2) public returns (bool success) {\n        var (signer1, depositIndex1, transactionIndex1) = getFundingTXdetailsFromProof(_plasmaBlockNumber1, _plasmaTxNumInBlock1, _plasmaTransaction1, _merkleProof1);\n        var (signer2, depositIndex2, transactionIndex2) = getFundingTXdetailsFromProof(_plasmaBlockNumber2, _plasmaTxNumInBlock2, _plasmaTransaction2, _merkleProof2);\n        require(checkDoubleFundingFromInternal(signer1, depositIndex1, transactionIndex1, signer2, depositIndex2, transactionIndex2));\n        doubleFundingRecords[transactionIndex1][transactionIndex2].prooved = true;\n        doubleFundingRecords[transactionIndex2][transactionIndex1].prooved = true;\n        return true;\n    }\n\n    function checkDoubleFundingFromInternal (address signer1,\n                                            uint256 depositIndex1,\n                                            uint256 transactionIndex1,\n                                            address signer2,\n                                            uint256 depositIndex2,\n                                            uint256 transactionIndex2) public view returns (bool) {\n        require(operators[signer1]);\n        require(operators[signer2]);\n        require(depositIndex1 == depositIndex2);\n        require(transactionIndex1 != transactionIndex2);\n        require(!doubleFundingRecords[transactionIndex1][transactionIndex2].prooved);\n        require(!doubleFundingRecords[transactionIndex2][transactionIndex1].prooved);\n        return true;\n    }\n\n// ----------------------------------\n// Convenience functions\n\n   function getTXinputDetailsFromProof(uint32 _plasmaBlockNumber, \n                            uint32 _plasmaTxNumInBlock, \n                            uint8 _inputNumber,\n                            bytes _plasmaTransaction, \n                            bytes _merkleProof) internal view returns (address signer, TransactionInput memory input) {\n        Header storage header = headers[uint256(_plasmaBlockNumber)];\n        require(uint32(header.blockNumber) > 0);\n        bool validProof = checkProof(header.merkleRootHash, _plasmaTransaction, _merkleProof, true);\n        require(validProof);\n        PlasmaTransaction memory TX = plasmaTransactionFromBytes(_plasmaTransaction);\n        require(TX.txType != TxTypeFund);\n        signer = recoverTXsigner(_plasmaTransaction, TX.v, TX.r, TX.s, TX.txType);\n        require(signer != address(0));\n        input = TX.inputs[uint256(_inputNumber)];\n    }\n\n    function getFundingTXdetailsFromProof(uint32 _plasmaBlockNumber, \n                            uint32 _plasmaTxNumInBlock, \n                            bytes _plasmaTransaction, \n                            bytes _merkleProof) internal view returns (address signer, uint256 depositIndex, uint256 transactionIndex) {\n        Header storage header = headers[uint256(_plasmaBlockNumber)];\n        require(uint32(header.blockNumber) > 0);\n        bool validProof = checkProof(header.merkleRootHash, _plasmaTransaction, _merkleProof, true);\n        require(validProof);\n        PlasmaTransaction memory TX = plasmaTransactionFromBytes(_plasmaTransaction);\n        require(TX.txType == TxTypeFund);\n        signer = recoverTXsigner(_plasmaTransaction, TX.v, TX.r, TX.s, TX.txType);\n        TransactionOutput memory outputAux = TX.outputs[1];\n        require(outputAux.outputNumberInTX == 255);\n        require(TX.txNumberInBlock == _plasmaTxNumInBlock);\n        depositIndex = outputAux.amount;\n        transactionIndex = makeTransactionIndex(_plasmaBlockNumber, TX.txNumberInBlock, 0);\n        return (signer, depositIndex, transactionIndex);\n    }\n\n    function plasmaTransactionFromBytes(bytes _rawTX) internal view returns (PlasmaTransaction memory TX) {\n        uint8 txType = uint8(extract1(_rawTX, TxNumberLength));\n        uint256 expectedLength = TxLengthForType[txType];\n        require(_rawTX.length == expectedLength);\n        uint256 numInputs = NumInputsForType[txType];\n        uint256 numOutputs = NumOutputsForType[txType];\n        uint32 numInBlock = uint32(extract4(_rawTX,0));\n        uint256 signatureOffset = TxNumberLength + TxTypeLength + numInputs*TransactionInputLength + numOutputs*TransactionOutputLength;\n        uint8 v = uint8(extract1(_rawTX, signatureOffset));\n        bytes32 r = extract32(_rawTX, signatureOffset + 1);\n        bytes32 s = extract32(_rawTX, signatureOffset + 33);\n        TX = PlasmaTransaction({\n            txNumberInBlock: numInBlock,\n            txType: txType,\n            inputs: new TransactionInput[](numInputs),\n            outputs: new TransactionOutput[](numOutputs),\n            v : v,\n            r: r,\n            s: s\n        });\n        bytes memory insAndOutsSlice = _rawTX.slice(TxNumberLength + TxTypeLength, signatureOffset).toBytes();\n        assert(populateInsAndOuts(TX, numInputs, numOutputs, insAndOutsSlice));\n        return TX;\n    }\n\n    function populateInsAndOuts(PlasmaTransaction memory _TX, uint256 _numIns, uint256 _numOuts, bytes memory _insAndOutsSlice) \n        internal view returns (bool success) {\n            uint256 i;\n            for (i = 0; i < _numIns; i++) {\n                bytes memory rawInput = _insAndOutsSlice.slice(i*TransactionInputLength, (i+1)*TransactionInputLength).toBytes();\n                TransactionInput memory input = transactionInputFromBytes(rawInput);\n                _TX.inputs[i] = input;\n            }\n            for (i = 0; i < _numOuts; i++) {\n                bytes memory rawOutput = _insAndOutsSlice.slice(_numIns*TransactionInputLength + i*TransactionOutputLength, \n                                                _numIns*TransactionInputLength + (i+1)*TransactionOutputLength).toBytes();\n                TransactionOutput memory output = transactionOutputFromBytes(rawOutput);\n                if (output.outputNumberInTX == 255) {\n                    continue;\n                }\n                require(output.outputNumberInTX == i);\n                _TX.outputs[i] = output;\n            }\n            return true;\n    }\n\n    function transactionInputFromBytes(bytes _rawInput) internal view returns(TransactionInput memory input) {\n        require(_rawInput.length == TransactionInputLength);\n        uint32 blockNumber = uint32(extract4(_rawInput,0));\n        uint32 txNumberInBlock = uint32(extract4(_rawInput, BlockNumberLength));\n        uint8 outputNumberInTX = uint8(extract1(_rawInput, BlockNumberLength + TxNumberLength));\n        uint256 amount = uint256(extract32(_rawInput, BlockNumberLength + TxNumberLength + TxOutputNumberLength));\n        input = TransactionInput({\n            blockNumber: blockNumber,\n            txNumberInBlock: txNumberInBlock,\n            outputNumberInTX: outputNumberInTX,\n            amount: amount\n        });\n        return input;\n    }\n\n    function transactionOutputFromBytes(bytes _rawOutput) internal view returns(TransactionOutput memory output) {\n        require(_rawOutput.length == TransactionOutputLength);\n        address recipient = address(extract20(_rawOutput, 0));\n        uint8 outputNumberInTX = uint8(extract1(_rawOutput, 20));\n        uint256 amount = uint256(extract32(_rawOutput, 20 + TxOutputNumberLength));\n        output = TransactionOutput({\n            recipient: recipient,\n            outputNumberInTX: outputNumberInTX,\n            amount: amount\n        });\n        return output;\n    }\n\n    function createPersonalMessageTypeHash(bytes memory message) internal view returns (bytes32 msgHash) {\n        // bytes memory prefixBytes = \"\\x19Ethereum Signed Message:\\n\";\n        bytes memory lengthBytes = message.length.uintToBytes();\n        // bytes memory prefix = prefixBytes.concat(lengthBytes);\n        bytes memory prefix = PersonalMessagePrefixBytes.concat(lengthBytes);\n        return keccak256(prefix, message);\n    }\n    \n    function recoverTXsigner(bytes memory txData, uint8 v, bytes32 r, bytes32 s, uint256 txType) internal view returns (address signer) {\n        bytes memory sliceNoNumberNoSignatureParts = txData.slice(TxNumberLength, TxLengthForType[txType] - SignatureLength).toBytes();\n        bytes32 persMessageHashWithoutNumber = createPersonalMessageTypeHash(sliceNoNumberNoSignatureParts);\n        signer = ecrecover(persMessageHashWithoutNumber, v, r, s);\n        return signer;\n    }\n\n    function checkProof(bytes32 root, bytes data, bytes proof, bool convertToMessageHash) view public returns (bool) {\n        bytes32 h;\n        if (convertToMessageHash) {\n            h = createPersonalMessageTypeHash(data);\n        } else {\n            h = keccak256(data);\n        }\n        bytes32 elProvided;\n        uint8 rightElementProvided;\n        uint32 loc;\n        uint32 elLoc;\n        for (uint32 i = 32; i <= uint32(proof.length); i += 33) {\n            assembly {\n                loc  := proof \n                elLoc := add(loc, add(i, 1))\n                elProvided := mload(elLoc)\n            }\n            rightElementProvided = uint8(bytes1(0xff)&proof[i-32]);\n            if (rightElementProvided > 0) {\n                h = keccak256(h, elProvided);\n            } else {\n                h = keccak256(elProvided, h);\n            }\n        }\n        return h == root;\n      }\n    \n    function makeTransactionIndex(uint32 _blockNumber, uint32 _txNumberInBlock, uint8 _outputNumberInTX) pure public returns (uint256 index) { \n        index = uint256(_blockNumber) << ((TxNumberLength + TxTypeLength)*8) + uint256(_txNumberInBlock) << (TxTypeLength*8) + uint256(_outputNumberInTX);\n        return index;\n    }\n}\n"
  },
  {
    "path": "lib/Block/block.js",
    "content": "const {blockNumberLength,\n    txNumberLength,\n    txTypeLength, \n    signatureVlength,\n    signatureRlength,\n    signatureSlength,\n    merkleRootLength,\n    previousHashLength} = require('../dataStructureLengths');\n\nconst ethUtil = require('ethereumjs-util');\nconst BN = ethUtil.BN\nconst {PlasmaTransaction,\n    TxTypeFund, \n    TxTypeMerge, \n    TxTypeSplit, \n    TxTypeWithdraw, \n    TxTypeTransfer,\n    TxLengthForType} = require('../Tx/tx');\nconst MerkleTools = require('../merkle-tools');\nconst {BlockHeader, BlockHeaderLength, BlockHeaderNumItems} = require('./blockHeader'); \nconst assert = require('assert');\nconst stripHexPrefix = require('strip-hex-prefix');\n\n// secp256k1n/2\nconst N_DIV_2 = new BN('7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a0', 16);\n\nclass Block {\n  constructor (data) {\n    if (data instanceof Object && data.constructor === Object ){ \n        this.blockNumber = data.blockNumber || Buffer.alloc(blockNumberLength);\n        this.parentHash = data.parentHash || Buffer.alloc(previousHashLength);\n        this.transactions = data.transactions || [];\n        this.numberOfTransactions = data.transactions.length || 0;\n        const numberOfTransactionsBuffer = ethUtil.setLengthLeft(ethUtil.toBuffer(this.numberOfTransactions), txNumberLength);\n\n        assert(this.transactions && Array.isArray(this.transactions), \"TXs should be an array\");\n        const treeOptions = {\n            hashType: 'sha3'\n        }\n        \n        this.merkleTree = new MerkleTools(treeOptions)\n        for (let i = 0; i < this.transactions.length; i++) {\n            const tx = this.transactions[i];\n            const txHash = tx.hash(true, true);\n            // console.log(\"Added tx hash \" + ethUtil.bufferToHex(txHash));\n            // console.log(\"TX with content \" + ethUtil.bufferToHex(Buffer.concat(tx.clearRaw(true, true))));\n            this.merkleTree.addLeaf(txHash);\n        }  \n        assert (this.merkleTree.getLeafCount() == this.numberOfTransactions);\n        this.merkleTree.makeTree(false);\n        const rootValue = this.merkleTree.getMerkleRoot();\n        // console.log(\"Merkle root of block is \" + ethUtil.bufferToHex(rootValue));\n        const headerParams = {\n            blockNumber: this.blockNumber,\n            parentHash: this.parentHash,\n            merkleRootHash: rootValue,\n            numberOfTransactions: numberOfTransactionsBuffer\n        }\n        this.header = new BlockHeader(headerParams);\n    } else if (Buffer.isBuffer(data)) {\n        this.transactions = [];\n        const head = data.slice(0, BlockHeaderLength);\n        let i = 0;\n        const headerArray = [];\n        for (let sliceLen of [blockNumberLength, txNumberLength, previousHashLength, merkleRootLength, signatureVlength, signatureRlength, signatureSlength]) {\n            headerArray.push(head.slice(i, i + sliceLen));\n            i += sliceLen;\n        }\n        this.header = new BlockHeader(headerArray);\n        let transactionsBuffer = data.slice(BlockHeaderLength, data.length);\n        while (transactionsBuffer.length > 0) {\n            const txType = ethUtil.bufferToInt(transactionsBuffer.slice(txNumberLength,txNumberLength + txTypeLength))\n            const txBin = transactionsBuffer.slice(0, TxLengthForType[txType]);\n            const TX = PlasmaTransaction.prototype.initTxForTypeFromBinary(txType, txBin);\n            this.transactions.push(TX);\n            transactionsBuffer = transactionsBuffer.slice(TxLengthForType[txType], transactionsBuffer.length);\n        }\n        assert(this.transactions.length == ethUtil.bufferToInt(head.slice(blockNumberLength,blockNumberLength+txNumberLength)));\n        const treeOptions = {\n            hashType: 'sha3'\n          }\n        this.merkleTree = new MerkleTools(treeOptions)\n        for (let j = 0; j < this.transactions.length; j++) {\n            const tx = this.transactions[j];\n            const txHash = tx.hash(true, true);\n            // console.log(\"Added tx hash \" + ethUtil.bufferToHex(txHash));\n            // console.log(\"TX with content \" + ethUtil.bufferToHex(Buffer.concat(tx.clearRaw(true, true))));\n            this.merkleTree.addLeaf(txHash);\n        }  \n        assert(this.merkleTree.getLeafCount() == ethUtil.bufferToInt(head.slice(blockNumberLength,blockNumberLength+txNumberLength)));\n        this.merkleTree.makeTree(false);\n        const rootValue = this.merkleTree.getMerkleRoot();\n        assert(rootValue.equals(this.header.merkleRootHash))\n        assert(this.header.validate());\n    }\n    Object.defineProperty(this, 'from', {\n      enumerable: true,\n      configurable: true,\n      get: this.getSenderAddress.bind(this)\n    })\n\n    Object.defineProperty(this, 'raw', {\n        get: function () {\n        return this.serialize(false)\n        }\n    })\n    \n}\n\nserializeSignature(signatureString) {\n    this.header.serializeSignature(signatureString);\n    const signature = stripHexPrefix(signatureString);\n  }\n   \nserialize(includeSignature) {\n    var txRaws = [];\n    this.transactions.forEach((tx) => {\n        const r = tx.clearRaw(true, true);\n        // const r = tx.raw.filter((f) => {\n        //     return (typeof f !== 'undefined')\n        // })\n        txRaws.push(Buffer.concat(r))\n    })\n    return this.header.raw.concat(txRaws);\n}  \n\nclearRaw(includeSignature) {\n    return this.header.clearRaw(includeSignature);\n  }\n\n  /**\n   * Computes a sha3-256 hash of the serialized tx\n   * @param {Boolean} [includeSignature=true] whether or not to inculde the signature\n   * @return {Buffer}\n   */\n  hash (includeSignature) {\n      return this.header.hash(includeSignature)\n  }\n\n  /**\n   * returns the sender's address\n   * @return {Buffer}\n   */\n  getSenderAddress () {\n      return this.header.getSenderAddress()\n  }\n\n  /**\n   * returns the public key of the sender\n   * @return {Buffer}\n   */\n  getSenderPublicKey () {\n      return this.header._senderPubKey\n  }\n\n  getMerkleHash () {\n    return this.header.merkleRootHash;\n  }\n\n  /**\n   * Determines if the signature is valid\n   * @return {Boolean}\n   */\n  verifySignature () {\n      return this.header.verifySignature()\n  }\n\n  /**\n   * sign a transaction with a given a private key\n   * @param {Buffer} privateKey\n   */\n  sign (privateKey) {\n      this.header.sign(privateKey)\n  }\n\n\n  /**\n   * validates the signature and checks to see if it has enough gas\n   * @param {Boolean} [stringError=false] whether to return a string with a dscription of why the validation failed or return a Bloolean\n   * @return {Boolean|String}\n   */\n  validate (stringError) {\n    const errors = []\n    if (!this.verifySignature()) {\n      errors.push('Invalid Signature')\n    }\n    if (stringError === undefined || stringError === false) {\n      return errors.length === 0\n    } else {\n      return errors.join(' ')\n    }\n  }\n\n}\n\nBlock.prototype.toJSON = function (labeled) {\n    if (labeled) {\n      var obj = {\n        header: this.header.toJSON(labeled),\n        transactions: []\n      }\n  \n      this.transactions.forEach(function (tx) {\n        const txJSON = tx.toJSON(labeled)\n        obj.transactions.push(txJSON);\n      })\n  \n      return obj\n    } else {\n      return ethUtil.baToJSON(this.raw)\n    }\n  }\n\nBlock.prototype.toFullJSON = function (labeled) {\n    if (labeled) {\n      var obj = {\n        header: this.header.toFullJSON(labeled),\n        transactions: []\n      }\n  \n      this.transactions.forEach(function (tx) {\n        const txJSON = tx.toFullJSON(labeled)\n        obj.transactions.push(txJSON);\n      })\n  \n      return obj\n    } else {\n      return ethUtil.baToJSON(this.raw)\n    }\n  }\n\nmodule.exports = Block"
  },
  {
    "path": "lib/Block/blockHeader.js",
    "content": "const {blockNumberLength,\n  txNumberLength,\n  txTypeLength, \n  signatureVlength,\n  signatureRlength,\n  signatureSlength,\n  merkleRootLength,\n  previousHashLength} = require('../dataStructureLengths');\n\nconst stripHexPrefix = require('strip-hex-prefix');\nconst ethUtil = require('ethereumjs-util')\nconst BN = ethUtil.BN\nconst defineProperties = require('../serialize').defineProperties;\n// secp256k1n/2\nconst N_DIV_2 = new BN('7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a0', 16)\n\nclass BlockHeader {\n  constructor (data) {\n    data = data || {}\n    // Define Properties\n    const fields = [{\n      name: 'blockNumber',\n      alias: 'block',\n      length: blockNumberLength,\n      allowLess: false,\n      default: Buffer.alloc(blockNumberLength)\n    }, {\n      name: 'numberOfTransactions',\n      alias: 'numTX',\n      length: txNumberLength,\n      allowLess: false,\n      default: Buffer.alloc(txNumberLength)\n    }, {\n      name: 'parentHash',\n      allowZero: true,\n      length: previousHashLength,\n      allowLess: false,\n      default: Buffer.alloc(previousHashLength)\n    }, {\n      name: 'merkleRootHash',\n      allowZero: true,\n      alias: 'merkle',\n      length: merkleRootLength,\n      allowLess: false,\n      default: Buffer.alloc(merkleRootLength)\n    }, {\n      name: 'v',\n      allowZero: true,\n      length: signatureVlength,\n      allowLess: false,\n      default: Buffer.alloc(signatureVlength)\n    }, {\n      name: 'r',\n      length: signatureRlength,\n      allowZero: true,\n      allowLess: false,\n      default: Buffer.alloc(signatureRlength)\n    }, {\n      name: 's',\n      length: signatureSlength,\n      allowZero: true,\n      allowLess: false,\n      default: Buffer.alloc(signatureSlength)\n    }]\n\n defineProperties(this, fields, data)\n\n    /**\n     * @property {Buffer} from (read only) sender address of this transaction, mathematically derived from other parameters.\n     * @name from\n     * @memberof Transaction\n     */\n    Object.defineProperty(this, 'from', {\n      enumerable: true,\n      configurable: true,\n      get: this.getSenderAddress.bind(this)\n    })\n\n    Object.defineProperty(this, 'length', {\n      enumerable: true,\n      configurable: true,\n      get: (() => Buffer.concat(this.raw).length) \n    })\n  }\n  /**\n   * Computes a sha3-256 hash of the serialized tx\n   * @param {Boolean} [includeSignature=true] whether or not to inculde the signature\n   * @return {Buffer}\n   */\n  hash (includeSignature) {\n    if (includeSignature === undefined) includeSignature = true\n\n    // EIP155 spec:\n    // when computing the hash of a transaction for purposes of signing or recovering,\n    // instead of hashing only the first six elements (ie. nonce, gasprice, startgas, to, value, data),\n    // hash nine elements, with v replaced by CHAIN_ID, r = 0 and s = 0\n\n    let items = this.clearRaw(includeSignature);\n    // return ethUtil.sha3(Buffer.concat(items));\n    return ethUtil.hashPersonalMessage(Buffer.concat(items));\n\n  }\n\n  serializeSignature(signatureString) {\n    const signature = stripHexPrefix(signatureString);\n    let r = ethUtil.addHexPrefix(signature.substring(0,64));\n    let s = ethUtil.addHexPrefix(signature.substring(64,128));\n    let v = ethUtil.addHexPrefix(signature.substring(128,130));\n    r = ethUtil.toBuffer(r);\n    s = ethUtil.toBuffer(s);\n    v = ethUtil.bufferToInt(ethUtil.toBuffer(v));\n    if (v < 27) {\n        v = v + 27;\n    }\n    v = ethUtil.toBuffer(v);\n    this.r = r;\n    this.v = v;\n    this.s = s;\n  }\n\n  /**\n   * returns the sender's address\n   * @return {Buffer}\n   */\n  getSenderAddress () {\n    if (this._from) {\n      return this._from\n    }\n    const pubkey = this.getSenderPublicKey()\n    this._from = ethUtil.publicToAddress(pubkey)\n    return this._from\n  }\n\n  /**\n   * returns the public key of the sender\n   * @return {Buffer}\n   */\n  getSenderPublicKey () {\n    if (!this._senderPubKey || !this._senderPubKey.length) {\n      if (!this.verifySignature()) throw new Error('Invalid Signature')\n    }\n    return this._senderPubKey\n  }\n\n  /**\n   * Determines if the signature is vali\n   * d\n   * @return {Boolean}\n   */\n  verifySignature () {\n    const msgHash = this.hash(false)\n    // All transaction signatures whose s-value is greater than secp256k1n/2 are considered invalid.\n    if (new BN(this.s).cmp(N_DIV_2) === 1) {\n      return false\n    }\n    try {\n      let v = ethUtil.bufferToInt(this.v)\n    //   if (this._chainId > 0) {\n    //     v -= this._chainId * 2 + 8\n    //   }\n      this._senderPubKey = ethUtil.ecrecover(msgHash, v, this.r, this.s)\n    } catch (e) {\n      return false\n    }\n\n    return !!this._senderPubKey\n  }\n\n  /**\n   * sign a transaction with a given a private key\n   * @param {Buffer} privateKey\n   */\n  sign (privateKey) {\n    const msgHash = this.hash(false)\n    const sig = ethUtil.ecsign(msgHash, privateKey)\n    if (sig.v < 27){\n        sig.v += 27\n    }\n \n    Object.assign(this, sig)\n  }\n\n\n  clearRaw(includeSignature) {\n    let items\n    if (includeSignature) {\n      items = this.raw\n    } else {\n        items = this.raw.slice(0, this.raw.length-3)\n    }\n    return items;\n    // return Buffer.concat(items);\n  }\n\n  /**\n   * validates the signature and checks to see if it has enough gas\n   * @param {Boolean} [stringError=false] whether to return a string with a dscription of why the validation failed or return a Bloolean\n   * @return {Boolean|String}\n   */\n  validate (stringError) {\n    const errors = []\n    if (!this.verifySignature()) {\n      errors.push('Invalid Signature')\n    }\n    if (stringError === undefined || stringError === false) {\n      return errors.length === 0\n    } else {\n      return errors.join(' ')\n    }\n  }\n\n  toFullJSON(labeled) {\n    if (labeled) {\n      const header = this.toJSON(labeled);\n      const blockNumber = ethUtil.bufferToInt(this.blockNumber)\n      const numberOfTransactions = ethUtil.bufferToInt(this.numberOfTransactions)\n      header.blockNumber = blockNumber\n      header.numberOfTransactions = numberOfTransactions\n      return header\n    } else {\n      return ethUtil.baToJSON(this.raw)\n    }\n  }\n}\n\nconst dummy = new BlockHeader();\nconst BlockHeaderLength = dummy.length;\nconst BlockHeaderNumItems = dummy.raw.length;\n\nmodule.exports = {BlockHeader, BlockHeaderLength, BlockHeaderNumItems}\n\n"
  },
  {
    "path": "lib/Tx/input.js",
    "content": "const {blockNumberLength,\ntxNumberLength,\ntxTypeLength, \nsignatureVlength,\nsignatureRlength,\nsignatureSlength,\nmerkleRootLength,\npreviousHashLength,\ntxOutputNumberLength,\ntxAmountLength} = require('../dataStructureLengths');\n\nconst ethUtil = require('ethereumjs-util')\nconst BN = ethUtil.BN\nconst defineProperties = require('../serialize').defineProperties;\n// secp256k1n/2\nconst N_DIV_2 = new BN('7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a0', 16)\n\nclass TransactionInput {\n  constructor (data) {\n    data = data || {}\n    // Define Properties\n    const fields = [{\n      name: 'blockNumber',\n      alias: 'block',\n      allowZero: true,\n      length: blockNumberLength,\n      allowLess: false,\n      default: Buffer.alloc(blockNumberLength)\n    }, {\n      name: 'txNumberInBlock',\n      allowZero: true,\n      alias: 'txNum',\n      length: txNumberLength,\n      allowLess: false,\n      default: Buffer.alloc(txNumberLength)\n    }, {\n      name: 'outputNumberInTransaction',\n      allowZero: true,\n      alias: 'outputNum',\n      length: txOutputNumberLength,\n      allowLess: false,\n      default: Buffer.alloc(txOutputNumberLength)\n    }, \n    // {\n    //   name: 'assetID',\n    //   allowZero: true,\n    //   alias: 'asset',\n    //   length: 4,\n    //   allowLess: false,\n    //   default: Buffer.alloc(4)\n    // }, \n    {\n      name: 'amountBuffer',\n      allowZero: true,\n      alias: 'valueBuffer',\n      length: txAmountLength,\n      allowLess: false,\n      default: Buffer.alloc(txAmountLength)\n    }]\n\n     defineProperties(this, fields, data)\n\n    /**\n     * @property {BigNumber} from (read only) amount of this transaction, mathematically derived from other parameters.\n     * @name from\n     * @memberof Transaction\n     */\n    Object.defineProperty(this, 'value', {\n        enumerable: true,\n        configurable: true,\n        get: (() => new BN(this.valueBuffer)) \n    })\n\n    Object.defineProperty(this, 'length', {\n        enumerable: true,\n        configurable: true,\n        get: (() => Buffer.concat(this.raw).length) \n    })\n  }\n  getKey() {\n    if(this._key) {\n      return this._key;\n    }\n    this._key = Buffer.concat(this.raw.slice(0,3)).toString('hex')\n    return this._key;\n  }\n\n  toFullJSON(labeled) {\n    if (labeled) {\n      const blockNumber = ethUtil.bufferToInt(this.blockNumber)\n      const txNumberInBlock = ethUtil.bufferToInt(this.txNumberInBlock)\n      const outputNumberInTransaction = ethUtil.bufferToInt(this.outputNumberInTransaction)\n      const value = this.value.toString(10);\n      const obj = {\n        blockNumber,\n        txNumberInBlock,\n        outputNumberInTransaction : outputNumberInTransaction,\n        value\n      }\n      return obj;\n    } else {\n      return ethUtil.baToJSON(this.raw)\n    }\n  }\n}\n\n\n\nconst dummy = new TransactionInput();\nconst TransactionInputLength = dummy.length;\n\nTransactionInput.prototype.initFromBinaryBlob = function(blob) {\n  if (!blob || blob.length != TransactionInputLength) {\n    return null;\n  }\n  const split = [];\n  let i=0;\n  for (let sliceLen of [blockNumberLength, txNumberLength, txOutputNumberLength, txAmountLength]) {\n    split.push(blob.slice(i, i + sliceLen));\n    i += sliceLen;\n  }\n  const input = new TransactionInput(split);\n  return input;\n}\n\n\n\nmodule.exports = {TransactionInput, TransactionInputLength}"
  },
  {
    "path": "lib/Tx/output.js",
    "content": "const {blockNumberLength,\n    txNumberLength,\n    txTypeLength, \n    signatureVlength,\n    signatureRlength,\n    signatureSlength,\n    merkleRootLength,\n    previousHashLength,\n    txOutputNumberLength,\n    txAmountLength,\n    txToAddressLength} = require('../dataStructureLengths');\n\nconst ethUtil = require('ethereumjs-util')\nconst BN = ethUtil.BN\nconst defineProperties = require('../serialize').defineProperties;\n// secp256k1n/2\nconst N_DIV_2 = new BN('7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a0', 16)\n\nclass TransactionOutput {\n  constructor (data) {\n    data = data || {}\n    // Define Properties\n    const fields = [{\n        name: 'to',\n        allowZero: true,\n        alias: 'recipient',\n        length: txToAddressLength,\n        allowLess: false,\n        default: Buffer.alloc(txToAddressLength)\n        }, \n        // {\n        // name: 'assetID',\n        // allowZero: true,\n        // alias: 'asset',\n        // length: 4,\n        // allowLess: false,\n        // default: Buffer.alloc(4)\n        // }, \n        {\n        name: 'outputNumberInTransaction',\n        allowZero: true,\n        alias: 'outputNum',\n        length: txOutputNumberLength,\n        allowLess: false,\n        default: Buffer.alloc(txOutputNumberLength)\n        },\n        {\n        name: 'amountBuffer',\n        allowZero: true,\n        alias: 'valueBuffer',\n        length: txAmountLength,\n        allowLess: false,\n        default: Buffer.alloc(txAmountLength)\n        }]\n\n        defineProperties(this, fields, data)\n\n    /**\n     * @property {BigNumber} from (read only) amount of this transaction, mathematically derived from other parameters.\n     * @name from\n     * @memberof Transaction\n     */\n    Object.defineProperty(this, 'value', {\n        enumerable: true,\n        configurable: true,\n        get: (() => new BN(this.valueBuffer)) \n    })\n\n    Object.defineProperty(this, 'length', {\n        enumerable: true,\n        configurable: true,\n        get: (() =>  Buffer.concat(this.raw).length) \n    })\n    }\n    getKey() {\n        if(this._key) {\n            return this._key;\n        }\n        this._key = Buffer.concat(this.raw.slice(0,2)).toString('hex')\n        return this._key;\n    }\n\n    toFullJSON(labeled) {\n        if (labeled) {\n            let to = ethUtil.bufferToHex(this.to)\n            to = ethUtil.toChecksumAddress(to)\n            const outputNumberInTransaction = ethUtil.bufferToInt(this.outputNumberInTransaction)\n            const value = this.value.toString(10);\n            const obj = {\n              to,\n              outputNumberInTransaction,\n              value\n            }\n            return obj;\n        } else {\n          return ethUtil.baToJSON(this.raw)\n        }\n      }\n}\n\n\n\nconst dummy = new TransactionOutput();\nconst TransactionOutputLength = dummy.length;\n\nTransactionOutput.prototype.initFromBinaryBlob = function(blob) {\n    if (!blob || blob.length != TransactionOutputLength) {\n        return null;\n    }\n    const split = [];\n    let i=0;\n    for (let sliceLen of [txToAddressLength, txOutputNumberLength, txAmountLength]) {\n        split.push(blob.slice(i, i+ sliceLen));\n        i += sliceLen;\n    }\n    const output = new TransactionOutput(split);\n    return output\n}\n\n\n\nmodule.exports = function(){\n    return {TransactionOutput, TransactionOutputLength}}()"
  },
  {
    "path": "lib/Tx/tx.js",
    "content": "const {blockNumberLength,\n  txNumberLength,\n  txTypeLength, \n  signatureVlength,\n  signatureRlength,\n  signatureSlength,\n  merkleRootLength,\n  previousHashLength,\n  txOutputNumberLength,\n  txAmountLength,\n  txToAddressLength} = require('../dataStructureLengths');\n\nconst ethUtil = require('ethereumjs-util')\nconst BN = ethUtil.BN\nconst defineProperties = require('../serialize').defineProperties;\nconst stripHexPrefix = require('strip-hex-prefix');\n\nconst TxTypeSplit = 1;\nconst TxTypeMerge = 2;\nconst TxTypeWithdraw = 3;\nconst TxTypeFund = 4;\nconst TxTypeTransfer = 5;\n\n// secp256k1n/2\nconst N_DIV_2 = new BN('7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a0', 16)\n\nconst {TransactionInput, TransactionInputLength} = require(\"./input\");\nconst {TransactionOutput, TransactionOutputLength} = require(\"./output\");\n\nconst config = require(\"../../app/config/config\");\nconst plasmaOperatorAddress = config.plasmaOperatorAddress;\n\nclass PlasmaTransaction {\n  constructor (data) {\n    data = data || {}\n    // Define Properties\n    const fields = [\n    {\n      name: 'transactionNumberInBlock',\n      length: txNumberLength,\n      alias : \"txNumberInBlock\",\n      allowLess: false,\n      allowZero: true,\n      default: Buffer.alloc(txNumberLength)\n    }, {\n      name: 'transactionType',\n      alias: 'txType',\n      length: txTypeLength,\n      allowLess: false,\n      allowZero: true,\n      default: Buffer.alloc(txTypeLength)\n    }, {\n      name: 'inputNum0',\n      alias: 'input0',\n      length: TransactionInputLength,\n      allowLess: false\n    }, {\n      name: 'inputNum1',\n      alias: 'input1',\n      length: TransactionInputLength,\n      allowLess: false\n    }, {\n      name: 'outputNum0',\n      alias: 'output0',\n      length: TransactionOutputLength,\n      allowLess: false\n    }, {\n      name: 'outputNum1',\n      alias: 'output1',\n      length: TransactionOutputLength,\n      allowLess: false\n    }, {\n      name: 'v',\n      allowZero: true,\n      length: signatureVlength,\n      allowLess: false,\n      default: Buffer.alloc(signatureVlength)\n    }, {\n      name: 'r',\n      length: signatureRlength,\n      allowZero: true,\n      allowLess: false,\n      default: Buffer.alloc(signatureRlength)\n    }, {\n      name: 's',\n      length: signatureSlength,\n      allowZero: true,\n      allowLess: false,\n      default: Buffer.alloc(signatureSlength)\n    }]\n\n    defineProperties(this, fields, data)\n    this._inputs = {};\n    this._outputs = {};\n    /**\n     * @property {Buffer} from (read only) sender address of this transaction, mathematically derived from other parameters.\n     * @name from\n     * @memberof Transaction\n     */\n    Object.defineProperty(this, 'from', {\n      enumerable: true,\n      configurable: true,\n      get: this.getSenderAddress.bind(this)\n    })\n  }\n\n  /**\n   * If the tx's `to` is to the creation address\n   * @return {Boolean}\n   */\n  toWithdrawAddress () {\n    return this.output1.toString('hex') === ''\n  }\n\n    /**\n   * If the tx's `from` is from the creation address\n   * @return {Boolean}\n   */\n  fromFundingAddress () {\n    return this.input1.toString('hex') === ''\n  }\n\n  /**\n   * Computes a sha3-256 hash of the serialized tx\n   * @param {Boolean} [includeSignature=true] whether or not to inculde the signature\n   * @return {Buffer}\n   */\n  hash (includeSignature, includeNumber) {\n    if (includeSignature === undefined) includeSignature = true\n    if (includeNumber === undefined) includeNumber = false\n    // EIP155 spec:\n    // when computing the hash of a transaction for purposes of signing or recovering,\n    // instead of hashing only the first six elements (ie. nonce, gasprice, startgas, to, value, data),\n    // hash nine elements, with v replaced by CHAIN_ID, r = 0 and s = 0\n    let items = this.clearRaw(includeNumber, includeSignature);\n    return ethUtil.hashPersonalMessage(Buffer.concat(items));\n\n  }\n\n  serializeSignature(signatureString) {\n    const signature = stripHexPrefix(signatureString);\n    let r = ethUtil.addHexPrefix(signature.substring(0,64));\n    let s = ethUtil.addHexPrefix(signature.substring(64,128));\n    let v = ethUtil.addHexPrefix(signature.substring(128,130));\n    r = ethUtil.toBuffer(r);\n    s = ethUtil.toBuffer(s);\n    v = ethUtil.bufferToInt(ethUtil.toBuffer(v));\n    if (v < 27) {\n        v = v + 27;\n    }\n    v = ethUtil.toBuffer(v);\n    this.r = r;\n    this.v = v;\n    this.s = s;\n  }\n\n  getTransactionInput(inputNumber) {\n      if (this._inputs[inputNumber]) {\n        return this._inputs[inputNumber]\n      }\n      this._inputs[inputNumber] = TransactionInput.prototype.initFromBinaryBlob(this[\"inputNum\"+inputNumber]);\n      return this._inputs[inputNumber]\n  }\n\n  getTransactionOutput(outputNumber) {\n      if (this._outputs[outputNumber]) {\n        return this._outputs[outputNumber]\n      }\n      this._outputs[outputNumber] = TransactionOutput.prototype.initFromBinaryBlob(this[\"outputNum\"+outputNumber]);\n      return this._outputs[outputNumber]\n  }\n\n  getKey() {\n    if(this._key) {\n      return this._key;\n    }\n    this._key = \"\";\n    for (let i of [0,1]) {\n        let inp = this.getTransactionInput(i);\n        if (inp && typeof inp != \"undefined\") {\n          this._key = this._key + inp.getKey();\n        }\n    }\n    return this._key;\n  }\n\n  clearRaw(includeNumber, includeSignature) {\n    let items\n    let start = 0;\n    if (!includeNumber) {\n      start = 1;\n    }\n    if (includeSignature) {\n      items = this.raw.slice(start, this.raw.length)\n    } else {\n        items = this.raw.slice(start, this.raw.length-3)\n    }\n    items = items.filter((i) =>{\n      return typeof i !== 'undefined';\n    })\n    return items;\n    // return Buffer.concat(items);\n  }\n  /**\n   * returns the sender's address\n   * @return {Buffer}\n   */\n  getSenderAddress () {\n    if (this._from) {\n      return this._from\n    }\n    const pubkey = this.getSenderPublicKey()\n    this._from = ethUtil.publicToAddress(pubkey)\n    return this._from\n  }\n\n  /**\n   * returns the public key of the sender\n   * @return {Buffer}\n   */\n  getSenderPublicKey () {\n    if (!this._senderPubKey || !this._senderPubKey.length) {\n      if (!this.verifySignature()) throw new Error('Invalid Signature')\n    }\n    return this._senderPubKey\n  }\n\n  /**\n   * Determines if the signature is valid\n   * @return {Boolean}\n   */\n  verifySignature () {\n    const msgHash = this.hash(false, false);\n    // All transaction signatures whose s-value is greater than secp256k1n/2 are considered invalid.\n    if (new BN(this.s).cmp(N_DIV_2) === 1) {\n      return false\n    }\n\n    try {\n      let v = ethUtil.bufferToInt(this.v)\n    //   if (this._chainId > 0) {\n    //     v -= this._chainId * 2 + 8\n    //   }\n      this._senderPubKey = ethUtil.ecrecover(msgHash, v, this.r, this.s)\n    } catch (e) {\n      return false\n    }\n\n    return !!this._senderPubKey\n  }\n\n  /**\n   * sign a transaction with a given a private key\n   * @param {Buffer} privateKey\n   */\n  sign (privateKey) {\n    const msgHash = this.hash(false)\n    const sig = ethUtil.ecsign(msgHash, privateKey)\n    if (sig.v < 27){\n        sig.v += 27\n    }\n    Object.assign(this, sig)\n  }\n\n  assignNumber (numberInBlock) {\n    const transactionNumberInBlock = ethUtil.setLengthLeft(ethUtil.toBuffer(new BN(numberInBlock)),txNumberLength)\n    Object.assign(this, transactionNumberInBlock)\n  }\n\n  transactionTypeUInt() {\n    const txType = ethUtil.bufferToInt(this.transactionType)\n    return txType;\n  }\n\n  /**\n   * validates the signature and checks to see if it has enough gas\n   * @param {Boolean} [stringError=false] whether to return a string with a dscription of why the validation failed or return a Bloolean\n   * @return {Boolean|String}\n   */\n  validate (stringError) {\n    const errors = []\n    for (let i of [0,1]) {\n      const input = this.getTransactionInput(i);\n      if (input && input.outputNumberInTransaction.equals(Buffer.from(\"ff\", \"hex\")) ) {\n            errors.push('Invalid Input numbers')\n          }\n    }\n    // if (this.transactionTypeUInt() == TxTypeMerge) {\n    //   if (!this.getTransactionInput(0).to.equal(this.getTransactionInput(1).to)){\n    //     errors.push('Invalid Inputs')\n    //   }\n    // }\n    if (this.getKey() == \"000000000000000000\" && !( \"0x\" + this.getSenderAddress().toString('hex') == config.plasmaOperatorAddress)) {\n      errors.push('Funding without permissions')\n    }\n    if (!this.verifySignature()) {\n      errors.push('Invalid Signature')\n    }\n    if (stringError === undefined || stringError === false) {\n      return errors.length === 0\n    } else {\n      return errors.join(' ')\n    }\n  }\n\n  toFullJSON(labeled) {\n    if (labeled) {\n      const rawObj = this.toJSON(labeled);\n      const txNumberInBlock = ethUtil.bufferToInt(this.txNumberInBlock)\n      const transactionType = this.transactionTypeUInt()\n      const header = {\n        txNumberInBlock,\n        transactionType,\n        v: rawObj.v,\n        r: rawObj.r,\n        s: rawObj.s\n      }\n      var obj = {\n        header,\n        inputs: {},\n        outputs: {}\n      }\n      for (let i of [0,1]) {\n        const inp = this.getTransactionInput(i);\n        if (inp && typeof inp !== \"undefined\") {\n          obj.inputs[i] = inp.toFullJSON(labeled)\n        }\n      }\n      for (let i of [0,1]) {\n        const out = this.getTransactionOutput(i);\n        if (out && typeof out !== \"undefined\") {\n          obj.outputs[i] = out.toFullJSON(labeled)\n        }\n      }\n      return obj\n    } else {\n      return ethUtil.baToJSON(this.raw)\n    }\n  }\n}\n\nconst dummy = new PlasmaTransaction();\nconst TXmainLength = Buffer.concat(dummy.raw.filter((r) =>{\n  return typeof r !== \"undefined\"\n})).length\n\nconst TxLengthForType = {};\nTxLengthForType[TxTypeMerge]= TXmainLength+2*TransactionInputLength + 1*TransactionOutputLength\nTxLengthForType[TxTypeSplit]= TXmainLength+1*TransactionInputLength + 2*TransactionOutputLength\nTxLengthForType[TxTypeWithdraw]= TXmainLength+1*TransactionInputLength + 1*TransactionOutputLength\nTxLengthForType[TxTypeFund]= TXmainLength+1*TransactionInputLength + 2*TransactionOutputLength\nTxLengthForType[TxTypeTransfer]= TXmainLength+1*TransactionInputLength + 1*TransactionOutputLength\n\nPlasmaTransaction.prototype.initTxForTypeFromBinary = function(txType, blob) {\n  const numInputs = NumInputsForType[txType];\n  const numOutputs = NumOutputsForType[txType];\n  if (numInputs == undefined || numOutputs == undefined) {\n    return null;\n  }\n  const splitFront = [];\n  let i=0;\n  for (let sliceLen of [txNumberLength, txTypeLength]) {\n    splitFront.push(blob.slice(i, i+ sliceLen));\n    i += sliceLen;\n  }\n  const txParams = {};\n  for (let j = 0; j < numInputs; j++){\n    const input = TransactionInput.prototype.initFromBinaryBlob(blob.slice(i, i+TransactionInputLength));\n    i+= TransactionInputLength;\n    txParams[\"inputNum\"+j] = Buffer.concat(input.raw);\n  }\n  for (let j = 0; j < numOutputs; j++){\n    const output = TransactionOutput.prototype.initFromBinaryBlob(blob.slice(i, i+TransactionOutputLength));\n    i+= TransactionOutputLength;\n    txParams[\"outputNum\"+j] = Buffer.concat(output.raw);\n  }\n  const splitEnd = [];\n  for (let sliceLen of [signatureVlength, signatureRlength, signatureSlength]) {\n    splitEnd.push(blob.slice(i, i+ sliceLen));\n    i += sliceLen;\n  }\n  txParams['transactionNumberInBlock'] = splitFront[0];\n  txParams['transactionType'] = splitFront[1];\n  txParams['v'] = splitEnd[0];\n  txParams['r'] = splitEnd[1];\n  txParams['s'] = splitEnd[2];\n  const TX = new PlasmaTransaction(txParams);\n  return TX;\n}\n\n\n\nconst NumInputsForType = {}\nNumInputsForType[TxTypeFund] =  1\nNumInputsForType[TxTypeWithdraw]= 1\nNumInputsForType[TxTypeMerge]= 2\nNumInputsForType[TxTypeSplit]= 1\nNumInputsForType[TxTypeTransfer] = 1\n\nconst NumOutputsForType = {}\nNumOutputsForType[TxTypeFund]= 2\nNumOutputsForType[TxTypeWithdraw]= 1\nNumOutputsForType[TxTypeMerge]= 1\nNumOutputsForType[TxTypeSplit]= 2\nNumOutputsForType[TxTypeTransfer] = 1\n\nmodule.exports = {PlasmaTransaction,\n                  TxTypeFund, \n                  TxTypeMerge, \n                  TxTypeSplit, \n                  TxTypeWithdraw,\n                  TxTypeTransfer, \n                  TxLengthForType,\n                  NumInputsForType,\n                  NumOutputsForType}"
  },
  {
    "path": "lib/dataStructureLengths.js",
    "content": "module.exports = {\n    blockNumberLength: 4,\n    txNumberLength: 4,\n    txTypeLength :1, \n    signatureVlength : 1,\n    signatureRlength : 32,\n    signatureSlength: 32,\n    merkleRootLength: 32,\n    previousHashLength: 32,\n    txOutputNumberLength: 1,\n    txAmountLength : 32,\n    txToAddressLength : 20\n}"
  },
  {
    "path": "lib/merkle-tools.js",
    "content": "'use strict'\n\n/* Copyright 2017 Tierion\n* Licensed under the Apache License, Version 2.0 (the \"License\");\n* you may not use this file except in compliance with the License.\n* You may obtain a copy of the License at\n*     http://www.apache.org/licenses/LICENSE-2.0\n* Unless required by applicable law or agreed to in writing, software\n* distributed under the License is distributed on an \"AS IS\" BASIS,\n* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n* See the License for the specific language governing permissions and\n* limitations under the License.\n*/\n\nvar sha3512 = require('js-sha3').sha3_512\nvar sha3384 = require('js-sha3').sha3_384\nvar sha3256 = require('js-sha3').sha3_256\nvar sha3224 = require('js-sha3').sha3_224\nvar crypto = require('crypto')\nvar ethUtil = require('ethereumjs-util')\n\nvar MerkleTools = function (treeOptions) {\n  // in case 'new' was omitted\n  if (!(this instanceof MerkleTools)) {\n    return new MerkleTools(treeOptions)\n  }\n\n  var hashType = 'sha256'\n  if (treeOptions) { // if tree options were supplied, then process them\n    if (treeOptions.hashType !== undefined) { // set the hash function to the user's choice\n      hashType = treeOptions.hashType\n    }\n  }\n\n  var hashFunction = function (value) {\n    switch (hashType) {\n      case 'SHA3-224':\n        return new Buffer(sha3224.array(value))\n      case 'SHA3-256':\n        return new Buffer(sha3256.array(value))\n      case 'SHA3-384':\n        return new Buffer(sha3384.array(value))\n      case 'SHA3-512':\n        return new Buffer(sha3512.array(value))\n      case 'sha3':\n        return ethUtil.sha3(value, 256)  \n      default:\n        return crypto.createHash(hashType).update(value).digest()\n    }\n  }\n\n  var tree = {}\n  tree.leaves = []\n  tree.levels = []\n  tree.isReady = false\n\n  /// /////////////////////////////////////////\n  // Public Primary functions\n  /// /////////////////////////////////////////\n\n  // Resets the current tree to empty\n  this.resetTree = function () {\n    tree = {}\n    tree.leaves = []\n    tree.levels = []\n    tree.isReady = false\n  }\n\n  // Add a leaf to the tree\n  // Accepts hash value as a Buffer or hex string\n  this.addLeaf = function (value, doHash) {\n    tree.isReady = false\n    if (doHash) value = hashFunction(value)\n    tree.leaves.push(_getBuffer(value))\n  }\n\n  // Add a leaves to the tree\n  // Accepts hash values as an array of Buffers or hex strings\n  this.addLeaves = function (valuesArray, doHash) {\n    tree.isReady = false\n    valuesArray.forEach(function (value) {\n      if (doHash) value = hashFunction(value)\n      tree.leaves.push(_getBuffer(value))\n    })\n  }\n\n  // Returns a leaf at the given index\n  this.getLeaf = function (index) {\n    if (index < 0 || index > tree.leaves.length - 1) return null // index is out of array bounds\n\n    return tree.leaves[index]\n  }\n\n  // Returns the number of leaves added to the tree\n  this.getLeafCount = function () {\n    return tree.leaves.length\n  }\n\n  // Returns the ready state of the tree\n  this.getTreeReadyState = function () {\n    return tree.isReady\n  }\n\n  // Generates the merkle tree\n  this.makeTree = function (doubleHash) {\n    tree.isReady = false\n    var leafCount = tree.leaves.length\n    if (leafCount > 0) { // skip this whole process if there are no leaves added to the tree\n      tree.levels = []\n      tree.levels.unshift(tree.leaves)\n      while (tree.levels[0].length > 1) {\n        tree.levels.unshift(_calculateNextLevel(doubleHash))\n      }\n    }\n    tree.isReady = true\n  }\n\n  // Generates a Bitcoin style merkle tree\n  this.makeBTCTree = function (doubleHash) {\n    tree.isReady = false\n    var leafCount = tree.leaves.length\n    if (leafCount > 0) { // skip this whole process if there are no leaves added to the tree\n      tree.levels = []\n      tree.levels.unshift(tree.leaves)\n      while (tree.levels[0].length > 1) {\n        tree.levels.unshift(_calculateBTCNextLevel(doubleHash))\n      }\n    }\n    tree.isReady = true\n  }\n\n  // Returns the merkle root value for the tree\n  this.getMerkleRoot = function () {\n    if (!tree.isReady || tree.levels.length === 0) return null\n    return tree.levels[0][0]\n  }\n\n  // Returns the proof for a leaf at the given index as an array of merkle siblings in hex format\n  this.getProof = function (index, asBinary) {\n    if (!tree.isReady) return null\n    var currentRowIndex = tree.levels.length - 1\n    if (index < 0 || index > tree.levels[currentRowIndex].length - 1) return null // the index it out of the bounds of the leaf array\n\n    var proof = []\n    for (var x = currentRowIndex; x > 0; x--) {\n      var currentLevelNodeCount = tree.levels[x].length\n            // skip if this is an odd end node\n      if (index === currentLevelNodeCount - 1 && currentLevelNodeCount % 2 === 1) {\n        index = Math.floor(index / 2)\n        continue\n      }\n\n            // determine the sibling for the current index and get its value\n      var isRightNode = index % 2\n      var siblingIndex = isRightNode ? (index - 1) : (index + 1)\n\n      if (asBinary) {\n        proof.push(new Buffer(isRightNode ? [0x00] : [0x01]))\n        proof.push(tree.levels[x][siblingIndex])\n      } else {\n        var sibling = {}\n        var siblingPosition = isRightNode ? 'left' : 'right'\n        var siblingValue = tree.levels[x][siblingIndex].toString('hex')\n        sibling[siblingPosition] = siblingValue\n\n        proof.push(sibling)\n      }\n\n      index = Math.floor(index / 2) // set index to the parent index\n    }\n\n    return proof\n  }\n\n  // Takes a proof array, a target hash value, and a merkle root\n  // Checks the validity of the proof and return true or false\n  this.validateProof = function (proof, targetHash, merkleRoot) {\n    targetHash = _getBuffer(targetHash)\n    merkleRoot = _getBuffer(merkleRoot)\n    if (proof.length === 0) return targetHash.toString('hex') === merkleRoot.toString('hex') // no siblings, single item tree, so the hash should also be the root\n\n    var proofHash = targetHash\n    for (var x = 0; x < proof.length; x++) {\n      if (proof[x].left) { // then the sibling is a left node\n        proofHash = hashFunction(Buffer.concat([_getBuffer(proof[x].left), proofHash]))\n      } else if (proof[x].right) { // then the sibling is a right node\n        proofHash = hashFunction(Buffer.concat([proofHash, _getBuffer(proof[x].right)]))\n      } else { // no left or right designation exists, proof is invalid\n        return false\n      }\n    }\n\n    return proofHash.toString('hex') === merkleRoot.toString('hex')\n  }\n\n  /// ///////////////////////////////////////\n  // Private Utility functions\n  /// ///////////////////////////////////////\n\n  // Internally, trees are made of nodes containing Buffer values only\n  // This helps ensure that leaves being added are Buffers, and will convert hex to Buffer if needed\n  function _getBuffer (value) {\n    if (value instanceof Buffer) { // we already have a buffer, so return it\n      return value\n    } else if (_isHex(value)) { // the value is a hex string, convert to buffer and return\n      return new Buffer(value, 'hex')\n    } else { // the value is neither buffer nor hex string, will not process this, throw error\n      throw new Error(\"Bad hex value - '\" + value + \"'\")\n    }\n  }\n\n  function _isHex (value) {\n    var hexRegex = /^[0-9A-Fa-f]{2,}$/\n    return hexRegex.test(value)\n  }\n\n  // Calculates the next level of node when building the merkle tree\n  // These values are calcalated off of the current highest level, level 0 and will be prepended to the levels array\n  function _calculateNextLevel (doubleHash) {\n    var nodes = []\n    var topLevel = tree.levels[0]\n    var topLevelCount = topLevel.length\n    for (var x = 0; x < topLevelCount; x += 2) {\n      if (x + 1 <= topLevelCount - 1) { // concatenate and hash the pair, add to the next level array, doubleHash if requested\n        if (doubleHash) {\n          nodes.push(hashFunction(hashFunction(Buffer.concat([topLevel[x], topLevel[x + 1]]))))\n        } else {\n          nodes.push(hashFunction(Buffer.concat([topLevel[x], topLevel[x + 1]])))\n        }\n      } else { // this is an odd ending node, promote up to the next level by itself\n        nodes.push(topLevel[x])\n      }\n    }\n    return nodes\n  }\n\n  // This version uses the BTC method of duplicating the odd ending nodes\n  function _calculateBTCNextLevel (doubleHash) {\n    var nodes = []\n    var topLevel = tree.levels[0]\n    var topLevelCount = topLevel.length\n    if (topLevelCount % 2 === 1) { // there is an odd count, duplicate the last element\n      topLevel.push(topLevel[topLevelCount - 1])\n    }\n    for (var x = 0; x < topLevelCount; x += 2) {\n      // concatenate and hash the pair, add to the next level array, doubleHash if requested\n      if (doubleHash) {\n        nodes.push(hashFunction(hashFunction(Buffer.concat([topLevel[x], topLevel[x + 1]]))))\n      } else {\n        nodes.push(hashFunction(Buffer.concat([topLevel[x], topLevel[x + 1]])))\n      }\n    }\n    return nodes\n  }\n}\n\nmodule.exports = MerkleTools"
  },
  {
    "path": "lib/serialize.js",
    "content": "const ethUtil = require('ethereumjs-util')\nconst assert = require('assert');\n\nexports.defineProperties = function (self, fields, data) {\n    self.raw = []\n    self._fields = []\n  \n    // attach the `toJSON`\n    self.toJSON = function (label) {\n      if (label) {\n        var obj = {}\n        self._fields.forEach(function (field) {\n          if (!self[field] || typeof self[field] === \"undefined\"){\n            return;\n          }\n          obj[field] = '0x' + self[field].toString('hex')\n        })\n        return obj\n      }\n      return ethUtil.baToJSON(this.raw)\n    }\n  \n    self.serialize = function serialize () {\n      return Buffer.concat(this.raw)\n    }\n  \n    fields.forEach(function (field, i) {\n      self._fields.push(field.name)\n      function getter () {\n        return self.raw[i]\n      }\n      function setter (v) {\n        v = ethUtil.toBuffer(v)\n  \n        if (v.toString('hex') === '00' && !field.allowZero) {\n          v = Buffer.allocUnsafe(0)\n        }\n  \n        if (field.allowLess && field.length) {\n          v = ethUtil.stripZeros(v)\n          assert(field.length >= v.length, 'The field ' + field.name + ' must not have more ' + field.length + ' bytes')\n        } else if (!(field.allowZero && v.length === 0) && field.length) {\n          assert(field.length === v.length, 'The field ' + field.name + ' must have byte length of ' + field.length)\n        }\n  \n        self.raw[i] = v\n      }\n  \n      Object.defineProperty(self, field.name, {\n        enumerable: true,\n        configurable: true,\n        get: getter,\n        set: setter\n      })\n  \n      if (field.default) {\n        self[field.name] = field.default\n      }\n  \n      // attach alias\n      if (field.alias) {\n        Object.defineProperty(self, field.alias, {\n          enumerable: false,\n          configurable: true,\n          set: setter,\n          get: getter\n        })\n      }\n    })\n  \n    // if the constuctor is passed data\n    if (data) {\n      if (typeof data === 'string') {\n        data = Buffer.from(ethUtil.stripHexPrefix(data), 'hex')\n      }\n \n      if (Array.isArray(data)) {\n        if (data.length > self._fields.length) {\n          throw (new Error('wrong number of fields in data'))\n        }\n  \n        // make sure all the items are buffers\n        data.forEach(function (d, i) {\n          self[self._fields[i]] = ethUtil.toBuffer(d)\n        })\n      } else if (typeof data === 'object') {\n        const keys = Object.keys(data)\n        fields.forEach(function (field) {\n          if (keys.indexOf(field.name) !== -1) self[field.name] = data[field.name]\n          if (keys.indexOf(field.alias) !== -1) self[field.alias] = data[field.alias]\n        })\n      } else {\n        throw new Error('invalid data')\n      }\n    }\n  }"
  },
  {
    "path": "package.json",
    "content": "{\n  \"name\": \"plasma\",\n  \"version\": \"1.0.0\",\n  \"repository\": {\n    \"type\": \"git\",\n    \"url\": \"https://github.com/BankEx/PlasmaETHexchange\"\n  },\n  \"description\": \"Plasma protocol compatible ETH Exchange Platform\",\n  \"main\": \"server.js\",\n  \"scripts\": {\n    \"test\": \"echo \\\"Error: no test specified\\\" && exit 1\",\n    \"server\": \"node server.js\"\n  },\n  \"author\": \"Alexander Vlasov @shamatar\",\n  \"license\": \"ISC\",\n  \"dependencies\": {\n    \"coinstring\": \"^2.3.0\",\n    \"ethereumjs-testrpc\": \"^6.0.1\",\n    \"ethereumjs-util\": \"^5.1.2\",\n    \"express\": \"^4.16.2\",\n    \"js-sha3\": \"^0.6.1\",\n    \"jsonschema\": \"^1.2.0\",\n    \"leveldown\": \"^2.0.0\",\n    \"levelup\": \"^2.0.0\",\n    \"merkle-tools\": \"^1.4.0\",\n    \"moment\": \"^2.19.1\",\n    \"named-routes\": \"^2.0.6\",\n    \"queue\": \"^4.4.2\",\n    \"rimraf\": \"^2.6.2\",\n    \"scrypt\": \"^6.0.3\",\n    \"solc\": \"^0.4.18\",\n    \"strip-hex-prefix\": \"^1.0.0\",\n    \"truffle-artifactor\": \"^3.0.0\",\n    \"truffle-contract\": \"^3.0.1\",\n    \"web3\": \"^1.0.0-beta.24\"\n  }\n}\n"
  },
  {
    "path": "server.js",
    "content": "const config = require('./app/config/config');\nvar rimraf = require('rimraf');\nif (!config.testOnRinkeby) {\n    rimraf.sync('./db');\n    console.log(\"Cleared DB\");\n}\n\nconst express        = require('express');\nconst app            = express();\nconst https = require('https')\nconst Router = require('named-routes');\nvar router = new Router();\nrouter.extendExpress(app);\nrouter.registerAppHelpers(app);\nconst bodyParser = require('body-parser');\napp.use(bodyParser.json());\n\nconst comp = require('./compile');\n\nconst assert = require('assert');\nconst moment = require('moment');\nconst coinstring = require('coinstring');\nconst fs = require(\"fs\");\nconst solc = require('solc');\nconst Artifactor = require(\"truffle-artifactor\"); \nconst async = require(\"async\");\nconst TruffleContract = require('truffle-contract');\n \nvar TestRPC = require(\"ethereumjs-testrpc\");\n \nconst Web3 = require(\"web3\");\nconst BN = Web3.utils.BN;\nconst util = require('util');\nconst ethUtil = require('ethereumjs-util'); \nconst PlasmaTransaction = require('./lib/Tx/tx');\nconst Block = require('./lib/Block/block');\nconst fromBtcWif = coinstring.createDecoder(0x80);\nconst levelup = require('levelup')\nconst leveldown = require('leveldown')\nconst levelDB = levelup(leveldown('./db'))\n\nlet lastBlock;\nlet lastBlockHash;\nlet blockMiningTimer;\nconst {blockNumberLength} = require(\"./lib/dataStructureLengths\");\n\nconst plasmaOperatorPrivKeyHex = config.plasmaOperatorPrivKeyHex;\nconst plasmaOperatorPrivKey = ethUtil.toBuffer(plasmaOperatorPrivKeyHex);\nconst plasmaOperatorAddress = config.plasmaOperatorAddress;      \nconst testPrivKeys = config.testPrivKeys;  \nconst port = config.port;\n\nlet sendAsyncPromisified;\nlet PlasmaContract;\nlet DeployedPlasmaContract;\nlet Web3PlasmaContract;\nlet web3;\n\nasync function startVM(){\n    if (config.testOnRinkeby) {\n        web3 = new Web3(config.provider);\n        let unlocked = await web3.eth.personal.unlockAccount(config.plasmaOperatorAddress, config.plasmaOperatorPassword, 0);\n        let provider = web3.currentProvider;\n        sendAsyncPromisified = util.promisify(provider.send).bind(provider);\n        return;\n    }\n    let provider = TestRPC.provider({\n        total_accounts: 10,\n        time:new Date(),\n        verbose:false,\n        gasPrice: 0,\n      accounts:[\n          {secretKey:\"0x\" + plasmaOperatorPrivKey.toString('hex'), balance: 4.2e18},\n          {secretKey:\"0x\" + testPrivKeys[0].toString('hex'), balance: 4.2e18},\n          {secretKey:\"0x\" + testPrivKeys[1].toString('hex'), balance: 4.2e18}    \n      ],\n        mnemonic: \"42\"\n        // ,\n        // logger: console\n      });\n      web3 = new Web3(provider);\n\n      sendAsyncPromisified = util.promisify(provider.sendAsync).bind(provider);\n}\n\n\n\nasync function deployContracts() {\n    PlasmaContract = new TruffleContract(require(\"./build/contracts/PlasmaParent.json\"));\n    if (config.testOnRinkeby) {\n        if (config.deployedPlasmaContract == \"\") {\n            Web3PlasmaContract = new web3.eth.Contract(PlasmaContract.abi, {from: config.plasmaOperatorAddress, gasPrice: 35e9});\n            DeployedPlasmaContract = await Web3PlasmaContract.deploy({data: PlasmaContract.bytecode}).send({from: config.plasmaOperatorAddress, gas: 6e6});\n            console.log(\"Deployed at \"+ DeployedPlasmaContract._address);\n            return;\n        }\n        DeployedPlasmaContract = new web3.eth.Contract(PlasmaContract.abi, config.deployedPlasmaContract,{from: config.plasmaOperatorAddress, gasPrice: 35e9});\n        console.log(\"Deployed at \"+ DeployedPlasmaContract._address);\n        return;\n    }\n    Web3PlasmaContract = new web3.eth.Contract(PlasmaContract.abi, {from: config.plasmaOperatorAddress});\n    DeployedPlasmaContract = await Web3PlasmaContract.deploy({data: PlasmaContract.bytecode}).send({from: plasmaOperatorAddress, gas: 6e6});\n    console.log(\"Deployed at \"+ DeployedPlasmaContract._address);\n}\n\n\n\nfunction jump(duration) {\n    return async function() {\n      var params = duration.split(\" \");\n      params[0] = parseInt(params[0])\n      var seconds = moment.duration.apply(moment, params).asSeconds();\n      await sendAsyncPromisified({\n        jsonrpc: \"2.0\",\n        method: \"evm_increaseTime\",\n        params: [seconds],\n        id: new Date().getTime()\n        });\n    }\n}\n\napp.jump = jump;\n\n\nasync function prepareOracle(){\n    await startVM();\n    await comp();\n    await deployContracts();\n    try{\n        lastBlock = await levelDB.get('lastBlockNumber');\n    }\n    catch(error) {\n        lastBlock = ethUtil.setLengthLeft(ethUtil.toBuffer(new BN(0)),blockNumberLength)\n        await levelDB.put('lastBlockNumber', lastBlock);\n    }\n    try{\n        lastBlockHash = await levelDB.get('lastBlockHash');\n    }\n    catch(error) {\n        lastBlockHash = ethUtil.sha3('bankex.com')\n        await levelDB.put('lastBlockHash', lastBlockHash);\n    }\n    app.txQueueArray = [];\n    app.DeployedPlasmaContract = DeployedPlasmaContract;\n    const processDepositEvent = require('./app/helpers/processDepositEvent')(app, levelDB, web3);\n    const processExpressWithdrawMakeEvent = require('./app/helpers/processExpressWithdrawMadeEvent')(app, levelDB, web3);\n    app.processDepositEvent = processDepositEvent;\n    app.processExpressWithdrawMakeEvent = processExpressWithdrawMakeEvent;\n    require('./app/miner')(app, levelDB, web3);\n    // require('./app/endpoints/fundPlasma')(app, levelDB, web3);\n    // require('./app/endpoints/acceptAndSignTransaction')(app, levelDB, web3);\n    require('./app/endpoints/createTransactionToSign')(app,levelDB,web3);\n    require('./app/endpoints/acceptSignedTX')(app, levelDB, web3);\n    require('./app/endpoints/getBlockByNumber')(app, levelDB, web3);\n    require('./app/endpoints/getTxByNumber')(app, levelDB, web3);\n    require('./app/endpoints/getUTXOsForAddress')(app, levelDB, web3);\n    require('./app/endpoints/getTXsForAddress')(app, levelDB, web3);\n    require('./app/endpoints/getWithdrawsForAddress')(app, levelDB, web3);\n    // require('./app/endpoints/withdraw')(app, levelDB, web3);\n    require('./app/endpoints/auxilary')(app, levelDB, web3);\n    require('./app/endpoints/prepareProofForExpressWithdraw')(app, levelDB, web3);\n}\n\nprepareOracle().then(async (result) => {\n    if (config.useSSL) {\n        const privateKey = fs.readFileSync( 'privatekey.pem' );\n        const certificate = fs.readFileSync( 'certificate.pem' );\n        await https.createServer({\n            key: privateKey,\n            cert: certificate\n        }, app).listen(port);\n        console.log(\"Live using SSL\")\n        console.log('We are live on ' + port);\n        // console.log(config.testAccounts[0])\n        // console.log(config.testAccounts[1])\n        console.log(\"Operator address = \" + config.plasmaOperatorAddress);\n        app._router.stack.forEach(function(r){\n        if (r.name && r.name == 'bound dispatch'){\n            console.log(r.route.path)\n            }\n            })\n        }\n    else {\n        app.listen(port, async () => {\n            console.log('We are live on ' + port);\n            // console.log(config.testAccounts[0])\n            // console.log(config.testAccounts[1])\n            console.log(\"Operator address = \" + config.plasmaOperatorAddress);\n            app._router.stack.forEach(function(r){\n            if (r.name && r.name == 'bound dispatch'){\n                console.log(r.route.path)\n                }\n                })\n            })\n        }\n    }\n)\n\n         \n"
  }
]