├── .gitattributes ├── .gitignore ├── LICENSE ├── README.md ├── RootChain.sol ├── contracts.json ├── requirements.txt ├── rootchain_abi.py ├── smt.py └── test.py /.gitattributes: -------------------------------------------------------------------------------- 1 | *.sol linguist-language=Solidity 2 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | venv/ 2 | .vscode/ 3 | __pycache__/ 4 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2018 Counterfactual 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | PoC, untested. 188 CLOC. 2 | 3 | Forked from https://github.com/omisego/plasma-cash 4 | 5 | to generate the abi json file: 6 | 7 | ``` 8 | solc --combined-json abi,bin,bin-runtime RootChain.sol > contracts.json 9 | ``` 10 | 11 | requires a patched pyethereum that allows passing `data` directly 12 | -------------------------------------------------------------------------------- /RootChain.sol: -------------------------------------------------------------------------------- 1 | pragma solidity ^0.4.25; 2 | pragma experimental "ABIEncoderV2"; 3 | 4 | contract RootChain { 5 | 6 | enum ExitStage { 7 | NOT_STARTED, // default unintialized 8 | STARTED, 9 | FINISHED 10 | } 11 | 12 | struct Transfer { 13 | address oldOwner; 14 | address newOwner; 15 | uint256 oldBlkNum; 16 | uint8 sigV; 17 | bytes32 sigR; 18 | bytes32 sigS; 19 | } 20 | 21 | struct IncludedTransfer { 22 | uint256 blkNum; 23 | Transfer txn; 24 | } 25 | 26 | struct Exit { 27 | ExitStage stage; 28 | uint256 challengeDeadline; 29 | uint256 numChallenges; 30 | address pcOwner; 31 | uint256 cBlkNum; 32 | uint256 pcBlkNum; 33 | } 34 | 35 | /** 36 | * @dev Validate the merkle proof of a specifc leaf with index 37 | */ 38 | function checkMembership( 39 | bytes32 leaf, 40 | uint256 index, 41 | bytes32 rootHash, 42 | bytes proof 43 | ) 44 | public 45 | pure 46 | returns (bool) 47 | { 48 | bytes32 proofElement; 49 | bytes32 computedHash = leaf; 50 | 51 | require(proof.length == 256); 52 | 53 | for (uint256 i = 32; i <= proof.length; i += 32) { 54 | assembly { 55 | proofElement := mload(add(proof, i)) 56 | } 57 | if (index % 2 == 0) { 58 | computedHash = keccak256(abi.encode(computedHash, proofElement)); 59 | } else { 60 | computedHash = keccak256(abi.encode(proofElement, computedHash)); 61 | } 62 | index = index / 2; 63 | } 64 | return computedHash == rootHash; 65 | } 66 | 67 | /* 68 | * Storage 69 | */ 70 | address public authority; 71 | bytes32[] public childBlockRoots; 72 | uint256[] public coins; 73 | mapping(uint256 => mapping(address => Exit)) exits; 74 | mapping(uint256 => mapping(address => bytes32)) exitHashes; 75 | mapping(uint256 => mapping(address => mapping(uint256 => IncludedTransfer))) challenges; 76 | uint256[] coinDepositBlkNum; 77 | 78 | constructor () 79 | public 80 | { 81 | authority = msg.sender; 82 | } 83 | 84 | // @dev Allows Plasma chain operator to submit block root 85 | // @param blkRoot The root of a transaction SMT 86 | function submitBlock(bytes32 blkRoot) 87 | public 88 | { 89 | require(msg.sender == authority); 90 | childBlockRoots.push(blkRoot); 91 | } 92 | 93 | function deposit() 94 | payable 95 | public 96 | { 97 | coinDepositBlkNum.push(childBlockRoots.length); 98 | childBlockRoots.push(bytes32(0)); 99 | coins.push(msg.value); 100 | } 101 | 102 | function checkInclusion( 103 | uint256 coinId, 104 | IncludedTransfer itxn, 105 | bytes txnProof 106 | ) public view returns (bool) { 107 | if (itxn.blkNum == coinDepositBlkNum[coinId]) return true; 108 | bytes32 txnDigest = keccak256(abi.encode(coinId, itxn.txn)); 109 | if (itxn.txn.oldOwner != ecrecover(txnDigest, itxn.txn.sigV, itxn.txn.sigR, itxn.txn.sigS)) return false; 110 | bytes32 blkRoot = childBlockRoots[itxn.blkNum]; 111 | bytes32 digest = keccak256(abi.encode(coinId, itxn.txn)); 112 | return checkMembership(digest, coinId, blkRoot, txnProof); 113 | } 114 | 115 | function startExitOfDeposit( 116 | uint256 coinId 117 | ) { 118 | exits[coinId][msg.sender] = Exit({ 119 | stage: ExitStage.STARTED, 120 | challengeDeadline: block.number + 100, 121 | numChallenges: 0, 122 | pcOwner: address(0), 123 | cBlkNum: coinDepositBlkNum[coinId], 124 | pcBlkNum: uint256(0) 125 | }); 126 | } 127 | 128 | // @dev Starts to exit a transaction producing an output C 129 | function startExit( 130 | uint256 coinId, 131 | 132 | IncludedTransfer c, 133 | bytes cProof, 134 | 135 | IncludedTransfer pc, 136 | bytes pcProof 137 | ) 138 | public 139 | { 140 | require(msg.sender == c.txn.newOwner); 141 | 142 | // check inclusion proofs 143 | require(checkInclusion(coinId, c, cProof)); 144 | require(checkInclusion(coinId, pc, pcProof)); 145 | 146 | // check owners match 147 | require(c.txn.oldOwner == pc.txn.newOwner); 148 | 149 | // check separation 150 | require(pc.blkNum < c.blkNum); 151 | 152 | // Record the exit tx. 153 | require(exits[coinId][msg.sender].stage == ExitStage.NOT_STARTED); 154 | 155 | // todo: gas limit nonsense 156 | 157 | exits[coinId][msg.sender] = Exit({ 158 | stage: ExitStage.STARTED, 159 | challengeDeadline: block.number + 100, 160 | numChallenges: 0, 161 | pcOwner: pc.txn.newOwner, 162 | cBlkNum: c.blkNum, 163 | pcBlkNum: pc.blkNum 164 | }); 165 | } 166 | 167 | function spends( 168 | IncludedTransfer a, 169 | IncludedTransfer b, 170 | uint256 deadline 171 | ) public pure returns (bool) { 172 | return ( 173 | a.blkNum < b.blkNum 174 | && a.txn.newOwner == b.txn.oldOwner 175 | && a.blkNum == b.txn.oldBlkNum 176 | && b.blkNum < deadline 177 | ); 178 | } 179 | 180 | // @dev Challenge an exit transaction 181 | function challengeExit( 182 | uint256 coinId, 183 | address exitBeneficiary, 184 | IncludedTransfer cs, 185 | bytes csProof 186 | ) public { 187 | require(exits[coinId][exitBeneficiary].stage == ExitStage.STARTED); 188 | require(checkInclusion(coinId, cs, csProof)); 189 | 190 | Exit storage exit = exits[coinId][exitBeneficiary]; 191 | 192 | if ( /* Type 1: C has been spent */ 193 | (exit.cBlkNum < cs.blkNum) 194 | && (exit.cBlkNum == cs.txn.oldBlkNum) 195 | && (exitBeneficiary == cs.txn.oldOwner) 196 | ) { 197 | exits[coinId][exitBeneficiary].stage = ExitStage.FINISHED; 198 | } else if ( /* Type 2: P(C) has been spent before C */ 199 | (exit.pcBlkNum < cs.blkNum) 200 | && (exit.pcOwner == cs.txn.newOwner) 201 | && (exit.pcBlkNum == cs.txn.oldBlkNum) 202 | && (cs.blkNum < exit.cBlkNum) 203 | ) { 204 | exits[coinId][exitBeneficiary].stage = ExitStage.FINISHED; 205 | } else if ( /* Type 3: Challenger provides a tx in history. Exitor needs to respond it. */ 206 | cs.blkNum < exits[coinId][exitBeneficiary].pcBlkNum 207 | ) { 208 | challenges[coinId][exitBeneficiary][cs.blkNum] = cs; 209 | exits[coinId][exitBeneficiary].numChallenges += 1; 210 | } 211 | } 212 | 213 | function respondChallengeExit( 214 | uint256 coinId, 215 | address exitBeneficiary, 216 | uint256 csBlkNum, 217 | IncludedTransfer css, 218 | bytes cssProof 219 | ) 220 | public 221 | { 222 | require(checkInclusion(coinId, css, cssProof)); 223 | IncludedTransfer storage cs = challenges[coinId][exitBeneficiary][csBlkNum]; 224 | require(spends(cs, css, uint256(-1))); 225 | exits[coinId][exitBeneficiary].numChallenges -= 1; 226 | } 227 | 228 | function finalizeExit(uint256 coinId, address exitBeneficiary) public { 229 | Exit storage exit = exits[coinId][exitBeneficiary]; 230 | 231 | require(exit.stage == ExitStage.STARTED); 232 | require(block.number >= exit.challengeDeadline); 233 | require(exit.numChallenges == 0); 234 | 235 | exitBeneficiary.transfer(coins[coinId]); 236 | exit.stage = ExitStage.FINISHED; 237 | } 238 | } 239 | 240 | -------------------------------------------------------------------------------- /contracts.json: -------------------------------------------------------------------------------- 1 | {"contracts":{"RootChain.sol:RootChain":{"abi":"[{\"constant\":true,\"inputs\":[{\"name\":\"coinId\",\"type\":\"uint256\"},{\"components\":[{\"name\":\"blkNum\",\"type\":\"uint256\"},{\"components\":[{\"name\":\"oldOwner\",\"type\":\"address\"},{\"name\":\"newOwner\",\"type\":\"address\"},{\"name\":\"oldBlkNum\",\"type\":\"uint256\"},{\"name\":\"sigV\",\"type\":\"uint8\"},{\"name\":\"sigR\",\"type\":\"bytes32\"},{\"name\":\"sigS\",\"type\":\"bytes32\"}],\"name\":\"txn\",\"type\":\"tuple\"}],\"name\":\"itxn\",\"type\":\"tuple\"},{\"name\":\"txnProof\",\"type\":\"bytes\"}],\"name\":\"checkInclusion\",\"outputs\":[{\"name\":\"\",\"type\":\"bool\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"childBlockRoots\",\"outputs\":[{\"name\":\"\",\"type\":\"bytes32\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"name\":\"leaf\",\"type\":\"bytes32\"},{\"name\":\"index\",\"type\":\"uint256\"},{\"name\":\"rootHash\",\"type\":\"bytes32\"},{\"name\":\"proof\",\"type\":\"bytes\"}],\"name\":\"checkMembership\",\"outputs\":[{\"name\":\"\",\"type\":\"bool\"}],\"payable\":false,\"stateMutability\":\"pure\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"coinId\",\"type\":\"uint256\"},{\"name\":\"exitBeneficiary\",\"type\":\"address\"},{\"components\":[{\"name\":\"blkNum\",\"type\":\"uint256\"},{\"components\":[{\"name\":\"oldOwner\",\"type\":\"address\"},{\"name\":\"newOwner\",\"type\":\"address\"},{\"name\":\"oldBlkNum\",\"type\":\"uint256\"},{\"name\":\"sigV\",\"type\":\"uint8\"},{\"name\":\"sigR\",\"type\":\"bytes32\"},{\"name\":\"sigS\",\"type\":\"bytes32\"}],\"name\":\"txn\",\"type\":\"tuple\"}],\"name\":\"cs\",\"type\":\"tuple\"},{\"name\":\"csProof\",\"type\":\"bytes\"}],\"name\":\"challengeExit\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"blkRoot\",\"type\":\"bytes32\"}],\"name\":\"submitBlock\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"coinId\",\"type\":\"uint256\"}],\"name\":\"startExitOfDeposit\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"authority\",\"outputs\":[{\"name\":\"\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"coins\",\"outputs\":[{\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[],\"name\":\"deposit\",\"outputs\":[],\"payable\":true,\"stateMutability\":\"payable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"components\":[{\"name\":\"blkNum\",\"type\":\"uint256\"},{\"components\":[{\"name\":\"oldOwner\",\"type\":\"address\"},{\"name\":\"newOwner\",\"type\":\"address\"},{\"name\":\"oldBlkNum\",\"type\":\"uint256\"},{\"name\":\"sigV\",\"type\":\"uint8\"},{\"name\":\"sigR\",\"type\":\"bytes32\"},{\"name\":\"sigS\",\"type\":\"bytes32\"}],\"name\":\"txn\",\"type\":\"tuple\"}],\"name\":\"a\",\"type\":\"tuple\"},{\"components\":[{\"name\":\"blkNum\",\"type\":\"uint256\"},{\"components\":[{\"name\":\"oldOwner\",\"type\":\"address\"},{\"name\":\"newOwner\",\"type\":\"address\"},{\"name\":\"oldBlkNum\",\"type\":\"uint256\"},{\"name\":\"sigV\",\"type\":\"uint8\"},{\"name\":\"sigR\",\"type\":\"bytes32\"},{\"name\":\"sigS\",\"type\":\"bytes32\"}],\"name\":\"txn\",\"type\":\"tuple\"}],\"name\":\"b\",\"type\":\"tuple\"},{\"name\":\"deadline\",\"type\":\"uint256\"}],\"name\":\"spends\",\"outputs\":[{\"name\":\"\",\"type\":\"bool\"}],\"payable\":false,\"stateMutability\":\"pure\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"coinId\",\"type\":\"uint256\"},{\"components\":[{\"name\":\"blkNum\",\"type\":\"uint256\"},{\"components\":[{\"name\":\"oldOwner\",\"type\":\"address\"},{\"name\":\"newOwner\",\"type\":\"address\"},{\"name\":\"oldBlkNum\",\"type\":\"uint256\"},{\"name\":\"sigV\",\"type\":\"uint8\"},{\"name\":\"sigR\",\"type\":\"bytes32\"},{\"name\":\"sigS\",\"type\":\"bytes32\"}],\"name\":\"txn\",\"type\":\"tuple\"}],\"name\":\"c\",\"type\":\"tuple\"},{\"name\":\"cProof\",\"type\":\"bytes\"},{\"components\":[{\"name\":\"blkNum\",\"type\":\"uint256\"},{\"components\":[{\"name\":\"oldOwner\",\"type\":\"address\"},{\"name\":\"newOwner\",\"type\":\"address\"},{\"name\":\"oldBlkNum\",\"type\":\"uint256\"},{\"name\":\"sigV\",\"type\":\"uint8\"},{\"name\":\"sigR\",\"type\":\"bytes32\"},{\"name\":\"sigS\",\"type\":\"bytes32\"}],\"name\":\"txn\",\"type\":\"tuple\"}],\"name\":\"pc\",\"type\":\"tuple\"},{\"name\":\"pcProof\",\"type\":\"bytes\"}],\"name\":\"startExit\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"coinId\",\"type\":\"uint256\"},{\"name\":\"exitBeneficiary\",\"type\":\"address\"},{\"name\":\"csBlkNum\",\"type\":\"uint256\"},{\"components\":[{\"name\":\"blkNum\",\"type\":\"uint256\"},{\"components\":[{\"name\":\"oldOwner\",\"type\":\"address\"},{\"name\":\"newOwner\",\"type\":\"address\"},{\"name\":\"oldBlkNum\",\"type\":\"uint256\"},{\"name\":\"sigV\",\"type\":\"uint8\"},{\"name\":\"sigR\",\"type\":\"bytes32\"},{\"name\":\"sigS\",\"type\":\"bytes32\"}],\"name\":\"txn\",\"type\":\"tuple\"}],\"name\":\"css\",\"type\":\"tuple\"},{\"name\":\"cssProof\",\"type\":\"bytes\"}],\"name\":\"respondChallengeExit\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"coinId\",\"type\":\"uint256\"},{\"name\":\"exitBeneficiary\",\"type\":\"address\"}],\"name\":\"finalizeExit\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"}]","bin":"608060405234801561001057600080fd5b50336000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550611d67806100606000396000f3006080604052600436106100c5576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff168063263792c9146100ca57806338def2f5146101075780636c8f455c14610144578063b89820f014610181578063baa47694146101aa578063bc77856a146101d3578063bf7e214f146101fc578063c661065714610227578063d0e30db014610264578063df8a9a671461026e578063e756b6c5146102ab578063eb8b5c30146102d4578063fbbed6d1146102fd575b600080fd5b3480156100d657600080fd5b506100f160048036036100ec919081019061195a565b610326565b6040516100fe9190611b4f565b60405180910390f35b34801561011357600080fd5b5061012e600480360361012991908101906117e7565b610555565b60405161013b9190611b6a565b60405180910390f35b34801561015057600080fd5b5061016b6004803603610166919081019061171b565b610578565b6040516101789190611b4f565b60405180910390f35b34801561018d57600080fd5b506101a860048036036101a3919081019061184c565b6106ef565b005b3480156101b657600080fd5b506101d160048036036101cc91908101906116f2565b610bf7565b005b3480156101df57600080fd5b506101fa60048036036101f591908101906117e7565b610c87565b005b34801561020857600080fd5b50610211610de4565b60405161021e9190611b34565b60405180910390f35b34801561023357600080fd5b5061024e600480360361024991908101906117e7565b610e09565b60405161025b9190611bf3565b60405180910390f35b61026c610e2c565b005b34801561027a57600080fd5b5061029560048036036102909190810190611796565b610ec1565b6040516102a29190611b4f565b60405180910390f35b3480156102b757600080fd5b506102d260048036036102cd91908101906119c3565b610f44565b005b3480156102e057600080fd5b506102fb60048036036102f691908101906118c9565b6111ed565b005b34801561030957600080fd5b50610324600480360361031f9190810190611810565b611429565b005b60008060008060068781548110151561033b57fe5b90600052602060002001548660000151141561035a576001935061054b565b868660200151604051602001610371929190611c0e565b6040516020818303038152906040526040518082805190602001908083835b6020831015156103b55780518252602082019150602081019050602083039250610390565b6001836020036101000a03801982511681845116808217855250505050505090500191505060405180910390209250600183876020015160600151886020015160800151896020015160a001516040516000815260200160405260405161041f9493929190611bae565b60206040516020810390808403906000865af1158015610443573d6000803e3d6000fd5b5050506020604051035173ffffffffffffffffffffffffffffffffffffffff1686602001516000015173ffffffffffffffffffffffffffffffffffffffff16141515610492576000935061054b565b600186600001518154811015156104a557fe5b906000526020600020015491508686602001516040516020016104c9929190611c0e565b6040516020818303038152906040526040518082805190602001908083835b60208310151561050d57805182526020820191506020810190506020830392506104e8565b6001836020036101000a0380198251168184511680821785525050505050509050019150506040518091039020905061054881888488610578565b93505b5050509392505050565b60018181548110151561056457fe5b906000526020600020016000915090505481565b600080600080879150602090505b8451811115156106d75780850151925060006002888115156105a457fe5b0614156106365781836040516020016105be929190611b85565b6040516020818303038152906040526040518082805190602001908083835b60208310151561060257805182526020820191506020810190506020830392506105dd565b6001836020036101000a038019825116818451168082178552505050505050905001915050604051809103902091506106bd565b8282604051602001610649929190611b85565b6040516020818303038152906040526040518082805190602001908083835b60208310151561068d5780518252602082019150602081019050602083039250610668565b6001836020036101000a038019825116818451168082178552505050505050905001915050604051809103902091505b6002878115156106c957fe5b049650602081019050610586565b85600019168260001916149350505050949350505050565b6000600160028111156106fe57fe5b6003600087815260200190815260200160002060008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060000160009054906101000a900460ff16600281111561076a57fe5b14151561077657600080fd5b610781858484610326565b151561078c57600080fd5b6003600086815260200190815260200160002060008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002090508260000151816004015410801561080057508260200151604001518160040154145b801561083f575082602001516000015173ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff16145b156108be5760026003600087815260200190815260200160002060008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060000160006101000a81548160ff021916908360028111156108b457fe5b0217905550610bf0565b8260000151816005015410801561092c575082602001516020015173ffffffffffffffffffffffffffffffffffffffff168160030160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16145b801561094357508260200151604001518160050154145b8015610956575080600401548360000151105b156109d55760026003600087815260200190815260200160002060008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060000160006101000a81548160ff021916908360028111156109cb57fe5b0217905550610bef565b6003600086815260200190815260200160002060008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206005015483600001511015610bee57826005600087815260200190815260200160002060008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000856000015181526020019081526020016000206000820151816000015560208201518160010160008201518160000160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555060208201518160010160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055506040820151816002015560608201518160030160006101000a81548160ff021916908360ff1602179055506080820151816004019060001916905560a08201518160050190600019169055505090505060016003600087815260200190815260200160002060008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600201600082825401925050819055505b5b5b5050505050565b6000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16141515610c5257600080fd5b600181908060018154018082558091505090600182039060005260206000200160009091929091909150906000191690555050565b60c06040519081016040528060016002811115610ca057fe5b815260200160644301815260200160008152602001600073ffffffffffffffffffffffffffffffffffffffff168152602001600683815481101515610ce157fe5b9060005260206000200154815260200160008152506003600083815260200190815260200160002060003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008201518160000160006101000a81548160ff02191690836002811115610d6a57fe5b0217905550602082015181600101556040820151816002015560608201518160030160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055506080820151816004015560a0820151816005015590505050565b6000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b600281815481101515610e1857fe5b906000526020600020016000915090505481565b600660018054905090806001815401808255809150509060018203906000526020600020016000909192909190915055506001600060010290806001815401808255809150509060018203906000526020600020016000909192909190915090600019169055506002349080600181540180825580915050906001820390600052602060002001600090919290919091505550565b600082600001518460000151108015610f15575082602001516000015173ffffffffffffffffffffffffffffffffffffffff1684602001516020015173ffffffffffffffffffffffffffffffffffffffff16145b8015610f2c57508260200151604001518460000151145b8015610f3b5750818360000151105b90509392505050565b83602001516020015173ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16141515610f8657600080fd5b610f91858585610326565b1515610f9c57600080fd5b610fa7858383610326565b1515610fb257600080fd5b81602001516020015173ffffffffffffffffffffffffffffffffffffffff1684602001516000015173ffffffffffffffffffffffffffffffffffffffff16141515610ffc57600080fd5b8360000151826000015110151561101257600080fd5b6000600281111561101f57fe5b6003600087815260200190815260200160002060003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060000160009054906101000a900460ff16600281111561108b57fe5b14151561109757600080fd5b60c060405190810160405280600160028111156110b057fe5b81526020016064430181526020016000815260200183602001516020015173ffffffffffffffffffffffffffffffffffffffff1681526020018560000151815260200183600001518152506003600087815260200190815260200160002060003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008201518160000160006101000a81548160ff0219169083600281111561116f57fe5b0217905550602082015181600101556040820151816002015560608201518160030160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055506080820151816004015560a082015181600501559050505050505050565b60006111fa868484610326565b151561120557600080fd5b6005600087815260200190815260200160002060008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600085815260200190815260200160002090506113b481604080519081016040529081600082015481526020016001820160c060405190810160405290816000820160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020016001820160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001600282015481526020016003820160009054906101000a900460ff1660ff1660ff168152602001600482015460001916600019168152602001600582015460001916600019168152505081525050847fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff610ec1565b15156113bf57600080fd5b60016003600088815260200190815260200160002060008773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060020160008282540392505081905550505050505050565b60006003600084815260200190815260200160002060008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002090506001600281111561148a57fe5b8160000160009054906101000a900460ff1660028111156114a757fe5b1415156114b357600080fd5b806001015443101515156114c657600080fd5b600081600201541415156114d957600080fd5b8173ffffffffffffffffffffffffffffffffffffffff166108fc60028581548110151561150257fe5b90600052602060002001549081150290604051600060405180830381858888f19350505050158015611538573d6000803e3d6000fd5b5060028160000160006101000a81548160ff0219169083600281111561155a57fe5b0217905550505050565b60006115708235611cdd565b905092915050565b60006115848235611cfd565b905092915050565b600082601f830112151561159f57600080fd5b81356115b26115ad82611c64565b611c37565b915080825260208301602083018583830111156115ce57600080fd5b6115d9838284611d1e565b50505092915050565b600060e082840312156115f457600080fd5b6115fe6040611c37565b9050600061160e848285016116ca565b60008301525060206116228482850161162e565b60208301525092915050565b600060c0828403121561164057600080fd5b61164a60c0611c37565b9050600061165a84828501611564565b600083015250602061166e84828501611564565b6020830152506040611682848285016116ca565b6040830152506060611696848285016116de565b60608301525060806116aa84828501611578565b60808301525060a06116be84828501611578565b60a08301525092915050565b60006116d68235611d07565b905092915050565b60006116ea8235611d11565b905092915050565b60006020828403121561170457600080fd5b600061171284828501611578565b91505092915050565b6000806000806080858703121561173157600080fd5b600061173f87828801611578565b9450506020611750878288016116ca565b935050604061176187828801611578565b925050606085013567ffffffffffffffff81111561177e57600080fd5b61178a8782880161158c565b91505092959194509250565b60008060006101e084860312156117ac57600080fd5b60006117ba868287016115e2565b93505060e06117cb868287016115e2565b9250506101c06117dd868287016116ca565b9150509250925092565b6000602082840312156117f957600080fd5b6000611807848285016116ca565b91505092915050565b6000806040838503121561182357600080fd5b6000611831858286016116ca565b925050602061184285828601611564565b9150509250929050565b600080600080610140858703121561186357600080fd5b6000611871878288016116ca565b945050602061188287828801611564565b9350506040611893878288016115e2565b92505061012085013567ffffffffffffffff8111156118b157600080fd5b6118bd8782880161158c565b91505092959194509250565b600080600080600061016086880312156118e257600080fd5b60006118f0888289016116ca565b955050602061190188828901611564565b9450506040611912888289016116ca565b9350506060611923888289016115e2565b92505061014086013567ffffffffffffffff81111561194157600080fd5b61194d8882890161158c565b9150509295509295909350565b6000806000610120848603121561197057600080fd5b600061197e868287016116ca565b935050602061198f868287016115e2565b92505061010084013567ffffffffffffffff8111156119ad57600080fd5b6119b98682870161158c565b9150509250925092565b600080600080600061022086880312156119dc57600080fd5b60006119ea888289016116ca565b95505060206119fb888289016115e2565b94505061010086013567ffffffffffffffff811115611a1957600080fd5b611a258882890161158c565b935050610120611a37888289016115e2565b92505061020086013567ffffffffffffffff811115611a5557600080fd5b611a618882890161158c565b9150509295509295909350565b611a7781611c90565b82525050565b611a8681611cb0565b82525050565b611a9581611cbc565b82525050565b60c082016000820151611ab16000850182611a6e565b506020820151611ac46020850182611a6e565b506040820151611ad76040850182611b16565b506060820151611aea6060850182611b25565b506080820151611afd6080850182611a8c565b5060a0820151611b1060a0850182611a8c565b50505050565b611b1f81611cc6565b82525050565b611b2e81611cd0565b82525050565b6000602082019050611b496000830184611a6e565b92915050565b6000602082019050611b646000830184611a7d565b92915050565b6000602082019050611b7f6000830184611a8c565b92915050565b6000604082019050611b9a6000830185611a8c565b611ba76020830184611a8c565b9392505050565b6000608082019050611bc36000830187611a8c565b611bd06020830186611b25565b611bdd6040830185611a8c565b611bea6060830184611a8c565b95945050505050565b6000602082019050611c086000830184611b16565b92915050565b600060e082019050611c236000830185611b16565b611c306020830184611a9b565b9392505050565b6000604051905081810181811067ffffffffffffffff82111715611c5a57600080fd5b8060405250919050565b600067ffffffffffffffff821115611c7b57600080fd5b601f19601f8301169050602081019050919050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b60008115159050919050565b6000819050919050565b6000819050919050565b600060ff82169050919050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b6000819050919050565b6000819050919050565b600060ff82169050919050565b828183376000838301525050505600a265627a7a72305820c1bac3221178846dc25dad447a51b8cfc0c40b0721ad230b03dd802a9516fb416c6578706572696d656e74616cf50037","bin-runtime":"6080604052600436106100c5576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff168063263792c9146100ca57806338def2f5146101075780636c8f455c14610144578063b89820f014610181578063baa47694146101aa578063bc77856a146101d3578063bf7e214f146101fc578063c661065714610227578063d0e30db014610264578063df8a9a671461026e578063e756b6c5146102ab578063eb8b5c30146102d4578063fbbed6d1146102fd575b600080fd5b3480156100d657600080fd5b506100f160048036036100ec919081019061195a565b610326565b6040516100fe9190611b4f565b60405180910390f35b34801561011357600080fd5b5061012e600480360361012991908101906117e7565b610555565b60405161013b9190611b6a565b60405180910390f35b34801561015057600080fd5b5061016b6004803603610166919081019061171b565b610578565b6040516101789190611b4f565b60405180910390f35b34801561018d57600080fd5b506101a860048036036101a3919081019061184c565b6106ef565b005b3480156101b657600080fd5b506101d160048036036101cc91908101906116f2565b610bf7565b005b3480156101df57600080fd5b506101fa60048036036101f591908101906117e7565b610c87565b005b34801561020857600080fd5b50610211610de4565b60405161021e9190611b34565b60405180910390f35b34801561023357600080fd5b5061024e600480360361024991908101906117e7565b610e09565b60405161025b9190611bf3565b60405180910390f35b61026c610e2c565b005b34801561027a57600080fd5b5061029560048036036102909190810190611796565b610ec1565b6040516102a29190611b4f565b60405180910390f35b3480156102b757600080fd5b506102d260048036036102cd91908101906119c3565b610f44565b005b3480156102e057600080fd5b506102fb60048036036102f691908101906118c9565b6111ed565b005b34801561030957600080fd5b50610324600480360361031f9190810190611810565b611429565b005b60008060008060068781548110151561033b57fe5b90600052602060002001548660000151141561035a576001935061054b565b868660200151604051602001610371929190611c0e565b6040516020818303038152906040526040518082805190602001908083835b6020831015156103b55780518252602082019150602081019050602083039250610390565b6001836020036101000a03801982511681845116808217855250505050505090500191505060405180910390209250600183876020015160600151886020015160800151896020015160a001516040516000815260200160405260405161041f9493929190611bae565b60206040516020810390808403906000865af1158015610443573d6000803e3d6000fd5b5050506020604051035173ffffffffffffffffffffffffffffffffffffffff1686602001516000015173ffffffffffffffffffffffffffffffffffffffff16141515610492576000935061054b565b600186600001518154811015156104a557fe5b906000526020600020015491508686602001516040516020016104c9929190611c0e565b6040516020818303038152906040526040518082805190602001908083835b60208310151561050d57805182526020820191506020810190506020830392506104e8565b6001836020036101000a0380198251168184511680821785525050505050509050019150506040518091039020905061054881888488610578565b93505b5050509392505050565b60018181548110151561056457fe5b906000526020600020016000915090505481565b600080600080879150602090505b8451811115156106d75780850151925060006002888115156105a457fe5b0614156106365781836040516020016105be929190611b85565b6040516020818303038152906040526040518082805190602001908083835b60208310151561060257805182526020820191506020810190506020830392506105dd565b6001836020036101000a038019825116818451168082178552505050505050905001915050604051809103902091506106bd565b8282604051602001610649929190611b85565b6040516020818303038152906040526040518082805190602001908083835b60208310151561068d5780518252602082019150602081019050602083039250610668565b6001836020036101000a038019825116818451168082178552505050505050905001915050604051809103902091505b6002878115156106c957fe5b049650602081019050610586565b85600019168260001916149350505050949350505050565b6000600160028111156106fe57fe5b6003600087815260200190815260200160002060008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060000160009054906101000a900460ff16600281111561076a57fe5b14151561077657600080fd5b610781858484610326565b151561078c57600080fd5b6003600086815260200190815260200160002060008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002090508260000151816004015410801561080057508260200151604001518160040154145b801561083f575082602001516000015173ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff16145b156108be5760026003600087815260200190815260200160002060008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060000160006101000a81548160ff021916908360028111156108b457fe5b0217905550610bf0565b8260000151816005015410801561092c575082602001516020015173ffffffffffffffffffffffffffffffffffffffff168160030160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16145b801561094357508260200151604001518160050154145b8015610956575080600401548360000151105b156109d55760026003600087815260200190815260200160002060008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060000160006101000a81548160ff021916908360028111156109cb57fe5b0217905550610bef565b6003600086815260200190815260200160002060008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206005015483600001511015610bee57826005600087815260200190815260200160002060008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000856000015181526020019081526020016000206000820151816000015560208201518160010160008201518160000160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555060208201518160010160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055506040820151816002015560608201518160030160006101000a81548160ff021916908360ff1602179055506080820151816004019060001916905560a08201518160050190600019169055505090505060016003600087815260200190815260200160002060008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600201600082825401925050819055505b5b5b5050505050565b6000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16141515610c5257600080fd5b600181908060018154018082558091505090600182039060005260206000200160009091929091909150906000191690555050565b60c06040519081016040528060016002811115610ca057fe5b815260200160644301815260200160008152602001600073ffffffffffffffffffffffffffffffffffffffff168152602001600683815481101515610ce157fe5b9060005260206000200154815260200160008152506003600083815260200190815260200160002060003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008201518160000160006101000a81548160ff02191690836002811115610d6a57fe5b0217905550602082015181600101556040820151816002015560608201518160030160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055506080820151816004015560a0820151816005015590505050565b6000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b600281815481101515610e1857fe5b906000526020600020016000915090505481565b600660018054905090806001815401808255809150509060018203906000526020600020016000909192909190915055506001600060010290806001815401808255809150509060018203906000526020600020016000909192909190915090600019169055506002349080600181540180825580915050906001820390600052602060002001600090919290919091505550565b600082600001518460000151108015610f15575082602001516000015173ffffffffffffffffffffffffffffffffffffffff1684602001516020015173ffffffffffffffffffffffffffffffffffffffff16145b8015610f2c57508260200151604001518460000151145b8015610f3b5750818360000151105b90509392505050565b83602001516020015173ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16141515610f8657600080fd5b610f91858585610326565b1515610f9c57600080fd5b610fa7858383610326565b1515610fb257600080fd5b81602001516020015173ffffffffffffffffffffffffffffffffffffffff1684602001516000015173ffffffffffffffffffffffffffffffffffffffff16141515610ffc57600080fd5b8360000151826000015110151561101257600080fd5b6000600281111561101f57fe5b6003600087815260200190815260200160002060003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060000160009054906101000a900460ff16600281111561108b57fe5b14151561109757600080fd5b60c060405190810160405280600160028111156110b057fe5b81526020016064430181526020016000815260200183602001516020015173ffffffffffffffffffffffffffffffffffffffff1681526020018560000151815260200183600001518152506003600087815260200190815260200160002060003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008201518160000160006101000a81548160ff0219169083600281111561116f57fe5b0217905550602082015181600101556040820151816002015560608201518160030160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055506080820151816004015560a082015181600501559050505050505050565b60006111fa868484610326565b151561120557600080fd5b6005600087815260200190815260200160002060008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600085815260200190815260200160002090506113b481604080519081016040529081600082015481526020016001820160c060405190810160405290816000820160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020016001820160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001600282015481526020016003820160009054906101000a900460ff1660ff1660ff168152602001600482015460001916600019168152602001600582015460001916600019168152505081525050847fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff610ec1565b15156113bf57600080fd5b60016003600088815260200190815260200160002060008773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060020160008282540392505081905550505050505050565b60006003600084815260200190815260200160002060008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002090506001600281111561148a57fe5b8160000160009054906101000a900460ff1660028111156114a757fe5b1415156114b357600080fd5b806001015443101515156114c657600080fd5b600081600201541415156114d957600080fd5b8173ffffffffffffffffffffffffffffffffffffffff166108fc60028581548110151561150257fe5b90600052602060002001549081150290604051600060405180830381858888f19350505050158015611538573d6000803e3d6000fd5b5060028160000160006101000a81548160ff0219169083600281111561155a57fe5b0217905550505050565b60006115708235611cdd565b905092915050565b60006115848235611cfd565b905092915050565b600082601f830112151561159f57600080fd5b81356115b26115ad82611c64565b611c37565b915080825260208301602083018583830111156115ce57600080fd5b6115d9838284611d1e565b50505092915050565b600060e082840312156115f457600080fd5b6115fe6040611c37565b9050600061160e848285016116ca565b60008301525060206116228482850161162e565b60208301525092915050565b600060c0828403121561164057600080fd5b61164a60c0611c37565b9050600061165a84828501611564565b600083015250602061166e84828501611564565b6020830152506040611682848285016116ca565b6040830152506060611696848285016116de565b60608301525060806116aa84828501611578565b60808301525060a06116be84828501611578565b60a08301525092915050565b60006116d68235611d07565b905092915050565b60006116ea8235611d11565b905092915050565b60006020828403121561170457600080fd5b600061171284828501611578565b91505092915050565b6000806000806080858703121561173157600080fd5b600061173f87828801611578565b9450506020611750878288016116ca565b935050604061176187828801611578565b925050606085013567ffffffffffffffff81111561177e57600080fd5b61178a8782880161158c565b91505092959194509250565b60008060006101e084860312156117ac57600080fd5b60006117ba868287016115e2565b93505060e06117cb868287016115e2565b9250506101c06117dd868287016116ca565b9150509250925092565b6000602082840312156117f957600080fd5b6000611807848285016116ca565b91505092915050565b6000806040838503121561182357600080fd5b6000611831858286016116ca565b925050602061184285828601611564565b9150509250929050565b600080600080610140858703121561186357600080fd5b6000611871878288016116ca565b945050602061188287828801611564565b9350506040611893878288016115e2565b92505061012085013567ffffffffffffffff8111156118b157600080fd5b6118bd8782880161158c565b91505092959194509250565b600080600080600061016086880312156118e257600080fd5b60006118f0888289016116ca565b955050602061190188828901611564565b9450506040611912888289016116ca565b9350506060611923888289016115e2565b92505061014086013567ffffffffffffffff81111561194157600080fd5b61194d8882890161158c565b9150509295509295909350565b6000806000610120848603121561197057600080fd5b600061197e868287016116ca565b935050602061198f868287016115e2565b92505061010084013567ffffffffffffffff8111156119ad57600080fd5b6119b98682870161158c565b9150509250925092565b600080600080600061022086880312156119dc57600080fd5b60006119ea888289016116ca565b95505060206119fb888289016115e2565b94505061010086013567ffffffffffffffff811115611a1957600080fd5b611a258882890161158c565b935050610120611a37888289016115e2565b92505061020086013567ffffffffffffffff811115611a5557600080fd5b611a618882890161158c565b9150509295509295909350565b611a7781611c90565b82525050565b611a8681611cb0565b82525050565b611a9581611cbc565b82525050565b60c082016000820151611ab16000850182611a6e565b506020820151611ac46020850182611a6e565b506040820151611ad76040850182611b16565b506060820151611aea6060850182611b25565b506080820151611afd6080850182611a8c565b5060a0820151611b1060a0850182611a8c565b50505050565b611b1f81611cc6565b82525050565b611b2e81611cd0565b82525050565b6000602082019050611b496000830184611a6e565b92915050565b6000602082019050611b646000830184611a7d565b92915050565b6000602082019050611b7f6000830184611a8c565b92915050565b6000604082019050611b9a6000830185611a8c565b611ba76020830184611a8c565b9392505050565b6000608082019050611bc36000830187611a8c565b611bd06020830186611b25565b611bdd6040830185611a8c565b611bea6060830184611a8c565b95945050505050565b6000602082019050611c086000830184611b16565b92915050565b600060e082019050611c236000830185611b16565b611c306020830184611a9b565b9392505050565b6000604051905081810181811067ffffffffffffffff82111715611c5a57600080fd5b8060405250919050565b600067ffffffffffffffff821115611c7b57600080fd5b601f19601f8301169050602081019050919050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b60008115159050919050565b6000819050919050565b6000819050919050565b600060ff82169050919050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b6000819050919050565b6000819050919050565b600060ff82169050919050565b828183376000838301525050505600a265627a7a72305820c1bac3221178846dc25dad447a51b8cfc0c40b0721ad230b03dd802a9516fb416c6578706572696d656e74616cf50037"}},"version":"0.4.25+commit.59dbf8f1.Darwin.appleclang"} 2 | -------------------------------------------------------------------------------- /requirements.txt: -------------------------------------------------------------------------------- 1 | bitcoin 2 | ethereum 3 | -------------------------------------------------------------------------------- /rootchain_abi.py: -------------------------------------------------------------------------------- 1 | #!./venv/bin/python3 2 | 3 | import json 4 | 5 | with open("contracts.json") as f: 6 | rootchain = json.loads(f.read())['contracts']['RootChain.sol:RootChain']['abi'] 7 | rootchain = json.loads(rootchain) 8 | 9 | functions = dict() 10 | 11 | for elem in rootchain: 12 | if elem['type'] == 'function': 13 | functions[elem['name']] = elem 14 | elif elem['type'] == 'constructor': 15 | functions['constructor'] = elem 16 | 17 | def decode_input(inp): 18 | if inp['type'] == 'tuple': 19 | return "(" + ",".join(decode_input(component) for component in inp['components']) + ")" 20 | else: 21 | return inp['type'] 22 | 23 | def decode_inputs(fn): 24 | return "(" + ",".join(decode_input(inp) for inp in fn['inputs']) + ")" 25 | -------------------------------------------------------------------------------- /smt.py: -------------------------------------------------------------------------------- 1 | import sha3 2 | 3 | def short_keccak256(x): 4 | k = sha3.keccak_256() 5 | k.update(x) 6 | return k.digest()[0:1] 7 | 8 | def bl(x): 9 | k = short_keccak256(x) 10 | k = int.from_bytes(k, 'big') 11 | return "{0:b}".format(k) 12 | 13 | print(bl(b'')) 14 | print(bl(b'a')) 15 | 16 | # def smt(depth, elems) -------------------------------------------------------------------------------- /test.py: -------------------------------------------------------------------------------- 1 | #!./venv/bin/python3 2 | 3 | import binascii 4 | import bitcoin 5 | import ethereum 6 | 7 | import eth_abi 8 | 9 | from ethereum.tools import tester 10 | from ethereum.tools._solidity import get_solidity 11 | 12 | import rootchain_abi 13 | 14 | def sign(h, priv): 15 | assert len(h) == 32 16 | V, R, S = bitcoin.ecdsa_raw_sign(h, priv) 17 | return V,R,S 18 | 19 | c = tester.Chain() 20 | 21 | with open('./RootChain.sol') as f: 22 | code = f.read() 23 | 24 | RootChain = c.contract( 25 | sourcecode=code, # todo: better error message if a list of lines is passed 26 | language="solidity" 27 | ) 28 | 29 | assert(RootChain.authority(sender=tester.k1) == f"0x{tester.a0.hex()}") 30 | 31 | RootChain.deposit(sender=tester.k1, value=5) 32 | 33 | c.mine() # bump gas limit 34 | 35 | assert(RootChain.coins(0) == 5) 36 | 37 | deposit_block = RootChain.childBlockRoots(0) 38 | 39 | def Transfer(*args): return tuple(args) 40 | def IncludedTransfer(*args): return tuple(args) 41 | 42 | startExitSig = rootchain_abi.decode_inputs(rootchain_abi.functions['startExit']) 43 | selector = ethereum.utils.sha3("startExit" + startExitSig)[0:4] 44 | 45 | myAddr = tester.a1 46 | 47 | it = IncludedTransfer( 48 | 0, 49 | Transfer( 50 | myAddr, myAddr, 0, 0, b"", b"" 51 | ) 52 | ) 53 | calldata = selector + eth_abi.encode_single(startExitSig, (0, it, b"", it, b"")) 54 | 55 | # print(RootChain.startExit(data=calldata, sender=tester.k1)) 56 | --------------------------------------------------------------------------------