From 7e6a2626a3573dbf4372aca7df008dcae8e943f6 Mon Sep 17 00:00:00 2001 From: youwenbusi <1245549353@qq.com> Date: Wed, 19 Aug 2020 11:07:34 +0800 Subject: [PATCH] support multi-tree --- api/zeth_messages_pb2.py | 10 +++--- api/zeth_messages_pb2.pyi | 8 ++--- commands/constants.py | 12 +++++-- commands/event_sync.py | 48 ++++++++++++++++++--------- commands/utils.py | 6 ++-- commands/zeth_deploy.py | 5 +-- commands/zeth_deposit.py | 15 ++++++--- commands/zeth_ls_notes.py | 2 +- commands/zeth_mix.py | 20 ++++++++--- contract/Groth16Mixer.abi | 2 +- contract/Groth16Mixer.bin | 2 +- contract/Groth16Mixer.py | 13 ++++++-- zeth/constants.py | 2 +- zeth/contracts.py | 5 +-- zeth/merkle_tree.py | 24 ++++++++------ zeth/mixer_client.py | 38 ++++++++++++--------- zeth/wallet.py | 70 +++++++++++++++++++++++---------------- zkclientapp/models.py | 2 +- zkclientapp/routes.py | 57 +++++++++++++++---------------- zkclientapp/urls.py | 2 +- 20 files changed, 211 insertions(+), 132 deletions(-) diff --git a/api/zeth_messages_pb2.py b/api/zeth_messages_pb2.py index 637b1ee..47dfe66 100644 --- a/api/zeth_messages_pb2.py +++ b/api/zeth_messages_pb2.py @@ -20,7 +20,7 @@ package='zeth_proto', syntax='proto3', serialized_options=None, - serialized_pb=_b('\n\x17\x61pi/zeth_messages.proto\x12\nzeth_proto\"C\n\x08ZethNote\x12\x0b\n\x03\x61pk\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t\x12\x0b\n\x03rho\x18\x03 \x01(\t\x12\x0e\n\x06trap_r\x18\x04 \x01(\t\"\x83\x01\n\x0eJoinsplitInput\x12\x13\n\x0bmerkle_path\x18\x01 \x03(\t\x12\x0f\n\x07\x61\x64\x64ress\x18\x02 \x01(\x03\x12\"\n\x04note\x18\x03 \x01(\x0b\x32\x14.zeth_proto.ZethNote\x12\x14\n\x0cspending_ask\x18\x04 \x01(\t\x12\x11\n\tnullifier\x18\x05 \x01(\t\"\xc0\x01\n\x0bProofInputs\x12\x0f\n\x07mk_root\x18\x01 \x01(\t\x12-\n\tjs_inputs\x18\x02 \x03(\x0b\x32\x1a.zeth_proto.JoinsplitInput\x12(\n\njs_outputs\x18\x03 \x03(\x0b\x32\x14.zeth_proto.ZethNote\x12\x14\n\x0cpub_in_value\x18\x04 \x01(\t\x12\x15\n\rpub_out_value\x18\x05 \x01(\t\x12\r\n\x05h_sig\x18\x06 \x01(\t\x12\x0b\n\x03phi\x18\x07 \x01(\tb\x06proto3') + serialized_pb=_b('\n\x17\x61pi/zeth_messages.proto\x12\nzeth_proto\"C\n\x08ZethNote\x12\x0b\n\x03\x61pk\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t\x12\x0b\n\x03rho\x18\x03 \x01(\t\x12\x0e\n\x06trap_r\x18\x04 \x01(\t\"\x83\x01\n\x0eJoinsplitInput\x12\x13\n\x0bmerkle_path\x18\x01 \x03(\t\x12\x0f\n\x07\x61\x64\x64ress\x18\x02 \x01(\x03\x12\"\n\x04note\x18\x03 \x01(\x0b\x32\x14.zeth_proto.ZethNote\x12\x14\n\x0cspending_ask\x18\x04 \x01(\t\x12\x11\n\tnullifier\x18\x05 \x01(\t\"\xc1\x01\n\x0bProofInputs\x12\x10\n\x08mk_roots\x18\x01 \x03(\t\x12-\n\tjs_inputs\x18\x02 \x03(\x0b\x32\x1a.zeth_proto.JoinsplitInput\x12(\n\njs_outputs\x18\x03 \x03(\x0b\x32\x14.zeth_proto.ZethNote\x12\x14\n\x0cpub_in_value\x18\x04 \x01(\t\x12\x15\n\rpub_out_value\x18\x05 \x01(\t\x12\r\n\x05h_sig\x18\x06 \x01(\t\x12\x0b\n\x03phi\x18\x07 \x01(\tb\x06proto3') ) @@ -145,9 +145,9 @@ containing_type=None, fields=[ _descriptor.FieldDescriptor( - name='mk_root', full_name='zeth_proto.ProofInputs.mk_root', index=0, - number=1, type=9, cpp_type=9, label=1, - has_default_value=False, default_value=_b("").decode('utf-8'), + name='mk_roots', full_name='zeth_proto.ProofInputs.mk_roots', index=0, + number=1, type=9, cpp_type=9, label=3, + has_default_value=False, default_value=[], message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, serialized_options=None, file=DESCRIPTOR), @@ -206,7 +206,7 @@ oneofs=[ ], serialized_start=243, - serialized_end=435, + serialized_end=436, ) _JOINSPLITINPUT.fields_by_name['note'].message_type = _ZETHNOTE diff --git a/api/zeth_messages_pb2.pyi b/api/zeth_messages_pb2.pyi index bf84520..81280eb 100644 --- a/api/zeth_messages_pb2.pyi +++ b/api/zeth_messages_pb2.pyi @@ -84,7 +84,7 @@ class JoinsplitInput(google___protobuf___message___Message): class ProofInputs(google___protobuf___message___Message): DESCRIPTOR: google___protobuf___descriptor___Descriptor = ... - mk_root = ... # type: typing___Text + mk_roots = ... # type: google___protobuf___internal___containers___RepeatedScalarFieldContainer[typing___Text] pub_in_value = ... # type: typing___Text pub_out_value = ... # type: typing___Text h_sig = ... # type: typing___Text @@ -98,7 +98,7 @@ class ProofInputs(google___protobuf___message___Message): def __init__(self, *, - mk_root : typing___Optional[typing___Text] = None, + mk_roots : typing___Optional[typing___Iterable[typing___Text]] = None, js_inputs : typing___Optional[typing___Iterable[JoinsplitInput]] = None, js_outputs : typing___Optional[typing___Iterable[ZethNote]] = None, pub_in_value : typing___Optional[typing___Text] = None, @@ -111,6 +111,6 @@ class ProofInputs(google___protobuf___message___Message): def MergeFrom(self, other_msg: google___protobuf___message___Message) -> None: ... def CopyFrom(self, other_msg: google___protobuf___message___Message) -> None: ... if sys.version_info >= (3,): - def ClearField(self, field_name: typing_extensions___Literal[u"h_sig",u"js_inputs",u"js_outputs",u"mk_root",u"phi",u"pub_in_value",u"pub_out_value"]) -> None: ... + def ClearField(self, field_name: typing_extensions___Literal[u"h_sig",u"js_inputs",u"js_outputs",u"mk_roots",u"phi",u"pub_in_value",u"pub_out_value"]) -> None: ... else: - def ClearField(self, field_name: typing_extensions___Literal[u"h_sig",b"h_sig",u"js_inputs",b"js_inputs",u"js_outputs",b"js_outputs",u"mk_root",b"mk_root",u"phi",b"phi",u"pub_in_value",b"pub_in_value",u"pub_out_value",b"pub_out_value"]) -> None: ... + def ClearField(self, field_name: typing_extensions___Literal[u"h_sig",b"h_sig",u"js_inputs",b"js_inputs",u"js_outputs",b"js_outputs",u"mk_roots",b"mk_roots",u"phi",b"phi",u"pub_in_value",b"pub_in_value",u"pub_out_value",b"pub_out_value"]) -> None: ... diff --git a/commands/constants.py b/commands/constants.py index b6122a3..2c25910 100644 --- a/commands/constants.py +++ b/commands/constants.py @@ -8,7 +8,7 @@ """ FISCO_RPC_ENDPOINT_DEFAULT = "http://119.23.46.126:8545" -PROVER_SERVER_ENDPOINT_DEFAULT = "139.9.222.236:50051" +PROVER_SERVER_ENDPOINT_DEFAULT = "116.85.72.123:50051" FISCO_ADDRESS_FILE = "fisco_account.keystore" ADDRESS_FILE_DEFAULT = "zeth-address.json" @@ -19,8 +19,16 @@ WALLET_USERNAME = "zbac" USER_DIR = "user" +""" DATABASE_DEFAULT_ADDRESS = "39.108.248.156" DATABASE_DEFAULT_PORT = 3306 DATABASE_DEFAULT_USER = "root" -DATABASE_DEFAULT_PASSWORD = "xBj2019" +DATABASE_DEFAULT_PASSWORD = "******" DATABASE_DEFAULT_DATABASE = "zkclient" +""" + +DATABASE_DEFAULT_ADDRESS = "127.0.0.1" +DATABASE_DEFAULT_PORT = 3306 +DATABASE_DEFAULT_USER = "root" +DATABASE_DEFAULT_PASSWORD = "8614" +DATABASE_DEFAULT_DATABASE = "merkletree" \ No newline at end of file diff --git a/commands/event_sync.py b/commands/event_sync.py index db62e9b..c6f7584 100644 --- a/commands/event_sync.py +++ b/commands/event_sync.py @@ -16,6 +16,9 @@ from python_web3.client.event_callback import EventCallbackHandler from zeth.contracts import _event_args_to_mix_result from zeth.wallet import Wallet +from zeth.merkle_tree import sqlMerkleTree +from zeth.constants import ZETH_MERKLE_TREE_DEPTH +import math ''' def usage(): @@ -51,16 +54,18 @@ def usage(): class LogMixEvent(object): def __init__( self, + mid: int, root: bytes, nullifiers: bytes(2), commitments: bytes(2), ciphertexts: bytes(2)): + self.mid = mid self.root = root self.nullifiers = nullifiers self.commitments = commitments self.ciphertexts = ciphertexts -def make_wallet() -> List[Wallet]: +def make_wallet(mid: int, next_addr: int) -> List[Wallet]: ''' Return all the wallet in local server ''' @@ -68,7 +73,7 @@ def make_wallet() -> List[Wallet]: for username in os.listdir(USER_DIR): wallet_dir = "{}/{}/{}".format(USER_DIR, username, WALLET_DIR_DEFAULT) zeth_address = load_zeth_address(username) - wallet_list.append(Wallet(None, username, wallet_dir, zeth_address.addr_sk)) + wallet_list.append(Wallet(None, username, wallet_dir, zeth_address.addr_sk, mid, next_addr)) return wallet_list class EventCallbackImpl(EventCallbackHandler): @@ -85,25 +90,39 @@ def on_event(self, eventdata): logresult = self.abiparser.parse_event_logs(eventdata["logs"]) print("--------------------EventCallbackImpl--------------------\n") blockNumber = eventdata["logs"][0]['blockNumber'] + print("the blockNumber in log is :", blockNumber) logMix = logresult[0]['eventdata'] - logMixEvent = LogMixEvent(logMix[0],logMix[1], logMix[2], logMix[3]) + logMixEvent = LogMixEvent(logMix[0],logMix[1], logMix[2], logMix[3], logMix[4]) mix_result = _event_args_to_mix_result(logMixEvent) + mid = mix_result.mid + # load merkletree from database + merkle_tree = sqlMerkleTree.open(int(math.pow(2, ZETH_MERKLE_TREE_DEPTH)), mid) + #print("init root: ", merkle_tree.get_root()) + # check merkel root whether is new or not new_merkle_root = mix_result.new_merkle_root - print("new_merkle_root in log: ", new_merkle_root) - for wallet in make_wallet(): - # check merkel root - if new_merkle_root==wallet.merkle_tree.get_root(): - return + print("new_merkle_roots in log: ", new_merkle_root) + if new_merkle_root == merkle_tree.get_root(): + return + + # get the next_address of updated tree + next_addr = merkle_tree.get_num_entries() + + # update each merkletree + for out_ev in mix_result.output_events: + print("commitment: ", out_ev.commitment) + merkle_tree.insert(out_ev.commitment) + merkle_tree.recompute_root() + merkle_tree.save(blockNumber,mid) + print(f"The update_merkle_root of {mid} is {merkle_tree.get_root()}") + + # update each user's wallet + for wallet in make_wallet(mid, next_addr): # received_notes - wallet.blockNumber = blockNumber - print("blockNumber:", blockNumber) wallet.receive_notes(mix_result.output_events) spent_commits = wallet.mark_nullifiers_used(mix_result.nullifiers) for commit in spent_commits: print(f"{wallet.username} spent commits: {commit}") wallet.update_and_save_state() - update_merkle_root = wallet.merkle_tree.get_root() - print(f"The update_merkle_root in wallet of {wallet.username} is {update_merkle_root}") @command() @@ -127,11 +146,12 @@ def event_sync(mixer_addr: str): eventcallback = EventCallbackImpl() eventcallback.abiparser = abiparser blockNumber = 0 + # maybe change to use cursor.lastrowid to get the last row sqlSearch = "select * from merkletree" cursor.execute(sqlSearch) results = cursor.fetchall() if results: - blockNumber = results[0][2] + blockNumber = results[-1][2] print("blockNumber: ", blockNumber) result = bcos_event.register_eventlog_filter( eventcallback, abiparser, [mixer_addr], "LogMix", indexed_value, str(blockNumber+1)) @@ -148,12 +168,10 @@ def event_sync(mixer_addr: str): print("Exception!") import traceback traceback.print_exc() - db.close() finally: print("event callback finished!") if bcos_event.client is not None: bcos_event.client.finish() - db.close() sys.exit(-1) diff --git a/commands/utils.py b/commands/utils.py index 8c78ae9..22ee606 100644 --- a/commands/utils.py +++ b/commands/utils.py @@ -165,13 +165,15 @@ def load_zeth_address(username: str) -> ZethAddress: def open_wallet( mixer_instance: Any, js_secret: ZethAddressPriv, - username: str + username: str, + mids: List[int], + next_addrs: List[int] ) -> Wallet: """ Load a wallet using a secret key. """ wallet_dir = "{}/{}/{}".format(USER_DIR, username, WALLET_DIR_DEFAULT) - return Wallet(mixer_instance, username, wallet_dir, js_secret) + return Wallet(mixer_instance, username, wallet_dir, js_secret, mids, next_addrs) def do_sync( diff --git a/commands/zeth_deploy.py b/commands/zeth_deploy.py index 3a1b566..a4889e5 100644 --- a/commands/zeth_deploy.py +++ b/commands/zeth_deploy.py @@ -50,8 +50,9 @@ def deploy( bin = f1.read() f1.close() ''' - abi = [{"inputs": [{"internalType": "uint256", "name": "mk_depth", "type": "uint256"}, {"internalType": "address", "name": "token", "type": "address"}, {"internalType": "uint256[2]", "name": "Alpha", "type": "uint256[2]"}, {"internalType": "uint256[2]", "name": "Beta1", "type": "uint256[2]"}, {"internalType": "uint256[2]", "name": "Beta2", "type": "uint256[2]"}, {"internalType": "uint256[2]", "name": "Delta1", "type": "uint256[2]"}, {"internalType": "uint256[2]", "name": "Delta2", "type": "uint256[2]"}, {"internalType": "uint256[]", "name": "ABC_coords", "type": "uint256[]"}], "payable": False, "stateMutability": "nonpayable", "type": "constructor"}, {"anonymous": False, "inputs": [{"indexed": False, "internalType": "string", "name": "message", "type": "string"}], "name": "LogDebug", "type": "event"}, {"anonymous": False, "inputs": [{"indexed": False, "internalType": "bytes32", "name": "message", "type": "bytes32"}], "name": "LogDebug", "type": "event"}, {"anonymous": False, "inputs": [{"indexed": False, "internalType": "bytes32", "name": "root", "type": "bytes32"}, {"indexed": False, "internalType": "bytes32[2]", "name": "nullifiers", "type": "bytes32[2]"}, {"indexed": False, "internalType": "bytes32[2]", "name": "commitments", "type": "bytes32[2]"}, {"indexed": False, "internalType": "bytes[2]", "name": "ciphertexts", "type": "bytes[2]"}], "name": "LogMix", "type": "event"}, {"constant": True, "inputs": [{"internalType": "uint256[9]", "name": "primary_inputs", "type": "uint256[9]"}], "name": "assemble_hsig", "outputs": [{"internalType": "bytes32", "name": "hsig", "type": "bytes32"}], "payable": False, "stateMutability": "pure", "type": "function"}, {"constant": True, "inputs": [{"internalType": "uint256", "name": "index", "type": "uint256"}, {"internalType": "uint256[9]", "name": "primary_inputs", "type": "uint256[9]"}], "name": "assemble_nullifier", "outputs": [{"internalType": "bytes32", "name": "nf", "type": "bytes32"}], "payable": False, "stateMutability": "pure", "type": "function"}, {"constant": True, "inputs": [{"internalType": "uint256[9]", "name": "primary_inputs", "type": "uint256[9]"}], "name": "assemble_public_values", "outputs": [{"internalType": "uint256", "name": "vpub_in", "type": "uint256"}, {"internalType": "uint256", "name": "vpub_out", "type": "uint256"}], "payable": False, "stateMutability": "pure", "type": "function"}, {"constant": True, "inputs": [], "name": "get_constants", "outputs": [{"internalType": "uint256", "name": "js_in", "type": "uint256"}, {"internalType": "uint256", "name": "js_out", "type": "uint256"}, {"internalType": "uint256", "name": "num_inputs", "type": "uint256"}], "payable": False, "stateMutability": "pure", "type": "function"}, {"constant": False, "inputs": [{"internalType": "bytes32", "name": "commitment", "type": "bytes32"}], "name": "insert", "outputs": [], "payable": False, "stateMutability": "nonpayable", "type": "function"}, {"constant": False, "inputs": [{"internalType": "uint256[2]", "name": "a", "type": "uint256[2]"}, {"internalType": "uint256[4]", "name": "b", "type": "uint256[4]"}, {"internalType": "uint256[2]", "name": "c", "type": "uint256[2]"}, {"internalType": "uint256[4]", "name": "vk", "type": "uint256[4]"}, {"internalType": "uint256", "name": "sigma", "type": "uint256"}, {"internalType": "uint256[9]", "name": "input", "type": "uint256[9]"}, {"internalType": "bytes[2]", "name": "ciphertexts", "type": "bytes[2]"}], "name": "mix", "outputs": [], "payable": True, "stateMutability": "payable", "type": "function"}, {"constant": False, "inputs": [{"internalType": "address", "name": "", "type": "address"}, {"internalType": "address", "name": "", "type": "address"}, {"internalType": "uint256", "name": "", "type": "uint256"}, {"internalType": "bytes", "name": "", "type": "bytes"}], "name": "onBAC001Received", "outputs": [{"internalType": "bytes4", "name": "", "type": "bytes4"}], "payable": False, "stateMutability": "nonpayable", "type": "function"}, {"constant": True, "inputs": [], "name": "token", "outputs": [{"internalType": "address", "name": "", "type": "address"}], "payable": False, "stateMutability": "view", "type": "function"}] - binstr = "60806040523480156200001157600080fd5b506040516200364e3803806200364e833981810160405262000037919081019062000685565b878781806005811462000081576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016200007890620008ba565b60405180910390fd5b50620000926200040360201b60201c565b506000806000603f8110620000a357fe5b0154905060016040600083815260200190815260200160002060006101000a81548160ff02191690831515021790555081604260006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555061010060fd106200015c576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401620001539062000876565b60405180910390fd5b60fd6002800260010160fd610100030260406002020110620001b5576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401620001ac9062000898565b60405180910390fd5b505050604051806040016040528087600060028110620001d157fe5b6020020151815260200187600160028110620001e957fe5b6020020151815250604360000160008201518160000155602082015181600101559050506040518060800160405280866000600281106200022657fe5b60200201518152602001866001600281106200023e57fe5b60200201518152602001856000600281106200025657fe5b60200201518152602001856001600281106200026e57fe5b6020020151815250604360020160008201518160000155602082015181600101556040820151816002015560608201518160030155905050604051806080016040528084600060028110620002bf57fe5b6020020151815260200184600160028110620002d757fe5b6020020151815260200183600060028110620002ef57fe5b60200201518152602001836001600281106200030757fe5b602002015181525060436006016000820151816000015560208201518160010155604082015181600201556060820151816003015590505060008090505b60028251816200035157fe5b046043600a018054905014620003f4576043600a0160405180604001604052808484815181106200037e57fe5b602002602001015181526020018460018501815181106200039b57fe5b602002602001015181525090806001815401808255809150509060018203906000526020600020906002020160009091929091909150600082015181600001556020820151816001015550505060028101905062000345565b505050505050505050620009d9565b60008060001b90508060006002600560020a60020203603f81106200042457fe5b018190555060006002600560020a816200043a57fe5b0490505b600081111562000495576200045f82836200049960201b620014e31760201c565b9150600060028260020203905082600082603f81106200047b57fe5b0181905550600282816200048b57fe5b049150506200043e565b5050565b60007fdec937b7fa8db3de380427a8cc947bfab68514522c3439cfa2e99655098368146000527f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f00000018284828282088381820984858383098683840909925060005b605a8112156200053457602060002080600052868688838808089350868485099250868488858a8788090909945050600181019050620004f9565b508484868a8888880808089550505050505092915050565b6000815190506200055d81620009a5565b92915050565b600082601f8301126200057557600080fd5b60026200058c62000586826200090a565b620008dc565b91508183856020840282011115620005a357600080fd5b60005b83811015620005d75781620005bc88826200066e565b845260208401935060208301925050600181019050620005a6565b5050505092915050565b600082601f830112620005f357600080fd5b81516200060a62000604826200092d565b620008dc565b915081818352602084019350602081019050838560208402820111156200063057600080fd5b60005b838110156200066457816200064988826200066e565b84526020840193506020830192505060018101905062000633565b5050505092915050565b6000815190506200067f81620009bf565b92915050565b6000806000806000806000806101a0898b031215620006a357600080fd5b6000620006b38b828c016200066e565b9850506020620006c68b828c016200054c565b9750506040620006d98b828c0162000563565b9650506080620006ec8b828c0162000563565b95505060c0620006ff8b828c0162000563565b945050610100620007138b828c0162000563565b935050610140620007278b828c0162000563565b92505061018089015167ffffffffffffffff8111156200074657600080fd5b620007548b828c01620005e1565b9150509295985092959890939650565b600062000773602d8362000956565b91507f41206861736820646967657374206669747320696e20612073696e676c65206660008301527f69656c6420656c656d656e742e000000000000000000000000000000000000006020830152604082019050919050565b6000620007db602b8362000956565b91507f546f6f206d616e7920696e70757420616e64206f7574707574206e6f7465732060008301527f636f6e736964657265642e0000000000000000000000000000000000000000006020830152604082019050919050565b600062000843601f8362000956565b91507f496e76616c696420646570746820696e20426173654d65726b6c6554726565006000830152602082019050919050565b60006020820190508181036000830152620008918162000764565b9050919050565b60006020820190508181036000830152620008b381620007cc565b9050919050565b60006020820190508181036000830152620008d58162000834565b9050919050565b6000604051905081810181811067ffffffffffffffff821117156200090057600080fd5b8060405250919050565b600067ffffffffffffffff8211156200092257600080fd5b602082029050919050565b600067ffffffffffffffff8211156200094557600080fd5b602082029050602081019050919050565b600082825260208201905092915050565b600062000974826200097b565b9050919050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b6000819050919050565b620009b08162000967565b8114620009bc57600080fd5b50565b620009ca816200099b565b8114620009d657600080fd5b50565b612c6580620009e96000396000f3fe60806040526004361061007b5760003560e01c806397e004891161004e57806397e0048914610161578063c73d16ae1461017d578063f9eb943f146101ba578063fc0c546a146101e75761007b565b806305ceb93c146100805780631f40927c146100bd5780632d287e43146100fb578063354d06fd14610124575b600080fd5b34801561008c57600080fd5b506100a760048036036100a29190810190611aaf565b610212565b6040516100b491906125c9565b60405180910390f35b3480156100c957600080fd5b506100e460048036036100df9190810190611a33565b610332565b6040516100f292919061282b565b60405180910390f35b34801561010757600080fd5b50610122600480360361011d9190810190611a5d565b6103af565b005b34801561013057600080fd5b5061014b60048036036101469190810190611a33565b610434565b60405161015891906125c9565b60405180910390f35b61017b60048036036101769190810190611978565b6104b2565b005b34801561018957600080fd5b506101a4600480360361019f91908101906118fd565b6106d4565b6040516101b19190612630565b60405180910390f35b3480156101c657600080fd5b506101cf6106e8565b6040516101de93929190612854565b60405180910390f35b3480156101f357600080fd5b506101fc61070c565b6040516102099190612528565b60405180910390f35b600060028310610257576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161024e9061264b565b60405180910390fd5b600060fd610100038460010102604060020201905060fd61010003810160fd10156102b7576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016102ae906126eb565b60405180910390fd5b600060fd826002800260010160fd610100030260406002020161010003018560028002600101600260010101600981106102ed57fe5b602002015160001b901b901c9050600060fd6101000385876002600101016009811061031557fe5b6020020151901b90508160001c810160001b935050505092915050565b600080600083600280026001016002600101016009811061034f57fe5b602002015190506002800260010160fd610100030281901c905064e8d4a5100067ffffffffffffffff168167ffffffffffffffff1602915064e8d4a5100067ffffffffffffffff16604082901c67ffffffffffffffff1602925050915091565b600560020a603f54106103f7576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016103ee906126cb565b60405180910390fd5b6000603f549050603f60008154600101919050819055506000816001600560020a0301905082600082603f811061042a57fe5b0181905550505050565b60008060fd60406002026002800260010160fd6101000302604060020201610100030184600280026001016002600101016009811061046f57fe5b602002015160001b901b901c9050600060fd6101000384600280600101016009811061049757fe5b6020020151901b90508160001c810160001b92505050919050565b6104ba611594565b6104c5858483610732565b600060023373ffffffffffffffffffffffffffffffffffffffff16846000600281106104ed57fe5b6020020151856001600281106104ff57fe5b60200201518c8c8c8a60405160200161051e97969594939291906124ae565b60405160208183030381529060405260405161053a9190612482565b602060405180830381855afa158015610557573d6000803e3d6000fd5b5050506040513d601f19601f8201168201806040525061057a9190810190611a86565b90506105ce8660006004811061058c57fe5b60200201518760016004811061059e57fe5b6020020151886002600481106105b057fe5b6020020151896003600481106105c257fe5b60200201518986610940565b61060d576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610604906127cb565b60405180910390fd5b61061989898987610a17565b610658576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161064f9061276b565b60405180910390fd5b610660611594565b61066a8582610c20565b60006106766002610c7c565b905061068181610cde565b7f36ed7c3f2ecfb5a5226c478b034d33144c060afe361be291e948f861dcddc618818584886040516106b694939291906125e4565b60405180910390a16106c786610d0d565b5050505050505050505050565b600063c73d16ae60e01b9050949350505050565b60008060006002925060029150600160028002600101600260010101019050909192565b604260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b604060008360006009811061074357fe5b602002015160001b815260200190815260200160002060009054906101000a900460ff166107a6576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161079d9061270b565b60405180910390fd5b60008090505b60028110156108745760006107c18285610212565b90506041600082815260200190815260200160002060009054906101000a900460ff1615610824576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161081b9061266b565b60405180910390fd5b60016041600083815260200190815260200160002060006101000a81548160ff0219169083151502179055508083836002811061085d57fe5b6020020181815250505080806001019150506107ac565b5060006002828560405160200161088c929190612456565b6040516020818303038152906040526040516108a89190612482565b602060405180830381855afa1580156108c5573d6000803e3d6000fd5b5050506040513d601f19601f820116820180604052506108e89190810190611a86565b905060006108f584610434565b9050808214610939576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016109309061272b565b60405180910390fd5b5050505050565b600061094a6115b6565b6107d05a038682528560208301528360408301526020608083016060846000600286f150604082018981528860208201526040816060836000600787f1506040836080856000600687f15060016040840152600260608401528560808401526040816060836000600787f1505050806002600581106109c557fe5b6020020151816000600581106109d757fe5b6020020151148015610a0a5750806003600581106109f157fe5b602002015181600160058110610a0357fe5b6020020151145b9150509695505050505050565b6000807f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f00000019050610a456115d8565b86600060028110610a5257fe5b602002015181600001818152505086600160028110610a6d57fe5b602002015181602001818152505085600060048110610a8857fe5b602002015181604001818152505085600160048110610aa357fe5b602002015181606001818152505085600260048110610abe57fe5b602002015181608001818152505085600360048110610ad957fe5b60200201518160a001818152505084600060028110610af457fe5b60200201518160c001818152505084600160028110610b0f57fe5b60200201518160e0018181525050606060016002800260010160026001010101604051908082528060200260200182016040528015610b5d5781602001602082028038833980820191505090505b50905060008090505b60016002800260010160026001010101811015610c055783868260098110610b8a57fe5b602002015110610bcf576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610bc6906127ab565b60405180910390fd5b858160098110610bdb57fe5b6020020151828281518110610bec57fe5b6020026020010181815250508080600101915050610b66565b50610c1081836110c5565b6001149350505050949350505050565b60008090505b6002811015610c77576000838260010160098110610c4057fe5b602002015160001b905080838360028110610c5757fe5b602002018181525050610c69816103af565b508080600101915050610c26565b505050565b600080603f549050600083603f540390506000600560020a90505b6001811115610cc557610cab8183856113e2565b809450819350505060028181610cbd57fe5b049050610c97565b600080603f8110610cd257fe5b01549350505050919050565b60016040600083815260200190815260200160002060006101000a81548160ff02191690831515021790555050565b600080610d1983610332565b915091506000821115610e6057600073ffffffffffffffffffffffffffffffffffffffff16604260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614610e18576000604260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1690508073ffffffffffffffffffffffffffffffffffffffff1663d0e7d6113330866040518463ffffffff1660e01b8152600401610de093929190612543565b600060405180830381600087803b158015610dfa57600080fd5b505af1158015610e0e573d6000803e3d6000fd5b5050505050610e5b565b813414610e5a576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610e519061278b565b60405180910390fd5b5b610f18565b6000341115610f175760003373ffffffffffffffffffffffffffffffffffffffff1634604051610e8f90612499565b60006040518083038185875af1925050503d8060008114610ecc576040519150601f19603f3d011682016040523d82523d6000602084013e610ed1565b606091505b5050905080610f15576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610f0c9061268b565b60405180910390fd5b505b5b60008111156110c057600073ffffffffffffffffffffffffffffffffffffffff16604260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614611011576000604260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1690508073ffffffffffffffffffffffffffffffffffffffff16639bd9bbc633846040518363ffffffff1660e01b8152600401610fd992919061258d565b600060405180830381600087803b158015610ff357600080fd5b505af1158015611007573d6000803e3d6000fd5b50505050506110bf565b60003373ffffffffffffffffffffffffffffffffffffffff168260405161103790612499565b60006040518083038185875af1925050503d8060008114611074576040519150601f19603f3d011682016040523d82523d6000602084013e611079565b606091505b50509050806110bd576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016110b4906126ab565b60405180910390fd5b505b5b505050565b60006043600a0180549050600184510114611115576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161110c9061274b565b60405180910390fd5b61111d61161d565b6000600190506107d05a03600a60430183526020832060208701875160200281018254865260018301546020870152600283019250604086015b818310156111a657835481526001840154602082015282516040820152604081606083600060078af160408860808a600060068bf1808216881697505050600284019350602083019250611157565b5050505050806111eb576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016111e29061280b565b60405180910390fd5b7f198e9393920d483a7260bfb731fb5d25f1aa493335a9e71297e485b7aef312c260408301527f1800deef121f1e76426a00665e5c4479674322d4f75edadd46debd5cd992f6ed60608301527f090689d0585ff075ec9e99ad690c3395bc4b313370b38ef355acdadcd122975b60808301527f12c85ea5db8c6deb4aab71808dcb408fe3d1e7690c43d37b4ce6cc0166fa7daa60a083015260435460c083015260016043015460e083015260026043015461010083015260036043015461012083015260046043015461014083015260056043015461016083015283516101808301527f30644e72e131a029b85045b68181585d97816a916871ca8d3c208c16d87cfd47602085015181810682036101a085015260408601516101c085015260608601516101e0850152608086015161020085015260a086015161022085015260c086015161024085015260e08601516102608501526006604301546102808501526007604301546102a08501526008604301546102c08501526009604301546102e085015260208461030086600060086107d05a03f192505050806113c6576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016113bd906127eb565b60405180910390fd5b816000601881106113d357fe5b60200201519250505092915050565b600080600060018603905060006001198616820190506000806001871614611459576001868401039050611435600082603f811061141c57fe5b0154600085600202603f811061142e57fe5b01546114e3565b60006002600184038161144457fe5b04603f811061144f57fe5b018190555061145f565b85830190505b5b818111156114bb57600281039050611497600082603f811061147e57fe5b0154600060018401603f811061149057fe5b01546114e3565b6000600260018403816114a657fe5b04603f81106114b157fe5b0181905550611460565b600287816114c557fe5b04600260018801816114d357fe5b0494509450505050935093915050565b60007fdec937b7fa8db3de380427a8cc947bfab68514522c3439cfa2e99655098368146000527f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f00000018284828282088381820984858383098683840909925060005b605a81121561157c57602060002080600052868688838808089350868485099250868488858a8788090909945050600181019050611543565b508484868a8888880808089550505050505092915050565b6040518060400160405280600290602082028038833980820191505090505090565b6040518060a00160405280600590602082028038833980820191505090505090565b60405180610100016040528060008152602001600081526020016000815260200160008152602001600081526020016000815260200160008152602001600081525090565b604051806103000160405280601890602082028038833980820191505090505090565b60008135905061164f81612bdd565b92915050565b600082601f83011261166657600080fd5b6002611679611674826128b8565b61288b565b9150818360005b838110156116b057813586016116968882611840565b845260208401935060208301925050600181019050611680565b5050505092915050565b600082601f8301126116cb57600080fd5b60026116de6116d9826128da565b61288b565b915081838560208402820111156116f457600080fd5b60005b83811015611724578161170a88826118e8565b8452602084019350602083019250506001810190506116f7565b5050505092915050565b600082601f83011261173f57600080fd5b600461175261174d826128fc565b61288b565b9150818385602084028201111561176857600080fd5b60005b83811015611798578161177e88826118e8565b84526020840193506020830192505060018101905061176b565b5050505092915050565b600082601f8301126117b357600080fd5b60096117c66117c18261291e565b61288b565b915081838560208402820111156117dc57600080fd5b60005b8381101561180c57816117f288826118e8565b8452602084019350602083019250506001810190506117df565b5050505092915050565b60008135905061182581612bf4565b92915050565b60008151905061183a81612bf4565b92915050565b600082601f83011261185157600080fd5b813561186461185f82612940565b61288b565b9150808252602083016020830185838301111561188057600080fd5b61188b838284612b80565b50505092915050565b600082601f8301126118a557600080fd5b81356118b86118b38261296c565b61288b565b915080825260208301602083018583830111156118d457600080fd5b6118df838284612b80565b50505092915050565b6000813590506118f781612c0b565b92915050565b6000806000806080858703121561191357600080fd5b600061192187828801611640565b945050602061193287828801611640565b9350506040611943878288016118e8565b925050606085013567ffffffffffffffff81111561196057600080fd5b61196c87828801611894565b91505092959194509250565b60008060008060008060006102e0888a03121561199457600080fd5b60006119a28a828b016116ba565b97505060406119b38a828b0161172e565b96505060c06119c48a828b016116ba565b9550506101006119d68a828b0161172e565b9450506101806119e88a828b016118e8565b9350506101a06119fa8a828b016117a2565b9250506102c088013567ffffffffffffffff811115611a1857600080fd5b611a248a828b01611655565b91505092959891949750929550565b60006101208284031215611a4657600080fd5b6000611a54848285016117a2565b91505092915050565b600060208284031215611a6f57600080fd5b6000611a7d84828501611816565b91505092915050565b600060208284031215611a9857600080fd5b6000611aa68482850161182b565b91505092915050565b6000806101408385031215611ac357600080fd5b6000611ad1858286016118e8565b9250506020611ae2858286016117a2565b9150509250929050565b6000611af88383611d8e565b60208301905092915050565b6000611b108383611dac565b60208301905092915050565b6000611b288383611dfb565b905092915050565b6000611b3c8383612430565b60208301905092915050565b611b5181612b4a565b82525050565b611b6081612ad8565b82525050565b611b6f816129ca565b611b798184612a58565b9250611b8482612998565b8060005b83811015611bb5578151611b9c8782611aec565b9650611ba783612a17565b925050600181019050611b88565b505050505050565b611bc6816129ca565b611bd08184612a63565b9250611bdb82612998565b8060005b83811015611c0c578151611bf38782611b04565b9650611bfe83612a17565b925050600181019050611bdf565b505050505050565b6000611c1f826129d5565b611c298185612a6e565b935083602082028501611c3b856129a2565b8060005b85811015611c775784840389528151611c588582611b1c565b9450611c6383612a24565b925060208a01995050600181019050611c3f565b50829750879550505050505092915050565b611c92816129e0565b611c9c8184612a79565b9250611ca7826129ac565b8060005b83811015611cd8578151611cbf8782611b30565b9650611cca83612a31565b925050600181019050611cab565b505050505050565b611ce9816129eb565b611cf38184612a84565b9250611cfe826129b6565b8060005b83811015611d2f578151611d168782611b30565b9650611d2183612a3e565b925050600181019050611d02565b505050505050565b611d40816129f6565b611d4a8184612a8f565b9250611d55826129c0565b8060005b83811015611d86578151611d6d8782611b30565b9650611d7883612a4b565b925050600181019050611d59565b505050505050565b611d9781612aea565b82525050565b611da681612aea565b82525050565b611db581612aea565b82525050565b611dc481612af4565b82525050565b6000611dd582612a0c565b611ddf8185612abc565b9350611def818560208601612b8f565b80840191505092915050565b6000611e0682612a01565b611e108185612a9a565b9350611e20818560208601612b8f565b611e2981612bcc565b840191505092915050565b6000611e3f82612a01565b611e498185612abc565b9350611e59818560208601612b8f565b80840191505092915050565b6000611e72601883612ac7565b91507f6e756c6c696669657220696e646578206f766572666c6f7700000000000000006000830152602082019050919050565b6000611eb2603783612ac7565b91507f496e76616c6964206e756c6c69666965723a2054686973206e756c6c6966696560008301527f722068617320616c7265616479206265656e20757365640000000000000000006020830152604082019050919050565b6000611f18601e83612ac7565b91507f767075625f696e2072657475726e207472616e73666572206661696c656400006000830152602082019050919050565b6000611f58601883612ac7565b91507f767075625f6f7574207472616e73666572206661696c656400000000000000006000830152602082019050919050565b6000611f98602783612ac7565b91507f4d65726b6c6520747265652066756c6c3a2043616e6e6f7420617070656e642060008301527f616e796d6f7265000000000000000000000000000000000000000000000000006020830152604082019050919050565b6000611ffe603083612ac7565b91507f6e756c6c6966696572207772697474656e20696e20646966666572656e74207260008301527f6573696475616c2062697420662e652e000000000000000000000000000000006020830152604082019050919050565b6000612064602583612ac7565b91507f496e76616c696420726f6f743a205468697320726f6f7420646f65736e27742060008301527f65786973740000000000000000000000000000000000000000000000000000006020830152604082019050919050565b60006120ca604983612ac7565b91507f496e76616c696420687369673a2054686973206873696720646f6573206e6f7460008301527f20636f72726573706f6e6420746f207468652068617368206f6620766b20616e60208301527f6420746865206e667300000000000000000000000000000000000000000000006040830152606082019050919050565b6000612156602283612ac7565b91507f496e707574206c656e67746820646966666572732066726f6d2065787065637460008301527f65640000000000000000000000000000000000000000000000000000000000006020830152604082019050919050565b60006121bc603383612ac7565b91507f496e76616c69642070726f6f663a20556e61626c6520746f207665726966792060008301527f7468652070726f6f6620636f72726563746c79000000000000000000000000006020830152604082019050919050565b6000612222602a83612ac7565b91507f57726f6e67206d73672e76616c75653a2056616c75652070616964206973206e60008301527f6f7420636f7272656374000000000000000000000000000000000000000000006020830152604082019050919050565b6000612288601c83612ac7565b91507f496e707574206973206e6f7420696e207363616c6172206669656c64000000006000830152602082019050919050565b60006122c8603b83612ac7565b91507f496e76616c6964207369676e61747572653a20556e61626c6520746f2076657260008301527f69667920746865207369676e617475726520636f72726563746c7900000000006020830152604082019050919050565b600061232e600083612aab565b9150600082019050919050565b6000612348600083612abc565b9150600082019050919050565b6000612362603783612ac7565b91507f43616c6c20746f20626e3235364164642c20626e3235365363616c61724d756c60008301527f206f7220626e32353650616972696e67206661696c65640000000000000000006020830152604082019050919050565b60006123c8603983612ac7565b91507f43616c6c20746f2074686520626e323536416464206f7220626e32353653636160008301527f6c61724d756c20707265636f6d70696c6564206661696c6564000000000000006020830152604082019050919050565b61242a81612b40565b82525050565b61243981612b40565b82525050565b61245061244b82612b40565b612bc2565b82525050565b60006124628285611bbd565b6040820191506124728284611ce0565b6080820191508190509392505050565b600061248e8284611dca565b915081905092915050565b60006124a48261233b565b9150819050919050565b60006124ba828a61243f565b6020820191506124ca8289611e34565b91506124d68288611e34565b91506124e28287611c89565b6040820191506124f28286611ce0565b6080820191506125028285611c89565b6040820191506125128284611d37565b6101208201915081905098975050505050505050565b600060208201905061253d6000830184611b57565b92915050565b60006080820190506125586000830186611b48565b6125656020830185611b57565b6125726040830184612421565b818103606083015261258381612321565b9050949350505050565b60006060820190506125a26000830185611b48565b6125af6020830184612421565b81810360408301526125c081612321565b90509392505050565b60006020820190506125de6000830184611d9d565b92915050565b600060c0820190506125f96000830187611d9d565b6126066020830186611b66565b6126136060830185611b66565b81810360a08301526126258184611c14565b905095945050505050565b60006020820190506126456000830184611dbb565b92915050565b6000602082019050818103600083015261266481611e65565b9050919050565b6000602082019050818103600083015261268481611ea5565b9050919050565b600060208201905081810360008301526126a481611f0b565b9050919050565b600060208201905081810360008301526126c481611f4b565b9050919050565b600060208201905081810360008301526126e481611f8b565b9050919050565b6000602082019050818103600083015261270481611ff1565b9050919050565b6000602082019050818103600083015261272481612057565b9050919050565b60006020820190508181036000830152612744816120bd565b9050919050565b6000602082019050818103600083015261276481612149565b9050919050565b60006020820190508181036000830152612784816121af565b9050919050565b600060208201905081810360008301526127a481612215565b9050919050565b600060208201905081810360008301526127c48161227b565b9050919050565b600060208201905081810360008301526127e4816122bb565b9050919050565b6000602082019050818103600083015261280481612355565b9050919050565b60006020820190508181036000830152612824816123bb565b9050919050565b60006040820190506128406000830185612421565b61284d6020830184612421565b9392505050565b60006060820190506128696000830186612421565b6128766020830185612421565b6128836040830184612421565b949350505050565b6000604051905081810181811067ffffffffffffffff821117156128ae57600080fd5b8060405250919050565b600067ffffffffffffffff8211156128cf57600080fd5b602082029050919050565b600067ffffffffffffffff8211156128f157600080fd5b602082029050919050565b600067ffffffffffffffff82111561291357600080fd5b602082029050919050565b600067ffffffffffffffff82111561293557600080fd5b602082029050919050565b600067ffffffffffffffff82111561295757600080fd5b601f19601f8301169050602081019050919050565b600067ffffffffffffffff82111561298357600080fd5b601f19601f8301169050602081019050919050565b6000819050919050565b6000819050919050565b6000819050919050565b6000819050919050565b6000819050919050565b600060029050919050565b600060029050919050565b600060029050919050565b600060049050919050565b600060099050919050565b600081519050919050565b600081519050919050565b6000602082019050919050565b6000602082019050919050565b6000602082019050919050565b6000602082019050919050565b6000602082019050919050565b600081905092915050565b600081905092915050565b600081905092915050565b600081905092915050565b600081905092915050565b600081905092915050565b600082825260208201905092915050565b600082825260208201905092915050565b600081905092915050565b600082825260208201905092915050565b6000612ae382612b20565b9050919050565b6000819050919050565b60007fffffffff0000000000000000000000000000000000000000000000000000000082169050919050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b6000819050919050565b6000612b5582612b5c565b9050919050565b6000612b6782612b6e565b9050919050565b6000612b7982612b20565b9050919050565b82818337600083830152505050565b60005b83811015612bad578082015181840152602081019050612b92565b83811115612bbc576000848401525b50505050565b6000819050919050565b6000601f19601f8301169050919050565b612be681612ad8565b8114612bf157600080fd5b50565b612bfd81612aea565b8114612c0857600080fd5b50565b612c1481612b40565b8114612c1f57600080fd5b5056fea365627a7a7231582015c071139d561376dc726ac2a4746c70b465ba5933ab1663b55ed1c13980d2086c6578706572696d656e74616cf564736f6c63430005110040" + abi = [{'inputs': [{'internalType': 'uint256', 'name': 'mk_depth', 'type': 'uint256'}, {'internalType': 'address', 'name': 'token', 'type': 'address'}, {'internalType': 'uint256[2]', 'name': 'Alpha', 'type': 'uint256[2]'}, {'internalType': 'uint256[2]', 'name': 'Beta1', 'type': 'uint256[2]'}, {'internalType': 'uint256[2]', 'name': 'Beta2', 'type': 'uint256[2]'}, {'internalType': 'uint256[2]', 'name': 'Delta1', 'type': 'uint256[2]'}, {'internalType': 'uint256[2]', 'name': 'Delta2', 'type': 'uint256[2]'}, {'internalType': 'uint256[]', 'name': 'ABC_coords', 'type': 'uint256[]'}], 'payable': False, 'stateMutability': 'nonpayable', 'type': 'constructor'}, {'anonymous': False, 'inputs': [{'indexed': False, 'internalType': 'string', 'name': 'message', 'type': 'string'}], 'name': 'LogDebug', 'type': 'event'}, {'anonymous': False, 'inputs': [{'indexed': False, 'internalType': 'bytes32', 'name': 'message', 'type': 'bytes32'}], 'name': 'LogDebug', 'type': 'event'}, {'anonymous': False, 'inputs': [{'indexed': False, 'internalType': 'uint256', 'name': 'mid', 'type': 'uint256'}, {'indexed': False, 'internalType': 'bytes32', 'name': 'root', 'type': 'bytes32'}, {'indexed': False, 'internalType': 'bytes32[2]', 'name': 'nullifiers', 'type': 'bytes32[2]'}, {'indexed': False, 'internalType': 'bytes32[2]', 'name': 'commitments', 'type': 'bytes32[2]'}, {'indexed': False, 'internalType': 'bytes[2]', 'name': 'ciphertexts', 'type': 'bytes[2]'}], 'name': 'LogMix', 'type': 'event'}, {'constant': True, 'inputs': [{'internalType': 'uint256[10]', 'name': 'primary_inputs', 'type': 'uint256[10]'}], 'name': 'assemble_hsig', 'outputs': [{'internalType': 'bytes32', 'name': 'hsig', 'type': 'bytes32'}], 'payable': False, 'stateMutability': 'pure', 'type': 'function'}, {'constant': True, 'inputs': [{'internalType': 'uint256', 'name': 'index', 'type': 'uint256'}, {'internalType': 'uint256[10]', 'name': 'primary_inputs', 'type': 'uint256[10]'}], 'name': 'assemble_nullifier', 'outputs': [{'internalType': 'bytes32', 'name': 'nf', 'type': 'bytes32'}], 'payable': False, 'stateMutability': 'pure', 'type': 'function'}, {'constant': True, 'inputs': [{'internalType': 'uint256[10]', 'name': 'primary_inputs', 'type': 'uint256[10]'}], 'name': 'assemble_public_values', 'outputs': [{'internalType': 'uint256', 'name': 'vpub_in', 'type': 'uint256'}, {'internalType': 'uint256', 'name': 'vpub_out', 'type': 'uint256'}], 'payable': False, 'stateMutability': 'pure', 'type': 'function'}, {'constant': True, 'inputs': [], 'name': 'get_constants', 'outputs': [{'internalType': 'uint256', 'name': 'js_in', 'type': 'uint256'}, {'internalType': 'uint256', 'name': 'js_out', 'type': 'uint256'}, {'internalType': 'uint256', 'name': 'num_inputs', 'type': 'uint256'}], 'payable': False, 'stateMutability': 'pure', 'type': 'function'}, {'constant': False, 'inputs': [{'internalType': 'bytes32', 'name': 'commitment', 'type': 'bytes32'}], 'name': 'insert', 'outputs': [], 'payable': False, 'stateMutability': 'nonpayable', 'type': 'function'}, {'constant': True, 'inputs': [], 'name': 'mid', 'outputs': [{'internalType': 'uint256', 'name': '', 'type': 'uint256'}], 'payable': False, 'stateMutability': 'view', 'type': 'function'}, {'constant': False, 'inputs': [{'internalType': 'uint256[2]', 'name': 'a', 'type': 'uint256[2]'}, {'internalType': 'uint256[4]', 'name': 'b', 'type': 'uint256[4]'}, {'internalType': 'uint256[2]', 'name': 'c', 'type': 'uint256[2]'}, {'internalType': 'uint256[4]', 'name': 'vk', 'type': 'uint256[4]'}, {'internalType': 'uint256', 'name': 'sigma', 'type': 'uint256'}, {'internalType': 'uint256[10]', 'name': 'input', 'type': 'uint256[10]'}, {'internalType': 'bytes[2]', 'name': 'ciphertexts', 'type': 'bytes[2]'}], 'name': 'mix', 'outputs': [], 'payable': True, 'stateMutability': 'payable', 'type': 'function'}, {'constant': False, 'inputs': [{'internalType': 'address', 'name': '', 'type': 'address'}, {'internalType': 'address', 'name': '', 'type': 'address'}, {'internalType': 'uint256', 'name': '', 'type': 'uint256'}, {'internalType': 'bytes', 'name': '', 'type': 'bytes'}], 'name': 'onBAC001Received', 'outputs': [{'internalType': 'bytes4', 'name': '', 'type': 'bytes4'}], 'payable': False, 'stateMutability': 'nonpayable', 'type': 'function'}, {'constant': True, 'inputs': [], 'name': 'token', 'outputs': [{'internalType': 'address', 'name': '', 'type': 'address'}], 'payable': False, 'stateMutability': 'view', 'type': 'function'}] + + binstr = "6080604052600080553480156200001557600080fd5b506040516200393b3803806200393b83398181016040526200003b9190810190620006cf565b878781806005811462000085576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016200007c9062000904565b60405180910390fd5b50620000966200042960201b60201c565b506000600160008081526020019081526020016000206000603f8110620000b957fe5b01549050600160036000808152602001908152602001600020600083815260200190815260200160002060006101000a81548160ff02191690831515021790555081600560006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555061010060fd1062000183576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016200017a90620008c0565b60405180910390fd5b60fd6002800260010160fd610100030260406002020110620001dc576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401620001d390620008e2565b60405180910390fd5b505050604051806040016040528087600060028110620001f857fe5b60200201518152602001876001600281106200021057fe5b6020020151815250600660000160008201518160000155602082015181600101559050506040518060800160405280866000600281106200024d57fe5b60200201518152602001866001600281106200026557fe5b60200201518152602001856000600281106200027d57fe5b60200201518152602001856001600281106200029557fe5b6020020151815250600660020160008201518160000155602082015181600101556040820151816002015560608201518160030155905050604051806080016040528084600060028110620002e657fe5b6020020151815260200184600160028110620002fe57fe5b60200201518152602001836000600281106200031657fe5b60200201518152602001836001600281106200032e57fe5b6020020151815250600680016000820151816000015560208201518160010155604082015181600201556060820151816003015590505060008090505b60028251816200037757fe5b046006600a0180549050146200041a576006600a016040518060400160405280848481518110620003a457fe5b60200260200101518152602001846001850181518110620003c157fe5b60200260200101518152509080600181540180825580915050906001820390600052602060002090600202016000909192909190915060008201518160000155602082015181600101555050506002810190506200036b565b50505050505050505062000a23565b60008060001b90508060016000805481526020019081526020016000206002600560020a60020203603f81106200045c57fe5b018190555060006002600560020a816200047257fe5b0490505b6000811115620004df57620004978283620004e360201b620011e91760201c565b9150600060028260020203905082600160008054815260200190815260200160002082603f8110620004c557fe5b018190555060028281620004d557fe5b0491505062000476565b5050565b60007fdec937b7fa8db3de380427a8cc947bfab68514522c3439cfa2e99655098368146000527f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f00000018284828282088381820984858383098683840909925060005b605a8112156200057e57602060002080600052868688838808089350868485099250868488858a878809090994505060018101905062000543565b508484868a8888880808089550505050505092915050565b600081519050620005a781620009ef565b92915050565b600082601f830112620005bf57600080fd5b6002620005d6620005d08262000954565b62000926565b91508183856020840282011115620005ed57600080fd5b60005b83811015620006215781620006068882620006b8565b845260208401935060208301925050600181019050620005f0565b5050505092915050565b600082601f8301126200063d57600080fd5b8151620006546200064e8262000977565b62000926565b915081818352602084019350602081019050838560208402820111156200067a57600080fd5b60005b83811015620006ae5781620006938882620006b8565b8452602084019350602083019250506001810190506200067d565b5050505092915050565b600081519050620006c98162000a09565b92915050565b6000806000806000806000806101a0898b031215620006ed57600080fd5b6000620006fd8b828c01620006b8565b9850506020620007108b828c0162000596565b9750506040620007238b828c01620005ad565b9650506080620007368b828c01620005ad565b95505060c0620007498b828c01620005ad565b9450506101006200075d8b828c01620005ad565b935050610140620007718b828c01620005ad565b92505061018089015167ffffffffffffffff8111156200079057600080fd5b6200079e8b828c016200062b565b9150509295985092959890939650565b6000620007bd602d83620009a0565b91507f41206861736820646967657374206669747320696e20612073696e676c65206660008301527f69656c6420656c656d656e742e000000000000000000000000000000000000006020830152604082019050919050565b600062000825602b83620009a0565b91507f546f6f206d616e7920696e70757420616e64206f7574707574206e6f7465732060008301527f636f6e736964657265642e0000000000000000000000000000000000000000006020830152604082019050919050565b60006200088d601f83620009a0565b91507f496e76616c696420646570746820696e20426173654d65726b6c6554726565006000830152602082019050919050565b60006020820190508181036000830152620008db81620007ae565b9050919050565b60006020820190508181036000830152620008fd8162000816565b9050919050565b600060208201905081810360008301526200091f816200087e565b9050919050565b6000604051905081810181811067ffffffffffffffff821117156200094a57600080fd5b8060405250919050565b600067ffffffffffffffff8211156200096c57600080fd5b602082029050919050565b600067ffffffffffffffff8211156200098f57600080fd5b602082029050602081019050919050565b600082825260208201905092915050565b6000620009be82620009c5565b9050919050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b6000819050919050565b620009fa81620009b1565b811462000a0657600080fd5b50565b62000a1481620009e5565b811462000a2057600080fd5b50565b612f088062000a336000396000f3fe6080604052600436106100865760003560e01c80634773862d116100595780634773862d1461015a578063a52f1ea814610176578063c73d16ae146101b3578063f9eb943f146101f0578063fc0c546a1461021d57610086565b80632d287e431461008b5780632e94420f146100b45780633e49ba65146100df57806346deb3411461011d575b600080fd5b34801561009757600080fd5b506100b260048036036100ad9190810190611cd7565b610248565b005b3480156100c057600080fd5b506100c9610318565b6040516100d69190612a59565b60405180910390f35b3480156100eb57600080fd5b5061010660048036036101019190810190611bf2565b61031e565b604051610114929190612ace565b60405180910390f35b34801561012957600080fd5b50610144600480360361013f9190810190611bf2565b61039a565b6040516101519190612843565b60405180910390f35b610174600480360361016f9190810190611c1c565b610417565b005b34801561018257600080fd5b5061019d60048036036101989190810190611d29565b61063d565b6040516101aa9190612843565b60405180910390f35b3480156101bf57600080fd5b506101da60048036036101d59190810190611b77565b61075b565b6040516101e7919061285e565b60405180910390f35b3480156101fc57600080fd5b5061020561076f565b60405161021493929190612af7565b60405180910390f35b34801561022957600080fd5b50610232610792565b60405161023f91906127a2565b60405180910390f35b600560020a600254141561028157600160005401600081905550600560020a6002548161027157fe5b066002819055506102806107b8565b5b600560020a600254106102c9576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016102c0906128f9565b60405180910390fd5b60006002549050600260008154600101919050819055506000816001600560020a0301905082600160008054815260200190815260200160002082603f811061030e57fe5b0181905550505050565b60005481565b600080600083600280026001016002800101600a811061033a57fe5b602002015190506002800260010160fd610100030281901c905064e8d4a5100067ffffffffffffffff168167ffffffffffffffff1602915064e8d4a5100067ffffffffffffffff16604082901c67ffffffffffffffff1602925050915091565b60008060fd60406002026002800260010160fd6101000302604060020201610100030184600280026001016002800101600a81106103d457fe5b602002015160001b901b901c9050600060fd610100038460028060020101600a81106103fc57fe5b6020020151901b90508160001c810160001b92505050919050565b61041f61180e565b61042a85848361085f565b600060023373ffffffffffffffffffffffffffffffffffffffff168460006002811061045257fe5b60200201518560016002811061046457fe5b60200201518c8c8c8a6040516020016104839796959493929190612728565b60405160208183030381529060405260405161049f91906126fc565b602060405180830381855afa1580156104bc573d6000803e3d6000fd5b5050506040513d601f19601f820116820180604052506104df9190810190611d00565b9050610533866000600481106104f157fe5b60200201518760016004811061050357fe5b60200201518860026004811061051557fe5b60200201518960036004811061052757fe5b60200201518986610a41565b610572576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610569906129f9565b60405180910390fd5b61057e89898987610b18565b6105bd576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016105b490612999565b60405180910390fd5b6105c561180e565b6105cf8582610d1f565b60006105db6002610d7b565b90506105e681610df0565b7f5b20d7b970f991ad433adaa73d15ec55f2dc64ddfecb9505eb1f94e330ecddf76000548286858960405161061f959493929190612a74565b60405180910390a161063086610e31565b5050505050505050505050565b600060028310610682576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161067990612879565b60405180910390fd5b600060fd610100038460010102604060020201905060fd61010003810160fd10156106e2576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016106d990612919565b60405180910390fd5b600060fd826002800260010160fd6101000302604060020201610100030185600280026001016002800101600a811061071757fe5b602002015160001b901b901c9050600060fd6101000385876002800101600a811061073e57fe5b6020020151901b90508160001c810160001b935050505092915050565b600063c73d16ae60e01b9050949350505050565b600080600060029250600291506001600280026001016002800101019050909192565b600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b60008060001b90508060016000805481526020019081526020016000206002600560020a60020203603f81106107ea57fe5b018190555060006002600560020a816107ff57fe5b0490505b600081111561085b5761081682836111e9565b9150600060028260020203905082600160008054815260200190815260200160002082603f811061084357fe5b01819055506002828161085257fe5b04915050610803565b5050565b6108688261129a565b6108a7576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161089e90612939565b60405180910390fd5b60008090505b60028110156109755760006108c2828561063d565b90506004600082815260200190815260200160002060009054906101000a900460ff1615610925576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161091c90612899565b60405180910390fd5b60016004600083815260200190815260200160002060006101000a81548160ff0219169083151502179055508083836002811061095e57fe5b6020020181815250505080806001019150506108ad565b5060006002828560405160200161098d9291906126d0565b6040516020818303038152906040526040516109a991906126fc565b602060405180830381855afa1580156109c6573d6000803e3d6000fd5b5050506040513d601f19601f820116820180604052506109e99190810190611d00565b905060006109f68461039a565b9050808214610a3a576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610a3190612959565b60405180910390fd5b5050505050565b6000610a4b611830565b6107d05a038682528560208301528360408301526020608083016060846000600286f150604082018981528860208201526040816060836000600787f1506040836080856000600687f15060016040840152600260608401528560808401526040816060836000600787f150505080600260058110610ac657fe5b602002015181600060058110610ad857fe5b6020020151148015610b0b575080600360058110610af257fe5b602002015181600160058110610b0457fe5b6020020151145b9150509695505050505050565b6000807f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f00000019050610b46611852565b86600060028110610b5357fe5b602002015181600001818152505086600160028110610b6e57fe5b602002015181602001818152505085600060048110610b8957fe5b602002015181604001818152505085600160048110610ba457fe5b602002015181606001818152505085600260048110610bbf57fe5b602002015181608001818152505085600360048110610bda57fe5b60200201518160a001818152505084600060028110610bf557fe5b60200201518160c001818152505084600160028110610c1057fe5b60200201518160e00181815250506060600160028002600101600280010101604051908082528060200260200182016040528015610c5d5781602001602082028038833980820191505090505b50905060008090505b600160028002600101600280010101811015610d0457838682600a8110610c8957fe5b602002015110610cce576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610cc5906129d9565b60405180910390fd5b8581600a8110610cda57fe5b6020020151828281518110610ceb57fe5b6020026020010181815250508080600101915050610c66565b50610d0f8183611385565b6001149350505050949350505050565b60008090505b6002811015610d765760008382600201600a8110610d3f57fe5b602002015160001b905080838360028110610d5657fe5b602002018181525050610d6881610248565b508080600101915050610d25565b505050565b60008060025490506000836002540390506000600560020a90505b6001811115610dc457610daa8183856116a1565b809450819350505060028181610dbc57fe5b049050610d96565b60016000805481526020019081526020016000206000603f8110610de457fe5b01549350505050919050565b60016003600080548152602001908152602001600020600083815260200190815260200160002060006101000a81548160ff02191690831515021790555050565b600080610e3d8361031e565b915091506000821115610f8457600073ffffffffffffffffffffffffffffffffffffffff16600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614610f3c576000600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1690508073ffffffffffffffffffffffffffffffffffffffff1663d0e7d6113330866040518463ffffffff1660e01b8152600401610f04939291906127bd565b600060405180830381600087803b158015610f1e57600080fd5b505af1158015610f32573d6000803e3d6000fd5b5050505050610f7f565b813414610f7e576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610f75906129b9565b60405180910390fd5b5b61103c565b600034111561103b5760003373ffffffffffffffffffffffffffffffffffffffff1634604051610fb390612713565b60006040518083038185875af1925050503d8060008114610ff0576040519150601f19603f3d011682016040523d82523d6000602084013e610ff5565b606091505b5050905080611039576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611030906128b9565b60405180910390fd5b505b5b60008111156111e457600073ffffffffffffffffffffffffffffffffffffffff16600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614611135576000600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1690508073ffffffffffffffffffffffffffffffffffffffff16639bd9bbc633846040518363ffffffff1660e01b81526004016110fd929190612807565b600060405180830381600087803b15801561111757600080fd5b505af115801561112b573d6000803e3d6000fd5b50505050506111e3565b60003373ffffffffffffffffffffffffffffffffffffffff168260405161115b90612713565b60006040518083038185875af1925050503d8060008114611198576040519150601f19603f3d011682016040523d82523d6000602084013e61119d565b606091505b50509050806111e1576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016111d8906128d9565b60405180910390fd5b505b5b505050565b60007fdec937b7fa8db3de380427a8cc947bfab68514522c3439cfa2e99655098368146000527f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f00000018284828282088381820984858383098683840909925060005b605a81121561128257602060002080600052868688838808089350868485099250868488858a8788090909945050600181019050611249565b508484868a8888880808089550505050505092915050565b6000806000905060008090505b600054811161137957600360008281526020019081526020016000206000856000600a81106112d257fe5b602002015160001b815260200190815260200160002060009054906101000a900460ff16156113045781806001019250505b600360008281526020019081526020016000206000856001600a811061132657fe5b602002015160001b815260200190815260200160002060009054906101000a900460ff16156113585781806001019250505b600282141561136c57600192505050611380565b80806001019150506112a7565b5060009150505b919050565b60006006600a01805490506001845101146113d5576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016113cc90612979565b60405180910390fd5b6113dd611897565b6000600190506107d05a03600a60060183526020832060208701875160200281018254865260018301546020870152600283019250604086015b8183101561146657835481526001840154602082015282516040820152604081606083600060078af160408860808a600060068bf1808216881697505050600284019350602083019250611417565b5050505050806114ab576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016114a290612a39565b60405180910390fd5b7f198e9393920d483a7260bfb731fb5d25f1aa493335a9e71297e485b7aef312c260408301527f1800deef121f1e76426a00665e5c4479674322d4f75edadd46debd5cd992f6ed60608301527f090689d0585ff075ec9e99ad690c3395bc4b313370b38ef355acdadcd122975b60808301527f12c85ea5db8c6deb4aab71808dcb408fe3d1e7690c43d37b4ce6cc0166fa7daa60a083015260065460c083015260016006015460e083015260026006015461010083015260036006015461012083015260046006015461014083015260056006015461016083015283516101808301527f30644e72e131a029b85045b68181585d97816a916871ca8d3c208c16d87cfd47602085015181810682036101a085015260408601516101c085015260608601516101e0850152608086015161020085015260a086015161022085015260c086015161024085015260e086015161026085015260068001546102808501526007600601546102a08501526008600601546102c08501526009600601546102e085015260208461030086600060086107d05a03f19250505080611685576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161167c90612a19565b60405180910390fd5b8160006018811061169257fe5b60200201519250505092915050565b60008060006001860390506000600119861682019050600080600187161461174e576001868401039050611718600160008054815260200190815260200160002082603f81106116ed57fe5b0154600160008054815260200190815260200160002085600202603f811061171157fe5b01546111e9565b60016000805481526020019081526020016000206002600184038161173957fe5b04603f811061174457fe5b0181905550611754565b85830190505b5b818111156117e6576002810390506117b0600160008054815260200190815260200160002082603f811061178557fe5b0154600160008054815260200190815260200160002060018401603f81106117a957fe5b01546111e9565b6001600080548152602001908152602001600020600260018403816117d157fe5b04603f81106117dc57fe5b0181905550611755565b600287816117f057fe5b04600260018801816117fe57fe5b0494509450505050935093915050565b6040518060400160405280600290602082028038833980820191505090505090565b6040518060a00160405280600590602082028038833980820191505090505090565b60405180610100016040528060008152602001600081526020016000815260200160008152602001600081526020016000815260200160008152602001600081525090565b604051806103000160405280601890602082028038833980820191505090505090565b6000813590506118c981612e80565b92915050565b600082601f8301126118e057600080fd5b60026118f36118ee82612b5b565b612b2e565b9150818360005b8381101561192a57813586016119108882611aba565b8452602084019350602083019250506001810190506118fa565b5050505092915050565b600082601f83011261194557600080fd5b600a61195861195382612b7d565b612b2e565b9150818385602084028201111561196e57600080fd5b60005b8381101561199e57816119848882611b62565b845260208401935060208301925050600181019050611971565b5050505092915050565b600082601f8301126119b957600080fd5b60026119cc6119c782612b9f565b612b2e565b915081838560208402820111156119e257600080fd5b60005b83811015611a1257816119f88882611b62565b8452602084019350602083019250506001810190506119e5565b5050505092915050565b600082601f830112611a2d57600080fd5b6004611a40611a3b82612bc1565b612b2e565b91508183856020840282011115611a5657600080fd5b60005b83811015611a865781611a6c8882611b62565b845260208401935060208301925050600181019050611a59565b5050505092915050565b600081359050611a9f81612e97565b92915050565b600081519050611ab481612e97565b92915050565b600082601f830112611acb57600080fd5b8135611ade611ad982612be3565b612b2e565b91508082526020830160208301858383011115611afa57600080fd5b611b05838284612e23565b50505092915050565b600082601f830112611b1f57600080fd5b8135611b32611b2d82612c0f565b612b2e565b91508082526020830160208301858383011115611b4e57600080fd5b611b59838284612e23565b50505092915050565b600081359050611b7181612eae565b92915050565b60008060008060808587031215611b8d57600080fd5b6000611b9b878288016118ba565b9450506020611bac878288016118ba565b9350506040611bbd87828801611b62565b925050606085013567ffffffffffffffff811115611bda57600080fd5b611be687828801611b0e565b91505092959194509250565b60006101408284031215611c0557600080fd5b6000611c1384828501611934565b91505092915050565b6000806000806000806000610300888a031215611c3857600080fd5b6000611c468a828b016119a8565b9750506040611c578a828b01611a1c565b96505060c0611c688a828b016119a8565b955050610100611c7a8a828b01611a1c565b945050610180611c8c8a828b01611b62565b9350506101a0611c9e8a828b01611934565b9250506102e088013567ffffffffffffffff811115611cbc57600080fd5b611cc88a828b016118cf565b91505092959891949750929550565b600060208284031215611ce957600080fd5b6000611cf784828501611a90565b91505092915050565b600060208284031215611d1257600080fd5b6000611d2084828501611aa5565b91505092915050565b6000806101608385031215611d3d57600080fd5b6000611d4b85828601611b62565b9250506020611d5c85828601611934565b9150509250929050565b6000611d728383612008565b60208301905092915050565b6000611d8a8383612026565b60208301905092915050565b6000611da28383612075565b905092915050565b6000611db683836126aa565b60208301905092915050565b611dcb81612ded565b82525050565b611dda81612d7b565b82525050565b611de981612c6d565b611df38184612cfb565b9250611dfe82612c3b565b8060005b83811015611e2f578151611e168782611d66565b9650611e2183612cba565b925050600181019050611e02565b505050505050565b611e4081612c6d565b611e4a8184612d06565b9250611e5582612c3b565b8060005b83811015611e86578151611e6d8782611d7e565b9650611e7883612cba565b925050600181019050611e59565b505050505050565b6000611e9982612c78565b611ea38185612d11565b935083602082028501611eb585612c45565b8060005b85811015611ef15784840389528151611ed28582611d96565b9450611edd83612cc7565b925060208a01995050600181019050611eb9565b50829750879550505050505092915050565b611f0c81612c83565b611f168184612d1c565b9250611f2182612c4f565b8060005b83811015611f52578151611f398782611daa565b9650611f4483612cd4565b925050600181019050611f25565b505050505050565b611f6381612c8e565b611f6d8184612d27565b9250611f7882612c59565b8060005b83811015611fa9578151611f908782611daa565b9650611f9b83612ce1565b925050600181019050611f7c565b505050505050565b611fba81612c99565b611fc48184612d32565b9250611fcf82612c63565b8060005b83811015612000578151611fe78782611daa565b9650611ff283612cee565b925050600181019050611fd3565b505050505050565b61201181612d8d565b82525050565b61202081612d8d565b82525050565b61202f81612d8d565b82525050565b61203e81612d97565b82525050565b600061204f82612caf565b6120598185612d5f565b9350612069818560208601612e32565b80840191505092915050565b600061208082612ca4565b61208a8185612d3d565b935061209a818560208601612e32565b6120a381612e6f565b840191505092915050565b60006120b982612ca4565b6120c38185612d5f565b93506120d3818560208601612e32565b80840191505092915050565b60006120ec601883612d6a565b91507f6e756c6c696669657220696e646578206f766572666c6f7700000000000000006000830152602082019050919050565b600061212c603783612d6a565b91507f496e76616c6964206e756c6c69666965723a2054686973206e756c6c6966696560008301527f722068617320616c7265616479206265656e20757365640000000000000000006020830152604082019050919050565b6000612192601e83612d6a565b91507f767075625f696e2072657475726e207472616e73666572206661696c656400006000830152602082019050919050565b60006121d2601883612d6a565b91507f767075625f6f7574207472616e73666572206661696c656400000000000000006000830152602082019050919050565b6000612212602783612d6a565b91507f4d65726b6c6520747265652066756c6c3a2043616e6e6f7420617070656e642060008301527f616e796d6f7265000000000000000000000000000000000000000000000000006020830152604082019050919050565b6000612278603083612d6a565b91507f6e756c6c6966696572207772697474656e20696e20646966666572656e74207260008301527f6573696475616c2062697420662e652e000000000000000000000000000000006020830152604082019050919050565b60006122de602583612d6a565b91507f496e76616c696420726f6f743a205468697320726f6f7420646f65736e27742060008301527f65786973740000000000000000000000000000000000000000000000000000006020830152604082019050919050565b6000612344604983612d6a565b91507f496e76616c696420687369673a2054686973206873696720646f6573206e6f7460008301527f20636f72726573706f6e6420746f207468652068617368206f6620766b20616e60208301527f6420746865206e667300000000000000000000000000000000000000000000006040830152606082019050919050565b60006123d0602283612d6a565b91507f496e707574206c656e67746820646966666572732066726f6d2065787065637460008301527f65640000000000000000000000000000000000000000000000000000000000006020830152604082019050919050565b6000612436603383612d6a565b91507f496e76616c69642070726f6f663a20556e61626c6520746f207665726966792060008301527f7468652070726f6f6620636f72726563746c79000000000000000000000000006020830152604082019050919050565b600061249c602a83612d6a565b91507f57726f6e67206d73672e76616c75653a2056616c75652070616964206973206e60008301527f6f7420636f7272656374000000000000000000000000000000000000000000006020830152604082019050919050565b6000612502601c83612d6a565b91507f496e707574206973206e6f7420696e207363616c6172206669656c64000000006000830152602082019050919050565b6000612542603b83612d6a565b91507f496e76616c6964207369676e61747572653a20556e61626c6520746f2076657260008301527f69667920746865207369676e617475726520636f72726563746c7900000000006020830152604082019050919050565b60006125a8600083612d4e565b9150600082019050919050565b60006125c2600083612d5f565b9150600082019050919050565b60006125dc603783612d6a565b91507f43616c6c20746f20626e3235364164642c20626e3235365363616c61724d756c60008301527f206f7220626e32353650616972696e67206661696c65640000000000000000006020830152604082019050919050565b6000612642603983612d6a565b91507f43616c6c20746f2074686520626e323536416464206f7220626e32353653636160008301527f6c61724d756c20707265636f6d70696c6564206661696c6564000000000000006020830152604082019050919050565b6126a481612de3565b82525050565b6126b381612de3565b82525050565b6126ca6126c582612de3565b612e65565b82525050565b60006126dc8285611e37565b6040820191506126ec8284611fb1565b6080820191508190509392505050565b60006127088284612044565b915081905092915050565b600061271e826125b5565b9150819050919050565b6000612734828a6126b9565b60208201915061274482896120ae565b915061275082886120ae565b915061275c8287611f5a565b60408201915061276c8286611fb1565b60808201915061277c8285611f5a565b60408201915061278c8284611f03565b6101408201915081905098975050505050505050565b60006020820190506127b76000830184611dd1565b92915050565b60006080820190506127d26000830186611dc2565b6127df6020830185611dd1565b6127ec604083018461269b565b81810360608301526127fd8161259b565b9050949350505050565b600060608201905061281c6000830185611dc2565b612829602083018461269b565b818103604083015261283a8161259b565b90509392505050565b60006020820190506128586000830184612017565b92915050565b60006020820190506128736000830184612035565b92915050565b60006020820190508181036000830152612892816120df565b9050919050565b600060208201905081810360008301526128b28161211f565b9050919050565b600060208201905081810360008301526128d281612185565b9050919050565b600060208201905081810360008301526128f2816121c5565b9050919050565b6000602082019050818103600083015261291281612205565b9050919050565b600060208201905081810360008301526129328161226b565b9050919050565b60006020820190508181036000830152612952816122d1565b9050919050565b6000602082019050818103600083015261297281612337565b9050919050565b60006020820190508181036000830152612992816123c3565b9050919050565b600060208201905081810360008301526129b281612429565b9050919050565b600060208201905081810360008301526129d28161248f565b9050919050565b600060208201905081810360008301526129f2816124f5565b9050919050565b60006020820190508181036000830152612a1281612535565b9050919050565b60006020820190508181036000830152612a32816125cf565b9050919050565b60006020820190508181036000830152612a5281612635565b9050919050565b6000602082019050612a6e600083018461269b565b92915050565b600060e082019050612a89600083018861269b565b612a966020830187612017565b612aa36040830186611de0565b612ab06080830185611de0565b81810360c0830152612ac28184611e8e565b90509695505050505050565b6000604082019050612ae3600083018561269b565b612af0602083018461269b565b9392505050565b6000606082019050612b0c600083018661269b565b612b19602083018561269b565b612b26604083018461269b565b949350505050565b6000604051905081810181811067ffffffffffffffff82111715612b5157600080fd5b8060405250919050565b600067ffffffffffffffff821115612b7257600080fd5b602082029050919050565b600067ffffffffffffffff821115612b9457600080fd5b602082029050919050565b600067ffffffffffffffff821115612bb657600080fd5b602082029050919050565b600067ffffffffffffffff821115612bd857600080fd5b602082029050919050565b600067ffffffffffffffff821115612bfa57600080fd5b601f19601f8301169050602081019050919050565b600067ffffffffffffffff821115612c2657600080fd5b601f19601f8301169050602081019050919050565b6000819050919050565b6000819050919050565b6000819050919050565b6000819050919050565b6000819050919050565b600060029050919050565b600060029050919050565b6000600a9050919050565b600060029050919050565b600060049050919050565b600081519050919050565b600081519050919050565b6000602082019050919050565b6000602082019050919050565b6000602082019050919050565b6000602082019050919050565b6000602082019050919050565b600081905092915050565b600081905092915050565b600081905092915050565b600081905092915050565b600081905092915050565b600081905092915050565b600082825260208201905092915050565b600082825260208201905092915050565b600081905092915050565b600082825260208201905092915050565b6000612d8682612dc3565b9050919050565b6000819050919050565b60007fffffffff0000000000000000000000000000000000000000000000000000000082169050919050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b6000819050919050565b6000612df882612dff565b9050919050565b6000612e0a82612e11565b9050919050565b6000612e1c82612dc3565b9050919050565b82818337600083830152505050565b60005b83811015612e50578082015181840152602081019050612e35565b83811115612e5f576000848401525b50505050565b6000819050919050565b6000601f19601f8301169050919050565b612e8981612d7b565b8114612e9457600080fd5b50565b612ea081612d8d565b8114612eab57600080fd5b50565b612eb781612de3565b8114612ec257600080fd5b5056fea365627a7a72315820f62d867b7f806cc547daab622cb427ec98c2222a4a755612cb1dc066faf41a526c6578706572696d656e74616cf564736f6c63430005110040" # with open("./contract/mixer/abi/Groth16Mixer.abi", "r") as abistring: # abistr = abistring.readlines()[0] # abi = ast.literal_eval(abistr) diff --git a/commands/zeth_deposit.py b/commands/zeth_deposit.py index 5659df0..18a154f 100644 --- a/commands/zeth_deposit.py +++ b/commands/zeth_deposit.py @@ -6,14 +6,16 @@ load_zeth_address, open_wallet, parse_output, do_sync from zeth.constants import JS_INPUTS, JS_OUTPUTS from commands.constants import PROVER_SERVER_ENDPOINT_DEFAULT +from zeth.constants import ZETH_MERKLE_TREE_DEPTH from zeth.mixer_client import ZethAddressPub from zeth.utils import EtherValue, from_zeth_units +from zeth.merkle_tree import sqlMerkleTree from api.zeth_messages_pb2 import ZethNote from click import ClickException from typing import List, Tuple, Optional from contract.Groth16Mixer import Groth16Mixer from python_web3.eth_account.account import Account - +import math def deposit( mixer_addr: str, @@ -35,9 +37,10 @@ def deposit( zeth_client = create_zeth_client_and_mixer_desc(PROVER_SERVER_ENDPOINT_DEFAULT, mixer_addr, username, password) zeth_address = load_zeth_address(username) + ''' wallet = open_wallet( - zeth_client.mixer_instance, zeth_address.addr_sk, username) - + zeth_client.mixer_instance, zeth_address.addr_sk, username, ) + ''' outputs: List[Tuple[ZethAddressPub, EtherValue]] = [ parse_output(out_spec) for out_spec in output_specs] @@ -52,9 +55,11 @@ def deposit( tx_value: Optional[EtherValue] = EtherValue(0) #if mixer_desc.token: # tx_value = EtherValue(0) - + merkle_trees = [] + for i in range(2): + merkle_trees.append(sqlMerkleTree.open(int(math.pow(2, ZETH_MERKLE_TREE_DEPTH)), 0)) (outputresult, receipt) = zeth_client.deposit( - wallet.merkle_tree, + merkle_trees, zeth_address, fisco_bcos_address, vin_pub, diff --git a/commands/zeth_ls_notes.py b/commands/zeth_ls_notes.py index 6a17861..561bb38 100644 --- a/commands/zeth_ls_notes.py +++ b/commands/zeth_ls_notes.py @@ -18,7 +18,7 @@ def ls_notes(username: str): #mixer_instance = mixer_desc.mixer.instantiate(web3) #mixer_instance = Groth16Mixer(mixer_addr) js_secret = load_zeth_address_secret(username) - wallet = open_wallet(None, js_secret, username) + wallet = open_wallet(None, js_secret, username,None, None) total = EtherValue(0) commits = [] diff --git a/commands/zeth_mix.py b/commands/zeth_mix.py index ed41b64..a4fdba6 100644 --- a/commands/zeth_mix.py +++ b/commands/zeth_mix.py @@ -3,7 +3,7 @@ # SPDX-License-Identifier: LGPL-3.0+ from commands.utils import create_zeth_client_and_mixer_desc, \ - load_zeth_address, open_wallet, parse_output, do_sync + load_zeth_address, parse_output, do_sync from zeth.constants import JS_INPUTS, JS_OUTPUTS from commands.constants import PROVER_SERVER_ENDPOINT_DEFAULT from zeth.mixer_client import ZethAddressPub @@ -13,6 +13,9 @@ from typing import List, Tuple, Optional from contract.Groth16Mixer import Groth16Mixer from python_web3.eth_account.account import Account +from zeth.merkle_tree import sqlMerkleTree +from zeth.constants import ZETH_MERKLE_TREE_DEPTH +import math def mix( mixer_addr: str, @@ -21,7 +24,8 @@ def mix( vin_pub: EtherValue, vout_pub: EtherValue, inputs: List[Tuple[int, ZethNote]], - outputs: List[Tuple[ZethAddressPub, EtherValue]] + outputs: List[Tuple[ZethAddressPub, EtherValue]], + mids: List[int] ) : """ Generic mix function @@ -34,18 +38,24 @@ def mix( zeth_client = create_zeth_client_and_mixer_desc(PROVER_SERVER_ENDPOINT_DEFAULT, mixer_addr, username, password) zeth_address = load_zeth_address(username) + ''' wallet = open_wallet( zeth_client.mixer_instance, zeth_address.addr_sk, username) - + ''' #eth_address = load_eth_address(eth_addr) fisco_bcos_address = zeth_client.mixer_instance.client.ecdsa_account.address # If instance uses an ERC20 token, tx_value can be 0 not default vin_pub. tx_value: Optional[EtherValue] = EtherValue(0) #if mixer_desc.token: # tx_value = EtherValue(0) - + if len(mids) < JS_INPUTS: + mids.append(0) + print("mids: ", mids) + merkle_trees = [] + for mid in mids: + merkle_trees.append(sqlMerkleTree.open(int(math.pow(2, ZETH_MERKLE_TREE_DEPTH)), mid)) (outputresult, receipt) = zeth_client.joinsplit( - wallet.merkle_tree, + merkle_trees, zeth_address.ownership_keypair(), fisco_bcos_address, inputs, diff --git a/contract/Groth16Mixer.abi b/contract/Groth16Mixer.abi index eef03f7..663498b 100644 --- a/contract/Groth16Mixer.abi +++ b/contract/Groth16Mixer.abi @@ -1 +1 @@ -[{"inputs": [{"internalType": "uint256", "name": "mk_depth", "type": "uint256"}, {"internalType": "address", "name": "token", "type": "address"}, {"internalType": "uint256[2]", "name": "Alpha", "type": "uint256[2]"}, {"internalType": "uint256[2]", "name": "Beta1", "type": "uint256[2]"}, {"internalType": "uint256[2]", "name": "Beta2", "type": "uint256[2]"}, {"internalType": "uint256[2]", "name": "Delta1", "type": "uint256[2]"}, {"internalType": "uint256[2]", "name": "Delta2", "type": "uint256[2]"}, {"internalType": "uint256[]", "name": "ABC_coords", "type": "uint256[]"}], "payable": false, "stateMutability": "nonpayable", "type": "constructor"}, {"anonymous": false, "inputs": [{"indexed": false, "internalType": "string", "name": "message", "type": "string"}], "name": "LogDebug", "type": "event"}, {"anonymous": false, "inputs": [{"indexed": false, "internalType": "bytes32", "name": "message", "type": "bytes32"}], "name": "LogDebug", "type": "event"}, {"anonymous": false, "inputs": [{"indexed": false, "internalType": "bytes32", "name": "root", "type": "bytes32"}, {"indexed": false, "internalType": "bytes32[2]", "name": "nullifiers", "type": "bytes32[2]"}, {"indexed": false, "internalType": "bytes32[2]", "name": "commitments", "type": "bytes32[2]"}, {"indexed": false, "internalType": "bytes[2]", "name": "ciphertexts", "type": "bytes[2]"}], "name": "LogMix", "type": "event"}, {"constant": true, "inputs": [{"internalType": "uint256[9]", "name": "primary_inputs", "type": "uint256[9]"}], "name": "assemble_hsig", "outputs": [{"internalType": "bytes32", "name": "hsig", "type": "bytes32"}], "payable": false, "stateMutability": "pure", "type": "function"}, {"constant": true, "inputs": [{"internalType": "uint256", "name": "index", "type": "uint256"}, {"internalType": "uint256[9]", "name": "primary_inputs", "type": "uint256[9]"}], "name": "assemble_nullifier", "outputs": [{"internalType": "bytes32", "name": "nf", "type": "bytes32"}], "payable": false, "stateMutability": "pure", "type": "function"}, {"constant": true, "inputs": [{"internalType": "uint256[9]", "name": "primary_inputs", "type": "uint256[9]"}], "name": "assemble_public_values", "outputs": [{"internalType": "uint256", "name": "vpub_in", "type": "uint256"}, {"internalType": "uint256", "name": "vpub_out", "type": "uint256"}], "payable": false, "stateMutability": "pure", "type": "function"}, {"constant": true, "inputs": [], "name": "get_constants", "outputs": [{"internalType": "uint256", "name": "js_in", "type": "uint256"}, {"internalType": "uint256", "name": "js_out", "type": "uint256"}, {"internalType": "uint256", "name": "num_inputs", "type": "uint256"}], "payable": false, "stateMutability": "pure", "type": "function"}, {"constant": false, "inputs": [{"internalType": "bytes32", "name": "commitment", "type": "bytes32"}], "name": "insert", "outputs": [], "payable": false, "stateMutability": "nonpayable", "type": "function"}, {"constant": false, "inputs": [{"internalType": "uint256[2]", "name": "a", "type": "uint256[2]"}, {"internalType": "uint256[4]", "name": "b", "type": "uint256[4]"}, {"internalType": "uint256[2]", "name": "c", "type": "uint256[2]"}, {"internalType": "uint256[4]", "name": "vk", "type": "uint256[4]"}, {"internalType": "uint256", "name": "sigma", "type": "uint256"}, {"internalType": "uint256[9]", "name": "input", "type": "uint256[9]"}, {"internalType": "bytes[2]", "name": "ciphertexts", "type": "bytes[2]"}], "name": "mix", "outputs": [], "payable": true, "stateMutability": "payable", "type": "function"}, {"constant": false, "inputs": [{"internalType": "address", "name": "", "type": "address"}, {"internalType": "address", "name": "", "type": "address"}, {"internalType": "uint256", "name": "", "type": "uint256"}, {"internalType": "bytes", "name": "", "type": "bytes"}], "name": "onBAC001Received", "outputs": [{"internalType": "bytes4", "name": "", "type": "bytes4"}], "payable": false, "stateMutability": "nonpayable", "type": "function"}, {"constant": true, "inputs": [], "name": "token", "outputs": [{"internalType": "address", "name": "", "type": "address"}], "payable": false, "stateMutability": "view", "type": "function"}] \ No newline at end of file +[{"inputs": [{"internalType": "uint256", "name": "mk_depth", "type": "uint256"}, {"internalType": "address", "name": "token", "type": "address"}, {"internalType": "uint256[2]", "name": "Alpha", "type": "uint256[2]"}, {"internalType": "uint256[2]", "name": "Beta1", "type": "uint256[2]"}, {"internalType": "uint256[2]", "name": "Beta2", "type": "uint256[2]"}, {"internalType": "uint256[2]", "name": "Delta1", "type": "uint256[2]"}, {"internalType": "uint256[2]", "name": "Delta2", "type": "uint256[2]"}, {"internalType": "uint256[]", "name": "ABC_coords", "type": "uint256[]"}], "payable": false, "stateMutability": "nonpayable", "type": "constructor"}, {"anonymous": false, "inputs": [{"indexed": false, "internalType": "string", "name": "message", "type": "string"}], "name": "LogDebug", "type": "event"}, {"anonymous": false, "inputs": [{"indexed": false, "internalType": "bytes32", "name": "message", "type": "bytes32"}], "name": "LogDebug", "type": "event"}, {"anonymous": false, "inputs": [{"indexed": false, "internalType": "uint256", "name": "mid", "type": "uint256"}, {"indexed": false, "internalType": "bytes32", "name": "root", "type": "bytes32"}, {"indexed": false, "internalType": "bytes32[2]", "name": "nullifiers", "type": "bytes32[2]"}, {"indexed": false, "internalType": "bytes32[2]", "name": "commitments", "type": "bytes32[2]"}, {"indexed": false, "internalType": "bytes[2]", "name": "ciphertexts", "type": "bytes[2]"}], "name": "LogMix", "type": "event"}, {"constant": true, "inputs": [{"internalType": "uint256[10]", "name": "primary_inputs", "type": "uint256[10]"}], "name": "assemble_hsig", "outputs": [{"internalType": "bytes32", "name": "hsig", "type": "bytes32"}], "payable": false, "stateMutability": "pure", "type": "function"}, {"constant": true, "inputs": [{"internalType": "uint256", "name": "index", "type": "uint256"}, {"internalType": "uint256[10]", "name": "primary_inputs", "type": "uint256[10]"}], "name": "assemble_nullifier", "outputs": [{"internalType": "bytes32", "name": "nf", "type": "bytes32"}], "payable": false, "stateMutability": "pure", "type": "function"}, {"constant": true, "inputs": [{"internalType": "uint256[10]", "name": "primary_inputs", "type": "uint256[10]"}], "name": "assemble_public_values", "outputs": [{"internalType": "uint256", "name": "vpub_in", "type": "uint256"}, {"internalType": "uint256", "name": "vpub_out", "type": "uint256"}], "payable": false, "stateMutability": "pure", "type": "function"}, {"constant": true, "inputs": [], "name": "get_constants", "outputs": [{"internalType": "uint256", "name": "js_in", "type": "uint256"}, {"internalType": "uint256", "name": "js_out", "type": "uint256"}, {"internalType": "uint256", "name": "num_inputs", "type": "uint256"}], "payable": false, "stateMutability": "pure", "type": "function"}, {"constant": false, "inputs": [{"internalType": "bytes32", "name": "commitment", "type": "bytes32"}], "name": "insert", "outputs": [], "payable": false, "stateMutability": "nonpayable", "type": "function"}, {"constant": true, "inputs": [], "name": "mid", "outputs": [{"internalType": "uint256", "name": "", "type": "uint256"}], "payable": false, "stateMutability": "view", "type": "function"}, {"constant": false, "inputs": [{"internalType": "uint256[2]", "name": "a", "type": "uint256[2]"}, {"internalType": "uint256[4]", "name": "b", "type": "uint256[4]"}, {"internalType": "uint256[2]", "name": "c", "type": "uint256[2]"}, {"internalType": "uint256[4]", "name": "vk", "type": "uint256[4]"}, {"internalType": "uint256", "name": "sigma", "type": "uint256"}, {"internalType": "uint256[10]", "name": "input", "type": "uint256[10]"}, {"internalType": "bytes[2]", "name": "ciphertexts", "type": "bytes[2]"}], "name": "mix", "outputs": [], "payable": true, "stateMutability": "payable", "type": "function"}, {"constant": false, "inputs": [{"internalType": "address", "name": "", "type": "address"}, {"internalType": "address", "name": "", "type": "address"}, {"internalType": "uint256", "name": "", "type": "uint256"}, {"internalType": "bytes", "name": "", "type": "bytes"}], "name": "onBAC001Received", "outputs": [{"internalType": "bytes4", "name": "", "type": "bytes4"}], "payable": false, "stateMutability": "nonpayable", "type": "function"}, {"constant": true, "inputs": [], "name": "token", "outputs": [{"internalType": "address", "name": "", "type": "address"}], "payable": false, "stateMutability": "view", "type": "function"}] \ No newline at end of file diff --git a/contract/Groth16Mixer.bin b/contract/Groth16Mixer.bin index 82b926c..c33b91e 100644 --- a/contract/Groth16Mixer.bin +++ b/contract/Groth16Mixer.bin @@ -1 +1 @@ -60806040523480156200001157600080fd5b506040516200364e3803806200364e833981810160405262000037919081019062000685565b878781806005811462000081576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016200007890620008ba565b60405180910390fd5b50620000926200040360201b60201c565b506000806000603f8110620000a357fe5b0154905060016040600083815260200190815260200160002060006101000a81548160ff02191690831515021790555081604260006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555061010060fd106200015c576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401620001539062000876565b60405180910390fd5b60fd6002800260010160fd610100030260406002020110620001b5576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401620001ac9062000898565b60405180910390fd5b505050604051806040016040528087600060028110620001d157fe5b6020020151815260200187600160028110620001e957fe5b6020020151815250604360000160008201518160000155602082015181600101559050506040518060800160405280866000600281106200022657fe5b60200201518152602001866001600281106200023e57fe5b60200201518152602001856000600281106200025657fe5b60200201518152602001856001600281106200026e57fe5b6020020151815250604360020160008201518160000155602082015181600101556040820151816002015560608201518160030155905050604051806080016040528084600060028110620002bf57fe5b6020020151815260200184600160028110620002d757fe5b6020020151815260200183600060028110620002ef57fe5b60200201518152602001836001600281106200030757fe5b602002015181525060436006016000820151816000015560208201518160010155604082015181600201556060820151816003015590505060008090505b60028251816200035157fe5b046043600a018054905014620003f4576043600a0160405180604001604052808484815181106200037e57fe5b602002602001015181526020018460018501815181106200039b57fe5b602002602001015181525090806001815401808255809150509060018203906000526020600020906002020160009091929091909150600082015181600001556020820151816001015550505060028101905062000345565b505050505050505050620009d9565b60008060001b90508060006002600560020a60020203603f81106200042457fe5b018190555060006002600560020a816200043a57fe5b0490505b600081111562000495576200045f82836200049960201b620014e31760201c565b9150600060028260020203905082600082603f81106200047b57fe5b0181905550600282816200048b57fe5b049150506200043e565b5050565b60007fdec937b7fa8db3de380427a8cc947bfab68514522c3439cfa2e99655098368146000527f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f00000018284828282088381820984858383098683840909925060005b605a8112156200053457602060002080600052868688838808089350868485099250868488858a8788090909945050600181019050620004f9565b508484868a8888880808089550505050505092915050565b6000815190506200055d81620009a5565b92915050565b600082601f8301126200057557600080fd5b60026200058c62000586826200090a565b620008dc565b91508183856020840282011115620005a357600080fd5b60005b83811015620005d75781620005bc88826200066e565b845260208401935060208301925050600181019050620005a6565b5050505092915050565b600082601f830112620005f357600080fd5b81516200060a62000604826200092d565b620008dc565b915081818352602084019350602081019050838560208402820111156200063057600080fd5b60005b838110156200066457816200064988826200066e565b84526020840193506020830192505060018101905062000633565b5050505092915050565b6000815190506200067f81620009bf565b92915050565b6000806000806000806000806101a0898b031215620006a357600080fd5b6000620006b38b828c016200066e565b9850506020620006c68b828c016200054c565b9750506040620006d98b828c0162000563565b9650506080620006ec8b828c0162000563565b95505060c0620006ff8b828c0162000563565b945050610100620007138b828c0162000563565b935050610140620007278b828c0162000563565b92505061018089015167ffffffffffffffff8111156200074657600080fd5b620007548b828c01620005e1565b9150509295985092959890939650565b600062000773602d8362000956565b91507f41206861736820646967657374206669747320696e20612073696e676c65206660008301527f69656c6420656c656d656e742e000000000000000000000000000000000000006020830152604082019050919050565b6000620007db602b8362000956565b91507f546f6f206d616e7920696e70757420616e64206f7574707574206e6f7465732060008301527f636f6e736964657265642e0000000000000000000000000000000000000000006020830152604082019050919050565b600062000843601f8362000956565b91507f496e76616c696420646570746820696e20426173654d65726b6c6554726565006000830152602082019050919050565b60006020820190508181036000830152620008918162000764565b9050919050565b60006020820190508181036000830152620008b381620007cc565b9050919050565b60006020820190508181036000830152620008d58162000834565b9050919050565b6000604051905081810181811067ffffffffffffffff821117156200090057600080fd5b8060405250919050565b600067ffffffffffffffff8211156200092257600080fd5b602082029050919050565b600067ffffffffffffffff8211156200094557600080fd5b602082029050602081019050919050565b600082825260208201905092915050565b600062000974826200097b565b9050919050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b6000819050919050565b620009b08162000967565b8114620009bc57600080fd5b50565b620009ca816200099b565b8114620009d657600080fd5b50565b612c6580620009e96000396000f3fe60806040526004361061007b5760003560e01c806397e004891161004e57806397e0048914610161578063c73d16ae1461017d578063f9eb943f146101ba578063fc0c546a146101e75761007b565b806305ceb93c146100805780631f40927c146100bd5780632d287e43146100fb578063354d06fd14610124575b600080fd5b34801561008c57600080fd5b506100a760048036036100a29190810190611aaf565b610212565b6040516100b491906125c9565b60405180910390f35b3480156100c957600080fd5b506100e460048036036100df9190810190611a33565b610332565b6040516100f292919061282b565b60405180910390f35b34801561010757600080fd5b50610122600480360361011d9190810190611a5d565b6103af565b005b34801561013057600080fd5b5061014b60048036036101469190810190611a33565b610434565b60405161015891906125c9565b60405180910390f35b61017b60048036036101769190810190611978565b6104b2565b005b34801561018957600080fd5b506101a4600480360361019f91908101906118fd565b6106d4565b6040516101b19190612630565b60405180910390f35b3480156101c657600080fd5b506101cf6106e8565b6040516101de93929190612854565b60405180910390f35b3480156101f357600080fd5b506101fc61070c565b6040516102099190612528565b60405180910390f35b600060028310610257576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161024e9061264b565b60405180910390fd5b600060fd610100038460010102604060020201905060fd61010003810160fd10156102b7576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016102ae906126eb565b60405180910390fd5b600060fd826002800260010160fd610100030260406002020161010003018560028002600101600260010101600981106102ed57fe5b602002015160001b901b901c9050600060fd6101000385876002600101016009811061031557fe5b6020020151901b90508160001c810160001b935050505092915050565b600080600083600280026001016002600101016009811061034f57fe5b602002015190506002800260010160fd610100030281901c905064e8d4a5100067ffffffffffffffff168167ffffffffffffffff1602915064e8d4a5100067ffffffffffffffff16604082901c67ffffffffffffffff1602925050915091565b600560020a603f54106103f7576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016103ee906126cb565b60405180910390fd5b6000603f549050603f60008154600101919050819055506000816001600560020a0301905082600082603f811061042a57fe5b0181905550505050565b60008060fd60406002026002800260010160fd6101000302604060020201610100030184600280026001016002600101016009811061046f57fe5b602002015160001b901b901c9050600060fd6101000384600280600101016009811061049757fe5b6020020151901b90508160001c810160001b92505050919050565b6104ba611594565b6104c5858483610732565b600060023373ffffffffffffffffffffffffffffffffffffffff16846000600281106104ed57fe5b6020020151856001600281106104ff57fe5b60200201518c8c8c8a60405160200161051e97969594939291906124ae565b60405160208183030381529060405260405161053a9190612482565b602060405180830381855afa158015610557573d6000803e3d6000fd5b5050506040513d601f19601f8201168201806040525061057a9190810190611a86565b90506105ce8660006004811061058c57fe5b60200201518760016004811061059e57fe5b6020020151886002600481106105b057fe5b6020020151896003600481106105c257fe5b60200201518986610940565b61060d576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610604906127cb565b60405180910390fd5b61061989898987610a17565b610658576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161064f9061276b565b60405180910390fd5b610660611594565b61066a8582610c20565b60006106766002610c7c565b905061068181610cde565b7f36ed7c3f2ecfb5a5226c478b034d33144c060afe361be291e948f861dcddc618818584886040516106b694939291906125e4565b60405180910390a16106c786610d0d565b5050505050505050505050565b600063c73d16ae60e01b9050949350505050565b60008060006002925060029150600160028002600101600260010101019050909192565b604260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b604060008360006009811061074357fe5b602002015160001b815260200190815260200160002060009054906101000a900460ff166107a6576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161079d9061270b565b60405180910390fd5b60008090505b60028110156108745760006107c18285610212565b90506041600082815260200190815260200160002060009054906101000a900460ff1615610824576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161081b9061266b565b60405180910390fd5b60016041600083815260200190815260200160002060006101000a81548160ff0219169083151502179055508083836002811061085d57fe5b6020020181815250505080806001019150506107ac565b5060006002828560405160200161088c929190612456565b6040516020818303038152906040526040516108a89190612482565b602060405180830381855afa1580156108c5573d6000803e3d6000fd5b5050506040513d601f19601f820116820180604052506108e89190810190611a86565b905060006108f584610434565b9050808214610939576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016109309061272b565b60405180910390fd5b5050505050565b600061094a6115b6565b6107d05a038682528560208301528360408301526020608083016060846000600286f150604082018981528860208201526040816060836000600787f1506040836080856000600687f15060016040840152600260608401528560808401526040816060836000600787f1505050806002600581106109c557fe5b6020020151816000600581106109d757fe5b6020020151148015610a0a5750806003600581106109f157fe5b602002015181600160058110610a0357fe5b6020020151145b9150509695505050505050565b6000807f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f00000019050610a456115d8565b86600060028110610a5257fe5b602002015181600001818152505086600160028110610a6d57fe5b602002015181602001818152505085600060048110610a8857fe5b602002015181604001818152505085600160048110610aa357fe5b602002015181606001818152505085600260048110610abe57fe5b602002015181608001818152505085600360048110610ad957fe5b60200201518160a001818152505084600060028110610af457fe5b60200201518160c001818152505084600160028110610b0f57fe5b60200201518160e0018181525050606060016002800260010160026001010101604051908082528060200260200182016040528015610b5d5781602001602082028038833980820191505090505b50905060008090505b60016002800260010160026001010101811015610c055783868260098110610b8a57fe5b602002015110610bcf576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610bc6906127ab565b60405180910390fd5b858160098110610bdb57fe5b6020020151828281518110610bec57fe5b6020026020010181815250508080600101915050610b66565b50610c1081836110c5565b6001149350505050949350505050565b60008090505b6002811015610c77576000838260010160098110610c4057fe5b602002015160001b905080838360028110610c5757fe5b602002018181525050610c69816103af565b508080600101915050610c26565b505050565b600080603f549050600083603f540390506000600560020a90505b6001811115610cc557610cab8183856113e2565b809450819350505060028181610cbd57fe5b049050610c97565b600080603f8110610cd257fe5b01549350505050919050565b60016040600083815260200190815260200160002060006101000a81548160ff02191690831515021790555050565b600080610d1983610332565b915091506000821115610e6057600073ffffffffffffffffffffffffffffffffffffffff16604260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614610e18576000604260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1690508073ffffffffffffffffffffffffffffffffffffffff1663d0e7d6113330866040518463ffffffff1660e01b8152600401610de093929190612543565b600060405180830381600087803b158015610dfa57600080fd5b505af1158015610e0e573d6000803e3d6000fd5b5050505050610e5b565b813414610e5a576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610e519061278b565b60405180910390fd5b5b610f18565b6000341115610f175760003373ffffffffffffffffffffffffffffffffffffffff1634604051610e8f90612499565b60006040518083038185875af1925050503d8060008114610ecc576040519150601f19603f3d011682016040523d82523d6000602084013e610ed1565b606091505b5050905080610f15576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610f0c9061268b565b60405180910390fd5b505b5b60008111156110c057600073ffffffffffffffffffffffffffffffffffffffff16604260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614611011576000604260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1690508073ffffffffffffffffffffffffffffffffffffffff16639bd9bbc633846040518363ffffffff1660e01b8152600401610fd992919061258d565b600060405180830381600087803b158015610ff357600080fd5b505af1158015611007573d6000803e3d6000fd5b50505050506110bf565b60003373ffffffffffffffffffffffffffffffffffffffff168260405161103790612499565b60006040518083038185875af1925050503d8060008114611074576040519150601f19603f3d011682016040523d82523d6000602084013e611079565b606091505b50509050806110bd576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016110b4906126ab565b60405180910390fd5b505b5b505050565b60006043600a0180549050600184510114611115576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161110c9061274b565b60405180910390fd5b61111d61161d565b6000600190506107d05a03600a60430183526020832060208701875160200281018254865260018301546020870152600283019250604086015b818310156111a657835481526001840154602082015282516040820152604081606083600060078af160408860808a600060068bf1808216881697505050600284019350602083019250611157565b5050505050806111eb576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016111e29061280b565b60405180910390fd5b7f198e9393920d483a7260bfb731fb5d25f1aa493335a9e71297e485b7aef312c260408301527f1800deef121f1e76426a00665e5c4479674322d4f75edadd46debd5cd992f6ed60608301527f090689d0585ff075ec9e99ad690c3395bc4b313370b38ef355acdadcd122975b60808301527f12c85ea5db8c6deb4aab71808dcb408fe3d1e7690c43d37b4ce6cc0166fa7daa60a083015260435460c083015260016043015460e083015260026043015461010083015260036043015461012083015260046043015461014083015260056043015461016083015283516101808301527f30644e72e131a029b85045b68181585d97816a916871ca8d3c208c16d87cfd47602085015181810682036101a085015260408601516101c085015260608601516101e0850152608086015161020085015260a086015161022085015260c086015161024085015260e08601516102608501526006604301546102808501526007604301546102a08501526008604301546102c08501526009604301546102e085015260208461030086600060086107d05a03f192505050806113c6576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016113bd906127eb565b60405180910390fd5b816000601881106113d357fe5b60200201519250505092915050565b600080600060018603905060006001198616820190506000806001871614611459576001868401039050611435600082603f811061141c57fe5b0154600085600202603f811061142e57fe5b01546114e3565b60006002600184038161144457fe5b04603f811061144f57fe5b018190555061145f565b85830190505b5b818111156114bb57600281039050611497600082603f811061147e57fe5b0154600060018401603f811061149057fe5b01546114e3565b6000600260018403816114a657fe5b04603f81106114b157fe5b0181905550611460565b600287816114c557fe5b04600260018801816114d357fe5b0494509450505050935093915050565b60007fdec937b7fa8db3de380427a8cc947bfab68514522c3439cfa2e99655098368146000527f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f00000018284828282088381820984858383098683840909925060005b605a81121561157c57602060002080600052868688838808089350868485099250868488858a8788090909945050600181019050611543565b508484868a8888880808089550505050505092915050565b6040518060400160405280600290602082028038833980820191505090505090565b6040518060a00160405280600590602082028038833980820191505090505090565b60405180610100016040528060008152602001600081526020016000815260200160008152602001600081526020016000815260200160008152602001600081525090565b604051806103000160405280601890602082028038833980820191505090505090565b60008135905061164f81612bdd565b92915050565b600082601f83011261166657600080fd5b6002611679611674826128b8565b61288b565b9150818360005b838110156116b057813586016116968882611840565b845260208401935060208301925050600181019050611680565b5050505092915050565b600082601f8301126116cb57600080fd5b60026116de6116d9826128da565b61288b565b915081838560208402820111156116f457600080fd5b60005b83811015611724578161170a88826118e8565b8452602084019350602083019250506001810190506116f7565b5050505092915050565b600082601f83011261173f57600080fd5b600461175261174d826128fc565b61288b565b9150818385602084028201111561176857600080fd5b60005b83811015611798578161177e88826118e8565b84526020840193506020830192505060018101905061176b565b5050505092915050565b600082601f8301126117b357600080fd5b60096117c66117c18261291e565b61288b565b915081838560208402820111156117dc57600080fd5b60005b8381101561180c57816117f288826118e8565b8452602084019350602083019250506001810190506117df565b5050505092915050565b60008135905061182581612bf4565b92915050565b60008151905061183a81612bf4565b92915050565b600082601f83011261185157600080fd5b813561186461185f82612940565b61288b565b9150808252602083016020830185838301111561188057600080fd5b61188b838284612b80565b50505092915050565b600082601f8301126118a557600080fd5b81356118b86118b38261296c565b61288b565b915080825260208301602083018583830111156118d457600080fd5b6118df838284612b80565b50505092915050565b6000813590506118f781612c0b565b92915050565b6000806000806080858703121561191357600080fd5b600061192187828801611640565b945050602061193287828801611640565b9350506040611943878288016118e8565b925050606085013567ffffffffffffffff81111561196057600080fd5b61196c87828801611894565b91505092959194509250565b60008060008060008060006102e0888a03121561199457600080fd5b60006119a28a828b016116ba565b97505060406119b38a828b0161172e565b96505060c06119c48a828b016116ba565b9550506101006119d68a828b0161172e565b9450506101806119e88a828b016118e8565b9350506101a06119fa8a828b016117a2565b9250506102c088013567ffffffffffffffff811115611a1857600080fd5b611a248a828b01611655565b91505092959891949750929550565b60006101208284031215611a4657600080fd5b6000611a54848285016117a2565b91505092915050565b600060208284031215611a6f57600080fd5b6000611a7d84828501611816565b91505092915050565b600060208284031215611a9857600080fd5b6000611aa68482850161182b565b91505092915050565b6000806101408385031215611ac357600080fd5b6000611ad1858286016118e8565b9250506020611ae2858286016117a2565b9150509250929050565b6000611af88383611d8e565b60208301905092915050565b6000611b108383611dac565b60208301905092915050565b6000611b288383611dfb565b905092915050565b6000611b3c8383612430565b60208301905092915050565b611b5181612b4a565b82525050565b611b6081612ad8565b82525050565b611b6f816129ca565b611b798184612a58565b9250611b8482612998565b8060005b83811015611bb5578151611b9c8782611aec565b9650611ba783612a17565b925050600181019050611b88565b505050505050565b611bc6816129ca565b611bd08184612a63565b9250611bdb82612998565b8060005b83811015611c0c578151611bf38782611b04565b9650611bfe83612a17565b925050600181019050611bdf565b505050505050565b6000611c1f826129d5565b611c298185612a6e565b935083602082028501611c3b856129a2565b8060005b85811015611c775784840389528151611c588582611b1c565b9450611c6383612a24565b925060208a01995050600181019050611c3f565b50829750879550505050505092915050565b611c92816129e0565b611c9c8184612a79565b9250611ca7826129ac565b8060005b83811015611cd8578151611cbf8782611b30565b9650611cca83612a31565b925050600181019050611cab565b505050505050565b611ce9816129eb565b611cf38184612a84565b9250611cfe826129b6565b8060005b83811015611d2f578151611d168782611b30565b9650611d2183612a3e565b925050600181019050611d02565b505050505050565b611d40816129f6565b611d4a8184612a8f565b9250611d55826129c0565b8060005b83811015611d86578151611d6d8782611b30565b9650611d7883612a4b565b925050600181019050611d59565b505050505050565b611d9781612aea565b82525050565b611da681612aea565b82525050565b611db581612aea565b82525050565b611dc481612af4565b82525050565b6000611dd582612a0c565b611ddf8185612abc565b9350611def818560208601612b8f565b80840191505092915050565b6000611e0682612a01565b611e108185612a9a565b9350611e20818560208601612b8f565b611e2981612bcc565b840191505092915050565b6000611e3f82612a01565b611e498185612abc565b9350611e59818560208601612b8f565b80840191505092915050565b6000611e72601883612ac7565b91507f6e756c6c696669657220696e646578206f766572666c6f7700000000000000006000830152602082019050919050565b6000611eb2603783612ac7565b91507f496e76616c6964206e756c6c69666965723a2054686973206e756c6c6966696560008301527f722068617320616c7265616479206265656e20757365640000000000000000006020830152604082019050919050565b6000611f18601e83612ac7565b91507f767075625f696e2072657475726e207472616e73666572206661696c656400006000830152602082019050919050565b6000611f58601883612ac7565b91507f767075625f6f7574207472616e73666572206661696c656400000000000000006000830152602082019050919050565b6000611f98602783612ac7565b91507f4d65726b6c6520747265652066756c6c3a2043616e6e6f7420617070656e642060008301527f616e796d6f7265000000000000000000000000000000000000000000000000006020830152604082019050919050565b6000611ffe603083612ac7565b91507f6e756c6c6966696572207772697474656e20696e20646966666572656e74207260008301527f6573696475616c2062697420662e652e000000000000000000000000000000006020830152604082019050919050565b6000612064602583612ac7565b91507f496e76616c696420726f6f743a205468697320726f6f7420646f65736e27742060008301527f65786973740000000000000000000000000000000000000000000000000000006020830152604082019050919050565b60006120ca604983612ac7565b91507f496e76616c696420687369673a2054686973206873696720646f6573206e6f7460008301527f20636f72726573706f6e6420746f207468652068617368206f6620766b20616e60208301527f6420746865206e667300000000000000000000000000000000000000000000006040830152606082019050919050565b6000612156602283612ac7565b91507f496e707574206c656e67746820646966666572732066726f6d2065787065637460008301527f65640000000000000000000000000000000000000000000000000000000000006020830152604082019050919050565b60006121bc603383612ac7565b91507f496e76616c69642070726f6f663a20556e61626c6520746f207665726966792060008301527f7468652070726f6f6620636f72726563746c79000000000000000000000000006020830152604082019050919050565b6000612222602a83612ac7565b91507f57726f6e67206d73672e76616c75653a2056616c75652070616964206973206e60008301527f6f7420636f7272656374000000000000000000000000000000000000000000006020830152604082019050919050565b6000612288601c83612ac7565b91507f496e707574206973206e6f7420696e207363616c6172206669656c64000000006000830152602082019050919050565b60006122c8603b83612ac7565b91507f496e76616c6964207369676e61747572653a20556e61626c6520746f2076657260008301527f69667920746865207369676e617475726520636f72726563746c7900000000006020830152604082019050919050565b600061232e600083612aab565b9150600082019050919050565b6000612348600083612abc565b9150600082019050919050565b6000612362603783612ac7565b91507f43616c6c20746f20626e3235364164642c20626e3235365363616c61724d756c60008301527f206f7220626e32353650616972696e67206661696c65640000000000000000006020830152604082019050919050565b60006123c8603983612ac7565b91507f43616c6c20746f2074686520626e323536416464206f7220626e32353653636160008301527f6c61724d756c20707265636f6d70696c6564206661696c6564000000000000006020830152604082019050919050565b61242a81612b40565b82525050565b61243981612b40565b82525050565b61245061244b82612b40565b612bc2565b82525050565b60006124628285611bbd565b6040820191506124728284611ce0565b6080820191508190509392505050565b600061248e8284611dca565b915081905092915050565b60006124a48261233b565b9150819050919050565b60006124ba828a61243f565b6020820191506124ca8289611e34565b91506124d68288611e34565b91506124e28287611c89565b6040820191506124f28286611ce0565b6080820191506125028285611c89565b6040820191506125128284611d37565b6101208201915081905098975050505050505050565b600060208201905061253d6000830184611b57565b92915050565b60006080820190506125586000830186611b48565b6125656020830185611b57565b6125726040830184612421565b818103606083015261258381612321565b9050949350505050565b60006060820190506125a26000830185611b48565b6125af6020830184612421565b81810360408301526125c081612321565b90509392505050565b60006020820190506125de6000830184611d9d565b92915050565b600060c0820190506125f96000830187611d9d565b6126066020830186611b66565b6126136060830185611b66565b81810360a08301526126258184611c14565b905095945050505050565b60006020820190506126456000830184611dbb565b92915050565b6000602082019050818103600083015261266481611e65565b9050919050565b6000602082019050818103600083015261268481611ea5565b9050919050565b600060208201905081810360008301526126a481611f0b565b9050919050565b600060208201905081810360008301526126c481611f4b565b9050919050565b600060208201905081810360008301526126e481611f8b565b9050919050565b6000602082019050818103600083015261270481611ff1565b9050919050565b6000602082019050818103600083015261272481612057565b9050919050565b60006020820190508181036000830152612744816120bd565b9050919050565b6000602082019050818103600083015261276481612149565b9050919050565b60006020820190508181036000830152612784816121af565b9050919050565b600060208201905081810360008301526127a481612215565b9050919050565b600060208201905081810360008301526127c48161227b565b9050919050565b600060208201905081810360008301526127e4816122bb565b9050919050565b6000602082019050818103600083015261280481612355565b9050919050565b60006020820190508181036000830152612824816123bb565b9050919050565b60006040820190506128406000830185612421565b61284d6020830184612421565b9392505050565b60006060820190506128696000830186612421565b6128766020830185612421565b6128836040830184612421565b949350505050565b6000604051905081810181811067ffffffffffffffff821117156128ae57600080fd5b8060405250919050565b600067ffffffffffffffff8211156128cf57600080fd5b602082029050919050565b600067ffffffffffffffff8211156128f157600080fd5b602082029050919050565b600067ffffffffffffffff82111561291357600080fd5b602082029050919050565b600067ffffffffffffffff82111561293557600080fd5b602082029050919050565b600067ffffffffffffffff82111561295757600080fd5b601f19601f8301169050602081019050919050565b600067ffffffffffffffff82111561298357600080fd5b601f19601f8301169050602081019050919050565b6000819050919050565b6000819050919050565b6000819050919050565b6000819050919050565b6000819050919050565b600060029050919050565b600060029050919050565b600060029050919050565b600060049050919050565b600060099050919050565b600081519050919050565b600081519050919050565b6000602082019050919050565b6000602082019050919050565b6000602082019050919050565b6000602082019050919050565b6000602082019050919050565b600081905092915050565b600081905092915050565b600081905092915050565b600081905092915050565b600081905092915050565b600081905092915050565b600082825260208201905092915050565b600082825260208201905092915050565b600081905092915050565b600082825260208201905092915050565b6000612ae382612b20565b9050919050565b6000819050919050565b60007fffffffff0000000000000000000000000000000000000000000000000000000082169050919050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b6000819050919050565b6000612b5582612b5c565b9050919050565b6000612b6782612b6e565b9050919050565b6000612b7982612b20565b9050919050565b82818337600083830152505050565b60005b83811015612bad578082015181840152602081019050612b92565b83811115612bbc576000848401525b50505050565b6000819050919050565b6000601f19601f8301169050919050565b612be681612ad8565b8114612bf157600080fd5b50565b612bfd81612aea565b8114612c0857600080fd5b50565b612c1481612b40565b8114612c1f57600080fd5b5056fea365627a7a7231582015c071139d561376dc726ac2a4746c70b465ba5933ab1663b55ed1c13980d2086c6578706572696d656e74616cf564736f6c63430005110040 \ No newline at end of file +6080604052600080553480156200001557600080fd5b506040516200393b3803806200393b83398181016040526200003b9190810190620006cf565b878781806005811462000085576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016200007c9062000904565b60405180910390fd5b50620000966200042960201b60201c565b506000600160008081526020019081526020016000206000603f8110620000b957fe5b01549050600160036000808152602001908152602001600020600083815260200190815260200160002060006101000a81548160ff02191690831515021790555081600560006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555061010060fd1062000183576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016200017a90620008c0565b60405180910390fd5b60fd6002800260010160fd610100030260406002020110620001dc576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401620001d390620008e2565b60405180910390fd5b505050604051806040016040528087600060028110620001f857fe5b60200201518152602001876001600281106200021057fe5b6020020151815250600660000160008201518160000155602082015181600101559050506040518060800160405280866000600281106200024d57fe5b60200201518152602001866001600281106200026557fe5b60200201518152602001856000600281106200027d57fe5b60200201518152602001856001600281106200029557fe5b6020020151815250600660020160008201518160000155602082015181600101556040820151816002015560608201518160030155905050604051806080016040528084600060028110620002e657fe5b6020020151815260200184600160028110620002fe57fe5b60200201518152602001836000600281106200031657fe5b60200201518152602001836001600281106200032e57fe5b6020020151815250600680016000820151816000015560208201518160010155604082015181600201556060820151816003015590505060008090505b60028251816200037757fe5b046006600a0180549050146200041a576006600a016040518060400160405280848481518110620003a457fe5b60200260200101518152602001846001850181518110620003c157fe5b60200260200101518152509080600181540180825580915050906001820390600052602060002090600202016000909192909190915060008201518160000155602082015181600101555050506002810190506200036b565b50505050505050505062000a23565b60008060001b90508060016000805481526020019081526020016000206002600560020a60020203603f81106200045c57fe5b018190555060006002600560020a816200047257fe5b0490505b6000811115620004df57620004978283620004e360201b620011e91760201c565b9150600060028260020203905082600160008054815260200190815260200160002082603f8110620004c557fe5b018190555060028281620004d557fe5b0491505062000476565b5050565b60007fdec937b7fa8db3de380427a8cc947bfab68514522c3439cfa2e99655098368146000527f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f00000018284828282088381820984858383098683840909925060005b605a8112156200057e57602060002080600052868688838808089350868485099250868488858a878809090994505060018101905062000543565b508484868a8888880808089550505050505092915050565b600081519050620005a781620009ef565b92915050565b600082601f830112620005bf57600080fd5b6002620005d6620005d08262000954565b62000926565b91508183856020840282011115620005ed57600080fd5b60005b83811015620006215781620006068882620006b8565b845260208401935060208301925050600181019050620005f0565b5050505092915050565b600082601f8301126200063d57600080fd5b8151620006546200064e8262000977565b62000926565b915081818352602084019350602081019050838560208402820111156200067a57600080fd5b60005b83811015620006ae5781620006938882620006b8565b8452602084019350602083019250506001810190506200067d565b5050505092915050565b600081519050620006c98162000a09565b92915050565b6000806000806000806000806101a0898b031215620006ed57600080fd5b6000620006fd8b828c01620006b8565b9850506020620007108b828c0162000596565b9750506040620007238b828c01620005ad565b9650506080620007368b828c01620005ad565b95505060c0620007498b828c01620005ad565b9450506101006200075d8b828c01620005ad565b935050610140620007718b828c01620005ad565b92505061018089015167ffffffffffffffff8111156200079057600080fd5b6200079e8b828c016200062b565b9150509295985092959890939650565b6000620007bd602d83620009a0565b91507f41206861736820646967657374206669747320696e20612073696e676c65206660008301527f69656c6420656c656d656e742e000000000000000000000000000000000000006020830152604082019050919050565b600062000825602b83620009a0565b91507f546f6f206d616e7920696e70757420616e64206f7574707574206e6f7465732060008301527f636f6e736964657265642e0000000000000000000000000000000000000000006020830152604082019050919050565b60006200088d601f83620009a0565b91507f496e76616c696420646570746820696e20426173654d65726b6c6554726565006000830152602082019050919050565b60006020820190508181036000830152620008db81620007ae565b9050919050565b60006020820190508181036000830152620008fd8162000816565b9050919050565b600060208201905081810360008301526200091f816200087e565b9050919050565b6000604051905081810181811067ffffffffffffffff821117156200094a57600080fd5b8060405250919050565b600067ffffffffffffffff8211156200096c57600080fd5b602082029050919050565b600067ffffffffffffffff8211156200098f57600080fd5b602082029050602081019050919050565b600082825260208201905092915050565b6000620009be82620009c5565b9050919050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b6000819050919050565b620009fa81620009b1565b811462000a0657600080fd5b50565b62000a1481620009e5565b811462000a2057600080fd5b50565b612f088062000a336000396000f3fe6080604052600436106100865760003560e01c80634773862d116100595780634773862d1461015a578063a52f1ea814610176578063c73d16ae146101b3578063f9eb943f146101f0578063fc0c546a1461021d57610086565b80632d287e431461008b5780632e94420f146100b45780633e49ba65146100df57806346deb3411461011d575b600080fd5b34801561009757600080fd5b506100b260048036036100ad9190810190611cd7565b610248565b005b3480156100c057600080fd5b506100c9610318565b6040516100d69190612a59565b60405180910390f35b3480156100eb57600080fd5b5061010660048036036101019190810190611bf2565b61031e565b604051610114929190612ace565b60405180910390f35b34801561012957600080fd5b50610144600480360361013f9190810190611bf2565b61039a565b6040516101519190612843565b60405180910390f35b610174600480360361016f9190810190611c1c565b610417565b005b34801561018257600080fd5b5061019d60048036036101989190810190611d29565b61063d565b6040516101aa9190612843565b60405180910390f35b3480156101bf57600080fd5b506101da60048036036101d59190810190611b77565b61075b565b6040516101e7919061285e565b60405180910390f35b3480156101fc57600080fd5b5061020561076f565b60405161021493929190612af7565b60405180910390f35b34801561022957600080fd5b50610232610792565b60405161023f91906127a2565b60405180910390f35b600560020a60025410610290576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610287906128f9565b60405180910390fd5b60026000815460010191905081905550600560020a60025414156102c3576001600054016000819055506102c26107b8565b5b600560020a600254816102d257fe5b06600281905550600060025490506000816001600560020a0301905082600160008054815260200190815260200160002082603f811061030e57fe5b0181905550505050565b60005481565b600080600083600280026001016002800101600a811061033a57fe5b602002015190506002800260010160fd610100030281901c905064e8d4a5100067ffffffffffffffff168167ffffffffffffffff1602915064e8d4a5100067ffffffffffffffff16604082901c67ffffffffffffffff1602925050915091565b60008060fd60406002026002800260010160fd6101000302604060020201610100030184600280026001016002800101600a81106103d457fe5b602002015160001b901b901c9050600060fd610100038460028060020101600a81106103fc57fe5b6020020151901b90508160001c810160001b92505050919050565b61041f61180e565b61042a85848361085f565b600060023373ffffffffffffffffffffffffffffffffffffffff168460006002811061045257fe5b60200201518560016002811061046457fe5b60200201518c8c8c8a6040516020016104839796959493929190612728565b60405160208183030381529060405260405161049f91906126fc565b602060405180830381855afa1580156104bc573d6000803e3d6000fd5b5050506040513d601f19601f820116820180604052506104df9190810190611d00565b9050610533866000600481106104f157fe5b60200201518760016004811061050357fe5b60200201518860026004811061051557fe5b60200201518960036004811061052757fe5b60200201518986610a41565b610572576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610569906129f9565b60405180910390fd5b61057e89898987610b18565b6105bd576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016105b490612999565b60405180910390fd5b6105c561180e565b6105cf8582610d1f565b60006105db6002610d7b565b90506105e681610df0565b7f5b20d7b970f991ad433adaa73d15ec55f2dc64ddfecb9505eb1f94e330ecddf76000548286858960405161061f959493929190612a74565b60405180910390a161063086610e31565b5050505050505050505050565b600060028310610682576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161067990612879565b60405180910390fd5b600060fd610100038460010102604060020201905060fd61010003810160fd10156106e2576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016106d990612919565b60405180910390fd5b600060fd826002800260010160fd6101000302604060020201610100030185600280026001016002800101600a811061071757fe5b602002015160001b901b901c9050600060fd6101000385876002800101600a811061073e57fe5b6020020151901b90508160001c810160001b935050505092915050565b600063c73d16ae60e01b9050949350505050565b600080600060029250600291506001600280026001016002800101019050909192565b600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b60008060001b90508060016000805481526020019081526020016000206002600560020a60020203603f81106107ea57fe5b018190555060006002600560020a816107ff57fe5b0490505b600081111561085b5761081682836111e9565b9150600060028260020203905082600160008054815260200190815260200160002082603f811061084357fe5b01819055506002828161085257fe5b04915050610803565b5050565b6108688261129a565b6108a7576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161089e90612939565b60405180910390fd5b60008090505b60028110156109755760006108c2828561063d565b90506004600082815260200190815260200160002060009054906101000a900460ff1615610925576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161091c90612899565b60405180910390fd5b60016004600083815260200190815260200160002060006101000a81548160ff0219169083151502179055508083836002811061095e57fe5b6020020181815250505080806001019150506108ad565b5060006002828560405160200161098d9291906126d0565b6040516020818303038152906040526040516109a991906126fc565b602060405180830381855afa1580156109c6573d6000803e3d6000fd5b5050506040513d601f19601f820116820180604052506109e99190810190611d00565b905060006109f68461039a565b9050808214610a3a576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610a3190612959565b60405180910390fd5b5050505050565b6000610a4b611830565b6107d05a038682528560208301528360408301526020608083016060846000600286f150604082018981528860208201526040816060836000600787f1506040836080856000600687f15060016040840152600260608401528560808401526040816060836000600787f150505080600260058110610ac657fe5b602002015181600060058110610ad857fe5b6020020151148015610b0b575080600360058110610af257fe5b602002015181600160058110610b0457fe5b6020020151145b9150509695505050505050565b6000807f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f00000019050610b46611852565b86600060028110610b5357fe5b602002015181600001818152505086600160028110610b6e57fe5b602002015181602001818152505085600060048110610b8957fe5b602002015181604001818152505085600160048110610ba457fe5b602002015181606001818152505085600260048110610bbf57fe5b602002015181608001818152505085600360048110610bda57fe5b60200201518160a001818152505084600060028110610bf557fe5b60200201518160c001818152505084600160028110610c1057fe5b60200201518160e00181815250506060600160028002600101600280010101604051908082528060200260200182016040528015610c5d5781602001602082028038833980820191505090505b50905060008090505b600160028002600101600280010101811015610d0457838682600a8110610c8957fe5b602002015110610cce576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610cc5906129d9565b60405180910390fd5b8581600a8110610cda57fe5b6020020151828281518110610ceb57fe5b6020026020010181815250508080600101915050610c66565b50610d0f8183611385565b6001149350505050949350505050565b60008090505b6002811015610d765760008382600201600a8110610d3f57fe5b602002015160001b905080838360028110610d5657fe5b602002018181525050610d6881610248565b508080600101915050610d25565b505050565b60008060025490506000836002540390506000600560020a90505b6001811115610dc457610daa8183856116a1565b809450819350505060028181610dbc57fe5b049050610d96565b60016000805481526020019081526020016000206000603f8110610de457fe5b01549350505050919050565b60016003600080548152602001908152602001600020600083815260200190815260200160002060006101000a81548160ff02191690831515021790555050565b600080610e3d8361031e565b915091506000821115610f8457600073ffffffffffffffffffffffffffffffffffffffff16600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614610f3c576000600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1690508073ffffffffffffffffffffffffffffffffffffffff1663d0e7d6113330866040518463ffffffff1660e01b8152600401610f04939291906127bd565b600060405180830381600087803b158015610f1e57600080fd5b505af1158015610f32573d6000803e3d6000fd5b5050505050610f7f565b813414610f7e576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610f75906129b9565b60405180910390fd5b5b61103c565b600034111561103b5760003373ffffffffffffffffffffffffffffffffffffffff1634604051610fb390612713565b60006040518083038185875af1925050503d8060008114610ff0576040519150601f19603f3d011682016040523d82523d6000602084013e610ff5565b606091505b5050905080611039576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611030906128b9565b60405180910390fd5b505b5b60008111156111e457600073ffffffffffffffffffffffffffffffffffffffff16600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614611135576000600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1690508073ffffffffffffffffffffffffffffffffffffffff16639bd9bbc633846040518363ffffffff1660e01b81526004016110fd929190612807565b600060405180830381600087803b15801561111757600080fd5b505af115801561112b573d6000803e3d6000fd5b50505050506111e3565b60003373ffffffffffffffffffffffffffffffffffffffff168260405161115b90612713565b60006040518083038185875af1925050503d8060008114611198576040519150601f19603f3d011682016040523d82523d6000602084013e61119d565b606091505b50509050806111e1576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016111d8906128d9565b60405180910390fd5b505b5b505050565b60007fdec937b7fa8db3de380427a8cc947bfab68514522c3439cfa2e99655098368146000527f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f00000018284828282088381820984858383098683840909925060005b605a81121561128257602060002080600052868688838808089350868485099250868488858a8788090909945050600181019050611249565b508484868a8888880808089550505050505092915050565b6000806000905060008090505b600054811161137957600360008281526020019081526020016000206000856000600a81106112d257fe5b602002015160001b815260200190815260200160002060009054906101000a900460ff16156113045781806001019250505b600360008281526020019081526020016000206000856001600a811061132657fe5b602002015160001b815260200190815260200160002060009054906101000a900460ff16156113585781806001019250505b600282141561136c57600192505050611380565b80806001019150506112a7565b5060009150505b919050565b60006006600a01805490506001845101146113d5576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016113cc90612979565b60405180910390fd5b6113dd611897565b6000600190506107d05a03600a60060183526020832060208701875160200281018254865260018301546020870152600283019250604086015b8183101561146657835481526001840154602082015282516040820152604081606083600060078af160408860808a600060068bf1808216881697505050600284019350602083019250611417565b5050505050806114ab576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016114a290612a39565b60405180910390fd5b7f198e9393920d483a7260bfb731fb5d25f1aa493335a9e71297e485b7aef312c260408301527f1800deef121f1e76426a00665e5c4479674322d4f75edadd46debd5cd992f6ed60608301527f090689d0585ff075ec9e99ad690c3395bc4b313370b38ef355acdadcd122975b60808301527f12c85ea5db8c6deb4aab71808dcb408fe3d1e7690c43d37b4ce6cc0166fa7daa60a083015260065460c083015260016006015460e083015260026006015461010083015260036006015461012083015260046006015461014083015260056006015461016083015283516101808301527f30644e72e131a029b85045b68181585d97816a916871ca8d3c208c16d87cfd47602085015181810682036101a085015260408601516101c085015260608601516101e0850152608086015161020085015260a086015161022085015260c086015161024085015260e086015161026085015260068001546102808501526007600601546102a08501526008600601546102c08501526009600601546102e085015260208461030086600060086107d05a03f19250505080611685576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161167c90612a19565b60405180910390fd5b8160006018811061169257fe5b60200201519250505092915050565b60008060006001860390506000600119861682019050600080600187161461174e576001868401039050611718600160008054815260200190815260200160002082603f81106116ed57fe5b0154600160008054815260200190815260200160002085600202603f811061171157fe5b01546111e9565b60016000805481526020019081526020016000206002600184038161173957fe5b04603f811061174457fe5b0181905550611754565b85830190505b5b818111156117e6576002810390506117b0600160008054815260200190815260200160002082603f811061178557fe5b0154600160008054815260200190815260200160002060018401603f81106117a957fe5b01546111e9565b6001600080548152602001908152602001600020600260018403816117d157fe5b04603f81106117dc57fe5b0181905550611755565b600287816117f057fe5b04600260018801816117fe57fe5b0494509450505050935093915050565b6040518060400160405280600290602082028038833980820191505090505090565b6040518060a00160405280600590602082028038833980820191505090505090565b60405180610100016040528060008152602001600081526020016000815260200160008152602001600081526020016000815260200160008152602001600081525090565b604051806103000160405280601890602082028038833980820191505090505090565b6000813590506118c981612e80565b92915050565b600082601f8301126118e057600080fd5b60026118f36118ee82612b5b565b612b2e565b9150818360005b8381101561192a57813586016119108882611aba565b8452602084019350602083019250506001810190506118fa565b5050505092915050565b600082601f83011261194557600080fd5b600a61195861195382612b7d565b612b2e565b9150818385602084028201111561196e57600080fd5b60005b8381101561199e57816119848882611b62565b845260208401935060208301925050600181019050611971565b5050505092915050565b600082601f8301126119b957600080fd5b60026119cc6119c782612b9f565b612b2e565b915081838560208402820111156119e257600080fd5b60005b83811015611a1257816119f88882611b62565b8452602084019350602083019250506001810190506119e5565b5050505092915050565b600082601f830112611a2d57600080fd5b6004611a40611a3b82612bc1565b612b2e565b91508183856020840282011115611a5657600080fd5b60005b83811015611a865781611a6c8882611b62565b845260208401935060208301925050600181019050611a59565b5050505092915050565b600081359050611a9f81612e97565b92915050565b600081519050611ab481612e97565b92915050565b600082601f830112611acb57600080fd5b8135611ade611ad982612be3565b612b2e565b91508082526020830160208301858383011115611afa57600080fd5b611b05838284612e23565b50505092915050565b600082601f830112611b1f57600080fd5b8135611b32611b2d82612c0f565b612b2e565b91508082526020830160208301858383011115611b4e57600080fd5b611b59838284612e23565b50505092915050565b600081359050611b7181612eae565b92915050565b60008060008060808587031215611b8d57600080fd5b6000611b9b878288016118ba565b9450506020611bac878288016118ba565b9350506040611bbd87828801611b62565b925050606085013567ffffffffffffffff811115611bda57600080fd5b611be687828801611b0e565b91505092959194509250565b60006101408284031215611c0557600080fd5b6000611c1384828501611934565b91505092915050565b6000806000806000806000610300888a031215611c3857600080fd5b6000611c468a828b016119a8565b9750506040611c578a828b01611a1c565b96505060c0611c688a828b016119a8565b955050610100611c7a8a828b01611a1c565b945050610180611c8c8a828b01611b62565b9350506101a0611c9e8a828b01611934565b9250506102e088013567ffffffffffffffff811115611cbc57600080fd5b611cc88a828b016118cf565b91505092959891949750929550565b600060208284031215611ce957600080fd5b6000611cf784828501611a90565b91505092915050565b600060208284031215611d1257600080fd5b6000611d2084828501611aa5565b91505092915050565b6000806101608385031215611d3d57600080fd5b6000611d4b85828601611b62565b9250506020611d5c85828601611934565b9150509250929050565b6000611d728383612008565b60208301905092915050565b6000611d8a8383612026565b60208301905092915050565b6000611da28383612075565b905092915050565b6000611db683836126aa565b60208301905092915050565b611dcb81612ded565b82525050565b611dda81612d7b565b82525050565b611de981612c6d565b611df38184612cfb565b9250611dfe82612c3b565b8060005b83811015611e2f578151611e168782611d66565b9650611e2183612cba565b925050600181019050611e02565b505050505050565b611e4081612c6d565b611e4a8184612d06565b9250611e5582612c3b565b8060005b83811015611e86578151611e6d8782611d7e565b9650611e7883612cba565b925050600181019050611e59565b505050505050565b6000611e9982612c78565b611ea38185612d11565b935083602082028501611eb585612c45565b8060005b85811015611ef15784840389528151611ed28582611d96565b9450611edd83612cc7565b925060208a01995050600181019050611eb9565b50829750879550505050505092915050565b611f0c81612c83565b611f168184612d1c565b9250611f2182612c4f565b8060005b83811015611f52578151611f398782611daa565b9650611f4483612cd4565b925050600181019050611f25565b505050505050565b611f6381612c8e565b611f6d8184612d27565b9250611f7882612c59565b8060005b83811015611fa9578151611f908782611daa565b9650611f9b83612ce1565b925050600181019050611f7c565b505050505050565b611fba81612c99565b611fc48184612d32565b9250611fcf82612c63565b8060005b83811015612000578151611fe78782611daa565b9650611ff283612cee565b925050600181019050611fd3565b505050505050565b61201181612d8d565b82525050565b61202081612d8d565b82525050565b61202f81612d8d565b82525050565b61203e81612d97565b82525050565b600061204f82612caf565b6120598185612d5f565b9350612069818560208601612e32565b80840191505092915050565b600061208082612ca4565b61208a8185612d3d565b935061209a818560208601612e32565b6120a381612e6f565b840191505092915050565b60006120b982612ca4565b6120c38185612d5f565b93506120d3818560208601612e32565b80840191505092915050565b60006120ec601883612d6a565b91507f6e756c6c696669657220696e646578206f766572666c6f7700000000000000006000830152602082019050919050565b600061212c603783612d6a565b91507f496e76616c6964206e756c6c69666965723a2054686973206e756c6c6966696560008301527f722068617320616c7265616479206265656e20757365640000000000000000006020830152604082019050919050565b6000612192601e83612d6a565b91507f767075625f696e2072657475726e207472616e73666572206661696c656400006000830152602082019050919050565b60006121d2601883612d6a565b91507f767075625f6f7574207472616e73666572206661696c656400000000000000006000830152602082019050919050565b6000612212602783612d6a565b91507f4d65726b6c6520747265652066756c6c3a2043616e6e6f7420617070656e642060008301527f616e796d6f7265000000000000000000000000000000000000000000000000006020830152604082019050919050565b6000612278603083612d6a565b91507f6e756c6c6966696572207772697474656e20696e20646966666572656e74207260008301527f6573696475616c2062697420662e652e000000000000000000000000000000006020830152604082019050919050565b60006122de602583612d6a565b91507f496e76616c696420726f6f743a205468697320726f6f7420646f65736e27742060008301527f65786973740000000000000000000000000000000000000000000000000000006020830152604082019050919050565b6000612344604983612d6a565b91507f496e76616c696420687369673a2054686973206873696720646f6573206e6f7460008301527f20636f72726573706f6e6420746f207468652068617368206f6620766b20616e60208301527f6420746865206e667300000000000000000000000000000000000000000000006040830152606082019050919050565b60006123d0602283612d6a565b91507f496e707574206c656e67746820646966666572732066726f6d2065787065637460008301527f65640000000000000000000000000000000000000000000000000000000000006020830152604082019050919050565b6000612436603383612d6a565b91507f496e76616c69642070726f6f663a20556e61626c6520746f207665726966792060008301527f7468652070726f6f6620636f72726563746c79000000000000000000000000006020830152604082019050919050565b600061249c602a83612d6a565b91507f57726f6e67206d73672e76616c75653a2056616c75652070616964206973206e60008301527f6f7420636f7272656374000000000000000000000000000000000000000000006020830152604082019050919050565b6000612502601c83612d6a565b91507f496e707574206973206e6f7420696e207363616c6172206669656c64000000006000830152602082019050919050565b6000612542603b83612d6a565b91507f496e76616c6964207369676e61747572653a20556e61626c6520746f2076657260008301527f69667920746865207369676e617475726520636f72726563746c7900000000006020830152604082019050919050565b60006125a8600083612d4e565b9150600082019050919050565b60006125c2600083612d5f565b9150600082019050919050565b60006125dc603783612d6a565b91507f43616c6c20746f20626e3235364164642c20626e3235365363616c61724d756c60008301527f206f7220626e32353650616972696e67206661696c65640000000000000000006020830152604082019050919050565b6000612642603983612d6a565b91507f43616c6c20746f2074686520626e323536416464206f7220626e32353653636160008301527f6c61724d756c20707265636f6d70696c6564206661696c6564000000000000006020830152604082019050919050565b6126a481612de3565b82525050565b6126b381612de3565b82525050565b6126ca6126c582612de3565b612e65565b82525050565b60006126dc8285611e37565b6040820191506126ec8284611fb1565b6080820191508190509392505050565b60006127088284612044565b915081905092915050565b600061271e826125b5565b9150819050919050565b6000612734828a6126b9565b60208201915061274482896120ae565b915061275082886120ae565b915061275c8287611f5a565b60408201915061276c8286611fb1565b60808201915061277c8285611f5a565b60408201915061278c8284611f03565b6101408201915081905098975050505050505050565b60006020820190506127b76000830184611dd1565b92915050565b60006080820190506127d26000830186611dc2565b6127df6020830185611dd1565b6127ec604083018461269b565b81810360608301526127fd8161259b565b9050949350505050565b600060608201905061281c6000830185611dc2565b612829602083018461269b565b818103604083015261283a8161259b565b90509392505050565b60006020820190506128586000830184612017565b92915050565b60006020820190506128736000830184612035565b92915050565b60006020820190508181036000830152612892816120df565b9050919050565b600060208201905081810360008301526128b28161211f565b9050919050565b600060208201905081810360008301526128d281612185565b9050919050565b600060208201905081810360008301526128f2816121c5565b9050919050565b6000602082019050818103600083015261291281612205565b9050919050565b600060208201905081810360008301526129328161226b565b9050919050565b60006020820190508181036000830152612952816122d1565b9050919050565b6000602082019050818103600083015261297281612337565b9050919050565b60006020820190508181036000830152612992816123c3565b9050919050565b600060208201905081810360008301526129b281612429565b9050919050565b600060208201905081810360008301526129d28161248f565b9050919050565b600060208201905081810360008301526129f2816124f5565b9050919050565b60006020820190508181036000830152612a1281612535565b9050919050565b60006020820190508181036000830152612a32816125cf565b9050919050565b60006020820190508181036000830152612a5281612635565b9050919050565b6000602082019050612a6e600083018461269b565b92915050565b600060e082019050612a89600083018861269b565b612a966020830187612017565b612aa36040830186611de0565b612ab06080830185611de0565b81810360c0830152612ac28184611e8e565b90509695505050505050565b6000604082019050612ae3600083018561269b565b612af0602083018461269b565b9392505050565b6000606082019050612b0c600083018661269b565b612b19602083018561269b565b612b26604083018461269b565b949350505050565b6000604051905081810181811067ffffffffffffffff82111715612b5157600080fd5b8060405250919050565b600067ffffffffffffffff821115612b7257600080fd5b602082029050919050565b600067ffffffffffffffff821115612b9457600080fd5b602082029050919050565b600067ffffffffffffffff821115612bb657600080fd5b602082029050919050565b600067ffffffffffffffff821115612bd857600080fd5b602082029050919050565b600067ffffffffffffffff821115612bfa57600080fd5b601f19601f8301169050602081019050919050565b600067ffffffffffffffff821115612c2657600080fd5b601f19601f8301169050602081019050919050565b6000819050919050565b6000819050919050565b6000819050919050565b6000819050919050565b6000819050919050565b600060029050919050565b600060029050919050565b6000600a9050919050565b600060029050919050565b600060049050919050565b600081519050919050565b600081519050919050565b6000602082019050919050565b6000602082019050919050565b6000602082019050919050565b6000602082019050919050565b6000602082019050919050565b600081905092915050565b600081905092915050565b600081905092915050565b600081905092915050565b600081905092915050565b600081905092915050565b600082825260208201905092915050565b600082825260208201905092915050565b600081905092915050565b600082825260208201905092915050565b6000612d8682612dc3565b9050919050565b6000819050919050565b60007fffffffff0000000000000000000000000000000000000000000000000000000082169050919050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b6000819050919050565b6000612df882612dff565b9050919050565b6000612e0a82612e11565b9050919050565b6000612e1c82612dc3565b9050919050565b82818337600083830152505050565b60005b83811015612e50578082015181840152602081019050612e35565b83811115612e5f576000848401525b50505050565b6000819050919050565b6000601f19601f8301169050919050565b612e8981612d7b565b8114612e9457600080fd5b50565b612ea081612d8d565b8114612eab57600080fd5b50565b612eb781612de3565b8114612ec257600080fd5b5056fea365627a7a72315820bbb7c67e4f7643068dc730e4d702259c054025afbb61541c4f7d157f70e5ba6f6c6578706572696d656e74616cf564736f6c63430005110040 \ No newline at end of file diff --git a/contract/Groth16Mixer.py b/contract/Groth16Mixer.py index c00af77..86bc259 100644 --- a/contract/Groth16Mixer.py +++ b/contract/Groth16Mixer.py @@ -1,16 +1,16 @@ # template for codegen -from eth_utils import to_checksum_address - from python_web3.client.bcosclient import ( BcosClient ) from python_web3.client.datatype_parser import DatatypeParser import json +from eth_utils import to_checksum_address + class Groth16Mixer: # name of abi address = None - contract_abi_string = '''[{"inputs": [{"internalType": "uint256", "name": "mk_depth", "type": "uint256"}, {"internalType": "address", "name": "token", "type": "address"}, {"internalType": "uint256[2]", "name": "Alpha", "type": "uint256[2]"}, {"internalType": "uint256[2]", "name": "Beta1", "type": "uint256[2]"}, {"internalType": "uint256[2]", "name": "Beta2", "type": "uint256[2]"}, {"internalType": "uint256[2]", "name": "Delta1", "type": "uint256[2]"}, {"internalType": "uint256[2]", "name": "Delta2", "type": "uint256[2]"}, {"internalType": "uint256[]", "name": "ABC_coords", "type": "uint256[]"}], "payable": false, "stateMutability": "nonpayable", "type": "constructor"}, {"anonymous": false, "inputs": [{"indexed": false, "internalType": "string", "name": "message", "type": "string"}], "name": "LogDebug", "type": "event", "topic": "0xd44da6836c8376d1693e8b9cacf1c39b9bed3599164ad6d8e60902515f83938e"}, {"anonymous": false, "inputs": [{"indexed": false, "internalType": "bytes32", "name": "message", "type": "bytes32"}], "name": "LogDebug", "type": "event", "topic": "0x05e46912c9be87d8a6830598db8544b61884d9d22f3921597a9a6e8a340914b3"}, {"anonymous": false, "inputs": [{"indexed": false, "internalType": "bytes32", "name": "root", "type": "bytes32"}, {"indexed": false, "internalType": "bytes32[2]", "name": "nullifiers", "type": "bytes32[2]"}, {"indexed": false, "internalType": "bytes32[2]", "name": "commitments", "type": "bytes32[2]"}, {"indexed": false, "internalType": "bytes[2]", "name": "ciphertexts", "type": "bytes[2]"}], "name": "LogMix", "type": "event", "topic": "0x36ed7c3f2ecfb5a5226c478b034d33144c060afe361be291e948f861dcddc618"}, {"constant": true, "inputs": [{"internalType": "uint256[9]", "name": "primary_inputs", "type": "uint256[9]"}], "name": "assemble_hsig", "outputs": [{"internalType": "bytes32", "name": "hsig", "type": "bytes32"}], "payable": false, "stateMutability": "pure", "type": "function"}, {"constant": true, "inputs": [{"internalType": "uint256", "name": "index", "type": "uint256"}, {"internalType": "uint256[9]", "name": "primary_inputs", "type": "uint256[9]"}], "name": "assemble_nullifier", "outputs": [{"internalType": "bytes32", "name": "nf", "type": "bytes32"}], "payable": false, "stateMutability": "pure", "type": "function"}, {"constant": true, "inputs": [{"internalType": "uint256[9]", "name": "primary_inputs", "type": "uint256[9]"}], "name": "assemble_public_values", "outputs": [{"internalType": "uint256", "name": "vpub_in", "type": "uint256"}, {"internalType": "uint256", "name": "vpub_out", "type": "uint256"}], "payable": false, "stateMutability": "pure", "type": "function"}, {"constant": true, "inputs": [], "name": "get_constants", "outputs": [{"internalType": "uint256", "name": "js_in", "type": "uint256"}, {"internalType": "uint256", "name": "js_out", "type": "uint256"}, {"internalType": "uint256", "name": "num_inputs", "type": "uint256"}], "payable": false, "stateMutability": "pure", "type": "function"}, {"constant": false, "inputs": [{"internalType": "bytes32", "name": "commitment", "type": "bytes32"}], "name": "insert", "outputs": [], "payable": false, "stateMutability": "nonpayable", "type": "function"}, {"constant": false, "inputs": [{"internalType": "uint256[2]", "name": "a", "type": "uint256[2]"}, {"internalType": "uint256[4]", "name": "b", "type": "uint256[4]"}, {"internalType": "uint256[2]", "name": "c", "type": "uint256[2]"}, {"internalType": "uint256[4]", "name": "vk", "type": "uint256[4]"}, {"internalType": "uint256", "name": "sigma", "type": "uint256"}, {"internalType": "uint256[9]", "name": "input", "type": "uint256[9]"}, {"internalType": "bytes[2]", "name": "ciphertexts", "type": "bytes[2]"}], "name": "mix", "outputs": [], "payable": true, "stateMutability": "payable", "type": "function"}, {"constant": false, "inputs": [{"internalType": "address", "name": "", "type": "address"}, {"internalType": "address", "name": "", "type": "address"}, {"internalType": "uint256", "name": "", "type": "uint256"}, {"internalType": "bytes", "name": "", "type": "bytes"}], "name": "onBAC001Received", "outputs": [{"internalType": "bytes4", "name": "", "type": "bytes4"}], "payable": false, "stateMutability": "nonpayable", "type": "function"}, {"constant": true, "inputs": [], "name": "token", "outputs": [{"internalType": "address", "name": "", "type": "address"}], "payable": false, "stateMutability": "view", "type": "function"}]''' + contract_abi_string = '''[{"inputs": [{"internalType": "uint256", "name": "mk_depth", "type": "uint256"}, {"internalType": "address", "name": "token", "type": "address"}, {"internalType": "uint256[2]", "name": "Alpha", "type": "uint256[2]"}, {"internalType": "uint256[2]", "name": "Beta1", "type": "uint256[2]"}, {"internalType": "uint256[2]", "name": "Beta2", "type": "uint256[2]"}, {"internalType": "uint256[2]", "name": "Delta1", "type": "uint256[2]"}, {"internalType": "uint256[2]", "name": "Delta2", "type": "uint256[2]"}, {"internalType": "uint256[]", "name": "ABC_coords", "type": "uint256[]"}], "payable": false, "stateMutability": "nonpayable", "type": "constructor"}, {"anonymous": false, "inputs": [{"indexed": false, "internalType": "string", "name": "message", "type": "string"}], "name": "LogDebug", "type": "event", "topic": "0xd44da6836c8376d1693e8b9cacf1c39b9bed3599164ad6d8e60902515f83938e"}, {"anonymous": false, "inputs": [{"indexed": false, "internalType": "bytes32", "name": "message", "type": "bytes32"}], "name": "LogDebug", "type": "event", "topic": "0x05e46912c9be87d8a6830598db8544b61884d9d22f3921597a9a6e8a340914b3"}, {"anonymous": false, "inputs": [{"indexed": false, "internalType": "uint256", "name": "mid", "type": "uint256"}, {"indexed": false, "internalType": "bytes32", "name": "root", "type": "bytes32"}, {"indexed": false, "internalType": "bytes32[2]", "name": "nullifiers", "type": "bytes32[2]"}, {"indexed": false, "internalType": "bytes32[2]", "name": "commitments", "type": "bytes32[2]"}, {"indexed": false, "internalType": "bytes[2]", "name": "ciphertexts", "type": "bytes[2]"}], "name": "LogMix", "type": "event", "topic": "0x5b20d7b970f991ad433adaa73d15ec55f2dc64ddfecb9505eb1f94e330ecddf7"}, {"constant": true, "inputs": [{"internalType": "uint256[10]", "name": "primary_inputs", "type": "uint256[10]"}], "name": "assemble_hsig", "outputs": [{"internalType": "bytes32", "name": "hsig", "type": "bytes32"}], "payable": false, "stateMutability": "pure", "type": "function"}, {"constant": true, "inputs": [{"internalType": "uint256", "name": "index", "type": "uint256"}, {"internalType": "uint256[10]", "name": "primary_inputs", "type": "uint256[10]"}], "name": "assemble_nullifier", "outputs": [{"internalType": "bytes32", "name": "nf", "type": "bytes32"}], "payable": false, "stateMutability": "pure", "type": "function"}, {"constant": true, "inputs": [{"internalType": "uint256[10]", "name": "primary_inputs", "type": "uint256[10]"}], "name": "assemble_public_values", "outputs": [{"internalType": "uint256", "name": "vpub_in", "type": "uint256"}, {"internalType": "uint256", "name": "vpub_out", "type": "uint256"}], "payable": false, "stateMutability": "pure", "type": "function"}, {"constant": true, "inputs": [], "name": "get_constants", "outputs": [{"internalType": "uint256", "name": "js_in", "type": "uint256"}, {"internalType": "uint256", "name": "js_out", "type": "uint256"}, {"internalType": "uint256", "name": "num_inputs", "type": "uint256"}], "payable": false, "stateMutability": "pure", "type": "function"}, {"constant": false, "inputs": [{"internalType": "bytes32", "name": "commitment", "type": "bytes32"}], "name": "insert", "outputs": [], "payable": false, "stateMutability": "nonpayable", "type": "function"}, {"constant": true, "inputs": [], "name": "mid", "outputs": [{"internalType": "uint256", "name": "", "type": "uint256"}], "payable": false, "stateMutability": "view", "type": "function"}, {"constant": false, "inputs": [{"internalType": "uint256[2]", "name": "a", "type": "uint256[2]"}, {"internalType": "uint256[4]", "name": "b", "type": "uint256[4]"}, {"internalType": "uint256[2]", "name": "c", "type": "uint256[2]"}, {"internalType": "uint256[4]", "name": "vk", "type": "uint256[4]"}, {"internalType": "uint256", "name": "sigma", "type": "uint256"}, {"internalType": "uint256[10]", "name": "input", "type": "uint256[10]"}, {"internalType": "bytes[2]", "name": "ciphertexts", "type": "bytes[2]"}], "name": "mix", "outputs": [], "payable": true, "stateMutability": "payable", "type": "function"}, {"constant": false, "inputs": [{"internalType": "address", "name": "", "type": "address"}, {"internalType": "address", "name": "", "type": "address"}, {"internalType": "uint256", "name": "", "type": "uint256"}, {"internalType": "bytes", "name": "", "type": "bytes"}], "name": "onBAC001Received", "outputs": [{"internalType": "bytes4", "name": "", "type": "bytes4"}], "payable": false, "stateMutability": "nonpayable", "type": "function"}, {"constant": true, "inputs": [], "name": "token", "outputs": [{"internalType": "address", "name": "", "type": "address"}], "payable": false, "stateMutability": "view", "type": "function"}]''' contract_abi = None data_parser = DatatypeParser() client = None @@ -62,6 +62,13 @@ def insert(self, commitment): outputresult = self.data_parser.parse_receipt_output(func_name, receipt['output']) return outputresult, receipt + # ------------------------------------------ + def mid(self): + func_name = 'mid' + args = [] + result = self.client.call(self.address, self.contract_abi, func_name, args) + return result + # ------------------------------------------ def mix(self, a, b, c, vk, sigma, input, ciphertexts): func_name = 'mix' diff --git a/zeth/constants.py b/zeth/constants.py index 4ae3d43..c61fe6b 100644 --- a/zeth/constants.py +++ b/zeth/constants.py @@ -97,7 +97,7 @@ def bit_length_to_byte_length(bit_length: int) -> int: # [2 + jsOut + 2*jsIn] - 1 x residual bits, v_in, v_out # Index (in public inputs) of residual bits -RESIDUAL_BITS_INDEX: int = (2 * JS_INPUTS) + JS_OUTPUTS + 2 +RESIDUAL_BITS_INDEX: int = (2 * JS_INPUTS) + JS_OUTPUTS + 3 # Number of full-length digests to be encoded in public inputs NUM_INPUT_DIGESTS: int = (2 * JS_INPUTS) + 1 diff --git a/zeth/contracts.py b/zeth/contracts.py index 1f5c14c..f3f20ef 100644 --- a/zeth/contracts.py +++ b/zeth/contracts.py @@ -84,9 +84,11 @@ class MixResult: """ def __init__( self, + mid: int, new_merkle_root: bytes, nullifiers: List[bytes], output_events: List[MixOutputEvents]): + self.mid = mid self.new_merkle_root = new_merkle_root self.nullifiers = nullifiers self.output_events = output_events @@ -96,6 +98,7 @@ def _event_args_to_mix_result(event_args: Any) -> MixResult: mix_out_args = zip(event_args.commitments, event_args.ciphertexts) out_events = [MixOutputEvents(c, ciph) for (c, ciph) in mix_out_args] return MixResult( + mid = event_args.mid, new_merkle_root=event_args.root, nullifiers=event_args.nullifiers, output_events=out_events) @@ -180,12 +183,10 @@ def instantiate(self, web3: Any) -> Any: Return the instantiated contract """ return web3.eth.contract(address=self.address, abi=self.abi) -''' def get_block_number(web3: Any) -> int: return web3.eth.blockNumber -''' def install_sol() -> None: solcx.install_solc(SOL_COMPILER_VERSION) diff --git a/zeth/merkle_tree.py b/zeth/merkle_tree.py index db00358..e10fabc 100644 --- a/zeth/merkle_tree.py +++ b/zeth/merkle_tree.py @@ -245,11 +245,12 @@ def __init__( self, tree_data: MerkleTreeData, depth: int): MerkleTree.__init__(self, tree_data, depth) - def open(max_num_leaves: int) -> sqlMerkleTree: + def open(max_num_leaves: int, mid: int) -> sqlMerkleTree: depth = int(math.log(max_num_leaves, 2)) - sqlSearch = "select * from merkletree" - cursor.execute(sqlSearch) + sqlSearch = "select * from merkletree where MID=%s" + cursor.execute(sqlSearch, [mid]) results = cursor.fetchall() + db.commit() if not results: tree_data = MerkleTreeData.empty_with_depth(depth) else: @@ -260,19 +261,22 @@ def open(max_num_leaves: int) -> sqlMerkleTree: assert depth == tree_data.depth return sqlMerkleTree(tree_data, depth) - def save(self, blockNumber : int) -> None: - sqlSearch = "select * from merkletree" - cursor.execute(sqlSearch) + def save(self, blockNumber: int, mid: int) -> None: + sqlSearch = "select * from merkletree where MID=%s" + cursor.execute(sqlSearch, [mid]) results = cursor.fetchall() if not results: json_str = json.dumps(self.tree_data.to_json_dict()) print("json_str: ", json_str) print("blockNumber: ", blockNumber) - sqlInsert = "insert into merkletree (tree_data, blockNumber) values (%s, %s);" - cursor.execute(sqlInsert, [json_str, blockNumber]) + sqlInsert = "insert into merkletree (MID, tree_data, blockNumber) values (%s, %s, %s);" + cursor.execute(sqlInsert, [mid, json_str, blockNumber]) db.commit() + # make sure the inserting row's MID == mid + sqlSearch = "select * from merkletree where MID=%s" + cursor.execute(sqlSearch, [mid]) + assert cursor.fetchall() else: - result = results[0] json_str = json.dumps(self.tree_data.to_json_dict()) #json_str = pymysql.escape_string(json_str) #print("json_str: ", json_str) @@ -285,7 +289,7 @@ def save(self, blockNumber : int) -> None: ''' sqlUpdate = "update merkletree set tree_data=%s, blockNumber=%s where MID=%s;" #print("sqlUpdate: ", sqlUpdate) - cursor.execute(sqlUpdate, [json_str, blockNumber, result[0]]) + cursor.execute(sqlUpdate, [json_str, blockNumber, mid]) db.commit() diff --git a/zeth/mixer_client.py b/zeth/mixer_client.py index e5b970a..38d29c0 100644 --- a/zeth/mixer_client.py +++ b/zeth/mixer_client.py @@ -225,7 +225,7 @@ def get_dummy_input_and_address( def compute_joinsplit2x2_inputs( - mk_root: bytes, + mk_roots: List[bytes], input0: Tuple[int, ZethNote], mk_path0: List[str], input1: Tuple[int, ZethNote], @@ -271,9 +271,11 @@ def compute_joinsplit2x2_inputs( output_note0, output_note1 ] - + merkle_roots = [] + for mk_root in mk_roots: + merkle_roots.append(mk_root.hex()) return ProofInputs( - mk_root=mk_root.hex(), + mk_roots=merkle_roots, js_inputs=js_inputs, js_outputs=js_outputs, pub_in_value=int64_to_hex(public_in_value_zeth_units), @@ -357,7 +359,7 @@ def deploy( ''' def deposit( self, - mk_tree: MerkleTree, + mk_trees: List[MerkleTree], zeth_address: ZethAddress, sender_eth_address: str, eth_amount: EtherValue, @@ -367,7 +369,7 @@ def deposit( if not outputs or len(outputs) == 0: outputs = [(zeth_address.addr_pk, eth_amount)] return self.joinsplit( - mk_tree, + mk_trees, sender_ownership_keypair=zeth_address.ownership_keypair(), sender_eth_address=sender_eth_address, inputs=[], @@ -378,7 +380,7 @@ def deposit( def joinsplit( self, - mk_tree: MerkleTree, + mk_trees: List[MerkleTree], sender_ownership_keypair: OwnershipKeyPair, sender_eth_address: str, inputs: List[Tuple[int, ZethNote]], @@ -388,7 +390,7 @@ def joinsplit( tx_value: Optional[EtherValue] = None, compute_h_sig_cb: Optional[ComputeHSigCB] = None) -> str: mix_params = self.create_mix_parameters( - mk_tree, + mk_trees, sender_ownership_keypair, sender_eth_address, inputs, @@ -408,7 +410,7 @@ def joinsplit( def create_mix_parameters_keep_signing_key( self, - mk_tree: MerkleTree, + mk_trees: List[MerkleTree], sender_ownership_keypair: OwnershipKeyPair, sender_eth_address: str, inputs: List[Tuple[int, ZethNote]], @@ -426,8 +428,14 @@ def create_mix_parameters_keep_signing_key( inputs + \ [get_dummy_input_and_address(sender_a_pk) for _ in range(constants.JS_INPUTS - len(inputs))] - mk_root = mk_tree.get_root() - mk_paths = [compute_merkle_path(addr, mk_tree) for addr, _ in inputs] + mk_roots = [] + mk_paths = [] + for mk_tree in mk_trees: + mk_roots.append(mk_tree.get_root()) + print("merkle_roots: ", mk_roots) + mk_paths.append(compute_merkle_path(inputs[0][0], mk_trees[0])) + mk_paths.append(compute_merkle_path(inputs[1][0], mk_trees[1])) + #mk_paths = [compute_merkle_path(addr, mk_tree) for addr, _ in inputs] # Generate output notes and proof. Dummy outputs are constructed with # value 0 to an invalid ZethAddressPub, formed from the senders @@ -447,7 +455,7 @@ def create_mix_parameters_keep_signing_key( (output_note1, output_note2, proof_json, signing_keypair) = \ self.get_proof_joinsplit_2_by_2( - mk_root, + mk_roots, inputs[0], mk_paths[0], inputs[1], @@ -485,7 +493,7 @@ def create_mix_parameters_keep_signing_key( def create_mix_parameters( self, - mk_tree: MerkleTree, + mk_trees: List[MerkleTree], sender_ownership_keypair: OwnershipKeyPair, sender_eth_address: str, inputs: List[Tuple[int, ZethNote]], @@ -495,7 +503,7 @@ def create_mix_parameters( compute_h_sig_cb: Optional[ComputeHSigCB] = None ) -> contracts.MixParameters: mix_params, _sig_keypair = self.create_mix_parameters_keep_signing_key( - mk_tree, + mk_trees, sender_ownership_keypair, sender_eth_address, inputs, @@ -535,7 +543,7 @@ def mix_call( ''' def get_proof_joinsplit_2_by_2( self, - mk_root: bytes, + mk_roots: List[bytes], input0: Tuple[int, ZethNote], mk_path0: List[str], input1: Tuple[int, ZethNote], @@ -553,7 +561,7 @@ def get_proof_joinsplit_2_by_2( """ signing_keypair = signing.gen_signing_keypair() proof_input = compute_joinsplit2x2_inputs( - mk_root, + mk_roots, input0, mk_path0, input1, diff --git a/zeth/wallet.py b/zeth/wallet.py index 7f2e9c5..9405185 100644 --- a/zeth/wallet.py +++ b/zeth/wallet.py @@ -36,8 +36,9 @@ class ZethNoteDescription: All secret data about a single ZethNote, including address in the merkle tree and the commit value. """ - def __init__(self, note: ZethNote, address: int, commitment: bytes): + def __init__(self, note: ZethNote, mid: int, address: int, commitment: bytes): self.note = note + self.mid = mid self.address = address self.commitment = commitment @@ -50,6 +51,7 @@ def as_input(self) -> Tuple[int, ZethNote]: def to_json(self) -> str: json_dict = { "note": zeth_note_to_json_dict(self.note), + "mid": str(self.mid), "address": str(self.address), "commitment": self.commitment.hex(), } @@ -60,6 +62,7 @@ def from_json(json_str: str) -> ZethNoteDescription: json_dict = json.loads(json_str) return ZethNoteDescription( note=zeth_note_from_json_dict(json_dict["note"]), + mid = int(json_dict["mid"]), address=int(json_dict["address"]), commitment=bytes.fromhex(json_dict["commitment"])) @@ -122,7 +125,9 @@ def __init__( mixer_instance: Any, username: str, wallet_dir: str, - secret_address: ZethAddressPriv): + secret_address: ZethAddressPriv, + mid: int, + next_addr: int): # k_sk_receiver: EncryptionSecretKey): assert "_" not in username self.mixer_instance = mixer_instance @@ -132,15 +137,20 @@ def __init__( self.k_sk_receiver = secret_address.k_sk self.state_file = join(wallet_dir, f"state_{username}") self.state = _load_state_or_default(self.state_file) + self.mid = mid + self.next_addr = next_addr _ensure_dir(join(self.wallet_dir, SPENT_SUBDIRECTORY)) + ''' self.merkle_tree = sqlMerkleTree.open( int(math.pow(2, ZETH_MERKLE_TREE_DEPTH))) self.merkle_tree_changed = False self.next_addr = self.merkle_tree.get_num_entries() self.blockNumber = 1; + ''' def receive_note( self, + mid: int, comm_addr: int, out_ev: MixOutputEvents) -> Optional[ZethNoteDescription]: # Check this output event to see if it belongs to this wallet. @@ -152,7 +162,7 @@ def receive_note( if not _check_note(commit, note): return None - note_desc = ZethNoteDescription(note, comm_addr, commit) + note_desc = ZethNoteDescription(note, mid, comm_addr, commit) self._write_note(note_desc) # Add the nullifier to the map in the state file @@ -170,20 +180,30 @@ def receive_notes( """ new_notes = [] - self.merkle_tree_changed = len(output_events) != 0 + #self.merkle_tree_changed = len(output_events) != 0 + ''' + if self.next_addrs[0] == self.next_addrs[1]: + self.next_addrs[1] = self.next_addrs[0] + 1 + for i in range(2): + print( + f"wallet.receive_notes: idx:{self.next_addrs[i]}, " + + f"comm:{output_events[i].commitment[:8].hex()}") + note_desc = self.receive_note(self.mids[i], self.next_addrs[i], output_events[i]) + if note_desc is not None: + new_notes.append(note_desc) + ''' for out_ev in output_events: print( f"wallet.receive_notes: idx:{self.next_addr}, " + f"comm:{out_ev.commitment[:8].hex()}") # All commitments must be added to the tree in order. - self.merkle_tree.insert(out_ev.commitment) - note_desc = self.receive_note(self.next_addr, out_ev) + #self.merkle_tree.insert(out_ev.commitment) + note_desc = self.receive_note(self.mid, self.next_addr, out_ev) if note_desc is not None: new_notes.append(note_desc) self.next_addr = self.next_addr + 1 - # Record full set of notes seen to keep an estimate of the total in the # mixer. self.state.num_notes = self.state.num_notes + len(output_events) @@ -217,29 +237,16 @@ def spent_note_summaries(self) -> Iterator[Tuple[int, str, EtherValue]]: """ return self._decode_note_files_in_dir( join(self.wallet_dir, SPENT_SUBDIRECTORY)) - + ''' def get_next_block(self) -> int: return self.state.next_block - + ''' def update_and_save_state(self) -> None: #self.state.next_block = next_block - self._save_merkle_tree_if_changed() + #self._save_merkle_tree_if_changed() _save_state(self.state_file, self.state) - def find_note(self, note_id: str) -> ZethNoteDescription: - note_file = self._find_note_file(note_id) - if not note_file: - raise Exception(f"no note with id {note_id}") - with open(note_file, "r") as note_f: - return ZethNoteDescription.from_json(note_f.read()) - - def _save_merkle_tree_if_changed(self) -> None: - if self.merkle_tree_changed: - self.merkle_tree_changed = False - self.merkle_tree.recompute_root() - self.merkle_tree.save(self.blockNumber) - def _write_note(self, note_desc: ZethNoteDescription) -> None: """ Write a note to the database (currently just a file-per-note). @@ -248,6 +255,13 @@ def _write_note(self, note_desc: ZethNoteDescription) -> None: with open(note_filename, "w") as note_f: note_f.write(note_desc.to_json()) + def find_note(self, note_id: str) -> ZethNoteDescription: + note_file = self._find_note_file(note_id) + if not note_file: + raise Exception(f"no note with id {note_id}") + with open(note_file, "r") as note_f: + return ZethNoteDescription.from_json(note_f.read()) + def _mark_note_spent(self, nullifier_hex: str, short_commit: str) -> None: """ Mark a note as having been spent. Find the file, move it to the `spent` @@ -264,15 +278,15 @@ def _mark_note_spent(self, nullifier_hex: str, short_commit: str) -> None: def _note_basename(self, note_desc: ZethNoteDescription) -> str: value_eth = from_zeth_units(int(note_desc.note.value, 16)).ether() cm_str = short_commitment(note_desc.commitment) - return "note_%s_%04d_%s_%s" % ( - self.username, note_desc.address, cm_str, value_eth) + return "note_%s_%d_%04d_%s_%s" % ( + self.username, note_desc.mid, note_desc.address, cm_str, value_eth) @staticmethod def _decode_basename(filename: str) -> Tuple[int, str, EtherValue]: components = filename.split("_") - addr = int(components[2]) - short_commit = components[3] - value = EtherValue(components[4], 'ether') + addr = int(components[3]) + short_commit = components[4] + value = EtherValue(components[5], 'ether') return (addr, short_commit, value) def _decode_note_files_in_dir( diff --git a/zkclientapp/models.py b/zkclientapp/models.py index 1b9ff48..7d8fa92 100644 --- a/zkclientapp/models.py +++ b/zkclientapp/models.py @@ -4,6 +4,6 @@ class merkletree(models.Model): class Meta: db_table = 'merkletree' - mid = models.AutoField(db_column='MID',primary_key=True) + mid = models.IntegerField(db_column='MID',primary_key=True) tree_data = models.TextField(max_length=40000, db_column='tree_data', blank=False) blockNumber = models.IntegerField(db_column='blockNumber', default=1) diff --git a/zkclientapp/routes.py b/zkclientapp/routes.py index 0687e3d..2c2bfe3 100644 --- a/zkclientapp/routes.py +++ b/zkclientapp/routes.py @@ -6,7 +6,7 @@ from commands.zeth_token_deploy import deploy_asset from commands.zeth_deploy import deploy from commands.zeth_mix import mix -from commands.zeth_ls_commits import ls_commits +#from commands.zeth_ls_commits import ls_commits from commands.zeth_ls_notes import ls_notes from commands.zeth_deploy import deploy from commands.utils import load_zeth_address, load_zeth_address_secret, open_wallet, parse_output, load_zeth_address_public @@ -16,6 +16,7 @@ from python_web3.eth_account.account import Account from commands.constants import USER_DIR, FISCO_ADDRESS_FILE, WALLET_DIR_DEFAULT, ADDRESS_FILE_DEFAULT from django.shortcuts import render +from api.zeth_messages_pb2 import ZethNote import json import time from django.http import JsonResponse @@ -26,7 +27,6 @@ from . import models from .models import merkletree - ''' The wallet of user is designed as that every wallet need to be specified a username and store the reference accounts and assets data of that user. There two kinds of account in the wallet of a user, @@ -55,8 +55,13 @@ def checkUser(request) ->None: result['status'] = 1 result['text'] = 'your account is not recorded in server, please import it firstly or create a new one' return JsonResponse(result) +''' +make wallet by generate a new Fisco account for user with username and password +params: +username:str +password:str -def genAccount(request) -> None: +def genFiscoAddr(request) -> None: result = {} req = json.loads(request.body) keystore_file = "{}/{}/{}".format(USER_DIR, req['username'], FISCO_ADDRESS_FILE) @@ -64,31 +69,16 @@ def genAccount(request) -> None: result['status'] = 1 result['text'] = 'username existed' return JsonResponse(result) - addr_file = "{}/{}/{}".format(USER_DIR, req['username'], ADDRESS_FILE_DEFAULT) - if exists(addr_file): - result['status'] = 1 - result['text'] = 'account existed' - return JsonResponse(result) (address, publickey, privatekey) = gen_fisco_address(req['username'], req['password']) - zbac_addr = gen_address(req['username']) - pubkey = ''.join(['%02X' % b for b in publickey]) - prikey = ''.join(['%02X' % b for b in privatekey]) result['status'] = 0 - result['fisco_address'] = address + result['address'] = address + pubkey = ''.join(['%02X' % b for b in publickey]) result['publickey'] = "0x" + pubkey.lower() + prikey = ''.join(['%02X' % b for b in privatekey]) result['privatekey'] = "0x" + prikey.lower() - result['zbac_address'] = str(zbac_addr) return JsonResponse(result) - - - ''' -make wallet by generate a new Fisco account for user with username and password -params: -username:str -password:str - -def genFiscoAddr(request) -> None: +def genAccount(request) -> None: result = {} req = json.loads(request.body) keystore_file = "{}/{}/{}".format(USER_DIR, req['username'], FISCO_ADDRESS_FILE) @@ -96,16 +86,22 @@ def genFiscoAddr(request) -> None: result['status'] = 1 result['text'] = 'username existed' return JsonResponse(result) + addr_file = "{}/{}/{}".format(USER_DIR, req['username'], ADDRESS_FILE_DEFAULT) + if exists(addr_file): + result['status'] = 1 + result['text'] = 'account existed' + return JsonResponse(result) (address, publickey, privatekey) = gen_fisco_address(req['username'], req['password']) - result['status'] = 0 - result['address'] = address + zbac_addr = gen_address(req['username']) pubkey = ''.join(['%02X' % b for b in publickey]) - result['publickey'] = "0x" + pubkey.lower() prikey = ''.join(['%02X' % b for b in privatekey]) + result['status'] = 0 + result['fisco_address'] = address + result['publickey'] = "0x" + pubkey.lower() result['privatekey'] = "0x" + prikey.lower() + result['zbac_address'] = str(zbac_addr) return JsonResponse(result) ''' -''' make wallet by import the Fisco account that the user want to use with privatekey, username and password params: username:str @@ -317,11 +313,14 @@ def mixBac(request) -> None: addr_file = "{}/{}/{}".format(USER_DIR, req['username'], ADDRESS_FILE_DEFAULT) if exists(keystore_file) and exists(addr_file): js_secret = load_zeth_address_secret(req['username']) - wallet = open_wallet(None, js_secret, req['username']) + wallet = open_wallet(None, js_secret, req['username'], None, None) inputs: List[Tuple[int, ZethNote]] = [ wallet.find_note(note_id).as_input() for note_id in req['input_notes']] outputs: List[Tuple[ZethAddressPub, EtherValue]] = [ parse_output(out_spec) for out_spec in req['output_specs']] + mids = [] + for note_id in req['input_notes']: + mids.append(wallet.find_note(note_id).mid) ''' todo: check the reciever zeth_address whether record in server, if not, return / by searching the address in mysql, so for every zeth account, we need to save their zeth_address in mysql when generating / @@ -350,7 +349,7 @@ def mixBac(request) -> None: result['status'] = 1 result['text'] = 'token approve failed' return JsonResponse(result) - outputmix = mix(req['mixer_address'], req['username'], req['password'], vin_pub, vout_pub, inputs, outputs) + outputmix = mix(req['mixer_address'], req['username'], req['password'], vin_pub, vout_pub, inputs, outputs, mids) if outputmix: ''' event_sync(req['mixer_address'],sqlResult.blockNumber) @@ -414,6 +413,7 @@ def getNotes(request) -> None: params: username:str ''' +''' def getCommits(request) -> None: result = {} #req = json.loads(request.body) @@ -433,3 +433,4 @@ def getCommits(request) -> None: result['status'] = 1 result['text'] = 'your account is not recorded in server, please import it firstly or create a new one' return JsonResponse(result) +''' \ No newline at end of file diff --git a/zkclientapp/urls.py b/zkclientapp/urls.py index 8311e11..b7f9e0b 100644 --- a/zkclientapp/urls.py +++ b/zkclientapp/urls.py @@ -25,7 +25,7 @@ url(r'^mixBac$', routes.mixBac), url(r'^sendAsset$', routes.sendAsset), url(r'^getNotes$', routes.getNotes), - url(r'^getCommits$', routes.getCommits), + #url(r'^getCommits$', routes.getCommits), url(r'^checkUser$', routes.checkUser), url(r'^genAccount$', routes.genAccount), ]