[
  {
    "path": ".github/ISSUE_TEMPLATE/bug_report.md",
    "content": "---\nname: Bug report\nabout: Create a report to help us improve\ntitle: ''\nlabels: ''\nassignees: ''\n\n---\n\n**Describe the bug**\nA clear and concise description of what the bug is.\n\n**To Reproduce**\nSteps to reproduce the behavior:\n1. Go to '...'\n2. Click on '....'\n3. Scroll down to '....'\n4. See error\n\n**Expected behavior**\nA clear and concise description of what you expected to happen.\n\n**Screenshots**\nIf applicable, add screenshots to help explain your problem.\n\n**Desktop (please complete the following information):**\n - OS: [e.g. iOS]\n - Browser [e.g. chrome, safari]\n - Version [e.g. 22]\n\n**Smartphone (please complete the following information):**\n - Device: [e.g. iPhone6]\n - OS: [e.g. iOS8.1]\n - Browser [e.g. stock browser, safari]\n - Version [e.g. 22]\n\n**Additional context**\nAdd any other context about the problem here.\n"
  },
  {
    "path": ".github/PULL_REQUEST_TEMPLATE.md",
    "content": "## Description\n\nPlease add a brief description of the feature / change / bug-fix you want to merge.\n\n## Type of change\n\nPlease delete options that are not relevant.\n\n- [ ] Bug fix (non-breaking change which fixes an issue)\n- [ ] New feature (non-breaking change which adds functionality)\n- [ ] Breaking change (fix or feature that would require a resync of blockchain state)\n\n## Checklist\n\n- [ ] I have performed a self-review of my own code\n- [ ] I have tested this change in my development environment.\n- [ ] I have added tests to prove that this change works\n- [ ] All existing tests pass after this change\n- [ ] I have added / updated documentation related to this change"
  },
  {
    "path": ".github/dependabot.yml",
    "content": "version: 2\nupdates:\n  - package-ecosystem: \"pip\" # Type of package ecosystem (e.g., \"npm\", \"maven\")\n    directory: \"/\" # Location of package manifests\n    schedule:\n      interval: \"daily\" # How often to check for updates\n    open-pull-requests-limit: 10 # Maximum number of open pull requests Dependabot should have"
  },
  {
    "path": ".github/workflows/publish.yml",
    "content": "name: Publish to PyPI and GitHub Release\n\non:\n  push:\n    tags:\n      - 'v*'  # Trigger on version tags\n\njobs:\n  build-and-publish:\n    runs-on: ubuntu-latest\n    steps:\n      - uses: actions/checkout@v3\n      \n      - name: Set up Python 3.11\n        uses: actions/setup-python@v4\n        with:\n          python-version: '3.11'\n      \n      - name: Install Poetry\n        run: |\n          curl -sSL https://install.python-poetry.org | python3 -\n      \n      - name: Build and Publish to PyPI\n        env:\n          PYPI_TOKEN: ${{ secrets.PYPI_TOKEN }}\n        run: |\n          poetry config pypi-token.pypi $PYPI_TOKEN\n          poetry build\n          poetry publish\n      \n      - name: Create GitHub Release\n        uses: softprops/action-gh-release@v1\n        with:\n          files: dist/*\n          generate_release_notes: true\n"
  },
  {
    "path": ".gitignore",
    "content": "# Python\n__pycache__/\n*.py[cod]\n*$py.class\n*.so\n.Python\nbuild/\ndevelop-eggs/\ndist/\ndownloads/\neggs/\n.eggs/\nlib/\nlib64/\nparts/\nsdist/\nvar/\nwheels/\n*.egg-info/\n.installed.cfg\n*.egg\n\n# Virtual Environment\n.env\n.venv\nenv/\nvenv/\nENV/\n\n# IDE\n.idea/\n.vscode/\n*.swp\n*.swo\n\n# Testing\n.coverage\n.pytest_cache/\nhtmlcov/\n\n# Poetry\npoetry.lock__pycache__/\ndist\nxian_contracting.egg-info\ncontracting.egg-info\nbuild\n.idea\nlogs\n*.so\n.ccls\n*.pyc\n"
  },
  {
    "path": "LICENSE",
    "content": "Creative Commons Attribution‑NonCommercial 4.0 International\n\nCopyright © 2025 XIAN.org\n\nThis work is licensed under CC BY‑NC 4.0.  \nYou may copy, modify, and share it **for non‑commercial purposes only**, provided that you give appropriate credit.  \nFull legal text: https://creativecommons.org/licenses/by-nc/4.0/legalcode\n"
  },
  {
    "path": "README.md",
    "content": "# Xian Contracting\n\nXian Contracting is a Python-based smart contract development and execution framework. Unlike traditional blockchain platforms like Ethereum, Xian Contracting leverages Python's VM to create a more accessible and familiar environment for developers to write smart contracts.\n\n## Features\n\n- **Python-Native**: Write smart contracts in standard Python with some additional decorators and constructs\n- **Storage System**: Built-in ORM-like system with `Variable` and `Hash` data structures\n- **Runtime Security**: Secure execution environment with memory and computation limitations\n- **Metering System**: Built-in computation metering to prevent infinite loops and resource abuse\n- **Event System**: Built-in logging and event system for contract state changes\n- **Import Controls**: Secure import system that prevents access to dangerous system modules\n\n## Installation\n\n```bash\npip install xian-contracting\n```\n\n## Quick Start\n\nHere's a complete token contract example with approval system:\n\n```python\ndef token_contract():\n    balances = Hash()\n    owner = Variable()\n    \n    @construct\n    def seed():\n       owner.set(ctx.caller)\n    \n    @export\n    def approve(amount: float, to: str):\n       assert amount > 0, 'Cannot send negative balances.'\n       balances[ctx.caller, to] += amount\n    \n    @export\n    def transfer_from(amount: float, to: str, main_account: str):\n        approved = allowances[main_account, ctx.caller]\n    \n        assert amount > 0, 'Cannot send negative balances!'\n        assert approved >= amount, f'You approved {approved} but need {amount}'\n        assert balances[main_account] >= amount, 'Not enough tokens to send!'\n    \n        allowances[main_account, ctx.caller] -= amount\n        balances[main_account] -= amount\n        balances[to] += amount\n    \n    @export\n    def transfer(amount: float, to: str):\n       assert amount > 0, 'Cannot send negative balances.'\n       assert balances[ctx.caller] >= amount, 'Not enough coins to send.'\n    \n       balances[ctx.caller] -= amount\n       balances[to] += amount\n    \n    @export\n    def mint(to, amount):\n       assert ctx.caller == owner.get(), 'Only the original contract author can mint!'\n       balances[to] += amount\n```\n\n## Core Concepts\n\n### Storage Types\n\n- **Variable**: Single-value storage\n  ```python\n  counter = Variable()\n  counter.set(0)  # Set value\n  current = counter.get()  # Get value\n  ```\n\n- **Hash**: Key-value storage with support for complex and multi-level keys\n  ```python\n  balances = Hash()\n  # Single-level key\n  balances['alice'] = 100\n  alice_balance = balances['alice']\n  \n  # Multi-level keys for complex relationships\n  balances['alice', 'bob'] = 50  # e.g., alice approves bob to spend 50 tokens\n  approved_amount = balances['alice', 'bob']  # Get the approved amount\n  \n  # You can use up to 16 dimensions in key tuples\n  data['user', 'preferences', 'theme'] = 'dark'\n  ```\n\n### Contract Decorators\n\n- **@construct**: Initializes contract state (can only be called once)\n  ```python\n  @construct\n  def seed():\n      owner.set(ctx.caller)\n  ```\n\n- **@export**: Makes function callable from outside the contract\n  ```python\n  @export\n  def increment(amount: int):\n      counter.set(counter.get() + amount)\n  ```\n\n### Contract Context\n\nThe `ctx` object provides important runtime information:\n\n- `ctx.caller`: Address of the account calling the contract\n- `ctx.this`: Current contract's address\n- `ctx.signer`: Original transaction signer\n- `ctx.owner`: Contract owner's address\n\n## Using the ContractingClient\n\nThe `ContractingClient` class is your main interface for deploying and interacting with contracts:\n\n```python\nfrom contracting.client import ContractingClient\n\n# Initialize the client\nclient = ContractingClient()\n\n# Submit a contract\nwith open('token.py', 'r') as f:\n    contract = f.read()\n    \nclient.submit(name='con_token', code=contract)\n\n# Get contract instance\ntoken = client.get_contract('con_token')\n\n# Call contract methods\ntoken.transfer(amount=100, to='bob')\n```\n\n## Storage Driver\n\nThe framework includes a powerful storage system:\n\n```python\nfrom contracting.storage.driver import Driver\n\ndriver = Driver()\n\n# Direct storage operations\ndriver.set('key', 'value')\ndriver.get('key')\n\n# Contract storage\ndriver.set_contract(name='contract_name', code=contract_code)\ndriver.get_contract('contract_name')\n```\n\n## Event System\n\nContracts can emit events which can be tracked by external systems:\n\n```python\ndef token_contract():\n    transfer_event = LogEvent(\n        'transfer',\n        {\n            'sender': {'type': str, 'idx': True},\n            'receiver': {'type': str, 'idx': True},\n            'amount': {'type': float}\n        }\n    )\n\n    @export\n    def transfer(amount: float, to: str):\n        # ... transfer logic ...\n        \n        # Emit event\n        transfer_event({\n            'sender': ctx.caller,\n            'receiver': to,\n            'amount': amount\n        })\n```\n\n## Security Features\n\n- Restricted imports to prevent malicious code execution\n- Memory usage tracking and limitations\n- Computation metering to prevent infinite loops\n- Secure runtime environment\n- Type checking and validation\n- Private method protection\n\n## Development and Testing\n\nWhen developing contracts, you can use the linter to check for common issues:\n\n```python\nfrom contracting.client import ContractingClient\n\nclient = ContractingClient()\nviolations = client.lint(contract_code)\n```\n\n## License\n\nThis project is licensed under the Creative Commons Attribution‑NonCommercial 4.0 International - see the [LICENSE](LICENSE) file for details.\nNon‑commercial use only.  See LICENSE for details.\n"
  },
  {
    "path": "examples/01 A very simple Counter contract.ipynb",
    "content": "{\n \"cells\": [\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"# A very simple Counter contract\\n\",\n    \"\\n\",\n    \"Let's start writing a contract in python that stores a number which everyone can increment:\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": 1,\n   \"metadata\": {},\n   \"outputs\": [],\n   \"source\": [\n    \"def counter_contract():\\n\",\n    \"    # introduce a state called count which holds a single value\\n\",\n    \"    count = Variable()\\n\",\n    \"    \\n\",\n    \"    # @construct means that this is the function that will be called when the smart contract is created\\n\",\n    \"    @construct\\n\",\n    \"    def constructor():\\n\",\n    \"        count.set(0)\\n\",\n    \"        \\n\",\n    \"    # @export makes this function public, so it can be called by anyone on a deployed contract    \\n\",\n    \"    @export\\n\",\n    \"    def increment():\\n\",\n    \"        count.set(count.get() + 1)\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"To interact with smart contracts we need a client:\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": 2,\n   \"metadata\": {},\n   \"outputs\": [],\n   \"source\": [\n    \"from contracting.client import ContractingClient\\n\",\n    \"client = ContractingClient(signer='ren')\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"Next we will submit the contract to the client:\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": 3,\n   \"metadata\": {},\n   \"outputs\": [],\n   \"source\": [\n    \"client.submit(counter_contract)\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"Now we can get the submitted contract to interact with it:\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": 4,\n   \"metadata\": {},\n   \"outputs\": [],\n   \"source\": [\n    \"contract = client.get_contract('counter_contract')\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"Let's investigate the counter:\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": 5,\n   \"metadata\": {},\n   \"outputs\": [\n    {\n     \"data\": {\n      \"text/plain\": [\n       \"0\"\n      ]\n     },\n     \"execution_count\": 5,\n     \"metadata\": {},\n     \"output_type\": \"execute_result\"\n    }\n   ],\n   \"source\": [\n    \"contract.count.get()\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"It is 0 as expected because we initialized it to 0 in the constructor function.\\n\",\n    \"\\n\",\n    \"Everyone can increment the counter by calling the public increment function:\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": 6,\n   \"metadata\": {},\n   \"outputs\": [],\n   \"source\": [\n    \"contract.increment()\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"Let's investigate the counter again:\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": 7,\n   \"metadata\": {},\n   \"outputs\": [\n    {\n     \"data\": {\n      \"text/plain\": [\n       \"1\"\n      ]\n     },\n     \"execution_count\": 7,\n     \"metadata\": {},\n     \"output_type\": \"execute_result\"\n    }\n   ],\n   \"source\": [\n    \"contract.count.get()\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"Seems like our increment function works.\\n\",\n    \"\\n\",\n    \"This concludes our first look into writing smart contracts in Python on Lamden. Dive deeper by looking at the next example. \"\n   ]\n  }\n ],\n \"metadata\": {\n  \"kernelspec\": {\n   \"display_name\": \"Python 3\",\n   \"language\": \"python\",\n   \"name\": \"python3\"\n  },\n  \"language_info\": {\n   \"codemirror_mode\": {\n    \"name\": \"ipython\",\n    \"version\": 3\n   },\n   \"file_extension\": \".py\",\n   \"mimetype\": \"text/x-python\",\n   \"name\": \"python\",\n   \"nbconvert_exporter\": \"python\",\n   \"pygments_lexer\": \"ipython3\",\n   \"version\": \"3.6.5\"\n  }\n },\n \"nbformat\": 4,\n \"nbformat_minor\": 2\n}\n"
  },
  {
    "path": "examples/02 Ingredients of a Smart Contract.ipynb",
    "content": "{\n \"cells\": [\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"# What is inside a smart contract?\\n\",\n    \"\\n\",\n    \"Every smart contract has a set of methods that can be exposed to outside users, or kept internally for the operations of the smart contract. Each smart contract also has a data namespace on which it can read and write data too. Smart contracts can read data from other smart contracts, but they cannot write to other smart contracts.\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": 10,\n   \"metadata\": {},\n   \"outputs\": [],\n   \"source\": [\n    \"def basic_contract():\\n\",\n    \"    # data section\\n\",\n    \"    owner = Variable()\\n\",\n    \"    balances = Hash(default_value=0)\\n\",\n    \"    \\n\",\n    \"    @construct\\n\",\n    \"    def seed():\\n\",\n    \"        owner.set('stuart')\\n\",\n    \"        balances['stuart'] = 1000000\\n\",\n    \"\\n\",\n    \"    @export\\n\",\n    \"    def mint(amount, to):\\n\",\n    \"        assert_is_owner()\\n\",\n    \"        \\n\",\n    \"        balances[to] += amount\\n\",\n    \"        \\n\",\n    \"    def assert_is_owner():\\n\",\n    \"        assert ctx.caller == owner.get(), 'You are not the owner! {} is!'.format(owner.get())\\n\",\n    \"        \\n\",\n    \"    @export\\n\",\n    \"    def send(amount, to):\\n\",\n    \"        assert balances[ctx.caller] >= amount, 'You do not have enough to send! {} is less than {}'.format(\\n\",\n    \"            balances[ctx.caller], amount\\n\",\n    \"        )\\n\",\n    \"        \\n\",\n    \"        balances[ctx.caller] -= amount\\n\",\n    \"        balances[to] += amount\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"## Functions\\n\",\n    \"This looks like a lot to chew over, but let's go over it piece by piece. There are 3 types of functions:\\n\",\n    \"\\n\",\n    \"* @construct\\n\",\n    \"    \\n\",\n    \"    This function is run once on contract submission. It 'constructs' the initial state of the smart contract. Use this for setting initial variables. You can only have one @construct function, but you can call it whatever you want.\\n\",\n    \"    \\n\",\n    \"    \\n\",\n    \"* @export\\n\",\n    \"    \\n\",\n    \"    These functions are callable by outside users and other smart contracts. Therefore, you have to pay extra attention to the code you write in them. If @export functions do things that you do not want every user to do, you should put them in a private function, or add access control features.\\n\",\n    \"    \\n\",\n    \"    \\n\",\n    \"* everything else\\n\",\n    \"    \\n\",\n    \"    Any other function without a decorator is a private method that can only be called by the contract itself. These functions are good for complex contracts that need to abstract and reuse some logic over and over again. It also allows you to set apart the pieces of the smart contract logic between core controller code, and external interaction functions.\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": 14,\n   \"metadata\": {},\n   \"outputs\": [],\n   \"source\": [\n    \"from contracting.client import ContractingClient\\n\",\n    \"client = ContractingClient(signer='stuart')\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": 15,\n   \"metadata\": {},\n   \"outputs\": [],\n   \"source\": [\n    \"client.submit(basic_contract)\\n\",\n    \"contract = client.get_contract('basic_contract')\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"Because @constructor sets `stuart`'s balance to 1,000,000, we can access the variable directly from our contract object to check.\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": 22,\n   \"metadata\": {},\n   \"outputs\": [\n    {\n     \"data\": {\n      \"text/plain\": [\n       \"1000000\"\n      ]\n     },\n     \"execution_count\": 22,\n     \"metadata\": {},\n     \"output_type\": \"execute_result\"\n    }\n   ],\n   \"source\": [\n    \"contract.balances['stuart']\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"Because `mint` is an @export function, we can call it from the outside. Remember, the `client` was initialized with the `signer` equal to `stuart`.\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": 21,\n   \"metadata\": {},\n   \"outputs\": [\n    {\n     \"data\": {\n      \"text/plain\": [\n       \"20000\"\n      ]\n     },\n     \"execution_count\": 21,\n     \"metadata\": {},\n     \"output_type\": \"execute_result\"\n    }\n   ],\n   \"source\": [\n    \"contract.mint(amount=10000, to='raghu')\\n\",\n    \"contract.balances['raghu']\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"If we override the signer keyword to someone who is `not_stuart`, the function will fail because of the assertation. The internal function is called here.\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": 18,\n   \"metadata\": {},\n   \"outputs\": [\n    {\n     \"name\": \"stdout\",\n     \"output_type\": \"stream\",\n     \"text\": [\n      \"You are not the owner! stuart is!\\n\"\n     ]\n    }\n   ],\n   \"source\": [\n    \"try:\\n\",\n    \"    contract.mint(amount=500, to='raghu', signer='not_stuart')\\n\",\n    \"except AssertionError as e:\\n\",\n    \"    print(e)\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"However, if you try to access the function normally (and remember to prepend the `__` before it), you can see that the function is not available to us to call.\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": 28,\n   \"metadata\": {},\n   \"outputs\": [\n    {\n     \"name\": \"stdout\",\n     \"output_type\": \"stream\",\n     \"text\": [\n      \"module 'basic_contract' has no attribute '__assert_is_owner'\\n\"\n     ]\n    }\n   ],\n   \"source\": [\n    \"try:\\n\",\n    \"    contract.__assert_is_owner()\\n\",\n    \"except Exception as e:\\n\",\n    \"    print(e)\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"## Data\\n\",\n    \"You will also notice a `Variable` object and `Hash` object initialized in the beginning of the smart contract. These are data variables that are used to store data on the smart contract. You cannot modify these variables directly. Instead, the @export functions you write determine how data is modified in these variables. This allows you to create extremely robust and secure data models for your application.\\n\",\n    \"\\n\",\n    \"There are also `ForeignVariable` and `ForeignHash` objects. These are 'read-only' variables that allow your smart contract to import the namespace of another smart contract for internal use, but prevents writing to them. For example, your function might only pass given certain conditions on another smart contract that it is watching. Foreign varibles would be used in this case.\\n\",\n    \"\\n\",\n    \"The Contracting client exposes these variables into Python objects and *does* allow modification. This is so that the developer can test various situations more easily. It does not reflect how users will be able to modify data in a smart contract namespace.\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": 37,\n   \"metadata\": {},\n   \"outputs\": [],\n   \"source\": [\n    \"def data_contract():\\n\",\n    \"    basic_contract_owner = ForeignVariable(foreign_contract='basic_contract', foreign_name='owner')\\n\",\n    \"    \\n\",\n    \"    variable = Variable()\\n\",\n    \"    hash_ = Hash()\\n\",\n    \"    \\n\",\n    \"    # Demonstration of returning a value in another smart contract's namespace\\n\",\n    \"    @export\\n\",\n    \"    def whos_the_owner():\\n\",\n    \"        return basic_contract_owner.get()\\n\",\n    \"    \\n\",\n    \"    @export\\n\",\n    \"    def set_var(x):\\n\",\n    \"        variable.set(x)\\n\",\n    \"        \\n\",\n    \"    @export\\n\",\n    \"    def set_hash(k, v):\\n\",\n    \"        hash_[k] = v\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": 38,\n   \"metadata\": {},\n   \"outputs\": [],\n   \"source\": [\n    \"client.submit(data_contract)\\n\",\n    \"d_contract = client.get_contract('data_contract')\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"#### Read the Foreign Variable\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": 39,\n   \"metadata\": {},\n   \"outputs\": [\n    {\n     \"data\": {\n      \"text/plain\": [\n       \"'stuart'\"\n      ]\n     },\n     \"execution_count\": 39,\n     \"metadata\": {},\n     \"output_type\": \"execute_result\"\n    }\n   ],\n   \"source\": [\n    \"d_contract.whos_the_owner()\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"#### Set the Variable via Smart Contract and via Client\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": 44,\n   \"metadata\": {},\n   \"outputs\": [\n    {\n     \"data\": {\n      \"text/plain\": [\n       \"1000\"\n      ]\n     },\n     \"execution_count\": 44,\n     \"metadata\": {},\n     \"output_type\": \"execute_result\"\n    }\n   ],\n   \"source\": [\n    \"d_contract.set_var(x=1000)\\n\",\n    \"d_contract.variable.get()\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": 45,\n   \"metadata\": {},\n   \"outputs\": [\n    {\n     \"data\": {\n      \"text/plain\": [\n       \"123\"\n      ]\n     },\n     \"execution_count\": 45,\n     \"metadata\": {},\n     \"output_type\": \"execute_result\"\n    }\n   ],\n   \"source\": [\n    \"d_contract.set_var(x=123)\\n\",\n    \"d_contract.variable.get()\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": 46,\n   \"metadata\": {},\n   \"outputs\": [\n    {\n     \"data\": {\n      \"text/plain\": [\n       \"555\"\n      ]\n     },\n     \"execution_count\": 46,\n     \"metadata\": {},\n     \"output_type\": \"execute_result\"\n    }\n   ],\n   \"source\": [\n    \"# Overriding our method to modify the variable directly\\n\",\n    \"d_contract.variable.set(555)\\n\",\n    \"d_contract.variable.get()\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"#### Set the Hash via Smart Contract and via Client\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": 52,\n   \"metadata\": {},\n   \"outputs\": [\n    {\n     \"data\": {\n      \"text/plain\": [\n       \"'world'\"\n      ]\n     },\n     \"execution_count\": 52,\n     \"metadata\": {},\n     \"output_type\": \"execute_result\"\n    }\n   ],\n   \"source\": [\n    \"d_contract.set_hash(k='hello', v='world')\\n\",\n    \"d_contract.hash_['hello']\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": 53,\n   \"metadata\": {},\n   \"outputs\": [\n    {\n     \"data\": {\n      \"text/plain\": [\n       \"'there'\"\n      ]\n     },\n     \"execution_count\": 53,\n     \"metadata\": {},\n     \"output_type\": \"execute_result\"\n    }\n   ],\n   \"source\": [\n    \"d_contract.hash_['hello'] = 'there'\\n\",\n    \"d_contract.hash_['hello']\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"### Behavior Note\\n\",\n    \"\\n\",\n    \"Variables and hashes only take up space in the database if they are initialized. Therefore, you cannot access a hash that has no values. Because you cannot access this hash (or variable), you cannot manually set values on it either. Make sure that you always either @construct your variables, or provide methods in your smart contract to interact with them.\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": 56,\n   \"metadata\": {},\n   \"outputs\": [],\n   \"source\": [\n    \"def variable_behavior():\\n\",\n    \"    invisible_variable = Variable()\\n\",\n    \"    \\n\",\n    \"    @export\\n\",\n    \"    def do_nothing():\\n\",\n    \"        return 0\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": 57,\n   \"metadata\": {},\n   \"outputs\": [],\n   \"source\": [\n    \"client.submit(variable_behavior)\\n\",\n    \"v_contract = client.get_contract('variable_behavior')\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": 59,\n   \"metadata\": {},\n   \"outputs\": [\n    {\n     \"name\": \"stdout\",\n     \"output_type\": \"stream\",\n     \"text\": [\n      \"'AbstractContract' object has no attribute 'invisible_variable'\\n\"\n     ]\n    }\n   ],\n   \"source\": [\n    \"try:\\n\",\n    \"    v_contract.invisible_variable\\n\",\n    \"except AttributeError as e:\\n\",\n    \"    print(e)\"\n   ]\n  }\n ],\n \"metadata\": {\n  \"kernelspec\": {\n   \"display_name\": \"Python 3\",\n   \"language\": \"python\",\n   \"name\": \"python3\"\n  },\n  \"language_info\": {\n   \"codemirror_mode\": {\n    \"name\": \"ipython\",\n    \"version\": 3\n   },\n   \"file_extension\": \".py\",\n   \"mimetype\": \"text/x-python\",\n   \"name\": \"python\",\n   \"nbconvert_exporter\": \"python\",\n   \"pygments_lexer\": \"ipython3\",\n   \"version\": \"3.6.5\"\n  }\n },\n \"nbformat\": 4,\n \"nbformat_minor\": 2\n}\n"
  },
  {
    "path": "examples/03 Interacting with the Client.ipynb",
    "content": "{\n \"cells\": [\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"# The Main Contracting Client\\n\",\n    \"Contracting comes with a robust client that abstracts most of the underpinnings of the smart contracting system so that it feels like regular Python. This lets you worry about your programming rather than the mechanics of the protocol. To start, create an instance of the `ContractingClient` like so. You can set the default `signer` who will then automatically be the `signer` of the subsequent function calls (or transactions, in blockchain terms).\\n\",\n    \"\\n\",\n    \"You can change the signer by setting this property on the client, or by overriding the keyword `sender` when calling a function.\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": 1,\n   \"metadata\": {},\n   \"outputs\": [],\n   \"source\": [\n    \"from contracting.client import ContractingClient\\n\",\n    \"client = ContractingClient(signer='stu')\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"## Viewing contracts\\n\",\n    \"\\n\",\n    \"The client preloads a set of 'genesis' contracts that are required for the system to operate. These genesis contracts bypass some of the system protections to allow a channel between the low level protocol and the higher level programming interface to occur without exposing everything to the developer. This allows us to create powerful system level contracts while maintaining tight security on user level contracts.\\n\",\n    \"\\n\",\n    \"One of these genesis contracts is the contract submission contract. Ironically, we have a smart contract to submit smart contracts. This is for purposes of conflict resolution, which is a later topic. For now, you can see the contracts by calling the function below.\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": 2,\n   \"metadata\": {},\n   \"outputs\": [\n    {\n     \"data\": {\n      \"text/plain\": [\n       \"['submission']\"\n      ]\n     },\n     \"execution_count\": 2,\n     \"metadata\": {},\n     \"output_type\": \"execute_result\"\n    }\n   ],\n   \"source\": [\n    \"client.get_contracts()\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"## Interacting with existing smart contracts\\n\",\n    \"\\n\",\n    \"Contracts can be fetched into their own objects with the `get_contract` method.\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": 3,\n   \"metadata\": {},\n   \"outputs\": [\n    {\n     \"data\": {\n      \"text/plain\": [\n       \"<contracting.client.AbstractContract at 0x10c3643c8>\"\n      ]\n     },\n     \"execution_count\": 3,\n     \"metadata\": {},\n     \"output_type\": \"execute_result\"\n    }\n   ],\n   \"source\": [\n    \"client.get_contract('submission')\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"You can see all available functions you can call on this smart contract by accessing the `self.functions` property. This returns a list of tuples made up of function names and the list of keyword arguments they require.\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": 4,\n   \"metadata\": {},\n   \"outputs\": [\n    {\n     \"data\": {\n      \"text/plain\": [\n       \"[('submit_contract', ['name', 'code'])]\"\n      ]\n     },\n     \"execution_count\": 4,\n     \"metadata\": {},\n     \"output_type\": \"execute_result\"\n    }\n   ],\n   \"source\": [\n    \"submission = client.get_contract('submission')\\n\",\n    \"submission.functions\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"## Submitting new smart contracts\\n\",\n    \"\\n\",\n    \"Let's use the `submit_contract` function to submit a new smart contract!\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": 5,\n   \"metadata\": {},\n   \"outputs\": [],\n   \"source\": [\n    \"code = '''\\n\",\n    \"@export\\n\",\n    \"def hello_there():\\n\",\n    \"    print('howdy')\\n\",\n    \"'''\\n\",\n    \"\\n\",\n    \"name = 'howdy_time'\\n\",\n    \"\\n\",\n    \"submission.submit_contract(name=name, code=code)\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"Now we can check to make sure that the smart contract made it into the `submission` contract's \\\"namespace.\\\" Each smart contract has its own namespace where it stores data which isolates it from other smart contracts securely.\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": 6,\n   \"metadata\": {},\n   \"outputs\": [],\n   \"source\": [\n    \"howdy_time = client.get_contract(name)\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": 7,\n   \"metadata\": {},\n   \"outputs\": [\n    {\n     \"data\": {\n      \"text/plain\": [\n       \"['howdy_time.__author__',\\n\",\n       \" 'howdy_time.__code__',\\n\",\n       \" 'howdy_time.__compiled__',\\n\",\n       \" 'howdy_time.__type__']\"\n      ]\n     },\n     \"execution_count\": 7,\n     \"metadata\": {},\n     \"output_type\": \"execute_result\"\n    }\n   ],\n   \"source\": [\n    \"howdy_time.keys()\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": 8,\n   \"metadata\": {},\n   \"outputs\": [\n    {\n     \"name\": \"stdout\",\n     \"output_type\": \"stream\",\n     \"text\": [\n      \"def hello_there():\\n\",\n      \"    print('howdy')\\n\",\n      \"\\n\"\n     ]\n    }\n   ],\n   \"source\": [\n    \"print(howdy_time.__code__)\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"It worked! But why was the @export decorator deleted? This actually is a lower level Contracting function that parses submitted code and transforms it into proper Python. In this process, it also checks to make sure that the code contains all of the correct formatting and features. This is what a contract looks like if you include a private function as well.\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": 9,\n   \"metadata\": {},\n   \"outputs\": [],\n   \"source\": [\n    \"code = '''\\n\",\n    \"@export\\n\",\n    \"def secret():\\n\",\n    \"    return abcd()\\n\",\n    \"    \\n\",\n    \"def abcd():\\n\",\n    \"    return 5\\n\",\n    \"'''\\n\",\n    \"\\n\",\n    \"name = 'secret'\\n\",\n    \"\\n\",\n    \"submission.submit_contract(name=name, code=code)\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": 10,\n   \"metadata\": {},\n   \"outputs\": [],\n   \"source\": [\n    \"secret = client.get_contract('secret')\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": 11,\n   \"metadata\": {},\n   \"outputs\": [\n    {\n     \"data\": {\n      \"text/plain\": [\n       \"[('secret', []), ('__abcd', [])]\"\n      ]\n     },\n     \"execution_count\": 11,\n     \"metadata\": {},\n     \"output_type\": \"execute_result\"\n    }\n   ],\n   \"source\": [\n    \"secret.functions\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": 12,\n   \"metadata\": {},\n   \"outputs\": [\n    {\n     \"name\": \"stdout\",\n     \"output_type\": \"stream\",\n     \"text\": [\n      \"def secret():\\n\",\n      \"    return __abcd()\\n\",\n      \"\\n\",\n      \"\\n\",\n      \"def __abcd():\\n\",\n      \"    return 5\\n\",\n      \"\\n\"\n     ]\n    }\n   ],\n   \"source\": [\n    \"print(secret.__code__)\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": 13,\n   \"metadata\": {},\n   \"outputs\": [\n    {\n     \"data\": {\n      \"text/plain\": [\n       \"5\"\n      ]\n     },\n     \"execution_count\": 13,\n     \"metadata\": {},\n     \"output_type\": \"execute_result\"\n    }\n   ],\n   \"source\": [\n    \"secret.secret()\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"Notice how methods without @export on them get prepended with `__`. This prevents people from calling these methods in their own smart contracts, making them effectively private. The Contracting client, however, is designed for the maximal developer experience, so you may be able to call these functions from the client so that you can write unit tests and integration tests around their functionality.\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"## Closures and direct submission\\n\",\n    \"\\n\",\n    \"Instead of pulling out the `submission` contract every time before a session, you can access it via the client on the `submit` method. This method also allows you to submit closure functions (functions that have other functions inside of them). As long as the code inside of the closure can be considered a valid smart contract, the client will convert it into a code string and submit it to the `submission` smart contract.\\n\",\n    \"\\n\",\n    \"Contracts submitted this way will be named whatever their closure function is.\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": 14,\n   \"metadata\": {},\n   \"outputs\": [],\n   \"source\": [\n    \"def closure_example():\\n\",\n    \"    @export\\n\",\n    \"    def hello():\\n\",\n    \"        return 'How are you?'\\n\",\n    \"    \\n\",\n    \"    def shh():\\n\",\n    \"        return 10\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": 15,\n   \"metadata\": {},\n   \"outputs\": [],\n   \"source\": [\n    \"client.submit(closure_example)\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": 18,\n   \"metadata\": {},\n   \"outputs\": [],\n   \"source\": [\n    \"closure = client.get_contract('closure_example')\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": 20,\n   \"metadata\": {},\n   \"outputs\": [\n    {\n     \"name\": \"stdout\",\n     \"output_type\": \"stream\",\n     \"text\": [\n      \"def hello():\\n\",\n      \"    return 'How are you?'\\n\",\n      \"\\n\",\n      \"\\n\",\n      \"def __shh():\\n\",\n      \"    return 10\\n\",\n      \"\\n\"\n     ]\n    }\n   ],\n   \"source\": [\n    \"print(closure.__code__)\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"Now that you have an idea on how to use the client, let's dive into the mechanics behind smart contracts in the next notebook.\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": null,\n   \"metadata\": {},\n   \"outputs\": [],\n   \"source\": []\n  }\n ],\n \"metadata\": {\n  \"kernelspec\": {\n   \"display_name\": \"Python 3\",\n   \"language\": \"python\",\n   \"name\": \"python3\"\n  },\n  \"language_info\": {\n   \"codemirror_mode\": {\n    \"name\": \"ipython\",\n    \"version\": 3\n   },\n   \"file_extension\": \".py\",\n   \"mimetype\": \"text/x-python\",\n   \"name\": \"python\",\n   \"nbconvert_exporter\": \"python\",\n   \"pygments_lexer\": \"ipython3\",\n   \"version\": \"3.6.5\"\n  }\n },\n \"nbformat\": 4,\n \"nbformat_minor\": 2\n}\n"
  },
  {
    "path": "examples/04 Standard Library and Extending Contracting.ipynb",
    "content": "{\n \"cells\": [\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"# The Contracting Standard Library\\n\",\n    \"There are unique variables and functions available for smart contracts at runtime. In the last notebook, we used the ORM variables that are provided via the `stdlib` to interact with the database. We will explore the other methods in this notebook and the concept of `environment` and `ctx`.\\n\",\n    \"\\n\",\n    \"To see the basic standard library included at runtime, use `gather()` from the `env` module.\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": 1,\n   \"metadata\": {},\n   \"outputs\": [],\n   \"source\": [\n    \"from contracting.stdlib import env\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": 2,\n   \"metadata\": {},\n   \"outputs\": [\n    {\n     \"data\": {\n      \"text/plain\": [\n       \"{'Variable': contracting.db.orm.Variable,\\n\",\n       \" 'Hash': contracting.db.orm.Hash,\\n\",\n       \" 'ForeignVariable': contracting.db.orm.ForeignVariable,\\n\",\n       \" 'ForeignHash': contracting.db.orm.ForeignHash,\\n\",\n       \" '__Contract': contracting.db.contract.Contract,\\n\",\n       \" 'sha3': <function contracting.stdlib.bridge.hashing.sha3(hex_str:str)>,\\n\",\n       \" 'sha256': <function contracting.stdlib.bridge.hashing.sha256(hex_str:str)>,\\n\",\n       \" 'datetime': contracting.stdlib.bridge.time.Datetime}\"\n      ]\n     },\n     \"execution_count\": 2,\n     \"metadata\": {},\n     \"output_type\": \"execute_result\"\n    }\n   ],\n   \"source\": [\n    \"env.gather()\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"All of these functions are available at runtime. You can extend the standard library by updating the `env` dictionary. If you want to pass something more dynamic through, like the time that a transaction was submitted to the network, you would pass in an environment object.\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": 3,\n   \"metadata\": {},\n   \"outputs\": [],\n   \"source\": [\n    \"def stdlib_environment_examples():\\n\",\n    \"    \\n\",\n    \"    @export\\n\",\n    \"    def sha3_data(s):\\n\",\n    \"        return sha3(s)\\n\",\n    \"    \\n\",\n    \"    @export\\n\",\n    \"    def return_env_variable():\\n\",\n    \"        return this_will_be_defined_later\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"First, let's try to access the `sha3` function exposed in the `stdlib`.\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": 4,\n   \"metadata\": {},\n   \"outputs\": [],\n   \"source\": [\n    \"from contracting.client import ContractingClient\\n\",\n    \"client = ContractingClient(signer='stu')\\n\",\n    \"client.submit(stdlib_environment_examples)\\n\",\n    \"contract = client.get_contract('stdlib_environment_examples')\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": 5,\n   \"metadata\": {},\n   \"outputs\": [\n    {\n     \"data\": {\n      \"text/plain\": [\n       \"'a0d5f1e1000980a0ae98cffb12072a41328bbdfebf3f6012aa021b428daea5b7'\"\n      ]\n     },\n     \"execution_count\": 5,\n     \"metadata\": {},\n     \"output_type\": \"execute_result\"\n    }\n   ],\n   \"source\": [\n    \"contract.sha3_data(s='00ff00ff00ff')\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"Now, if we try to call `return_env_variable()`, we will get an error. This is because the variable is not included in the `stdlib` nor has been defined elsewhere in the contract.\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": 6,\n   \"metadata\": {},\n   \"outputs\": [\n    {\n     \"name\": \"stdout\",\n     \"output_type\": \"stream\",\n     \"text\": [\n      \"name 'this_will_be_defined_later' is not defined\\n\"\n     ]\n    }\n   ],\n   \"source\": [\n    \"try:\\n\",\n    \"    contract.return_env_variable()\\n\",\n    \"except Exception as e:\\n\",\n    \"    print(e)\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"But if we pass it in the environment, it becomes accessible. This function is used by our blockchain to pass contextual information such as block height, block hash, transaction time, etc.\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": 7,\n   \"metadata\": {},\n   \"outputs\": [\n    {\n     \"data\": {\n      \"text/plain\": [\n       \"42\"\n      ]\n     },\n     \"execution_count\": 7,\n     \"metadata\": {},\n     \"output_type\": \"execute_result\"\n    }\n   ],\n   \"source\": [\n    \"environment = {'this_will_be_defined_later': 42}\\n\",\n    \"contract.return_env_variable(environment=environment)\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"## Runtime Context `ctx`\\n\",\n    \"At runtime, there is a constant defined called `ctx`. `ctx` contains three fields:\\n\",\n    \"\\n\",\n    \"* `ctx.signer`\\n\",\n    \"\\n\",\n    \"    This is the signer of the initial transaction. This variable never changes. It should not be used for access control.\\n\",\n    \"\\n\",\n    \"---\\n\",\n    \"\\n\",\n    \"* `ctx.caller`\\n\",\n    \"    \\n\",\n    \"    This is the direct caller of the function. As explained in the next notebook, smart contracts can import functions from other smart contracts. If you submit a transaction to a smart contract which calls upon another smart contract, the call stack is modified. The `caller` becomes the calling smart contract on a function. This should be used for access control.\\n\",\n    \"    \\n\",\n    \"---    \\n\",\n    \"    \\n\",\n    \"* `ctx.this`\\n\",\n    \"\\n\",\n    \"    This is the name of the smart contract. This is how you will reference a smart contract for ascribing ownership to them.\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": 8,\n   \"metadata\": {},\n   \"outputs\": [],\n   \"source\": [\n    \"def call_me():\\n\",\n    \"    @export\\n\",\n    \"    def caller():\\n\",\n    \"        return ctx.caller\\n\",\n    \"    \\n\",\n    \"    @export\\n\",\n    \"    def this():\\n\",\n    \"        return ctx.this\\n\",\n    \"\\n\",\n    \"def ctx_example():\\n\",\n    \"    import call_me\\n\",\n    \"    \\n\",\n    \"    @export\\n\",\n    \"    def ctx_now():\\n\",\n    \"        return ctx.signer, ctx.caller, ctx.this\\n\",\n    \"    \\n\",\n    \"    @export\\n\",\n    \"    def ctx_after_call():\\n\",\n    \"        c = call_me.caller()\\n\",\n    \"        t = call_me.this()\\n\",\n    \"        \\n\",\n    \"        return ctx.signer, c, t\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": 9,\n   \"metadata\": {},\n   \"outputs\": [],\n   \"source\": [\n    \"client.submit(call_me)\\n\",\n    \"client.submit(ctx_example)\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": 10,\n   \"metadata\": {},\n   \"outputs\": [],\n   \"source\": [\n    \"ctx_contract = client.get_contract('ctx_example')\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": 11,\n   \"metadata\": {},\n   \"outputs\": [\n    {\n     \"data\": {\n      \"text/plain\": [\n       \"('stu', 'stu', 'ctx_example')\"\n      ]\n     },\n     \"execution_count\": 11,\n     \"metadata\": {},\n     \"output_type\": \"execute_result\"\n    }\n   ],\n   \"source\": [\n    \"ctx_contract.ctx_now()\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": 12,\n   \"metadata\": {},\n   \"outputs\": [\n    {\n     \"data\": {\n      \"text/plain\": [\n       \"('stu', 'ctx_example', 'call_me')\"\n      ]\n     },\n     \"execution_count\": 12,\n     \"metadata\": {},\n     \"output_type\": \"execute_result\"\n    }\n   ],\n   \"source\": [\n    \"ctx_contract.ctx_after_call()\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"Notice above how `ctx_after_call` returns different information. This is because `ctx` is modified after each function call. Because `ctx_example` called `call_me`, the `ctx.caller` returned was `ctx_example`. If we call that function directly, we will get `stu` back.\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": 13,\n   \"metadata\": {},\n   \"outputs\": [],\n   \"source\": [\n    \"call_me_contract = client.get_contract('call_me')\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": 14,\n   \"metadata\": {},\n   \"outputs\": [\n    {\n     \"data\": {\n      \"text/plain\": [\n       \"'stu'\"\n      ]\n     },\n     \"execution_count\": 14,\n     \"metadata\": {},\n     \"output_type\": \"execute_result\"\n    }\n   ],\n   \"source\": [\n    \"call_me_contract.caller()\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"## Why does `ctx` being dynamic matter?\\n\",\n    \"Having `ctx` lets you create smart contracts that act as operators for users and other smart contracts. Because they are given their own identity, they are essentially the signers of their own function calls. This allows you to give them their own accounts, balances, ownerships, etc. to create structures that behave complexly and securely.\\n\",\n    \"\\n\",\n    \"Assume you have a bank smart contract. You want to keep everyone's balance inside of the main bank vault, but keep sub-accounts in their name. You don't want the bank to be able to spend someone else's money on their behalf, so you would check the `ctx.caller` to make sure it is the user, and not the bank itself.\\n\",\n    \"\\n\",\n    \"Let's make a token contract to demonstrate this idea.\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": 15,\n   \"metadata\": {},\n   \"outputs\": [],\n   \"source\": [\n    \"def coin():\\n\",\n    \"    balances = Hash()\\n\",\n    \"    token_name = 'Stubucks'\\n\",\n    \"    token_symbol = 'SBX'\\n\",\n    \"    \\n\",\n    \"    @construct\\n\",\n    \"    def seed():\\n\",\n    \"        # Whoever creates this smart contract is minted 1,000,000 tokens\\n\",\n    \"        balances[ctx.caller] = 1000000\\n\",\n    \"        \\n\",\n    \"    @export\\n\",\n    \"    def transfer(amount, to):\\n\",\n    \"        # Make sure that the person calling this function has the amount they are trying to transfer\\n\",\n    \"        assert balances[ctx.caller] >= amount, \\\"You don't have enough to spend!\\\"\\n\",\n    \"        \\n\",\n    \"        # If so, deduct from their account and send to who they want to send to\\n\",\n    \"        balances[ctx.caller] -= amount\\n\",\n    \"        balances[to] += amount\\n\",\n    \"        \\n\",\n    \"    @export\\n\",\n    \"    def allow(amount, spender):\\n\",\n    \"        # This creates a 'subaccount' to allow the spender to transfer from our account a certain amount\\n\",\n    \"        balances[ctx.caller, spender] = amount\\n\",\n    \"        \\n\",\n    \"    @export\\n\",\n    \"    def spend_on_behalf(amount, owner, to):\\n\",\n    \"        # We make sure the subaccount has enough coins to spend\\n\",\n    \"        assert balances[owner, ctx.caller] >= amount, \\\"You can't spend that!\\\"\\n\",\n    \"        \\n\",\n    \"        # If so, deduct from the amount that the subaccount can spend\\n\",\n    \"        balances[owner, ctx.caller] -= amount\\n\",\n    \"        \\n\",\n    \"        # And then make the transfer\\n\",\n    \"        balances[owner] -= amount\\n\",\n    \"        balances[to] += amount\\n\",\n    \"        \\n\",\n    \"def bank():\\n\",\n    \"    import coin\\n\",\n    \"    \\n\",\n    \"    balances = Hash()\\n\",\n    \"    \\n\",\n    \"    @export\\n\",\n    \"    def deposit(amount):\\n\",\n    \"        # The bank spends the coins it is allowed to on itself. It takes it from the subaccount and give it to itself\\n\",\n    \"        # We don't need an assertion because this will fail\\n\",\n    \"        coin.spend_on_behalf(amount=amount, owner=ctx.caller, to=ctx.this)\\n\",\n    \"        \\n\",\n    \"        # The account that of whoever called the deposit function is incremented accordingly\\n\",\n    \"        balances[ctx.caller] += amount\\n\",\n    \"        \\n\",\n    \"    @export\\n\",\n    \"    def withdraw(amount):\\n\",\n    \"        # Make sure there is enough in the caller's account to withdraw\\n\",\n    \"        assert balances[ctx.caller] >= amount, \\\"You don't have enough in your account!\\\"\\n\",\n    \"        \\n\",\n    \"        # Deduct from the account\\n\",\n    \"        balances[ctx.caller] -= amount\\n\",\n    \"        \\n\",\n    \"        # Transfer the coins out to the caller\\n\",\n    \"        coin.transfer(amount=amount, to=ctx.caller)\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"Here is the idea:\\n\",\n    \"\\n\",\n    \"1. You must allow a user to spend tokens on your behalf by calling the `allow` function.\\n\",\n    \"2. You can then deposit tokens into the bank by calling deposit after you have `allow`ed the bank to spend on your behalf.\\n\",\n    \"3. You can withdraw tokens from the bank if they belong to you. However, the bank is the one that has the token balance. You have a sub-balance.\\n\",\n    \"    \\n\",\n    \"Let's see if it works!\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": 16,\n   \"metadata\": {},\n   \"outputs\": [\n    {\n     \"data\": {\n      \"text/plain\": [\n       \"1000000\"\n      ]\n     },\n     \"execution_count\": 16,\n     \"metadata\": {},\n     \"output_type\": \"execute_result\"\n    }\n   ],\n   \"source\": [\n    \"client.submit(coin)\\n\",\n    \"client.submit(bank)\\n\",\n    \"\\n\",\n    \"coin_contract = client.get_contract('coin')\\n\",\n    \"bank_contract = client.get_contract('bank')\\n\",\n    \"\\n\",\n    \"coin_contract.balances['stu'] # Check if things @construct'ed appropriately\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": 17,\n   \"metadata\": {},\n   \"outputs\": [\n    {\n     \"data\": {\n      \"text/plain\": [\n       \"['coin.__author__',\\n\",\n       \" 'coin.__code__',\\n\",\n       \" 'coin.__compiled__',\\n\",\n       \" 'coin.__type__',\\n\",\n       \" 'coin.balances:stu']\"\n      ]\n     },\n     \"execution_count\": 17,\n     \"metadata\": {},\n     \"output_type\": \"execute_result\"\n    }\n   ],\n   \"source\": [\n    \"coin_contract.keys()\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": 18,\n   \"metadata\": {},\n   \"outputs\": [\n    {\n     \"name\": \"stdout\",\n     \"output_type\": \"stream\",\n     \"text\": [\n      \"balances = Hash(contract='coin', name='balances')\\n\",\n      \"token_name = 'Stubucks'\\n\",\n      \"token_symbol = 'SBX'\\n\",\n      \"\\n\",\n      \"\\n\",\n      \"def ____():\\n\",\n      \"    balances[ctx.caller] = 1000000\\n\",\n      \"\\n\",\n      \"\\n\",\n      \"def transfer(amount, to):\\n\",\n      \"    assert balances[ctx.caller] >= amount, \\\"You don't have enough to spend!\\\"\\n\",\n      \"    balances[ctx.caller] -= amount\\n\",\n      \"    balances[to] += amount\\n\",\n      \"\\n\",\n      \"\\n\",\n      \"def allow(amount, spender):\\n\",\n      \"    balances[ctx.caller, spender] = amount\\n\",\n      \"\\n\",\n      \"\\n\",\n      \"def spend_on_behalf(amount, owner, to):\\n\",\n      \"    assert balances[owner, ctx.caller] >= amount, \\\"You can't spend that!\\\"\\n\",\n      \"    balances[owner, ctx.caller] -= amount\\n\",\n      \"    balances[owner] -= amount\\n\",\n      \"    balances[to] += amount\\n\",\n      \"\\n\"\n     ]\n    }\n   ],\n   \"source\": [\n    \"print(coin_contract.__code__)\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": 19,\n   \"metadata\": {},\n   \"outputs\": [\n    {\n     \"data\": {\n      \"text/plain\": [\n       \"10\"\n      ]\n     },\n     \"execution_count\": 19,\n     \"metadata\": {},\n     \"output_type\": \"execute_result\"\n    }\n   ],\n   \"source\": [\n    \"coin_contract.transfer(amount=10, to='hi')\\n\",\n    \"coin_contract.balances['hi']\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": 20,\n   \"metadata\": {},\n   \"outputs\": [\n    {\n     \"data\": {\n      \"text/plain\": [\n       \"0\"\n      ]\n     },\n     \"execution_count\": 20,\n     \"metadata\": {},\n     \"output_type\": \"execute_result\"\n    }\n   ],\n   \"source\": [\n    \"# Let's verify that the bank has no coins\\n\",\n    \"coin_contract.balances['bank']\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": 21,\n   \"metadata\": {},\n   \"outputs\": [],\n   \"source\": [\n    \"coin_contract.allow(amount=500, spender='bank')\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": 22,\n   \"metadata\": {},\n   \"outputs\": [\n    {\n     \"data\": {\n      \"text/plain\": [\n       \"500\"\n      ]\n     },\n     \"execution_count\": 22,\n     \"metadata\": {},\n     \"output_type\": \"execute_result\"\n    }\n   ],\n   \"source\": [\n    \"coin_contract.balances['stu', 'bank'] # This is how you access a 'subaccount.' A nice feature of multihashes!\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": 23,\n   \"metadata\": {},\n   \"outputs\": [\n    {\n     \"data\": {\n      \"text/plain\": [\n       \"999990\"\n      ]\n     },\n     \"execution_count\": 23,\n     \"metadata\": {},\n     \"output_type\": \"execute_result\"\n    }\n   ],\n   \"source\": [\n    \"coin_contract.balances['stu'] # Notice that it is not affecting the main account. It is just an allowance account.\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": 24,\n   \"metadata\": {},\n   \"outputs\": [],\n   \"source\": [\n    \"bank_contract.deposit(amount=450) # This should modify our balance and give bank 450 coins. Let's check!\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": 25,\n   \"metadata\": {},\n   \"outputs\": [\n    {\n     \"name\": \"stdout\",\n     \"output_type\": \"stream\",\n     \"text\": [\n      \"stu balance: 999540\\n\",\n      \"bank balance: 450\\n\",\n      \"bank allowance: 50\\n\"\n     ]\n    }\n   ],\n   \"source\": [\n    \"stu_balance = coin_contract.balances['stu']\\n\",\n    \"bank_balance = coin_contract.balances['bank']\\n\",\n    \"\\n\",\n    \"# This should only be 50, because 450 were spent on the bank's behalf.\\n\",\n    \"bank_allowance = coin_contract.balances['stu', 'bank']\\n\",\n    \"\\n\",\n    \"print('stu balance: {}\\\\nbank balance: {}\\\\nbank allowance: {}'.format(\\n\",\n    \"    stu_balance,\\n\",\n    \"    bank_balance,\\n\",\n    \"    bank_allowance\\n\",\n    \"))\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": 26,\n   \"metadata\": {},\n   \"outputs\": [\n    {\n     \"data\": {\n      \"text/plain\": [\n       \"450\"\n      ]\n     },\n     \"execution_count\": 26,\n     \"metadata\": {},\n     \"output_type\": \"execute_result\"\n    }\n   ],\n   \"source\": [\n    \"bank_contract.balances['stu'] # Our account in the bank reflects the total\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"## Adding another participant to the equation\\n\",\n    \"\\n\",\n    \"Now, let's transfer some coins to another account and do the same thing to see how the bank's total account value goes up and is the sum of all of the subaccounts from under it. We will also withdraw our coins from the bank and see them reappear in our balance on the coin contract.\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": 27,\n   \"metadata\": {},\n   \"outputs\": [],\n   \"source\": [\n    \"# 'stu' will transfer some coins to 'raghu' to put in the bank.\\n\",\n    \"coin_contract.transfer(amount=5000, to='raghu')\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": 28,\n   \"metadata\": {},\n   \"outputs\": [],\n   \"source\": [\n    \"# Remember, the default signer on this client is 'stu' so we have to set it to 'raghu' to call a function from him.\\n\",\n    \"coin_contract.allow(amount=4000, spender='bank', signer='raghu')\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": 29,\n   \"metadata\": {},\n   \"outputs\": [\n    {\n     \"name\": \"stdout\",\n     \"output_type\": \"stream\",\n     \"text\": [\n      \"raghu balance: 5000\\n\",\n      \"bank allowance for raghu: 4000\\n\"\n     ]\n    }\n   ],\n   \"source\": [\n    \"raghu_balance = coin_contract.balances['raghu']\\n\",\n    \"bank_raghu_allowance = coin_contract.balances['raghu', 'bank']\\n\",\n    \"\\n\",\n    \"print('raghu balance: {}\\\\nbank allowance for raghu: {}'.format(raghu_balance, bank_raghu_allowance))\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": 30,\n   \"metadata\": {},\n   \"outputs\": [\n    {\n     \"name\": \"stdout\",\n     \"output_type\": \"stream\",\n     \"text\": [\n      \"You can't spend that!\\n\"\n     ]\n    }\n   ],\n   \"source\": [\n    \"# If raghu tries to deposit more than 4000, an error will occur\\n\",\n    \"try:\\n\",\n    \"    bank_contract.deposit(amount=4001, signer='raghu')\\n\",\n    \"except AssertionError as e:\\n\",\n    \"    print(e)\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": 31,\n   \"metadata\": {},\n   \"outputs\": [],\n   \"source\": [\n    \"# Less than 4000 or 4000 will do.\\n\",\n    \"bank_contract.deposit(amount=3999, signer='raghu')\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": 32,\n   \"metadata\": {},\n   \"outputs\": [\n    {\n     \"name\": \"stdout\",\n     \"output_type\": \"stream\",\n     \"text\": [\n      \"raghu balance: 1001\\n\",\n      \"bank allowance for raghu: 1\\n\"\n     ]\n    }\n   ],\n   \"source\": [\n    \"# Updated balances\\n\",\n    \"raghu_balance = coin_contract.balances['raghu']\\n\",\n    \"bank_raghu_allowance = coin_contract.balances['raghu', 'bank']\\n\",\n    \"\\n\",\n    \"print('raghu balance: {}\\\\nbank allowance for raghu: {}'.format(raghu_balance, bank_raghu_allowance))\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": 33,\n   \"metadata\": {},\n   \"outputs\": [\n    {\n     \"name\": \"stdout\",\n     \"output_type\": \"stream\",\n     \"text\": [\n      \"bank balance: 4449\\n\",\n      \"stu bank account: 450\\n\",\n      \"raghu bank account: 3999\\n\"\n     ]\n    }\n   ],\n   \"source\": [\n    \"# The bank will now have 450 + 3999 coins total, with two subaccounts.\\n\",\n    \"bank_balance = coin_contract.balances['bank']\\n\",\n    \"stu_bank_account = bank_contract.balances['stu']\\n\",\n    \"raghu_bank_account = bank_contract.balances['raghu']\\n\",\n    \"\\n\",\n    \"print('bank balance: {}\\\\nstu bank account: {}\\\\nraghu bank account: {}'.format(\\n\",\n    \"    bank_balance,\\n\",\n    \"    stu_bank_account,\\n\",\n    \"    raghu_bank_account\\n\",\n    \"))\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": 34,\n   \"metadata\": {},\n   \"outputs\": [\n    {\n     \"name\": \"stdout\",\n     \"output_type\": \"stream\",\n     \"text\": [\n      \"You don't have enough in your account!\\n\"\n     ]\n    }\n   ],\n   \"source\": [\n    \"# If we try to withdraw more than our account balance from the bank, then we will have an AssertionError\\n\",\n    \"try:\\n\",\n    \"    bank_contract.withdraw(amount=500)\\n\",\n    \"except AssertionError as e:\\n\",\n    \"    print(e)\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": 35,\n   \"metadata\": {},\n   \"outputs\": [\n    {\n     \"name\": \"stdout\",\n     \"output_type\": \"stream\",\n     \"text\": [\n      \"stu prior balance:994540\\n\",\n      \"stu after balance: 994640\\n\"\n     ]\n    }\n   ],\n   \"source\": [\n    \"stu_prior_balance = coin_contract.balances['stu']\\n\",\n    \"bank_contract.withdraw(amount=100)\\n\",\n    \"stu_after_balance = coin_contract.balances['stu']\\n\",\n    \"\\n\",\n    \"print('stu prior balance: {}\\\\nstu after balance: {}'.format(\\n\",\n    \"    stu_prior_balance,\\n\",\n    \"    stu_after_balance\\n\",\n    \"))\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"Now that you understand the basics of the `ctx` object, you can create extremely robust smart contracts that pass around context. In the next section, we will learn more about the import system and multihashes to add even more capabilities to your smart contracts!\"\n   ]\n  }\n ],\n \"metadata\": {\n  \"kernelspec\": {\n   \"display_name\": \"Python 3\",\n   \"language\": \"python\",\n   \"name\": \"python3\"\n  },\n  \"language_info\": {\n   \"codemirror_mode\": {\n    \"name\": \"ipython\",\n    \"version\": 3\n   },\n   \"file_extension\": \".py\",\n   \"mimetype\": \"text/x-python\",\n   \"name\": \"python\",\n   \"nbconvert_exporter\": \"python\",\n   \"pygments_lexer\": \"ipython3\",\n   \"version\": \"3.6.5\"\n  }\n },\n \"nbformat\": 4,\n \"nbformat_minor\": 2\n}\n"
  },
  {
    "path": "examples/05 Imports and Advanced Data Storage.ipynb",
    "content": "{\n \"cells\": [\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"# Imports and Advanced Data Storage\\n\",\n    \"To add even more functionality to smart contracts, you can import the exported functions of other smart contracts. You can also store complex data in the form of Python objects, which is useful for storing things like lists, tuples, and dates. Here's how.\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": 10,\n   \"metadata\": {},\n   \"outputs\": [],\n   \"source\": [\n    \"def import_this():\\n\",\n    \"    @export\\n\",\n    \"    def dumb_func():\\n\",\n    \"        return 4\\n\",\n    \"    \\n\",\n    \"def to_import():\\n\",\n    \"    import import_this\\n\",\n    \"    @export\\n\",\n    \"    def dumber_func():\\n\",\n    \"        return import_this.dumb_func()\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": 11,\n   \"metadata\": {},\n   \"outputs\": [],\n   \"source\": [\n    \"from contracting.client import ContractingClient\\n\",\n    \"client = ContractingClient(signer='stu')\\n\",\n    \"client.flush()\\n\",\n    \"client.submit(import_this)\\n\",\n    \"client.submit(to_import)\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": 12,\n   \"metadata\": {},\n   \"outputs\": [\n    {\n     \"data\": {\n      \"text/plain\": [\n       \"4\"\n      ]\n     },\n     \"execution_count\": 12,\n     \"metadata\": {},\n     \"output_type\": \"execute_result\"\n    }\n   ],\n   \"source\": [\n    \"ti_contract = client.get_contract('to_import')\\n\",\n    \"ti_contract.dumber_func()\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"Easy! Notice that you can only import entire contracts. You cannot use `from a import b` notation to import just a singular function from a smart contract. Furthermore, dynamic imports will be added at a later time to allow importing a contract by name that can be used as an argument.\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"## Advanced Data\\n\",\n    \"Imagine a game where you can buy or sell pixels. Each pixel has an X and a Y coordinate. At each pixel, we want to store the owner, the price, and the color. While this might sound complicated, it is actually extremely straight forward to do.\\n\",\n    \"\\n\",\n    \"All `Hash` objects have the ability to store up to 16 dimensions of information in a key that a max of 1024 bytes in size. The stored object is just JSON using the standard Python JSON encoder and decoder, so you can store things such as lists, sets, etc. At this point in time, there is no limit on how large the value for a key can be, but it will be capped in the future. The current floating figure is 256 bytes to 1024 bytes, so design your contracts accordingly.\\n\",\n    \"\\n\",\n    \"Unlike normal Python dictionaries, which `Hash` objects are similar to, you can add different dimensions to your `Hash` object without an issue. For example:\\n\",\n    \"\\n\",\n    \"```\\n\",\n    \"h = Hash()\\n\",\n    \"h['one'] = 15\\n\",\n    \"h['one', 'two'] = 20\\n\",\n    \"h['two'] = 25\\n\",\n    \"h['a', 'b', 'c', 'd', 'e', 'f', 'g'] = 6\\n\",\n    \"```\\n\",\n    \"\\n\",\n    \"Let's try to build that pixel application.\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": 4,\n   \"metadata\": {},\n   \"outputs\": [],\n   \"source\": [\n    \"def coin():\\n\",\n    \"    balances = Hash(default_value=0)\\n\",\n    \"    token_name = 'Stubucks'\\n\",\n    \"    token_symbol = 'SBX'\\n\",\n    \"    \\n\",\n    \"    @construct\\n\",\n    \"    def seed():\\n\",\n    \"        # Whoever creates this smart contract is minted 1,000,000 tokens\\n\",\n    \"        balances[ctx.caller] = 1000000\\n\",\n    \"        \\n\",\n    \"    @export\\n\",\n    \"    def transfer(amount, to):\\n\",\n    \"        # Make sure that the person calling this function has the amount they are trying to transfer\\n\",\n    \"        assert balances[ctx.caller] >= amount, \\\"You don't have enough to spend!\\\"\\n\",\n    \"        \\n\",\n    \"        # If so, deduct from their account and send to who they want to send to\\n\",\n    \"        balances[ctx.caller] -= amount\\n\",\n    \"        balances[to] += amount\\n\",\n    \"        \\n\",\n    \"    @export\\n\",\n    \"    def allow(amount, spender):\\n\",\n    \"        # This creates a 'subaccount' to allow the spender to transfer from our account a certain amount\\n\",\n    \"        balances[ctx.caller, spender] = amount\\n\",\n    \"        \\n\",\n    \"    @export\\n\",\n    \"    def spend_on_behalf(amount, owner, to):\\n\",\n    \"        # We make sure the subaccount has enough coins to spend\\n\",\n    \"        assert balances[owner, ctx.caller] >= amount, \\\"You can't spend that!\\\"\\n\",\n    \"        \\n\",\n    \"        # If so, deduct from the amount that the subaccount can spend\\n\",\n    \"        balances[owner, ctx.caller] -= amount\\n\",\n    \"        \\n\",\n    \"        # And then make the transfer\\n\",\n    \"        balances[owner] -= amount\\n\",\n    \"        balances[to] += amount\\n\",\n    \"\\n\",\n    \"def pixel_game():\\n\",\n    \"    import coin\\n\",\n    \"    \\n\",\n    \"    # We set the default value of dictionary values to None for testing if they exist\\n\",\n    \"    pixels = Hash(default_value=None)\\n\",\n    \"    \\n\",\n    \"    # These constants can never be changed. If you want mutable variables, use Variable objects and provide getters\\n\",\n    \"    # and setters.\\n\",\n    \"    max_x = 256\\n\",\n    \"    max_y = 256\\n\",\n    \"    \\n\",\n    \"    # Just a palette to simplify this\\n\",\n    \"    color_min = 0\\n\",\n    \"    color_max = 16\\n\",\n    \"    \\n\",\n    \"    @export\\n\",\n    \"    def buy_pixel(x, y, color, amount):\\n\",\n    \"        assert x < max_x and x >= 0, 'X out of bounds!'\\n\",\n    \"        assert y < max_y and y >= 0, 'Y out of bounds!'\\n\",\n    \"        \\n\",\n    \"        assert color < color_max and color >= color_min, 'Color is out of bounds!'\\n\",\n    \"        \\n\",\n    \"        # If we make it to here, we can access the pixel.\\n\",\n    \"        pixel = pixels[x, y]\\n\",\n    \"        \\n\",\n    \"        # If it is None, it's never been bought before, so we can buy it outright\\n\",\n    \"        if pixel is None:\\n\",\n    \"            # Take the coins and store it in the pixel game's account\\n\",\n    \"            overwrite_pixel(x, y, color, amount, ctx.caller)\\n\",\n    \"            \\n\",\n    \"        else:\\n\",\n    \"            # Otherwise, the pixel is a dictionary, so we can access it like such\\n\",\n    \"            assert amount > pixel['amount'], 'You must pay at least {} to purchase.'.format(pixel['amount'])\\n\",\n    \"            overwrite_pixel(x, y, color, amount, ctx.caller)\\n\",\n    \"            \\n\",\n    \"    def overwrite_pixel(x, y, color, amount, owner):\\n\",\n    \"        coin.spend_on_behalf(amount=amount, owner=ctx.caller, to=ctx.this)\\n\",\n    \"            \\n\",\n    \"        pixels.set[x, y] = {\\n\",\n    \"            'owner': owner,\\n\",\n    \"            'amount': amount,\\n\",\n    \"            'color': color\\n\",\n    \"        }\\n\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"To keep things simple, let's just assume that we can buy pixels. If you see `overwrite_pixel`, you'll notice that we are setting the X and Y coordinates to a Python dictionary rather than just a primitive type. When we access the database again to pull it out, it is decoded into a Python dictionary again, so you can access it like how you are used to.\\n\",\n    \"\\n\",\n    \"Let's try to buy a pixel!\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": 5,\n   \"metadata\": {},\n   \"outputs\": [],\n   \"source\": [\n    \"client.submit(coin)\\n\",\n    \"client.submit(pixel_game)\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": 6,\n   \"metadata\": {},\n   \"outputs\": [],\n   \"source\": [\n    \"coin_contract = client.get_contract('coin')\\n\",\n    \"pixel_contract = client.get_contract('pixel_game')\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": 7,\n   \"metadata\": {},\n   \"outputs\": [\n    {\n     \"data\": {\n      \"text/plain\": [\n       \"1000000\"\n      ]\n     },\n     \"execution_count\": 7,\n     \"metadata\": {},\n     \"output_type\": \"execute_result\"\n    }\n   ],\n   \"source\": [\n    \"coin_contract.balances['stu'] # Let's make sure we have the coins to make a pixel purchase.\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": 8,\n   \"metadata\": {},\n   \"outputs\": [],\n   \"source\": [\n    \"coin_contract.allow(amount=1, spender='pixel_game')\\n\",\n    \"pixel_contract.buy_pixel(x=10, y=10, color=5, amount=1)\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": 9,\n   \"metadata\": {},\n   \"outputs\": [\n    {\n     \"data\": {\n      \"text/plain\": [\n       \"999999\"\n      ]\n     },\n     \"execution_count\": 9,\n     \"metadata\": {},\n     \"output_type\": \"execute_result\"\n    }\n   ],\n   \"source\": [\n    \"coin_contract.balances['stu'] # The balance has deducted properly\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": 10,\n   \"metadata\": {},\n   \"outputs\": [\n    {\n     \"data\": {\n      \"text/plain\": [\n       \"{'owner': 'stu', 'amount': 1, 'color': 5}\"\n      ]\n     },\n     \"execution_count\": 10,\n     \"metadata\": {},\n     \"output_type\": \"execute_result\"\n    }\n   ],\n   \"source\": [\n    \"pixel_contract.pixels[10, 10] # Now we can access the information and recieve the dictionary back\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": 11,\n   \"metadata\": {},\n   \"outputs\": [\n    {\n     \"data\": {\n      \"text/plain\": [\n       \"dict\"\n      ]\n     },\n     \"execution_count\": 11,\n     \"metadata\": {},\n     \"output_type\": \"execute_result\"\n    }\n   ],\n   \"source\": [\n    \"type(pixel_contract.pixels[10, 10]) # Proof the dictionary is in fact a dictionary!\"\n   ]\n  }\n ],\n \"metadata\": {\n  \"kernelspec\": {\n   \"display_name\": \"Python 3\",\n   \"language\": \"python\",\n   \"name\": \"python3\"\n  },\n  \"language_info\": {\n   \"codemirror_mode\": {\n    \"name\": \"ipython\",\n    \"version\": 3\n   },\n   \"file_extension\": \".py\",\n   \"mimetype\": \"text/x-python\",\n   \"name\": \"python\",\n   \"nbconvert_exporter\": \"python\",\n   \"pygments_lexer\": \"ipython3\",\n   \"version\": \"3.6.5\"\n  }\n },\n \"nbformat\": 4,\n \"nbformat_minor\": 2\n}\n"
  },
  {
    "path": "examples/Rock Paper Scissors Tutorial.ipynb",
    "content": "{\n \"cells\": [\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"# Rock Paper Scissors\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"In this tutorial you will learn how to build a Lamden smart contract for the classic game Rock, Paper, Scissors. Through this contract, two players can play Rock, Paper, Scissors over the Lamden Blockchain. \"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"This is an advanced example. Please make sure you have gone over the previous examples before this one so you have a better understanding of contracting as a whole. \"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"### Important Disclaimer:\\n\",\n    \"This is an example smart contract. It is not production ready. It needs more tests. It also does not address certain timing edge cases. For example a user can just not reveal their choice and stall a game forever. The solution is left as an exercise for you. It is important when building a smart contract that you think of all edge cases and test heavily before deploying it to the blockchain. \"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"First let's import some things we will need later.\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": 1,\n   \"metadata\": {},\n   \"outputs\": [],\n   \"source\": [\n    \"from contracting.stdlib.bridge.hashing import sha3\\n\",\n    \"from contracting.client import ContractingClient\\n\",\n    \"import secrets\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"Below is the function `rps_contract` containing the entire Rock, Paper, Scissors contract. It is never run as a Python function. Instead contracting extracts constructor, storage variables, public and private functions from it when it is submitted to the blockchain. We recomend reading on below the contract and then investigating the contract functions when they are being called.\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": 2,\n   \"metadata\": {},\n   \"outputs\": [],\n   \"source\": [\n    \"def rps_contract():\\n\",\n    \"    # This tells the blockchain to make space for data. Variable and Hash are not Python builtins. \\n\",\n    \"    # They are globals (globals are something you can access without importing it) made available by contracting. \\n\",\n    \"    # Calling Variable() creates a new piece of memory within the blockchain, that can hold a single value. \\n\",\n    \"    # If we say \\\"foo = Variable()\\\" then we can interact with that piece of memory through \\\"foo\\\". \\n\",\n    \"    # We can set the piece of memory to 1, for example by calling \\\"foo.set(1)\\\".\\n\",\n    \"    # Setting the value will change the value for the next call to the smart contract.\\n\",\n    \"    # We can get the piece of memory by calling \\\"foo.get()\\\".\\n\",\n    \"    next_game_id = Variable()\\n\",\n    \"    \\n\",\n    \"    game_id_to_password_hash = Hash()\\n\",\n    \"    \\n\",\n    \"    game_id_to_player1_choice_hash = Hash()\\n\",\n    \"    game_id_to_player2_choice_hash = Hash()\\n\",\n    \"    \\n\",\n    \"    game_id_to_player1_choice = Hash()\\n\",\n    \"    game_id_to_player2_choice = Hash()\\n\",\n    \"            \\n\",\n    \"    # @construct means that this is the function that will be called ONCE when the smart contract is created\\n\",\n    \"    @construct\\n\",\n    \"    def constructor():\\n\",\n    \"        # Game id starts at 0.\\n\",\n    \"        next_game_id.set(0)\\n\",\n    \"        \\n\",\n    \"    # @export makes this function public, so it can be called by anyone on a deployed contract.\\n\",\n    \"    # By calling start_game player1 creates a game and also submits their hashed and salted choice.\\n\",\n    \"    @export\\n\",\n    \"    def start_game(password_hash, player1_choice_hash):\\n\",\n    \"        # This retrieves unique game Id from the blockchain. \\n\",\n    \"        unique_game_id = next_game_id.get()\\n\",\n    \"        \\n\",\n    \"        assert get_game_state(unique_game_id) == \\\"game_doesnt_exist\\\", \\\"this is a bug in the contract. new game id already exists\\\"\\n\",\n    \"        \\n\",\n    \"        # This increments the number by 1, so the next game has a unique Id.\\n\",\n    \"        next_game_id.set(next_game_id.get() + 1)       \\n\",\n    \"        \\n\",\n    \"        # Hash throws error on integer keys. That's why we convert to a string\\n\",\n    \"        # Remember player1 choice hash, and password hash for this game. \\n\",\n    \"        game_id_to_password_hash[str(unique_game_id)] = password_hash\\n\",\n    \"\\n\",\n    \"        game_id_to_player1_choice_hash[str(unique_game_id)] = player1_choice_hash\\n\",\n    \"        \\n\",\n    \"        # assert get_game_state(unique_game_id) == \\\"only_player1_submitted\\\", \\\"this is a bug in the contract. after starting a new game only player 1 must have submitted\\\"\\n\",\n    \"        \\n\",\n    \"        return unique_game_id\\n\",\n    \"    \\n\",\n    \"    # By calling submit_choice player2 submits their hashed and salted choice.\\n\",\n    \"    @export\\n\",\n    \"    def submit_choice(game_id, game_password, player2_choice_hash):\\n\",\n    \"        assert get_game_state(game_id) == \\\"only_player1_submitted\\\", \\\"submit_choice can only be called if only player 1 has submitted their choice\\\"\\n\",\n    \"\\n\",\n    \"        # Check that this is the right password for the game.\\n\",\n    \"        assert hashlib.sha3(game_password) == game_id_to_password_hash[str(game_id)], 'Wrong password!'\\n\",\n    \"        \\n\",\n    \"        # Remember player2's choice.\\n\",\n    \"        game_id_to_player2_choice_hash[str(game_id)] = player2_choice_hash\\n\",\n    \"        \\n\",\n    \"        assert get_game_state(game_id) == \\\"both_players_submitted\\\", \\\"this is a bug in the contract. after submitting player2 choice both players must have submitted\\\"\\n\",\n    \"        \\n\",\n    \"        return\\n\",\n    \"    \\n\",\n    \"    # Returns 'player1_wins' if player1 is the winner.\\n\",\n    \"    # Returns 'player2_wins' if player2 is the winner.\\n\",\n    \"    # Returns 'tie' if both players made the same choice.\\n\",\n    \"    # Returns 'game_doesnt_exist' if the game doesn't exist\\n\",\n    \"    # Returns 'player1_has_submitted' if the game has been started and only player1 has submitted their choice\\n\",\n    \"    # Returns 'both_players_have_submitted' if both players have submitted but none has revealed their choice\\n\",\n    \"    # Returns 'only_player1_revealed' after player1 but not player2 has revealed their choice\\n\",\n    \"    # Returns 'only_player2_revealed' after player2 but not player1 has revealed their choice\\n\",\n    \"    \\n\",\n    \"    @export\\n\",\n    \"    def get_game_state(game_id):\\n\",\n    \"        if next_game_id.get() <= game_id:\\n\",\n    \"            return \\\"game_doesnt_exist\\\"\\n\",\n    \"        \\n\",\n    \"        player1_hashed_choice = game_id_to_player1_choice_hash[str(game_id)]\\n\",\n    \"        player2_hashed_choice = game_id_to_player2_choice_hash[str(game_id)]\\n\",\n    \"\\n\",\n    \"        if player1_hashed_choice is not None and player2_hashed_choice is None:\\n\",\n    \"            return \\\"only_player1_submitted\\\"\\n\",\n    \"        \\n\",\n    \"        player1_choice = game_id_to_player1_choice[str(game_id)]\\n\",\n    \"        player2_choice = game_id_to_player2_choice[str(game_id)]\\n\",\n    \"              \\n\",\n    \"        if player1_hashed_choice is not None and player2_hashed_choice is not None and player1_choice is None and player2_choice is None:\\n\",\n    \"            return \\\"both_players_submitted\\\"\\n\",\n    \"        \\n\",\n    \"        assert player1_hashed_choice is not None and player2_hashed_choice is not None, \\\"this is a bug in the contract. error code 1\\\"\\n\",\n    \"        # For the rest of the function we know that both players have submitted their choices \\n\",\n    \"        # and one player has revealed their choice\\n\",\n    \"        \\n\",\n    \"        if player1_choice is not None and player2_choice is None:\\n\",\n    \"            return \\\"only_player1_revealed\\\"\\n\",\n    \"        \\n\",\n    \"        if player1_choice is None and player2_choice is not None:\\n\",\n    \"            return \\\"only_player2_revealed\\\"\\n\",\n    \"        \\n\",\n    \"        # Make sure that both players have submitted their choices\\n\",\n    \"        assert player1_choice is not None and player2_choice is not None, \\\"this is a bug in the contract. error code 2\\\"\\n\",\n    \"        # For the rest of the function we know that both players have submitted their choices\\n\",\n    \"        \\n\",\n    \"        # Now that we have both choices we can resolve the game\\n\",\n    \"        \\n\",\n    \"        if player1_choice == player2_choice:\\n\",\n    \"            return \\\"tie\\\"\\n\",\n    \"\\n\",\n    \"        if beats(player1_choice, player2_choice):\\n\",\n    \"            return \\\"player1_wins\\\"\\n\",\n    \"        \\n\",\n    \"        if beats(player2_choice, player1_choice):\\n\",\n    \"            return \\\"player2_wins\\\"\\n\",\n    \"        \\n\",\n    \"    @export\\n\",\n    \"    def is_valid_choice(choice):\\n\",\n    \"        return choice in [\\\"rock\\\", \\\"paper\\\", \\\"scissors\\\"]\\n\",\n    \"      \\n\",\n    \"    # Returns whether choice1 beats choice2\\n\",\n    \"    @export\\n\",\n    \"    def beats(choice1, choice2):\\n\",\n    \"        assert is_valid_choice(choice1), \\\"choice1 must be a valid choice\\\"\\n\",\n    \"        assert is_valid_choice(choice2), \\\"choice2 must be a valid choice\\\"\\n\",\n    \"\\n\",\n    \"        if choice1 == \\\"rock\\\" and choice2 == \\\"scissors\\\":\\n\",\n    \"            return True\\n\",\n    \"        \\n\",\n    \"        if choice1 == \\\"paper\\\" and choice2 == \\\"rock\\\":\\n\",\n    \"            return True\\n\",\n    \"        \\n\",\n    \"        if choice1 == \\\"scissors\\\" and choice2 == \\\"paper\\\":\\n\",\n    \"            return True\\n\",\n    \"        \\n\",\n    \"        return False\\n\",\n    \"    \\n\",\n    \"    # By calling reveal a player can reveal their unhashed choice.\\n\",\n    \"    # Player1 has to call the function with is_player1=true.\\n\",\n    \"    # Player2 has to call the function with is_player1=false.\\n\",\n    \"    @export\\n\",\n    \"    def reveal(game_id, choice, choice_salt, is_player1):\\n\",\n    \"        if is_player1:\\n\",\n    \"            assert get_game_state(game_id) in [\\\"both_players_submitted\\\", \\\"only_player2_revealed\\\"], \\\"reveal can only be called by player1 if no player or only player2 has revealed\\\"\\n\",\n    \"        else:\\n\",\n    \"            assert get_game_state(game_id) in [\\\"both_players_submitted\\\", \\\"only_player1_revealed\\\"], \\\"reveal can only be called by player2 if no player or only player1 has revealed\\\"\\n\",\n    \"        \\n\",\n    \"        # Make sure players can only reveal valid choices\\n\",\n    \"        assert is_valid_choice(choice), \\\"choice must be rock, paper or scissors\\\"\\n\",\n    \"                \\n\",\n    \"        # Now we need to check that the reveal hashes to what was submitted earlier\\n\",\n    \"        \\n\",\n    \"        salted_choice = choice + choice_salt\\n\",\n    \"        hashed_choice = hashlib.sha3(salted_choice)\\n\",\n    \"        \\n\",\n    \"        if is_player1:\\n\",\n    \"            assert game_id_to_player1_choice_hash[str(game_id)] == hashed_choice, \\\"Player 1 has revealed a choice different from what they submitted\\\"\\n\",\n    \"        else:\\n\",\n    \"            assert game_id_to_player2_choice_hash[str(game_id)] == hashed_choice, \\\"Player 2 has revealed a choice different from what they submitted\\\"\\n\",\n    \"            \\n\",\n    \"        # Now we're sure that the player has revealed the choice they have previously submitted the hashed salted version of\\n\",\n    \"        \\n\",\n    \"        # Remember the choice\\n\",\n    \"        if is_player1:\\n\",\n    \"            game_id_to_player1_choice[str(game_id)] = choice\\n\",\n    \"        else:\\n\",\n    \"            game_id_to_player2_choice[str(game_id)] = choice\\n\",\n    \"        \\n\",\n    \"        return\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"Welcome back! Lets get this contract into the blockchain. To interact with the blockchain we need a client. \"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": 4,\n   \"metadata\": {},\n   \"outputs\": [],\n   \"source\": [\n    \"client = ContractingClient(signer='ren')\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"Get rid of all state of the blockchain so we have a blank slate. Otherwise running this script twice causes problems. \"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": 5,\n   \"metadata\": {},\n   \"outputs\": [],\n   \"source\": [\n    \"client.flush()\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"Now we submit the contract to the blockchain. `client.submit` doesn't run the function `rps_contract` but examines it, and extracts its public functions, state variables, ...\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": 6,\n   \"metadata\": {},\n   \"outputs\": [],\n   \"source\": [\n    \"client.submit(rps_contract)\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"Get a handle for the contract that we can interact with.\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": 7,\n   \"metadata\": {},\n   \"outputs\": [],\n   \"source\": [\n    \"contract = client.get_contract('rps_contract')\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"With the contract in the blockchain we can now play Rock, Paper, Scissors. Our players for this example are Alice and Bob.\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"Alice (player 1) chooses single use password. Only the person that has the password can join the game and play with Alice. Everything that starts with alice_ is only visible to Alice. \"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": 8,\n   \"metadata\": {},\n   \"outputs\": [],\n   \"source\": [\n    \"alice_game_password = \\\"trollbridge\\\"\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"Alice hashes the password so she can submit it to the blockchain without sharing the actual password. She does this because everything on the blockchain is public, and she wants only the person she chooses to play the game with to have the password. \"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": 9,\n   \"metadata\": {},\n   \"outputs\": [\n    {\n     \"data\": {\n      \"text/plain\": [\n       \"'47a5bcfb0d81053f5025ab57e6b94f43751f91bdb16fc0d63595223dc78ec1b4'\"\n      ]\n     },\n     \"execution_count\": 9,\n     \"metadata\": {},\n     \"output_type\": \"execute_result\"\n    }\n   ],\n   \"source\": [\n    \"alice_game_password_hash = sha3(alice_game_password)\\n\",\n    \"alice_game_password_hash\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"Alice chooses rock.\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": 10,\n   \"metadata\": {},\n   \"outputs\": [],\n   \"source\": [\n    \"alice_choice = \\\"rock\\\"\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"We can't submit the choice to the blockchain as plain text, because then Bob (player 2) can see it and win by choosing paper. \"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": 11,\n   \"metadata\": {},\n   \"outputs\": [\n    {\n     \"data\": {\n      \"text/plain\": [\n       \"'bd996e2dc82a7c3e2c2da41291648e852b62b01fb09bcb6ed77975c273f08404'\"\n      ]\n     },\n     \"execution_count\": 11,\n     \"metadata\": {},\n     \"output_type\": \"execute_result\"\n    }\n   ],\n   \"source\": [\n    \"alice_choice_hash = sha3(alice_choice)\\n\",\n    \"alice_choice_hash\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"The problem with submitting Alices choice like this is the 3 choices will be hashed the same every time. Bob (player 2) can know what each of the hashes for the 3 choices and pick paper to win. To fix this Alice needs to pick a random salt to hash with her choice so that Bob can't guess her choice by looking at the hash.\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": 12,\n   \"metadata\": {},\n   \"outputs\": [\n    {\n     \"data\": {\n      \"text/plain\": [\n       \"'88ceef7a2c748432d5a150fcff5df717c8a67298365ae2e1969be4ee856ce39e'\"\n      ]\n     },\n     \"execution_count\": 12,\n     \"metadata\": {},\n     \"output_type\": \"execute_result\"\n    }\n   ],\n   \"source\": [\n    \"alice_choice_salt = secrets.token_hex(32)\\n\",\n    \"alice_choice_salt\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"Now we can combine alice_choice and alice_choice_salt and hash them together to create something that Bob can't guess Alices choice from. But Alice can later submit her choice and the salt to prove her choice.\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": 13,\n   \"metadata\": {},\n   \"outputs\": [\n    {\n     \"data\": {\n      \"text/plain\": [\n       \"'rock88ceef7a2c748432d5a150fcff5df717c8a67298365ae2e1969be4ee856ce39e'\"\n      ]\n     },\n     \"execution_count\": 13,\n     \"metadata\": {},\n     \"output_type\": \"execute_result\"\n    }\n   ],\n   \"source\": [\n    \"alice_salted_choice = alice_choice + alice_choice_salt\\n\",\n    \"alice_salted_choice\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": 14,\n   \"metadata\": {},\n   \"outputs\": [\n    {\n     \"data\": {\n      \"text/plain\": [\n       \"'dcbd95890db4648405b1e04541b6dcabacc1c3e958172171262dc11d6dacebf7'\"\n      ]\n     },\n     \"execution_count\": 14,\n     \"metadata\": {},\n     \"output_type\": \"execute_result\"\n    }\n   ],\n   \"source\": [\n    \"alice_salted_choice_hash = sha3(alice_salted_choice)\\n\",\n    \"alice_salted_choice_hash\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"Before a game is started it is in state `\\\"game_doesnt_exist\\\"`\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": 15,\n   \"metadata\": {},\n   \"outputs\": [],\n   \"source\": [\n    \"assert contract.get_game_state(game_id=0) == \\\"game_doesnt_exist\\\"\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"Now Alice starts a game so she can invite Bob to play.\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": 16,\n   \"metadata\": {},\n   \"outputs\": [\n    {\n     \"data\": {\n      \"text/plain\": [\n       \"0\"\n      ]\n     },\n     \"execution_count\": 16,\n     \"metadata\": {},\n     \"output_type\": \"execute_result\"\n    }\n   ],\n   \"source\": [\n    \"alice_game_id = contract.start_game(password_hash=alice_game_password_hash, player1_choice_hash=alice_salted_choice_hash) \\n\",\n    \"alice_game_id\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"Alice gets back a game Id.\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"The game is now in state \\\"only_player1_submitted\\\"\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": 17,\n   \"metadata\": {},\n   \"outputs\": [],\n   \"source\": [\n    \"assert contract.get_game_state(game_id=alice_game_id) == \\\"only_player1_submitted\\\"\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"Now Alice has to tell Bob the password and the game Id. This could be done over a messenger or built into the frontend of an application. \\n\",\n    \"\\n\",\n    \"Everything that starts with bob_ is only visible to Bob.\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": 18,\n   \"metadata\": {},\n   \"outputs\": [],\n   \"source\": [\n    \"bob_game_password = alice_game_password\\n\",\n    \"bob_game_id = alice_game_id\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"Now it is Bobs turn.\\n\",\n    \"Bob chooses scissors.\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": 19,\n   \"metadata\": {},\n   \"outputs\": [],\n   \"source\": [\n    \"bob_choice = \\\"scissors\\\"\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"And now Bob has to salt his choice.\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": 20,\n   \"metadata\": {},\n   \"outputs\": [\n    {\n     \"data\": {\n      \"text/plain\": [\n       \"'13729fb6834f46b30046d82ba9e624821a479ed1f7714152c8a4da81b42d1213'\"\n      ]\n     },\n     \"execution_count\": 20,\n     \"metadata\": {},\n     \"output_type\": \"execute_result\"\n    }\n   ],\n   \"source\": [\n    \"bob_choice_salt = secrets.token_hex(32)\\n\",\n    \"bob_choice_salt\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"And now we combine bob_choice and bob_choice_salt together and hash them.\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": 21,\n   \"metadata\": {},\n   \"outputs\": [\n    {\n     \"data\": {\n      \"text/plain\": [\n       \"'scissors13729fb6834f46b30046d82ba9e624821a479ed1f7714152c8a4da81b42d1213'\"\n      ]\n     },\n     \"execution_count\": 21,\n     \"metadata\": {},\n     \"output_type\": \"execute_result\"\n    }\n   ],\n   \"source\": [\n    \"bob_salted_choice = bob_choice + bob_choice_salt\\n\",\n    \"bob_salted_choice\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": 22,\n   \"metadata\": {},\n   \"outputs\": [\n    {\n     \"data\": {\n      \"text/plain\": [\n       \"'9af37ec1317afab75c13f89f1d4a8b4c39f77ae52e7ad05116a5f8b2f9995125'\"\n      ]\n     },\n     \"execution_count\": 22,\n     \"metadata\": {},\n     \"output_type\": \"execute_result\"\n    }\n   ],\n   \"source\": [\n    \"bob_salted_choice_hash = sha3(bob_salted_choice)\\n\",\n    \"bob_salted_choice_hash\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"Bob now needs to submit his choice to the blockchain. Only Bob has the game password so only Bob can join Alices game.\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": 23,\n   \"metadata\": {},\n   \"outputs\": [],\n   \"source\": [\n    \"contract.submit_choice(game_password=bob_game_password, game_id=bob_game_id, player2_choice_hash=bob_salted_choice_hash)\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"The game is now in state \\\"both_players_submitted\\\"\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": 24,\n   \"metadata\": {},\n   \"outputs\": [],\n   \"source\": [\n    \"assert contract.get_game_state(game_id=bob_game_id) == \\\"both_players_submitted\\\"\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"Now that both players have submitted their hashed and salted choices, both players can reveal their choices.\\n\",\n    \"The order doesn't matter. Alice goes first in this example.\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": 25,\n   \"metadata\": {},\n   \"outputs\": [],\n   \"source\": [\n    \"contract.reveal(game_id=alice_game_id, choice=alice_choice, choice_salt=alice_choice_salt, is_player1=True)\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"The game is now in state \\\"only_player1_revealed\\\"\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": 26,\n   \"metadata\": {},\n   \"outputs\": [],\n   \"source\": [\n    \"assert contract.get_game_state(game_id=alice_game_id) == \\\"only_player1_revealed\\\"\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"Bob goes second\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": 27,\n   \"metadata\": {},\n   \"outputs\": [],\n   \"source\": [\n    \"contract.reveal(game_id=bob_game_id, choice=bob_choice, choice_salt=bob_choice_salt, is_player1=False)\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"Now we can see who won the game\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": 28,\n   \"metadata\": {},\n   \"outputs\": [\n    {\n     \"data\": {\n      \"text/plain\": [\n       \"'player1_wins'\"\n      ]\n     },\n     \"execution_count\": 28,\n     \"metadata\": {},\n     \"output_type\": \"execute_result\"\n    }\n   ],\n   \"source\": [\n    \"contract.get_game_state(game_id=alice_game_id)\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"As expected Alice, who is player1, wins!\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"## tests\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"Test function is_valid_choice\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": 29,\n   \"metadata\": {},\n   \"outputs\": [],\n   \"source\": [\n    \"assert contract.is_valid_choice(choice=\\\"rock\\\")\\n\",\n    \"assert contract.is_valid_choice(choice=\\\"paper\\\")\\n\",\n    \"assert contract.is_valid_choice(choice=\\\"scissors\\\")\\n\",\n    \"assert not contract.is_valid_choice(choice=\\\"airplane\\\")\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"Test function beats\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": 30,\n   \"metadata\": {},\n   \"outputs\": [],\n   \"source\": [\n    \"assert contract.beats(choice1=\\\"rock\\\", choice2=\\\"scissors\\\")\\n\",\n    \"assert not contract.beats(choice1=\\\"rock\\\", choice2=\\\"rock\\\")\\n\",\n    \"assert not contract.beats(choice1=\\\"rock\\\", choice2=\\\"paper\\\")\\n\",\n    \"\\n\",\n    \"assert contract.beats(choice1=\\\"paper\\\", choice2=\\\"rock\\\")\\n\",\n    \"assert not contract.beats(choice1=\\\"paper\\\", choice2=\\\"paper\\\")\\n\",\n    \"assert not contract.beats(choice1=\\\"paper\\\", choice2=\\\"scissors\\\")\\n\",\n    \"\\n\",\n    \"assert contract.beats(choice1=\\\"scissors\\\", choice2=\\\"paper\\\")\\n\",\n    \"assert not contract.beats(choice1=\\\"scissors\\\", choice2=\\\"scissors\\\")\\n\",\n    \"assert not contract.beats(choice1=\\\"scissors\\\", choice2=\\\"rock\\\")\"\n   ]\n  }\n ],\n \"metadata\": {\n  \"kernelspec\": {\n   \"display_name\": \"Python 3\",\n   \"language\": \"python\",\n   \"name\": \"python3\"\n  },\n  \"language_info\": {\n   \"codemirror_mode\": {\n    \"name\": \"ipython\",\n    \"version\": 3\n   },\n   \"file_extension\": \".py\",\n   \"mimetype\": \"text/x-python\",\n   \"name\": \"python\",\n   \"nbconvert_exporter\": \"python\",\n   \"pygments_lexer\": \"ipython3\",\n   \"version\": \"3.7.3\"\n  }\n },\n \"nbformat\": 4,\n \"nbformat_minor\": 2\n}\n"
  },
  {
    "path": "pyproject.toml",
    "content": "[tool.poetry]\nname = \"xian-contracting\"\nversion = \"1.0.1\"\ndescription = \"Xian Network Python Contracting Engine\"\nauthors = [\"Xian Network <info@xian.org>\"]\nreadme = \"README.md\"\npackages = [{include = \"contracting\", from = \"src\"}]\nlicense = \"GPL-3.0-only\"\nrepository = \"https://github.com/xian-network/xian-contracting\"\nkeywords = [\"blockchain\", \"xian\", \"contracting\", \"python\"]\nclassifiers = [\n    \"Programming Language :: Python :: 3.11\",\n    \"License :: OSI Approved :: GNU General Public License v3 (GPLv3)\",\n    \"Development Status :: 5 - Production/Stable\",\n]\n\n[tool.poetry.dependencies]\npython = \"~=3.11.0\"\nastor = \"0.8.1\"\npycodestyle = \"2.10.0\"\nautopep8 = \"1.5.7\"\niso8601 = \"*\"\nh5py = \"*\"\ncachetools = \"*\"\nloguru = \"*\"\npynacl = \"*\"\npsutil = \"*\"\n\n[build-system]\nrequires = [\"poetry-core\"]\nbuild-backend = \"poetry.core.masonry.api\"\n"
  },
  {
    "path": "release.sh",
    "content": "#!/bin/bash\n\nset -e  # Exit on any error\n\n# Colors for output\nRED='\\033[0;31m'\nGREEN='\\033[0;32m'\nYELLOW='\\033[1;33m'\nNC='\\033[0m' # No Color\n\n# Function to print with color\nprint_status() {\n    echo -e \"${GREEN}==>${NC} $1\"\n}\n\nprint_warning() {\n    echo -e \"${YELLOW}WARNING:${NC} $1\"\n}\n\nprint_error() {\n    echo -e \"${RED}ERROR:${NC} $1\"\n}\n\n# Check if a version bump type was provided\nif [ -z \"$1\" ]; then\n    print_error \"Please provide a version bump type: patch, minor, or major\"\n    echo \"Usage: ./release.sh [patch|minor|major]\"\n    exit 1\nfi\n\n# Validate version bump type\nif [ \"$1\" != \"patch\" ] && [ \"$1\" != \"minor\" ] && [ \"$1\" != \"major\" ]; then\n    print_error \"Invalid version bump type. Please use: patch, minor, or major\"\n    exit 1\nfi\n\n# Make sure we're on the master branch\nBRANCH=$(git branch --show-current)\nif [ \"$BRANCH\" != \"master\" ]; then\n    print_error \"Please switch to the master branch before creating a release\"\n    exit 1\nfi\n\n# Make sure the working directory is clean\nif [ -n \"$(git status --porcelain)\" ]; then\n    print_error \"Working directory is not clean. Please commit or stash changes first.\"\n    exit 1\nfi\n\n# Check if poetry is installed\nif ! command -v poetry &> /dev/null; then\n    print_error \"Poetry could not be found. Please install it first.\"\n    exit 1\nfi\n\n# Check if pytest is installed\nif ! poetry run python -c \"import pytest\" 2>/dev/null; then\n    print_warning \"pytest is not installed. Skipping tests.\"\n    RUN_TESTS=false\nelse\n    RUN_TESTS=true\nfi\n\n# Pull latest changes\nprint_status \"Pulling latest changes from master...\"\ngit pull origin master\n\n# Show what the new version will be and ask for confirmation\nCURRENT_VERSION=$(poetry version -s)\nNEW_VERSION=$(poetry version $1 --dry-run)\nprint_status \"Current version: $CURRENT_VERSION\"\nprint_status \"New version will be: $NEW_VERSION\"\n\n# Generate changelog\nLAST_TAG=$(git describe --tags --abbrev=0 2>/dev/null || echo \"none\")\nif [ \"$LAST_TAG\" != \"none\" ]; then\n    print_status \"Generating changelog since $LAST_TAG...\"\n    CHANGELOG=$(git log \"$LAST_TAG\"..HEAD --oneline --pretty=format:\"- %s\")\nelse\n    CHANGELOG=$(git log --oneline --pretty=format:\"- %s\")\nfi\n\necho -e \"\\nChangelog:\"\necho \"$CHANGELOG\"\necho\n\n# Check dependencies\nprint_status \"Checking for outdated dependencies...\"\npoetry show --outdated || true\n\n# Run tests if available\nif [ \"$RUN_TESTS\" = true ]; then\n    print_status \"Running tests...\"\n    poetry run pytest || {\n        print_error \"Tests failed!\"\n        exit 1\n    }\nfi\n\n# Final confirmation\necho\nprint_status \"Ready to release version $NEW_VERSION\"\nread -p \"Continue? (y/n) \" -n 1 -r\necho\nif [[ ! $REPLY =~ ^[Yy]$ ]]; then\n    print_status \"Release cancelled.\"\n    exit 1\nfi\n\n# Update version using Poetry\nprint_status \"Bumping version ($1)...\"\npoetry version $1\n\n# Create release notes file\nRELEASE_NOTES=\"release_notes.md\"\necho \"# Release Notes for v$NEW_VERSION\" > $RELEASE_NOTES\necho \"\" >> $RELEASE_NOTES\necho \"## Changes\" >> $RELEASE_NOTES\necho \"$CHANGELOG\" >> $RELEASE_NOTES\n\n# Stage and commit version bump\nprint_status \"Committing version bump...\"\ngit add pyproject.toml $RELEASE_NOTES\ngit commit -m \"Bump version to $NEW_VERSION\n\nRelease Notes:\n$CHANGELOG\"\n\n# Create and push tag\nprint_status \"Creating and pushing tag v$NEW_VERSION...\"\ngit tag -a \"v$NEW_VERSION\" -m \"Version $NEW_VERSION\n\n$CHANGELOG\"\ngit push && git push --tags\n\n# Cleanup\nrm $RELEASE_NOTES\n\nprint_status \"Release process initiated!\"\nprint_status \"Version $NEW_VERSION will be published to PyPI and GitHub releases automatically.\"\nprint_status \"You can monitor the progress at: https://github.com/xian-network/xian-contracting/actions\""
  },
  {
    "path": "src/contracting/__init__.py",
    "content": ""
  },
  {
    "path": "src/contracting/client.py",
    "content": "from contracting.execution.executor import Executor\nfrom contracting.storage.driver import Driver\nfrom contracting.compilation.compiler import ContractingCompiler\nfrom contracting.stdlib.bridge.time import Datetime\nfrom datetime import datetime\nfrom functools import partial\nfrom types import FunctionType\n\nimport ast\nimport inspect\nimport astor\nimport autopep8\nimport os\n\nfrom . import constants\n\nfrom .storage.orm import Variable\nfrom .storage.orm import Hash\n\n\nclass AbstractContract:\n    def __init__(self, name, signer, environment, executor: Executor, funcs, return_full_output=False):\n        self.name = name\n        self.signer = signer\n        self.environment = environment\n        self.executor = executor\n        self.functions = funcs\n\n        # set up virtual functions\n        for f in funcs:\n            # unpack tuple packed in SenecaClient\n            func, kwargs = f\n\n            # set the kwargs to None. these will fail if they are not provided\n            default_kwargs = {}\n            for kwarg in kwargs:\n                default_kwargs[kwarg] = None\n\n            # each function is a partial that allows kwarg overloading and overriding\n            setattr(self, func, partial(self._abstract_function_call,\n                                        signer=self.signer,\n                                        contract_name=self.name,\n                                        executor=self.executor,\n                                        func=func,\n                                        return_full_output=return_full_output,\n                                        # environment=self.environment,\n                                        **default_kwargs))\n\n    def keys(self):\n        # Scope strictly to this contract's namespace\n        return self.executor.driver.keys(f\"{self.name}.\")\n\n    # a variable contains a DOT, but no __, and no :\n    # a hash contains a DOT, no __, and a :\n    # a constant contains __, a DOT, and :\n\n    def quick_read(self, variable, key=None, args=None):\n        a = []\n\n        if key is not None:\n            a.append(key)\n\n        if args is not None and isinstance(args, list):\n            for arg in args:\n                a.append(arg)\n\n        k = self.executor.driver.make_key(contract=self.name, variable=variable, args=a)\n        return self.executor.driver.get(k)\n\n    def quick_write(self, variable, key=None, value=None, args=None):\n        if key is not None:\n            a = [key]\n        else:\n            a = []\n\n        if args is not None and isinstance(args, list):\n            for arg in args:\n                a.append(arg)\n\n        k = self.executor.driver.make_key(contract=self.name, variable=variable, args=a)\n\n        self.executor.driver.set(k, value)\n        self.executor.driver.commit()\n\n    def run_private_function(self, f, signer=None, environment=None, **kwargs):\n        # Override kwargs if provided\n        signer = signer or self.signer\n        environment = environment or self.environment\n\n        # Let executor access private functions\n        self.executor.bypass_privates = True\n\n        # Append private method prefix to function name if it isn't there already\n        if not f.startswith(constants.PRIVATE_METHOD_PREFIX):\n            f = '{}{}'.format(constants.PRIVATE_METHOD_PREFIX, f)\n\n        # Execute\n        result = self._abstract_function_call(\n            signer=signer,\n            executor=self.executor,\n            contract_name=self.name,\n            environment=environment,\n            func=f,\n            metering=None,\n            now=None,\n            **kwargs\n        )\n\n        # Set executor back to restricted mode\n        self.executor.bypass_privates = False\n\n        return result\n\n    def __getattr__(self, item):\n        try:\n            # return the attribute if it exists on the instance\n            return self.__getattribute__(item)\n        except AttributeError as e:\n\n            # otherwise, attempt to resolve it. full name is contract.item\n            fullname = '{}.{}'.format(self.name, item)\n\n            # if the raw name exists, it is a __protected__ or a variable, so prepare for those\n            if fullname in self.keys():\n                variable = Variable(contract=self.name, name=item, driver=self.executor.driver)\n\n                # return just the value if it is __protected__ to prevent sets\n                if item.startswith('__'):\n                    return variable.get()\n\n                # otherwise, return the variable object with allows sets\n                return variable\n\n            # otherwise, see if contract.items: has more than one entry\n            if len(self.executor.driver.values(prefix=self.name + '.' + item + ':')) > 0:\n\n                # if so, it is a hash. return the hash object\n                return Hash(contract=self.name, name=item, driver=self.executor.driver)\n\n            # otherwise, the attribut does not exist, so throw the error.\n            raise e\n\n    def now(self):\n        d = datetime.today()\n        return Datetime(d.year, d.month, d.day, hour=d.hour, minute=d.minute)\n\n    def _abstract_function_call(\n            self,\n            signer,\n            executor,\n            contract_name,\n            func,\n            environment=None,\n            stamps=constants.DEFAULT_STAMPS,\n            metering=None,\n            now=None,\n            return_full_output=False,\n            **kwargs\n    ):\n\n        # for k, v in kwargs.items():\n        #     assert v is not None, 'Keyword \"{}\" not provided. Must not be None.'.format(k)\n        environment = environment or self.environment\n\n        if now is None:\n            now = self.now()\n\n        if environment.get('now') is None:\n            environment.update({'now': now})\n\n        output = executor.execute(\n            sender=signer,\n            contract_name=contract_name,\n            function_name=func,\n            kwargs=kwargs,\n            stamps=stamps,\n            environment=environment,\n            metering=metering\n        )\n\n        if executor.production:\n            executor.sandbox.terminate()\n\n        if output['status_code'] == 1:\n            raise output['result'] if not return_full_output else output\n        return output['result'] if not return_full_output else output\n\n\nclass ContractingClient:\n    def __init__(\n            self,\n            signer='sys',\n            submission_filename=os.path.join(os.path.dirname(__file__), 'contracts/submission.s.py'),\n            storage_home=constants.STORAGE_HOME,\n            driver:Driver=None,\n            metering=False,\n            compiler=ContractingCompiler(),\n            environment={},\n    ):\n        driver = driver if driver is not None else Driver(storage_home=storage_home)\n        self.executor = Executor(metering=metering, driver=driver)\n        self.raw_driver = driver\n        self.signer = signer\n        self.compiler = compiler\n        self.submission_filename = submission_filename\n        self.environment = environment\n        # Get submission contract from file\n        if submission_filename is not None:\n            # Seed the genesis contracts into the instance\n            with open(self.submission_filename) as f:\n                contract = f.read()\n\n            self.raw_driver.set_contract(name='submission', code=contract)\n            self.raw_driver.commit()\n\n        # Get submission contract from state\n        self.submission_contract = self.get_contract('submission')\n\n    def set_submission_contract(self, filename=None, commit=True):\n        state_contract = self.get_contract('submission')\n\n        if filename is None:\n            filename = self.submission_filename\n\n        if filename is None and state_contract is None:\n            raise AssertionError(\"No submission contract provided or found in state.\")\n\n        if filename is not None:\n            with open(filename) as f:\n                contract = f.read()\n\n            self.raw_driver.delete_contract(name='submission')\n            self.raw_driver.set_contract(name='submission', code=contract)\n\n            if commit:\n                self.raw_driver.commit()\n\n        self.submission_contract = self.get_contract('submission')\n\n    def flush(self):\n        # flushes storage and resubmits genesis contracts\n        self.raw_driver.flush_full()\n        self.raw_driver.flush_cache()\n\n        if self.submission_filename is not None:\n            self.set_submission_contract()\n\n    # Returns abstract contract which has partial methods mapped to each exported function.\n    def get_contract(self, name):\n        contract = self.raw_driver.get_contract(name)\n\n        if contract is None:\n            return None\n\n        tree = ast.parse(contract)\n\n        function_defs = [n for n in ast.walk(tree) if isinstance(n, ast.FunctionDef)]\n\n        funcs = []\n        for definition in function_defs:\n            func_name = definition.name\n            kwargs = [arg.arg for arg in definition.args.args]\n\n            funcs.append((func_name, kwargs))\n\n        return AbstractContract(\n            name=name,\n            signer=self.signer,\n            environment=self.environment,\n            executor=self.executor,\n            funcs=funcs,\n        )\n\n    def closure_to_code_string(self, f):\n        closure_code = inspect.getsource(f)\n        closure_code = autopep8.fix_code(closure_code)\n        closure_tree = ast.parse(closure_code)\n\n        # Remove the enclosing function by swapping out the function def node with its children\n        assert len(closure_tree.body) == 1, 'Module has multiple body nodes.'\n        assert isinstance(closure_tree.body[0], ast.FunctionDef), 'Function definition not found at root.'\n\n        func_def_body = closure_tree.body[0]\n        closure_tree.body = func_def_body.body\n\n        contract_code = astor.to_source(closure_tree)\n        name = func_def_body.name\n\n        return contract_code, name\n\n    def lint(self, f, raise_errors=False):\n        if isinstance(f, FunctionType):\n            f, _ = self.closure_to_code_string(f)\n\n        tree = ast.parse(f)\n        violations = self.compiler.linter.check(tree)\n\n        if violations is None:\n            return None\n        else:\n            if raise_errors:\n                for v in violations:\n                    raise Exception(v)\n            else:\n                return violations\n\n    def compile(self, f):\n        if isinstance(f, FunctionType):\n            f, _ = self.closure_to_code_string(f)\n\n        code = self.compiler.parse_to_code(f)\n        return code\n\n    def submit(self, f, name=None, metering=None, owner=None, constructor_args={}, signer=None):\n\n        assert self.submission_contract is not None, \"No submission contract set. Try set_submission_contract first.\"\n\n        if isinstance(f, FunctionType):\n            f, n = self.closure_to_code_string(f)\n            if name is None:\n                name = n\n\n        assert name is not None, 'No name provided.'\n\n        if signer is None:\n            signer = self.signer\n\n        self.submission_contract.submit_contract(\n            name=name,\n            code=f,\n            owner=owner,\n            constructor_args=constructor_args,\n            metering=metering,\n            signer=signer\n        )\n\n    def get_contracts(self):\n        contracts = []\n        for key in self.raw_driver.keys():\n            if key.endswith('.__code__'):\n                contracts.append(key.replace('.__code__', ''))\n        return contracts\n\n    def get_var(self, contract, variable, arguments=[], mark=False):\n        return self.raw_driver.get_var(contract, variable, arguments, mark)\n\n    def set_var(self, contract, variable, arguments=[], value=None, mark=False):\n        self.raw_driver.set_var(contract, variable, arguments, value, mark)\n"
  },
  {
    "path": "src/contracting/compilation/__init__.py",
    "content": ""
  },
  {
    "path": "src/contracting/compilation/compiler.py",
    "content": "import ast\nimport astor\n\nfrom contracting import constants\nfrom contracting.compilation.linter import Linter\n\n\nclass ContractingCompiler(ast.NodeTransformer):\n    def __init__(self, module_name='__main__', linter=Linter()):\n        self.module_name = module_name\n        self.linter = linter\n        self.lint_alerts = None\n        self.constructor_visited = False\n        self.private_names = set()\n        self.orm_names = set()\n        self.visited_names = set()  # store the method visits\n\n    def parse(self, source: str, lint=True):\n        self.constructor_visited = False\n\n        tree = ast.parse(source)\n\n        if lint:\n            self.lint_alerts = self.linter.check(tree)\n            # compilation.fix_missing_locations(tree)\n\n        tree = self.visit(tree)\n\n        if self.lint_alerts is not None:\n            raise Exception(self.lint_alerts)\n\n        # check all visited nodes and see if they are actually private\n\n        # An Expr node can have a value func of compilation.Name, or compilation.\n        # Attribute which you much access the value of.\n        # TODO: This code branching is not ideal and should be investigated for simplicity.\n        for node in self.visited_names:\n            if node.id in self.private_names or node.id in self.orm_names:\n                node.id = self.privatize(node.id)\n\n        ast.fix_missing_locations(tree)\n\n        # reset state\n        self.private_names = set()\n        self.orm_names = set()\n        self.visited_names = set()\n\n        return tree\n\n    @staticmethod\n    def privatize(s):\n        return '{}{}'.format(constants.PRIVATE_METHOD_PREFIX, s)\n\n    def compile(self, source: str, lint=True):\n        tree = self.parse(source, lint=lint)\n\n        compiled_code = compile(tree, '<compilation>', 'exec')\n\n        return compiled_code\n\n    def parse_to_code(self, source, lint=True):\n        tree = self.parse(source, lint=lint)\n        code = astor.to_source(tree)\n        return code\n\n    def visit_FunctionDef(self, node):\n\n        # Presumes all decorators are valid, as caught by linter.\n        if node.decorator_list:\n            # Presumes that a single decorator is passed. This is caught by the linter.\n            decorator = node.decorator_list.pop()\n\n            # change the name of the init function to '____' so it is uncallable except once\n            if decorator.id == constants.INIT_DECORATOR_STRING:\n                node.name = '____'\n\n            elif decorator.id == constants.EXPORT_DECORATOR_STRING:\n                # Transform @export decorators to @__export(contract_name) decorators\n                decorator.id = '{}{}'.format('__', constants.EXPORT_DECORATOR_STRING)\n\n                new_node = ast.Call(\n                    func=decorator,\n                    args=[ast.Str(s=self.module_name)],\n                    keywords=[]\n                )\n\n                node.decorator_list.append(new_node)\n\n        else:\n            self.private_names.add(node.name)\n            node.name = self.privatize(node.name)\n\n        self.generic_visit(node)\n\n        return node\n\n    def visit_Assign(self, node):\n        if (isinstance(node.value, ast.Call) and not\n            isinstance(node.value.func, ast.Attribute) and\n            node.value.func.id in constants.ORM_CLASS_NAMES):\n\n            node.value.keywords.append(ast.keyword('contract', ast.Str(self.module_name)))\n            node.value.keywords.append(ast.keyword('name', ast.Str(node.targets[0].id)))\n            self.orm_names.add(node.targets[0].id)\n\n        self.generic_visit(node)\n\n        return node\n\n    def visit_Name(self, node):\n        self.visited_names.add(node)\n        return node\n\n    def visit_Expr(self, node):\n        self.generic_visit(node)\n        return node\n\n    def visit_Num(self, node):\n        if isinstance(node.n, float):\n            return ast.Call(func=ast.Name(id='decimal', ctx=ast.Load()),\n                            args=[ast.Str(str(node.n))], keywords=[])\n        return node\n"
  },
  {
    "path": "src/contracting/compilation/linter.py",
    "content": "import ast\nimport sys\n\nfrom .. import constants\n\nfrom ..compilation.whitelists import (\n    ALLOWED_AST_TYPES,\n    ALLOWED_ANNOTATION_TYPES,\n    VIOLATION_TRIGGERS,\n    ILLEGAL_BUILTINS,\n    ILLEGAL_AST_TYPES\n)\n\n\nclass Linter(ast.NodeVisitor):\n\n    def __init__(self):\n        self._violations = []\n        self._functions = []\n        self._is_one_export = False\n        self._is_success = True\n        self._constructor_visited = False\n        self.orm_names = set()\n        self.visited_args = set()\n        self.return_annotation = set()\n        self.arg_types = set()\n\n        self.builtins = list(set(list(sys.stdlib_module_names) + list(sys.builtin_module_names)))\n\n    def ast_types(self, t, lnum):\n        if type(t) not in ALLOWED_AST_TYPES:\n            str = \"Line {}\".format(lnum) + \" : \" + VIOLATION_TRIGGERS[0] + \" : {}\" .format(type(t).__name__)\n            self._violations.append(str)\n            self._is_success = False\n\n    def not_system_variable(self, v, lnum):\n        if v.startswith('_') or v.endswith('_'):\n            str = \"Line {} : \".format(lnum) + VIOLATION_TRIGGERS[1] + \" : {}\" .format(v)\n            self._violations.append(str)\n            self._is_success = False\n\n    def no_nested_imports(self, node):\n        for item in node.body:\n            if type(item) in [ast.ImportFrom, ast.Import]:\n                str = \"Line {}: \".format(node.lineno) + VIOLATION_TRIGGERS[2]\n                self._violations.append(str)\n                self._is_success = False\n\n    def visit_Name(self, node):\n        self.not_system_variable(node.id, node.lineno)\n\n        if node.id == 'rt':# or node.id == 'Hash' or node.id == 'Variable':\n            self._is_success = False\n            str = \"Line {}: \".format(node.lineno) + VIOLATION_TRIGGERS[13]\n            self._violations.append(str)\n\n        if node.id in ILLEGAL_BUILTINS and node.id != 'float':\n            self._is_success = False\n            str = \"Line {}: \".format(node.lineno) + VIOLATION_TRIGGERS[13]\n            self._violations.append(str)\n\n        self.generic_visit(node)\n        return node\n\n    def visit_Attribute(self, node):\n        self.not_system_variable(node.attr, node.lineno)\n        if node.attr == 'rt':\n            self._is_success = False\n            str = \"Line {}: \".format(node.lineno) + VIOLATION_TRIGGERS[13]\n            self._violations.append(str)\n        self.generic_visit(node)\n        return node\n\n    def visit_Import(self, node):\n        for n in node.names:\n            if n.name in self.builtins:\n                self._is_success = False\n                str = \"Line {}: \".format(node.lineno) + VIOLATION_TRIGGERS[13]\n                self._violations.append(str)\n        return node\n\n    def visit_ImportFrom(self, node):\n        str = \"Line {}: \".format(node.lineno) + VIOLATION_TRIGGERS[3]\n        self._violations.append(str)\n        self._is_success = False\n\n    # TODO: Why are we even doing any logic instead of just failing on visiting these?\n    def visit_ClassDef(self, node):\n        str = \"Line {}: \".format(node.lineno) + VIOLATION_TRIGGERS[5]\n        self._violations.append(str)\n        self._is_success = False\n        self.generic_visit(node)\n        return node\n\n    def visit_AsyncFunctionDef(self, node):\n        str = \"Line {}: \".format(node.lineno) + VIOLATION_TRIGGERS[6]\n        self._violations.append(str)\n\n        self._is_success = False\n        self.generic_visit(node)\n        return node\n\n    def visit_Assign(self, node):\n        # resource_names, func_name = Assert.valid_assign(node, Parser.parser_scope)\n        if isinstance(node.value, ast.Name):\n            if node.value.id == 'Hash' or node.value.id == 'Variable' or node.value.id == 'LogEvent':\n                self._is_success = False\n                str = \"Line {}: \".format(node.lineno) + VIOLATION_TRIGGERS[13]\n                self._violations.append(str)\n\n        if (isinstance(node.value, ast.Call) and not\n            isinstance(node.value.func, ast.Attribute) and\n            node.value.func.id in constants.ORM_CLASS_NAMES):\n\n            if node.value.func.id in ['Variable', 'Hash', 'LogEvent']:\n                kwargs = [k.arg for k in node.value.keywords]\n                if 'contract' in kwargs or 'name' in kwargs:\n                    self._is_success = False\n                    str = \"Line {}: \".format(node.lineno) + VIOLATION_TRIGGERS[10]\n                    self._violations.append(str)\n            if ast.Tuple in [type(t) for t in node.targets] or isinstance(node.value, ast.Tuple):\n                self._is_success = False\n                str = \"Line {}: \".format(node.lineno) + VIOLATION_TRIGGERS[11]\n                self._violations.append(str)\n            try:\n                self.orm_names.add(node.targets[0].id)\n            except AttributeError:\n                pass\n\n        self.generic_visit(node)\n\n        return node\n\n    def visit_AugAssign(self, node):\n        # TODO: Checks here?\n        self.generic_visit(node)\n        return node\n\n    def visit_Call(self, node: ast.Call):\n        # Prevent calling of illegal builtins\n        if isinstance(node.func, ast.Name):\n            if node.func.id in ILLEGAL_BUILTINS:\n                self._is_success = False\n                str = \"Line {}: \".format(node.lineno) + VIOLATION_TRIGGERS[13]\n                self._violations.append(str)\n\n        self.generic_visit(node)\n        return node\n\n    def generic_visit(self, node):\n        # Prevent calling of illegal builtins\n\n        if type(node) in ILLEGAL_AST_TYPES:\n            self._is_success = False\n            s = \"Line {}: \".format(node.lineno) + VIOLATION_TRIGGERS[0]\n            self._violations.append(s)\n\n        return super().generic_visit(node)\n\n    def visit_Num(self, node):\n        # NOTE: Integers are important for indexing and slicing so we cannot replace them.\n        # They also will not suffer from rounding issues.\n        # TODO: are any types we don't allow right now?\n        self.generic_visit(node)\n        return node\n\n    def visit_FunctionDef(self, node):\n        self.no_nested_imports(node)\n\n        # Make sure there are no closures\n        try:\n            for n in node.body:\n                if isinstance(n, ast.FunctionDef):\n                    str = \"Line {}: \".format(node.lineno) + VIOLATION_TRIGGERS[18]\n                    self._violations.append(str)\n                    self._is_success = False\n        except:\n            pass\n\n        # Only allow 1 decorator per function definition.\n        if len(node.decorator_list) > 1:\n            str = \"Line {}: \".format(node.lineno) + VIOLATION_TRIGGERS[9] + \\\n                  \": Detected: {} MAX limit: 1\".format(len(node.decorator_list))\n            self._violations.append(str)\n            self._is_success = False\n        export_decorator = False\n        for d in node.decorator_list:\n            # Only allow decorators from the allowed set.\n            if d.id not in constants.VALID_DECORATORS:\n                str = \"Line {}: \".format(node.lineno) + VIOLATION_TRIGGERS[7] + \\\n                      \": valid list: {}\".format(d.id, constants.VALID_DECORATORS)\n                self._violations.append(str)\n                self._is_success = False\n\n            if d.id == constants.EXPORT_DECORATOR_STRING:\n                self._is_one_export = True\n                export_decorator = True\n\n            if d.id == constants.INIT_DECORATOR_STRING:\n                if self._constructor_visited:\n                    str = \"Line {}: \".format(node.lineno) + VIOLATION_TRIGGERS[8]\n                    self._violations.append(str)\n                    self._is_success = False\n                self._constructor_visited = True\n\n        # Add argument names to set to make sure that no ORM variable names are being reused in function def args\n        arguments = node.args\n        for a in arguments.args:\n            self.visited_args.add((a.arg, node.lineno))\n            if export_decorator:\n                if a.annotation is not None:\n                    try:\n                        self.arg_types.add((a.annotation.id, node.lineno))\n                    except AttributeError:\n                        arg = a.annotation.value.id + '.' + a.annotation.attr\n                        self.arg_types.add((arg, node.lineno))\n                else:\n                    self.arg_types.add((None, node.lineno))\n\n        if export_decorator:\n            if node.returns is not None:\n                try:\n                    self.arg_types.add((a.annotation.id, node.lineno))\n                except AttributeError:\n                    arg = a.annotation.value.id + '.' + a.annotation.attr\n                    self.arg_types.add((arg, node.lineno))\n            else:\n                self.return_annotation.add((None, node.lineno))\n\n        self.generic_visit(node)\n        return node\n\n    def annotation_types(self, t, lnum):\n        if t is None:\n            str = \"Line {}\".format(lnum) + \" : \" + VIOLATION_TRIGGERS[16]\n            self._violations.append(str)\n            self._is_success = False\n        elif t not in ALLOWED_ANNOTATION_TYPES:\n            str = \"Line {}\".format(lnum) + \" : \" + VIOLATION_TRIGGERS[15] + \" : {}\" .format(t)\n            self._violations.append(str)\n            self._is_success = False\n\n    def check_return_types(self, t, lnum):\n        if t is not None:\n            str = \"Line {}\".format(lnum) + \" : \" + VIOLATION_TRIGGERS[17] + \" : {}\" .format(t)\n            self._violations.append(str)\n            self._is_success = False\n\n    def _reset(self):\n        self._violations = []\n        self._functions = []\n        self._is_one_export = False\n        self._is_success = True\n        self._constructor_visited = False\n        self.orm_names = set()\n        self.visited_args = set()\n        self.return_annotation = set()\n        self.arg_types = set()\n\n    def _final_checks(self):\n        for name, lineno in self.visited_args:\n            if name in self.orm_names:\n                str = \"Line {}: \".format(lineno) + VIOLATION_TRIGGERS[14]\n                self._violations.append(str)\n                self._is_success = False\n\n        if not self._is_one_export:\n            str = \"Line 0: \" + VIOLATION_TRIGGERS[12]\n            self._violations.append(str)\n            self._is_success = False\n\n        for t, lineno in self.arg_types:\n            self.annotation_types(t,lineno)\n\n        for t, lineno in self.return_annotation:\n            self.check_return_types(t,lineno)\n\n    def _collect_function_defs(self, root):\n        for node in ast.walk(root):\n            if isinstance(node, ast.FunctionDef):\n                self._functions.append(node.name)\n            elif isinstance(node, ast.Import) or isinstance(node, ast.ImportFrom):\n                for n in node.names:\n                    if n.asname:\n                        self._functions.append(n.asname)\n                    else:\n                        self._functions.append(n.name.split('.')[-1])\n\n    def check(self, ast_tree):\n        self._reset()\n        # pass 1 - collect function def and imports\n        self._collect_function_defs(ast_tree)\n        self.visit(ast_tree)\n        self._final_checks()\n        if self._is_success is False:\n            return sorted(self._violations, key=lambda x: int(x.split(':')[0].split()[1]))\n        else:\n            return None\n\n    def dump_violations(self):\n        import pprint\n        pp = pprint.PrettyPrinter(indent=4)\n        pp.pprint(self._violations)\n"
  },
  {
    "path": "src/contracting/compilation/parser.py",
    "content": "import ast\n\n\ndef methods_for_contract(contract_code: str):\n    tree = ast.parse(contract_code)\n\n    function_defs = [n for n in ast.walk(tree) if isinstance(n, ast.FunctionDef)]\n\n    funcs = []\n    for definition in function_defs:\n        func_name = definition.name\n\n        if func_name.startswith('__'):\n            continue\n\n        kwargs = []\n\n        for arg in definition.args.args:\n            try:\n                a = arg.annotation.id\n            except AttributeError:\n                a = arg.annotation.value.id + '.' + arg.annotation.attr\n\n            kwargs.append({\n                'name': arg.arg,\n                'type': a\n            })\n\n        funcs.append({'name': func_name, 'arguments': kwargs})\n\n    return funcs\n\n\ndef variables_for_contract(contract_code: str):\n    tree = ast.parse(contract_code)\n\n    assigns = []\n\n    for node in ast.walk(tree):\n        if isinstance(node, ast.Assign):\n            assigns.append(node)\n\n        if isinstance(node, ast.FunctionDef):\n            break\n\n    variables = []\n    hashes = []\n\n    for assign in assigns:\n        if type(assign.value) == ast.Call:\n            if assign.value.func.id == 'Variable':\n                variables.append(assign.targets[0].id.lstrip('__'))\n            elif assign.value.func.id == 'Hash':\n                hashes.append(assign.targets[0].id.lstrip('__'))\n\n    return {\n        'variables': variables,\n        'hashes': hashes\n    }\n"
  },
  {
    "path": "src/contracting/compilation/whitelists.py",
    "content": "import ast, builtins\n\nALLOWED_BUILTINS = {'Exception', 'False', 'None', 'True', 'abs', 'all', 'any', 'ascii', 'bin', 'bool', 'bytearray',\n                    'bytes', 'chr', 'dict', 'divmod', 'filter', 'format', 'frozenset', 'hex', 'int', 'isinstance',\n                    'issubclass', 'import', 'len', 'list', 'map', 'max', 'min', 'oct', 'ord', 'pow', 'range', 'reversed',\n                    'round', 'set', 'sorted', 'str', 'sum', 'tuple', 'zip'}\n\nILLEGAL_BUILTINS = set(dir(builtins)) - ALLOWED_BUILTINS\n\nALLOWED_AST_TYPES = {ast.Module, ast.Eq, ast.Call, ast.Dict, ast.Attribute, ast.Pow, ast.Index, ast.Not, ast.alias,\n                     ast.If, ast.FunctionDef, ast.Global, ast.GtE, ast.LtE, ast.Load, ast.arg, ast.Add, ast.Import,\n                     ast.ImportFrom, ast.Name, ast.Num, ast.BinOp, ast.Store, ast.Assert, ast.Assign, ast.AugAssign,\n                     ast.Subscript, ast.Compare, ast.Return, ast.NameConstant, ast.Expr, ast.keyword, ast.Sub,\n                     ast.arguments, ast.List, ast.Set, ast.Str, ast.UnaryOp, ast.Pass, ast.Tuple, ast.Div, ast.In,\n                     ast.NotIn, ast.Gt, ast.Lt, ast.Starred, ast.Mod, ast.NotEq, ast.For, ast.While, ast.ListComp,\n                     ast.comprehension, ast.Slice, ast.USub, ast.BoolOp, ast.And, ast.Or, ast.Mult, ast.IsNot, ast.Is, ast.Constant}\n\nILLEGAL_AST_TYPES = {\n    ast.AsyncFor,\n    ast.AsyncFunctionDef,\n    ast.AsyncWith,\n    ast.Await,\n    ast.ClassDef,\n    ast.Ellipsis,\n    ast.GeneratorExp,\n    ast.Global,\n    ast.ImportFrom,\n    ast.Interactive,\n    ast.Lambda,\n    ast.MatMult,\n    ast.Nonlocal,\n    ast.Suite,\n    ast.Try,\n    ast.With,\n    ast.Yield,\n    ast.YieldFrom,\n}\n\nALLOWED_ANNOTATION_TYPES = {'dict', 'list', 'str', 'int', 'float', 'bool', 'datetime.timedelta', 'datetime.datetime', 'Any'}\n\nVIOLATION_TRIGGERS = [\n    \"S1- Illegal contracting syntax type used\",\n    \"S2- Illicit use of '_' before variable\",\n    \"S3- Illicit use of Nested imports\",\n    \"S4- ImportFrom compilation nodes not yet supported\",\n    \"S5- Contract not found in lib\",\n    \"S6- Illicit use of classes\",\n    \"S7- Illicit use of Async functions\",\n    \"S8- Invalid decorator used\",\n    \"S9- Multiple use of constructors detected\",\n    \"S10- Illicit use of multiple decorators\",\n    \"S11- Illicit keyword overloading for ORM assignments\",\n    \"S12- Multiple targets to ORM definition detected\",\n    \"S13- No valid contracting decorator found\",\n    \"S14- Illegal use of a builtin\",\n    \"S15- Reuse of ORM name definition in a function definition argument name\",\n    \"S16- Illegal argument annotation used\",\n    \"S17- No valid argument annotation found\",\n    \"S18- Illegal use of return annotation\",\n    \"S19- Illegal use of a nested function definition.\"\n]\n"
  },
  {
    "path": "src/contracting/constants.py",
    "content": "from pathlib import Path\n\nRECURSION_LIMIT = 1024\n\nDELIMITER = ':'\nINDEX_SEPARATOR = '.'\nHDF5_GROUP_SEPARATOR = '/'\n\nSUBMISSION_CONTRACT_NAME = 'submission'\nPRIVATE_METHOD_PREFIX = '__'\nEXPORT_DECORATOR_STRING = 'export'\nINIT_DECORATOR_STRING = 'construct'\nINIT_FUNC_NAME = '__{}'.format(PRIVATE_METHOD_PREFIX)\nVALID_DECORATORS = {EXPORT_DECORATOR_STRING, INIT_DECORATOR_STRING}\n\nORM_CLASS_NAMES = {'Variable', 'Hash', 'ForeignVariable', 'ForeignHash', 'LogEvent'}\n\nMAX_HASH_DIMENSIONS = 16\nMAX_KEY_SIZE = 1024\n\nREAD_COST_PER_BYTE = 1\nWRITE_COST_PER_BYTE = 25\n\nSTAMPS_PER_TAU = 20\n\nBLOCK_NUM_DEFAULT = -1\nFILENAME_LEN_MAX = 255\n\nDEFAULT_STAMPS = 1000000\n\nSTORAGE_HOME = Path().home().joinpath(\".cometbft/xian\")\n"
  },
  {
    "path": "src/contracting/contracts/__init__.py",
    "content": ""
  },
  {
    "path": "src/contracting/contracts/proxythis.py",
    "content": "@export\r\ndef proxythis(con: str):\r\n    return importlib.import_module(con).getthis()\r\n\r\n@export\r\ndef nestedproxythis(con: str):\r\n    return importlib.import_module(con).nested_exported()\r\n\r\n@export\r\ndef noproxy():\r\n    return ctx.this, ctx.caller"
  },
  {
    "path": "src/contracting/contracts/submission.s.py",
    "content": "@__export('submission')\ndef submit_contract(name: str, code: str, owner: Any=None, constructor_args: dict={}):\n    if ctx.caller != 'sys':\n        assert name.startswith('con_'), 'Contract must start with con_!'\n\n    assert ctx.caller == ctx.signer, 'Contract cannot be called from another contract!'\n    assert len(name) <= 64, 'Contract name length exceeds 64 characters!'\n    assert name.islower(), 'Contract name must be lowercase!'\n\n    __Contract().submit(\n        name=name,\n        code=code,\n        owner=owner,\n        constructor_args=constructor_args,\n        developer=ctx.caller\n    )\n\n\n@__export('submission')\ndef change_developer(contract: str, new_developer: str):\n    d = __Contract()._driver.get_var(contract=contract, variable='__developer__')\n    assert ctx.caller == d, 'Sender is not current developer!'\n\n    __Contract()._driver.set_var(\n        contract=contract,\n        variable='__developer__',\n        value=new_developer\n    )\n"
  },
  {
    "path": "src/contracting/contracts/thistest2.py",
    "content": "@export\r\ndef exported():\r\n    return ctx.this, ctx.caller\r\n\r\n@export\r\ndef getthis():\r\n    return ctx.this, ctx.caller\r\n\r\n@export\r\ndef nested_exported():\r\n    return exported()\r\n"
  },
  {
    "path": "src/contracting/execution/__init__.py",
    "content": ""
  },
  {
    "path": "src/contracting/execution/executor.py",
    "content": "from contracting.execution import runtime\nfrom contracting.storage.driver import Driver\nfrom contracting.execution.module import install_database_loader, uninstall_builtins, enable_restricted_imports, disable_restricted_imports\nfrom contracting.stdlib.bridge.decimal import ContractingDecimal, CONTEXT\nfrom contracting.stdlib.bridge.random import Seeded\nfrom contracting import constants\nfrom copy import deepcopy\n\nimport importlib\nimport decimal\n\n\nclass Executor:\n    def __init__(self,\n                 production=False,\n                 driver=None,\n                 metering=True,\n                 currency_contract='currency',\n                 balances_hash='balances',\n                 bypass_privates=False,\n                 bypass_balance_amount=False,\n                 bypass_cache=False):\n\n        self.metering = metering\n        self.driver = driver\n\n        if not self.driver:\n            self.driver = Driver(bypass_cache=bypass_cache)\n        self.production = production\n\n        self.currency_contract = currency_contract\n        self.balances_hash = balances_hash\n\n        self.bypass_privates = bypass_privates\n        self.bypass_balance_amount = bypass_balance_amount  # For Stamp Estimation\n\n        runtime.rt.env.update({'__Driver': self.driver})\n\n    def wipe_modules(self):\n        uninstall_builtins()\n        install_database_loader()\n\n    def execute(self, sender, contract_name, function_name, kwargs,\n                environment={},\n                auto_commit=False,\n                driver=None,\n                stamps=constants.DEFAULT_STAMPS,\n                stamp_cost=constants.STAMPS_PER_TAU,\n                metering=None) -> dict:\n\n        current_driver_pending_writes = deepcopy(self.driver.pending_writes)\n        self.driver.clear_transaction_writes()\n        self.driver.clear_events()\n\n        if not self.bypass_privates:\n            assert not function_name.startswith(constants.PRIVATE_METHOD_PREFIX), 'Private method not callable.'\n\n        if metering is None:\n            metering = self.metering\n\n        runtime.rt.env.update({'__Driver': self.driver})\n\n        if driver:\n            runtime.rt.env.update({'__Driver': driver})\n        else:\n            driver = runtime.rt.env.get('__Driver')\n\n        install_database_loader(driver=driver)\n\n        balances_key = None\n\n        try:\n            if metering:\n                balances_key = (f'{self.currency_contract}'\n                                f'{constants.INDEX_SEPARATOR}'\n                                f'{self.balances_hash}'\n                                f'{constants.DELIMITER}'\n                                f'{sender}')\n\n                if self.bypass_balance_amount:\n                    balance = 9999999\n\n                else:\n                    balance = driver.get(balances_key)\n\n                    if type(balance) == dict:\n                        balance = ContractingDecimal(balance.get('__fixed__'))\n\n                    if balance is None:\n                        balance = 0\n\n                assert balance * stamp_cost >= stamps, (f'Sender does not have enough stamps for the transaction. '\n                                                        f'Balance at key {balances_key} is {balance}')\n\n            runtime.rt.env.update(environment)\n            status_code = 0\n\n            # Multiply stamps by 1000 because we divide by it later\n            # runtime.rt.set_up(stmps=stamps * 1000, meter=metering)\n\n            runtime.rt.context._base_state = {\n                'signer': sender,\n                'caller': sender,\n                'this': contract_name,\n                'entry': (contract_name, function_name),\n                'owner': driver.get_owner(contract_name),\n                'submission_name': None\n            }\n\n            if runtime.rt.context.owner is not None and runtime.rt.context.owner != runtime.rt.context.caller:\n                raise Exception(f'Caller {runtime.rt.context.caller} is not the owner {runtime.rt.context.owner}!')\n\n            decimal.setcontext(CONTEXT)\n\n            module = importlib.import_module(contract_name)\n            func = getattr(module, function_name)\n\n            # Add the contract name to the context on a submission call\n            if contract_name == constants.SUBMISSION_CONTRACT_NAME:\n                runtime.rt.context._base_state['submission_name'] = kwargs.get('name')\n\n            for k, v in kwargs.items():\n                if type(v) == float:\n                    kwargs[k] = ContractingDecimal(str(v))\n\n            enable_restricted_imports()\n            runtime.rt.set_up(stmps=stamps * 1000, meter=metering)\n            result = func(**kwargs)\n            transaction_writes = deepcopy(driver.transaction_writes)\n            events = deepcopy(driver.log_events)\n            runtime.rt.tracer.stop()\n            disable_restricted_imports()\n\n            if auto_commit:\n                driver.commit()\n\n        except Exception as e:\n            result = e\n            status_code = 1\n            # Revert the writes if the transaction fails\n            driver.pending_writes = current_driver_pending_writes\n            transaction_writes = {}\n            events = []\n            if auto_commit:\n                driver.flush_cache()\n\n        finally:\n            driver.clear_events()\n            driver.clear_transaction_writes()\n            runtime.rt.tracer.stop()\n\n        #runtime.rt.tracer.stop()\n\n        # Deduct the stamps if that is enabled\n        stamps_used = runtime.rt.tracer.get_stamp_used()\n\n        stamps_used = stamps_used // 1000\n        stamps_used += 5\n\n        if stamps_used > stamps:\n            stamps_used = stamps\n\n        if metering:\n            assert balances_key is not None, 'Balance key was not set properly. Cannot deduct stamps.'\n\n            to_deduct = stamps_used\n            to_deduct /= stamp_cost\n            to_deduct = ContractingDecimal(to_deduct)\n\n            balance = driver.get(balances_key)\n            if balance is None:\n                balance = 0\n\n            balance = max(balance - to_deduct, 0)\n\n            driver.set(balances_key, balance)\n            transaction_writes[balances_key] = balance\n\n            if auto_commit:\n                driver.commit()\n\n        Seeded.s = False\n        runtime.rt.clean_up()\n        runtime.rt.env.update({'__Driver': driver})\n\n        output = {\n            'status_code': status_code,\n            'result': result,\n            'stamps_used': stamps_used,\n            'writes': transaction_writes,\n            'reads': driver.pending_reads,\n            'events': events\n        }\n\n        disable_restricted_imports()\n        return output\n"
  },
  {
    "path": "src/contracting/execution/module.py",
    "content": "from importlib.abc import Loader\nfrom importlib import invalidate_caches, __import__\nfrom importlib.machinery import ModuleSpec\nfrom contracting.storage.driver import Driver\nfrom contracting.stdlib import env\nfrom contracting.execution.runtime import rt\n\nimport marshal\nimport builtins\nimport sys\nimport importlib.util\n\n# This function overrides the __import__ function, which is the builtin function that is called whenever Python runs\n# an 'import' statement. If the globals dictionary contains {'__contract__': True}, then this function will make sure\n# that the module being imported comes from the database and not from builtins or site packages.\n#\n# For all exec statements, we add the {'__contract__': True} _key to the globals to protect against unwanted imports.\n#\n# Note: anything installed with pip or in site-packages will also not work, so contract package names *must* be unique.\n\n\ndef is_valid_import(name):\n    spec = importlib.util.find_spec(name)\n    if not isinstance(spec.loader, DatabaseLoader):\n        raise ImportError(\"module {} cannot be imported in a smart contract.\".format(name))\n\n\ndef restricted_import(name, globals=None, locals=None, fromlist=(), level=0):\n    if globals is not None and globals.get('__contract__') is True:\n        spec = importlib.util.find_spec(name)\n        if spec is None or not isinstance(spec.loader, DatabaseLoader):\n            raise ImportError(\"module {} cannot be imported in a smart contract.\".format(name))\n\n    return __import__(name, globals, locals, fromlist, level)\n\n\ndef enable_restricted_imports():\n    builtins.__import__ = restricted_import\n#    builtins.float = ContractingDecimal\n\n\ndef disable_restricted_imports():\n    builtins.__import__ = __import__\n\n\ndef uninstall_builtins():\n    sys.meta_path.clear()\n    sys.path_hooks.clear()\n    sys.path.clear()\n    sys.path_importer_cache.clear()\n    invalidate_caches()\n\n\ndef install_database_loader(driver=Driver()):\n    DatabaseFinder.driver = driver\n    if DatabaseFinder not in sys.meta_path:\n        sys.meta_path.insert(0, DatabaseFinder)\n\n\ndef uninstall_database_loader():\n    sys.meta_path = list(set(sys.meta_path))\n    if DatabaseFinder in sys.meta_path:\n        sys.meta_path.remove(DatabaseFinder)\n\n\ndef install_system_contracts(directory=''):\n    pass\n\n\n'''\n    Is this where interaction with the database occurs with the interface of code strings, etc?\n    IE: pushing a contract does sanity checks here?\n'''\n\n\nclass DatabaseFinder:\n    driver = Driver()\n\n    def find_spec(self, fullname, path=None, target=None):\n        if DatabaseFinder.driver.get_contract(self) is None:\n            return None\n        return ModuleSpec(self, DatabaseLoader(DatabaseFinder.driver))\n\n\nMODULE_CACHE = {}\n\n\nclass DatabaseLoader(Loader):\n    def __init__(self, d=Driver()):\n        self.d = d\n\n    def create_module(self, spec):\n        return None\n\n    def exec_module(self, module):\n        # fetch the individual contract\n        code = self.d.get_compiled(module.__name__)\n        if code is None:\n            raise ImportError(\"Module {} not found\".format(module.__name__))\n\n        if type(code) != bytes:\n            code = bytes.fromhex(code)\n\n        code = marshal.loads(code)\n\n        if code is None:\n            raise ImportError(\"Module {} not found\".format(module.__name__))\n\n        scope = env.gather()\n        scope.update(rt.env)\n\n        scope.update({'__contract__': True})\n\n        # execute the module with the std env and update the module to pass forward\n        exec(code, scope)\n\n        # Update the module's attributes with the new scope\n        vars(module).update(scope)\n        del vars(module)['__builtins__']\n\n        rt.loaded_modules.append(module.__name__)\n\n    def module_repr(self, module):\n        return '<module {!r} (smart contract)>'.format(module.__name__)\n"
  },
  {
    "path": "src/contracting/execution/runtime.py",
    "content": "from contracting import constants\nfrom contracting.execution.tracer import Tracer\n\nimport contracting\nimport sys\nimport os\nimport math\n\n\nclass Context:\n    def __init__(self, base_state, maxlen=constants.RECURSION_LIMIT):\n        self._state = []\n        self._depth = []\n        self._base_state = base_state\n        self._maxlen = maxlen\n\n    def _context_changed(self, contract):\n        if self._get_state()['this'] == contract:\n            return False\n        return True\n\n    def _get_state(self):\n        if len(self._state) == 0:\n            return self._base_state\n        return self._state[-1]\n\n    def _add_state(self, state: dict):\n        if self._context_changed(state['this']) and len(self._state) < self._maxlen:\n            self._state.append(state)\n            self._depth.append(1)\n\n    def _ins_state(self):\n        if len(self._depth) > 0:\n            self._depth[-1] += 1\n\n    def _pop_state(self):\n        if len(self._state) > 0: #len(self._state) should equal len(self._depth)\n            self._depth[-1] -= 1\n            if self._depth[-1] == 0:\n                self._state.pop(-1)\n                self._depth.pop(-1)\n\n    def _reset(self):\n        self._state = []\n        self._depth = []\n\n    @property\n    def this(self):\n        return self._get_state()['this']\n\n    @property\n    def caller(self):\n        return self._get_state()['caller']\n\n    @property\n    def signer(self):\n        return self._get_state()['signer']\n\n    @property\n    def owner(self):\n        return self._get_state()['owner']\n\n    @property\n    def entry(self):\n        return self._get_state()['entry']\n\n    @property\n    def submission_name(self):\n        return self._get_state()['submission_name']\n\n_context = Context({\n        'this': None,\n        'caller': None,\n        'owner': None,\n        'signer': None,\n        'entry': None,\n        'submission_name': None\n    })\n\nWRITE_MAX = 1024 * 128\n\n\nclass Runtime:\n    cu_path = contracting.__path__[0]\n    cu_path = os.path.join(cu_path, 'execution', 'metering', 'cu_costs.const')\n\n    os.environ['CU_COST_FNAME'] = cu_path\n\n    loaded_modules = []\n\n    env = {}\n    stamps = 0\n\n    writes = 0\n\n    tracer = Tracer()\n\n    signer = None\n\n    context = _context\n\n    @classmethod\n    def set_up(cls, stmps, meter):\n        if meter:\n            cls.stamps = stmps\n            cls.tracer.set_stamp(stmps)\n            cls.tracer.start()\n\n        cls.context._reset()\n\n    @classmethod\n    def clean_up(cls):\n        cls.tracer.stop()\n        cls.tracer.reset()\n        cls.stamps = 0\n        cls.writes = 0\n\n        cls.signer = None\n\n        for mod in cls.loaded_modules:\n            if sys.modules.get(mod) is not None:\n                del sys.modules[mod]\n\n        cls.loaded_modules = []\n        cls.env = {}\n\n    @classmethod\n    def deduct_read(cls, key, value):\n        if cls.tracer.is_started():\n            cost = len(key) + len(value)\n            cost *= constants.READ_COST_PER_BYTE\n            cls.tracer.add_cost(cost)\n\n    @classmethod\n    def deduct_write(cls, key, value):\n        if key is not None and cls.tracer.is_started():\n            cost = len(key) + len(value)\n            cls.writes += cost\n            assert cls.writes < WRITE_MAX, 'You have exceeded the maximum write capacity per transaction!'\n\n            stamp_cost = cost * constants.WRITE_COST_PER_BYTE\n            cls.tracer.add_cost(stamp_cost)\n\n\nrt = Runtime()\n"
  },
  {
    "path": "src/contracting/execution/tracer.py",
    "content": "import sys\nimport dis\nimport threading\nimport psutil\nimport os\n\n# Define the opcode costs\ncu_costs = {\n    0: 2, 1: 2, 2: 4, 3: 4, 4: 4, 5: 4, 6: 4, 7: 4, 8: 4, 9: 2, 10: 2, 11: 4, 12: 2,\n    13: 4, 14: 4, 15: 4, 16: 4, 17: 4, 18: 4, 19: 4, 20: 2, 21: 4, 22: 8, 23: 6, 24: 6,\n    25: 4, 26: 4, 27: 4, 28: 4, 29: 4, 30: 4, 31: 6, 32: 6, 33: 6, 34: 2, 35: 6, 36: 6,\n    37: 6, 38: 2, 39: 4, 40: 4, 41: 4, 42: 4, 43: 4, 44: 2, 45: 2, 46: 2, 47: 4, 48: 2,\n    49: 6, 50: 6, 51: 6, 52: 6, 53: 4, 54: 6, 55: 4, 56: 4, 57: 4, 58: 4, 59: 4, 60: 4,\n    61: 4, 62: 4, 63: 4, 64: 6, 65: 6, 66: 8, 67: 8, 68: 8, 69: 12, 70: 2, 71: 1610, 72: 8,\n    73: 6, 74: 4, 75: 6, 76: 6, 77: 4, 78: 4, 79: 4, 80: 6, 81: 6, 82: 4, 83: 2, 84: 126,\n    85: 1000, 86: 4, 87: 8, 88: 6, 89: 4, 90: 2, 91: 2, 92: 2, 93: 512, 94: 8, 95: 6, 96: 6,\n    97: 4, 98: 4, 99: 2, 100: 2, 101: 2, 102: 2, 103: 6, 104: 8, 105: 8, 106: 4, 107: 4,\n    108: 38, 109: 126, 110: 4, 111: 4, 112: 4, 113: 6, 114: 4, 115: 4, 116: 4, 117: 4, 118: 6,\n    119: 6, 120: 4, 121: 4, 122: 4, 123: 6, 124: 32, 125: 2, 126: 2, 127: 4, 128: 4, 129: 4,\n    130: 6, 131: 10, 132: 8, 133: 12, 134: 4, 135: 4, 136: 8, 137: 2, 138: 2, 139: 2, 140: 4,\n    141: 6, 142: 12, 143: 6, 144: 2, 145: 8, 146: 8, 147: 6, 148: 2, 149: 6, 150: 6, 151: 6,\n    152: 6, 153: 4, 154: 4, 155: 4, 156: 6, 157: 4, 158: 4, 159: 4, 160: 4, 161: 2, 162: 4,\n    163: 6, 164: 6, 165: 6, 166: 6, 167: 2, 168: 4, 169: 4, 170: 2, 171: 8, 172: 2, 173: 4,\n    174: 4, 175: 4, 176: 4, 177: 4, 178: 4, 179: 4, 180: 4, 255: 8\n}\n\n# Define maximum stamps\nMAX_STAMPS = 6500000\n\nclass Tracer:\n    def __init__(self):\n        self.cost = 0\n        self.stamp_supplied = 0\n        self.last_frame_mem_usage = 0\n        self.total_mem_usage = 0\n        self.started = False\n        self.call_count = 0\n        self.max_call_count = 800000\n        self.instruction_cache = {}\n        self.lock = threading.Lock()\n\n    def start(self):\n        sys.settrace(self.trace_func)\n        self.cost = 0\n        self.call_count = 0\n        self.started = True\n\n    def stop(self):\n        if self.started:\n            sys.settrace(None)\n            self.started = False\n\n    def reset(self):\n        self.stop()\n        self.cost = 0\n        self.stamp_supplied = 0\n        self.last_frame_mem_usage = 0\n        self.total_mem_usage = 0\n        self.call_count = 0\n\n    def set_stamp(self, stamp):\n        self.stamp_supplied = stamp\n\n    def add_cost(self, new_cost):\n        self.cost += new_cost\n        if self.cost > self.stamp_supplied or self.cost > MAX_STAMPS:\n            self.stop()\n            raise AssertionError(\"The cost has exceeded the stamp supplied!\")\n\n    def get_stamp_used(self):\n        return self.cost\n\n    def get_last_frame_mem_usage(self):\n        return self.last_frame_mem_usage\n\n    def get_total_mem_usage(self):\n        return self.total_mem_usage\n\n    def is_started(self):\n        return self.started\n\n    def get_memory_usage(self):\n        process = psutil.Process(os.getpid())\n        mem_info = process.memory_info()\n        # Return the RSS (Resident Set Size)\n        return mem_info.rss\n\n    def trace_func(self, frame, event, arg):\n        if event == 'line':\n            self.call_count += 1\n            if self.call_count > self.max_call_count:\n                self.stop()\n                raise AssertionError(\"Call count exceeded threshold! Infinite Loop?\")\n\n            # Check if the function matches the target module and function names\n            code = frame.f_code\n            current_function_name = code.co_name\n            globals_dict = frame.f_globals\n            module_name = globals_dict.get('__name__', '')\n\n            # Only trace code within contracts (if '__contract__' in globals)\n            if '__contract__' not in globals_dict:\n                return\n\n            # Get the opcode at the current instruction\n            lasti = frame.f_lasti\n            opcode = self.get_opcode(code, lasti)\n\n            # Update memory usage\n            if self.last_frame_mem_usage == 0:\n                self.last_frame_mem_usage = self.get_memory_usage()\n\n            new_memory_usage = self.get_memory_usage()\n            if new_memory_usage > self.last_frame_mem_usage:\n                self.total_mem_usage += (new_memory_usage - self.last_frame_mem_usage)\n            self.last_frame_mem_usage = new_memory_usage\n\n            # Check for memory usage limit (set an arbitrary limit, e.g., 500MB)\n            if self.total_mem_usage > 500 * 1024 * 1024:\n                self.stop()\n                raise AssertionError(f\"Transaction exceeded memory usage! Total usage: {self.total_mem_usage} bytes\")\n\n            # Add cost based on opcode\n            opcode_cost = cu_costs.get(opcode, 1)  # Default cost if opcode not found\n            self.cost += opcode_cost\n\n            if self.cost > self.stamp_supplied or self.cost > MAX_STAMPS:\n                self.stop()\n                raise AssertionError(\"The cost has exceeded the stamp supplied!\")\n\n        return self.trace_func\n\n    def get_opcode(self, code, offset):\n        # Cache the instruction map per code object\n        with self.lock:\n            instruction_map = self.instruction_cache.get(code)\n            if instruction_map is None:\n                instruction_map = {}\n                for instr in dis.get_instructions(code):\n                    instruction_map[instr.offset] = instr.opcode\n                self.instruction_cache[code] = instruction_map\n            opcode = instruction_map.get(offset, None)\n            if opcode is None:\n                # Instruction not found; default to 0\n                opcode = 0\n            return opcode\n"
  },
  {
    "path": "src/contracting/stdlib/__init__.py",
    "content": ""
  },
  {
    "path": "src/contracting/stdlib/bridge/__init__.py",
    "content": ""
  },
  {
    "path": "src/contracting/stdlib/bridge/access.py",
    "content": "from contracting.execution.runtime import rt\nfrom contextlib import ContextDecorator\nfrom contracting.storage.driver import Driver\nfrom typing import Any\n\n\nclass __export(ContextDecorator):\n    def __init__(self, contract):\n        self.contract = contract\n\n    def __enter__(self, *args, **kwargs):\n        driver = rt.env.get('__Driver') or Driver()\n\n        if rt.context._context_changed(self.contract):\n            current_state = rt.context._get_state()\n\n            state = {\n                'owner': driver.get_owner(self.contract),\n                'caller': current_state['this'],\n                'signer': current_state['signer'],\n                'this': self.contract,\n                'entry': current_state['entry'],\n                'submission_name': current_state['submission_name']\n            }\n\n            rt.context._add_state(state)\n\n            if state['owner'] is not None and state['owner'] != state['caller']:\n                raise Exception('Caller is not the owner!')\n        else:\n            rt.context._ins_state()\n\n    def __exit__(self, *args, **kwargs):\n        rt.context._pop_state()\n\n\nexports = {\n    '__export': __export,\n    'ctx': rt.context,\n    'rt': rt,\n    'Any': Any\n}\n"
  },
  {
    "path": "src/contracting/stdlib/bridge/crypto.py",
    "content": "from types import ModuleType\nimport nacl\n\n\ndef verify(vk: str, msg: str, signature: str):\n    vk = bytes.fromhex(vk)\n    msg = msg.encode()\n    signature = bytes.fromhex(signature)\n\n    vk = nacl.signing.VerifyKey(vk)\n    try:\n        vk.verify(msg, signature)\n    except:\n        return False\n    return True\n\n\ndef key_is_valid(key: str):\n    \"\"\" Check if the given address is valid.\n     Can be used with public and private keys \"\"\"\n    if not len(key) == 64:\n        return False\n    try:\n        int(key, 16)\n    except:\n        return False\n    return True\n\n\ncrypto_module = ModuleType('crypto')\ncrypto_module.verify = verify\ncrypto_module.key_is_valid = key_is_valid\n\nexports = {\n    'crypto': crypto_module\n}\n"
  },
  {
    "path": "src/contracting/stdlib/bridge/decimal.py",
    "content": "from decimal import Decimal, Context, ROUND_FLOOR\nimport decimal\n\n# Define precision constants\nMAX_UPPER_PRECISION = 30\nMAX_LOWER_PRECISION = 30\n\n# Set the decimal context for precision and rounding\nCONTEXT = Context(\n    prec=MAX_UPPER_PRECISION + MAX_LOWER_PRECISION,\n    rounding=ROUND_FLOOR,\n    Emin=-100,\n    Emax=100\n)\ndecimal.setcontext(CONTEXT)\n\n# Create min and max decimal strings for precision boundaries\ndef make_min_decimal_str(prec):\n    return '0.' + '0' * (prec - 1) + '1'\n\ndef make_max_decimal_str(prec):\n    return '1' + '0' * (prec - 1)\n\n# Convert scientific notation to non-exponential format if needed\ndef neg_sci_not(s: str):\n    try:\n        base, exp = s.split('e-')\n        if float(base) > 9:\n            return s\n\n        base = base.replace('.', '')\n        numbers = ('0' * (int(exp) - 1)) + base\n\n        if int(exp) > 0:\n            numbers = '0.' + numbers\n\n        return numbers\n    except ValueError:\n        return s\n\n# Define maximum and minimum decimal constants\nMAX_DECIMAL = Decimal(make_max_decimal_str(MAX_UPPER_PRECISION))\nMIN_DECIMAL = Decimal(make_min_decimal_str(MAX_LOWER_PRECISION))\n\n# Ensure the value is within bounds and quantized\ndef fix_precision(x: Decimal):\n    if x > MAX_DECIMAL:\n        return MAX_DECIMAL\n    return x.quantize(MIN_DECIMAL, rounding=ROUND_FLOOR).normalize()\n\n# Main ContractingDecimal class\nclass ContractingDecimal:\n    def _get_other(self, other):\n        if isinstance(other, ContractingDecimal):\n            return other._d\n        elif isinstance(other, (float, int)):\n            return fix_precision(Decimal(neg_sci_not(str(other))))\n        return other\n\n    def __init__(self, a):\n        if isinstance(a, (float, int)):\n            self._d = Decimal(neg_sci_not(str(a)))\n        elif isinstance(a, str):\n            self._d = Decimal(neg_sci_not(a))\n        elif isinstance(a, Decimal):\n            self._d = a\n        else:\n            self._d = Decimal(a)\n\n        # Clamp and quantize during initialization\n        self._d = fix_precision(self._d)\n\n    def __bool__(self):\n        return self._d > 0\n\n    def __eq__(self, other):\n        return self._d == self._get_other(other)\n\n    def __lt__(self, other):\n        return self._d < self._get_other(other)\n\n    def __le__(self, other):\n        return self._d <= self._get_other(other)\n\n    def __gt__(self, other):\n        return self._d > self._get_other(other)\n\n    def __ge__(self, other):\n        return self._d >= self._get_other(other)\n\n    def __str__(self):\n        return self._d.to_eng_string()\n\n    def __repr__(self):\n        return self._d.to_eng_string()\n\n    def __neg__(self):\n        return ContractingDecimal(-self._d)\n\n    def __pos__(self):\n        return self\n\n    def __abs__(self):\n        return ContractingDecimal(abs(self._d))\n\n    def __add__(self, other):\n        return ContractingDecimal(fix_precision(self._d + self._get_other(other)))\n\n    def __radd__(self, other):\n        return ContractingDecimal(fix_precision(self._get_other(other) + self._d))\n\n    def __sub__(self, other):\n        return ContractingDecimal(fix_precision(self._d - self._get_other(other)))\n\n    def __rsub__(self, other):\n        return ContractingDecimal(fix_precision(self._get_other(other) - self._d))\n\n    def __mul__(self, other):\n        return ContractingDecimal(fix_precision(self._d * self._get_other(other)))\n\n    def __rmul__(self, other):\n        return ContractingDecimal(fix_precision(self._get_other(other) * self._d))\n\n    def __truediv__(self, other):\n        return ContractingDecimal(fix_precision(self._d / self._get_other(other)))\n\n    def __rtruediv__(self, other):\n        return ContractingDecimal(fix_precision(self._get_other(other) / self._d))\n\n    def __mod__(self, other):\n        return ContractingDecimal(fix_precision(self._d % self._get_other(other)))\n\n    def __rmod__(self, other):\n        return ContractingDecimal(fix_precision(self._get_other(other) % self._d))\n\n    def __floordiv__(self, other):\n        return ContractingDecimal(fix_precision(self._d // self._get_other(other)))\n\n    def __rfloordiv__(self, other):\n        return ContractingDecimal(fix_precision(self._get_other(other) // self._d))\n\n    def __pow__(self, other):\n        return ContractingDecimal(fix_precision(self._d ** self._get_other(other)))\n\n    def __rpow__(self, other):\n        return ContractingDecimal(fix_precision(self._get_other(other) ** self._d))\n\n    def __int__(self):\n        return int(self._d)\n\n    def __float__(self):\n        return float(self._d)\n\n    def __round__(self, n=None):\n        return round(self._d, n)\n\n# Export ContractingDecimal for external use\nexports = {\n    'decimal': ContractingDecimal\n}\n"
  },
  {
    "path": "src/contracting/stdlib/bridge/hashing.py",
    "content": "import hashlib\n\nfrom types import ModuleType\n\n'''\nBytes can't be stored in JSON so we use hex-strings converted into bytes and back.\n'''\n\n\ndef sha3(hex_str: str):\n    try:\n        byte_str = bytes.fromhex(hex_str)\n    except ValueError:\n        byte_str = hex_str.encode()\n\n    hasher = hashlib.sha3_256()\n    hasher.update(byte_str)\n\n    hashed_bytes = hasher.digest()\n\n    return hashed_bytes.hex()\n\n\ndef sha256(hex_str: str):\n    try:\n        byte_str = bytes.fromhex(hex_str)\n    except ValueError:\n        byte_str = hex_str.encode()\n\n    hasher = hashlib.sha256()\n    hasher.update(byte_str)\n\n    hashed_bytes = hasher.digest()\n\n    return hashed_bytes.hex()\n\n\nhashlib_module = ModuleType('hashlib')\nhashlib_module.sha3 = sha3\nhashlib_module.sha256 = sha256\n\nexports = {\n    'hashlib': hashlib_module,\n}\n"
  },
  {
    "path": "src/contracting/stdlib/bridge/imports.py",
    "content": "from types import FunctionType, ModuleType\nfrom contracting.constants import PRIVATE_METHOD_PREFIX\nfrom contracting.storage.orm import Datum\nfrom contracting.storage.driver import Driver, OWNER_KEY\nfrom contracting.execution.runtime import rt\n\nimport importlib\nimport sys\n\n\ndef extract_closure(fn):\n    closure = fn.__closure__[0]\n    return closure.cell_contents\n\n\nclass Func:\n    def __init__(self, name, args=(), private=False):\n        self.name = name\n\n        if private:\n            self.name = PRIVATE_METHOD_PREFIX + self.name\n\n        self.args = args\n\n    def is_of(self, f: FunctionType):\n\n        if f.__closure__ is not None:\n            f = extract_closure(f)\n\n        num_args = f.__code__.co_argcount\n\n        if f.__code__.co_name == self.name and f.__code__.co_varnames[:num_args] == self.args:\n            return True\n\n        return False\n\n\nclass Var:\n    def __init__(self, name, t):\n        self.name = PRIVATE_METHOD_PREFIX + name\n        assert issubclass(t, Datum), 'Cannot enforce a variable that is not a Variable, Hash, or Foreign type!'\n        self.type = t\n\n    def is_of(self, v):\n        if isinstance(v, self.type):\n            return True\n        return False\n\n\ndef import_module(name):\n    assert not name.isdigit() and all(c.isalnum() or c == '_' for c in name), 'Invalid contract name!'\n    assert name.islower(), 'Name must be lowercase!'\n\n    _driver = rt.env.get('__Driver') or Driver()\n\n    if name in set(list(sys.stdlib_module_names) + list(sys.builtin_module_names)):\n        raise ImportError\n\n    if name.startswith('_'):\n        raise ImportError\n\n    if _driver.get_contract(name) is None:\n        raise ImportError\n\n    return importlib.import_module(name, package=None)\n\n\ndef enforce_interface(m: ModuleType, interface: list):\n    implemented = vars(m)\n\n    for i in interface:\n        attribute = implemented.get(i.name)\n        if attribute is None:\n            return False\n\n        # Branch for data types\n        if isinstance(attribute, Datum):\n            if not i.is_of(attribute):\n                return False\n\n        if isinstance(attribute, FunctionType):\n            if not i.is_of(attribute):\n                return False\n\n    return True\n\n\ndef owner_of(m: ModuleType):\n    _driver = rt.env.get('__Driver') or Driver()\n    owner = _driver.get_var(m.__name__, OWNER_KEY)\n    return owner\n\n\nimports_module = ModuleType('importlib')\nimports_module.import_module = import_module\nimports_module.enforce_interface = enforce_interface\nimports_module.Func = Func\nimports_module.Var = Var\nimports_module.owner_of = owner_of\n\nexports = {\n    'importlib': imports_module,\n}\n"
  },
  {
    "path": "src/contracting/stdlib/bridge/orm.py",
    "content": "from contracting.storage.orm import Variable, Hash, ForeignVariable, ForeignHash, LogEvent\nfrom contracting.storage.contract import Contract\nfrom contracting.execution.runtime import rt\n\n\nclass V(Variable):\n    def __init__(self, *args, **kwargs):\n        if rt.env.get('__Driver') is not None:\n            kwargs['driver'] = rt.env.get('__Driver')\n        super().__init__(*args, **kwargs)\n\n\nclass H(Hash):\n    def __init__(self, *args, **kwargs):\n        if rt.env.get('__Driver') is not None:\n            kwargs['driver'] = rt.env.get('__Driver')\n        super().__init__(*args, **kwargs)\n\n\nclass FV(ForeignVariable):\n    def __init__(self, *args, **kwargs):\n        if rt.env.get('__Driver') is not None:\n            kwargs['driver'] = rt.env.get('__Driver')\n        super().__init__(*args, **kwargs)\n\n\nclass FH(ForeignHash):\n    def __init__(self, *args, **kwargs):\n        if rt.env.get('__Driver') is not None:\n            kwargs['driver'] = rt.env.get('__Driver')\n        super().__init__(*args, **kwargs)\n\n\nclass C(Contract):\n    def __init__(self, *args, **kwargs):\n        if rt.env.get('__Driver') is not None:\n            kwargs['driver'] = rt.env.get('__Driver')\n        super().__init__(*args, **kwargs)\n        \n\nclass LE(LogEvent):\n    def __init__(self, *args, **kwargs):\n        if rt.env.get('__Driver') is not None:\n            kwargs['driver'] = rt.env.get('__Driver')\n        super().__init__(*args, **kwargs)\n\n\n# Define the locals that will be available for smart contracts at runtime\nexports = {\n    'Variable': V,\n    'Hash': H,\n    'ForeignVariable': FV,\n    'ForeignHash': FH,\n    'LogEvent': LE,\n    '__Contract': C\n}\n"
  },
  {
    "path": "src/contracting/stdlib/bridge/random.py",
    "content": "\"\"\"\n    This module wraps and exposes the Python stdlib random functions that can be made deterministic with a random seed\n    and return fixed point precision where possible. This allows some psuedorandom behavior when it is nice to have, but\n    with the caveat that it's based on environmental constants such as the last block hash and public information such\n    as the sender's address to seed the random state so it's not *really* random.\n\n    It's most likely 'random enough' for most cases, but people can always theoretically reproduce the seed and try to\n    front-run a smart contract by testing the seeded randoms for a preferable outcome and submitting a transaction\n    before the next block is minted. While this is extremely unlikely and hard to pull off, it's a valid hole in the\n    security and needs to be accepted as a flaw when using random numbers on a reproducible transaction log such as a\n    blockchain.\n\"\"\"\n\nimport random\n\nfrom types import ModuleType\nfrom contracting.execution.runtime import rt\n\n\nclass Seeded:\n    s = False\n\n\ndef seed(aux_salt=None):\n    block_height = '0'\n    if rt.env.get('block_num') is not None:\n        block_height = str(rt.env.get('block_num'))\n\n    block_hash = rt.env.get('block_hash') or '0'\n    __input_hash = rt.env.get('__input_hash') or '0'\n\n    # Auxiliary salt is used to create completely unique random seeds based on some other properties (optional)\n    auxiliary_salt = ''\n    if aux_salt is not None and rt.env.get(aux_salt):\n        auxiliary_salt = str(rt.env.get(aux_salt))\n    else:\n        if rt.env.get(\"AUXILIARY_SALT\"):\n            auxiliary_salt = str(rt.env.get(\"AUXILIARY_SALT\"))\n\n    s = block_height + block_hash + __input_hash + auxiliary_salt\n\n    random.seed(s)\n    Seeded.s = True\n\n\ndef getrandbits(k):\n    assert Seeded.s, 'Random state not seeded. Call seed().'\n\n    b_str = ''\n    for i in range(k):\n        if random.random() > 0.5:\n            b_str += '1'\n        else:\n            b_str += '0'\n\n    return int(b_str, 2)\n\n\ndef shuffle(l):\n    assert Seeded.s, 'Random state not seeded. Call seed().'\n    random.shuffle(l)\n\n\ndef randrange(k):\n    assert Seeded.s, 'Random state not seeded. Call seed().'\n    return random.randrange(k)\n\n\ndef randint(a, b):\n    assert Seeded.s, 'Random state not seeded. Call seed().'\n    return random.randint(a, b)\n\n\ndef choice(l):\n    assert Seeded.s, 'Random state not seeded. Call seed().'\n    return random.choice(l)\n\n\ndef choices(l, k):\n    assert Seeded.s, 'Random state not seeded. Call seed().'\n    return random.choices(l, k=k)\n\n\n# Construct module for exposure in the contract runtime\nrandom_module = ModuleType('random')\nrandom_module.seed = seed\nrandom_module.shuffle = shuffle\nrandom_module.getrandbits = getrandbits\nrandom_module.randrange = randrange\nrandom_module.randint = randint\nrandom_module.choice = choice\nrandom_module.choices = choices\n\n# Add it to the export object and it's good to go\nexports = {\n    'random': random_module\n}\n"
  },
  {
    "path": "src/contracting/stdlib/bridge/time.py",
    "content": "from datetime import datetime as dt\nfrom datetime import timedelta as td\nfrom types import ModuleType\n\n\n# Redefine a controlled datetime object that feels like a regular Python datetime object but is restricted so that we\n# can regulate the user interaction with it to prevent security attack vectors. It may seem redundant, but it guarantees\n# security.\nSECONDS_IN_MINUTE = 60\nSECONDS_IN_HOUR = 3600\nSECONDS_IN_DAY = 86400\nSECONDS_IN_WEEK = 604800\n\n\ndef get_raw_seconds(weeks, days, hours, minutes, seconds):\n    m_sec = minutes * SECONDS_IN_MINUTE\n    h_sec = hours * SECONDS_IN_HOUR\n    d_sec = days * SECONDS_IN_DAY\n    w_sec = weeks * SECONDS_IN_WEEK\n\n    raw_seconds = seconds + m_sec + h_sec + d_sec + w_sec\n\n    return raw_seconds\n\n\nclass Datetime:\n    def __init__(self, year, month, day, hour=0, minute=0, second=0, microsecond=0):\n        self._datetime = dt(\n            year=year,\n            month=month,\n            day=day,\n            hour=hour,\n            minute=minute,\n            second=second,\n            microsecond=microsecond\n        )\n\n        self.year = self._datetime.year\n        self.month = self._datetime.month\n        self.day = self._datetime.day\n        self.hour = self._datetime.hour\n        self.minute = self._datetime.minute\n        self.second = self._datetime.second\n        self.microsecond = self._datetime.microsecond\n\n    def __lt__(self, other):\n        if type(other) != Datetime:\n            raise TypeError(f'{type(other)} is not a Datetime!')\n        return self._datetime < other._datetime\n\n    def __le__(self, other):\n        if type(other) != Datetime:\n            raise TypeError(f'{type(other)} is not a Datetime!')\n        return self._datetime <= other._datetime\n\n    def __eq__(self, other):\n        if type(other) != Datetime:\n            raise TypeError(f'{type(other)} is not a Datetime!')\n        return self._datetime == other._datetime\n\n    def __ge__(self, other):\n        if type(other) != Datetime:\n            raise TypeError(f'{type(other)} is not a Datetime!')\n        return self._datetime >= other._datetime\n\n    def __gt__(self, other):\n        if type(other) != Datetime:\n            raise TypeError(f'{type(other)} is not a Datetime!')\n        return self._datetime > other._datetime\n\n    def __ne__(self, other):\n        if type(other) != Datetime:\n            raise TypeError(f'{type(other)} is not a Datetime!')\n        return self._datetime != other._datetime\n\n    def __sub__(self, other):\n        if isinstance(other, Datetime):\n            delta = self._datetime - other._datetime\n            return Timedelta(days=delta.days, seconds=delta.seconds)\n        return NotImplemented\n\n    def __add__(self, other):\n        if isinstance(other, Timedelta):\n            return Datetime._from_datetime(self._datetime + other._timedelta)\n        return NotImplemented\n\n    def __str__(self):\n        return str(self._datetime)\n\n    def __repr__(self):\n        return self.__str__()\n\n    @classmethod\n    def _from_datetime(cls, d: dt):\n        return cls(year=d.year,\n                   month=d.month,\n                   day=d.day,\n                   hour=d.hour,\n                   minute=d.minute,\n                   second=d.second,\n                   microsecond=d.microsecond)\n    \n    @classmethod\n    def strptime(cls, date_string, format):\n        d = dt.strptime(date_string, format)\n        return cls._from_datetime(d)\n\nclass Timedelta:\n    def __init__(self, weeks=0,\n                       days=0,\n                       hours=0,\n                       minutes=0,\n                       seconds=0):\n\n        self._timedelta = td(\n            weeks=int(weeks), days=int(days), hours=int(hours), minutes=int(minutes), seconds=int(seconds)\n        )\n\n        # For fast access to how many hours are in a timedelta.\n        self.__raw_seconds = get_raw_seconds(\n            weeks=int(weeks), days=int(days), hours=int(hours), minutes=int(minutes), seconds=int(seconds)\n        )\n\n    def __lt__(self, other):\n        if type(other) != Timedelta:\n            raise TypeError(f'{type(other)} is not a Timedelta!')\n        return self._timedelta < other._timedelta\n\n    def __le__(self, other):\n        if type(other) != Timedelta:\n            raise TypeError(f'{type(other)} is not a Timedelta!')\n        return self._timedelta <= other._timedelta\n\n    def __eq__(self, other):\n        if type(other) != Timedelta:\n            raise TypeError(f'{type(other)} is not a Timedelta!')\n        return self._timedelta == other._timedelta\n\n    def __ge__(self, other):\n        if type(other) != Timedelta:\n            raise TypeError(f'{type(other)} is not a Timedelta!')\n        return self._timedelta >= other._timedelta\n\n    def __gt__(self, other):\n        if type(other) != Timedelta:\n            raise TypeError(f'{type(other)} is not a Timedelta!')\n        return self._timedelta > other._timedelta\n\n    def __ne__(self, other):\n        if type(other) != Timedelta:\n            raise TypeError(f'{type(other)} is not a Timedelta!')\n        return self._timedelta != other._timedelta\n\n    # Operator implementations inspired by CPython implementations\n    def __add__(self, other):\n        if isinstance(other, Timedelta):\n            return Timedelta(days=self._timedelta.days + other._timedelta.days,\n                             seconds=self._timedelta.seconds + other._timedelta.seconds)\n\n        if isinstance(other, Datetime):\n            d = other._datetime + self._timedelta\n            return Datetime._from_datetime(d)\n\n        return NotImplemented\n\n    def __sub__(self, other):\n        if isinstance(other, Timedelta):\n            return Timedelta(days=self._timedelta.days - other._timedelta.days,\n                             seconds=self._timedelta.seconds - other._timedelta.seconds,)\n\n        if isinstance(other, Datetime):\n            d = other._datetime - self._timedelta\n            return Datetime._from_datetime(d)\n\n        return NotImplemented\n\n    def __mul__(self, other):\n        if isinstance(other, Timedelta):\n            return Timedelta(days=self._timedelta.days * other._timedelta.days,\n                             seconds=self._timedelta.seconds * other._timedelta.seconds)\n        elif isinstance(other, int):\n            return Timedelta(days=self._timedelta.days * other,\n                             seconds=self._timedelta.seconds * other)\n\n        return NotImplemented\n\n    def __str__(self):\n        return str(self._timedelta)\n\n    def __repr__(self):\n        return self.__str__()\n\n    # Accesses raw seconds and does a simple modulo to get the number of the component in the total seconds\n    @property\n    def seconds(self):\n        return self.__raw_seconds\n\n    @property\n    def minutes(self):\n        return self.__raw_seconds // SECONDS_IN_MINUTE\n\n    @property\n    def hours(self):\n        return self.__raw_seconds // SECONDS_IN_HOUR\n\n    @property\n    def days(self):\n        return self.__raw_seconds // SECONDS_IN_DAY\n\n    @property\n    def weeks(self):\n        return self.__raw_seconds // SECONDS_IN_WEEK\n\n\nWEEKS = Timedelta(weeks=1)\nDAYS = Timedelta(days=1)\nHOURS = Timedelta(hours=1)\nMINUTES = Timedelta(minutes=1)\nSECONDS = Timedelta(seconds=1)\n\ndatetime_module = ModuleType('datetime')\ndatetime_module.datetime = Datetime\ndatetime_module.timedelta = Timedelta\ndatetime_module.WEEKS = WEEKS\ndatetime_module.DAYS = DAYS\ndatetime_module.HOURS = HOURS\ndatetime_module.MINUTES = MINUTES\ndatetime_module.SECONDS = SECONDS\n\nexports = {\n    'datetime': datetime_module\n}\n"
  },
  {
    "path": "src/contracting/stdlib/env.py",
    "content": "from contracting.stdlib.bridge.orm import exports as orm_exports\nfrom contracting.stdlib.bridge.hashing import exports as hash_exports\nfrom contracting.stdlib.bridge.time import exports as time_exports\nfrom contracting.stdlib.bridge.random import exports as random_exports\nfrom contracting.stdlib.bridge.imports import exports as imports_exports\nfrom contracting.stdlib.bridge.access import exports as access_exports\nfrom contracting.stdlib.bridge.decimal import exports as decimal_exports\nfrom contracting.stdlib.bridge.crypto import exports as crypto_exports\n\n# TODO create a module instead and return it inside of a dictionary like:\n# {\n#    'stdlib': module\n# }\n#\n# Then stdlib.datetime becomes available, etc\n\n\ndef gather():\n    env = {}\n\n    env.update(orm_exports)\n    env.update(hash_exports)\n    env.update(time_exports)\n    env.update(random_exports)\n    env.update(imports_exports)\n    env.update(access_exports)\n    env.update(decimal_exports)\n    env.update(crypto_exports)\n\n    return env\n"
  },
  {
    "path": "src/contracting/storage/__init__.py",
    "content": ""
  },
  {
    "path": "src/contracting/storage/contract.py",
    "content": "from contracting.compilation.compiler import ContractingCompiler\nfrom contracting.storage.driver import Driver\nfrom contracting.execution.runtime import rt\nfrom contracting.stdlib import env\nfrom contracting import constants\n\n_driver = rt.env.get('__Driver') or Driver()\n\n\nclass Contract:\n    def __init__(self, driver: Driver = _driver):\n        self._driver = driver\n\n    def submit(self, name, code, owner=None, constructor_args={}, developer=None):\n        if self._driver.get_contract(name) is not None:\n            raise Exception('Contract already exists.')\n\n        c = ContractingCompiler(module_name=name)\n\n        code_obj = c.parse_to_code(code, lint=True)\n\n        scope = env.gather()\n        scope.update({'__contract__': True})\n        scope.update(rt.env)\n\n        exec(code_obj, scope)\n\n        if scope.get(constants.INIT_FUNC_NAME) is not None:\n            if constructor_args is None:\n                constructor_args = {}\n            scope[constants.INIT_FUNC_NAME](**constructor_args)\n\n        now = scope.get('now')\n        if now is not None:\n            self._driver.set_contract(\n                name=name,\n                code=code_obj,\n                owner=owner,\n                overwrite=False,\n                timestamp=now,\n                developer=developer\n            )\n        else:\n            self._driver.set_contract(\n                name=name,\n                code=code_obj,\n                owner=owner,\n                overwrite=False,\n                developer=developer\n            )\n"
  },
  {
    "path": "src/contracting/storage/driver.py",
    "content": "from contracting.storage.encoder import encode_kv\nfrom contracting.execution.runtime import rt\nfrom contracting.stdlib.bridge.time import Datetime\nfrom contracting.stdlib.bridge.decimal import ContractingDecimal\nfrom datetime import datetime\nfrom pathlib import Path\nfrom cachetools import TTLCache\nfrom contracting import constants\nfrom contracting.storage import hdf5\n\nimport marshal\nimport decimal\nimport os\nimport shutil\n\nFILE_EXT = \".d\"\nHASH_EXT = \".x\"\n\nDELIMITER = \".\"\nHASH_DEPTH_DELIMITER = \":\"\n\nCODE_KEY = \"__code__\"\nTYPE_KEY = \"__type__\"\nAUTHOR_KEY = \"__author__\"\nOWNER_KEY = \"__owner__\"\nTIME_KEY = \"__submitted__\"\nCOMPILED_KEY = \"__compiled__\"\nDEVELOPER_KEY = \"__developer__\"\n\n\nclass Driver:\n    def __init__(self, bypass_cache=False, storage_home=constants.STORAGE_HOME):\n        self.pending_deltas = {}\n        self.pending_writes = {}\n        self.pending_reads = {}\n        self.transaction_writes = {}\n        self.log_events = []\n        self.cache = TTLCache(maxsize=1000, ttl=6*3600)\n        self.bypass_cache = bypass_cache\n        self.contract_state = storage_home.joinpath(\"contract_state\")\n        self.run_state = storage_home.joinpath(\"run_state\")\n        self.__build_directories()\n\n    def __build_directories(self):\n        self.contract_state.mkdir(exist_ok=True, parents=True)\n        self.run_state.mkdir(exist_ok=True, parents=True)\n\n    def __parse_key(self, key):\n        # Split the key into parts (filename, group, etc.)\n        parts = key.split(constants.INDEX_SEPARATOR, 1)  # Ensure key contains the INDEX_SEPARATOR\n        \n        # The first part should be the filename (e.g., \"currency\")\n        filename = parts[0].split(constants.DELIMITER, 1)[0]  # Get only 'currency' from 'currency.balances'\n        \n        # The rest (after the first '.') becomes the group and attribute inside the HDF5 file\n        if len(parts) > 1:\n            variable = parts[1].replace(constants.DELIMITER, constants.HDF5_GROUP_SEPARATOR)\n        else:\n            variable = parts[0].replace(constants.DELIMITER, constants.HDF5_GROUP_SEPARATOR)\n        \n        return filename, variable\n\n\n    def __filename_to_path(self, filename):\n        if filename.startswith(\"__\"):\n            return str(self.run_state.joinpath(filename))\n        else:\n            return str(self.contract_state.joinpath(filename))\n\n    def __get_files(self):\n        return sorted(os.listdir(self.contract_state) + os.listdir(self.run_state))\n    \n    def is_file(self, filename):\n        file_path = Path(self.__filename_to_path(filename))\n        return file_path.is_file()\n\n    def get(self, key: str, save: bool = True):\n        \"\"\"\n        Get a value from the cache, pending reads, or disk. If save is True, \n        the value will be saved to pending_reads.\n        \"\"\" \n        # Parse the key to get the filename and group\n        value = self.find(key)\n        if save and self.pending_reads.get(key) is None:\n            self.pending_reads[key] = value\n        # if value is not None:\n        #     rt.deduct_read(*encode_kv(key, value))\n        return value\n\n\n    def set(self, key, value, is_txn_write=False):\n        rt.deduct_write(*encode_kv(key, value))\n        if self.pending_reads.get(key) is None:\n            self.get(key)\n        if type(value) in [decimal.Decimal, float]:\n            value = ContractingDecimal(str(value))\n        self.pending_writes[key] = value\n        if is_txn_write:\n            self.transaction_writes[key] = value\n\n\n    def find(self, key: str):\n        \"\"\"\n        Find the value for a given key. If not found in cache or pending writes, \n        it will look it up from the disk.\n        \"\"\"\n        if self.bypass_cache:\n            # Parse the key to get the filename and group\n            filename, variable = self.__parse_key(key)\n            value = hdf5.get_value_from_disk(self.__filename_to_path(filename), variable)\n            return value\n\n        value = self.pending_writes.get(key)\n        if value is None:\n            value = self.cache.get(key)\n        if value is None:\n            # Parse the key to get the filename and group for disk lookup\n            filename, variable = self.__parse_key(key)\n            value = hdf5.get_value_from_disk(self.__filename_to_path(filename), variable)\n        return value\n\n\n    def __get_keys_from_file(self, filename):\n        return hdf5.get_groups(self.__filename_to_path(filename))\n\n    def keys_from_disk(self, prefix=None, length=0):\n        \"\"\"\n        Get all keys from disk with a given prefix\n        \"\"\"\n        keys = set()\n        try:\n            for filename in self.__get_files():\n                for key in self.__get_keys_from_file(filename):\n                    if prefix and key.startswith(prefix):\n                        keys.add(key)\n                    elif not prefix:\n                        keys.add(key)\n\n                    if 0 < length <= len(keys):\n                        raise AssertionError(\"Length threshold has been hit. Continuing.\")\n        except AssertionError:\n            pass\n\n        keys = list(keys)\n        keys.sort()\n        return keys\n\n    def iter_from_disk(self, prefix=\"\", length=0):\n        try:\n            filename, _ = self.__parse_key(prefix)\n        except Exception:\n            return self.keys(prefix=prefix)\n\n        if not self.is_file(filename=filename):\n            return []\n\n        keys_from_file = self.__get_keys_from_file(filename)\n\n        keys = [key for key in keys_from_file if key.startswith(prefix)]\n        keys.sort()\n\n        return keys if length == 0 else keys[:length]\n\n    def value_from_disk(self, key):\n        \"\"\"\n        Retrieve a value from the disk based on the parsed key.\n        \"\"\"\n        # Parse the key to get the filename and group\n        filename, variable = self.__parse_key(key)\n        return hdf5.get_value_from_disk(self.__filename_to_path(filename), variable)\n\n    def items(self, prefix=\"\"):\n        \"\"\"\n        Get all existing items with a given prefix.\n        \"\"\"\n        _items = {}\n        keys = set()\n\n        # Collect pending writes with matching prefix\n        for k, v in self.pending_writes.items():\n            if k.startswith(prefix):\n                # Always mark the key as seen to suppress disk rehydration\n                keys.add(k)\n                if v is not None:\n                    _items[k] = v\n\n        # Collect cache items with matching prefix\n        for k, v in self.cache.items():\n            if k.startswith(prefix):\n                keys.add(k)\n                if v is not None:\n                    _items[k] = v\n\n        # Collect keys from the disk\n        db_keys = set(self.iter_from_disk(prefix=prefix))\n\n        # Subtract already collected keys and add missing ones from disk\n        for k in db_keys - keys:\n            _items[k] = self.get(k)  # Cache get will add the keys to the cache\n\n        return _items\n\n\n    def keys(self, prefix=\"\"):\n        return list(self.items(prefix).keys())\n\n    def values(self, prefix=\"\"):\n        return list(self.items(prefix).values())\n\n    def make_key(self, contract, variable, args=[]):\n        contract_variable = DELIMITER.join((contract, variable))\n        if args:\n            return HASH_DEPTH_DELIMITER.join((contract_variable, *[str(arg) for arg in args]))\n        return contract_variable\n\n    def set_var(self, contract, variable, arguments=[], value=None, mark=True):\n        \"\"\"\n        Set a variable in a contract.\n        \"\"\"\n        # Construct the key and set the value\n        key = self.make_key(contract, variable, arguments)\n        self.set(key, value)\n\n    def get_var(self, contract, variable, arguments=[], mark=True):\n        \"\"\"\n        Get a variable from a contract.\n        \"\"\"\n        # Construct the key and get the value\n        key = self.make_key(contract, variable, arguments)\n        return self.get(key)\n\n    def get_owner(self, name):\n        owner = self.get_var(name, OWNER_KEY)\n        if owner == \"\":\n            owner = None\n        return owner\n\n    def get_time_submitted(self, name):\n        return self.get_var(name, TIME_KEY)\n\n    def get_compiled(self, name):\n        return self.get_var(name, COMPILED_KEY)\n\n    def get_contract(self, name):\n        return self.get_var(name, CODE_KEY)\n\n    def set_contract(\n        self,\n        name,\n        code,\n        owner=None,\n        overwrite=False,\n        timestamp=Datetime._from_datetime(datetime.now()),\n        developer=None,\n    ):\n        if self.get_contract(name) is None:\n            code_obj = compile(code, \"\", \"exec\")\n            code_blob = marshal.dumps(code_obj)\n\n            self.set_var(name, CODE_KEY, value=code)\n            self.set_var(name, COMPILED_KEY, value=code_blob)\n            self.set_var(name, OWNER_KEY, value=owner)\n            self.set_var(name, TIME_KEY, value=timestamp)\n            self.set_var(name, DEVELOPER_KEY, value=developer)\n\n    def delete_contract(self, name):\n        \"\"\"\n        Fully delete a contract from the caches and disk\n        \"\"\"\n        for key in self.keys(name):\n            if self.cache.get(key) is not None:\n                del self.cache[key]\n\n            if self.pending_writes.get(key) is not None:\n                del self.pending_writes[key]\n\n            self.delete_key_from_disk(key)\n\n    def get_contract_files(self):\n        \"\"\"\n        Get all contract files as a list of strings\n        \"\"\"\n        return sorted(os.listdir(self.contract_state))\n\n    def delete_key_from_disk(self, key):\n        \"\"\"\n        Delete a key from the disk by parsing the filename and group from the key.\n        \"\"\"\n        # Parse the key to get the filename and group\n        filename, variable = self.__parse_key(key)\n        if len(filename) < constants.FILENAME_LEN_MAX:\n            hdf5.delete_key_from_disk(self.__filename_to_path(filename), variable)\n\n    def flush_cache(self):\n        self.pending_writes.clear()\n        self.pending_reads.clear()\n        self.pending_deltas.clear()\n        self.transaction_writes.clear()\n        self.log_events.clear()\n        self.cache.clear()\n\n    def flush_disk(self):\n        shutil.rmtree(self.run_state, ignore_errors=True)\n        shutil.rmtree(self.contract_state, ignore_errors=True)\n        self.__build_directories()\n\n    def flush_file(self, filename):\n        file_path = self.__filename_to_path(filename)\n        if os.path.isfile(file_path):\n            os.unlink(file_path)\n            \n    def set_event(self, event):\n        self.log_events.append(event)\n\n    def flush_full(self):\n        \"\"\"\n        Flush all caches and disk storage.\n        \"\"\"\n        self.flush_disk()\n        self.flush_cache()\n\n    def delete(self, key):\n        \"\"\"\n        Delete a key fully from the caches and queue it for deletion from disk on commit.\n        \"\"\"\n        self.set(key, None)  # Setting the value to None will mark it for deletion\n\n    def rollback(self, nanos=None):\n        \"\"\"\n        Rollback to a given Nanoseconds in L2 cache or if no Nanoseconds is given, rollback to the latest state on disk.\n        \"\"\"\n        if nanos is None:\n            # Resets to the latest state on disk\n            self.cache.clear()\n            self.pending_reads.clear()\n            self.pending_writes.clear()\n            self.pending_deltas.clear()\n        else:\n            to_delete = []\n            for _nanos, _deltas in sorted(self.pending_deltas.items(), reverse=True):\n                if _nanos < nanos:\n                    break\n                to_delete.append(_nanos)\n                for key, delta in _deltas['writes'].items():\n                    self.cache[key] = delta[0]  # Restoring the value before the write\n\n            for _nanos in to_delete:\n                self.pending_deltas.pop(_nanos, None)\n\n    def commit(self):\n        \"\"\"\n        Save the current state to disk and clear the L1 and L2 caches.\n        \"\"\"\n        for k, v in self.pending_writes.items():\n            # Parse the key before applying to HDF5\n            filename, variable = self.__parse_key(k)\n            if v is None:\n                hdf5.delete_key_from_disk(self.__filename_to_path(filename), variable)\n            else:\n                hdf5.set_value_to_disk(self.__filename_to_path(filename), variable, v, None)\n\n        self.cache.clear()\n        self.pending_writes.clear()\n        self.pending_reads.clear()\n\n\n    def hard_apply(self, nanos):\n        \"\"\"\n        Save the current state to disk and L1 cache and clear the L2 cache.\n        \"\"\"\n\n        deltas = {}\n        for k, v in self.pending_writes.items():\n            current = self.pending_reads.get(k)\n            deltas[k] = (current, v)\n\n            self.cache[k] = v\n\n        self.pending_deltas[nanos] = {\"writes\": deltas, \"reads\": self.pending_reads}\n\n        # Clear the top cache\n        self.pending_reads = {}\n        self.pending_writes.clear()\n\n        # Run through the sorted HCLs from oldest to newest applying each one\n        to_delete = []\n        for _nanos, _deltas in sorted(self.pending_deltas.items()):\n            # Run through all state changes, taking the second value, which is the post delta\n            for key, delta in _deltas[\"writes\"].items():\n                # Parse the key before applying to HDF5\n                filename, variable = self.__parse_key(key)\n                hdf5.set_value_to_disk(self.__filename_to_path(filename), variable, delta[1], nanos)\n\n            to_delete.append(_nanos)\n            if _nanos == nanos:\n                break\n\n        # Remove the deltas from the set\n        [self.pending_deltas.pop(key) for key in to_delete]\n\n\n    def get_all_contract_state(self):\n        \"\"\"\n        Queries the disk storage and returns a dictionary with all the state from the contract storage directory.\n        \"\"\"\n        all_contract_state = {}\n        for file_path in self.contract_state.iterdir():\n            filename = file_path.name\n            keys = hdf5.get_all_keys_from_file(self.__filename_to_path(filename))\n            for key in keys:\n                full_key = f\"{filename}{DELIMITER}{key}\"\n                value = self.get(full_key)\n                all_contract_state[full_key] = value\n\n        return all_contract_state\n    \n\n    def get_run_state(self):\n        \"\"\"\n        Retrieves the latest state information from the run state directory.\n        \"\"\"\n        run_state = {}\n        for file_path in self.run_state.iterdir():\n            filename = file_path.name\n            keys = self.__get_keys_from_file(self.__filename_to_path(filename))\n            for key in keys:\n                full_key = f\"{filename}{DELIMITER}{key}\"\n                value = hdf5.get_value_from_disk(self.__filename_to_path(filename), key)\n                run_state[full_key] = value\n\n        return run_state\n\n\n    def clear_transaction_writes(self):\n        \"\"\"\n        Clear the transaction-specific writes.\n        \"\"\"\n        self.transaction_writes.clear()\n\n    def clear_events(self):\n        self.log_events.clear()\n"
  },
  {
    "path": "src/contracting/storage/encoder.py",
    "content": "import json\nimport decimal\n\nfrom contracting.stdlib.bridge.time import Datetime, Timedelta\nfrom contracting.stdlib.bridge.decimal import ContractingDecimal, MAX_LOWER_PRECISION, fix_precision\nfrom contracting.constants import INDEX_SEPARATOR, DELIMITER\n\nMONGO_MIN_INT = -(2 ** 63)\nMONGO_MAX_INT = 2 ** 63 - 1\n\n##\n# ENCODER CLASS\n# Add to this to encode Python types for storage.\n# Right now, this is only for datetime types. They are passed into the system as ISO strings, cast into Datetime objs\n# and stored as dicts. Is there a better way? I don't know, maybe.\n##\n\n\ndef safe_repr(obj, max_len=1024):\n    try:\n        r = obj.__repr__()\n        rr = r.split(' at 0x')\n        if len(rr) > 1:\n            return rr[0] + '>'\n        return rr[0][:max_len]\n    except:\n        return None\n\n\nclass Encoder(json.JSONEncoder):\n    def default(self, o, *args):\n        if isinstance(o, Datetime) or o.__class__.__name__ == Datetime.__name__:\n            return {\n                '__time__': [o.year, o.month, o.day, o.hour, o.minute, o.second, o.microsecond]\n            }\n        elif isinstance(o, Timedelta) or o.__class__.__name__ == Timedelta.__name__:\n            return {\n                '__delta__': [o._timedelta.days, o._timedelta.seconds]\n            }\n        elif isinstance(o, bytes):\n            return {\n                '__bytes__': o.hex()\n            }\n        elif isinstance(o, decimal.Decimal) or o.__class__.__name__ == decimal.Decimal.__name__:\n            #return format(o, f'.{MAX_LOWER_PRECISION}f')\n            return {\n                '__fixed__': str(fix_precision(o))\n            }\n\n        elif isinstance(o, ContractingDecimal) or o.__class__.__name__ == ContractingDecimal.__name__:\n            #return format(o._d, f'.{MAX_LOWER_PRECISION}f')\n            return {\n                '__fixed__': str(fix_precision(o._d))\n            }\n        #else:\n        #    return safe_repr(o)\n        return super().default(o)\n\n\ndef encode_int(value: int):\n    if MONGO_MIN_INT < value < MONGO_MAX_INT:\n        return value\n\n    return {\n        '__big_int__': str(value)\n    }\n\n\ndef encode_ints_in_dict(data: dict):\n    d = dict()\n    for k, v in data.items():\n        if isinstance(v, int):\n            d[k] = encode_int(v)\n        elif isinstance(v, dict):\n            d[k] = encode_ints_in_dict(v)\n        elif isinstance(v, list):\n            d[k] = []\n            for i in v:\n                if isinstance(i, dict):\n                    d[k].append(encode_ints_in_dict(i))\n                elif isinstance(i, int):\n                    d[k].append(encode_int(i))\n                else:\n                    d[k].append(i)\n        else:\n            d[k] = v\n\n    return d\n\n\n# JSON library from Python 3 doesn't let you instantiate your custom Encoder. You have to pass it as an obj to json\ndef encode(data: str):\n    \"\"\" NOTE:\n    Normally encoding behavior is overriden in 'default' method inside\n    a class derived from json.JSONEncoder. Unfortunately this can be done only\n    for custom types.\n    \n    Due to MongoDB integer limitation (8 bytes), we need to preprocess 'big' integers.\n    \"\"\"\n    if isinstance(data, int):\n        data = encode_int(data)\n    elif isinstance(data, dict):\n        data = encode_ints_in_dict(data)\n\n    return json.dumps(data, cls=Encoder, separators=(',', ':'))\n\n\ndef as_object(d):\n    if '__time__' in d:\n        return Datetime(*d['__time__'])\n    elif '__delta__' in d:\n        return Timedelta(days=d['__delta__'][0], seconds=d['__delta__'][1])\n    elif '__bytes__' in d:\n        return bytes.fromhex(d['__bytes__'])\n    elif '__fixed__' in d:\n        return ContractingDecimal(d['__fixed__'])\n    elif '__big_int__' in d:\n        return int(d['__big_int__'])\n    return dict(d)\n\n\n# Decode has a hook for JSON objects, which are just Python dictionaries. You have to specify the logic in this hook.\n# This is not uniform, but this is how Python made it.\ndef decode(data):\n    if data is None:\n        return None\n\n    if isinstance(data, bytes):\n        data = data.decode()\n\n    try:\n        return json.loads(data, object_hook=as_object)\n    except json.decoder.JSONDecodeError as e:\n        return None\n\n\ndef make_key(contract, variable, args=[]):\n    contract_variable = INDEX_SEPARATOR.join((contract, variable))\n    if args:\n        return DELIMITER.join((contract_variable, *args))\n    return contract_variable\n\n\ndef encode_kv(key, value):\n    # if key is None:\n    #     key = ''\n    #\n    # if value is None:\n    #     value = ''\n\n    k = key.encode()\n    v = encode(value).encode()\n    return k, v\n\n\ndef decode_kv(key, value):\n    k = key.decode()\n    v = decode(value)\n    # if v == '':\n    #     v = None\n    return k, v\n\n\nTYPES = {'__fixed__', '__delta__', '__bytes__', '__time__', '__big_int__'}\n\n\ndef convert(k, v):\n    if k == '__fixed__':\n        return ContractingDecimal(v)\n    elif k == '__delta__':\n        return Timedelta(days=v[0], seconds=v[1])\n    elif k == '__bytes__':\n        return bytes.fromhex(v)\n    elif k == '__time__':\n        return Datetime(*v)\n    elif k == '__big_int__':\n        return int(v)\n    return v\n\n\ndef convert_dict(d):\n    if not isinstance(d, dict):\n        return d\n\n    d2 = dict()\n    for k, v in d.items():\n        if k in TYPES:\n            return convert(k, v)\n\n        elif isinstance(v, dict):\n            d2[k] = convert_dict(v)\n\n        elif isinstance(v, list):\n            d2[k] = []\n            for i in v:\n                d2[k].append(convert_dict(i))\n\n        else:\n            d2[k] = v\n\n    return d2\n"
  },
  {
    "path": "src/contracting/storage/hdf5.py",
    "content": "import h5py\n\nfrom threading import Lock\nfrom collections import defaultdict\nfrom contracting.storage.encoder import encode, decode\nfrom contracting import constants\n\n# A dictionary to maintain file-specific locks\nfile_locks = defaultdict(Lock)\n\n# Constants\nATTR_LEN_MAX = 64000\nATTR_VALUE = \"value\"\nATTR_BLOCK = \"block\"\n\n\ndef get_file_lock(file_path):\n    \"\"\"Retrieve a lock for a specific file path.\"\"\"\n    return file_locks[file_path]\n\n\ndef get_value(file_path, group_name):\n    return get_attr(file_path, group_name, ATTR_VALUE)\n\n\ndef get_block(file_path, group_name):\n    return get_attr(file_path, group_name, ATTR_BLOCK)\n\n\ndef get_attr(file_path, group_name, attr_name):\n    try:\n        with h5py.File(file_path, 'r') as f:\n            try:\n                value = f[group_name].attrs[attr_name]\n                return value.decode() if isinstance(value, bytes) else value\n            except KeyError:\n                return None\n    except OSError:\n        # File doesn't exist\n        return None\n\n\n\ndef get_groups(file_path):\n    try:\n        with h5py.File(file_path, 'r') as f:\n            return list(f.keys())\n    except OSError:\n        # File doesn't exist\n        return []\n\n\n\ndef set(file_path, group_name, value, blocknum, timeout=20):\n    \"\"\"\n    Set the value and blocknum attributes in the HDF5 file for the given group.\n    \"\"\"\n    # Acquire a file lock to prevent concurrent writes\n    lock = get_file_lock(file_path if isinstance(file_path, str) else file_path.filename)\n    if lock.acquire(timeout=timeout):\n        try:\n            with h5py.File(file_path, 'a') as f:\n\n                # Write value and blocknum to the group attributes\n                write_attr(f, group_name, ATTR_VALUE, value, timeout)\n                write_attr(f, group_name, ATTR_BLOCK, blocknum, timeout)\n        finally:\n            # Always release the lock after operation\n            lock.release()\n    else:\n        raise TimeoutError(\"Lock acquisition timed out\")\n\n\ndef write_attr(file_or_path, group_name, attr_name, value, timeout=20):\n    \"\"\"\n    Write an attribute to a group inside an HDF5 file.\n    \"\"\"\n\n    # Open the file and ensure group exists, then write the attribute\n    if isinstance(file_or_path, str):\n        with h5py.File(file_or_path, 'a') as f:\n            _write_attr_to_file(f, group_name, attr_name, value, timeout)\n    else:\n        _write_attr_to_file(file_or_path, group_name, attr_name, value, timeout)\n\n\ndef _write_attr_to_file(file, group_name, attr_name, value, timeout):\n    \"\"\"\n    Internal method to write the attribute to the group.\n    \"\"\"\n    # Ensure the group exists, or create it if necessary\n    grp = file.require_group(group_name)\n\n    # Write or update the attribute in the group\n    if attr_name in grp.attrs:\n        del grp.attrs[attr_name]\n    if value is not None:\n        grp.attrs[attr_name] = value\n\n\n\ndef delete(file_path, group_name, timeout=20):\n    lock = get_file_lock(file_path if isinstance(file_path, str) else file_path.filename)\n    if lock.acquire(timeout=timeout):\n        try:\n            with h5py.File(file_path, 'a') as f:\n                try:\n                    del f[group_name].attrs[ATTR_VALUE]\n                    del f[group_name].attrs[ATTR_BLOCK]\n                except KeyError:\n                    pass\n        finally:\n            lock.release()\n    else:\n        raise TimeoutError(\"Lock acquisition timed out\")\n\n\ndef set_value_to_disk(file_path, group_name, value, block_num=None, timeout=20):\n    \"\"\"\n    Save value to disk with optional block number.\n    \"\"\"\n    encoded_value = encode(value) if value is not None else None\n \n    set(file_path, group_name, encoded_value, block_num if block_num is not None else -1, timeout)\n\n\ndef delete_key_from_disk(file_path, group_name, timeout=20):\n    delete(file_path, group_name, timeout)\n\n\ndef get_value_from_disk(file_path, group_name):\n    return decode(get_value(file_path, group_name))\n\n\n        \ndef get_all_keys_from_file(file_path):\n    \"\"\"\n    Retrieve all keys (datasets and groups) from an HDF5 file and replace '/' with a specified character.\n    \n    :param file_path: Path to the HDF5 file.\n    :param replace_char: Character to replace '/' with in the keys.\n    :return: List of all keys in the HDF5 file with '/' replaced by replace_char.\n    \"\"\"\n    keys = []\n\n    def visit_func(name, node):\n        keys.append(name.replace(constants.HDF5_GROUP_SEPARATOR, constants.DELIMITER))\n\n    with h5py.File(file_path, 'r') as f:\n        f.visititems(visit_func)\n\n    return keys\n"
  },
  {
    "path": "src/contracting/storage/orm.py",
    "content": "from contracting.storage.driver import Driver\nfrom contracting.execution.runtime import rt\nfrom contracting import constants\nfrom contracting.stdlib.bridge.decimal import ContractingDecimal\nfrom contracting.storage.encoder import encode_kv\nfrom copy import deepcopy\n\ndriver = rt.env.get(\"__Driver\") or Driver()\n\n\nclass Datum:\n    def __init__(self, contract, name, driver: Driver):\n        self._driver = driver\n        self._key = self._driver.make_key(contract, name)\n\n\nclass Variable(Datum):\n    def __init__(self, contract, name, driver: Driver = driver, t=None, default_value=None):\n        self._type = None\n\n        if isinstance(t, type):\n            self._type = t\n\n        self._default_value = default_value\n\n        super().__init__(contract, name, driver=driver)\n\n    def set(self, value):\n        if self._type is not None and value is not None:\n            assert isinstance(value, self._type), (\n              f'Wrong type passed to variable! '\n              f'Expected {self._type}, got {type(value)}.'\n            )\n\n        self._driver.set(self._key, value, True)\n\n    def get(self):\n        value = self._driver.get(self._key)\n        if value is None:\n            dv = self._default_value\n            if isinstance(dv, (list, dict)):\n                return deepcopy(dv)\n            return dv\n        return value\n\nclass Hash(Datum):\n    def __init__(self, contract, name, driver: Driver = driver, default_value=None):\n        super().__init__(contract, name, driver=driver)\n        self._delimiter = constants.DELIMITER\n        self._default_value = default_value\n\n    def _set(self, key, value):\n        self._driver.set(f\"{self._key}{self._delimiter}{key}\", value, True)\n\n    def _get(self, item):\n        value = self._driver.get(f\"{self._key}{self._delimiter}{item}\")\n\n        # Add Python defaultdict behavior for easier smart contracting\n        if value is None:\n            value = self._default_value\n\n        if type(value) == float or type(value) == ContractingDecimal:\n            return ContractingDecimal(str(value))\n        # Return a defensive copy for mutable structures to prevent in-place\n        # mutations from affecting cached objects in the driver.\n        if isinstance(value, (list, dict)):\n            return deepcopy(value)\n        return value\n\n    def _validate_key(self, key):\n        if isinstance(key, tuple):\n            assert len(key) <= constants.MAX_HASH_DIMENSIONS, (\n                f\"Too many dimensions ({len(key)}) for hash. \"\n                f\"Max is {constants.MAX_HASH_DIMENSIONS}\"\n            )\n\n            new_key_str = \"\"\n            for k in key:\n                assert not isinstance(k, slice), \"Slices prohibited in hashes.\"\n\n                k = str(k)\n\n                assert constants.DELIMITER not in k, \"Illegal delimiter in key.\"\n                assert constants.INDEX_SEPARATOR not in k, \"Illegal separator in key.\"\n\n                new_key_str += f\"{k}{self._delimiter}\"\n\n            key = new_key_str[: -len(self._delimiter)]\n        else:\n            key = str(key)\n\n            assert constants.DELIMITER not in key, \"Illegal delimiter in key.\"\n            assert constants.INDEX_SEPARATOR not in key, \"Illegal separator in key.\"\n\n        assert (\n            len(key) <= constants.MAX_KEY_SIZE\n        ), f\"Key is too long ({len(key)}). Max is {constants.MAX_KEY_SIZE}.\"\n        return key\n\n    def _prefix_for_args(self, args):\n        multi = self._validate_key(args)\n        prefix = f\"{self._key}{self._delimiter}\"\n        if multi != \"\":\n            prefix += f\"{multi}{self._delimiter}\"\n\n        return prefix\n\n    def all(self, *args):\n        prefix = self._prefix_for_args(args)\n        return self._driver.values(prefix=prefix)\n\n    def _items(self, *args):\n        prefix = self._prefix_for_args(args)\n        return self._driver.items(prefix=prefix)\n\n    def clear(self, *args):\n        kvs = self._items(*args)\n\n        for k in kvs.keys():\n            self._driver.delete(k)\n\n    def __setitem__(self, key, value):\n        # handle multiple hashes differently\n        key = self._validate_key(key)\n        self._set(key, value)\n\n    def __getitem__(self, key):\n        key = self._validate_key(key)\n        return self._get(key)\n\n    def __contains__(self, key):\n        raise Exception('Cannot use \"in\" with a Hash.')\n\n\nclass ForeignVariable(Variable):\n    def __init__(\n        self, contract, name, foreign_contract, foreign_name, driver: Driver = driver\n    ):\n        super().__init__(contract, name, driver=driver)\n        self._key = self._driver.make_key(foreign_contract, foreign_name)\n\n    def set(self, value):\n        raise ReferenceError\n\n\nclass ForeignHash(Hash):\n    def __init__(\n        self, contract, name, foreign_contract, foreign_name, driver: Driver = driver\n    ):\n        super().__init__(contract, name, driver=driver)\n        self._key = self._driver.make_key(foreign_contract, foreign_name)\n\n    def _set(self, key, value):\n        raise ReferenceError\n\n    def __setitem__(self, key, value):\n        raise ReferenceError\n\n    def __getitem__(self, item):\n        return super().__getitem__(item)\n\n    def clear(self, *args):\n        raise Exception(\"Cannot write with a ForeignHash.\")\n\n\nclass LogEvent(Datum):\n    \"\"\"\n    TODO\n    - Break validation into smaller functions\n    - Add checks for use of illegal types and argument names (See Hash checks.)\n    \"\"\"\n\n    def __init__(self, contract, name, event, params, driver: Driver = driver):\n        self._driver = driver\n        self._params = params\n        self._event = event\n        self._signer = rt.context.signer\n\n        assert isinstance(params, dict), \"Args must be a dictionary.\"\n        assert len(params) > 0, \"Args must have at least one argument.\"\n        # Check for indexed arguments with a maximum of three\n        indexed_args_count = sum(1 for arg in params.values() if arg.get(\"idx\", False))\n        assert (\n            indexed_args_count <= 3\n        ), \"Args must have at most three indexed arguments.\"\n        for param in params.values():\n            if not isinstance(param[\"type\"], tuple):\n                param[\"type\"] = (param[\"type\"],)\n\n            assert all(\n                issubclass(t, (str, int, float, bool, ContractingDecimal))\n                for t in param[\"type\"]\n            ), \"Each type in args must be str, int, float, decimal or bool.\"\n\n\n    def write_event(self, event_data):\n        contract = rt.context.this\n        caller = rt.context.caller\n        assert len(event_data) == len(\n            self._params\n        ), \"Event Data must have the same number of arguments as specified in the event.\"\n\n        # Check for unexpected arguments\n        for arg in event_data:\n            assert (\n                arg in self._params\n            ), f\"Unexpected argument {arg} in the data dictionary.\"\n\n        # Check for missing and type-mismatched arguments\n        for arg in self._params:\n            assert (\n                arg in event_data\n            ), f\"Argument {arg} is missing from the data dictionary.\"\n\n            # Check the type of the argument\n            assert isinstance(event_data[arg], self._params[arg][\"type\"]), (\n                f\"Argument {arg} is the wrong type! \"\n                f\"Expected {self._params[arg]['type']}, got {type(event_data[arg])}.\"\n            )\n\n            # Check the size of the argument\n            value_size = len(str(event_data[arg]).encode(\"utf-8\"))\n            assert (\n                value_size <= 1024\n            ), f\"Argument {arg} is too large ({value_size} bytes). Max is 1024 bytes.\"\n        \n        event = {\n            \"contract\": contract,\n            \"event\": self._event,\n            \"signer\": self._signer,\n            \"caller\": caller,\n            \"data_indexed\": {\n                arg: event_data[arg]\n                for arg in self._params\n                if self._params[arg].get(\"idx\", False)\n            },\n            \"data\": {\n                arg: event_data[arg]\n                for arg in self._params\n                if not self._params[arg].get(\"idx\", False)\n            },\n        }\n\n\n        for arg, value in event[\"data_indexed\"].items():\n            assert isinstance(\n                value, self._params[arg][\"type\"]\n            ), f\"Indexed argument {arg} is the wrong type! Expected {self._params[arg]['type']}, got {type(value)}.\"\n            encoded = encode_kv(arg, value)\n            rt.deduct_write(*encoded)\n        for arg, value in event[\"data\"].items():\n            assert isinstance(\n                value, self._params[arg][\"type\"]\n            ), f\"Non-indexed argument {arg} is the wrong type! Expected {self._params[arg]['type']}, got {type(value)}.\"\n            encoded = encode_kv(arg, value)\n            rt.deduct_write(*encoded)\n\n        self._driver.set_event(event)\n\n\n    def __call__(self, data):\n        self.write_event(data)\n"
  },
  {
    "path": "tests/__init__.py",
    "content": ""
  },
  {
    "path": "tests/integration/__init__.py",
    "content": ""
  },
  {
    "path": "tests/integration/test_atomic_swap.py",
    "content": "from unittest import TestCase\nfrom contracting.storage.driver import Driver\nfrom contracting.execution.executor import Executor\nfrom contracting.stdlib.bridge.time import Datetime\nimport contracting\nimport os\ndef submission_kwargs_for_file(f):\n    # Get the file name only by splitting off directories\n    split = f.split('/')\n    split = split[-1]\n\n    # Now split off the .s\n    split = split.split('.')\n    contract_name = split[0]\n\n    with open(f) as file:\n        contract_code = file.read()\n\n    return {\n        'name': f\"con_{contract_name}\",\n        'code': contract_code,\n    }\n\n\nTEST_SUBMISSION_KWARGS = {\n    'sender': 'stu',\n    'contract_name': 'submission',\n    'function_name': 'submit_contract'\n}\n\n\nclass TestAtomicSwapContract(TestCase):\n    def setUp(self):\n        self.d = Driver()\n        self.d.flush_full()\n\n        with open(contracting.__path__[0] + '/contracts/submission.s.py') as f:\n            contract = f.read()\n\n        self.d.set_contract(name='submission',\n                            code=contract)\n        self.d.commit()\n\n        self.e = Executor(currency_contract='con_erc20_clone', metering=False)\n\n        environment = {'now': Datetime(2019, 1, 1)}\n\n        self.script_dir = os.path.dirname(os.path.abspath(__file__))\n\n        token_path = os.path.join(self.script_dir, \"test_contracts\", \"erc20_clone.s.py\")\n        atomic_swaps_path = os.path.join(self.script_dir, \"test_contracts\", \"atomic_swaps.s.py\")\n\n        self.e.execute(**TEST_SUBMISSION_KWARGS,\n                  kwargs=submission_kwargs_for_file(token_path), environment=environment)\n\n        self.e.execute(**TEST_SUBMISSION_KWARGS,\n                  kwargs=submission_kwargs_for_file(atomic_swaps_path))\n\n    def tearDown(self):\n        self.e.bypass_privates = False\n\n        self.d.flush_full()\n\n    def test_initiate_not_enough_approved(self):\n        self.e.execute('stu', 'con_erc20_clone', 'approve', kwargs={'amount': 1000000, 'to': 'con_atomic_swaps'})\n        output = self.e.execute('stu', 'con_atomic_swaps', 'initiate', kwargs={\n            'participant': 'raghu',\n            'expiration': Datetime(2020, 1, 1),\n            'hashlock': 'eaf48a02d3a4bb3aeb0ecb337f6efb026ee0bbc460652510cff929de78935514',\n            'amount': 5000000\n        })\n\n        self.assertEqual(output['status_code'], 1)\n        self.assertIn(\"You cannot initiate an atomic swap without allowing 'con_atomic_swaps' at least 5000000 coins. You have only allowed 1000000 coins\", str(output['result']))\n\n    def test_initiate_transfers_coins_correctly(self):\n        self.e.execute('stu', 'con_erc20_clone', 'approve', kwargs={'amount': 1000000, 'to': 'con_atomic_swaps'})\n        self.e.execute('stu', 'con_atomic_swaps', 'initiate', kwargs={\n            'participant': 'raghu',\n            'expiration': Datetime(2020, 1, 1),\n            'hashlock': 'eaf48a02d3a4bb3aeb0ecb337f6efb026ee0bbc460652510cff929de78935514',\n            'amount': 5\n        })\n\n        atomic_swaps = self.e.execute('stu', 'con_erc20_clone', 'balance_of', kwargs={'account':'con_atomic_swaps'})\n        stu = self.e.execute('stu', 'con_erc20_clone', 'balance_of', kwargs={'account': 'stu'})\n        stu_as = self.e.execute('stu', 'con_erc20_clone', 'allowance', kwargs={'owner': 'stu', 'spender': 'con_atomic_swaps'})\n\n        self.assertEqual(atomic_swaps['result'], 5)\n        self.assertEqual(stu['result'], 999995)\n        self.assertEqual(stu_as['result'], 999995)\n\n    def test_initiate_writes_to_correct_key_and_properly(self):\n        self.e.execute('stu', 'con_erc20_clone', 'approve', kwargs={'amount': 1000000, 'to': 'con_atomic_swaps'}, auto_commit=True)\n        self.e.execute('stu', 'con_atomic_swaps', 'initiate', kwargs={\n            'participant': 'raghu',\n            'expiration': Datetime(2020, 1, 1),\n            'hashlock': 'eaf48a02d3a4bb3aeb0ecb337f6efb026ee0bbc460652510cff929de78935514',\n            'amount': 5\n        }, auto_commit=True)\n\n        key = 'con_atomic_swaps.swaps:raghu:eaf48a02d3a4bb3aeb0ecb337f6efb026ee0bbc460652510cff929de78935514'\n\n        expiration, amount = self.d.get(key)\n        self.assertEqual(expiration, Datetime(2020, 1, 1))\n        self.assertEqual(amount, 5)\n\n    def test_redeem_on_wrong_secret_fails(self):\n        self.e.execute('stu', 'con_erc20_clone', 'approve', kwargs={'amount': 1000000, 'to': 'con_atomic_swaps'})\n        self.e.execute('stu', 'con_atomic_swaps', 'initiate', kwargs={\n            'participant': 'raghu',\n            'expiration': Datetime(2020, 1, 1),\n            'hashlock': 'eaf48a02d3a4bb3aeb0ecb337f6efb026ee0bbc460652510cff929de78935514',\n            'amount': 5\n        })\n\n        output = self.e.execute('raghu', 'con_atomic_swaps', 'redeem', kwargs={'secret': '00'})\n\n        self.assertEqual(output['status_code'], 1)\n        self.assertIn('Incorrect sender or secret passed.', str(output['result']))\n\n    def test_redeem_on_wrong_sender_fails(self):\n        self.e.execute('stu', 'con_erc20_clone', 'approve', kwargs={'amount': 1000000, 'to': 'con_atomic_swaps'})\n        self.e.execute('stu', 'con_atomic_swaps', 'initiate', kwargs={\n            'participant': 'raghu',\n            'expiration': Datetime(2020, 1, 1),\n            'hashlock': 'eaf48a02d3a4bb3aeb0ecb337f6efb026ee0bbc460652510cff929de78935514',\n            'amount': 5\n        })\n\n        output = self.e.execute('stu', 'con_atomic_swaps', 'redeem', kwargs={'secret': '842b65a7d48e3a3c3f0e9d37eaced0b2'})\n        # status_code, result, stamps_used\n        self.assertEqual(output['status_code'], 1)\n        self.assertIn('Incorrect sender or secret passed.', str(output['result']))\n\n    def test_past_expiration_fails(self):\n        self.e.execute('stu', 'con_erc20_clone', 'approve', kwargs={'amount': 1000000, 'to': 'con_atomic_swaps'})\n        self.e.execute('stu', 'con_atomic_swaps', 'initiate', kwargs={\n            'participant': 'raghu',\n            'expiration': Datetime(2020, 1, 1),\n            'hashlock': 'eaf48a02d3a4bb3aeb0ecb337f6efb026ee0bbc460652510cff929de78935514',\n            'amount': 5\n        })\n\n        environment = {'now': Datetime(2021, 1, 1)}\n\n        output = self.e.execute('raghu', 'con_atomic_swaps', 'redeem', kwargs={'secret': '842b65a7d48e3a3c3f0e9d37eaced0b2'},\n                              environment=environment)\n\n        self.assertEqual(output['status_code'], 1)\n        self.assertIn('Swap has expired.', str(output['result']))\n\n    def test_successful_redeem_transfers_coins_correctly(self):\n        self.e.execute('stu', 'con_erc20_clone', 'approve', kwargs={'amount': 1000000, 'to': 'con_atomic_swaps'})\n        self.e.execute('stu', 'con_atomic_swaps', 'initiate', kwargs={\n            'participant': 'raghu',\n            'expiration': Datetime(2020, 1, 1),\n            'hashlock': 'eaf48a02d3a4bb3aeb0ecb337f6efb026ee0bbc460652510cff929de78935514',\n            'amount': 5\n        })\n\n        environment = {'now': Datetime(2019, 1, 1)}\n\n        self.e.execute('raghu', 'con_atomic_swaps', 'redeem', kwargs={'secret': '842b65a7d48e3a3c3f0e9d37eaced0b2'},\n                       environment=environment)\n\n        atomic_swaps = self.e.execute('stu', 'con_erc20_clone', 'balance_of', kwargs={'account': 'con_atomic_swaps'})\n        raghu = self.e.execute('stu', 'con_erc20_clone', 'balance_of', kwargs={'account': 'raghu'})\n\n        self.assertEqual(raghu['result'], 5)\n        self.assertEqual(atomic_swaps['result'], 0)\n\n    def test_successful_redeem_deletes_entry(self):\n        self.e.execute('stu', 'con_erc20_clone', 'approve', kwargs={'amount': 1000000, 'to': 'con_atomic_swaps'})\n        self.e.execute('stu', 'con_atomic_swaps', 'initiate', kwargs={\n            'participant': 'raghu',\n            'expiration': Datetime(2020, 1, 1),\n            'hashlock': 'eaf48a02d3a4bb3aeb0ecb337f6efb026ee0bbc460652510cff929de78935514',\n            'amount': 5\n        })\n\n        environment = {'now': Datetime(2019, 1, 1)}\n\n        self.e.execute('raghu', 'con_atomic_swaps', 'redeem', kwargs={'secret': '842b65a7d48e3a3c3f0e9d37eaced0b2'},\n                       environment=environment)\n\n        key = 'atomic_swaps.swaps:raghu:eaf48a02d3a4bb3aeb0ecb337f6efb026ee0bbc460652510cff929de78935514'\n        v = self.d.get(key)\n\n        self.assertEqual(v, None)\n\n    def test_refund_works(self):\n        self.e.execute('stu', 'con_erc20_clone', 'approve', kwargs={'amount': 1000000, 'to': 'con_atomic_swaps'})\n        self.e.execute('stu', 'con_atomic_swaps', 'initiate', kwargs={\n            'participant': 'raghu',\n            'expiration': Datetime(2020, 1, 1),\n            'hashlock': 'eaf48a02d3a4bb3aeb0ecb337f6efb026ee0bbc460652510cff929de78935514',\n            'amount': 5\n        })\n\n        environment = {'now': Datetime(2021, 1, 1)}\n\n        self.e.execute('stu', 'con_atomic_swaps', 'refund', kwargs={'participant': 'raghu', 'secret': '842b65a7d48e3a3c3f0e9d37eaced0b2'},\n                       environment=environment)\n\n        atomic_swaps = self.e.execute('stu', 'con_erc20_clone', 'balance_of', kwargs={'account': 'con_atomic_swaps'})\n        stu = self.e.execute('stu', 'con_erc20_clone', 'balance_of', kwargs={'account': 'stu'})\n\n        self.assertEqual(stu['result'], 1000000)\n        self.assertEqual(atomic_swaps['result'], 0)\n\n    def test_refund_too_early_fails(self):\n        self.e.execute('stu', 'con_erc20_clone', 'approve', kwargs={'amount': 1000000, 'to': 'con_atomic_swaps'})\n        self.e.execute('stu', 'con_atomic_swaps', 'initiate', kwargs={\n            'participant': 'raghu',\n            'expiration': Datetime(2020, 1, 1),\n            'hashlock': 'eaf48a02d3a4bb3aeb0ecb337f6efb026ee0bbc460652510cff929de78935514',\n            'amount': 5\n        })\n\n        environment = {'now': Datetime(2019, 1, 1)}\n\n        res = self.e.execute('stu', 'con_atomic_swaps', 'refund',\n                       kwargs={'participant': 'raghu', 'secret': '842b65a7d48e3a3c3f0e9d37eaced0b2'},\n                       environment=environment)\n\n        self.assertIn('Swap has not expired.', str(res['result']))\n\n    def test_refund_participant_is_signer_fails(self):\n        self.e.execute('stu', 'con_erc20_clone', 'approve', kwargs={'amount': 1000000, 'to': 'con_atomic_swaps'})\n        self.e.execute('stu', 'con_atomic_swaps', 'initiate', kwargs={\n            'participant': 'raghu',\n            'expiration': Datetime(2020, 1, 1),\n            'hashlock': 'eaf48a02d3a4bb3aeb0ecb337f6efb026ee0bbc460652510cff929de78935514',\n            'amount': 5\n        })\n\n        environment = {'now': Datetime(2021, 1, 1)}\n\n        res = self.e.execute('raghu', 'con_atomic_swaps', 'refund',\n                       kwargs={'participant': 'raghu', 'secret': '842b65a7d48e3a3c3f0e9d37eaced0b2'},\n                       environment=environment)\n\n        self.assertIn('Caller and signer cannot issue a refund.', str(res['result']))\n\n    def test_refund_fails_with_wrong_secret(self):\n        self.e.execute('stu', 'con_erc20_clone', 'approve', kwargs={'amount': 1000000, 'to': 'con_atomic_swaps'})\n        self.e.execute('stu', 'con_atomic_swaps', 'initiate', kwargs={\n            'participant': 'raghu',\n            'expiration': Datetime(2020, 1, 1),\n            'hashlock': 'eaf48a02d3a4bb3aeb0ecb337f6efb026ee0bbc460652510cff929de78935514',\n            'amount': 5\n        })\n\n        environment = {'now': Datetime(2019, 1, 1)}\n\n        res = self.e.execute('stu', 'con_atomic_swaps', 'refund',\n                                kwargs={'participant': 'raghu', 'secret': '00'},\n                                environment=environment)\n\n        self.assertIn('No swap to refund found.', str(res['result']))\n\n    def test_refund_resets_swaps(self):\n        self.e.execute('stu', 'con_erc20_clone', 'approve', kwargs={'amount': 1000000, 'to': 'con_atomic_swaps'})\n        self.e.execute('stu', 'con_atomic_swaps', 'initiate', kwargs={\n            'participant': 'raghu',\n            'expiration': Datetime(2020, 1, 1),\n            'hashlock': 'eaf48a02d3a4bb3aeb0ecb337f6efb026ee0bbc460652510cff929de78935514',\n            'amount': 5\n        })\n\n        environment = {'now': Datetime(2021, 1, 1)}\n\n        self.e.execute('stu', 'con_atomic_swaps', 'refund',\n                       kwargs={'participant': 'raghu', 'secret': '842b65a7d48e3a3c3f0e9d37eaced0b2'},\n                       environment=environment)\n\n        key = 'atomic_swaps.swaps:raghu:eaf48a02d3a4bb3aeb0ecb337f6efb026ee0bbc460652510cff929de78935514'\n        v = self.d.get(key)\n\n        self.assertEqual(v, None)\n\n    def test_trying_to_call_private_function_fails(self):\n        with self.assertRaises(AssertionError):\n            self.e.execute('stu', 'con_atomic_swaps', '__test', kwargs={})\n\n        self.e.bypass_privates = True\n\n        self.e.execute('stu', 'con_atomic_swaps', '__test', kwargs={})\n"
  },
  {
    "path": "tests/integration/test_builtins_locked_off.py",
    "content": "from unittest import TestCase\nfrom contracting.client import ContractingClient\nimport os\n\nclass TestBuiltinsLockedOff(TestCase):\n    def setUp(self):\n        self.c = ContractingClient(signer='stu')\n\n    def tearDown(self):\n        self.c.raw_driver.flush_full()\n\n\n    def test_if_builtin_can_be_submitted(self):\n        builtin_path = os.path.join(os.path.dirname(__file__), \"test_contracts\", \"builtin_lib.s.py\")\n\n        with open(builtin_path) as f:\n            contract = f.read()\n\n        with self.assertRaises(Exception):\n            self.c.submit(contract, name='con_builtin')\n\n    def test_if_non_builtin_can_be_submitted(self):\n        pass\n\n\nclass TestMathBuiltinsLockedOff(TestCase):\n    def setUp(self):\n        self.c = ContractingClient(signer='stu')\n\n    def tearDown(self):\n        self.c.raw_driver.flush_full()\n\n    def test_if_builtin_can_be_submitted(self):\n        mathtime_path = os.path.join(os.path.dirname(__file__), \"test_contracts\", \"mathtime.s.py\")\n\n        with open(mathtime_path) as f:\n            contract = f.read()\n\n        with self.assertRaises(Exception):\n            self.c.submit(contract, name='con_mathtime')\n\n\nclass TestDatabaseLoaderLoadsFirst(TestCase):\n    def setUp(self):\n        self.c = ContractingClient(signer='stu')\n\n    def tearDown(self):\n        self.c.raw_driver.flush_full()\n\n    def test_if_builtin_can_be_submitted(self):\n        contracting_path = os.path.join(os.path.dirname(__file__), \"test_contracts\", \"contracting.s.py\")\n\n        with open(contracting_path) as f:\n            contract = f.read()\n            self.c.submit(contract, name='con_contracting')\n\n        import_test_path = os.path.join(os.path.dirname(__file__), \"test_contracts\", \"import_test.s.py\")\n\n        with open(import_test_path) as f:\n            contract = f.read()\n            with self.assertRaises(ImportError):\n                self.c.submit(contract, name='con_import_test')\n\n\nclass TestDynamicImport(TestCase):\n    def setUp(self):\n        self.c = ContractingClient(signer='stu')\n\n    def tearDown(self):\n        self.c.raw_driver.flush_full()\n\n    def test_if_builtin_can_be_submitted(self):\n        dynamic_import_path = os.path.join(os.path.dirname(__file__), \"test_contracts\", \"dynamic_import.s.py\")\n\n        with open(dynamic_import_path) as f:\n            contract = f.read()\n            self.c.submit(contract, name='con_dynamic_import')\n\n        dynamic_import = self.c.get_contract('con_dynamic_import')\n\n        with self.assertRaises(ImportError):\n            dynamic_import.import_thing(name='con_math')\n\n\nclass TestFloatIssue(TestCase):\n    def setUp(self):\n        self.c = ContractingClient(signer='stu')\n\n    def tearDown(self):\n        self.c.raw_driver.flush_full()\n\n    def test_if_builtin_can_be_submitted(self):\n        float_issue_path = os.path.join(os.path.dirname(__file__), \"test_contracts\", \"float_issue.s.py\")\n\n        with open(float_issue_path) as f:\n            contract = f.read()\n            self.c.submit(contract, name='con_float_issue')\n\n        float_issue = self.c.get_contract('con_float_issue')\n\n        float_issue.get(x=0.1, y=0.1)\n"
  },
  {
    "path": "tests/integration/test_complex_contracts.py",
    "content": "from unittest import TestCase\nfrom contracting.storage.driver import Driver\nfrom contracting.execution.executor import Executor\nfrom datetime import datetime\nfrom contracting.stdlib.env import gather\nfrom hashlib import sha256, sha3_256\nimport os\n\ndef submission_kwargs_for_file(f):\n    # Get the file name only by splitting off directories\n    split = f.split('/')\n    split = split[-1]\n\n    # Now split off the .s\n    split = split.split('.')\n    contract_name = split[0]\n\n    with open(f) as file:\n        contract_code = file.read()\n\n    return {\n        'name': f'con_{contract_name}',\n        'code': contract_code,\n    }\n\n\nTEST_SUBMISSION_KWARGS = {\n    'sender': 'stu',\n    'contract_name': 'submission',\n    'function_name': 'submit_contract'\n}\n\n\nclass TestComplexContracts(TestCase):\n    def setUp(self):\n        self.d = Driver()\n        self.d.flush_full()\n\n        submission_path = os.path.join(os.path.dirname(__file__), \"test_contracts\", \"submission.s.py\")\n        with open(submission_path) as f:\n            submission_contract = f.read()\n            self.d.set_contract(name='submission',\n                                code=submission_contract)\n            self.d.commit()\n\n\n    def tearDown(self):\n        self.d.flush_full()\n\n    def test_token_construction_works(self):\n        e = Executor(metering=False)\n\n        currency_path = os.path.join(os.path.dirname(__file__), \"test_contracts\", \"currency.s.py\")\n\n        e.execute(**TEST_SUBMISSION_KWARGS,\n                  kwargs=submission_kwargs_for_file(currency_path))\n\n        res = e.execute('stu', 'con_currency', 'balance', kwargs={'account': 'colin'})\n\n        self.assertEqual(res['result'], 100)\n\n        res = e.execute('stu', 'con_currency', 'balance', kwargs={'account': 'stu'})\n        self.assertEqual(res['result'], 1000000)\n\n        res = e.execute('stu', 'con_currency', 'balance', kwargs={'account': 'raghu'})\n        self.assertEqual(res['result'], None)\n\n    def test_token_transfer_works(self):\n        e = Executor(metering=False)\n\n        currency_path = os.path.join(os.path.dirname(__file__), \"test_contracts\", \"currency.s.py\")\n\n        e.execute(**TEST_SUBMISSION_KWARGS,\n                  kwargs=submission_kwargs_for_file(currency_path))\n\n        e.execute('stu', 'con_currency', 'transfer', kwargs={'amount': 1000, 'to': 'colin'})\n\n        stu_balance = e.execute('stu', 'con_currency', 'balance', kwargs={'account': 'stu'})\n        colin_balance = e.execute('stu', 'con_currency', 'balance', kwargs={'account': 'colin'})\n\n        self.assertEqual(stu_balance['result'], 1000000 - 1000)\n        self.assertEqual(colin_balance['result'], 100 + 1000)\n\n    def test_token_transfer_failure_not_enough_to_send(self):\n        e = Executor(metering=False)\n\n        currency_path = os.path.join(os.path.dirname(__file__), \"test_contracts\", \"currency.s.py\")  \n\n        e.execute(**TEST_SUBMISSION_KWARGS,\n                  kwargs=submission_kwargs_for_file(currency_path))\n\n        status = e.execute('stu', 'currency', 'transfer', kwargs={'amount': 1000001, 'to': 'colin'})\n\n        self.assertEqual(status['status_code'], 1)\n\n    def test_token_transfer_to_new_account(self):\n        e = Executor(metering=False)\n\n        currency_path = os.path.join(os.path.dirname(__file__), \"test_contracts\", \"currency.s.py\")\n\n        e.execute(**TEST_SUBMISSION_KWARGS,\n                  kwargs=submission_kwargs_for_file(currency_path))\n\n        e.execute('stu', 'con_currency', 'transfer', kwargs={'amount': 1000, 'to': 'raghu'})\n\n        raghu_balance = e.execute('stu', 'con_currency', 'balance', kwargs={'account': 'raghu'})\n\n        self.assertEqual(raghu_balance['result'], 1000)\n\n    def test_erc20_clone_construction_works(self):\n        e = Executor(metering=False)\n\n        erc20_clone_path = os.path.join(os.path.dirname(__file__), \"test_contracts\", \"erc20_clone.s.py\")\n\n        e.execute(**TEST_SUBMISSION_KWARGS,\n                  kwargs=submission_kwargs_for_file(erc20_clone_path))\n\n        stu = e.execute('stu', 'con_erc20_clone', 'balance_of', kwargs={'account': 'stu'})\n        colin = e.execute('stu', 'con_erc20_clone', 'balance_of', kwargs={'account': 'colin'})\n        supply = e.execute('stu', 'con_erc20_clone', 'total_supply', kwargs={})\n\n        self.assertEqual(stu['result'], 1000000)\n        self.assertEqual(colin['result'], 100)\n        self.assertEqual(supply['result'], 1000100)\n\n    def test_erc20_clone_transfer_works(self):\n        e = Executor(metering=False)\n\n        erc20_clone_path = os.path.join(os.path.dirname(__file__), \"test_contracts\", \"erc20_clone.s.py\")\n\n        e.execute(**TEST_SUBMISSION_KWARGS,\n                  kwargs=submission_kwargs_for_file(erc20_clone_path))\n\n        e.execute('stu', 'con_erc20_clone', 'transfer', kwargs={'amount': 1000000, 'to': 'raghu'})\n        raghu = e.execute('stu', 'con_erc20_clone', 'balance_of', kwargs={'account': 'raghu'})\n        stu = e.execute('stu', 'con_erc20_clone', 'balance_of', kwargs={'account': 'stu'})\n\n        self.assertEqual(raghu['result'], 1000000)\n        self.assertEqual(stu['result'], 0)\n\n    def test_erc20_clone_transfer_fails(self):\n        e = Executor(metering=False)\n\n        erc20_clone_path = os.path.join(os.path.dirname(__file__), \"test_contracts\", \"erc20_clone.s.py\")\n\n        e.execute(**TEST_SUBMISSION_KWARGS,\n                  kwargs=submission_kwargs_for_file(erc20_clone_path))\n\n        output = e.execute('stu', 'con_erc20_clone', 'transfer', kwargs={'amount': 10000000, 'to': 'raghu'})\n\n        self.assertEqual(output['status_code'], 1)\n        # breakpoint()    \n        self.assertEqual(str(output['result']), 'Not enough coins to send!')\n\n    def test_allowance_of_blank(self):\n        e = Executor(metering=False)\n\n        erc20_clone_path = os.path.join(os.path.dirname(__file__), \"test_contracts\", \"erc20_clone.s.py\")\n\n        e.execute(**TEST_SUBMISSION_KWARGS,\n                  kwargs=submission_kwargs_for_file(erc20_clone_path))\n\n        output = e.execute('stu', 'con_erc20_clone', 'allowance', kwargs={'owner': 'stu', 'spender': 'raghu'})\n        self.assertEqual(output['result'], 0)\n\n    def test_approve_works_and_allowance_shows(self):\n        e = Executor(metering=False)\n\n        erc20_clone_path = os.path.join(os.path.dirname(__file__), \"test_contracts\", \"erc20_clone.s.py\")\n\n        e.execute(**TEST_SUBMISSION_KWARGS,\n                  kwargs=submission_kwargs_for_file(erc20_clone_path))\n\n        e.execute('stu', 'con_erc20_clone', 'approve', kwargs={'amount': 1234, 'to': 'raghu'})\n\n        output = e.execute('stu', 'con_erc20_clone', 'allowance', kwargs={'owner': 'stu', 'spender': 'raghu'})\n        self.assertEqual(output['result'], 1234)\n\n    def test_approve_and_transfer_from(self):\n        e = Executor(metering=False)\n\n        erc20_clone_path = os.path.join(os.path.dirname(__file__), \"test_contracts\", \"erc20_clone.s.py\")\n\n        e.execute(**TEST_SUBMISSION_KWARGS,\n                  kwargs=submission_kwargs_for_file(erc20_clone_path))\n\n        e.execute('stu', 'con_erc20_clone', 'approve', kwargs={'amount': 1234, 'to': 'raghu'})\n        e.execute('raghu', 'con_erc20_clone', 'transfer_from', kwargs={'amount': 123, 'to': 'tejas', 'main_account': 'stu'})\n        raghu = e.execute('stu', 'con_erc20_clone', 'balance_of', kwargs={'account': 'raghu'})\n        stu = e.execute('stu', 'con_erc20_clone', 'balance_of', kwargs={'account': 'stu'})\n        tejas = e.execute('stu', 'con_erc20_clone', 'balance_of', kwargs={'account': 'tejas'})\n\n        self.assertEqual(raghu['result'], 0)\n        self.assertEqual(stu['result'], (1000000 - 123))\n        self.assertEqual(tejas['result'], 123)\n\n    def test_failure_after_data_writes_doesnt_commit(self):\n        e = Executor(metering=False)\n\n        leaky_path = os.path.join(os.path.dirname(__file__), \"test_contracts\", \"leaky.s.py\")\n\n        e.execute(**TEST_SUBMISSION_KWARGS,\n                  kwargs=submission_kwargs_for_file(leaky_path), auto_commit=True)\n\n        e.execute('colin', 'con_leaky', 'transfer', kwargs={'amount': 1234, 'to': 'raghu'}, auto_commit=True)\n\n        raghu = e.execute('stu', 'con_leaky', 'balance_of', kwargs={'account': 'raghu'}, auto_commit=True)\n        colin = e.execute('stu', 'con_leaky', 'balance_of', kwargs={'account': 'colin'}, auto_commit=True)\n\n        self.assertEqual(raghu['result'], 0)\n        self.assertEqual(colin['result'], 100)\n\n    def test_leaky_contract_commits_on_success(self):\n        e = Executor(metering=False)\n\n        leaky_path = os.path.join(os.path.dirname(__file__), \"test_contracts\", \"leaky.s.py\")\n\n        e.execute(**TEST_SUBMISSION_KWARGS,\n                  kwargs=submission_kwargs_for_file(leaky_path))\n\n        e.execute('colin', 'con_leaky', 'transfer', kwargs={'amount': 1, 'to': 'raghu'})\n\n        raghu = e.execute('stu', 'con_leaky', 'balance_of', kwargs={'account': 'raghu'})\n        colin = e.execute('stu', 'con_leaky', 'balance_of', kwargs={'account': 'colin'})\n\n        self.assertEqual(raghu['result'], 1)\n        self.assertEqual(colin['result'], 99)\n\n    def test_time_stdlib_works(self):\n        e = Executor(metering=False)\n        now = datetime.now()\n\n        environment = gather()\n        date = environment['datetime'].datetime(now.year, now.month, now.day)\n        environment.update({'now': date})\n\n        time_path = os.path.join(os.path.dirname(__file__), \"test_contracts\", \"time.s.py\")\n\n        res = e.execute(**TEST_SUBMISSION_KWARGS,\n                  kwargs=submission_kwargs_for_file(time_path),\n                  environment=environment)\n\n        gt = e.execute('colin', 'con_time', 'gt', kwargs={}, environment=environment)\n        self.assertTrue(gt['result'])\n\n        lt = e.execute('colin', 'con_time', 'lt', kwargs={}, environment=environment)\n        self.assertFalse(lt['result'])\n\n        eq = e.execute('colin', 'con_time', 'eq', kwargs={}, environment=environment)\n        self.assertFalse(eq['result'])\n\n    def test_bad_time_contract_not_submittable(self):\n        e = Executor(metering=False)\n        now = datetime.now()\n\n        environment = gather()\n        date = environment['datetime'].datetime(now.year, now.month, now.day)\n        environment.update({'now': date})\n\n        bad_time_path = os.path.join(os.path.dirname(__file__), \"test_contracts\", \"bad_time.s.py\")\n\n        output = e.execute(**TEST_SUBMISSION_KWARGS,\n                           kwargs=submission_kwargs_for_file(bad_time_path),\n                           environment=environment)\n\n        self.assertEqual(output['status_code'], 1)\n\n    def test_json_lists_work(self):\n        e = Executor(metering=False)\n\n        json_tests_path = os.path.join(os.path.dirname(__file__), \"test_contracts\", \"json_tests.s.py\")\n\n        e.execute(**TEST_SUBMISSION_KWARGS,\n                    kwargs=submission_kwargs_for_file(json_tests_path))\n\n        res = e.execute('colin', 'con_json_tests', 'get_some', kwargs={})\n\n        self.assertListEqual([1, 2, 3, 4], res['result'])\n\n    def test_time_storage_works(self):\n        e = Executor(metering=False)\n\n        environment = gather()\n\n        time_storage_path = os.path.join(os.path.dirname(__file__), \"test_contracts\", \"time_storage.s.py\")\n\n        e.execute(**TEST_SUBMISSION_KWARGS,\n                  kwargs=submission_kwargs_for_file(time_storage_path))\n\n        v = e.execute('colin', 'con_time_storage', 'get', kwargs={})\n\n        date = environment['datetime'].datetime(2019, 1, 1)\n\n        self.assertEqual(v['result'], date)\n\n    def test_hash_sha3_works(self):\n        e = Executor(metering=False)\n\n        hashing_works_path = os.path.join(os.path.dirname(__file__), \"test_contracts\", \"hashing_works.s.py\")\n\n        e.execute(**TEST_SUBMISSION_KWARGS,\n                  kwargs=submission_kwargs_for_file(hashing_works_path))\n\n        secret = 'c0d1cc254c2aca8716c6ef170630550d'\n        s3 = e.execute('colin', 'con_hashing_works', 't_sha3', kwargs={'s': secret})\n\n        h = sha3_256()\n        h.update(bytes.fromhex(secret))\n        self.assertEqual(h.hexdigest(), s3['result'])\n\n    def test_hash_sha256_works(self):\n        e = Executor(metering=False)\n\n        test_hashing_works_path = os.path.join(os.path.dirname(__file__), \"test_contracts\", \"hashing_works.s.py\")\n\n        e.execute(**TEST_SUBMISSION_KWARGS,\n                  kwargs=submission_kwargs_for_file(test_hashing_works_path))\n\n        secret = 'c0d1cc254c2aca8716c6ef170630550d'\n        s3 = e.execute('colin', 'con_hashing_works', 't_sha256', kwargs={'s': secret})\n\n        h = sha256()\n        h.update(bytes.fromhex(secret))\n        self.assertEqual(h.hexdigest(), s3['result'])"
  },
  {
    "path": "tests/integration/test_complex_object_setting.py",
    "content": "from contracting.client import ContractingClient\nfrom unittest import TestCase\nimport os\n\ndef contract():\n    storage = Hash()\n\n    @export\n    def create(x: int, y: int, color: str):\n        storage[x, y] = {\n            'color': color,\n            'owner': ctx.caller\n        }\n\n    @export\n    def update(x: int, y: int, color: str):\n        s = storage[x, y]\n\n        s['color'] = color\n\n        storage[x, y] = s\n\n\nclass TestComplexStorage(TestCase):\n    def setUp(self):\n        self.c = ContractingClient(signer='stu')\n        self.c.flush()\n\n        self.c.submit(contract, name=\"con_contract\")\n        self.contract = self.c.get_contract('con_contract')\n\n    def tearDown(self):\n        self.c.flush()\n\n    def test_storage(self):\n        self.contract.create(x=1, y=2, color='howdy')\n        self.assertEqual(self.contract.storage[1, 2]['color'], 'howdy')\n\n    def test_modify(self):\n        self.contract.create(x=1, y=2, color='howdy')\n        self.contract.update(x=1, y=2, color='yoyoyo')\n"
  },
  {
    "path": "tests/integration/test_constructor_args.py",
    "content": "from unittest import TestCase\nfrom contracting.stdlib.bridge.time import Datetime\nfrom contracting.client import ContractingClient\nimport os\n\nclass TestSenecaClientReplacesExecutor(TestCase):\n    def setUp(self):\n        self.c = ContractingClient(signer='stu')\n        self.c.raw_driver.flush_full()\n\n        submission_path = os.path.join(os.path.dirname(__file__), \"test_contracts\", \"submission.s.py\")\n\n        with open(submission_path) as f:\n            contract = f.read()\n\n        self.c.raw_driver.set_contract(name='submission', code=contract)\n\n        self.c.raw_driver.commit()\n\n        # submit erc20 clone\n        constructor_args_contract_path = os.path.join(os.path.dirname(__file__), \"test_contracts\", \"constructor_args_contract.s.py\")\n\n        with open(constructor_args_contract_path) as f:\n            self.code = f.read()\n\n    def test_custom_args_works(self):\n        self.c.submit(self.code, name='con_constructor_args_contract', constructor_args={'a': 123, 'b': 321})\n\n        contract = self.c.get_contract('con_constructor_args_contract')\n        a, b = contract.get()\n\n        self.assertEqual(a, 123)\n        self.assertEqual(b, 321)\n\n    def test_custom_args_overloading(self):\n        with self.assertRaises(TypeError):\n            self.c.submit(self.code, name='con_constructor_args_contract', constructor_args={'a': 123, 'x': 321})\n\n    def test_custom_args_not_enough_args(self):\n        with self.assertRaises(TypeError):\n            self.c.submit(self.code, name='con_constructor_args_contract', constructor_args={'a': 123})\n"
  },
  {
    "path": "tests/integration/test_contracts/__init__.py",
    "content": ""
  },
  {
    "path": "tests/integration/test_contracts/atomic_swaps.s.py",
    "content": "import con_erc20_clone\n\nswaps = Hash()\n\n@export\ndef initiate(participant: str, expiration: datetime.datetime, hashlock: str, amount: float):\n    allowance = con_erc20_clone.allowance(ctx.caller, ctx.this)\n\n    assert allowance >= amount, \\\n        \"You cannot initiate an atomic swap without allowing '{}' \" \\\n        \"at least {} coins. You have only allowed {} coins\".format(ctx.this, amount, allowance)\n\n    swaps[participant, hashlock] = [expiration, amount]\n\n    con_erc20_clone.transfer_from(amount, ctx.this, ctx.caller)\n\n@export\ndef redeem(secret: str):\n\n    hashlock = hashlib.sha256(secret)\n\n    result = swaps[ctx.caller, hashlock]\n\n    assert result is not None, 'Incorrect sender or secret passed.'\n\n    expiration, amount = result\n\n    assert expiration >= now, 'Swap has expired.'\n\n    con_erc20_clone.transfer(amount, ctx.caller)\n    swaps[ctx.caller, hashlock] = None # change this to respond to the del keyword?\n\n@export\ndef refund(participant: str, secret: str):\n\n    assert participant != ctx.caller and participant != ctx.signer, \\\n        'Caller and signer cannot issue a refund.'\n\n    hashlock = hashlib.sha256(secret)\n\n    result = swaps[participant, hashlock]\n\n    assert result is not None, 'No swap to refund found.'\n\n    expiration, amount = result\n\n    assert expiration < now, 'Swap has not expired.'\n\n    con_erc20_clone.transfer(amount, ctx.caller)\n    swaps[participant, hashlock] = None\n\n\n# Should fail if called\ndef test():\n    return 123"
  },
  {
    "path": "tests/integration/test_contracts/bad_time.s.py",
    "content": "old_time = time.datetime(2019, 1, 1)\n\n@export\ndef ha():\n    old_time._datetime = None\n    return old_time\n"
  },
  {
    "path": "tests/integration/test_contracts/bastardcoin.s.py",
    "content": "balances = Hash(default_value=0)\n\n@construct\ndef seed():\n    balances['stu'] = 999\n    balances['colin'] = 555\n\n@export\ndef transfer(amount: int, to: str):\n    sender = ctx.caller\n    assert balances[sender] >= amount, 'Not enough coins to send!'\n\n    balances[sender] -= amount\n    balances[to] += amount\n\n@export\ndef balance_of(account: str):\n    return balances[account]"
  },
  {
    "path": "tests/integration/test_contracts/builtin_lib.s.py",
    "content": "import token\n\n@export\ndef hahaha():\n    print('I work, fool!')\n\n@export\ndef return_token():\n    return vars(token)\n"
  },
  {
    "path": "tests/integration/test_contracts/child_test.s.py",
    "content": "@export\ndef get_value():\n    return 'good'"
  },
  {
    "path": "tests/integration/test_contracts/client.py",
    "content": ""
  },
  {
    "path": "tests/integration/test_contracts/con_pass_hash.s.py",
    "content": "import con_pass_hash\n\nmy_hash = Hash()\n\n@export\ndef store(k: Any, v: Any):\n    con_pass_hash.store_on_behalf(my_hash, k, v)\n\n@export\ndef get(k: Any):\n    return my_hash[k]\n"
  },
  {
    "path": "tests/integration/test_contracts/construct_function_works.s.py",
    "content": "v = Variable()\n\n@export\ndef get():\n    return v.get()\n\n@construct\ndef seed():\n    v.set(42)\n"
  },
  {
    "path": "tests/integration/test_contracts/constructor_args_contract.s.py",
    "content": "var1 = Variable()\nvar2 = Variable()\n\n@construct\ndef seed(a, b):\n    var1.set(a)\n    var2.set(b)\n    \n@export\ndef get():\n    a = var1.get()\n    b = var2.get()\n    return a, b"
  },
  {
    "path": "tests/integration/test_contracts/contracting.s.py",
    "content": "@export\ndef hello():\n    return 'hello'"
  },
  {
    "path": "tests/integration/test_contracts/currency.s.py",
    "content": "balances = Hash()\n\n@construct\ndef seed():\n    balances['stu'] = 1000000\n    balances['colin'] = 100\n\n@export\ndef transfer(amount: int, to: str):\n    sender = ctx.signer\n    assert balances[sender] >= amount, 'Not enough coins to send!'\n\n    balances[sender] -= amount\n\n    if balances[to] is None:\n        balances[to] = amount\n    else:\n        balances[to] += amount\n\n@export\ndef balance(account: str):\n    return balances[account]\n"
  },
  {
    "path": "tests/integration/test_contracts/dater.py",
    "content": "#import datetime\n\nv = Variable()\n\n@export\ndef replicate(d: datetime.datetime):\n    assert d > now, 'D IS NOT LARGER THAN NOW'\n    v.set(d)\n\n@export\ndef subtract(d1: datetime.datetime, d2: datetime.datetime):\n    return d1 - d2\n"
  },
  {
    "path": "tests/integration/test_contracts/dynamic_import.py",
    "content": "@export\ndef called_from_a_far():\n    m = importlib.import_module('con_all_in_one')\n    res = m.call_me_again_again()\n\n    return [res, {\n        'name': 'called_from_a_far',\n        'owner': ctx.owner,\n        'this': ctx.this,\n        'signer': ctx.signer,\n        'caller': ctx.caller,\n        'entry': ctx.entry,\n        'submission_name': ctx.submission_name\n    }]"
  },
  {
    "path": "tests/integration/test_contracts/dynamic_import.s.py",
    "content": "@export\ndef import_thing(name: str):\n    return importlib.import_module(name)"
  },
  {
    "path": "tests/integration/test_contracts/dynamic_importing.s.py",
    "content": "@export\ndef balance_for_token(tok: str, account: str):\n    t = importlib.import_module(tok)\n    return t.balance_of(account=account)\n\n@export\ndef only_erc20(tok: str, account: str):\n    t = importlib.import_module(tok)\n    assert enforce_erc20(t), 'You cannot use a non-ERC20 standard token!!'\n\n    return t.balance_of(account=account)\n\n@export\ndef is_erc20_compatible(tok: str):\n    interface = [\n        importlib.Func('transfer', args=('amount', 'to')),\n        importlib.Func('balance_of', args=('account',)),\n        importlib.Func('total_supply'),\n        importlib.Func('allowance', args=('owner', 'spender')),\n        importlib.Func('approve', args=('amount', 'to')),\n        importlib.Func('transfer_from', args=('amount', 'to', 'main_account')),\n        importlib.Var('supply', Variable),\n        importlib.Var('balances', Hash)\n    ]\n\n    t = importlib.import_module(tok)\n\n    return importlib.enforce_interface(t, interface)\n\ndef enforce_erc20(m):\n    interface = [\n        importlib.Func('transfer', args=('amount', 'to')),\n        importlib.Func('balance_of', args=('account',)),\n        importlib.Func('total_supply'),\n        importlib.Func('allowance', args=('owner', 'spender')),\n        importlib.Func('approve', args=('amount', 'to')),\n        importlib.Func('transfer_from', args=('amount', 'to', 'main_account')),\n        importlib.Var('supply', Variable),\n        importlib.Var('balances', Hash)\n    ]\n\n    return importlib.enforce_interface(m, interface)"
  },
  {
    "path": "tests/integration/test_contracts/erc20_clone.s.py",
    "content": "supply = Variable()\nbalances = Hash(default_value=0)\n\n@construct\ndef seed():\n    balances['stu'] = 1000000\n    balances['colin'] = 100\n    supply.set(balances['stu'] + balances['colin'])\n\n@export\ndef transfer(amount: int, to: str):\n    sender = ctx.caller\n    assert balances[sender] >= amount, 'Not enough coins to send!'\n\n    balances[sender] -= amount\n    balances[to] += amount\n\n@export\ndef balance_of(account: str):\n    return balances[account]\n\n@export\ndef total_supply():\n    return supply.get()\n\n@export\ndef allowance(owner: str, spender: str):\n    return balances[owner, spender]\n\n@export\ndef approve(amount: str, to: str):\n    sender = ctx.caller\n    balances[sender, to] += amount\n    return balances[sender, to]\n\n@export\ndef transfer_from(amount: int, to: str, main_account: str):\n    sender = ctx.caller\n\n    assert balances[main_account, sender] >= amount, 'Not enough coins approved to send! You have {} and are trying to spend {}'\\\n        .format(balances[main_account, sender], amount)\n    assert balances[main_account] >= amount, 'Not enough coins to send!'\n\n    balances[main_account, sender] -= amount\n    balances[main_account] -= amount\n\n    balances[to] += amount\n"
  },
  {
    "path": "tests/integration/test_contracts/exception.py",
    "content": "balances = Hash(default_value=0)\n\n@construct\ndef seed():\n    balances['stu'] = 999\n    balances['colin'] = 555\n\n@export\ndef transfer(amount: int, to: str):\n    sender = ctx.caller\n    assert balances[sender] >= amount, 'Not enough coins to send!'\n\n    balances[sender] -= amount\n    balances[to] += amount\n\n    raise Exception('This is an exception')\n\n@export\ndef balance_of(account: str):\n    return balances[account]"
  },
  {
    "path": "tests/integration/test_contracts/float_issue.s.py",
    "content": "random.seed()\ngradients = Hash()\n\ndef rand_vect():\n    theta = random.randint(0, 100) / 50 * 3.13\n    return {'x': 5.124 / theta, 'y': 7.124 / theta}\n\n\ndef dot_prod_grid(x, y, vx, vy):\n    d_vect = {'x': x - vx, 'y': y - vy}\n    key = str(vx) + ',' + str(vy)\n    if gradients[key]:\n        g_vect = gradients[key]\n    else:\n        g_vect = rand_vect()\n        gradients[key] = g_vect\n\n    return (d_vect['y']) * (g_vect['x']) + (d_vect['y']) * (g_vect['y'])\n\n\ndef smootherstep(x):\n    return (6.0 * x ** 5.0 - 15.0 * x ** 4.0 + 10.0 * x ** 3.0)\n\n\ndef interp(x, a, b):\n    return a + (b - a) * smootherstep(x)\n\n\n@export\ndef seed():\n    gradients['0'] = 1  # test\n\n@export\ndef get(x: float, y: float):\n    xf = int(x)\n    yf = int(y)\n    tl = dot_prod_grid(x, y, xf, yf)\n    tr = dot_prod_grid(x, y, xf + 1, yf)\n    bl = dot_prod_grid(x, y, xf, yf + 1)\n    br = dot_prod_grid(x, y, xf + 1, yf + 1)\n    xt = interp(x - xf, tl, tr)\n    xb = interp(x - xf, bl, br)\n    return interp(y - yf, xt, xb)"
  },
  {
    "path": "tests/integration/test_contracts/foreign_thing.s.py",
    "content": "thing_H = ForeignHash(foreign_contract='con_thing', foreign_name='H')\nthing_V = ForeignVariable(foreign_contract='con_thing', foreign_name='V')\n\n@export\ndef read_H_hello():\n    return thing_H['hello']\n\n@export\ndef read_H_something():\n    return thing_H['something']\n\n@export\ndef read_V():\n    return thing_V.get()\n\n@export\ndef set_H(k: str, v: Any):\n    thing_H[k] = v\n\n@export\ndef set_V(v: Any):\n    thing_V.set(v)"
  },
  {
    "path": "tests/integration/test_contracts/hashing_works.s.py",
    "content": "@export\ndef t_sha3(s: str):\n    return hashlib.sha3(s)\n\n@export\ndef t_sha256(s: str):\n    return hashlib.sha256(s)\n"
  },
  {
    "path": "tests/integration/test_contracts/i_use_env.s.py",
    "content": "@export\ndef env_var():\n    return this_is_a_passed_in_variable"
  },
  {
    "path": "tests/integration/test_contracts/import_test.s.py",
    "content": "import contracting\n\n@export\ndef woo():\n    importlib.import_module('contracting')\n    return contracting\n"
  },
  {
    "path": "tests/integration/test_contracts/import_this.s.py",
    "content": "@export\ndef howdy():\n    return 12345"
  },
  {
    "path": "tests/integration/test_contracts/importing_that.s.py",
    "content": "import con_import_this\n\n@export\ndef test():\n    a = con_import_this.howdy()\n    a -= 1000\n    return a"
  },
  {
    "path": "tests/integration/test_contracts/inf_loop.s.py",
    "content": "@construct\ndef seed():\n    i = 0\n    while True:\n        i += 1\n\n@export\ndef dummy():\n    return 0"
  },
  {
    "path": "tests/integration/test_contracts/json_tests.s.py",
    "content": "v = Variable()\n\n@construct\ndef seed():\n    v.set([1, 2, 3, 4, 5, 6, 7, 8])\n\n@export\ndef get_some():\n    return v.get()[0:4]\n"
  },
  {
    "path": "tests/integration/test_contracts/leaky.s.py",
    "content": "supply = Variable()\nbalances = Hash(default_value=0)\n\n@construct\ndef seed():\n    balances['stu'] = 1000000\n    balances['colin'] = 100\n    supply.set(balances['stu'] + balances['colin'])\n\n@export\ndef transfer(amount: int, to: str):\n    sender = ctx.signer\n\n    balances[sender] -= amount\n    balances[to] += amount\n\n    # putting the assert down here shouldn't matter to the execution and data environment\n    assert balances[sender] >= amount, 'Not enough coins to send!'\n\n@export\ndef balance_of(account: str):\n    return balances[account]"
  },
  {
    "path": "tests/integration/test_contracts/mathtime.s.py",
    "content": "import math\n\npi = Variable()\n\n@construct\ndef seed():\n    pi.set(math.pi)\n\n\n@export\ndef get_pi():\n    return pi.get()"
  },
  {
    "path": "tests/integration/test_contracts/modules/all_in_one.s.py",
    "content": "@export\ndef call_me():\n    return call_me_again()\n\n@export\ndef call_me_again():\n    return call_me_again_again()\n\n@export\ndef call_me_again_again():\n    return {\n        'owner': ctx.owner,\n        'this': ctx.this,\n        'signer': ctx.signer,\n        'caller': ctx.caller\n    }\n"
  },
  {
    "path": "tests/integration/test_contracts/modules/dynamic_import.s.py",
    "content": "@export\ndef called_from_a_far():\n    m = importlib.import_module('all_in_one')\n    return m.call_me_again_again()\n\n@export\ndef called_from_a_far_stacked():\n    m = importlib.import_module('all_in_one')\n    return m.call()"
  },
  {
    "path": "tests/integration/test_contracts/modules/module1.s.py",
    "content": "'''\nhow the modules import each other. this is to test ctx.caller etc\n\n   1\n |   |\n 2   3\n| | | |\n4 5 6 7\n  |\n  8\n\n'''\n\nimport module2\nimport module3\n\n\n@export\ndef get_context():\n    return {\n        'owner': ctx.owner,\n        'this': ctx.this,\n        'signer': ctx.signer,\n        'caller': ctx.caller\n    }\n"
  },
  {
    "path": "tests/integration/test_contracts/modules/module2.s.py",
    "content": "import module4\nimport module5\n\n@export\ndef get_context():\n    return {\n        'owner': ctx.owner,\n        'this': ctx.this,\n        'signer': ctx.signer,\n        'caller': ctx.caller\n    }\n"
  },
  {
    "path": "tests/integration/test_contracts/modules/module3.s.py",
    "content": "import module6\nimport module7\n\n@export\ndef get_context():\n    return {\n        'owner': ctx.owner,\n        'this': ctx.this,\n        'signer': ctx.signer,\n        'caller': ctx.caller\n    }\n"
  },
  {
    "path": "tests/integration/test_contracts/modules/module4.s.py",
    "content": "@export\ndef get_context():\n    return {\n        'owner': ctx.owner,\n        'this': ctx.this,\n        'signer': ctx.signer,\n        'caller': ctx.caller\n    }\n"
  },
  {
    "path": "tests/integration/test_contracts/modules/module5.s.py",
    "content": "import module8\n\n@export\ndef get_context():\n    return {\n        'owner': ctx.owner,\n        'this': ctx.this,\n        'signer': ctx.signer,\n        'caller': ctx.caller\n    }\n"
  },
  {
    "path": "tests/integration/test_contracts/modules/module6.s.py",
    "content": "@export\ndef get_context():\n    return {\n        'owner': ctx.owner,\n        'this': ctx.this,\n        'signer': ctx.signer,\n        'caller': ctx.caller\n    }\n"
  },
  {
    "path": "tests/integration/test_contracts/modules/module7.s.py",
    "content": "@export\ndef get_context():\n    return {\n        'owner': ctx.owner,\n        'this': ctx.this,\n        'signer': ctx.signer,\n        'caller': ctx.caller\n    }\n"
  },
  {
    "path": "tests/integration/test_contracts/modules/module8.s.py",
    "content": "@export\ndef get_context():\n    return {\n        'owner': ctx.owner,\n        'this': ctx.this,\n        'signer': ctx.signer,\n        'caller': ctx.caller\n    }\n"
  },
  {
    "path": "tests/integration/test_contracts/orm_foreign_hash_contract.s.py",
    "content": "fh = ForeignHash(foreign_contract='con_orm_hash_contract', foreign_name='h')\n\n@export\ndef set_fh(k: str, v: int):\n    fh[k] = v\n\n@export\ndef get_fh(k: str):\n    return fh[k]\n"
  },
  {
    "path": "tests/integration/test_contracts/orm_foreign_key_contract.s.py",
    "content": "fv = ForeignVariable(foreign_contract='con_orm_variable_contract', foreign_name='v')\n\n@export\ndef set_fv(i: int):\n    fv.set(i)\n\n@export\ndef get_fv():\n    return fv.get()\n"
  },
  {
    "path": "tests/integration/test_contracts/orm_hash_contract.s.py",
    "content": "h = Hash()\n\n@export\ndef set_h(k: str, v: int):\n    h[k] = v\n\n@export\ndef get_h(k: str):\n    return h[k]\n"
  },
  {
    "path": "tests/integration/test_contracts/orm_no_contract_access.s.py",
    "content": "c = __Contract()\n\n@export\ndef set_c():\n    code = '''\n@export\ndef a():\n    print('gottem')    \n'''\n    c.submit(name='baloney', code=code, author='sys')\n"
  },
  {
    "path": "tests/integration/test_contracts/orm_variable_contract.s.py",
    "content": "v = Variable()\n\n@export\ndef set_v(i: int):\n    v.set(i)\n\n@export\ndef get_v():\n    return v.get()\n"
  },
  {
    "path": "tests/integration/test_contracts/owner_stuff.s.py",
    "content": "@export\ndef get_owner(s: str):\n    m = importlib.import_module(s)\n    return importlib.owner_of(m)\n\n@export\ndef owner_of_this():\n    return ctx.owner\n"
  },
  {
    "path": "tests/integration/test_contracts/parent_test.s.py",
    "content": "@export\ndef get_val_from_child(s: str):\n    m = importlib.import_module(s)\n    return m.get_value()\n"
  },
  {
    "path": "tests/integration/test_contracts/pass_hash.s.py",
    "content": "@export\ndef store_on_behalf(H: Any, k: Any, v: Any):\n    H[k] = v\n"
  },
  {
    "path": "tests/integration/test_contracts/private_methods.s.py",
    "content": "test_hash = Hash()\n\n@export\ndef call_private():\n    return private()\n\ndef private():\n    return 'abc'\n\n@export\ndef set(k: str, v: int):\n    test_hash[k] = v\n\n@export\ndef set_multi(k: str, k2: str, k3: str, v: int):\n    test_hash[k, k2, k3] = v"
  },
  {
    "path": "tests/integration/test_contracts/stubucks.s.py",
    "content": "supply = Variable()\nbalances = Hash(default_value=0)\n\n@construct\ndef seed():\n    balances['stu'] = 123\n    balances['colin'] = 321\n    supply.set(balances['stu'] + balances['colin'])\n\n@export\ndef transfer(amount: int, to: str):\n    sender = ctx.caller\n    assert balances[sender] >= amount, 'Not enough coins to send!'\n\n    balances[sender] -= amount\n    balances[to] += amount\n\n@export\ndef balance_of(account: str):\n    return balances[account]\n\n@export\ndef total_supply():\n    return supply.get()\n\n@export\ndef allowance(owner: str, spender: str):\n    return balances[owner, spender]\n\n@export\ndef approve(amount: int, to: str):\n    sender = ctx.caller\n    balances[sender, to] += amount\n    return balances[sender, to]\n\n@export\ndef transfer_from(amount: int, to: str, main_account: str):\n    sender = ctx.caller\n\n    assert balances[main_account, sender] >= amount, 'Not enough coins approved to send! You have {} and are trying to spend {}'\\\n        .format(balances[main_account, sender], amount)\n    assert balances[main_account] >= amount, 'Not enough coins to send!'\n\n    balances[main_account, sender] -= amount\n    balances[main_account] -= amount\n\n    balances[to] += amount\n"
  },
  {
    "path": "tests/integration/test_contracts/submission.s.py",
    "content": "@__export('submission')\ndef submit_contract(name: str, code: str, owner: Any=None, constructor_args: dict={}):\n    if ctx.caller != 'sys':\n        assert name.startswith('con_'), 'Contract must start with con_!'\n\n    assert ctx.caller == ctx.signer, 'Contract cannot be called from another contract!'\n    assert len(name) <= 64, 'Contract name length exceeds 64 characters!'\n    assert name.islower(), 'Contract name must be lowercase!'\n\n    __Contract().submit(\n        name=name,\n        code=code,\n        owner=owner,\n        constructor_args=constructor_args,\n        developer=ctx.caller\n    )\n\n\n@__export('submission')\ndef change_developer(contract: str, new_developer: str):\n    d = __Contract()._driver.get_var(contract=contract, variable='__developer__')\n    assert ctx.caller == d, 'Sender is not current developer!'\n\n    __Contract()._driver.set_var(\n        contract=contract,\n        variable='__developer__',\n        value=new_developer\n    )\n"
  },
  {
    "path": "tests/integration/test_contracts/tejastokens.s.py",
    "content": "supply = Variable()\nbalances = Hash(default_value=0)\n\n@construct\ndef seed():\n    balances['stu'] = 321\n    balances['colin'] = 123\n    supply.set(balances['stu'] + balances['colin'])\n\n@export\ndef transfer(amount: int, to: str):\n    sender = ctx.caller\n    assert balances[sender] >= amount, 'Not enough coins to send!'\n\n    balances[sender] -= amount\n    balances[to] += amount\n\n@export\ndef balance_of(account: str):\n    return balances[account]\n\n@export\ndef total_supply():\n    return supply.get()\n\n@export\ndef allowance(owner: str, spender: str):\n    return balances[owner, spender]\n\n@export\ndef approve(amount: int, to: str):\n    sender = ctx.caller\n    balances[sender, to] += amount\n    return balances[sender, to]\n\n@export\ndef transfer_from(amount: int, to: str, main_account: str):\n    sender = ctx.caller\n\n    assert balances[main_account, sender] >= amount, 'Not enough coins approved to send! You have {} and are trying to spend {}'\\\n        .format(balances[main_account, sender], amount)\n    assert balances[main_account] >= amount, 'Not enough coins to send!'\n\n    balances[main_account, sender] -= amount\n    balances[main_account] -= amount\n\n    balances[to] += amount\n"
  },
  {
    "path": "tests/integration/test_contracts/thing.s.py",
    "content": "H = Hash()\nV = Variable()\n\n@construct\ndef seed():\n    H['hello'] = 'there'\n    H['something'] = 'else'\n    V.set('hi')\n\n@export\ndef nop():\n    pass\n"
  },
  {
    "path": "tests/integration/test_contracts/time.s.py",
    "content": "old_time = datetime.datetime(2019, 1, 1)\n\n@export\ndef gt():\n    return now > old_time\n\n@export\ndef lt():\n    return now < old_time\n\n@export\ndef eq():\n    return now == old_time\n"
  },
  {
    "path": "tests/integration/test_contracts/time_storage.s.py",
    "content": "time = Variable()\n\n@construct\ndef seed():\n    time.set(datetime.datetime(2019, 1, 1))\n\n@export\ndef get():\n    return time.get()\n"
  },
  {
    "path": "tests/integration/test_datetime_contracts.py",
    "content": "from unittest import TestCase\nfrom contracting.client import ContractingClient\nfrom contracting.stdlib.bridge.time import Datetime\nimport os\n\nclass TestSenecaClientReplacesExecutor(TestCase):\n    def setUp(self):\n        self.c = ContractingClient(signer='stu')\n        self.c.flush()\n\n        dater_path = os.path.join(os.path.dirname(__file__), \"test_contracts\", \"dater.py\")\n\n        with open(dater_path) as f:\n            self.c.submit(f=f.read(), name='con_dater')\n\n        self.dater = self.c.get_contract('con_dater')\n\n    def tearDown(self):\n        self.c.flush()\n\n    def test_datetime_passed_argument_and_now_are_correctly_compared(self):\n        self.dater.replicate(d=Datetime(year=3000, month=1, day=1))\n\n    def test_datetime_passed_argument_and_now_are_correctly_compared_json(self):\n        with self.assertRaises(TypeError):\n            self.dater.replicate(d={'__time__':[3000, 12, 15, 12, 12, 12, 0]})\n\n        with self.assertRaises(TypeError):\n            self.dater.replicate(d=[2025, 11, 15, 21, 47, 14, 0])\n\n    def test_datetime_subtracts(self):\n        self.dater.subtract(d1=Datetime(year=2000, month=1, day=1), d2=Datetime(year=2001, month=1, day=1))"
  },
  {
    "path": "tests/integration/test_dynamic_imports.py",
    "content": "from unittest import TestCase\nfrom contracting.stdlib.bridge.time import Datetime\nfrom contracting.client import ContractingClient\nimport os\n\nclass TestDynamicImports(TestCase):\n    def setUp(self):\n        self.c = ContractingClient(signer='stu')\n        self.c.raw_driver.flush_full()\n\n        submission_path = os.path.join(os.path.dirname(__file__), \"test_contracts\", \"submission.s.py\")\n\n        with open(submission_path) as f:\n            contract = f.read()\n\n        self.c.raw_driver.set_contract(name='submission', code=contract)\n\n        self.c.raw_driver.commit()\n\n        # submit erc20 clone\n        stubucks_path = os.path.join(os.path.dirname(__file__), \"test_contracts\", \"stubucks.s.py\")\n\n        with open(stubucks_path) as f:\n            code = f.read()\n            self.c.submit(code, name='con_stubucks')\n\n        tejastokens_path = os.path.join(os.path.dirname(__file__), \"test_contracts\", \"tejastokens.s.py\")\n\n        with open(tejastokens_path) as f:\n            code = f.read()\n            self.c.submit(code, name='con_tejastokens')\n\n        bastardcoin_path = os.path.join(os.path.dirname(__file__), \"test_contracts\", \"bastardcoin.s.py\")\n\n        with open(bastardcoin_path) as f:\n            code = f.read()\n            self.c.submit(code, name='con_bastardcoin')\n\n        dynamic_importing_path = os.path.join(os.path.dirname(__file__), \"test_contracts\", \"dynamic_importing.s.py\")\n\n        with open(dynamic_importing_path) as f:\n            code = f.read()\n            self.c.submit(code, name='con_dynamic_importing')\n\n        self.stubucks = self.c.get_contract('con_stubucks')\n        self.tejastokens = self.c.get_contract('con_tejastokens')\n        self.bastardcoin = self.c.get_contract('con_bastardcoin')\n        self.dynamic_importing = self.c.get_contract('con_dynamic_importing')\n\n    def tearDown(self):\n        self.c.raw_driver.flush_full()\n\n    def test_successful_submission(self):\n        self.assertEqual(self.stubucks.balance_of(account='stu'), 123)\n        self.assertEqual(self.stubucks.balance_of(account='colin'), 321)\n\n        self.assertEqual(self.tejastokens.balance_of(account='stu'), 321)\n        self.assertEqual(self.tejastokens.balance_of(account='colin'), 123)\n\n        self.assertEqual(self.bastardcoin.balance_of(account='stu'), 999)\n        self.assertEqual(self.bastardcoin.balance_of(account='colin'), 555)\n\n    def test_get_stubuck_balances(self):\n        stu = self.dynamic_importing.balance_for_token(tok='con_stubucks', account='stu')\n        colin = self.dynamic_importing.balance_for_token(tok='con_stubucks', account='colin')\n\n        self.assertEqual(stu, 123)\n        self.assertEqual(colin, 321)\n\n    def test_get_tejastokens_balances(self):\n        stu = self.dynamic_importing.balance_for_token(tok='con_tejastokens', account='stu')\n        colin = self.dynamic_importing.balance_for_token(tok='con_tejastokens', account='colin')\n\n        self.assertEqual(stu, 321)\n        self.assertEqual(colin, 123)\n\n    def test_get_bastardcoin_balances(self):\n        stu = self.dynamic_importing.balance_for_token(tok='con_bastardcoin', account='stu')\n        colin = self.dynamic_importing.balance_for_token(tok='con_bastardcoin', account='colin')\n\n        self.assertEqual(stu, 999)\n        self.assertEqual(colin, 555)\n\n    def test_is_erc20(self):\n        self.assertTrue(self.dynamic_importing.is_erc20_compatible(tok='con_stubucks'))\n        self.assertTrue(self.dynamic_importing.is_erc20_compatible(tok='con_tejastokens'))\n        self.assertFalse(self.dynamic_importing.is_erc20_compatible(tok='con_bastardcoin'))\n\n    def test_get_balances_erc20_enforced_stubucks(self):\n        stu = self.dynamic_importing.only_erc20(tok='con_stubucks', account='stu')\n        colin = self.dynamic_importing.only_erc20(tok='con_stubucks', account='colin')\n\n        self.assertEqual(stu, 123)\n        self.assertEqual(colin, 321)\n\n    def test_get_balances_erc20_enforced_tejastokens(self):\n        stu = self.dynamic_importing.only_erc20(tok='con_tejastokens', account='stu')\n        colin = self.dynamic_importing.only_erc20(tok='con_tejastokens', account='colin')\n\n        self.assertEqual(stu, 321)\n        self.assertEqual(colin, 123)\n\n    def test_erc20_enforced_fails_for_bastardcoin(self):\n        with self.assertRaises(AssertionError):\n            stu = self.dynamic_importing.only_erc20(tok='con_bastardcoin', account='stu')\n\n    def test_owner_of_returns_default(self):\n        owner_stuff_path = os.path.join(os.path.dirname(__file__), \"test_contracts\", \"owner_stuff.s.py\")\n\n        with open(owner_stuff_path) as f:\n            code = f.read()\n            self.c.submit(code, name='con_owner_stuff', owner='poo')\n\n        owner_stuff = self.c.get_contract('con_owner_stuff')\n\n        self.assertIsNone(owner_stuff.get_owner(s='con_stubucks', signer='poo'))\n        self.assertEqual(owner_stuff.get_owner(s='con_owner_stuff', signer='poo'), 'poo')\n\n    def test_ctx_owner_works(self):\n        owner_stuff_path = os.path.join(os.path.dirname(__file__), \"test_contracts\", \"owner_stuff.s.py\")\n\n        with open(owner_stuff_path) as f:\n            code = f.read()\n            self.c.submit(code, name='con_owner_stuff', owner='poot')\n\n        owner_stuff = self.c.get_contract('con_owner_stuff')\n\n        self.assertEqual(owner_stuff.owner_of_this(signer='poot'), 'poot')\n\n    def test_incorrect_owner_prevents_function_call(self):\n        owner_stuff_path = os.path.join(os.path.dirname(__file__), \"test_contracts\", \"owner_stuff.s.py\")\n\n        with open(owner_stuff_path) as f:\n            code = f.read()\n            self.c.submit(code, name='con_owner_stuff', owner='poot')\n\n        owner_stuff = self.c.get_contract('owner_stuff')\n        with self.assertRaises(Exception):\n            owner_stuff.owner_of_this()\n\n    def test_delegate_call_with_owner_works(self):\n        parent_test_path = os.path.join(os.path.dirname(__file__), \"test_contracts\", \"parent_test.s.py\")\n\n        with open(parent_test_path) as f:\n            code = f.read()\n            self.c.submit(code, name='con_parent_test')\n\n        child_test_path = os.path.join(os.path.dirname(__file__), \"test_contracts\", \"child_test.s.py\")\n\n        with open(child_test_path) as f:\n            code = f.read()\n            self.c.submit(code, name='con_child_test', owner='con_parent_test')\n\n        parent_test = self.c.get_contract('con_parent_test')\n\n        val = parent_test.get_val_from_child(s='con_child_test')\n\n        self.assertEqual(val, 'good')\n\n    def test_delegate_with_wrong_owner_does_not_work(self):\n        parent_test_path = os.path.join(os.path.dirname(__file__), \"test_contracts\", \"parent_test.s.py\")\n\n        with open(parent_test_path) as f:\n            code = f.read()\n            self.c.submit(code, name='con_parent_test')\n\n        child_test_path = os.path.join(os.path.dirname(__file__), \"test_contracts\", \"child_test.s.py\")\n\n        with open(child_test_path) as f:\n            code = f.read()\n            self.c.submit(code, name='con_child_test', owner='blorg')\n\n        parent_test = self.c.get_contract('parent_test')\n\n        with self.assertRaises(Exception) as e:\n            parent_test.get_val_from_child(s='child_test')\n"
  },
  {
    "path": "tests/integration/test_executor_submission_process.py",
    "content": "from unittest import TestCase\nfrom contracting.storage.driver import Driver\nfrom contracting.execution.executor import Executor\nfrom contracting.compilation.compiler import ContractingCompiler\nimport os\n\ndef submission_kwargs_for_file(f):\n    # Get the file name only by splitting off directories\n    split = f.split('/')\n    split = split[-1]\n\n    # Now split off the .s\n    split = split.split('.')\n    contract_name = split[0]\n\n    with open(f) as file:\n        contract_code = file.read()\n\n    return {\n        'name': f'con_{contract_name}',\n        'code': contract_code,\n    }\n\n\nTEST_SUBMISSION_KWARGS = {\n    'sender': 'stu',\n    'contract_name': 'submission',\n    'function_name': 'submit_contract'\n}\n\n\nclass TestExecutor(TestCase):\n    def setUp(self):\n        self.d = Driver()\n        self.d.flush_full()\n\n        submission_path = os.path.join(os.path.dirname(__file__), \"test_contracts\", \"submission.s.py\")\n\n        with open(submission_path) as f:\n            contract = f.read()\n\n        self.d.set_contract(name='submission',\n                            code=contract)\n        self.d.commit()\n\n        self.compiler = ContractingCompiler()\n\n    def tearDown(self):\n        self.d.flush_full()\n\n    def test_submission(self):\n        e = Executor(metering=False)\n\n        code = '''@export\ndef d():\n    a = 1\n    return 1            \n'''\n\n        kwargs = {\n            'name': 'con_stubucks',\n            'code': code\n        }\n\n        e.execute(**TEST_SUBMISSION_KWARGS, kwargs=kwargs, auto_commit=True)\n\n        self.compiler.module_name = 'con_stubucks'\n        new_code = self.compiler.parse_to_code(code)\n\n        self.assertEqual(self.d.get_contract('con_stubucks'), new_code)\n\n    def test_submission_then_function_call(self):\n        e = Executor(metering=False)\n\n        code = '''@export\ndef d():\n    return 1            \n'''\n\n        kwargs = {\n            'name': 'con_stubuckz',\n            'code': code\n        }\n\n        e.execute(**TEST_SUBMISSION_KWARGS, kwargs=kwargs)\n        output = e.execute(sender='stu', contract_name='con_stubuckz', function_name='d', kwargs={})\n\n        self.assertEqual(output['result'], 1)\n        self.assertEqual(output['status_code'], 0)\n\n    def test_kwarg_helper(self):\n        test_orm_variable_contract_path = os.path.join(os.path.dirname(__file__), \"test_contracts\", \"orm_variable_contract.s.py\")\n\n        k = submission_kwargs_for_file(test_orm_variable_contract_path)\n\n        code = '''v = Variable()\n\n@export\ndef set_v(i: int):\n    v.set(i)\n\n@export\ndef get_v():\n    return v.get()\n'''\n\n        self.assertEqual(k['name'], 'con_orm_variable_contract')\n        self.assertEqual(k['code'], code)\n\n    def test_orm_variable_sets_in_contract(self):\n        e = Executor(metering=False)\n\n        test_orm_variable_contract_path = os.path.join(os.path.dirname(__file__), \"test_contracts\", \"orm_variable_contract.s.py\")\n\n        e.execute(**TEST_SUBMISSION_KWARGS,\n                  kwargs=submission_kwargs_for_file(test_orm_variable_contract_path), auto_commit=True)\n\n        e.execute('stu', 'con_orm_variable_contract', 'set_v', kwargs={'i': 1000}, auto_commit=True)\n\n        i = self.d.get('con_orm_variable_contract.v')\n        self.assertEqual(i, 1000)\n\n    def test_orm_variable_gets_in_contract(self):\n        e = Executor(metering=False)\n\n        test_orm_variable_contract_path = os.path.join(os.path.dirname(__file__), \"test_contracts\", \"orm_variable_contract.s.py\")\n\n        e.execute(**TEST_SUBMISSION_KWARGS,\n                    kwargs=submission_kwargs_for_file(test_orm_variable_contract_path))\n\n        res = e.execute('stu', 'con_orm_variable_contract', 'get_v', kwargs={})\n\n        self.assertEqual(res['result'], None)\n\n    def test_orm_variable_gets_and_sets_in_contract(self):\n        e = Executor(metering=False)\n\n        test_orm_variable_contract_path = os.path.join(os.path.dirname(__file__), \"test_contracts\", \"orm_variable_contract.s.py\")\n\n        e.execute(**TEST_SUBMISSION_KWARGS,\n                  kwargs=submission_kwargs_for_file(test_orm_variable_contract_path))\n\n        e.execute('stu', 'con_orm_variable_contract', 'set_v', kwargs={'i': 1000})\n        res = e.execute('stu', 'con_orm_variable_contract', 'get_v', kwargs={})\n\n        self.assertEqual(res['result'], 1000)\n\n    def test_orm_hash_sets_in_contract(self):\n        e = Executor(metering=False)\n\n        test_orm_hash_contract_path = os.path.join(os.path.dirname(__file__), \"test_contracts\", \"orm_hash_contract.s.py\")\n\n        e.execute(**TEST_SUBMISSION_KWARGS,\n                  kwargs=submission_kwargs_for_file(test_orm_hash_contract_path), auto_commit=True)\n\n        e.execute('stu', 'con_orm_hash_contract', 'set_h', kwargs={'k': 'key1', 'v': 1234}, auto_commit=True)\n        e.execute('stu', 'con_orm_hash_contract', 'set_h', kwargs={'k': 'another_key', 'v': 9999}, auto_commit=True)\n\n        key1 = self.d.get('con_orm_hash_contract.h:key1')\n        another_key = self.d.get('con_orm_hash_contract.h:another_key')\n\n        self.assertEqual(key1, 1234)\n        self.assertEqual(another_key, 9999)\n\n    def test_orm_hash_gets_in_contract(self):\n        e = Executor(metering=False)\n\n        test_orm_hash_contract_path = os.path.join(os.path.dirname(__file__), \"test_contracts\", \"orm_hash_contract.s.py\")\n\n        e.execute(**TEST_SUBMISSION_KWARGS,\n                  kwargs=submission_kwargs_for_file(test_orm_hash_contract_path))\n\n        res = e.execute('stu', 'con_orm_hash_contract', 'get_h', kwargs={'k': 'test'})\n\n        self.assertEqual(res['result'], None)\n\n    def test_orm_hash_gets_and_sets_in_contract(self):\n        e = Executor(metering=False)\n\n        test_orm_hash_contract_path = os.path.join(os.path.dirname(__file__), \"test_contracts\", \"orm_hash_contract.s.py\")\n\n        e.execute(**TEST_SUBMISSION_KWARGS,\n                  kwargs=submission_kwargs_for_file(test_orm_hash_contract_path))\n\n        e.execute('stu', 'con_orm_hash_contract', 'set_h', kwargs={'k': 'key1', 'v': 1234})\n        e.execute('stu', 'con_orm_hash_contract', 'set_h', kwargs={'k': 'another_key', 'v': 9999})\n\n        key1 = e.execute('stu', 'con_orm_hash_contract', 'get_h', kwargs={'k': 'key1'})\n        another_key = e.execute('stu', 'con_orm_hash_contract', 'get_h', kwargs={'k': 'another_key'})\n\n        self.assertEqual(key1['result'], 1234)\n        self.assertEqual(another_key['result'], 9999)\n\n    def test_orm_foreign_variable_sets_in_contract_doesnt_work(self):\n        e = Executor(metering=False)\n\n        test_orm_variable_contract_path = os.path.join(os.path.dirname(__file__), \"test_contracts\", \"orm_variable_contract.s.py\")\n        test_orm_foreign_key_contract_path = os.path.join(os.path.dirname(__file__), \"test_contracts\", \"orm_foreign_key_contract.s.py\")\n\n        e.execute(**TEST_SUBMISSION_KWARGS,\n                  kwargs=submission_kwargs_for_file(test_orm_variable_contract_path))\n        e.execute(**TEST_SUBMISSION_KWARGS,\n                  kwargs=submission_kwargs_for_file(test_orm_foreign_key_contract_path))\n\n        e.execute('stu', 'con_orm_variable_contract', 'set_v', kwargs={'i': 1000})\n\n        # this should fail\n        status = e.execute('stu', 'con_orm_foreign_key_contract', 'set_fv', kwargs={'i': 999})\n\n        self.assertEqual(status['status_code'], 1)\n\n        i = e.execute('stu', 'con_orm_variable_contract', 'get_v', kwargs={})\n        self.assertEqual(i['result'], 1000)\n\n    def test_orm_foreign_variable_gets_in_contract(self):\n        e = Executor(metering=False)\n\n        test_orm_variable_contract_path = os.path.join(os.path.dirname(__file__), \"test_contracts\", \"orm_variable_contract.s.py\")\n        test_orm_foreign_key_contract_path = os.path.join(os.path.dirname(__file__), \"test_contracts\", \"orm_foreign_key_contract.s.py\")\n\n        e.execute(**TEST_SUBMISSION_KWARGS, \n                  kwargs=submission_kwargs_for_file(test_orm_variable_contract_path))\n        e.execute(**TEST_SUBMISSION_KWARGS,\n                  kwargs=submission_kwargs_for_file(test_orm_foreign_key_contract_path))\n\n        e.execute('stu', 'con_orm_variable_contract', 'set_v', kwargs={'i': 424242})\n        # this should fail\n        i = e.execute('stu', 'con_orm_foreign_key_contract', 'get_fv', kwargs={})\n\n        self.assertEqual(i['result'], 424242)\n\n    def test_orm_foreign_hash_sets_in_contract_doesnt_work(self):\n        e = Executor(metering=False)\n\n        test_orm_hash_contract_path = os.path.join(os.path.dirname(__file__), \"test_contracts\", \"orm_hash_contract.s.py\")\n        test_orm_foreign_hash_contract_path = os.path.join(os.path.dirname(__file__), \"test_contracts\", \"orm_foreign_hash_contract.s.py\")  \n\n        e.execute(**TEST_SUBMISSION_KWARGS,\n                  kwargs=submission_kwargs_for_file(test_orm_hash_contract_path), auto_commit=True)\n        e.execute(**TEST_SUBMISSION_KWARGS, \n                  kwargs=submission_kwargs_for_file(test_orm_foreign_hash_contract_path), auto_commit=True)\n\n        e.execute('stu', 'con_orm_hash_contract', 'set_h', kwargs={'k': 'key1', 'v': 1234}, auto_commit=True)\n        e.execute('stu', 'con_orm_hash_contract', 'set_h', kwargs={'k': 'another_key', 'v': 9999}, auto_commit=True)\n\n        status_1 = e.execute('stu', 'con_orm_foreign_hash_contract', 'set_fh', kwargs={'k': 'key1', 'v': 5555}, auto_commit=True)\n        status_2 = e.execute('stu', 'con_orm_foreign_hash_contract', 'set_fh', kwargs={'k': 'another_key', 'v': 1000}, auto_commit=True)\n\n        key1 = self.d.get('con_orm_hash_contract.h:key1')\n        another_key = self.d.get('con_orm_hash_contract.h:another_key')\n\n        self.assertEqual(key1, 1234)\n        self.assertEqual(another_key, 9999)\n        self.assertEqual(status_1['status_code'], 1)\n        self.assertEqual(status_2['status_code'], 1)\n\n    def test_orm_foreign_hash_gets_and_sets_in_contract(self):\n        e = Executor(metering=False)\n\n        test_orm_hash_contract_path = os.path.join(os.path.dirname(__file__), \"test_contracts\", \"orm_hash_contract.s.py\")\n        test_orm_foreign_hash_contract_path = os.path.join(os.path.dirname(__file__), \"test_contracts\", \"orm_foreign_hash_contract.s.py\")  \n\n        e.execute(**TEST_SUBMISSION_KWARGS,\n                  kwargs=submission_kwargs_for_file(test_orm_hash_contract_path))\n\n        e.execute(**TEST_SUBMISSION_KWARGS,\n                  kwargs=submission_kwargs_for_file(test_orm_foreign_hash_contract_path))\n\n        e.execute('stu', 'con_orm_hash_contract', 'set_h', kwargs={'k': 'key1', 'v': 1234})\n        e.execute('stu', 'con_orm_hash_contract', 'set_h', kwargs={'k': 'another_key', 'v': 9999})\n\n        key1 = e.execute('stu', 'con_orm_foreign_hash_contract', 'get_fh', kwargs={'k': 'key1'})\n        another_key = e.execute('stu', 'con_orm_foreign_hash_contract', 'get_fh', kwargs={'k': 'another_key'})\n\n        self.assertEqual(key1['result'], 1234)\n        self.assertEqual(another_key['result'], 9999)\n\n    def test_orm_contract_not_accessible(self):\n        e = Executor(metering=False)\n\n        test_orm_no_contract_access_path = os.path.join(os.path.dirname(__file__), \"test_contracts\", \"orm_no_contract_access.s.py\")\n\n        output = e.execute(**TEST_SUBMISSION_KWARGS,\n            kwargs=submission_kwargs_for_file(test_orm_no_contract_access_path))\n\n        self.assertEqual(str(output['result']) , '[\"Line 1 : S2- Illicit use of \\'_\\' before variable : __Contract\"]')\n\n    def test_construct_function_sets_properly(self):\n        e = Executor(metering=False)\n\n        test_construct_function_works_path = os.path.join(os.path.dirname(__file__), \"test_contracts\", \"construct_function_works.s.py\")\n\n        r = e.execute(**TEST_SUBMISSION_KWARGS,\n            kwargs=submission_kwargs_for_file(test_construct_function_works_path))\n\n        output = e.execute('stu', 'con_construct_function_works', 'get', kwargs={})\n\n        self.assertEqual(output['result'], 42)\n\n    def test_import_exported_function_works(self):\n        e = Executor(metering=False)\n\n        import_this_path = os.path.join(os.path.dirname(__file__), \"test_contracts\", \"import_this.s.py\")\n        importing_that_path = os.path.join(os.path.dirname(__file__), \"test_contracts\", \"importing_that.s.py\")\n\n        e.execute(**TEST_SUBMISSION_KWARGS,\n                  kwargs=submission_kwargs_for_file(import_this_path))\n\n        e.execute(**TEST_SUBMISSION_KWARGS,\n                  kwargs=submission_kwargs_for_file(importing_that_path))\n\n        output = e.execute('stu', 'con_importing_that', 'test', kwargs={})\n        self.assertEqual(output['result'], 12345 - 1000)\n\n    def test_arbitrary_environment_passing_works_via_executor(self):\n        e = Executor(metering=False)\n\n        i_use_env_path = os.path.join(os.path.dirname(__file__), \"test_contracts\", \"i_use_env.s.py\")\n\n        e.execute(**TEST_SUBMISSION_KWARGS,\n                  kwargs=submission_kwargs_for_file(i_use_env_path))\n\n        this_is_a_passed_in_variable = 555\n\n        env = {'this_is_a_passed_in_variable': this_is_a_passed_in_variable}\n\n        output = e.execute('stu', 'con_i_use_env', 'env_var', kwargs={}, environment=env)\n\n        self.assertEqual(output['result'], this_is_a_passed_in_variable)\n\n    def test_arbitrary_environment_passing_fails_if_not_passed_correctly(self):\n        e = Executor(metering=False)\n\n        i_use_env_path = os.path.join(os.path.dirname(__file__), \"test_contracts\", \"i_use_env.s.py\")\n\n        e.execute(**TEST_SUBMISSION_KWARGS,\n                  kwargs=submission_kwargs_for_file(i_use_env_path))\n\n        this_is_a_passed_in_variable = 555\n\n        env = {'this_is_another_passed_in_variable': this_is_a_passed_in_variable}\n\n        output = e.execute('stu', 'i_use_env', 'env_var', kwargs={}, environment=env)\n\n        self.assertEqual(output['status_code'], 1)\n"
  },
  {
    "path": "tests/integration/test_executor_transaction_writes.py",
    "content": "import importlib\nfrom unittest import TestCase\nfrom contracting.stdlib.bridge.time import Datetime\nfrom contracting.client import ContractingClient\nfrom contracting.storage.driver import Driver\nimport os\n\nclass TestTransactionWrites(TestCase):\n    def setUp(self):\n        self.c = ContractingClient()\n        self.c.flush()\n\n        currency_path = os.path.join(os.path.dirname(__file__), \"test_contracts\", \"currency.s.py\")\n\n        with open(currency_path) as f:\n            contract = f.read()\n\n        self.c.submit(contract, name=\"currency\")\n\n        self.c.executor.driver.commit()\n\n    def tearDown(self):\n        self.c.raw_driver.flush_full()\n\n    def test_transfers(self):\n        self.c.set_var(\n            contract=\"currency\", variable=\"balances\", arguments=[\"bill\"], value=200\n        )\n        res3 = self.c.executor.execute(\n            contract_name=\"currency\",\n            function_name=\"transfer\",\n            kwargs={\"to\": \"someone\", \"amount\": 100},\n            stamps=1000,\n            sender=\"bill\",\n        )\n        self.assertEquals(res3[\"writes\"], self.c.executor.driver.pending_writes)\n        res2 = self.c.executor.execute(\n            contract_name=\"currency\",\n            function_name=\"transfer\",\n            kwargs={\"to\": \"someone\", \"amount\": 100},\n            stamps=1000,\n            sender=\"bill\",\n        )\n        \n        self.assertEquals(res2[\"writes\"], self.c.executor.driver.pending_writes)\n        # This operation will raise an exception, so will not make any writes.\n        res3 = self.c.executor.execute(\n            contract_name=\"currency\",\n            function_name=\"transfer\",\n            kwargs={\"to\": \"someone\", \"amount\": 100},\n            stamps=1000,\n            sender=\"bill\",\n        )\n        self.assertEquals(res3[\"writes\"], {})\n\n\nif __name__ == \"__main__\":\n    import unittest\n\n    unittest.main()\n"
  },
  {
    "path": "tests/integration/test_memory_clean_up_after_execution.py",
    "content": "from unittest import TestCase\nfrom contracting.storage.driver import Driver\nfrom contracting.execution.executor import Executor\nimport os\n\nimport contracting\nimport psutil\nimport gc\n\n\ndef submission_kwargs_for_file(f):\n    # Get the file name only by splitting off directories\n    split = f.split('/')\n    split = split[-1]\n\n    # Now split off the .s\n    split = split.split('.')\n    contract_name = split[0]\n\n    with open(f) as file:\n        contract_code = file.read()\n\n    return {\n        'name': f'con_{contract_name}',\n        'code': contract_code,\n    }\n\n\nTEST_SUBMISSION_KWARGS = {\n    'sender': 'stu',\n    'contract_name': 'submission',\n    'function_name': 'submit_contract'\n}\n\n\nclass TestMetering(TestCase):\n    def setUp(self):\n        # Hard load the submission contract\n        self.d = Driver()\n        self.d.flush_full()\n\n        submission_path = os.path.join(os.path.dirname(__file__), \"test_contracts\", \"submission.s.py\")\n\n        with open(submission_path) as f:\n            contract = f.read()\n\n        self.d.set_contract(name='submission',\n                            code=contract)\n        self.d.commit()\n\n        currency_path = os.path.join(os.path.dirname(__file__), \"test_contracts\", \"currency.s.py\")\n        # Execute the currency contract with metering disabled\n        self.e = Executor(driver=self.d)\n        self.e.execute(**TEST_SUBMISSION_KWARGS,\n                       kwargs=submission_kwargs_for_file(currency_path), metering=False, auto_commit=True)\n\n    def tearDown(self):\n        self.d.flush_full()\n\n    # def test_memory_clean_up_after_execution(self):\n    #     process = psutil.Process(os.getpid())\n    #     before = process.memory_info().rss / 1024 / 1024\n    #     for i in range(500):\n    #         output = self.e.execute('stu', 'con_currency', 'transfer', kwargs={'amount': 100, 'to': 'colin'}, auto_commit=True,metering=True)\n    #     gc.collect()\n    #     after = process.memory_info().rss / 1024 / 1024\n    #     before_2 = process.memory_info().rss / 1024 / 1024\n    #     for i in range(500):\n    #         output = self.e.execute('stu', 'con_currency', 'transfer', kwargs={'amount': 100, 'to': 'colin'}, auto_commit=True,metering=False)\n    #     gc.collect()\n    #     after_2 = process.memory_info().rss / 1024 / 1024\n\n    #     print(f'RAM Difference with metering: {after - before} MB')\n    #     print(f'RAM Difference without metering: {after_2 - before_2} MB')\n\n        \n\nif __name__ == '__main__':\n    t = TestMetering()\n    t.setUp()\n    t.test_memory_clean_up_after_execution()\n    t.tearDown()\n   "
  },
  {
    "path": "tests/integration/test_misc_contracts.py",
    "content": "import importlib\nfrom unittest import TestCase\nfrom contracting.stdlib.bridge.time import Datetime\nfrom contracting.client import ContractingClient\nfrom contracting.storage.driver import Driver\nimport os\n\ndef too_many_writes():\n    v = Variable()\n\n    @export\n    def single():\n        v.set('a' * (128 * 1024 + 1))\n\n    @export\n    def multiple():\n        for i in range(32 * 1024 + 1):\n            v.set('a')\n\n    @export\n    def not_enough():\n        v.set('a' * (30 * 1024))\n\n    @export\n    def run():\n        a = \"\"\n        for i in range(1000000):\n            a += \"NAME\" * 10\n\n        return a\n\n    @export\n    def run2():\n        a = 0\n        b = \"\"\n        for i in range(1000000):\n            b = b + \"wow\" + \"baseName\" * a\n            a += 1\n        return b\n\n\ndef exploit():\n    @construct\n    def seed():\n        a = 0\n        b = \"\"\n        for i in range(10000000):\n            b = b + \"wow\" + \"baseName\" * a\n            a += 1\n        return b\n\n    @export\n    def b():\n        pass\n\n\nclass TestMiscContracts(TestCase):\n    def setUp(self):\n        self.c = ContractingClient(signer='stu')\n        self.c.raw_driver.flush_full()\n\n        submission_path = os.path.join(os.path.dirname(__file__), \"test_contracts\", \"submission.s.py\")\n\n        with open(submission_path) as f:\n            contract = f.read()\n\n        self.c.raw_driver.set_contract(name='submission', code=contract,)\n\n        self.c.raw_driver.commit()\n\n        submission = self.c.get_contract('submission')\n\n        self.c.submit(too_many_writes, name=\"con_too_many_writes\")\n\n        # submit erc20 clone\n        thing_path = os.path.join(os.path.dirname(__file__), \"test_contracts\", \"thing.s.py\")\n\n        with open(thing_path) as f:\n            code = f.read()\n            self.c.submit(code, name='con_thing')\n\n        foreign_thing_path = os.path.join(os.path.dirname(__file__), \"test_contracts\", \"foreign_thing.s.py\")\n\n        with open(foreign_thing_path) as f:\n            code = f.read()\n            self.c.submit(code, name='con_foreign_thing')\n\n        self.thing = self.c.get_contract('con_thing')\n        self.foreign_thing = self.c.get_contract('con_foreign_thing')\n\n    def tearDown(self):\n        self.c.raw_driver.flush_full()\n\n    def test_H_values_return(self):\n        output = self.foreign_thing.read_H_hello()\n        self.assertEqual(output, 'there')\n\n        output = self.foreign_thing.read_H_something()\n        self.assertEqual(output, 'else')\n\n    def test_cant_modify_H(self):\n        with self.assertRaises(ReferenceError):\n            self.foreign_thing.set_H(k='hello', v='not_there')\n\n    def test_cant_add_H(self):\n        with self.assertRaises(ReferenceError):\n            self.foreign_thing.set_H(k='asdf', v='123')\n\n    def test_cant_set_V(self):\n        with self.assertRaises(ReferenceError):\n            self.foreign_thing.set_V(v=123)\n\n    def test_V_returns(self):\n        output = self.foreign_thing.read_V()\n        self.assertEqual(output, 'hi')\n\n    def test_single_too_many_writes_fails(self):\n        tmwc = self.c.get_contract('con_too_many_writes')\n        self.c.executor.metering = True\n        self.c.set_var(contract='currency', variable='balances', arguments=['stu'], value=1000000)\n        self.assertEqual(self.c.executor.execute(contract_name=\"con_too_many_writes\", function_name=\"single\", kwargs={}, stamps=1000, sender='stu')[\"status_code\"], 1)\n        self.c.executor.metering = False\n\n    def test_multiple_too_many_writes_fails(self):\n        tmwc = self.c.get_contract('con_too_many_writes')\n        self.c.executor.metering = True\n        self.c.set_var(contract='currency', variable='balances', arguments=['stu'], value=1000000)\n        # AssertEquals that the status code is 1 (failed tx)\n        self.assertEqual(self.c.executor.execute(contract_name=\"con_too_many_writes\", function_name=\"multiple\", kwargs={}, stamps=1000, sender='stu')[\"status_code\"], 1)\n        self.c.executor.metering = False\n\n    def test_failed_once_doesnt_affect_others(self):\n        tmwc = self.c.get_contract('con_too_many_writes')\n        self.c.executor.metering = True\n        self.c.set_var(contract='currency', variable='balances', arguments=['stu'], value=1000000)\n        # AssertEquals that the status code is 1 (failed tx)\n        self.assertEqual(self.c.executor.execute(contract_name=\"con_too_many_writes\", function_name=\"multiple\", kwargs={}, stamps=1000, sender='stu')[\"status_code\"], 1)\n        self.c.executor.execute(contract_name=\"con_too_many_writes\", function_name=\"not_enough\", kwargs={}, stamps=1000, sender='stu')\n        self.c.executor.metering = False\n\n    def test_memory_overload(self):\n        tmwc = self.c.get_contract('con_too_many_writes')\n        self.c.executor.metering = True\n        self.c.set_var(contract='currency', variable='balances', arguments=['stu'], value=1000000)\n        # AssertEquals that the status code is 1 (failed tx)\n        self.assertEqual(self.c.executor.execute(contract_name=\"con_too_many_writes\", function_name=\"run\", kwargs={}, stamps=1000, sender='stu')[\"status_code\"], 1)\n        self.c.executor.metering = False\n\n    def test_memory_overload2(self):\n        tmwc = self.c.get_contract('con_too_many_writes')\n        self.c.executor.metering = True\n        self.c.set_var(contract='currency', variable='balances', arguments=['stu'], value=1000000)\n        # AssertEquals that the status code is 1 (failed tx)\n        self.assertEqual(self.c.executor.execute(contract_name=\"con_too_many_writes\", function_name=\"run2\", kwargs={}, stamps=1000, sender='stu')[\"status_code\"], 1)\n        self.c.executor.metering = False\n\n    def test_memory_exploit(self):\n        self.c.executor.metering = True\n        self.c.set_var(contract='currency', variable='balances', arguments=['stu'], value=1000000)\n        # AssertEquals that the status code is 1 (failed tx)\n        self.assertEqual(self.c.executor.execute(contract_name='submission', function_name='submit_contract', kwargs={'name': 'exploit', 'code': exploit}, stamps=1000, sender='stu')[\"status_code\"], 1)\n        self.c.executor.metering = False\n\nclass TestPassHash(TestCase):\n    def setUp(self):\n        self.c = ContractingClient(signer='stu')\n        self.c.raw_driver.flush_full()\n\n        submission_path = os.path.join(os.path.dirname(__file__), \"test_contracts\", \"submission.s.py\")\n\n        with open(submission_path) as f:\n            contract = f.read()\n\n        self.c.raw_driver.set_contract(name='submission', code=contract,)\n\n        self.c.raw_driver.commit()\n\n        submission = self.c.get_contract('submission')\n\n        # submit erc20 clone\n        pass_hash_path = os.path.join(os.path.dirname(__file__), \"test_contracts\", \"pass_hash.s.py\")\n\n        with open(pass_hash_path) as f:\n            code = f.read()\n            self.c.submit(code, name='con_pass_hash')\n\n        test_pass_hash_path = os.path.join(os.path.dirname(__file__), \"test_contracts\", \"con_pass_hash.s.py\")\n\n        with open(test_pass_hash_path) as f:\n            code = f.read()\n            self.c.submit(code, name='con_test_pass_hash')\n\n        self.pass_hash = self.c.get_contract('con_pass_hash')\n        self.test_pass_hash = self.c.get_contract('con_test_pass_hash')\n\n    def test_store_value(self):\n        self.test_pass_hash.store(k='thing', v='value')\n        output = self.test_pass_hash.get(k='thing')\n\n        self.assertEqual(output, 'value')\n\n\ndef some_test_contract():\n    @export\n    def return_something():\n        return 1\n\n\ndef import_submission():\n    import submission\n\n    @export\n    def haha():\n        code = '''\n@export\ndef something():\n    pass\n'''\n        submission.submit_contract(name='something123', code=code)\n\n\nclass TestDeveloperSubmission(TestCase):\n    def setUp(self):\n        self.c = ContractingClient(signer='stu')\n        self.c.raw_driver.flush_full()\n\n        submission_path = os.path.join(os.path.dirname(__file__), \"test_contracts\", \"submission.s.py\")\n\n        with open(submission_path) as f:\n            contract = f.read()\n\n        self.c.raw_driver.set_contract(name='submission', code=contract,)\n\n        self.c.raw_driver.commit()\n\n    def test_submit_sets_developer(self):\n        self.c.submit(some_test_contract, name=\"con_some_test_contract\")\n\n        dev = self.c.get_var('con_some_test_contract', '__developer__')\n\n        self.assertEqual(dev, 'stu')\n\n    def test_change_developer_if_developer_works(self):\n        self.c.submit(some_test_contract, name=\"con_some_test_contract\")\n\n        submission = self.c.get_contract('submission')\n\n        submission.change_developer(contract='con_some_test_contract', new_developer='not_stu')\n\n        dev = self.c.get_var('con_some_test_contract', '__developer__')\n\n        self.assertEqual(dev, 'not_stu')\n\n    def test_change_developer_prevents_new_change(self):\n        self.c.submit(some_test_contract, name=\"con_some_test_contract\")\n\n        submission = self.c.get_contract('submission')\n\n        submission.change_developer(contract='con_some_test_contract', new_developer='not_stu')\n\n        with self.assertRaises(AssertionError):\n            submission.change_developer(contract='con_some_test_contract', new_developer='woohoo')\n\n    def test_cannot_import_submission(self):\n        self.c.submit(import_submission, name=\"con_import_submission\")\n\n        imp_con = self.c.get_contract('con_import_submission')\n\n        with self.assertRaises(AssertionError):\n            imp_con.haha()\n\n\ndef con_float_thing():\n    @export\n    def float_thing_fn(currency_reserve: float, token_reserve: float, currency_amount: float):\n        k = currency_reserve * token_reserve\n\n        new_currency_reserve = currency_reserve + currency_amount\n        new_token_reserve = k / new_currency_reserve\n\n        tokens_purchased = token_reserve - new_token_reserve\n        return tokens_purchased\n\n\nclass TestFloatThing(TestCase):\n    def setUp(self):\n        self.c = ContractingClient(signer='stu')\n        self.c.raw_driver.flush_full()\n\n        submission_path = os.path.join(os.path.dirname(__file__), \"test_contracts\", \"submission.s.py\")\n\n        with open(submission_path) as f:\n            contract = f.read()\n\n        self.c.raw_driver.set_contract(name='submission', code=contract,)\n\n        self.c.raw_driver.commit()\n\n    def test_can_add(self):\n        self.c.submit(con_float_thing, name=\"con_float_thing\")\n\n        ft_con = self.c.get_contract('con_float_thing')\n        ft_con.float_thing_fn(currency_reserve=50000.125, token_reserve=52.45, currency_amount=100.25)\n\ndef a():\n    @export\n    def x():\n        return 1\n\ndef module_hack():\n    v = Variable()\n\n    @export\n    def hack():\n        hack.__module__\n        return 1\n\n\ndef class_var():\n    @export\n    def hack():\n        v = Variable\n        x = v(contract=\"currency\", name=\"balances\")\n\n\ndef class_hash():\n    @export\n    def hack():\n        v = Hash\n        x = v(contract=\"currency\", name=\"balances\")\n\n\ndef exec_contract():\n    @export\n    def fn():\n        def builtins__():\n            pass\n\n    wExec = builtins__[\"exec\"]\n    wExec(\"print('hello world')\")\n\ndef type_exploit():\n    @export\n    def attack(to: str):\n        # before\n        # assert amount > 0, 'Cannot send negative balances!'\n        def gt(a, b):\n            print(\"gt\", a, b)\n            return True\n\n        # assert balances[sender] >= amount, 'Not enough coins to send!'\n        def le(a, b):\n            print(\"lt\", a, b)\n            return True\n\n        # balances[sender] -= amount\n        def rsub(a, b):\n            print(\"rsub\", a, b)\n            return b\n\n        # balances[to] += amount\n        def radd(a, b):\n            print(\"radd\", a, b)\n            return 100\n\n        wAmount = type(\"wAmount\", (), {\"__gt__\": gt, \"__le__\": le, \"__radd__\": radd, \"__rsub__\": rsub})\n        fake_amount_object = wAmount()\n\ndef con_test_one():\n    h = Hash()\n\n    @construct\n    def seed():\n        h['a'] = 100\n        h['b'] = 999\n\n    @export\n    def output():\n        return h['a'], h['b']\n\ndef con_test_two():\n    f = ForeignHash(foreign_contract='con_test_one', foreign_name='h')\n\n    @export\n    def clear():\n        f.clear()\n\ndef test_closure():\n    def export(contract):\n        def decorator(func):\n            def enter(*args, **kwargs):\n                result = func(*args, **kwargs)\n                return result\n            return enter\n        return decorator\n\n    @export\n    def closure_inner():\n        return 1\n\ndef test_closure2():\n    def export(contract):\n        a = 1\n        def decorator(func):\n            b = 2\n            def enter(*args, **kwargs):\n                result = func(*args, **kwargs)\n                return result\n            return enter\n        return decorator\n\n    @export\n    def closure_inner():\n        return 1\n\nclass TestHackThing(TestCase):\n    def setUp(self):\n        self.c = ContractingClient(signer='stu')\n        self.c.raw_driver.flush_full()\n\n        submission_path = os.path.join(os.path.dirname(__file__), \"test_contracts\", \"submission.s.py\")\n\n        with open(submission_path) as f:\n            contract = f.read()\n\n        self.c.raw_driver.set_contract(name='submission', code=contract,)\n\n        self.c.raw_driver.commit()\n\n    def test_can_add(self):\n        self.c.submit(a, name=\"con_a\")\n        with self.assertRaises(Exception):\n            self.c.submit(module_hack, name=\"con_module_hack\")\n\n            ft_con = self.c.get_contract('con_module_hack')\n\n            ft_con.hack()\n\n    def test_cant_submit_class_var(self):\n        with self.assertRaises(Exception):\n            self.c.submit(class_var)\n\n    def test_cant_submit_class_hash(self):\n        with self.assertRaises(Exception):\n            self.c.submit(class_hash)\n\n    def test_cant_submit_exec(self):\n        with self.assertRaises(Exception):\n            self.c.submit(exec_contract)\n\n    def test_cant_submit_type(self):\n        with self.assertRaises(Exception):\n            self.c.submit(type_exploit)\n\n    def test_cant_clear_foreign_hash(self):\n        self.c.submit(con_test_one)\n        self.c.submit(con_test_two)\n\n        t2 = self.c.get_contract('con_test_two')\n\n        with self.assertRaises(Exception):\n            t2.clear()\n\n    def test_no_closures(self):\n        with self.assertRaises(Exception):\n            self.c.submit(test_closure)\n\n    def test_no_closures_work_around(self):\n        with self.assertRaises(Exception):\n            self.c.submit(test_closure2)\n\n\ndef con_test_fixed():\n    v = Variable()\n    @construct\n    def seed():\n        v.set([1.234, 5.678])\n\n    @export\n    def multiply():\n        a, b = v.get()\n        return a * b\n\n\nclass TestFixed(TestCase):\n    def setUp(self):\n        self.c = ContractingClient(signer='stu', driver=Driver())\n        self.c.raw_driver.flush_full()\n\n        submission_path = os.path.join(os.path.dirname(__file__), \"test_contracts\", \"submission.s.py\")\n\n        with open(submission_path) as f:\n            contract = f.read()\n\n        self.c.raw_driver.set_contract(name='submission', code=contract,)\n\n        self.c.raw_driver.commit()\n\n    def test_can_multiply(self):\n        self.c.submit(con_test_fixed)\n\n        self.c.raw_driver.commit()\n        self.c.raw_driver.flush_cache()\n        f = self.c.get_contract('con_test_fixed')\n\n        z = f.multiply()\n        self.assertEqual(z, 1.234 * 5.678)\n\nif __name__ == '__main__':\n    import unittest\n    unittest.main()\n"
  },
  {
    "path": "tests/integration/test_pixel_game.py",
    "content": "from contracting.client import ContractingClient\nfrom unittest import TestCase\n\n\ndef con_coin():\n    supply = Variable()\n    balances = Hash(default_value=0)\n    owner = Variable()\n\n    @construct\n    def seed():\n        balances[ctx.caller] = 1000000\n        owner.set(ctx.caller)\n        supply.set(1000000)\n\n    @export\n    def transfer(amount: int, to: str):\n        sender = ctx.caller\n        assert balances[sender] >= amount, 'Not enough coins to send!'\n\n        balances[sender] -= amount\n        balances[to] += amount\n\n    @export\n    def balance_of(account: str):\n        return balances[account]\n\n    @export\n    def total_supply():\n        return supply.get()\n\n    @export\n    def allowance(main: str, spender: str):\n        return balances[main, spender]\n\n    @export\n    def approve(amount: int, to: str):\n        sender = ctx.caller\n        balances[sender, to] += amount\n        return balances[sender, to]\n\n    @export\n    def transfer_from(amount: int, to: str, main_account: str):\n        sender = ctx.caller\n\n        assert balances[main_account, sender] >= amount, 'Not enough coins approved to send! You have {} and are trying to spend {}'\\\n            .format(balances[main_account, sender], amount)\n        assert balances[main_account] >= amount, 'Not enough coins to send!'\n\n        balances[main_account, sender] -= amount\n        balances[main_account] -= amount\n\n        balances[to] += amount\n\n    @export\n    def mint(amount: int, to: str):\n        assert ctx.caller == owner.get(), 'Only the owner can mint!'\n\n        balances[to] += amount\n\n        s = supply.get()\n        supply.set(s + amount)\n\n    @export\n    def change_ownership(new_owner: str):\n        assert ctx.caller == owner.get(), 'Only the owner can change ownership!'\n\n        owner.set(new_owner)\n\n\nclass TestCoinContract(TestCase):\n    def setUp(self):\n        self.c = ContractingClient(signer='stu')\n        self.c.flush()\n\n        self.c.submit(con_coin)\n        self.coin = self.c.get_contract('con_coin')\n\n    def tearDown(self):\n        self.c.flush()\n\n    def test_coin_construction(self):\n        self.assertEqual(self.coin.balances['stu'], 1000000)\n\n    def test_transfer_not_enough(self):\n        with self.assertRaises(AssertionError):\n            self.coin.transfer(amount=9999999, to='raghu')\n\n    def test_transfer_enough(self):\n        self.coin.transfer(amount=123, to='raghu')\n        self.assertEqual(self.coin.balances['raghu'], 123)\n\n    def test_balance_of_works(self):\n        self.coin.transfer(amount=123, to='raghu')\n        self.assertEqual(self.coin.balance_of(account='raghu'), 123)\n\n    def test_total_supply_pre_mint(self):\n        self.assertEqual(self.coin.total_supply(), 1000000)\n        self.assertEqual(self.coin.supply.get(), 1000000)\n\n    def test_approve_modified_balances(self):\n        self.coin.approve(amount=100, to='raghu')\n        self.assertEqual(self.coin.balances['stu', 'raghu'], 100)\n\n    def test_allowance_returns_approve(self):\n        self.coin.approve(amount=100, to='raghu')\n        self.assertEqual(self.coin.allowance(main='stu', spender='raghu'), 100)\n\n    def test_transfer_from_failure_not_enough_allowance(self):\n        self.coin.approve(amount=100, to='raghu')\n        with self.assertRaises(AssertionError):\n            self.coin.transfer_from(amount=101, to='colin', main_account='stu', signer='raghu')\n\n    def test_transfer_from_failure_not_enough_in_main_account(self):\n        self.coin.approve(amount=1000000000, to='raghu')\n        with self.assertRaises(AssertionError):\n            self.coin.transfer_from(amount=1000000000, to='colin', main_account='stu', signer='raghu')\n\n    def test_transfer_from_success_modified_balance_to_and_allowance(self):\n        self.coin.approve(amount=100, to='raghu')\n        self.coin.transfer_from(amount=33, to='colin', main_account='stu', signer='raghu')\n\n        self.assertEqual(self.coin.balances['colin'], 33)\n        self.assertEqual(self.coin.balances['stu'], 1000000 - 33)\n        self.assertEqual(self.coin.balances['stu', 'raghu'], 67)\n\n    def test_mint_fails_if_not_owner(self):\n        with self.assertRaises(AssertionError):\n            self.coin.mint(amount=1000000, to='raghu', signer='raghu')\n\n    def test_mint_succeeds_if_owner_and_modifies_balance_and_supply(self):\n        self.coin.mint(amount=999, to='raghu')\n\n        self.assertEqual(self.coin.balances['raghu'], 999)\n        self.assertEqual(self.coin.supply.get(), 1000000 + 999)\n\n    def test_change_ownership_modifies_owner(self):\n        self.coin.change_ownership(new_owner='raghu')\n        self.assertEqual(self.coin.owner.get(), 'raghu')\n\n    def test_change_ownership_only_prior_owner(self):\n        with self.assertRaises(AssertionError):\n            self.coin.change_ownership(new_owner='colin', signer='raghu')\n\n    def test_change_ownership_then_mint_succeeds(self):\n        self.coin.change_ownership(new_owner='raghu')\n        self.coin.mint(amount=999, to='raghu', signer='raghu')\n\n        self.assertEqual(self.coin.balances['raghu'], 999)\n        self.assertEqual(self.coin.supply.get(), 1000000 + 999)\n\n\ndef con_pixel_game():\n    import con_coin\n\n    plots = Hash()\n    landlord = Variable()\n\n    max_x = 256\n    max_y = 256\n\n    decay = 0.02\n    tax_period = datetime.DAYS * 1\n\n    def assert_in_bounds(x: int, y: int):\n        assert 0 <= x < max_x, 'X coordinate out of bounds.'\n        assert 0 <= y < max_y, 'Y coordinate out of bounds.'\n\n    def assert_is_hex(color_string):\n        assert len(color_string) == 256, 'Invalid color string passed.'\n        assert int(color_string, 16), 'Color string is not a hex string.'\n\n    @construct\n    def seed():\n        landlord.set(ctx.caller)\n\n    @export\n    def buy_plot(x: int, y: int, amount: float, price: float):\n        assert_in_bounds(x, y)\n\n        plot = plots[x, y]\n        if plot is None:\n            plot = {\n                'colors': '0' * 256,\n                'owner': ctx.caller,\n                'price': price,\n                'purchase_time': now\n            }\n            plots[x. y] = plot\n        else:\n            assert plot['price'] <= amount\n            assert amount <= coin.allowance(owner=ctx.caller, spender=ctx.this)\n\n            coin.transfer_from(amount=plot['price'], to=plot['owner'], main_account=ctx.sender)\n\n            plot.update({\n                'owner': ctx.caller,\n                'price': price,\n                'purchase_time': now\n            })\n            plots[x, y] = plot\n\n    @export\n    def set_plot(x: int, y: int, color_string: str):\n        assert_is_hex(color_string)\n\n        plot = plots[x, y]\n\n        assert plot['owner'] == ctx.caller, 'You do not own this plot!'\n\n        plot['colors'] = color_string\n\n        plots[x, y] = plot\n\n\nclass TestPixelGame(TestCase):\n    def setUp(self):\n        self.c = ContractingClient(signer='stu')\n        self.c.flush()\n\n        self.c.submit(con_coin)\n        self.c.submit(con_pixel_game)\n        self.pixel = self.c.get_contract('con_pixel_game')\n\n    def tearDown(self):\n        self.c.flush()\n\n    def test_init(self):\n        self.assertEqual(1, 1)\n"
  },
  {
    "path": "tests/integration/test_rich_ctx_calling.py",
    "content": "from unittest import TestCase\nfrom contracting.client import ContractingClient\n\n\ndef con_module1():\n    @export\n    def get_context2():\n        return {\n            'name': 'get_context2',\n            'owner': ctx.owner,\n            'this': ctx.this,\n            'signer': ctx.signer,\n            'caller': ctx.caller,\n            'entry': ctx.entry,\n            'submission_name': ctx.submission_name\n        }\n\n\ndef con_all_in_one():\n    @export\n    def call_me():\n        return call_me_again()\n\n    @export\n    def call_me_again():\n        return call_me_again_again()\n\n    @export\n    def call_me_again_again():\n        return({\n            'name': 'call_me_again_again',\n            'owner': ctx.owner,\n            'this': ctx.this,\n            'signer': ctx.signer,\n            'caller': ctx.caller,\n            'entry': ctx.entry,\n            'submission_name': ctx.submission_name\n        })\n\n\ndef con_dynamic_import():\n\n    @export\n    def called_from_a_far():\n        m = importlib.import_module('con_all_in_one')\n        res = m.call_me_again_again()\n\n        return [res, {\n            'name': 'called_from_a_far',\n            'owner': ctx.owner,\n            'this': ctx.this,\n            'signer': ctx.signer,\n            'caller': ctx.caller,\n            'entry': ctx.entry,\n            'submission_name': ctx.submission_name\n        }]\n\n    @export\n    def con_called_from_a_far_stacked():\n        m = importlib.import_module('con_all_in_one')\n        return m.call()\n\ndef con_submission_name_test():\n    submission_name = Variable()\n\n    @construct\n    def seed():\n        submission_name.set(ctx.submission_name)\n\n    @export\n    def get_submission_context():\n        return submission_name.get()\n\n    @export\n    def get_entry_context():\n        con_name, func_name = ctx.entry\n\n        return {\n            'entry_contract': con_name,\n            'entry_function': func_name\n        }\n\n\n\nclass TestRandomsContract(TestCase):\n    def setUp(self):\n        self.c = ContractingClient(signer='stu')\n        self.c.flush()\n\n        # Submit contracts\n        self.c.submit(con_module1)\n        self.c.submit(con_all_in_one)\n        self.c.submit(con_dynamic_import)\n        self.c.submit(con_submission_name_test)\n\n    def tearDown(self):\n        self.c.flush()\n\n    def test_ctx2(self):\n        module = self.c.get_contract('con_module1')\n        res = module.get_context2()\n        expected = {\n            'name': 'get_context2',\n            'entry': ('con_module1', 'get_context2'),\n            'owner': None,\n            'this': 'con_module1',\n            'signer': 'stu',\n            'caller': 'stu',\n            'submission_name': None\n        }\n        self.assertDictEqual(res, expected)\n\n    def test_multi_call_doesnt_affect_parameters(self):\n        aio = self.c.get_contract('con_all_in_one')\n        res = aio.call_me()\n\n        expected = {\n            'name': 'call_me_again_again',\n            'entry': ('con_all_in_one', 'call_me'),\n            'owner': None,\n            'this': 'con_all_in_one',\n            'signer': 'stu',\n            'caller': 'stu',\n            'submission_name': None\n        }\n\n        self.assertDictEqual(res, expected)\n\n    # To-Do: Figure out why this test does not work when using pytest tests/integration, but works when running the test directly\n    # def test_dynamic_call(self):\n    #     dy = self.c.get_contract('con_dynamic_import')\n    #     res1, res2 = dy.called_from_a_far()\n\n    #     expected1 = {\n    #         'name': 'call_me_again_again',\n    #         'entry': ('con_dynamic_import', 'called_from_a_far'),\n    #         'owner': None,\n    #         'this': 'con_all_in_one',\n    #         'signer': 'stu',\n    #         'caller': 'con_dynamic_import',\n    #         'submission_name': None\n    #     }\n\n    #     expected2 = {\n    #         'name': 'called_from_a_far',\n    #         'entry': ('con_dynamic_import', 'called_from_a_far'),\n    #         'owner': None,\n    #         'this': 'con_dynamic_import',\n    #         'signer': 'stu',\n    #         'caller': 'stu',\n    #         'submission_name': None\n    #     }\n\n    #     self.assertDictEqual(res1, expected1)\n    #     self.assertDictEqual(res2, expected2)\n\n\n    def test_submission_name_in_construct_function(self):\n        contract = self.c.get_contract('con_submission_name_test')\n        submission_name = contract.get_submission_context()\n\n        self.assertEqual(\"con_submission_name_test\", submission_name)\n\n    def test_entry_context(self):\n        contract = self.c.get_contract('con_submission_name_test')\n        details = contract.get_entry_context()\n\n        self.assertEqual(\"con_submission_name_test\", details.get('entry_contract'))\n        self.assertEqual(\"get_entry_context\", details.get('entry_function'))"
  },
  {
    "path": "tests/integration/test_run_private_function.py",
    "content": "from unittest import TestCase\nfrom contracting.client import ContractingClient\nimport os\n\nclass TestRunPrivateFunction(TestCase):\n    def setUp(self):\n        self.client = ContractingClient()\n\n        private_methods_path = os.path.join(os.path.dirname(__file__), \"test_contracts\", \"private_methods.s.py\")\n\n        with open(private_methods_path) as f:\n            code = f.read()\n\n        self.client.submit(code, name='private_methods')\n        self.private_methods = self.client.get_contract('private_methods')\n\n    def tearDown(self):\n        self.client.flush()\n\n    def test_can_call_public_func(self):\n        self.assertEqual(self.private_methods.call_private(), 'abc')\n\n    def test_cannot_call_private_func(self):\n        with self.assertRaises(Exception):\n            self.private_methods.private()\n\n    def test_cannot_execute_private_func(self):\n        with self.assertRaises(AssertionError):\n            self.private_methods.executor.execute(\n                sender='sys',\n                contract_name='private_methods',\n                function_name='__private',\n                kwargs={}\n            )\n\n    def test_can_call_private_func_if_run_private_function_called(self):\n        self.assertEqual(self.private_methods.run_private_function('__private'), 'abc')\n\n    def test_can_call_private_func_if_run_private_function_called_and_no_prefix(self):\n        self.assertEqual(self.private_methods.run_private_function('private'), 'abc')\n\n    def test_can_call_private_but_then_not(self):\n        self.assertEqual(self.private_methods.run_private_function('private'), 'abc')\n\n        with self.assertRaises(AssertionError):\n            self.private_methods.executor.execute(\n                sender='sys',\n                contract_name='private_methods',\n                function_name='__private',\n                kwargs={}\n            )\n"
  },
  {
    "path": "tests/integration/test_senecaCompiler_integration.py",
    "content": "from unittest import TestCase\nfrom contracting.compilation.compiler import ContractingCompiler\nfrom contracting.stdlib import env\nfrom contracting import constants\n\nimport re\nimport astor\nimport os\n\nclass TestSenecaCompiler(TestCase):\n    def test_visit_assign_variable(self):\n        code = '''\nv = Variable()\n'''\n        c = ContractingCompiler()\n        comp = c.parse(code, lint=False)\n        code_str = astor.to_source(comp)\n\n        scope = env.gather()\n\n        exec(code_str, scope)\n\n        v = scope['__v']\n\n        self.assertEqual(v._key, '__main__.v')\n\n    def test_visit_assign_foreign_variable(self):\n        code = '''\nfv = ForeignVariable(foreign_contract='scoob', foreign_name='kumbucha')\n        '''\n        c = ContractingCompiler()\n        comp = c.parse(code, lint=False)\n        code_str = astor.to_source(comp)\n\n        scope = env.gather()\n\n        exec(code_str, scope)\n\n        fv = scope['__fv']\n\n        self.assertEqual(fv._key, 'scoob.kumbucha')\n\n    def test_assign_hash_variable(self):\n        code = '''\nh = Hash()\n        '''\n        c = ContractingCompiler()\n        comp = c.parse(code, lint=False)\n        code_str = astor.to_source(comp)\n\n        scope = env.gather()\n\n        exec(code_str, scope)\n\n        h = scope['__h']\n\n        self.assertEqual(h._key, '__main__.h')\n\n    def test_assign_foreign_hash(self):\n        code = '''\nfv = ForeignHash(foreign_contract='scoob', foreign_name='kumbucha')\n        '''\n\n        c = ContractingCompiler()\n        comp = c.parse(code, lint=False)\n        code_str = astor.to_source(comp)\n\n        scope = env.gather()\n\n        exec(code_str, scope)\n\n        fv = scope['__fv']\n\n        self.assertEqual(fv._key, 'scoob.kumbucha')\n        # self.assertEqual(fv.foreign_key, 'scoob.kumbucha')\n#\n#     def test_export_decorator_pops(self):\n#         code = '''\n# @export\n# def funtimes():\n#     print('cool')\n#         '''\n#\n#         c = ContractingCompiler()\n#         comp = c.parse(code, lint=False)\n#         code_str = astor.to_source(comp)\n#\n#         self.assertNotIn('@export', code_str)\n\n    def test_private_function_prefixes_properly(self):\n        code = '''\ndef private():\n    print('cool')\n        '''\n\n        c = ContractingCompiler()\n        comp = c.parse(code, lint=False)\n        code_str = astor.to_source(comp)\n\n        self.assertIn('__private', code_str)\n\n    def test_private_func_call_in_public_func_properly_renamed(self):\n        code = '''\n@export\ndef public():\n    private('hello')\n    \ndef private(message):\n    print(message)\n'''\n\n        c = ContractingCompiler()\n        comp = c.parse(code, lint=False)\n        code_str = astor.to_source(comp)\n\n        # there should be two private occurances of the method call\n        self.assertEqual(len([m.start() for m in re.finditer('__private', code_str)]), 2)\n\n    def test_private_func_call_in_other_private_functions(self):\n        code = '''\ndef a():\n    b()\n    \ndef b():\n    c()\n    \ndef c():\n    e()\n    \ndef d():\n    print('hello')\n    \ndef e():\n    d()        \n'''\n        c = ContractingCompiler()\n        comp = c.parse(code, lint=False)\n        code_str = astor.to_source(comp)\n\n        self.assertEqual(len([m.start() for m in re.finditer(constants.PRIVATE_METHOD_PREFIX, code_str)]), 9)\n\n    def test_construct_renames_properly(self):\n        code = '''\n@construct\ndef seed():\n    print('yes')\n\n@export\ndef hello():\n    print('no')\n    \ndef goodbye():\n    print('idk')\n        '''\n\n        c = ContractingCompiler()\n        comp = c.parse(code, lint=False)\n        code_str = astor.to_source(comp)\n\n    def test_token_contract_parses_correctly(self):\n        currency_path = os.path.join(os.path.dirname(__file__), \"test_contracts\", \"currency.s.py\")\n\n        with open(currency_path) as f:\n            code = f.read()\n\n\n        c = ContractingCompiler()\n        comp = c.parse(code, lint=False)\n        code_str = astor.to_source(comp)\n\n    def test_export_decorator_argument_is_added(self):\n        code = '''\n@export\ndef test():\n    pass        \n'''\n        c = ContractingCompiler()\n        comp = c.parse(code, lint=False)\n        code_str = astor.to_source(comp)\n        print(code_str)\n"
  },
  {
    "path": "tests/integration/test_seneca_client_randoms.py",
    "content": "from unittest import TestCase\nfrom contracting.client import ContractingClient\nimport random\n\ndef con_random_contract():\n    random.seed()\n\n    cards = [1, 2, 3, 4, 5, 6, 7, 8]\n\n    cardinal_values = ['A', '1', '2', '3', '4', '5', '6', '7', '8', '9', '10', 'J', 'Q', 'K']\n    suits = ['S', 'C', 'H', 'D']\n\n    cities = ['Cleveland', 'Detroit', 'Chicago', 'New York', 'San Francisco']\n\n    @export\n    def shuffle_cards(**kwargs: dict):\n        random.shuffle(cards)\n        return cards\n\n    @export\n    def random_number(k: int):\n        return random.randrange(k)\n\n    @export\n    def random_number_2(k: int):\n        # adjust the random state by calling another random function\n        shuffle_cards()\n        return random.randrange(k)\n\n    @export\n    def random_bits(k: int):\n        shuffle_cards()\n        shuffle_cards()\n        shuffle_cards()\n        return random.getrandbits(k)\n\n    @export\n    def int_in_range(a: int, b: int):\n        shuffle_cards()\n        shuffle_cards()\n        return random.randint(a, b)\n\n    @export\n    def deal_card():\n        random.shuffle(cardinal_values)\n        random.shuffle(cardinal_values)\n        random.shuffle(cardinal_values)\n\n        random.shuffle(suits)\n        random.shuffle(suits)\n        random.shuffle(suits)\n\n        c = ''\n        c += random.choice(cardinal_values)\n        c += random.choice(suits)\n\n        return c\n\n    @export\n    def pick_cities(k: int):\n        return random.choices(cities, k)\n\n\nclass TestRandomsContract(TestCase):\n    def setUp(self):\n        self.c = ContractingClient(signer='stu')\n        self.c.flush()\n        self.c.submit(con_random_contract)\n\n        self.random_contract = self.c.get_contract('con_random_contract')\n\n    def tearDown(self):\n        self.c.flush()\n\n    def test_basic_shuffle(self):\n        cards_1 = self.random_contract.shuffle_cards()\n        cards_2 = self.random_contract.shuffle_cards()\n\n        self.assertEqual(cards_1, cards_2)\n\n    def test_basic_shuffle_different_with_different_seeds(self):\n        cards_1 = self.random_contract.shuffle_cards(environment={'block_num': 999})\n        cards_2 = self.random_contract.shuffle_cards(environment={'block_num': 998})\n\n        self.assertNotEqual(cards_1, cards_2)\n\n    def test_random_num_one_vs_two(self):\n        k = self.random_contract.random_number(k=1000)\n        k2 = self.random_contract.random_number_2(k=1000)\n\n        self.assertNotEqual(k, k2)\n\n        random.seed('000')\n\n        self.assertEqual(k, random.randrange(1000))\n\n        random.seed('000')\n        cards = [1, 2, 3, 4, 5, 6, 7, 8]\n        random.shuffle(cards)\n\n        self.assertEqual(k2, random.randrange(1000))\n    '''' TEST CASE IS IRRELEVANT as getrandbits will never sync with system random.\n    def test_random_getrandbits(self):\n        b = self.random_contract.random_bits(k=20)\n\n        random.seed('000')\n\n        cards = [1, 2, 3, 4, 5, 6, 7, 8]\n        random.shuffle(cards)\n        random.shuffle(cards)\n        random.shuffle(cards)\n\n        self.assertEqual(b, random.getrandbits(20))\n    '''\n\n    def test_random_range_int(self):\n        a = self.random_contract.int_in_range(a=100, b=50000)\n\n        random.seed('000')\n\n        cards = [1, 2, 3, 4, 5, 6, 7, 8]\n        random.shuffle(cards)\n        random.shuffle(cards)\n\n        self.assertEqual(a, random.randint(a=100, b=50000))\n\n    def test_random_choice(self):\n        cities = self.random_contract.pick_cities(k=2)\n\n        random.seed('000')\n        c = ['Cleveland', 'Detroit', 'Chicago', 'New York', 'San Francisco']\n        cc = random.choices(c, k=2)\n\n        self.assertListEqual(cities, cc)\n\n    def test_auxiliary_salt(self):\n        cards_1 = self.random_contract.shuffle_cards(environment={\n            'AUXILIARY_SALT': 'ffd8ded9ced929a41dae83b1f22a6a31b52f79bbf4cdabe6a27d9646dd2bd725fc29c8bc122cb9e37a2904da00e34df499ee7a897505d1de3f0511f9f9c1150c'})\n        cards_2 = self.random_contract.shuffle_cards(environment={\n            'AUXILIARY_SALT': 'ffd8ded9ced929a41dae83b1f22a6a31b52f79bbf4cdabe6a27d9646dd2bd725fc29c8bc122cb9e37a2904da00e34df499ee7a897505d1de3f0511f9f9c1150c'})\n        cards_3 = self.random_contract.shuffle_cards(environment={\n            'AUXILIARY_SALT': 'f79bbded9ced929a41dae83b1f22a6a31b52f79bbf4cdabe6a27d9646dd2bd725fc29c8bc122cb9e37a2904da00e34df499ee7a897505d1de3f0511f9f9c1150c'})\n\n        self.assertEqual(cards_1, cards_2)\n        self.assertNotEqual(cards_1, cards_3)"
  },
  {
    "path": "tests/integration/test_seneca_client_replaces_executor.py",
    "content": "from unittest import TestCase\nfrom contracting.stdlib.bridge.time import Datetime\nfrom contracting.client import ContractingClient\nimport os\n\nclass TestSenecaClientReplacesExecutor(TestCase):\n    def setUp(self):\n        self.c = ContractingClient(signer='stu')\n        self.c.raw_driver.flush_full()\n\n        submission_path = os.path.join(os.path.dirname(__file__), \"test_contracts\", \"submission.s.py\")\n\n        with open(submission_path) as f:\n            contract = f.read()\n\n        self.c.raw_driver.set_contract(name='submission', code=contract,)\n\n        self.c.raw_driver.commit()\n\n        submission = self.c.get_contract('submission')\n\n        # submit erc20 clone\n        erc20_clone_path = os.path.join(os.path.dirname(__file__), \"test_contracts\", \"erc20_clone.s.py\")\n\n        with open(erc20_clone_path) as f:\n            code = f.read()\n            self.c.submit(code, name='con_erc20_clone')\n\n        atomic_swaps_path = os.path.join(os.path.dirname(__file__), \"test_contracts\", \"atomic_swaps.s.py\")\n\n        with open(atomic_swaps_path) as f:\n            code = f.read()\n            self.c.submit(code, name='con_atomic_swaps')\n\n        self.erc20_clone = self.c.get_contract('con_erc20_clone')\n        self.atomic_swaps = self.c.get_contract('con_atomic_swaps')\n\n    def tearDown(self):\n        self.c.raw_driver.flush_full()\n\n    def test_initiate_not_enough_approved(self):\n        self.erc20_clone.approve(amount=1000000, to='con_atomic_swaps')\n\n        with self.assertRaises(AssertionError):\n            self.atomic_swaps.initiate(participant='raghu',\n                                       expiration=Datetime(2020, 1, 1),\n                                       hashlock='eaf48a02d3a4bb3aeb0ecb337f6efb026ee0bbc460652510cff929de78935514',\n                                       amount=5000000)\n\n    def test_initiate_transfers_coins_correctly(self):\n        self.erc20_clone.approve(amount=1000000, to='con_atomic_swaps')\n\n        self.atomic_swaps.initiate(participant='raghu',\n                                   expiration=Datetime(2020, 1, 1),\n                                   hashlock='eaf48a02d3a4bb3aeb0ecb337f6efb026ee0bbc460652510cff929de78935514',\n                                   amount=5)\n\n        atomic_swaps = self.erc20_clone.balance_of(account='con_atomic_swaps')\n        stu_bal = self.erc20_clone.balance_of(account='stu')\n        stu_as = self.erc20_clone.allowance(owner='stu', spender='con_atomic_swaps')\n\n        self.assertEqual(atomic_swaps, 5)\n        self.assertEqual(stu_bal, 999995)\n        self.assertEqual(stu_as, 999995)\n\n    def test_initiate_writes_to_correct_key_and_properly(self):\n        self.erc20_clone.approve(amount=1000000, to='con_atomic_swaps')\n\n        self.atomic_swaps.initiate(participant='raghu',\n                                   expiration=Datetime(2020, 1, 1),\n                                   hashlock='eaf48a02d3a4bb3aeb0ecb337f6efb026ee0bbc460652510cff929de78935514',\n                                   amount=5)\n\n        key = 'con_atomic_swaps.swaps:raghu:eaf48a02d3a4bb3aeb0ecb337f6efb026ee0bbc460652510cff929de78935514'\n\n        expiration, amount = self.c.raw_driver.get(key)\n        self.assertEqual(expiration, Datetime(2020, 1, 1))\n        self.assertEqual(amount, 5)\n\n    def test_redeem_on_wrong_secret_fails(self):\n        self.erc20_clone.approve(amount=1000000, to='con_atomic_swaps')\n\n        self.atomic_swaps.initiate(participant='raghu',\n                                   expiration=Datetime(2020, 1, 1),\n                                   hashlock='eaf48a02d3a4bb3aeb0ecb337f6efb026ee0bbc460652510cff929de78935514',\n                                   amount=5)\n\n        with self.assertRaises(AssertionError):\n            self.atomic_swaps.redeem(signer='raghu', secret='00')\n\n    def test_redeem_on_wrong_sender_fails(self):\n        self.erc20_clone.approve(amount=1000000, to='con_atomic_swaps')\n        self.atomic_swaps.initiate(participant='raghu',\n                                   expiration=Datetime(2020, 1, 1),\n                                   hashlock='eaf48a02d3a4bb3aeb0ecb337f6efb026ee0bbc460652510cff929de78935514',\n                                   amount=5)\n\n        with self.assertRaises(AssertionError):\n            self.atomic_swaps.redeem(secret='842b65a7d48e3a3c3f0e9d37eaced0b2')\n\n    def test_past_expiration_fails(self):\n        self.erc20_clone.approve(amount=1000000, to='con_atomic_swaps')\n\n        self.atomic_swaps.initiate(participant='raghu',\n                                   expiration=Datetime(2020, 1, 1),\n                                   hashlock='eaf48a02d3a4bb3aeb0ecb337f6efb026ee0bbc460652510cff929de78935514',\n                                   amount=5)\n\n        environment = {'now': Datetime(2021, 1, 1)}\n\n        with self.assertRaises(AssertionError):\n            self.atomic_swaps.redeem(secret='842b65a7d48e3a3c3f0e9d37eaced0b2',\n                                     signer='raghu',\n                                     environment=environment)\n\n    def test_successful_redeem_transfers_coins_correctly(self):\n        self.erc20_clone.approve(amount=1000000, to='con_atomic_swaps')\n\n        self.atomic_swaps.initiate(participant='raghu',\n                                   expiration=Datetime(2020, 1, 1),\n                                   hashlock='eaf48a02d3a4bb3aeb0ecb337f6efb026ee0bbc460652510cff929de78935514',\n                                   amount=5)\n\n        environment = {'now': Datetime(2019, 1, 1)}\n\n        self.atomic_swaps.redeem(secret='842b65a7d48e3a3c3f0e9d37eaced0b2',\n                                 signer='raghu',\n                                 environment=environment)\n\n        atomic_swaps = self.erc20_clone.balance_of(account='con_atomic_swaps')\n        raghu = self.erc20_clone.balance_of(account='raghu')\n\n        self.assertEqual(raghu, 5)\n        self.assertEqual(atomic_swaps, 0)\n\n    def test_successful_redeem_deletes_entry(self):\n        self.erc20_clone.approve(amount=1000000, to='con_atomic_swaps')\n\n        self.atomic_swaps.initiate(participant='raghu',\n                                   expiration=Datetime(2020, 1, 1),\n                                   hashlock='eaf48a02d3a4bb3aeb0ecb337f6efb026ee0bbc460652510cff929de78935514',\n                                   amount=5)\n\n        environment = {'now': Datetime(2019, 1, 1)}\n\n        self.atomic_swaps.redeem(secret='842b65a7d48e3a3c3f0e9d37eaced0b2',\n                                 signer='raghu',\n                                 environment=environment)\n\n        key = 'atomic_swaps.swaps:raghu:eaf48a02d3a4bb3aeb0ecb337f6efb026ee0bbc460652510cff929de78935514'\n        v = self.c.raw_driver.get(key)\n\n        self.assertEqual(v, None)\n\n    def test_refund_works(self):\n        self.erc20_clone.approve(amount=1000000, to='con_atomic_swaps')\n\n        self.atomic_swaps.initiate(participant='raghu',\n                                   expiration=Datetime(2020, 1, 1),\n                                   hashlock='eaf48a02d3a4bb3aeb0ecb337f6efb026ee0bbc460652510cff929de78935514',\n                                   amount=5)\n\n        environment = {'now': Datetime(2021, 1, 1)}\n\n        self.atomic_swaps.refund(participant='raghu', secret='842b65a7d48e3a3c3f0e9d37eaced0b2',\n                                 environment=environment)\n\n        atomic_swaps = self.erc20_clone.balance_of(account='con_atomic_swaps')\n        stu = self.erc20_clone.balance_of(account='stu')\n\n        self.assertEqual(stu, 1000000)\n        self.assertEqual(atomic_swaps, 0)\n\n    def test_refund_too_early_fails(self):\n        self.erc20_clone.approve(amount=1000000, to='con_atomic_swaps')\n\n        self.atomic_swaps.initiate(participant='raghu',\n                                   expiration=Datetime(2020, 1, 1),\n                                   hashlock='eaf48a02d3a4bb3aeb0ecb337f6efb026ee0bbc460652510cff929de78935514',\n                                   amount=5)\n\n        environment = {'now': Datetime(2019, 1, 1)}\n\n        with self.assertRaises(AssertionError):\n            self.atomic_swaps.refund(participant='raghu', secret='842b65a7d48e3a3c3f0e9d37eaced0b2',\n                                    environment=environment)\n\n    def test_refund_participant_is_signer_fails(self):\n        self.erc20_clone.approve(amount=1000000, to='con_atomic_swaps')\n\n        self.atomic_swaps.initiate(participant='raghu',\n                                   expiration=Datetime(2020, 1, 1),\n                                   hashlock='eaf48a02d3a4bb3aeb0ecb337f6efb026ee0bbc460652510cff929de78935514',\n                                   amount=5)\n\n        environment = {'now': Datetime(2021, 1, 1)}\n\n        with self.assertRaises(AssertionError):\n            self.atomic_swaps.refund(participant='raghu', secret='842b65a7d48e3a3c3f0e9d37eaced0b2',\n                                     environment=environment,\n                                     signer='raghu')\n\n    def test_refund_fails_with_wrong_secret(self):\n        self.erc20_clone.approve(amount=1000000, to='con_atomic_swaps')\n\n        self.atomic_swaps.initiate(participant='raghu',\n                                   expiration=Datetime(2020, 1, 1),\n                                   hashlock='eaf48a02d3a4bb3aeb0ecb337f6efb026ee0bbc460652510cff929de78935514',\n                                   amount=5)\n\n        environment = {'now': Datetime(2021, 1, 1)}\n\n        with self.assertRaises(AssertionError):\n            self.atomic_swaps.refund(participant='raghu', secret='00',\n                                     environment=environment,\n                                     )\n\n    def test_refund_resets_swaps(self):\n        self.erc20_clone.approve(amount=1000000, to='con_atomic_swaps')\n\n        self.atomic_swaps.initiate(participant='raghu',\n                                   expiration=Datetime(2020, 1, 1),\n                                   hashlock='eaf48a02d3a4bb3aeb0ecb337f6efb026ee0bbc460652510cff929de78935514',\n                                   amount=5)\n\n        environment = {'now': Datetime(2021, 1, 1)}\n\n        self.atomic_swaps.refund(participant='raghu', secret='842b65a7d48e3a3c3f0e9d37eaced0b2',\n                                 environment=environment)\n\n        key = 'atomic_swaps.swaps:raghu:eaf48a02d3a4bb3aeb0ecb337f6efb026ee0bbc460652510cff929de78935514'\n        v = self.c.raw_driver.get(key)\n\n        self.assertEqual(v, None)\n"
  },
  {
    "path": "tests/integration/test_stamp_deduction.py",
    "content": "from unittest import TestCase\nfrom contracting.storage.driver import Driver\nfrom contracting.execution.executor import Executor\nfrom contracting.constants import STAMPS_PER_TAU\n\nimport contracting\nimport os\n\ndef submission_kwargs_for_file(f):\n    # Get the file name only by splitting off directories\n    split = f.split('/')\n    split = split[-1]\n\n    # Now split off the .s\n    split = split.split('.')\n    contract_name = split[0]\n\n    with open(f) as file:\n        contract_code = file.read()\n\n    return {\n        'name': f'con_{contract_name}',\n        'code': contract_code,\n    }\n\n\nTEST_SUBMISSION_KWARGS = {\n    'sender': 'stu',\n    'contract_name': 'submission',\n    'function_name': 'submit_contract'\n}\n\n\nclass TestMetering(TestCase):\n    def setUp(self):\n        # Hard load the submission contract\n        self.d = Driver()\n        self.d.flush_full()\n\n        submission_path = os.path.join(os.path.dirname(__file__), \"test_contracts\", \"submission.s.py\")\n\n        with open(submission_path) as f:\n            contract = f.read()\n\n        self.d.set_contract(name='submission',\n                            code=contract)\n        self.d.commit()\n\n        # Execute the currency contract with metering disabled\n        self.e = Executor(driver=self.d, currency_contract='con_currency')\n        currency_path = os.path.join(os.path.dirname(__file__), \"test_contracts\", \"currency.s.py\")\n        self.e.execute(**TEST_SUBMISSION_KWARGS,\n                       kwargs=submission_kwargs_for_file(currency_path), metering=False, auto_commit=True)\n\n    def tearDown(self):\n        self.d.flush_full()\n\n    def test_simple_execution_deducts_stamps(self):\n        prior_balance = self.d.get('con_currency.balances:stu')\n\n        output = self.e.execute('stu', 'con_currency', 'transfer', kwargs={'amount': 100, 'to': 'colin'}, auto_commit=True)\n\n        new_balance = self.d.get('con_currency.balances:stu')\n\n        self.assertEqual(float(prior_balance - new_balance - 100), output['stamps_used'] / STAMPS_PER_TAU)\n\n    def test_too_few_stamps_fails_and_deducts_properly(self):\n        prior_balance = self.d.get('con_currency.balances:stu')\n\n        print(prior_balance)\n\n        output = self.e.execute('stu', 'con_currency', 'transfer', kwargs={'amount': 100, 'to': 'colin'},\n                                                stamps=1, auto_commit=True)\n\n        print(output)\n\n        new_balance = self.d.get('con_currency.balances:stu')\n\n        self.assertEqual(float(prior_balance - new_balance), output['stamps_used'] / STAMPS_PER_TAU)\n\n    def test_adding_too_many_stamps_throws_error(self):\n        prior_balance = self.d.get('con_currency.balances:stu')\n        too_many_stamps = (prior_balance + 1000) * STAMPS_PER_TAU\n\n        output = self.e.execute('stu', 'con_currency', 'transfer', kwargs={'amount': 100, 'to': 'colin'},\n                                                stamps=too_many_stamps, auto_commit=True)\n\n        self.assertEqual(output['status_code'], 1)\n\n    def test_adding_all_stamps_with_infinate_loop_eats_all_balance(self):\n        self.d.set('con_currency.balances:stu', 500)\n        self.d.commit()\n\n        prior_balance = self.d.get('con_currency.balances:stu')\n\n        prior_balance *= STAMPS_PER_TAU\n\n        inf_loop_path = os.path.join(os.path.dirname(__file__), \"test_contracts\", \"inf_loop.s.py\")\n\n        res = self.e.execute(\n            **TEST_SUBMISSION_KWARGS,\n            kwargs=submission_kwargs_for_file(inf_loop_path),\n            stamps=prior_balance,\n            \n            metering=True, auto_commit=True\n        )\n\n        new_balance = self.d.get('con_currency.balances:stu')\n\n        # Not all stamps will be deducted because it will blow up in the middle of execution\n\n        self.assertTrue(new_balance < 500)\n\n    def test_submitting_contract_succeeds_with_enough_stamps(self):\n        prior_balance = self.d.get('con_currency.balances:stu')\n\n        print(prior_balance)\n\n        erc20_clone_path = os.path.join(os.path.dirname(__file__), \"test_contracts\", \"erc20_clone.s.py\")\n        output = self.e.execute(**TEST_SUBMISSION_KWARGS,\n                                                kwargs=submission_kwargs_for_file(erc20_clone_path), auto_commit=True\n                                                )\n        print(output)\n\n        new_balance = self.d.get('con_currency.balances:stu')\n\n        print(new_balance)\n\n        self.assertEqual(float(prior_balance - new_balance), output['stamps_used'] / STAMPS_PER_TAU)\n\n    def test_pending_writes_has_deducted_stamp_amount_prior_to_auto_commit(self):\n        prior_balance = self.d.get('con_currency.balances:stu')\n\n        erc20_clone_path = os.path.join(os.path.dirname(__file__), \"test_contracts\", \"erc20_clone.s.py\")\n        output = self.e.execute(**TEST_SUBMISSION_KWARGS,\n                                kwargs=submission_kwargs_for_file(erc20_clone_path), auto_commit=False\n                                )\n        self.assertNotEquals(self.e.driver.pending_writes['con_currency.balances:stu'], prior_balance)\n\n"
  },
  {
    "path": "tests/performance/__init__.py",
    "content": ""
  },
  {
    "path": "tests/performance/prof_transfer.py",
    "content": "import secrets\nfrom contracting.storage.driver import Driver\nfrom contracting.execution.executor import Executor\n\ndef submission_kwargs_for_file(f):\n    # Get the file name only by splitting off directories\n    split = f.split('/')\n    split = split[-1]\n\n    # Now split off the .s\n    split = split.split('.')\n    contract_name = split[0]\n\n    with open(f) as file:\n        contract_code = file.read()\n\n    return {\n        'name': contract_name,\n        'code': contract_code,\n    }\n\n\nTEST_SUBMISSION_KWARGS = {\n    'sender': 'stu',\n    'contract_name': 'submission',\n    'function_name': 'submit_contract'\n}\n\n\nd = Driver()\nd.flush_full()\n\nwith open('../../contracting/contracts/submission.s.py') as f:\n    contract = f.read()\n\nd.set_contract(name='submission',\n                    code=contract)\nd.commit()\n\nrecipients = [secrets.token_hex(16) for _ in range(1000)]\n\n\ne = Executor()\n\ne.execute(**TEST_SUBMISSION_KWARGS,\n          kwargs=submission_kwargs_for_file('../integration/test_contracts/erc20_clone.s.py'))\n\n\nimport datetime\n\nfor i in range(20):\n    now = datetime.datetime.now()\n\n    # profiler = Profiler()\n    # profiler.start()\n    for r in recipients:\n        res = e.execute(sender='stu',\n                  contract_name='con_erc20_clone',\n                  function_name='transfer',\n                  kwargs={\n                      'amount': 1,\n                      'to': r\n                  })\n        print(res)\n\n    # profiler.stop()\n\n    print(datetime.datetime.now() - now)\n\nd.flush_full()\n\n# print(profiler.last_session.duration)\n# print(profiler.output_text(unicode=True, color=True, show_all=True))\n\n"
  },
  {
    "path": "tests/performance/test_contracts/__init__.py",
    "content": ""
  },
  {
    "path": "tests/performance/test_contracts/erc20_clone.s.py",
    "content": "supply = Variable()\nbalances = Hash(default_value=0)\n\n@construct\ndef seed():\n    balances['stu'] = 1000000\n    balances['colin'] = 100\n    supply.set(balances['stu'] + balances['colin'])\n\n@export\ndef transfer(amount: int, to: str):\n    sender = ctx.caller\n    assert balances[sender] >= amount, 'Not enough coins to send!'\n\n    balances[sender] -= amount\n    balances[to] += amount\n\n@export\ndef balance_of(account: str):\n    return balances[account]\n\n@export\ndef total_supply():\n    return supply.get()\n\n@export\ndef allowance(owner: str, spender: str):\n    return balances[owner, spender]\n\n@export\ndef approve(amount: str, to: str):\n    sender = ctx.caller\n    balances[sender, to] += amount\n    return balances[sender, to]\n\n@export\ndef transfer_from(amount: int, to: str, main_account: str):\n    sender = ctx.caller\n\n    assert balances[main_account, sender] >= amount, 'Not enough coins approved to send! You have {} and are trying to spend {}'\\\n        .format(balances[main_account, sender], amount)\n    assert balances[main_account] >= amount, 'Not enough coins to send!'\n\n    balances[main_account, sender] -= amount\n    balances[main_account] -= amount\n\n    balances[to] += amount\n"
  },
  {
    "path": "tests/performance/test_contracts/modules/all_in_one.s.py",
    "content": "@export\ndef call_me():\n    return call_me_again()\n\n@export\ndef call_me_again():\n    return call_me_again_again()\n\n@export\ndef call_me_again_again():\n    return {\n        'owner': ctx.owner,\n        'this': ctx.this,\n        'signer': ctx.signer,\n        'caller': ctx.caller\n    }\n"
  },
  {
    "path": "tests/performance/test_contracts/modules/dynamic_import.s.py",
    "content": "@export\ndef called_from_a_far():\n    m = importlib.import_module('all_in_one')\n    return m.call_me_again_again()\n\n@export\ndef called_from_a_far_stacked():\n    m = importlib.import_module('all_in_one')\n    return m.call()"
  },
  {
    "path": "tests/performance/test_contracts/modules/module1.s.py",
    "content": "'''\nhow the modules import each other. this is to test ctx.caller etc\n\n   1\n |   |\n 2   3\n| | | |\n4 5 6 7\n  |\n  8\n\n'''\n\nimport module2\nimport module3\n\n\n@export\ndef get_context():\n    return {\n        'owner': ctx.owner,\n        'this': ctx.this,\n        'signer': ctx.signer,\n        'caller': ctx.caller\n    }\n"
  },
  {
    "path": "tests/performance/test_contracts/modules/module2.s.py",
    "content": "import module4\nimport module5\n\n@export\ndef get_context():\n    return {\n        'owner': ctx.owner,\n        'this': ctx.this,\n        'signer': ctx.signer,\n        'caller': ctx.caller\n    }\n"
  },
  {
    "path": "tests/performance/test_contracts/modules/module3.s.py",
    "content": "import module6\nimport module7\n\n@export\ndef get_context():\n    return {\n        'owner': ctx.owner,\n        'this': ctx.this,\n        'signer': ctx.signer,\n        'caller': ctx.caller\n    }\n"
  },
  {
    "path": "tests/performance/test_contracts/modules/module4.s.py",
    "content": "@export\ndef get_context():\n    return {\n        'owner': ctx.owner,\n        'this': ctx.this,\n        'signer': ctx.signer,\n        'caller': ctx.caller\n    }\n"
  },
  {
    "path": "tests/performance/test_contracts/modules/module5.s.py",
    "content": "import module8\n\n@export\ndef get_context():\n    return {\n        'owner': ctx.owner,\n        'this': ctx.this,\n        'signer': ctx.signer,\n        'caller': ctx.caller\n    }\n"
  },
  {
    "path": "tests/performance/test_contracts/modules/module6.s.py",
    "content": "@export\ndef get_context():\n    return {\n        'owner': ctx.owner,\n        'this': ctx.this,\n        'signer': ctx.signer,\n        'caller': ctx.caller\n    }\n"
  },
  {
    "path": "tests/performance/test_contracts/modules/module7.s.py",
    "content": "@export\ndef get_context():\n    return {\n        'owner': ctx.owner,\n        'this': ctx.this,\n        'signer': ctx.signer,\n        'caller': ctx.caller\n    }\n"
  },
  {
    "path": "tests/performance/test_contracts/modules/module8.s.py",
    "content": "@export\ndef get_context():\n    return {\n        'owner': ctx.owner,\n        'this': ctx.this,\n        'signer': ctx.signer,\n        'caller': ctx.caller\n    }\n"
  },
  {
    "path": "tests/performance/test_contracts/submission.s.py",
    "content": "@__export('submission')\ndef submit_contract(name: str, code: str, owner: Any=None, constructor_args: dict={}):\n    if ctx.caller != 'sys':\n        assert name.startswith('con_'), 'Contract must start with con_!'\n\n    assert ctx.caller == ctx.signer, 'Contract cannot be called from another contract!'\n    assert len(name) <= 64, 'Contract name length exceeds 64 characters!'\n    assert name.islower(), 'Contract name must be lowercase!'\n\n    __Contract().submit(\n        name=name,\n        code=code,\n        owner=owner,\n        constructor_args=constructor_args,\n        developer=ctx.caller\n    )\n\n\n@__export('submission')\ndef change_developer(contract: str, new_developer: str):\n    d = __Contract()._driver.get_var(contract=contract, variable='__developer__')\n    assert ctx.caller == d, 'Sender is not current developer!'\n\n    __Contract()._driver.set_var(\n        contract=contract,\n        variable='__developer__',\n        value=new_developer\n    )\n"
  },
  {
    "path": "tests/performance/test_transfer.py",
    "content": "from unittest import TestCase\nimport secrets\nfrom contracting.storage.driver import Driver\nfrom contracting.execution.executor import Executor\nimport os\n\ndef submission_kwargs_for_file(f):\n    # Get the file name only by splitting off directories\n    split = f.split('/')\n    split = split[-1]\n\n    # Now split off the .s\n    split = split.split('.')\n    contract_name = split[0]\n\n    with open(f) as file:\n        contract_code = file.read()\n\n    return {\n        'name': f'con_{contract_name}',\n        'code': contract_code,\n    }\n\n\nTEST_SUBMISSION_KWARGS = {\n    'sender': 'stu',\n    'contract_name': 'submission',\n    'function_name': 'submit_contract'\n}\n\n\nclass TestSandbox(TestCase):\n    def setUp(self):\n        self.d = Driver()\n        self.d.flush_full()\n\n        self.script_dir = os.path.dirname(os.path.abspath(__file__))\n\n        submission_path = os.path.join(self.script_dir, \"test_contracts\", \"submission.s.py\")\n        with open(submission_path) as f:\n            contract = f.read()\n\n        self.d.set_contract(name='submission',\n                            code=contract)\n        self.d.commit()\n\n        self.recipients = [secrets.token_hex(16) for _ in range(10000)]\n\n    def tearDown(self):\n        self.d.flush_full()\n\n    def test_transfer_performance(self):\n        e = Executor()\n\n        e.execute(**TEST_SUBMISSION_KWARGS,\n                  kwargs=submission_kwargs_for_file(os.path.join(self.script_dir, \"test_contracts\", \"erc20_clone.s.py\")))\n\n        for r in self.recipients:\n            e.execute(sender='stu',\n                      contract_name='con_erc20_clone',\n                      function_name='transfer',\n                      kwargs={\n                          'amount': 1,\n                          'to': r\n                      })"
  },
  {
    "path": "tests/security/__init__.py",
    "content": ""
  },
  {
    "path": "tests/security/contracts/builtin_hack_token.s.py",
    "content": "balances = Hash(default_value=0)\n\n@construct\ndef seed():\n    setattr(balances, '_key', 'erc20.balances')\n    balances['stu'] = 99999999999999999\n\n@export\ndef blah():\n    return 1"
  },
  {
    "path": "tests/security/contracts/call_infinate_loop.s.py",
    "content": "import con_infinate_loop\n\n@export\ndef call():\n    con_infinate_loop.loop()"
  },
  {
    "path": "tests/security/contracts/con_inf_writes.s.py",
    "content": "hhash = Hash(default_value=0)\n\n@construct\ndef seed():\n    hashed_data = 'woohoo'\n    while True:\n        hashed_data = hashlib.sha3(hashed_data)\n        hhash[hashed_data] = 'a'\n\n@export\ndef dummy():\n    return 0"
  },
  {
    "path": "tests/security/contracts/constructor_infinate_loop.s.py",
    "content": "@construct\ndef seed():\n    i = 0\n    while True:\n        i += 1\n\n@export\ndef dummy():\n    return 0"
  },
  {
    "path": "tests/security/contracts/double_spend_gas_attack.s.py",
    "content": "import con_erc20\n\n@construct\ndef seed():\n    pass\n\n@export\ndef double_spend(receiver: str):\n    allowance = con_erc20.allowance(owner=ctx.caller, spender=ctx.this)\n    con_erc20.transfer_from(amount=allowance, to=receiver, main_account=ctx.caller)\n\n    i = 0\n    while True:\n        i += 1\n"
  },
  {
    "path": "tests/security/contracts/erc20_clone.s.py",
    "content": "supply = Variable()\nbalances = Hash(default_value=0)\n\n@construct\ndef seed():\n    balances['stu'] = 1000000\n    balances['colin'] = 100\n    supply.set(balances['stu'] + balances['colin'])\n\n@export\ndef transfer(amount: int, to: str):\n    sender = ctx.caller\n    assert balances[sender] >= amount, 'Not enough coins to send!'\n\n    balances[sender] -= amount\n    balances[to] += amount\n\n@export\ndef balance_of(account: str):\n    return balances[account]\n\n@export\ndef total_supply():\n    return supply.get()\n\n@export\ndef allowance(owner: str, spender: str):\n    return balances[owner, spender]\n\n@export\ndef approve(amount: str, to: str):\n    sender = ctx.caller\n    balances[sender, to] += amount\n    return balances[sender, to]\n\n@export\ndef transfer_from(amount: int, to: str, main_account: str):\n    sender = ctx.caller\n\n    assert balances[main_account, sender] >= amount, 'Not enough coins approved to send! You have {} and are trying to spend {}'\\\n        .format(balances[main_account, sender], amount)\n    assert balances[main_account] >= amount, 'Not enough coins to send!'\n\n    balances[main_account, sender] -= amount\n    balances[main_account] -= amount\n\n    balances[to] += amount\n"
  },
  {
    "path": "tests/security/contracts/get_set_driver.py",
    "content": "import erc20\ndriver = erc20.rt.env.get('__Driver')\n\n@construct\ndef seed():\n    driver.set(\n        key='erc20.balances:stu',\n        value=1\n    )\n\n@export\ndef dummy():\n    pass\n"
  },
  {
    "path": "tests/security/contracts/get_set_driver_2.py",
    "content": "import erc20\nz = erc20.rt\ndriver = z.env.get('__Driver')\n\n@construct\ndef seed():\n    driver.set(\n        key='erc20.balances:stu',\n        value=1\n    )\n\n@export\ndef dummy():\n    pass\n"
  },
  {
    "path": "tests/security/contracts/hack_tokens.s.py",
    "content": "balances = Hash(default_value=0)\n\n@construct\ndef seed():\n    balances.key = 'con_erc20.balances'\n    balances['stu'] = 99999999999999999\n\n@export\ndef blah():\n    return 1"
  },
  {
    "path": "tests/security/contracts/import_hash_from_contract.s.py",
    "content": "import erc20\n\n@construct\ndef seed():\n    erc20.balances['stu'] = 999999999999\n\n@export\ndef dummy():\n    return 0"
  },
  {
    "path": "tests/security/contracts/infinate_loop.s.py",
    "content": "@export\ndef loop():\n    i = 0\n    while True:\n        i += 1\n\n@export\ndef eat_stamps():\n    while True:\n        pass"
  },
  {
    "path": "tests/security/contracts/submission.s.py",
    "content": "@__export('submission')\ndef submit_contract(name: str, code: str, owner: Any=None, constructor_args: dict={}):\n    if ctx.caller != 'sys':\n        assert name.startswith('con_'), 'Contract must start with con_!'\n\n    assert ctx.caller == ctx.signer, 'Contract cannot be called from another contract!'\n    assert len(name) <= 64, 'Contract name length exceeds 64 characters!'\n    assert name.islower(), 'Contract name must be lowercase!'\n\n    __Contract().submit(\n        name=name,\n        code=code,\n        owner=owner,\n        constructor_args=constructor_args,\n        developer=ctx.caller\n    )\n\n\n@__export('submission')\ndef change_developer(contract: str, new_developer: str):\n    d = __Contract()._driver.get_var(contract=contract, variable='__developer__')\n    assert ctx.caller == d, 'Sender is not current developer!'\n\n    __Contract()._driver.set_var(\n        contract=contract,\n        variable='__developer__',\n        value=new_developer\n    )\n"
  },
  {
    "path": "tests/security/test_erc20_token_hacks.py",
    "content": "from unittest import TestCase\nfrom contracting.client import ContractingClient\nimport os\nclass TestTokenHacks(TestCase):\n    def setUp(self):\n        self.c = ContractingClient(signer='stu')\n        self.c.raw_driver.flush_full()\n        \n\n        self.script_dir = os.path.dirname(os.path.abspath(__file__))\n        submission_path = os.path.join(self.script_dir, \"contracts\", \"submission.s.py\")\n        with open(submission_path) as f:\n            contract = f.read()\n\n        self.c.raw_driver.set_contract(name='submission', code=contract)\n\n        self.c.raw_driver.commit()\n\n        self.c.executor.currency_contract = 'con_erc20'\n        self.c.signer = 'stu'\n\n        # submit erc20 clone\n        with open(os.path.join(self.script_dir, \"contracts\", \"erc20_clone.s.py\")) as f:\n            code = f.read()\n            self.c.submit(code, name='con_erc20', metering=False)\n\n        self.c.executor.metering = True\n\n    def tearDown(self):\n        self.c.raw_driver.flush_full()\n\n    def test_orm_rename_hack(self):\n        # This hack renames the contract property on its own balances hash to modify the erc20 balances\n\n        token = self.c.get_contract('con_erc20')\n\n        pre_hack_balance = self.c.raw_driver.get_var('con_erc20', \"balances\", arguments=[\"stu\"])\n\n        with open(os.path.join(self.script_dir, \"contracts\", \"hack_tokens.s.py\")) as f:\n            code = f.read()\n            self.c.submit(code, name='con_token_hack', signer=\"stu\")\n\n        post_hack_balance = self.c.raw_driver.get_var('con_erc20', \"balances\", arguments=[\"stu\"])\n\n        # Assert greater because some of the balance is lost to stamps\n        self.assertGreater(pre_hack_balance, post_hack_balance)\n\n    def test_orm_setattr_hack(self):\n        # This hack uses setattr instead of direct property access to do the same thing as above\n\n        token = self.c.get_contract('con_erc20')\n\n        pre_hack_balance = self.c.raw_driver.get_var('con_erc20', \"balances\", arguments=[\"stu\"])\n\n        with self.assertRaises(Exception):\n            with open(os.path.join(self.script_dir, \"contracts\", \"builtin_hack_token.s.py\")) as f:\n                code = f.read()\n                self.c.submit(code, name='token_hack')\n\n            post_hack_balance = self.c.raw_driver.get_var('con_erc20', \"balances\", arguments=[\"stu\"])\n\n            # The balance *should not* change between these tests!\n            self.assertEqual(pre_hack_balance, post_hack_balance)\n\n    def test_double_spend_if_stamps_run_out(self):\n        token = self.c.get_contract('con_erc20')\n\n        pre_hack_balance_stu = float(str(self.c.get_var('con_erc20', \"balances\", arguments=[\"stu\"])))\n        pre_hack_balance_colin = float(str(self.c.get_var('con_erc20', \"balances\", arguments=[\"colin\"])))\n\n        # Approve the \"hack\" contract to spend stu's tokens\n        tx_amount=10000\n        token.approve(amount=tx_amount, to='con_hack', stamps=200)\n        with open(os.path.join(self.script_dir, \"contracts\", \"double_spend_gas_attack.s.py\")) as f:\n            code = f.read()\n            self.c.submit(code, name='con_hack', metering=True)\n        # Test the double_spend contract\n        # - sends the amount of the \"allowance\" (set in token.approve as 'tx_amount')\n        # - calls transfer_from to send from 'stu' to 'colin' as 'con_hack'\n        con_hack = self.c.get_contract('con_hack')\n        self.c.raw_driver.commit()\n        with self.assertRaises(AssertionError):\n            # breakpoint()\n            # Should fail when stamp_limit of 200 is reached\n            con_hack.double_spend(receiver='colin', stamps=200)\n\n        # Since the above call failed, the balance should be the same as before and NOT balance + tx_amount\n\n        post_hack_balance_stu = float(str(self.c.get_var('con_erc20', \"balances\", arguments=[\"stu\"])))\n        post_hack_balance_colin = float(str(self.c.get_var('con_erc20', \"balances\", arguments=[\"colin\"])))\n        # Contracting will revert the state if the stamps run out and the transaction fails, which previously was not the case\n\n        # Stu's POST balance should be less than the pre balance (less the tx_amount) because stamps were also deducted\n        self.assertLess(post_hack_balance_stu, pre_hack_balance_stu + tx_amount)\n\n        # Colin's balance will not change because the transaction failed and the state was not updated\n        # Assert greater because some of the balance is lost to stamps\n        self.assertEqual(pre_hack_balance_colin, post_hack_balance_colin)\n\n\n    def test_stamp_fails_when_calling_infinate_loop_from_another_contract(self):\n        with open(os.path.join(self.script_dir, \"contracts\", \"infinate_loop.s.py\")) as f:\n            code = f.read()\n            self.c.submit(code, name='con_infinate_loop')\n\n        with open(os.path.join(self.script_dir, \"contracts\", \"call_infinate_loop.s.py\")) as f:\n            code = f.read()\n            self.c.submit(code, name='con_call_infinate_loop', metering=True)\n\n        loop = self.c.get_contract('con_call_infinate_loop')\n\n        with self.assertRaises(AssertionError):\n            loop.call()\n\n    def test_constructor_with_infinate_loop_fails(self):\n        with self.assertRaises(AssertionError):\n            with open(os.path.join(self.script_dir, \"contracts\", \"constructor_infinate_loop.s.py\")) as f:\n                code = f.read()\n                self.c.submit(code, name='con_constructor_infinate_loop', metering=True)\n\n    def test_infinate_loop_of_writes_undos_everything(self):\n        with self.assertRaises(AssertionError):\n            with open(os.path.join(self.script_dir, \"contracts\", \"con_inf_writes.s.py\")) as f:\n                code = f.read()\n                self.c.submit(code, name='con_inf_writes', metering=True)\n\n    def test_accessing_variable_on_another_contract(self):\n        token = self.c.get_contract('con_erc20')\n\n        pre_hack_balance_stu = self.c.raw_driver.get_var('con_erc20', \"balances\", arguments=[\"stu\"])\n\n        try:\n            with open(os.path.join(self.script_dir, \"contracts\", \"import_hash_from_contract.s.py\")) as f:\n                code = f.read()\n                self.c.submit(code, name='import_hash_from_contract', metering=False)\n        except:\n            pass\n\n        post_hack_balance_stu = self.c.raw_driver.get_var('con_erc20', \"balances\", arguments=[\"stu\"])\n\n        self.assertEqual(pre_hack_balance_stu, post_hack_balance_stu)\n\n    def test_get_set_driver(self):\n        # This hack uses setattr instead of direct property access to do the same thing as above\n\n        token = self.c.get_contract('con_erc20')\n        pre_hack_balance = self.c.raw_driver.get_var('con_erc20', \"balances\", arguments=[\"stu\"])\n\n        #with self.assertRaises(Exception):\n        try:\n            with open(os.path.join(self.script_dir, \"contracts\", \"get_set_driver.py\")) as f:\n                code = f.read()\n                self.c.submit(code, name='token_hack', metering=False)\n        except Exception as err:\n            print(err)\n            pass\n\n        post_hack_balance = self.c.raw_driver.get_var('con_erc20', \"balances\", arguments=[\"stu\"])\n\n        print()\n        print(post_hack_balance)\n\n        # The balance *should not* change between these tests!\n        self.assertEqual(pre_hack_balance, post_hack_balance)\n\n    def test_get_set_driver_2(self):\n        # This hack uses setattr instead of direct property access to do the same thing as above\n\n        token = self.c.get_contract('con_erc20')\n        pre_hack_balance = self.c.raw_driver.get_var('con_erc20', \"balances\", arguments=[\"stu\"])\n\n        #with self.assertRaises(Exception):\n        try:\n            with open(os.path.join(self.script_dir, \"contracts\", \"get_set_driver_2.py\")) as f:\n                code = f.read()\n                self.c.submit(code, name='token_hack', metering=False)\n        except Exception as err:\n            print(err)\n            pass\n\n        post_hack_balance = self.c.raw_driver.get_var('con_erc20', \"balances\", arguments=[\"stu\"])\n\n        print()\n        print(post_hack_balance)\n\n        # The balance *should not* change between these tests!\n        self.assertEqual(pre_hack_balance, post_hack_balance)"
  },
  {
    "path": "tests/unit/__init__.py",
    "content": ""
  },
  {
    "path": "tests/unit/contracts/currency.s.py",
    "content": "balances = Hash()\n\n@construct\ndef seed():\n    balances['stu'] = 1000000\n    balances['colin'] = 100\n\n@export\ndef transfer(amount: int, to: str):\n    sender = ctx.signer\n    assert balances[sender] >= amount, 'Not enough coins to send!'\n\n    balances[sender] -= amount\n\n    if balances[to] is None:\n        balances[to] = amount\n    else:\n        balances[to] += amount\n\n@export\ndef balance(account: str):\n    return balances[account]\n"
  },
  {
    "path": "tests/unit/contracts/exception.s.py",
    "content": "balances = Hash(default_value=0)\n\n@construct\ndef seed():\n    balances['stu'] = 999\n    balances['colin'] = 555\n\n@export\ndef transfer(amount: int, to: str):\n    sender = ctx.caller\n    assert balances[sender] >= amount, 'Not enough coins to send!'\n\n    balances[sender] -= amount\n    balances[to] += amount\n\n    raise Exception('This is an exception')\n\n@export\ndef balance_of(account: str):\n    return balances[account]"
  },
  {
    "path": "tests/unit/contracts/proxythis.py",
    "content": "@export\r\ndef proxythis(con: str):\r\n    return importlib.import_module(con).getthis()\r\n\r\n@export\r\ndef nestedproxythis(con: str):\r\n    return importlib.import_module(con).nested_exported()\r\n\r\n@export\r\ndef noproxy():\r\n    return ctx.this, ctx.caller"
  },
  {
    "path": "tests/unit/contracts/submission.s.py",
    "content": "@__export('submission')\ndef submit_contract(name: str, code: str, owner: Any=None, constructor_args: dict={}):\n    if ctx.caller != 'sys':\n        assert name.startswith('con_'), 'Contract must start with con_!'\n\n    assert ctx.caller == ctx.signer, 'Contract cannot be called from another contract!'\n    assert len(name) <= 64, 'Contract name length exceeds 64 characters!'\n    assert name.islower(), 'Contract name must be lowercase!'\n\n    __Contract().submit(\n        name=name,\n        code=code,\n        owner=owner,\n        constructor_args=constructor_args,\n        developer=ctx.caller\n    )\n\n\n@__export('submission')\ndef change_developer(contract: str, new_developer: str):\n    d = __Contract()._driver.get_var(contract=contract, variable='__developer__')\n    assert ctx.caller == d, 'Sender is not current developer!'\n\n    __Contract()._driver.set_var(\n        contract=contract,\n        variable='__developer__',\n        value=new_developer\n    )\n"
  },
  {
    "path": "tests/unit/contracts/thistest2.py",
    "content": "@export\r\ndef exported():\r\n    return ctx.this, ctx.caller\r\n\r\n@export\r\ndef getthis():\r\n    return ctx.this, ctx.caller\r\n\r\n@export\r\ndef nested_exported():\r\n    return exported()\r\n"
  },
  {
    "path": "tests/unit/loop_client_test.sh",
    "content": "#!/usr/bin/env bash\ncount=0\nwhile :\ndo\n\toutput=$(python test_client.py TestSenecaClient.test_update_master_db_with_incomplete_sb 2>&1 >/dev/null)\n\tif [[ $output == *\"FAIL:\"* ]]; then\n\t\techo \"FAILURE!!\"\n\t\techo \"$output\"\n\t\tbreak\n\telse\n\t\tcount=$((count+1))\n\t\techo \"Test passed (succ #$count)\"\n\tfi\ndone\n\n"
  },
  {
    "path": "tests/unit/precompiled/__init__.py",
    "content": ""
  },
  {
    "path": "tests/unit/precompiled/compiled_token.py",
    "content": "# Monkey patch for testing, as this is purely for 'interface enforcement' testing\nfrom contracting.storage.orm import Variable, Hash\n\nclass ctx:\n    caller = 1\n\n__supply = Variable(contract='__main__', name='supply')\n__balances = Hash(default_value=0, contract='__main__', name='balances')\n\n\ndef ____():\n    __balances['stu'] = 1000000\n    __balances['colin'] = 100\n    __supply.set(__balances['stu'] + __balances['colin'])\n\ndef transfer(amount, to):\n    sender = ctx.caller\n    assert __balances[sender] >= amount, 'Not enough coins to send!'\n    __balances[sender] -= amount\n    __balances[to] += amount\n\ndef balance_of(account):\n    return __balances[account]\n\ndef total_supply():\n    return __supply.get()\n\ndef allowance(owner, spender):\n    return __balances[owner, spender]\n\ndef approve(amount, to):\n    sender = ctx.caller\n    __balances[sender, to] += amount\n    return __balances[sender, to]\n\ndef transfer_from(amount, to, main_account):\n    sender = ctx.caller\n    assert __balances[main_account, sender\n        ] >= amount, 'Not enough coins approved to send! You have {} and are trying to spend {}'.format(\n        __balances[main_account, sender], amount)\n    assert __balances[main_account] >= amount, 'Not enough coins to send!'\n    __balances[main_account, sender] -= amount\n    __balances[main_account] -= amount\n    __balances[to] += amount\n\ndef __private_func():\n    return 5"
  },
  {
    "path": "tests/unit/precompiled/updated_submission.py",
    "content": "@__export('submission')\ndef submit_contract(name: str, code: str, owner: Any=None, constructor_args: dict={}):\n    if ctx.caller != 'sys':\n        assert name.startswith('con_'), 'Contract must start with con_!'\n\n    assert ctx.caller == ctx.signer, 'Contract cannot be called from another contract!'\n    assert len(name) <= 64, 'Contract name length exceeds 64 characters!'\n    assert name.islower(), 'Contract name must be lowercase!'\n\n    __Contract().submit(\n        name=name,\n        code=code,\n        owner=owner,\n        constructor_args=constructor_args,\n        developer=ctx.caller\n    )\n\n\n@__export('submission')\ndef change_developer(contract: str, new_developer: str):\n    d = __Contract()._driver.get_var(contract=contract, variable='__developer__')\n    assert ctx.caller == d, 'Sender is not current developer !!!!!!!!'\n\n    __Contract()._driver.set_var(\n        contract=contract,\n        variable='__developer__',\n        value=new_developer\n    )\n"
  },
  {
    "path": "tests/unit/test_client.py",
    "content": "from unittest import TestCase\nfrom contracting.client import ContractingClient\nfrom contracting.storage.driver import Driver\nimport os\nfrom pathlib import Path\n\nclass TestClient(TestCase):\n    def setUp(self):\n        self.client = None\n\n        self.driver = Driver()\n        \n        self.script_dir = os.path.dirname(os.path.abspath(__file__))\n\n        submission_file_path = os.path.join(self.script_dir, \"contracts\", \"submission.s.py\")\n        with open(submission_file_path) as f:\n            self.submission_contract_file = f.read()\n\n    def tearDown(self):\n        if self.client:\n            self.client.flush()\n\n    def test_set_submission_updates_contract_file(self):\n        self.client = ContractingClient(driver=self.driver)\n        self.client.flush()\n\n        submission_1_code = self.client.raw_driver.get('submission.__code__')\n        \n        self.script_dir = os.path.dirname(os.path.abspath(__file__))\n        submission_file_path = os.path.join(self.script_dir, \"precompiled\", \"updated_submission.py\")\n        \n        self.driver.flush_full()\n        self.client.set_submission_contract(filename=submission_file_path)\n\n        submission_2_code = self.client.raw_driver.get('submission.__code__')\n\n        self.assertNotEqual(submission_1_code, submission_2_code)\n\n    def test_can_create_instance_without_submission_contract(self):\n        self.client = ContractingClient(submission_filename=None, driver=self.driver)\n\n        self.assertIsNotNone(self.client)\n\n\n    def test_gets_submission_contract_from_state_if_no_filename_provided(self):\n        self.driver.set_contract(name='submission', code=self.submission_contract_file)\n        self.driver.commit()\n\n        self.client = ContractingClient(submission_filename=None, driver=self.driver)\n\n        self.assertIsNotNone(self.client.submission_contract)\n\n    def test_set_submission_contract__sets_from_submission_filename_property(self):\n        self.client = ContractingClient(driver=self.driver)\n\n        self.client.raw_driver.flush_full()\n        self.client.submission_contract = None\n\n        contract = self.client.raw_driver.get_contract('submission')\n        self.assertIsNone(contract)\n        self.assertIsNone(self.client.submission_contract)\n\n        self.client.set_submission_contract()\n\n        contract = self.client.raw_driver.get_contract('submission')\n        self.assertIsNotNone(contract)\n        self.assertIsNotNone(self.client.submission_contract)\n\n    def test_set_submission_contract__sets_from_submission_from_state(self):\n        self.client = ContractingClient(driver=self.driver)\n\n        self.client.raw_driver.flush_full()\n        self.client.submission_contract = None\n\n        contract = self.client.raw_driver.get_contract('submission')\n        self.assertIsNone(contract)\n        self.assertIsNone(self.client.submission_contract)\n\n        self.driver.set_contract(name='submission', code=self.submission_contract_file)\n        self.driver.commit()\n\n        self.client.set_submission_contract()\n\n        contract = self.client.raw_driver.get_contract('submission')\n        self.assertIsNotNone(contract)\n        self.assertIsNotNone(self.client.submission_contract)\n\n    def test_set_submission_contract__no_contract_provided_or_found_raises_AssertionError(self):\n        self.client = ContractingClient(driver=self.driver)\n\n        self.client.raw_driver.flush_full()\n        self.client.submission_filename = None\n\n        with self.assertRaises(AssertionError):\n            self.client.set_submission_contract()\n\n    def test_submit__raises_AssertionError_if_no_submission_contract_set(self):\n        self.client = ContractingClient(submission_filename=None, driver=self.driver)\n\n        with self.assertRaises(AssertionError):\n            self.client.submit(f=\"\")\n\n\n"
  },
  {
    "path": "tests/unit/test_client_keys_prefix.py",
    "content": "import unittest\nfrom contracting.client import ContractingClient\n\n\nclass TestClientKeysPrefix(unittest.TestCase):\n\n    def setUp(self):\n        self.client = ContractingClient()\n        self.client.flush()\n\n        # Submit two dummy contracts with similar prefixes\n        code_a = \"\"\"\n@export\ndef f():\n    pass\n\"\"\"\n        code_b = code_a\n        self.client.submit(code_a, name='abc')\n        self.client.submit(code_b, name='abc2')\n\n        # Write distinct state under each contract to detect leakage\n        self.client.set_var('abc', '__code__', value='X')\n        self.client.set_var('abc2', '__code__', value='Y')\n\n        # Also add a hash-like key for both\n        self.client.set_var('abc', 'h', arguments=['k'], value=1)\n        self.client.set_var('abc2', 'h', arguments=['k'], value=2)\n\n    def tearDown(self):\n        self.client.flush()\n\n    def test_keys_scoped_to_exact_contract(self):\n        abc = self.client.get_contract('abc')\n        keys = abc.keys()\n        # Ensure keys from abc2 are not present\n        self.assertTrue(all(not k.startswith('abc2.') for k in keys))\n\n\nif __name__ == '__main__':\n    unittest.main()\n\n\n"
  },
  {
    "path": "tests/unit/test_context_data_struct.py",
    "content": "from unittest import TestCase\nfrom contracting.execution.runtime import Context\n\n\nclass TestContext(TestCase):\n    def test_get_state(self):\n        c = Context(base_state={\n            'caller': 'stu',\n            'signer': 'stu',\n            'this': 'contract',\n            'owner': None\n        })\n\n        self.assertEqual(c._get_state(), c._base_state)\n\n    def test_get_state_after_added_state(self):\n        c = Context(base_state={\n            'caller': 'stu',\n            'signer': 'stu',\n            'this': 'contract',\n            'owner': None\n        })\n\n        new_state = {\n            'caller': 'stuart',\n            'signer': 'stuart',\n            'this': 'contracts',\n            'owner': 123\n        }\n\n        c._add_state(new_state)\n\n        self.assertEqual(c._get_state(), new_state)\n\n    def test_pop_state_doesnt_fail_if_none_added(self):\n        c = Context(base_state={\n            'caller': 'stu',\n            'signer': 'stu',\n            'this': 'contract',\n            'owner': None\n        })\n\n        c._pop_state()\n\n        self.assertEqual(c._get_state(), c._base_state)\n\n    def test_pop_state_removes_last_state(self):\n        c = Context(base_state={\n            'caller': 'stu',\n            'signer': 'stu',\n            'this': 'contract',\n            'owner': None\n        })\n\n        new_state = {\n            'caller': 'stuart',\n            'signer': 'stuart',\n            'this': 'contracts',\n            'owner': 123\n        }\n\n        c._add_state(new_state)\n\n        self.assertEqual(c._get_state(), new_state)\n\n        c._pop_state()\n\n        self.assertEqual(c._get_state(), c._base_state)\n\n    def test_add_state_doesnt_work_if_this_is_same(self):\n        c = Context(base_state={\n            'caller': 'stu',\n            'signer': 'stu',\n            'this': 'contract',\n            'owner': None\n        })\n\n        new_state = {\n            'caller': 'stuart',\n            'signer': 'stuart',\n            'this': 'contract',\n            'owner': 123\n        }\n\n        c._add_state(new_state)\n\n        self.assertEqual(c._get_state(), c._base_state)\n\n    def test_properties_read(self):\n        c = Context(base_state={\n            'caller': 'stu',\n            'signer': 'stu',\n            'this': 'contract',\n            'owner': None\n        })\n\n        self.assertEqual(c._base_state['this'], c.this)\n        self.assertEqual(c._base_state['caller'], c.caller)\n        self.assertEqual(c._base_state['signer'], c.signer)\n        self.assertEqual(c._base_state['owner'], c.owner)\n\n    def test_properties_cant_be_written(self):\n        c = Context(base_state={\n            'caller': 'stu',\n            'signer': 'stu',\n            'this': 'contract',\n            'owner': None\n        })\n\n        with self.assertRaises(Exception):\n            c.this = 1\n\n        with self.assertRaises(Exception):\n            c.caller = 1\n\n        with self.assertRaises(Exception):\n            c.signer = 1\n\n        with self.assertRaises(Exception):\n            c.owner = 1\n"
  },
  {
    "path": "tests/unit/test_datetime.py",
    "content": "from unittest import TestCase\nfrom contracting.stdlib.bridge.time import Datetime, Timedelta\nfrom datetime import datetime as dt\nfrom datetime import timedelta\n\n\nclass TestDatetime(TestCase):\n    def test_datetime_variables_set(self):\n        now = dt.now()\n\n        d = Datetime(now.year, now.month, now.day)\n\n        self.assertEqual(0, d.microsecond)\n        self.assertEqual(0, d.second)\n        self.assertEqual(0, d.minute)\n        self.assertEqual(0, d.hour)\n        self.assertEqual(now.day, d.day)\n        self.assertEqual(now.month, d.month)\n        self.assertEqual(now.year, d.year)\n\n    ###\n    # ==\n    ###\n    def test_datetime_eq_true(self):\n        now = dt.now()\n\n        d = Datetime(now.year, now.month, now.day)\n        e = Datetime(now.year, now.month, now.day)\n\n        self.assertTrue(d == e)\n\n    def test_datetime_eq_false(self):\n        now = dt.now()\n        d = Datetime(now.year, now.month, now.day)\n\n        then = now + timedelta(days=1)\n        e = Datetime(then.year, then.month, then.day)\n\n        self.assertFalse(d == e)\n\n    ###\n    # !=\n    ###\n    def test_datetime_ne_false(self):\n        now = dt.now()\n\n        d = Datetime(now.year, now.month, now.day)\n        e = Datetime(now.year, now.month, now.day)\n\n        self.assertFalse(d != e)\n\n    def test_datetime_ne_true(self):\n        now = dt.now()\n        d = Datetime(now.year, now.month, now.day)\n\n        then = now + timedelta(days=1)\n        e = Datetime(then.year, then.month, then.day)\n\n        self.assertTrue(d != e)\n\n    ###\n    # <\n    ###\n    def test_datetime_lt_true(self):\n        now = dt.now()\n        d = Datetime(now.year, now.month, now.day)\n\n        then = now + timedelta(days=1)\n        e = Datetime(then.year, then.month, then.day)\n\n        self.assertTrue(d < e)\n\n    def test_datetime_lt_false(self):\n        now = dt.now()\n        d = Datetime(now.year, now.month, now.day)\n\n        then = now + timedelta(days=1)\n        e = Datetime(then.year, then.month, then.day)\n\n        self.assertFalse(e < d)\n\n    ###\n    # >\n    ###\n    def test_datetime_gt_true(self):\n        now = dt.now()\n        d = Datetime(now.year, now.month, now.day)\n\n        then = now + timedelta(days=1)\n        e = Datetime(then.year, then.month, then.day)\n\n        self.assertTrue(e > d)\n\n    def test_datetime_gt_false(self):\n        now = dt.now()\n        d = Datetime(now.year, now.month, now.day)\n\n        then = now + timedelta(days=1)\n        e = Datetime(then.year, then.month, then.day)\n\n        self.assertFalse(d > e)\n\n    ###\n    # >=\n    ###\n    def test_datetime_ge_true_g(self):\n        now = dt.now()\n        d = Datetime(now.year, now.month, now.day)\n\n        then = now + timedelta(days=1)\n        e = Datetime(then.year, then.month, then.day)\n\n        self.assertTrue(e >= d)\n\n    def test_datetime_ge_true_eq(self):\n        now = dt.now()\n\n        d = Datetime(now.year, now.month, now.day)\n        e = Datetime(now.year, now.month, now.day)\n\n        self.assertTrue(d >= e)\n\n    def test_datetime_ge_false_g(self):\n        now = dt.now()\n        d = Datetime(now.year, now.month, now.day)\n\n        then = now + timedelta(days=1)\n        e = Datetime(then.year, then.month, then.day)\n\n        self.assertFalse(d >= e)\n\n    ###\n    # <=\n    ###\n    def test_datetime_le_true(self):\n        now = dt.now()\n        d = Datetime(now.year, now.month, now.day)\n\n        then = now + timedelta(days=1)\n        e = Datetime(then.year, then.month, then.day)\n\n        self.assertTrue(d <= e)\n\n    def test_datetime_le_true_eq(self):\n        now = dt.now()\n\n        d = Datetime(now.year, now.month, now.day)\n        e = Datetime(now.year, now.month, now.day)\n\n        self.assertTrue(d <= e)\n\n    def test_datetime_le_false(self):\n        now = dt.now()\n        d = Datetime(now.year, now.month, now.day)\n\n        then = now + timedelta(days=1)\n        e = Datetime(then.year, then.month, then.day)\n\n        self.assertFalse(e <= d)\n\n    def test_datetime_subtraction_to_proper_timedelta(self):\n        d = Datetime(2019, 1, 1)\n        e = Datetime(2018, 1, 1)\n\n        self.assertEqual((d - e), Timedelta(days=365))\n\n\n    def test_datetime_strptime(self):\n        d = dt(2019, 1, 1)\n        self.assertEqual(str(Datetime.strptime(str(d), '%Y-%m-%d %H:%M:%S')), str(d))\n\n    \n    def test_datetime_strptime_invalid_format(self):\n        d = dt(2019, 1, 1)\n        with self.assertRaises(ValueError):\n            Datetime.strptime(str(d), '%Y-%m-%d')\n\n    def test_datetime_strptime_invalid_date(self):\n        with self.assertRaises(ValueError):\n            Datetime.strptime('2019-02-30 12:00:00', '%Y-%m-%d %H:%M:%S')\n\n\n    def test_datetime_strptime_invalid_date_format(self):\n        with self.assertRaises(ValueError):\n            Datetime.strptime('2019-02-30 12:00:00', '%Y-%m-%d %H:%M:%S')\n\n\n    def test_datetime_returns_correct_datetime_cls(self):\n        d = dt(2019, 1, 1)\n        self.assertEqual(Datetime.strptime(str(d), '%Y-%m-%d %H:%M:%S'), Datetime(2019, 1, 1))\n\n"
  },
  {
    "path": "tests/unit/test_decimal.py",
    "content": "from decimal import Decimal\nimport decimal\nimport math\n\nfrom contracting.stdlib.bridge.decimal import ContractingDecimal, fix_precision, MAX_DECIMAL, neg_sci_not\nfrom unittest import TestCase\nimport unittest\n\n\nclass TestDecimal(TestCase):\n    def test_init(self):\n        ContractingDecimal('1.1')\n\n    def test_init_float(self):\n        ContractingDecimal(1.2)\n\n    def test_init_int(self):\n        ContractingDecimal(1)\n\n    def test_bool_true(self):\n        self.assertTrue(ContractingDecimal(1))\n\n    def test_bool_false(self):\n        self.assertFalse(ContractingDecimal(0))\n\n    def test_eq_whole_numbers(self):\n        self.assertEqual(ContractingDecimal(1), ContractingDecimal(1))\n\n    def test_eq_floats(self):\n        self.assertEqual(ContractingDecimal(1.234), ContractingDecimal(1.234))\n\n    def test_lt(self):\n        self.assertLess(ContractingDecimal(1), ContractingDecimal(2))\n        self.assertLess(ContractingDecimal(1.1), ContractingDecimal(2.2))\n\n    def test_lte(self):\n        self.assertLessEqual(ContractingDecimal(1), ContractingDecimal(2))\n        self.assertLessEqual(ContractingDecimal(1.1), ContractingDecimal(2.2))\n        self.assertLessEqual(ContractingDecimal(2.2), ContractingDecimal(2.2))\n\n    def test_gt(self):\n        self.assertGreater(ContractingDecimal(10), ContractingDecimal(2))\n        self.assertGreater(ContractingDecimal(10.1), ContractingDecimal(2.2))\n\n    def test_gte(self):\n        self.assertGreaterEqual(ContractingDecimal(10), ContractingDecimal(2))\n        self.assertGreaterEqual(ContractingDecimal(10.1), ContractingDecimal(2.2))\n        self.assertGreaterEqual(ContractingDecimal(2.2), ContractingDecimal(2.2))\n\n    def test_str(self):\n        f = ContractingDecimal(1.23445)\n        self.assertEqual(str(f), '1.23445')\n\n    def test_neg(self):\n        self.assertEqual(-ContractingDecimal(1), ContractingDecimal(-1))\n\n    def test_pos(self):\n        self.assertEqual(+ContractingDecimal(1), ContractingDecimal(1))\n\n    def test_other_equality(self):\n        self.assertEqual(ContractingDecimal(1), 1)\n        self.assertEqual(ContractingDecimal(1), 1.0)\n\n    def test_abs(self):\n        self.assertEqual(abs(ContractingDecimal(1)), 1)\n        self.assertEqual(abs(ContractingDecimal(-1)), 1)\n\n    def test_add(self):\n        self.assertEqual(ContractingDecimal(1) + ContractingDecimal(1), 2)\n        self.assertEqual(ContractingDecimal(1) + ContractingDecimal(10), 11)\n\n        self.assertEqual(ContractingDecimal(1.23456) + ContractingDecimal(6.54321), ContractingDecimal(7.77777))\n\n    def test_arbitrarily_large_number(self):\n        a = ContractingDecimal('38327950288419716939937510.582097494459230781640628620899')\n        b = ContractingDecimal('67523846748184676694051320.005681271452635608277857713427')\n        c = ContractingDecimal('105851797036604393633988830.587778765911866389918486334326')\n\n        self.assertEqual(a + b, c)\n\n    def test_zero_equality(self):\n        self.assertEqual(ContractingDecimal(0), 0)\n\n    def test_sub(self):\n        self.assertEqual(ContractingDecimal(1) - ContractingDecimal(1), 0)\n        self.assertEqual(ContractingDecimal(1) - ContractingDecimal(10), -9)\n\n        self.assertEqual(ContractingDecimal(1.23456) - ContractingDecimal(6.54321), ContractingDecimal(-5.30865))\n\n    def test_add_negs(self):\n        self.assertEqual(ContractingDecimal(1) + ContractingDecimal(-1), 0)\n\n    def test_radd(self):\n        self.assertEqual(1 + ContractingDecimal(1), 2)\n        self.assertEqual(1 + ContractingDecimal(10), 11)\n\n        self.assertEqual(1.23456 + ContractingDecimal(6.54321), ContractingDecimal(7.77777))\n\n    def test_rsub(self):\n        self.assertEqual(1 - ContractingDecimal(1), 0)\n        self.assertEqual(1 - ContractingDecimal(10), -9)\n\n        self.assertEqual(1.23456 - ContractingDecimal(6.54321), ContractingDecimal(-5.30865))\n\n    def test_mul(self):\n        self.assertEqual(ContractingDecimal(5) * ContractingDecimal(42), 210)\n        self.assertEqual(ContractingDecimal(0) * ContractingDecimal(100), 0)\n        self.assertEqual(ContractingDecimal(-5) * ContractingDecimal(42), -210)\n        self.assertEqual(ContractingDecimal(5.1234) * ContractingDecimal(2.3451), ContractingDecimal('12.01488534'))\n\n    def test_rmul(self):\n        self.assertEqual(5 * ContractingDecimal(42), 210)\n        self.assertEqual(0 * ContractingDecimal(100), 0)\n        self.assertEqual(-5 * ContractingDecimal(42), -210)\n        self.assertEqual(5.1234 * ContractingDecimal(2.3451), ContractingDecimal('12.01488534'))\n\n    def test_div(self):\n        self.assertEqual((ContractingDecimal(1) / ContractingDecimal(3)), ContractingDecimal('0.333333333333333333333333333333'))\n        self.assertEqual(ContractingDecimal(3) / ContractingDecimal(1), 3)\n\n    def test_div_large_decimals(self):\n        a = '0.78164062862089986280348253421170'\n        b = '0.53642401735797937714409102114816'\n\n        c = ContractingDecimal(a) / ContractingDecimal(b)\n\n        print(c)\n\n    def test_fix_precision_cuts_too_low(self):\n        d = Decimal('1.123456789012345678901234567890123')\n        e = Decimal('1.12345678901234567890123456789')\n\n        self.assertEqual(fix_precision(d), e)\n\n    def test_fix_precision_cuts_too_high(self):\n        e = Decimal('123456789012345678901234567890')\n        self.assertEqual(fix_precision(e), MAX_DECIMAL)\n\n    def test_fix_precision_doesnt_cut_high(self):\n        e = Decimal('12345678901234567890123456789')\n        self.assertEqual(fix_precision(e), e)\n\n    def test_fix_precision_cuts_all_decimals_if_too_high(self):\n        e = Decimal('123456789012345678901234567890.123456')\n        self.assertEqual(fix_precision(e), MAX_DECIMAL)\n\n    def test_fix_precision_cuts_decimals_if_high_but_not_too_high(self):\n        e = Decimal('12345678901234567890123456789.123456789012345678901234567890')\n        f = Decimal('12345678901234567890123456789.12345678901234567890123456789')\n\n        self.assertEqual(fix_precision(e), f)\n\n    def test_contracting_decimal_can_round(self):\n        s = '12345678901234567890123456789.123456789012345678901234567890'\n        self.assertEqual(round(Decimal(s), 10), round(ContractingDecimal(s), 10))\n\n    def test_sci_not_whole_number(self):\n        s = '2e-5'\n        expected = '0.00002'\n\n        self.assertEqual(neg_sci_not(s), expected)\n\n    def test_sci_not_decimal(self):\n        s = '2.2e-7'\n        expected = '0.00000022'\n\n        self.assertEqual(neg_sci_not(s), expected)\n\n    def test_sci_not_e0(self):\n        s = '2e-0'\n        expected = '2'\n\n        self.assertEqual(neg_sci_not(s), expected)\n\n    def test_sci_not_extra_precision(self):\n        s = '20e-5'\n        expected = '20e-5'\n\n        self.assertEqual(neg_sci_not(s), expected)\n\nif \"__main__\" == __name__:\n    unittest.main()"
  },
  {
    "path": "tests/unit/test_driver_tombstones.py",
    "content": "import unittest\nfrom contracting.storage.driver import Driver\n\n\nclass TestDriverTombstones(unittest.TestCase):\n\n    def setUp(self):\n        self.driver = Driver(bypass_cache=False)\n        self.driver.flush_full()\n\n    def tearDown(self):\n        self.driver.flush_full()\n\n    def test_items_excludes_pending_deletes(self):\n        key = 'con.hash:subkey'\n        self.driver.set(key, 'v1')\n        # Persist first so value exists on disk\n        self.driver.commit()\n        # Now set tombstone in the same transaction context\n        self.driver.set(key, None)\n\n        items = self.driver.items(prefix='con.hash:')\n        keys = self.driver.keys(prefix='con.hash:')\n        values = self.driver.values(prefix='con.hash:')\n\n        self.assertNotIn(key, items)\n        self.assertNotIn(key, keys)\n        self.assertEqual(values, [])\n\n\nif __name__ == '__main__':\n    unittest.main()\n\n\n"
  },
  {
    "path": "tests/unit/test_encode.py",
    "content": "from unittest import TestCase\nfrom contracting.storage.encoder import encode, decode, safe_repr, convert_dict, MONGO_MAX_INT, MONGO_MIN_INT\nfrom contracting.stdlib.bridge.time import Datetime, Timedelta\nfrom datetime import datetime\nfrom contracting.stdlib.bridge.decimal import ContractingDecimal\n\n\nclass TestEncode(TestCase):\n    def test_int_to_bytes(self):\n        i = 1000\n        b = '1000'\n\n        self.assertEqual(encode(i), b)\n\n    def test_str_to_bytes(self):\n        s = 'hello'\n        b = '\"hello\"'\n\n        self.assertEqual(encode(s), b)\n\n    def test_dec_to_bytes(self):\n        d = 1.098409840984\n        b = '1.098409840984'\n\n        self.assertEqual(encode(d), b)\n\n    def test_decode_bytes_to_int(self):\n        b = '1234'\n        i = 1234\n\n        self.assertEqual(decode(b), i)\n\n    def test_decode_bytes_to_str(self):\n        b = '\"howdy\"'\n        s = 'howdy'\n\n        self.assertEqual(decode(b), s)\n\n    def test_decode_bytes_to_dec(self):\n        b = '{\"__fixed__\":\"0.0044997618965276\"}'\n        d = ContractingDecimal('0.0044997618965276')\n\n        # _d is the actual Decimal object included in the wrapped stdlib ContractingDecimal\n        self.assertEqual(decode(b)._d, d)\n\n    def test_decode_failure(self):\n        b = b'xwow'\n\n        self.assertIsNone(decode(b))\n\n    def test_date_encode(self):\n        d = Datetime(2019, 1, 1)\n\n        _d = encode(d)\n\n        self.assertEqual(_d, '{\"__time__\":[2019,1,1,0,0,0,0]}')\n\n    def test_date_decode(self):\n        _d = '{\"__time__\": [2019, 1, 1, 0, 0, 0, 0]}'\n\n        d = decode(_d)\n\n        self.assertEqual(Datetime(2019, 1, 1), d)\n\n    def test_timedelta_encode(self):\n        t = Timedelta(weeks=1, days=1)\n\n        _t = encode(t)\n\n        self.assertEqual('{\"__delta__\":[8,0]}', _t)\n\n    def test_timedelta_decode(self):\n        _t = '{\"__delta__\": [8, 0]}'\n\n        t = decode(_t)\n\n        self.assertEqual(t, Timedelta(weeks=1, days=1))\n\n    def test_int_encode(self):\n        i = 10\n\n        self.assertEqual(str(i), encode(i))\n\n    def test_int_decode(self):\n        i = '10'\n\n        self.assertEqual(10, decode(i))\n\n    def test_bigint_encode(self):\n        si = MONGO_MIN_INT - 1\n        bi = MONGO_MAX_INT + 1\n\n        self.assertEqual('{\"__big_int__\":\"' + str(bi) + '\"}', encode(bi))\n        self.assertEqual('{\"__big_int__\":\"' + str(si) + '\"}', encode(si))\n\n    def test_bigint_decode(self):\n        _bi = '{\"__big_int__\":' + str(MONGO_MAX_INT+1) + '}'\n\n        self.assertEqual(decode(_bi), MONGO_MAX_INT+1)\n\n    def test_encode_ints_nested_list(self):\n        d = {'lists':[ {'i': 123,'bi': MONGO_MAX_INT} ]}\n        expected = '{\"lists\":[{\"i\":123,\"bi\":{\"__big_int__\":\"' + str(MONGO_MAX_INT) + '\"}}]}'\n\n        self.assertEqual(encode(d), expected)\n\n    def test_encode_dict_with_list_containing_different_types(self):\n        d = {'lists':[ {'i': 123,'bi': MONGO_MAX_INT}, 'hello' ]}\n        expected = '{\"lists\":[{\"i\":123,\"bi\":{\"__big_int__\":\"' + str(MONGO_MAX_INT) + '\"}},\"hello\"]}'\n\n        self.assertEqual(encode(d), expected)\n\n    def test_encode_ints_nested_dict(self):\n        d = {'d': {'bi': MONGO_MAX_INT, 'str': 'hello'}}\n        expected = '{\"d\":{\"bi\":{\"__big_int__\":\"' + str(MONGO_MAX_INT) + '\"},\"str\":\"hello\"}}'\n\n        self.assertEqual(encode(d), expected)\n\n    def test_safe_repr_non_object(self):\n        a = str(1)\n        b = safe_repr(1)\n\n        self.assertEqual(a, b)\n\n    def test_safe_repr_arbitrary_object(self):\n        class Object:\n            pass\n\n        a = Object()\n        b = Object()\n\n        self.assertEqual(safe_repr(a), safe_repr(b))\n\n    def test_safe_repr_decimal_object(self):\n        a = Timedelta(weeks=1, days=1)\n        b = Timedelta(weeks=1, days=1)\n\n        self.assertEqual(safe_repr(a), safe_repr(b))\n\n    def test_safe_repr_decimal_object_different_not_equal(self):\n        a = Timedelta(weeks=1, days=1)\n        b = Timedelta(weeks=2, days=1)\n\n        self.assertNotEqual(safe_repr(a), safe_repr(b))\n\n    def test_safe_repr_assertion_error_string(self):\n        a = AssertionError('Hello')\n        b = AssertionError('Hello')\n\n        self.assertEqual(safe_repr(a), safe_repr(b))\n\n    def test_contracting_decimal(self):\n        c = ContractingDecimal(a=123.456)\n        b = '{\"__fixed__\":\"123.456\"}'\n\n        self.assertEqual(encode(c), b)\n\n    def test_decode_fixed_trailing_doesnt_get_rid_of_zeros_properly(self):\n        b = '{\"__fixed__\":\"1.10\"}'\n\n        d = decode(b)\n\n    def test_encoding_fixed_trailing_zeros(self):\n        b = ContractingDecimal('123.000000')\n\n        e = encode(b)\n\n        print(e)\n\n    def test_convert_returns_normal_dict(self):\n        d = {\n            1: 2,\n            \"a\": \"b\"\n        }\n\n        d2 = convert_dict(d)\n        self.assertEqual(d, d2)\n\n    def test_convert_bigint(self):\n        d = {'bigint': {'__big_int__': str(2**65)}}\n        expected = {'bigint': 2**65}\n\n        self.assertDictEqual(convert_dict(d), expected)\n\n    def test_convert_contracting_decimal(self):\n        d = {\n            'kwargs': {\n                '__fixed__': '0.1234'\n            }\n        }\n\n        expected = {\n            'kwargs': ContractingDecimal('0.1234')\n        }\n\n        self.assertEqual(expected, convert_dict(d))\n\n    def test_convert_contracting_datetime(self):\n        d = {\n            'kwargs': {\n                    \"__time__\": [\n                      2021,\n                      4,\n                      29,\n                      21,\n                      30,\n                      54,\n                      0\n                    ]\n                  }\n        }\n\n        expected = {\n            'kwargs': Datetime(2021, 4, 29, 21, 30, 54, 0)\n        }\n\n        self.assertEqual(expected, convert_dict(d))\n\n    def test_convert_contracting_timedelta(self):\n        d = {\n            'kwargs': {\n                    \"__delta__\": [8, 0]\n            }\n        }\n\n        expected = {\n            'kwargs': Timedelta(days=8, seconds=0)\n        }\n\n        self.assertEqual(expected, convert_dict(d))\n\n    def test_convert_contracting_bytes(self):\n        d = {\n            'kwargs': {\n                    \"__bytes__\": \"123456\"\n            }\n        }\n\n        expected = {\n            'kwargs': b'\\x124V'\n        }\n\n        self.assertEqual(expected, convert_dict(d))\n\n    def test_multiple_conversions(self):\n        d = {\n            'kwargs': {\n                '__fixed__': '0.1234'\n            },\n            'kwargs2': {\n                \"__time__\": [\n                      2021,\n                      4,\n                      29,\n                      21,\n                      30,\n                      54,\n                      0\n                    ]\n                  },\n            'kwargs3': {\n                \"__delta__\": [8, 0]\n            },\n            'kwargs4': {\n                \"__bytes__\": \"123456\"\n            }\n        }\n\n        expected = {\n            'kwargs': ContractingDecimal('0.1234'),\n            'kwargs2': Datetime(2021, 4, 29, 21, 30, 54, 0),\n            'kwargs3': Timedelta(days=8, seconds=0),\n            'kwargs4': b'\\x124V',\n        }\n\n        self.assertEqual(expected, convert_dict(d))\n\n    def test_nested_dictionaries(self):\n        d = {\n            'kwargs': {\n                '__fixed__': '0.1234'\n            },\n            'thing': {\n                'thing2': {\n                    \"__time__\": [\n                        2021,\n                        4,\n                        29,\n                        21,\n                        30,\n                        54,\n                        0\n                    ]\n                },\n            }\n        }\n\n        expected = {\n            'kwargs': ContractingDecimal('0.1234'),\n            'thing': {\n                'thing2': Datetime(2021, 4, 29, 21, 30, 54, 0),\n            }\n        }\n\n        d2 = convert_dict(d)\n\n        self.assertEqual(expected, d2)\n\n    def test_lists(self):\n        d = {\n            'kwargs': [\n                {\n                    '__fixed__': '0.1234'\n                },\n                {\n                    '__fixed__': '0.1235'\n                },\n                {\n                    '__fixed__': '0.1236'\n                },\n                {\n                    '__fixed__': '0.1237'\n                },\n                {\n                    '__fixed__': '0.1238'\n                },\n            ]\n        }\n\n        expected = {\n            'kwargs': [\n                ContractingDecimal('0.1234'),\n                ContractingDecimal('0.1235'),\n                ContractingDecimal('0.1236'),\n                ContractingDecimal('0.1237'),\n                ContractingDecimal('0.1238'),\n            ]\n        }\n\n        d2 = convert_dict(d)\n\n        self.assertEqual(expected, d2)\n"
  },
  {
    "path": "tests/unit/test_imports_stdlib.py",
    "content": "from unittest import TestCase\nfrom contracting.stdlib.bridge import imports\nfrom types import ModuleType\nfrom contracting.storage.orm import Hash, Variable\nimport os\n\nclass TestImports(TestCase):\n    def setUp(self):\n        scope = {}\n        \n        self.script_dir = os.path.dirname(os.path.abspath(__file__))\n        compiled_token_file_path = os.path.join(self.script_dir, \"precompiled\", \"compiled_token.py\")\n\n        with open(compiled_token_file_path) as f:\n            code = f.read()\n\n        exec(code, scope)\n\n        m = ModuleType('testing')\n\n        vars(m).update(scope)\n        del vars(m)['__builtins__']\n\n        self.module = m\n\n    def test_func_correct_type(self):\n        def sup(x, y):\n            return x + y\n\n        s = imports.Func(name='sup', args=('x', 'y'))\n\n        self.assertTrue(s.is_of(sup))\n\n    def test_func_incorrect_name(self):\n        def sup(x, y):\n            return x + y\n\n        s = imports.Func(name='not_much', args=('x', 'y'))\n\n        self.assertFalse(s.is_of(sup))\n\n    def test_func_incorrect_args(self):\n        def sup(a, b):\n            return a + b\n\n        s = imports.Func(name='sup', args=('x', 'y'))\n\n        self.assertFalse(s.is_of(sup))\n\n    def test_func_correct_with_kwargs(self):\n        def sup(x=100, y=200):\n            return x + y\n\n        s = imports.Func(name='sup', args=('x', 'y'))\n\n        self.assertTrue(s.is_of(sup))\n\n    def test_func_correct_with_annotations(self):\n        def sup(x: int, y: int):\n            return x + y\n\n        s = imports.Func(name='sup', args=('x', 'y'))\n\n        self.assertTrue(s.is_of(sup))\n\n    def test_func_correct_with_kwargs_and_annotations(self):\n        def sup(x: int=100, y: int=100):\n            return x + y\n\n        s = imports.Func(name='sup', args=('x', 'y'))\n\n        self.assertTrue(s.is_of(sup))\n\n    def test_func_correct_private(self):\n        def __sup(a, b):\n            return a + b\n\n        s = imports.Func(name='sup', args=('a', 'b'), private=True)\n\n        self.assertTrue(s.is_of(__sup))\n\n    def test_func_false_private(self):\n        def __sup(a, b):\n            return a + b\n\n        s = imports.Func(name='sup', args=('x', 'y'), private=True)\n\n        self.assertFalse(s.is_of(__sup))\n\n    def test_var_fails_if_type_not_of_datum(self):\n        with self.assertRaises(AssertionError):\n            imports.Var('blah', str)\n\n    def test_enforce_interface_works_all_public_funcs(self):\n        interface = [\n            imports.Func('transfer', args=('amount', 'to')),\n            imports.Func('balance_of', args=('account',)),\n            imports.Func('total_supply'),\n            imports.Func('allowance', args=('owner', 'spender')),\n            imports.Func('approve', args=('amount', 'to')),\n            imports.Func('transfer_from', args=('amount', 'to', 'main_account'))\n        ]\n\n        self.assertTrue(imports.enforce_interface(self.module, interface))\n\n    def test_enforce_interface_works_on_subset_funcs(self):\n        interface = [\n            imports.Func('transfer', args=('amount', 'to')),\n            imports.Func('balance_of', args=('account',)),\n            imports.Func('total_supply'),\n            imports.Func('allowance', args=('owner', 'spender')),\n            imports.Func('transfer_from', args=('amount', 'to', 'main_account'))\n        ]\n\n        self.assertTrue(imports.enforce_interface(self.module, interface))\n\n    def test_enforce_interface_fails_on_wrong_funcs(self):\n        interface = [\n            imports.Func('transfer', args=('amount', 'to')),\n            imports.Func('balance_of', args=('account',)),\n            imports.Func('spooky'),\n            imports.Func('allowance', args=('owner', 'spender')),\n            imports.Func('transfer_from', args=('amount', 'to', 'main_account'))\n        ]\n\n        self.assertFalse(imports.enforce_interface(self.module, interface))\n\n    def test_enforce_interface_on_resources(self):\n        interface = [\n            imports.Var('supply', Variable),\n            imports.Var('balances', Hash),\n        ]\n\n        self.assertTrue(imports.enforce_interface(self.module, interface))\n\n    def test_complete_enforcement(self):\n        interface = [\n            imports.Func('transfer', args=('amount', 'to')),\n            imports.Func('balance_of', args=('account',)),\n            imports.Func('total_supply'),\n            imports.Func('allowance', args=('owner', 'spender')),\n            imports.Func('approve', args=('amount', 'to')),\n            imports.Func('transfer_from', args=('amount', 'to', 'main_account')),\n            imports.Var('supply', Variable),\n            imports.Var('balances', Hash)\n        ]\n\n        self.assertTrue(imports.enforce_interface(self.module, interface))\n\n    def test_private_function_enforcement(self):\n        interface = [\n            imports.Func('private_func', private=True),\n        ]\n\n        self.assertTrue(imports.enforce_interface(self.module, interface))\n\n    def test_complete_enforcement_with_private_func(self):\n        interface = [\n            imports.Func('transfer', args=('amount', 'to')),\n            imports.Func('balance_of', args=('account',)),\n            imports.Func('total_supply'),\n            imports.Func('allowance', args=('owner', 'spender')),\n            imports.Func('approve', args=('amount', 'to')),\n            imports.Func('private_func', private=True),\n            imports.Func('transfer_from', args=('amount', 'to', 'main_account')),\n            imports.Var('supply', Variable),\n            imports.Var('balances', Hash)\n        ]\n\n        self.assertTrue(imports.enforce_interface(self.module, interface))"
  },
  {
    "path": "tests/unit/test_linter.py",
    "content": "from unittest import TestCase\nfrom contracting.compilation.linter import Linter\nimport ast\nfrom contracting.compilation.whitelists import ALLOWED_AST_TYPES, ALLOWED_ANNOTATION_TYPES, VIOLATION_TRIGGERS\n\n\nclass TestLinter(TestCase):\n    def setUp(self):\n        self.l = Linter()\n\n    def test_linter(self):\n        # log = get_logger(\"TestSenecaLinter\")\n        data = '''\n@export\ndef a():\n    b = 10\n    return b\n    '''\n\n        print(\"stu code: \\n{}\".format(data))\n        ptree = ast.parse(data)\n        status = self.l.check(ptree)\n        self.l.dump_violations()\n        if status is None:\n            print(\"Success!\")\n        else:\n            print(\"Failed!\")\n\n        self.assertEqual(status, None)\n\n    # TODO - Verify this tetst is working as expected.\n    def test_good_ast_type(self):\n        # Dictionary to handle special cases of AST nodes that require arguments\n        special_cases = {\n            ast.Index: lambda: ast.Index(value=ast.Str(s='test')),\n        }\n\n        for t in ALLOWED_AST_TYPES:\n            if t in special_cases:\n                _t = special_cases[t]()\n            else:\n                _t = t()\n\n            self.l.ast_types(_t, 1)\n            self.assertListEqual([], self.l._violations)\n\n    def test_bad_ast_type(self):\n        err = 'Line 1 : S1- Illegal contracting syntax type used : AsyncFunctionDef'\n        t = ast.AsyncFunctionDef()\n        self.l.ast_types(t, 1)\n        self.l.dump_violations()\n        self.assertMultiLineEqual(err, self.l._violations[0])\n\n    def test_not_system_variable(self):\n        v = 'package'\n        self.l.not_system_variable(v, 1)\n        self.l.dump_violations()\n        self.assertListEqual([], self.l._violations)\n\n    def test_system_variable(self):\n        v = '__package__'\n        err = \"Line 1 : S2- Illicit use of '_' before variable : __package__\"\n        self.l.not_system_variable(v, 1)\n        self.l.dump_violations()\n        self.assertMultiLineEqual(err, self.l._violations[0])\n\n    '''\n    Is blocking all underscore variables really the solution to preventing access to system variables?\n    '''\n    def test_not_system_variable_ast(self):\n        code = '''\n@export\ndef a():\n    __ruh_roh__ = 'shaggy'\n        '''\n        err = \"Line 4 : S2- Illicit use of '_' before variable : __ruh_roh__\"\n\n        c = ast.parse(code)\n        chk = self.l.check(c)\n        self.l.dump_violations()\n        self.assertMultiLineEqual(err, self.l._violations[0])\n\n    def test_not_system_variable_ast_success(self):\n        code = '''\n@export\ndef a():\n    ruh_roh = 'shaggy'\n        '''\n        c = ast.parse(code)\n        chk = self.l.check(c)\n        self.l.dump_violations()\n        self.assertEqual(chk, None)\n        self.assertListEqual([], self.l._violations)\n\n    # def test_visit_async_func_def_fail(self):\n    #     err = 'Error : Illegal AST type: AsyncFunctionDef'\n    #     n = compilation.AsyncFunctionDef()\n    #\n    #     self.l.visit_AsyncFunctionDef(n)\n    #     self.l.dump_violations()\n    #     self.assertMultiLineEqual(err, self.l._violations[0])\n\n    def test_visit_async_func_def_fail_code(self):\n        code = '''\n@export\nasync def a():\n    ruh_roh = 'shaggy'\ndef b():\n    c = 1 + 2\n'''\n        err = 'Line 3: S7- Illicit use of Async functions'\n\n        c = ast.parse(code)\n        chk = self.l.check(c)\n        self.l.dump_violations()\n        self.assertEqual(len(chk), 3)\n        self.assertMultiLineEqual(err, self.l._violations[0])\n\n#TODO failing\n    # def test_visit_class_fail(self):\n    #     err = 'Error : Illegal AST type: ClassDef'\n    #     n = compilation.ClassDef()\n    #     self.l.visit_ClassDef(n)\n    #     self.l.dump_violations()\n\n        # self.assertMultiLineEqual(err, self.l._violations[0])\n\n    def test_visit_class_fail_code(self):\n        code = '''\nclass Scooby:\n    pass\n        '''\n        err = 'Line 2: S6- Illicit use of classes'\n\n        c = ast.parse(code)\n        chk = self.l.check(c)\n        self.l.dump_violations()\n        self.assertEqual(len(chk), 3)\n        self.assertMultiLineEqual(err, self.l._violations[0])\n\n    def test_visit_try_except_fail_code(self):\n        code = '''\n@export\ndef try_it():\n    try:\n        a = 0\n    except:\n        a = 1\n'''\n        c = ast.parse(code)\n        chk = self.l.check(c)\n        self.l.dump_violations()\n\n        print(self.l._violations)\n\n    def test_accessing_system_vars(self):\n        code = '''\n@export\ndef a():\n    ruh_roh = 'shaggy'\n    ruh_roh.__dir__()\n'''\n        err = \"Line 5 : S2- Illicit use of '_' before variable : __dir__\"\n        c = ast.parse(code)\n        chk = self.l.check(c)\n        self.l.dump_violations()\n        self.assertMultiLineEqual(err, self.l._violations[0])\n\n    def test_accessing_attribute(self):\n        code = '''\n@export\ndef a():\n    ruh_roh = 'shaggy'\n    ruh_roh.capitalize()\n    '''\n\n        c = ast.parse(code)\n        chk = self.l.check(c)\n        self.l.dump_violations()\n        self.assertEqual(chk, None)\n        self.assertListEqual([], self.l._violations)\n\n#TODO failed test case\n\n    def test_no_nested_imports(self):\n        code = '''\n@export\ndef a():\n    import something\n        '''\n\n        c = ast.parse(code)\n        chk = self.l.check(c)\n        self.l.dump_violations()\n        self.assertEqual(chk, ['Line 3: S3- Illicit use of Nested imports'])\n\n    def test_no_nested_imports_works(self):\n        code = '''\n@export\ndef a():\n    ruh_roh = 'shaggy'\n    ruh_roh.capitalize()\n            '''\n\n        c = ast.parse(code)\n        chk = self.l.check(c)\n        self.l.dump_violations()\n        self.assertEqual(chk, None)\n        self.assertListEqual([], self.l._violations)\n\n    def test_augassign(self):\n        code = '''\n@export\ndef a():\n    b = 0\n    b += 1\n'''\n        c = ast.parse(code)\n        chk = self.l.check(c)\n        self.l.dump_violations()\n        self.assertEqual(chk, None)\n        self.assertListEqual([], self.l._violations)\n\n    def test_no_import_from(self):\n        code = '''\nfrom something import a\n@export\ndef a():\n    b = 0\n    b += 1\n'''\n        err = 'Line 2: S4- ImportFrom compilation nodes not yet supported'\n\n        c = ast.parse(code)\n        chk = self.l.check(c)\n        self.l.dump_violations()\n        self.assertMultiLineEqual(err, self.l._violations[0])\n\n# disabling import check it would be done by compiler\n\n#     def test_import_non_existent_contract(self):\n#         code = '''\n# import something\n# @export\n# def a():\n#     b = 0\n#     b += 1\n# '''\n#         err = 'Line 2: S5- Contract not found in lib: something'\n#\n#         c = compilation.parse(code)\n#         self.l.check(c)\n#         self.l.dump_violations()\n#         self.assertMultiLineEqual(err, self.l._violations[0])\n\n    def test_final_checks_set_properly(self):\n        code = '''\ndef a():\n    b = 0\n    b += 1\n        '''\n\n        c = ast.parse(code)\n        chk = self.l.check(c)\n        self.l.dump_violations()\n        self.assertEqual(chk, ['Line 0: S13- No valid contracting decorator found'])\n        self.assertFalse(self.l._is_one_export)\n\n    def test_collect_function_defs(self):\n        code = '''\n@export\ndef a():\n    return 42\n\n@export\ndef b():\n    return 1000000\n\n@export\ndef x():\n    return 64\n\n@export\ndef y():\n    return 24\n'''\n        c = ast.parse(code)\n        self.l._collect_function_defs(c)\n        self.l.dump_violations()\n        self.assertEqual(self.l._functions, ['a', 'b', 'x', 'y'])\n\n    def test_assignment_of_import(self):\n        code = '''\nimport import_this\n\n@export\ndef test():\n    a = import_this.howdy()\n    a -= 1000\n    return a        \n'''\n        c = ast.parse(code)\n        chk = self.l.check(c)\n        self.l.dump_violations()\n\n    def test_good_orm_initialization(self):\n        code = '''\nv = Variable()\n\n@export\ndef set(i: int):\n    v.set(i)\n'''\n        c = ast.parse(code)\n        chk = self.l.check(c)\n        self.assertEqual(self.l._violations, [])\n\n    def test_bad_orm_initialization(self):\n        code = '''\nv = Variable(contract='currency', name='stus_balance')\n\n@export\ndef set(i: int):\n    v.set(i)\n'''\n        c = ast.parse(code)\n        chk = self.l.check(c)\n        self.assertEqual(chk[0], 'Line 2: S11- Illicit keyword overloading for ORM assignments')\n\n    def test_multi_targets_orm_fails(self):\n        code = '''\nv, x = Variable()\n\n@export\ndef set(i):\n    v.set(i)\n    '''\n        c = ast.parse(code)\n        chk = self.l.check(c)\n        self.l.dump_violations()\n        print(chk)\n        self.assertEqual(chk[0], 'Line 2: S12- Multiple targets to ORM definition detected')\n\n    def test_multi_decorator_fails(self):\n        code = '''\n@construct\n@export\ndef kaboom():\n    print('i like to break things')\n'''\n        c = ast.parse(code)\n        chk = self.l.check(c)\n        self.l.dump_violations()\n        self.assertEqual(chk[0], 'Line 4: S10- Illicit use of multiple decorators: Detected: 2 MAX limit: 1')\n\n    def test_invalid_decorator_fails(self):\n        code = '''\n@contracting_invalid\ndef wont_work():\n    print('i hope')\n'''\n        c = ast.parse(code)\n        chk = self.l.check(c)\n        self.l.dump_violations()\n        self.assertEqual(chk[1], 'Line 3: S8- Invalid decorator used: valid list: contracting_invalid')\n\n    def test_multiple_constructors_fails(self):\n        code = '''\n@construct\ndef seed_1():\n    pass\n    \n@construct\ndef seed_1():\n    pass\n    \n@export\ndef seed_5():\n    pass\n'''\n\n        c = ast.parse(code)\n        chk = self.l.check(c)\n        self.l.dump_violations()\n        self.assertEqual(len(chk),1)\n        self.assertEqual(self.l._violations, ['Line 7: S9- Multiple use of constructors detected'])\n\n    def test_function_str_annotation(self):\n        code = '''\n@export\ndef greeting(name: str):\n    return 'Hello ' + name\n'''\n        c = ast.parse(code)\n        chk = self.l.check(c)\n\n        self.assertEqual(chk, None)\n\n    def test_function_dict_annotation(self):\n        code = '''\n@export\ndef greeting(name: dict):\n    return 'Hello ' + name\n'''\n        c = ast.parse(code)\n        chk = self.l.check(c)\n\n        self.assertEqual(chk, None)\n\n    def test_function_bad_annotation(self):\n        code = '''\n@export\ndef greeting(name: mytype):\n    return 'Hello ' + name\n'''\n        c = ast.parse(code)\n        chk = self.l.check(c)\n\n        self.assertEqual(chk, ['Line 3 : S16- Illegal argument annotation used : mytype'])\n\n\n    def test_function_none_annotation(self):\n        code = '''\n@export\ndef greeting(name):\n    return 'Hello ' + name\n'''\n        c = ast.parse(code)\n        chk = self.l.check(c)\n\n        self.assertEqual(chk, ['Line 3 : S17- No valid argument annotation found'])\n\n\n    def test_none_return_annotation(self):\n        code = '''\n@export\ndef greeting(name: str):\n    return 'Hello ' + name\n'''\n        c = ast.parse(code)\n        chk = self.l.check(c)\n\n        self.assertEqual(self.l._violations, [])\n\n\n    def test_contract_annotation(self):\n        code ='''\n@export\ndef transfer(amount, to):\n    sender = ctx.caller\n    assert balances[sender] >= amount, 'Not enough coins to send!'\n\n    balances[sender] -= amount\n    balances[to] += amount\n\ndef greeting(name):\n    return 'Hello ' + name\n'''\n        c = ast.parse(code)\n        chk = self.l.check(c)\n\n        self.assertEqual(chk, ['Line 3 : S17- No valid argument annotation found'])\n\n\n## ANNOTATIONS ARE OKAY\n#   def test_function_return_annotation(self):\n#       code = '''\n#@export\n#def greeting(name: str) -> str:\n#    return 'Hello ' + name\n#'''\n#        c = ast.parse(code)\n#        chk = self.l.check(c)\n#\n#        self.assertEqual(['Line 2 : S18- Illegal use of return annotation : str'], chk)\n\n    def test_violations_sorted_by_line_number(self):\n        code = '''\nclass Illegal1:  # Line 2\n    pass\n\n@export\ndef good_function():\n    pass\n\nfrom something import stuff  # Line 8\n\nclass Illegal2:  # Line 10\n    pass\n    '''\n\n        c = ast.parse(code)\n        violations = self.l.check(c)\n\n        self.assertIsNotNone(violations)\n        self.assertEqual(len(violations), 5)\n\n        line_numbers = [int(v.split(':')[0].split()[1]) for v in violations]\n        \n\n        self.assertEqual(line_numbers, sorted(line_numbers))\n\n        self.assertTrue(violations[0].startswith('Line 2'))  # No export decorator\n        self.assertTrue(violations[1].startswith('Line 2'))  # First class definition\n        self.assertTrue(violations[2].startswith('Line 9'))  # ImportFrom\n        self.assertTrue(violations[3].startswith('Line 11'))  # Second class definition\n        self.assertTrue(violations[4].startswith('Line 11'))  # Second class definition\n\n"
  },
  {
    "path": "tests/unit/test_module.py",
    "content": "from unittest import TestCase\nfrom contracting.execution.module import *\nfrom contracting.storage.driver import Driver\nimport types\nimport glob\nimport os\n\nclass TestDatabase(TestCase):\n    def setUp(self):\n        self.d = Driver()\n        self.d.flush_full()\n\n    def tearDown(self):\n        self.d.flush_full()\n\n    def test_push_and_get_contract(self):\n        code = 'a = 123'\n        name = 'test'\n\n        self.d.set_contract(name, code)\n        _code = self.d.get_contract(name)\n\n        self.assertEqual(code, _code, 'Pushing and getting contracts is not working.')\n\n    def test_flush(self):\n        code = 'a = 123'\n        name = 'test'\n\n        self.d.set_contract(name, code)\n        self.d.commit()\n        self.d.flush_full()\n\n        self.assertIsNone(self.d.get_contract(name))\n\n\nclass TestDatabaseLoader(TestCase):\n    def setUp(self):\n        self.dl = DatabaseLoader()\n\n    def test_init(self):\n        self.assertTrue(isinstance(self.dl.d, Driver), 'self.d is not a Database object.')\n\n    def test_create_module(self):\n        self.assertEqual(self.dl.create_module(None), None, 'self.create_module should return None')\n\n    def test_exec_module(self):\n        module = types.ModuleType('test')\n\n        self.dl.d.set_contract('test', 'b = 1337')\n        self.dl.exec_module(module)\n        self.dl.d.flush_full()\n\n        self.assertEqual(module.b, 1337)\n\n    def test_exec_module_nonattribute(self):\n        module = types.ModuleType('test')\n\n        self.dl.d.set_contract('test', 'b = 1337')\n        self.dl.exec_module(module)\n        self.dl.d.flush_full()\n\n        with self.assertRaises(AttributeError):\n            module.a\n\n    def test_module_representation(self):\n        module = types.ModuleType('howdy')\n\n        self.assertEqual(self.dl.module_repr(module), \"<module 'howdy' (smart contract)>\")\n\n\nclass TestInstallLoader(TestCase):\n    def test_install_loader(self):\n        uninstall_database_loader()\n\n        self.assertNotIn(DatabaseFinder, sys.meta_path)\n\n        install_database_loader()\n\n        self.assertIn(DatabaseFinder, sys.meta_path)\n\n        uninstall_database_loader()\n\n        self.assertNotIn(DatabaseFinder, sys.meta_path)\n\n    def test_integration_and_importing(self):\n        dl = DatabaseLoader()\n        dl.d.set_contract('testing', 'a = 1234567890')\n        dl.d.commit()\n\n        install_database_loader()\n\n        import testing\n\n        #dl.d.flush()\n\n        self.assertEqual(testing.a, 1234567890)\n\n\ndriver = Driver()\n\n\nclass TestModuleLoadingIntegration(TestCase):\n    def setUp(self):\n        sys.meta_path.append(DatabaseFinder)\n        driver.flush_full()\n\n        self.script_dir = os.path.dirname(os.path.abspath(__file__))\n        contracts = glob.glob(os.path.join(self.script_dir, \"test_sys_contracts\", \"*.py\"))\n        for contract in contracts:\n            name = contract.split('/')[-1]\n            name = name.split('.')[0]\n\n            with open(contract) as f:\n                code = f.read()\n\n            driver.set_contract(name=name, code=code)\n            driver.commit()\n\n    def tearDown(self):\n        sys.meta_path.remove(DatabaseFinder)\n        driver.flush_full()\n\n    def test_get_code_string(self):\n        ctx = types.ModuleType('ctx')\n        code = '''import module1\n\nprint(\"now i can run my functions!\")\n'''\n\n        exec(code, vars(ctx))\n\n        print('ok do it again')\n\n        exec(code, vars(ctx))\n"
  },
  {
    "path": "tests/unit/test_new_driver.py",
    "content": "import unittest\nimport os\nfrom shutil import rmtree\nfrom datetime import datetime\nfrom contracting.storage.driver import Driver\n\nclass TestDriver(unittest.TestCase):\n\n    def setUp(self):\n        # Setup a fresh instance of Driver and ensure a clean storage environment\n        self.driver = Driver(bypass_cache=False)\n        self.driver.flush_full()\n\n    def tearDown(self):\n        # Clean up any state that might affect other tests\n        self.driver.flush_full()\n\n    def test_set_and_get(self):\n        key = 'test_key'\n        value = 'test_value'\n        self.driver.set(key, value)\n        self.driver.commit()\n        retrieved_value = self.driver.get(key)\n        self.assertEqual(retrieved_value, value)\n\n    def test_find(self):\n        key = 'test_key'\n        value = 'test_value'\n        self.driver.set(key, value)\n        self.driver.commit()\n        retrieved_value = self.driver.find(key)\n        self.assertEqual(retrieved_value, value)\n\n    def test_keys_from_disk(self):\n        key1 = 'test_key1'\n        key2 = 'test_key2'\n        value = 'test_value'\n        self.driver.set(key1, value)\n        self.driver.set(key2, value)\n        self.driver.commit()\n        keys = self.driver.keys_from_disk()\n        self.assertIn(key1, keys)\n        self.assertIn(key2, keys)\n\n    def test_iter_from_disk(self):\n        key1 = 'test_key1'\n        key2 = 'test_key2'\n        prefix_key = 'prefix_key'\n        value = 'test_value'\n        self.driver.set(key1, value)\n        self.driver.set(key2, value)\n        self.driver.set(prefix_key, value)\n        self.driver.commit()\n        keys = self.driver.iter_from_disk(prefix=prefix_key)\n        self.assertIn(prefix_key, keys)\n        self.assertNotIn(key1, keys)\n        self.assertNotIn(key2, keys)\n\n    def test_items(self):\n        prefix_key = 'prefix_key'\n        value = 'test_value'\n        self.driver.set(prefix_key, value)\n        self.driver.commit()\n        items = self.driver.items(prefix=prefix_key)\n        self.assertIn(prefix_key, items)\n        self.assertEqual(items[prefix_key], value)\n\n    def test_delete_key_from_disk(self):\n        key = 'test_key'\n        value = 'test_value'\n        self.driver.set(key, value)\n        self.driver.commit()\n        self.driver.delete_key_from_disk(key)\n        retrieved_value = self.driver.value_from_disk(key)\n        self.assertIsNone(retrieved_value)\n\n    def test_flush_cache(self):\n        key = 'test_key'\n        value = 'test_value'\n        self.driver.set(key, value)\n        self.driver.flush_cache()\n        self.assertFalse(self.driver.pending_writes)\n\n    def test_flush_disk(self):\n        key = 'test_key'\n        value = 'test_value'\n        self.driver.set(key, value)\n        self.driver.commit()\n        self.driver.flush_disk()\n        self.assertFalse(self.driver.get(key))\n\n    def test_commit(self):\n        key = 'test_key'\n        value = 'test_value'\n        self.driver.set(key, value)\n        self.driver.commit()\n        retrieved_value = self.driver.get(key)\n        self.assertEqual(retrieved_value, value)\n\n    def test_get_all_contract_state(self):\n        key = 'contract.key'\n        value = 'contract_value'\n        self.driver.set(key, value)\n        self.driver.commit()\n        contract_state = self.driver.get_all_contract_state()\n        self.assertIn(key, contract_state)\n        self.assertEqual(contract_state[key], value)\n        \n    def test_transaction_writes(self):\n        key = 'test_key'\n        value = 'test_value'\n        self.driver.set(key, value, is_txn_write=True)\n        # self.driver.commit()\n        transaction_writes = self.driver.transaction_writes\n        self.assertIn(key, transaction_writes)\n        self.assertEqual(transaction_writes[key], value)\n        \n    def test_clear_transaction_writes(self):\n        key = 'test_key'\n        value = 'test_value'\n        self.driver.set(key, value)\n        # self.driver.commit()\n        self.driver.clear_transaction_writes()\n        transaction_writes = self.driver.transaction_writes\n        self.assertNotIn(key, transaction_writes)\n\n    def test_get_run_state(self):\n        # We can't test this function here since we are not running a real blockchain.\n        pass\n\nif __name__ == '__main__':\n    unittest.main()\n"
  },
  {
    "path": "tests/unit/test_orm.py",
    "content": "from unittest import TestCase\nfrom contracting import constants\nfrom contracting.storage.driver import Driver\nfrom contracting.storage.orm import Datum, Variable, ForeignHash, ForeignVariable, Hash, LogEvent\nfrom contracting.stdlib.bridge.decimal import ContractingDecimal\n\n# from contracting.stdlib.env import gather\n\n# Variable = gather()['Variable']\n# Hash = gather()['Hash']\n# ForeignVariable = gather()['ForeignVariable']\n# ForeignHash = gather()['ForeignHash']\n\ndriver = Driver()\n\n\nclass TestDatum(TestCase):\n    def setUp(self):\n        driver.flush_full()\n\n    def tearDown(self):\n        driver.flush_full()\n\n    def test_init(self):\n        d = Datum('stustu', 'test', driver)\n        self.assertEqual(d._key, driver.make_key('stustu', 'test'))\n\n\nclass TestVariable(TestCase):\n    def setUp(self):\n        driver.flush_full()\n\n    def tearDown(self):\n        #_driver.flush_full()\n        pass\n\n    def test_set(self):\n        contract = 'stustu'\n        name = 'balance'\n        delimiter = constants.INDEX_SEPARATOR\n\n        raw_key = '{}{}{}'.format(contract, delimiter, name)\n\n        v = Variable(contract, name, driver=driver)\n        v.set(1000)\n\n        self.assertEqual(driver.get(raw_key), 1000)\n\n    def test_get(self):\n        contract = 'stustu'\n        name = 'balance'\n        delimiter = constants.INDEX_SEPARATOR\n\n        raw_key = '{}{}{}'.format(contract, delimiter, name)\n        driver.set(raw_key, 1234)\n\n        v = Variable(contract, name, driver=driver)\n        _v = v.get()\n\n        self.assertEqual(_v, 1234)\n\n    def test_set_get(self):\n        contract = 'stustu'\n        name = 'balance'\n\n        v = Variable(contract, name, driver=driver)\n        v.set(1000)\n\n        _v = v.get()\n\n        self.assertEqual(_v, 1000)\n\n    def test_default_value(self):\n        contract = 'stustu'\n        name = 'balance'\n\n        v = Variable(contract, name, driver=driver, default_value=999)\n        self.assertEqual(v.get(), 999)\n\n        v.set(123)\n        self.assertEqual(v.get(), 123)\n\n        v.set(None)\n        self.assertEqual(v.get(), 999)\n\n    def test_mutable_default_is_copied(self):\n        contract = 'stustu'\n        name = 'cfg'\n        v = Variable(contract, name, driver=driver, default_value={'a': []})\n        first = v.get()\n        first['a'].append(1)\n        second = v.get()\n        self.assertEqual(second, {'a': []})\n\n\nclass TestHash(TestCase):\n    def setUp(self):\n        driver.flush_full()\n\n    def tearDown(self):\n        driver.flush_full()\n\n    def test_set(self):\n        contract = 'stustu'\n        name = 'balance'\n        delimiter = constants.INDEX_SEPARATOR\n\n        raw_key_1 = '{}{}{}'.format(contract, delimiter, name)\n        raw_key_1 += ':stu'\n\n        h = Hash(contract, name, driver=driver)\n\n        h._set('stu', 1234)\n\n        driver.commit()\n\n        self.assertEqual(driver.get(raw_key_1), 1234)\n\n    def test_get(self):\n        contract = 'stustu'\n        name = 'balance'\n        delimiter = constants.INDEX_SEPARATOR\n\n        raw_key_1 = '{}{}{}'.format(contract, delimiter, name)\n        raw_key_1 += ':stu'\n\n        driver.set(raw_key_1, 1234)\n\n        h = Hash(contract, name, driver=driver)\n\n        self.assertEqual(h._get('stu'), 1234)\n\n    def test_set_get(self):\n        contract = 'stustu'\n        name = 'balance'\n\n        h = Hash(contract, name, driver=driver)\n\n        h._set('stu', 1234)\n        _h = h._get('stu')\n\n        self.assertEqual(_h, 1234)\n\n        h._set('colin', 5678)\n        _h2 = h._get('colin')\n\n        self.assertEqual(_h2, 5678)\n\n    def test_setitem(self):\n        contract = 'blah'\n        name = 'scoob'\n        delimiter = constants.INDEX_SEPARATOR\n\n        h = Hash(contract, name, driver=driver)\n\n        prefix = '{}{}{}{}'.format(contract, delimiter, name, h._delimiter)\n\n        h['stu'] = 9999999\n\n        raw_key = '{}stu'.format(prefix)\n\n        self.assertEqual(driver.get(raw_key), 9999999)\n\n    def test_getitem(self):\n        contract = 'blah'\n        name = 'scoob'\n        delimiter = constants.INDEX_SEPARATOR\n\n        h = Hash(contract, name, driver=driver)\n\n        prefix = '{}{}{}{}'.format(contract, delimiter, name, h._delimiter)\n\n        raw_key = '{}stu'.format(prefix)\n\n        driver.set(raw_key, 54321)\n\n        self.assertEqual(h['stu'], 54321)\n\n    def test_setitems(self):\n        contract = 'blah'\n        name = 'scoob'\n\n        h = Hash(contract, name, driver=driver)\n        h['stu'] = 123\n        h['stu', 'raghu'] = 1000\n        driver.commit()\n\n        val = driver.get('blah.scoob:stu:raghu')\n        self.assertEqual(val, 1000)\n\n    def test_setitem_delimiter_illegal(self):\n        contract = 'blah'\n        name = 'scoob'\n\n        h = Hash(contract, name, driver=driver)\n        with self.assertRaises(AssertionError):\n            h['stu:123'] = 123\n\n    def test_setitems_too_many_dimensions_fails(self):\n        contract = 'blah'\n        name = 'scoob'\n\n        h = Hash(contract, name, driver=driver)\n\n        with self.assertRaises(Exception):\n            h['a', 'b', 'c', 'a', 'b', 'c', 'a', 'b', 'c', 'a', 'b', 'c', 'a', 'b', 'c', 'a', 'b', 'c'] = 1000\n\n    def test_setitems_key_too_large(self):\n        contract = 'blah'\n        name = 'scoob'\n\n        h = Hash(contract, name, driver=driver)\n\n        key = 'a' * 1025\n\n        with self.assertRaises(Exception):\n            h[key] = 100\n\n    def test_setitem_value_too_large(self):\n        pass\n\n    def test_setitems_keys_too_large(self):\n        contract = 'blah'\n        name = 'scoob'\n\n        h = Hash(contract, name, driver=driver)\n\n        key1 = 'a' * 800\n        key2 = 'b' * 100\n        key3 = 'c' * 200\n\n        with self.assertRaises(Exception):\n            h[key1, key2, key3] = 100\n\n    def test_getitems_keys(self):\n        contract = 'blah'\n        name = 'scoob'\n        delimiter = constants.INDEX_SEPARATOR\n\n        h = Hash(contract, name, driver=driver)\n\n        prefix = '{}{}{}{}'.format(contract, delimiter, name, h._delimiter)\n\n        raw_key = '{}stu:raghu'.format(prefix)\n\n        driver.set(raw_key, 54321)\n\n        driver.commit()\n\n        self.assertEqual(h['stu', 'raghu'], 54321)\n\n    def test_getsetitems(self):\n        contract = 'blah'\n        name = 'scoob'\n        delimiter = constants.INDEX_SEPARATOR\n\n        h = Hash(contract, name, driver=driver)\n\n        h['stu', 'raghu'] = 999\n\n        driver.commit()\n\n        self.assertEqual(h['stu', 'raghu'], 999)\n\n    def test_getitems_keys_too_large(self):\n        contract = 'blah'\n        name = 'scoob'\n\n        h = Hash(contract, name, driver=driver)\n\n        key1 = 'a' * 800\n        key2 = 'b' * 100\n        key3 = 'c' * 200\n\n        with self.assertRaises(Exception):\n            x = h[key1, key2, key3]\n\n    def test_getitems_too_many_dimensions_fails(self):\n        contract = 'blah'\n        name = 'scoob'\n\n        h = Hash(contract, name, driver=driver)\n\n        with self.assertRaises(Exception):\n            a = h['a', 'b', 'c', 'a', 'b', 'c', 'a', 'b', 'c', 'a', 'b', 'c', 'a', 'b', 'c', 'a', 'b', 'c']\n\n    def test_getitems_key_too_large(self):\n        contract = 'blah'\n        name = 'scoob'\n\n        h = Hash(contract, name, driver=driver)\n\n        key = 'a' * 1025\n\n        with self.assertRaises(Exception):\n            a = h[key]\n\n    def test_getitem_returns_default_value_if_none(self):\n        contract = 'blah'\n        name = 'scoob'\n\n        h = Hash(contract, name, driver=driver, default_value=0)\n\n        self.assertEqual(h['hello'], 0)\n\n    def test_get_all_when_none_exist(self):\n        contract = 'blah'\n        name = 'scoob'\n\n        h = Hash(contract, name, driver=driver, default_value=0)\n        all =h.all()\n        self.assertEqual(all, [])\n\n    def test_get_all_after_setting(self):\n        contract = 'blah'\n        name = 'scoob'\n\n        hsh = Hash(contract, name, driver=driver, default_value=0)\n\n        hsh['1'] = 123\n        hsh['2'] = 456\n        hsh['3'] = 789\n\n        l = [123, 456, 789]\n\n        # TODO - this ok ? :D\n        # driver.commit()\n\n        # we care about whats included, not order\n        self.assertSetEqual(set(hsh.all()), set(l))\n\n    def test_items_returns_kv_pairs(self):\n        contract = 'blah'\n        name = 'scoob'\n\n        hsh = Hash(contract, name, driver=driver, default_value=0)\n\n        hsh['1'] = 123\n        hsh['2'] = 456\n        hsh['3'] = 789\n\n        # driver.commit()\n\n        kvs = {\n            'blah.scoob:3': 789,\n            'blah.scoob:1': 123,\n            'blah.scoob:2': 456\n        }\n\n        got = hsh._items()\n\n        self.assertDictEqual(kvs, got)\n\n    def test_items_multi_hash_returns_kv_pairs(self):\n        contract = 'blah'\n        name = 'scoob'\n\n        hsh = Hash(contract, name, driver=driver, default_value=0)\n\n        hsh[0, '1'] = 123\n        hsh[0, '2'] = 456\n        hsh[0, '3'] = 789\n\n        hsh[1, '1'] = 999\n        hsh[1, '2'] = 888\n        hsh[1, '3'] = 777\n\n        # driver.commit()\n\n        kvs = {\n            'blah.scoob:0:3': 789,\n            'blah.scoob:0:1': 123,\n            'blah.scoob:0:2': 456\n        }\n\n        got = hsh._items(0)\n\n        self.assertDictEqual(kvs, got)\n\n    def test_items_multi_hash_returns_all(self):\n        contract = 'blah'\n        name = 'scoob'\n\n        hsh = Hash(contract, name, driver=driver, default_value=0)\n\n        hsh[0, '1'] = 123\n        hsh[0, '2'] = 456\n        hsh[0, '3'] = 789\n\n        hsh[1, '1'] = 999\n        hsh[1, '2'] = 888\n        hsh[1, '3'] = 777\n\n        # driver.commit()\n\n        kvs = {\n            'blah.scoob:0:3': 789,\n            'blah.scoob:0:1': 123,\n            'blah.scoob:0:2': 456,\n            'blah.scoob:1:3': 777,\n            'blah.scoob:1:1': 999,\n            'blah.scoob:1:2': 888\n        }\n\n        got = hsh._items()\n\n        self.assertDictEqual(kvs, got)\n\n    def test_items_clear_deletes_only_multi_hash(self):\n        contract = 'blah'\n        name = 'scoob'\n\n        hsh = Hash(contract, name, driver=driver, default_value=0)\n\n        hsh[0, '1'] = 123\n        hsh[0, '2'] = 456\n        hsh[0, '3'] = 789\n\n        hsh[1, '1'] = 999\n        hsh[1, '2'] = 888\n        hsh[1, '3'] = 777\n\n        # driver.commit()\n\n        kvs = {\n            'blah.scoob:0:3': 789,\n            'blah.scoob:0:1': 123,\n            'blah.scoob:0:2': 456\n        }\n\n        hsh.clear(1)\n\n        # driver.commit()\n\n        got = hsh._items()\n\n        self.assertDictEqual(kvs, got)\n\n    def test_all_multihash_returns_values(self):\n        contract = 'blah'\n        name = 'scoob'\n\n        hsh = Hash(contract, name, driver=driver, default_value=0)\n\n        hsh[0, '1'] = 123\n        hsh[0, '2'] = 456\n        hsh[0, '3'] = 789\n\n        hsh[1, '1'] = 999\n        hsh[1, '2'] = 888\n        hsh[1, '3'] = 777\n\n        l = [123, 456, 789]\n\n        # TODO\n        # Test works when below line is commented out - not sure if our driver works differently now\n        # driver.commit()\n\n        # we care about whats included, not order\n        self.assertSetEqual(set(hsh.all(0)), set(l))\n\n    def test_multihash_multiple_dims_clear_behaves_similar_to_single_dim(self):\n        contract = 'blah'\n        name = 'scoob'\n\n        hsh = Hash(contract, name, driver=driver, default_value=0)\n\n        hsh[1, 0, '1'] = 123\n        hsh[1, 0, '2'] = 456\n        hsh[1, 0, '3'] = 789\n\n        hsh[1, 1, '1'] = 999\n        hsh[1, 1, '2'] = 888\n        hsh[1, 1, '3'] = 777\n\n        # driver.commit()\n\n        kvs = {\n            'blah.scoob:1:0:3': 789,\n            'blah.scoob:1:0:1': 123,\n            'blah.scoob:1:0:2': 456\n        }\n\n        hsh.clear(1, 1)\n\n        # driver.commit()\n\n        got = hsh._items()\n\n        self.assertDictEqual(kvs, got)\n\n    def test_multihash_multiple_dims_all_gets_items_similar_to_single_dim(self):\n        contract = 'blah'\n        name = 'scoob'\n\n        hsh = Hash(contract, name, driver=driver, default_value=0)\n\n        hsh[1, 0, '1'] = 123\n        hsh[1, 0, '2'] = 456\n        hsh[1, 0, '3'] = 789\n\n        hsh[1, 1, '1'] = 999\n        hsh[1, 1, '2'] = 888\n        hsh[1, 1, '3'] = 777\n\n        l = [123, 456, 789]\n\n        # driver.commit()\n\n        # we care about whats included, not order\n        self.assertSetEqual(set(hsh.all(1, 0)), set(l))\n\n    def test_clear_items_deletes_all_key_value_pairs(self):\n        contract = 'blah'\n        name = 'scoob'\n\n        hsh = Hash(contract, name, driver=driver, default_value=0)\n\n        hsh['1'] = 123\n        hsh['2'] = 456\n        hsh['3'] = 789\n\n        # TODO - test works without commit - is ok\n        # driver.commit()\n\n        kvs = {\n            'blah.scoob:3': 789,\n            'blah.scoob:1': 123,\n            'blah.scoob:2': 456\n        }\n\n        got = hsh._items()\n\n        self.assertDictEqual(kvs, got)\n        hsh.clear()\n\n        # driver.commit()\n\n        got = hsh._items()\n\n        self.assertDictEqual({}, got)\n\n\nclass TestForeignVariable(TestCase):\n    def setUp(self):\n        driver.flush_full()\n\n    def tearDown(self):\n        driver.flush_full()\n\n    def test_set(self):\n        contract = 'stustu'\n        name = 'balance'\n\n        f_contract = 'colinbucks'\n        f_name = 'balances'\n\n        f = ForeignVariable(contract, name, f_contract, f_name, driver=driver)\n\n        with self.assertRaises(ReferenceError):\n            f.set('poo')\n\n    def test_get(self):\n        # set up the foreign variable\n        contract = 'stustu'\n        name = 'balance'\n\n        f_contract = 'colinbucks'\n        f_name = 'balances'\n\n        f = ForeignVariable(contract, name, f_contract, f_name, driver=driver)\n\n        # set the variable using the foreign names (assuming this is another contract namespace)\n        v = Variable(f_contract, f_name, driver=driver)\n        v.set('howdy')\n\n        self.assertEqual(f.get(), 'howdy')\n\n\nclass TestForeignHash(TestCase):\n    def setUp(self):\n        driver.flush_full()\n\n    def tearDown(self):\n        #_driver.flush_full()\n        pass\n\n    def test_set(self):\n        # set up the foreign variable\n        contract = 'stustu'\n        name = 'balance'\n\n        f_contract = 'colinbucks'\n        f_name = 'balances'\n\n        f = ForeignHash(contract, name, f_contract, f_name, driver=driver)\n\n        with self.assertRaises(ReferenceError):\n            f._set('stu', 1234)\n\n    def test_get(self):\n        # set up the foreign variable\n        contract = 'stustu'\n        name = 'balance'\n\n        f_contract = 'colinbucks'\n        f_name = 'balances'\n\n        f = ForeignHash(contract, name, f_contract, f_name, driver=driver)\n\n        h = Hash(f_contract, f_name, driver=driver)\n        h._set('howdy', 555)\n\n        self.assertEqual(f._get('howdy'), 555)\n\n    def test_setitem(self):\n        # set up the foreign variable\n        contract = 'stustu'\n        name = 'balance'\n\n        f_contract = 'colinbucks'\n        f_name = 'balances'\n\n        f = ForeignHash(contract, name, f_contract, f_name, driver=driver)\n\n        with self.assertRaises(ReferenceError):\n            f['stu'] = 1234\n\n    def test_getitem(self):\n        # set up the foreign variable\n        contract = 'stustu'\n        name = 'balance'\n\n        f_contract = 'colinbucks'\n        f_name = 'balances'\n\n        f = ForeignHash(contract, name, f_contract, f_name, driver=driver)\n\n        h = Hash(f_contract, f_name, driver=driver)\n        h['howdy'] = 555\n\n        self.assertEqual(f['howdy'], 555)\n        \n        \n\n\n\nclass TestLogEvent(TestCase):\n\n    def setUp(self):\n\n        # Define the event arguments\n        self.args = {\n            \"from\": {\"type\": str, \"idx\": True},\n            \"to\": {\"type\": str, \"idx\": True},\n            \"amount\": {\"type\": (int, float)}\n        }\n\n        # Create a LogEvent instance\n        self.log_event = LogEvent(contract=\"test_contract\", name=\"con_some_contract\", event=\"Transfer\", params=self.args)\n        self.contract = \"test_contract\"\n        self.name = \"Transfer\"\n        self.driver = driver  \n        \n    def test_log_event(self):\n        contract = 'currency'\n        name = 'Transfer'\n        \n        args = {\n            'from': {\n                'type': str,\n                'idx': True\n            }, \n            'to': {\n                'type': str,\n                'idx': True\n            },\n            'amount': {\n                'type': (int, float)\n            }\n        }\n        \n\n        le = LogEvent(contract, name, event=name, params=args, driver=driver)\n\n\n    def test_log_event_with_max_indexed_args(self):\n        contract = 'currency'\n        name = 'Transfer'\n        \n        args = {\n            'from': {\n                'type': str,\n                'idx': True\n            }, \n            'to': {\n                'type': str,\n                'idx': True\n            },\n            'amount': {\n                'type': (int, float),\n                'idx': True\n            }\n        }\n        # This should not raise an assertion error\n        le = LogEvent(contract, name, event=name, params=args, driver=driver)\n        self.assertIsInstance(le, LogEvent)\n        \n\n    def test_log_event_with_too_many_indexed_args(self):\n        contract = 'currency'\n        name = 'Transfer'\n        \n        args = {\n            'from': {\n                'type': str,\n                'idx': True\n            }, \n            'to': {\n                'type': str,\n                'idx': True\n            },\n            'amount': {\n                'type': (int, float),\n                'idx': True\n            },\n            'extra': {\n                'type': str,\n                'idx': True\n            }\n        }\n        \n        # This should raise an assertion error\n        with self.assertRaisesRegex(AssertionError, \"Args must have at most three indexed arguments.\"):\n            LogEvent(contract, name, event=name, params=args, driver=driver)\n\n    def test_write_event_success(self):\n        # Define the event data\n        data = {\n            \"from\": \"Alice\",\n            \"to\": \"Bob\",\n            \"amount\": 100\n        }\n\n        # Call the write_event method\n        self.log_event.write_event(data)\n\n        # No assertions needed here if no exceptions are raised\n\n    def test_write_event_missing_argument(self):\n        # Define the event data with a missing argument\n        data = {\n            \"from\": \"Alice\",\n            \"amount\": 100\n        }\n\n        with self.assertRaises(AssertionError) as context:\n            self.log_event.write_event(data)\n\n        self.assertIn(\"Data must have the same number of arguments as specified in the event.\", str(context.exception))\n\n    def test_write_event_wrong_type(self):\n        # Define the event data with a wrong type\n        data = {\n            \"from\": \"Alice\",\n            \"to\": \"Bob\",\n            \"amount\": \"one hundred\"\n        }\n\n        with self.assertRaises(AssertionError) as context:\n            self.log_event.write_event(data)\n\n        self.assertIn(\"Argument amount is the wrong type!\", str(context.exception))\n        \n\n    def test_write_event_with_empty_data(self):\n        # Test with an empty dictionary\n        data = {}\n\n        with self.assertRaises(AssertionError) as context:\n            self.log_event.write_event(data)\n\n        self.assertIn(\"Data must have the same number of arguments as specified in the event.\", str(context.exception))\n\n    def test_write_event_with_none(self):\n        # Test with None as data\n        data = None\n\n        with self.assertRaises(TypeError) as context:\n            self.log_event.write_event(data)\n\n        self.assertIn(\"object of type 'NoneType' has no len()\", str(context.exception))\n\n    def test_write_event_with_invalid_argument_names(self):\n        # Define the event arguments correctly\n        args = {\n            \"from\": {\"type\": str, \"idx\": True},\n            \"to\": {\"type\": str, \"idx\": True},\n            \"amount\": {\"type\": (int, float)}\n        }\n\n        # Create a LogEvent instance\n        log_event = LogEvent(self.contract, self.name, event=self.name, params=args, driver=self.driver)\n\n        # Define event data with an unexpected argument name\n        data = {\n            \"from\": \"Alice\",\n            \"to\": \"Bob\",\n            \"unexpected_arg\": 100\n        }\n\n        # This should raise an assertion error\n        with self.assertRaises(AssertionError) as context:\n            log_event.write_event(data)\n\n        self.assertIn(\"Unexpected argument unexpected_arg in the data dictionary.\", str(context.exception))\n\nclass TestLogEventBoundaryIndexedArgs(TestCase):\n    def setUp(self):\n        # Common setup for the tests\n        self.contract = \"test_contract\"\n        self.name = \"Transfer\"\n        self.driver = driver  # Assuming driver is defined elsewhere\n\n    def test_log_event_with_exactly_three_indexed_args(self):\n        # Define arguments with exactly three indexed arguments\n        args = {\n            \"from\": {\"type\": str, \"idx\": True},\n            \"to\": {\"type\": str, \"idx\": True},\n            \"amount\": {\"type\": (int, float), \"idx\": True}\n        }\n\n        # This should not raise an assertion error\n        log_event = LogEvent(self.contract, self.name, event=self.name, params=args, driver=self.driver)\n        self.assertIsInstance(log_event, LogEvent)\n\n    def test_log_event_with_more_than_three_indexed_args(self):\n        # Define arguments with more than three indexed arguments\n        args = {\n            \"from\": {\"type\": str, \"idx\": True},\n            \"to\": {\"type\": str, \"idx\": True},\n            \"amount\": {\"type\": (int, float), \"idx\": True},\n            \"extra\": {\"type\": str, \"idx\": True}\n        }\n\n        # This should raise an assertion error\n        with self.assertRaises(AssertionError) as context:\n            LogEvent(self.contract, self.name, event=self.name, params=args, driver=self.driver)\n\n        self.assertIn(\"Args must have at most three indexed arguments.\", str(context.exception))\n        \nimport random\nimport string\n\nclass TestLogEventTypeEnforcementFuzz(TestCase):\n    def setUp(self):\n        # Define the event arguments\n        self.args = {\n            \"from\": {\"type\": str, \"idx\": True},\n            \"to\": {\"type\": str, \"idx\": True},\n            \"amount\": {\"type\": (int, float)}\n        }\n\n        # Create a LogEvent instance\n        self.log_event = LogEvent(contract=\"test_contract\", name=\"con_some_contract\", event=\"Transfer\", params=self.args)\n\n    def random_string(self, length=10):\n        return ''.join(random.choices(string.ascii_letters + string.digits, k=length))\n\n    def test_write_event_with_random_data(self):\n        # Generate random data for each argument\n        for _ in range(100):  # Run 100 iterations for fuzz testing\n            data = {\n                \"from\": self.random_string(),\n                \"to\": self.random_string(),\n                \"amount\": random.choice([self.random_string(), None, [], {}, set(), object()])\n            }\n\n            with self.assertRaises(AssertionError) as context:\n                self.log_event.write_event(data)\n\n            self.assertIn(\"Argument amount is the wrong type!\", str(context.exception))\n\n    def test_write_event_with_random_structures(self):\n        # Test with random structures for the 'amount' field\n        random_structures = [None, [], {}, set(), object(), lambda x: x, b\"bytes\", (1, 2, 3)]\n\n        for structure in random_structures:\n            data = {\n                \"from\": \"Alice\",\n                \"to\": \"Bob\",\n                \"amount\": structure\n            }\n\n            with self.assertRaises(AssertionError) as context:\n                self.log_event.write_event(data)\n\n            self.assertIn(\"Argument amount is the wrong type!\", str(context.exception))\n\n    def test_write_event_with_random_numeric_types(self):\n        # Test with various numeric types that are not allowed\n        random_numeric_types = [\n            complex(1, 1), \n            # float('nan'), # Doesnt raise IS THIS OK ?\n            # float('inf'), # Doesn't raise IS THIS OK ?\n            # -float('inf') # Doesn't raise IS THIS OK ?\n        ]\n\n        for num in random_numeric_types:\n            data = {\n                \"from\": \"Alice\",\n                \"to\": \"Bob\",\n                \"amount\": num\n            }\n\n            with self.assertRaises(AssertionError) as context:\n                self.log_event.write_event(data)\n\n            self.assertIn(\"Argument amount is the wrong type!\", str(context.exception))\n\nclass TestLogEventInvalidArgumentNames(TestCase):\n    def setUp(self):\n        # Define the event arguments\n        self.args = {\n            \"from\": {\"type\": str, \"idx\": True},\n            \"to\": {\"type\": str, \"idx\": True},\n            \"amount\": {\"type\": (int, float)}\n        }\n\n        # Create a LogEvent instance\n        self.log_event = LogEvent(contract=\"test_contract\", name=\"con_some_contract\", event=\"Transfer\", params=self.args)\n\n    def test_write_event_with_invalid_argument_names(self):\n        # Define event data with an unexpected argument name\n        data = {\n            \"from\": \"Alice\",\n            \"to\": \"Bob\",\n            \"unexpected_arg\": 100\n        }\n\n        # This should raise an assertion error\n        with self.assertRaises(AssertionError) as context:\n            self.log_event.write_event(data)\n\n        self.assertIn(\"Unexpected argument unexpected_arg in the data dictionary.\", str(context.exception))\n\nclass TestLogEventLargeData(TestCase):\n    def setUp(self):\n        # Define the event arguments\n        self.args = {\n            \"from\": {\"type\": str, \"idx\": True},\n            \"to\": {\"type\": str, \"idx\": True},\n            \"amount\": {\"type\": (int, float)}\n        }\n\n        # Create a LogEvent instance\n        self.log_event = LogEvent(contract=\"test_contract\", name=\"con_some_contract\", event=\"Transfer\", params=self.args)\n\n    def test_write_event_with_large_data(self):\n        # Generate a large string for the 'from' and 'to' fields\n        large_string = 'A' * 10**6  # 1 million characters\n\n        # Generate a large number for the 'amount' field\n        large_number = 10**18  # A very large number\n\n        # Define the event data with large values\n        data = {\n            \"from\": large_string,\n            \"to\": large_string,\n            \"amount\": large_number\n        }\n\n        # Call the write_event method and ensure it completes without error\n        try:\n            self.log_event.write_event(data)\n            success = True\n        except Exception as e:\n            success = False\n            print(f\"Error occurred: {e}\")\n\n        self.assertFalse(success, \"write_event should not handle large data without errors.\")\n\n\nclass TestLogEventInvalidDataTypes(TestCase):\n    def setUp(self):\n        # Define the event arguments\n        self.args = {\n            \"from\": {\"type\": str, \"idx\": True},\n            \"to\": {\"type\": str, \"idx\": True},\n            \"amount\": {\"type\": (int, float)}\n        }\n\n        # Create a LogEvent instance\n        self.log_event = LogEvent(contract=\"test_contract\", name=\"con_some_contract\", event=\"Transfer\", params=self.args)\n\n    def test_write_event_with_invalid_string_type(self):\n        # Use an invalid type (e.g., list) for the 'from' field\n        data = {\n            \"from\": [\"Alice\"],  # Invalid type: list instead of str\n            \"to\": \"Bob\",\n            \"amount\": 100\n        }\n\n        # This should raise an assertion error\n        with self.assertRaises(AssertionError) as context:\n            self.log_event.write_event(data)\n\n        self.assertIn(\"Argument from is the wrong type!\", str(context.exception))\n\n    def test_write_event_with_invalid_numeric_type(self):\n        # Use an invalid type (e.g., string) for the 'amount' field\n        data = {\n            \"from\": \"Alice\",\n            \"to\": \"Bob\",\n            \"amount\": \"one hundred\"  # Invalid type: str instead of int/float/ContractingDecimal\n        }\n\n        # This should raise an assertion error\n        with self.assertRaises(AssertionError) as context:\n            self.log_event.write_event(data)\n\n        self.assertIn(\"Argument amount is the wrong type!\", str(context.exception))\n\n    def test_write_event_with_unexpected_object_type(self):\n        # Use an unexpected object type for the 'to' field\n        data = {\n            \"from\": \"Alice\",\n            \"to\": object(),  # Invalid type: object instead of str\n            \"amount\": 100\n        }\n\n        # This should raise an assertion error\n        with self.assertRaises(AssertionError) as context:\n            self.log_event.write_event(data)\n\n        self.assertIn(\"Argument to is the wrong type!\", str(context.exception))\n        \nclass TestLogEventNonStandardTypes(TestCase):\n    def setUp(self):\n        # Common setup for the tests\n        self.contract = \"test_contract\"\n        self.name = \"Transfer\"\n        self.driver = driver  # Assuming driver is defined elsewhere\n\n    def test_log_event_with_non_standard_type(self):\n        # Define arguments with a non-standard type (e.g., list)\n        args = {\n            \"from\": {\"type\": list, \"idx\": True},  # Invalid type: list\n            \"to\": {\"type\": str, \"idx\": True},\n            \"amount\": {\"type\": (int, float, ContractingDecimal)}\n        }\n\n        # This should raise an assertion error\n        with self.assertRaises(AssertionError) as context:\n            LogEvent(self.contract, self.name, event=self.name, params=args, driver=self.driver)\n\n        self.assertIn(\"Each type in args must be str, int, float, decimal or bool.\", str(context.exception))\n\n    def test_log_event_with_custom_object_type(self):\n        # Define arguments with a custom object type\n        class CustomType:\n            pass\n\n        args = {\n            \"from\": {\"type\": CustomType, \"idx\": True},  # Invalid type: CustomType\n            \"to\": {\"type\": str, \"idx\": True},\n            \"amount\": {\"type\": (int, float)}\n        }\n\n        # This should raise an assertion error\n        with self.assertRaises(AssertionError) as context:\n            LogEvent(self.contract, self.name, event=self.name, params=args, driver=self.driver)\n\n        self.assertIn(\"Each type in args must be str, int, float, decimal or bool.\", str(context.exception))\n\nif __name__ == '__main__':\n    unittest.main()"
  },
  {
    "path": "tests/unit/test_parser.py",
    "content": "from contracting.compilation import parser\nfrom contracting.compilation.compiler import ContractingCompiler\nfrom unittest import TestCase\n\n\nclass TestParser(TestCase):\n    def setUp(self):\n        self.compiler = ContractingCompiler()\n\n    def test_methods_for_contract_single_function(self):\n        code = '''\n@export\ndef test_func(arg: str, arg2: int):\n    return arg, arg2\n        '''\n\n        compiled = self.compiler.parse_to_code(code)\n\n        expected = [{\n            'name': 'test_func',\n            'arguments': [\n                {\n                    'name': 'arg',\n                    'type': 'str'\n                },\n                {\n                    'name': 'arg2',\n                    'type': 'int'\n                }\n            ]\n        }]\n\n        got = parser.methods_for_contract(compiled)\n\n        self.assertListEqual(expected, got)\n\n    def test_methods_for_contract_datetime(self):\n        code = '''\n@export\ndef thing(arg: datetime.datetime, arg2: datetime.timedelta):\n    return 123        \n'''\n        compiled = self.compiler.parse_to_code(code)\n        got = parser.methods_for_contract(compiled)\n\n        expected = [\n            {\n                'name': 'thing',\n                'arguments': [\n                    {\n                        'name': 'arg',\n                        'type': 'datetime.datetime'\n                    },\n                    {\n                        'name': 'arg2',\n                        'type': 'datetime.timedelta'\n                    }\n                 ]\n             }\n        ]\n\n        self.assertEqual(expected, got)\n\n    def test_methods_for_contract_multiple_functions_and_privates(self):\n        code = '''\n@export\ndef test_func(arg: str, arg2: int):\n    return arg, arg2\n    \n@export\ndef another_one(something: Any, something_else: dict):\n    a = 123\n    b = 456\n    return add(a, b)\n    \ndef add(a, b):\n    return a + b\n'''\n        compiled = self.compiler.parse_to_code(code)\n\n        expected = [{\n            'name': 'test_func',\n            'arguments': [\n                {\n                    'name': 'arg',\n                    'type': 'str'\n                },\n                {\n                    'name': 'arg2',\n                    'type': 'int'\n                }\n            ],\n        },\n        {\n            'name': 'another_one',\n            'arguments': [\n                {\n                    'name': 'something',\n                    'type': 'Any'\n                },\n                {\n                    'name': 'something_else',\n                    'type': 'dict'\n                }\n            ]\n        }]\n\n        got = parser.methods_for_contract(compiled)\n\n        self.assertListEqual(expected, got)\n\n    def test_variables_for_contract_passes_election_house(self):\n        code = '''\n# Convenience\nI = importlib\n\n#Policies\npolicies = Hash()\n\n# Policy interface\npolicy_interface = [\n    I.Func('vote', args=('vk', 'obj')),\n    I.Func('current_value')\n]\n\n@export\ndef register_policy(contract: str):\n    if policies[contract] is None:\n        # Attempt to import the contract to make sure it is already submitted\n        p = I.import_module(contract)\n\n        # Assert ownership is election_house and interface is correct\n        assert I.owner_of(p) == ctx.this, \\\n            'Election house must control the policy contract!'\n\n        assert I.enforce_interface(p, policy_interface), \\\n            'Policy contract does not follow the correct interface'\n\n        policies[contract] = True\n    else:\n        raise Exception('Policy already registered')\n\n@export\ndef current_value_for_policy(policy: str):\n    assert policies.get(policy) is not None, 'Invalid policy.'\n    p = I.import_module(policy)\n\n    return p.current_value()\n\n@export\ndef vote(policy: str, value: Any):\n    # Verify policy has been registered\n    assert policies.get(policy) is not None, 'Invalid policy.'\n    p = I.import_module(policy)\n\n    p.vote(vk=ctx.caller, obj=value)\n    '''\n\n        compiled = self.compiler.parse_to_code(code)\n\n        got = parser.variables_for_contract(compiled)\n\n        expected = {\n            'variables': [],\n            'hashes': ['policies']\n        }\n\n        self.assertDictEqual(got, expected)\n\n    def test_variables_for_contract_multiple_variables(self):\n        code = '''\nv1 = Variable()\nv2 = Variable()\nv3 = Variable()\n\n@export\ndef something():\n   return 1\n        '''\n\n        compiled = self.compiler.parse_to_code(code)\n\n        got = parser.variables_for_contract(compiled)\n\n        expected = {\n            'variables': ['v1', 'v2', 'v3'],\n            'hashes': []\n        }\n\n        self.assertDictEqual(got, expected)\n\n    def test_variables_for_contract_multiple_hashes(self):\n        code = '''\nh1 = Hash()\nh2 = Hash()\nh3 = Hash()\n\n@export\ndef something():\n   return 1\n        '''\n\n        compiled = self.compiler.parse_to_code(code)\n\n        got = parser.variables_for_contract(compiled)\n\n        expected = {\n            'variables': [],\n            'hashes': ['h1', 'h2', 'h3']\n        }\n\n        self.assertDictEqual(got, expected)\n\n    def test_variables_mix(self):\n        code = '''\nv1 = Variable()\nv2 = Variable()\nv3 = Variable()\nh1 = Hash()\nh2 = Hash()\nh3 = Hash()\n\n@export\ndef something():\n   return 1\n        '''\n\n        compiled = self.compiler.parse_to_code(code)\n\n        got = parser.variables_for_contract(compiled)\n\n        expected = {\n            'variables': ['v1', 'v2', 'v3'],\n            'hashes': ['h1', 'h2', 'h3']\n        }\n\n        self.assertDictEqual(got, expected)\n\n"
  },
  {
    "path": "tests/unit/test_revert_on_exception.py",
    "content": "import unittest\nfrom contracting.storage.driver import Driver\nfrom contracting.execution.executor import Executor\nfrom contracting.constants import STAMPS_PER_TAU\nfrom xian.processor import TxProcessor\nfrom contracting.client import ContractingClient\nimport contracting\nimport random\nimport string\nimport os\nimport sys\nfrom loguru import logger\n\n# Get the directory where the script is located\nscript_dir = os.path.dirname(os.path.abspath(sys.argv[0]))\n\n# Change the current working directory\nos.chdir(script_dir)\n\ndef submission_kwargs_for_file(f):\n    # Get the file name only by splitting off directories\n    split = f.split('/')\n    split = split[-1]\n\n    # Now split off the .s\n    split = split.split('.')\n    contract_name = split[0]\n\n    with open(f) as file:\n        contract_code = file.read()\n\n    return {\n        'name': f'con_{contract_name}',\n        'code': contract_code,\n    }\n\nTEST_SUBMISSION_KWARGS = {\n    'sender': 'stu',\n    'contract_name': 'submission',\n    'function_name': 'submit_contract'\n}\n\nclass MyTestCase(unittest.TestCase):\n\n    def setUp(self):\n        self.c = ContractingClient()\n        self.tx_processor = TxProcessor(client=self.c)\n        # Hard load the submission contract\n        self.d = self.c.raw_driver\n        self.d.flush_full()\n\n        self.script_dir = os.path.dirname(os.path.abspath(__file__))\n        submission_file_path = os.path.join(self.script_dir, \"contracts\", \"submission.s.py\")\n\n        with open(submission_file_path) as f:\n            contract = f.read()\n\n        self.d.set_contract(name='submission', code=contract)\n        \n        currency_file_path = os.path.join(self.script_dir, \"contracts\", \"currency.s.py\")\n\n        with open(currency_file_path) as f:\n            contract = f.read()\n        self.d.set_contract(name='currency', code=contract)\n\n        self.c.executor.execute(**TEST_SUBMISSION_KWARGS, kwargs=submission_kwargs_for_file(currency_file_path), metering=False, auto_commit=True)\n\n        exception_file_path = os.path.join(self.script_dir, \"contracts\", \"exception.s.py\")\n\n        with open(exception_file_path) as f:\n            contract = f.read()\n        self.d.set_contract(name='exception', code=contract)\n\n        self.c.executor.execute(**TEST_SUBMISSION_KWARGS,\n                       kwargs=submission_kwargs_for_file(exception_file_path), \n                       metering=False, auto_commit=True)\n        self.d.commit()\n\n    def test_exception(self):\n        prior_balance = self.d.get('con_exception.balances:stu')\n        logger.debug(f\"Prior balance (exception): {prior_balance}\")\n\n        \n        output = self.tx_processor.process_tx({\n            \"payload\":\n            {'sender': 'stu', 'contract': 'con_exception', 'function': 'transfer', 'kwargs': {'amount': 100, 'to': 'colin'},\"stamps_supplied\":1000},\n            \"metadata\":\n            {\"signature\":\"abc\"},\"b_meta\":{\"nanos\":0,\n            \"hash\":\"0x0\",\"height\":0, \"chain_id\":\"xian-1\"}})\n        logger.debug(f\"Output (exception): {output}\")\n\n        new_balance = self.d.get('con_exception.balances:stu')\n        logger.debug(f\"New balance (exception): {new_balance}\")\n\n        self.assertEqual(prior_balance, new_balance)\n\n    def test_non_exception(self):\n        prior_balance = self.d.get('con_currency.balances:stu')\n\n        output = self.tx_processor.process_tx({\n            \"payload\":\n            {'sender': 'stu', 'contract': 'con_currency', 'function': 'transfer', 'kwargs': {'amount': 100, 'to': 'colin'},\"stamps_supplied\":1000},\n            \"metadata\":\n            {\"signature\":\"abc\"},\"b_meta\":{\"nanos\":0,\"hash\":\"0x0\",\"height\":0, \"chain_id\":\"xian-1\"}})\n        \n        new_balance = self.d.get('con_currency.balances:stu')\n        logger.debug(f\"New balance (non-exception): {new_balance}\")\n\n        self.assertEqual(prior_balance - 100, new_balance)\n\nif __name__ == '__main__':\n    unittest.main()\n"
  },
  {
    "path": "tests/unit/test_runtime.py",
    "content": "from unittest import TestCase\nfrom contracting.execution import runtime\nimport sys\nimport psutil\nimport os\n\n\nclass TestRuntime(TestCase):\n    def tearDown(self):\n        runtime.rt.tracer.stop()\n        runtime.rt.clean_up()\n\n    def test_tracer_works_roughly(self):\n        stamps = 1000000\n        # This doesnt work because we are only metering things with _contract_ in Globals\n        runtime.rt.set_up(stmps=stamps, meter=True)\n        globals()['__contract__'] = True\n        x = max([i for i in range(2)])\n        globals()['__contract__'] = False\n        runtime.rt.tracer.stop()\n        used = runtime.rt.tracer.get_stamp_used()\n        runtime.rt.clean_up()\n        self.assertLess(stamps - used, stamps)\n\n    def test_tracer_bypass_records_no_stamps(self):\n        stamps = 1000\n        runtime.rt.set_up(stmps=stamps, meter=False)\n        a = 5\n        b = 5\n        runtime.rt.tracer.stop()\n        used = runtime.rt.tracer.get_stamp_used()\n        runtime.rt.clean_up()\n        self.assertEqual(stamps - used, stamps)\n\n    def test_arbitrary_modification_of_stamps_works(self):\n        stamps = 1000\n        sub = 500\n        runtime.rt.set_up(stmps=stamps, meter=True)\n        globals()['__contract__'] = True\n        a = 5\n        globals()['__contract__'] = False\n        runtime.rt.tracer.stop()\n        used_1 = runtime.rt.tracer.get_stamp_used()\n        runtime.rt.tracer.set_stamp(stamps - sub)\n        used_2 = runtime.rt.tracer.get_stamp_used()\n        runtime.rt.clean_up()\n\n        print(used_1, used_2)\n\n    def test_starting_and_stopping_tracer_works_roughly(self):\n        stamps = 1000000\n        runtime.rt.set_up(stmps=stamps, meter=True)\n        globals()['__contract__'] = True\n        x = max([i for i in range(4)])\n        globals()['__contract__'] = False\n        runtime.rt.tracer.stop()\n        used_1 = runtime.rt.tracer.get_stamp_used()\n        runtime.rt.clean_up()\n\n        stamps = 10000000\n        runtime.rt.set_up(stmps=stamps, meter=True)\n        globals()['__contract__'] = True\n        x = max([i for i in range(1)])\n        runtime.rt.tracer.stop()\n        x = max([i for i in range(1)])\n        runtime.rt.tracer.stop()\n        globals()['__contract__'] = False\n        used_2 = runtime.rt.tracer.get_stamp_used()\n        runtime.rt.clean_up()\n\n        self.assertGreater(used_1, used_2)\n\n    def test_modifying_stamps_during_tracing(self):\n        stamps = 10000\n        runtime.rt.set_up(stmps=stamps, meter=True)\n        a = 5\n        b = 5\n        runtime.rt.tracer.stop()\n        c = 5\n        d = 5\n        e = 5\n        runtime.rt.clean_up()\n        used_1 = runtime.rt.tracer.get_stamp_used()\n\n        stamps = 5000\n        runtime.rt.set_up(stmps=stamps, meter=True)\n        a = 5\n        b = 5\n        runtime.rt.tracer.stop()\n        used_1 = runtime.rt.tracer.get_stamp_used()\n        runtime.rt.set_up(stmps=stamps - used_1, meter=True)\n        c = 5\n        d = 5\n        e = 5\n        runtime.rt.clean_up()\n        used_2 = runtime.rt.tracer.get_stamp_used()\n\n        print(used_1, used_2)\n\n    def test_add_exists(self):\n        stamps = 1000\n\n        runtime.rt.set_up(stmps=stamps, meter=True)\n\n        runtime.rt.tracer.add_cost(900)\n        runtime.rt.tracer.stop()\n\n        used_1 = runtime.rt.tracer.get_stamp_used()\n\n        runtime.rt.clean_up()\n        print(used_1)\n\n    def test_deduct_write_adjusts_total_writes(self):\n        stamps = 1000\n\n        runtime.rt.set_up(stmps=stamps, meter=True)\n\n        self.assertEqual(runtime.rt.writes, 0)\n\n        runtime.rt.deduct_write('a', 'bad')\n\n        self.assertEqual(runtime.rt.writes, 4)\n\n        runtime.rt.clean_up()\n\n    def test_deduct_write_fails_if_too_many_writes(self):\n        stamps = 1000\n\n        runtime.rt.set_up(stmps=stamps, meter=True)\n\n        self.assertEqual(runtime.rt.writes, 0)\n\n        runtime.rt.deduct_write('a', 'bad')\n\n        self.assertEqual(runtime.rt.writes, 4)\n\n        with self.assertRaises(AssertionError):\n            runtime.rt.deduct_write('a', 'b' * 32 * 1024)\n\n        runtime.rt.clean_up()"
  },
  {
    "path": "tests/unit/test_state_management.py",
    "content": "import unittest\r\nfrom xian.processor import TxProcessor\r\nfrom contracting.client import ContractingClient\r\nfrom xian.services.simulator import Simulator\r\nfrom xian.constants import Constants\r\nimport os\r\nimport pathlib\r\nclass MyTestCase(unittest.TestCase):\r\n\r\n    def setUp(self):\r\n        constants = Constants()\r\n        self.c = ContractingClient(storage_home=constants.STORAGE_HOME)\r\n        self.tx_processor = TxProcessor(client=self.c)\r\n        self.stamp_calculator = Simulator()\r\n        self.d = self.c.raw_driver\r\n        self.d.flush_full()\r\n\r\n        script_dir = os.path.dirname(os.path.abspath(__file__))\r\n\r\n        submission_contract_path = os.path.join(script_dir, \"contracts\", \"submission.s.py\")\r\n\r\n        with open(submission_contract_path) as f:\r\n            contract = f.read()\r\n        self.d.set_contract(name=\"submission\", code=contract)\r\n\r\n    def deploy_broken_stuff(self):\r\n         # Get the directory where the script is located\r\n        script_dir = os.path.dirname(os.path.abspath(__file__))\r\n\r\n        proxythis_path = os.path.join(script_dir, \"contracts\", \"proxythis.py\")\r\n        with open(proxythis_path) as f:\r\n            contract = f.read()\r\n\r\n            self.c.submit(\r\n                contract,\r\n                name=\"con_proxythis\",\r\n            )\r\n\r\n            self.proxythis = self.c.get_contract(\"con_proxythis\")\r\n\r\n        thistest2_path = os.path.join(script_dir, \"contracts\", \"thistest2.py\")\r\n\r\n        with open(thistest2_path) as f:\r\n            contract = f.read()\r\n\r\n            self.c.submit(\r\n                contract,\r\n                name=\"con_thistest2\",\r\n            )\r\n\r\n            self.thistest2 = self.c.get_contract(\"con_thistest2\")\r\n\r\n    def test_submit(self):\r\n        self.deploy_broken_stuff()\r\n        self.assertEqual(self.proxythis.proxythis(con=\"con_thistest2\", signer=\"address\"), (\"con_thistest2\", \"con_proxythis\"))\r\n        self.assertEqual(self.proxythis.noproxy(signer=\"address\"), (\"con_proxythis\", \"address\"))\r\n        self.assertEqual(self.proxythis.nestedproxythis(con=\"con_thistest2\", signer=\"address\"), (\"con_thistest2\", \"con_proxythis\"))\r\n\r\nif __name__ == '__main__':\r\n    unittest.main()"
  },
  {
    "path": "tests/unit/test_stdlib_hashing.py",
    "content": "from unittest import TestCase\nfrom contracting.stdlib.bridge.hashing import sha256, sha3\n\n\nclass TestHashing(TestCase):\n    def test_sha3(self):\n        secret = '1a54390942257a70bb843c1bd94eb996'\n        _hash = '6c839446b4d4fa2582af5011730c680b3ee39929f041b7bee6f376211cc710f7'\n\n        self.assertEqual(_hash, sha3(secret))\n\n    def test_sha256(self):\n        secret = '842b65a7d48e3a3c3f0e9d37eaced0b2'\n        _hash = 'eaf48a02d3a4bb3aeb0ecb337f6efb026ee0bbc460652510cff929de78935514'\n\n        self.assertEqual(_hash, sha256(secret))"
  },
  {
    "path": "tests/unit/test_sys_contracts/__init__.py",
    "content": ""
  },
  {
    "path": "tests/unit/test_sys_contracts/bad_lint.s.py",
    "content": "def no_exports():\n    return 'hahaha'"
  },
  {
    "path": "tests/unit/test_sys_contracts/compile_this.s.py",
    "content": "@export\ndef good_function():\n    return 5\n\ndef another_function():\n    return 100"
  },
  {
    "path": "tests/unit/test_sys_contracts/currency.s.py",
    "content": "xrate = Variable()\nseed_amount = Variable()\nbalances = Hash()\nallowed = Hash()\n\n@construct\ndef seed():\n    xrate = 1.0\n    seed_amount.set(1000000)\n    balances['reserves'] = 0\n\n    founder_wallets = [\n        '324ee2e3544a8853a3c5a0ef0946b929aa488cbe7e7ee31a0fef9585ce398502',\n        'a103715914a7aae8dd8fddba945ab63a169dfe6e37f79b4a58bcf85bfd681694',\n        '20da05fdba92449732b3871cc542a058075446fedb41430ee882e99f9091cc4d',\n        'ed19061921c593a9d16875ca660b57aa5e45c811c8cf7af0cfcbd23faa52cbcd',\n        'cb9bfd4b57b243248796e9eb90bc4f0053d78f06ce68573e0fdca422f54bb0d2',\n        'c1f845ad8967b93092d59e4ef56aef3eba49c33079119b9c856a5354e9ccdf84'\n    ]\n\n    for w in founder_wallets:\n        balances[w] = seed_amount.get()\n\n\ndef assert_stamps(stamps):\n    assert balances[ctx.signer] >= stamps, \\\n        \"Not enough funds to submit stamps\"\n\n\ndef submit_stamps(stamps):\n    stamps *= xrate\n\n    balances[ctx.signer] -= stamps\n    balances['reserves'] += stamps\n\n@export\ndef transfer(to, amount):\n    assert balances[ctx.signer] - amount >= 0, \\\n        'Sender balance must be non-negative!!!'\n\n    balances[ctx.sender] -= amount\n    balances[to] += amount\n\n@export\ndef approve(spender, amount):\n    allowed[ctx.sender][spender] = amount\n\n@export\ndef transfer_from(approver, spender, amount):\n    assert allowed[approver][spender] >= amount\n    assert balances[approver] >= amount\n\n    allowed[approver][spender] -= amount\n\n    balances[approver] -= amount\n    balances[spender] += amount\n"
  },
  {
    "path": "tests/unit/test_sys_contracts/good_lint.s.py",
    "content": "@export\ndef exports():\n    return 'huehuehue'"
  },
  {
    "path": "tests/unit/test_sys_contracts/module1.py",
    "content": "'''\nhow the modules import each other. this is to test ctx.caller etc\n\n   1\n |   |\n 2   3\n| | | |\n4 5 6 7\n  |\n  8\n\n'''\n\nimport module2\nimport module3\n\n\nprint('{} called from {}, signed by {}'.format(ctx.this, ctx.caller, ctx.signer))\n"
  },
  {
    "path": "tests/unit/test_sys_contracts/module2.py",
    "content": "import module4\nimport module5\n\nprint('{} called from {}, signed by {}'.format(ctx.this, ctx.caller, ctx.signer))"
  },
  {
    "path": "tests/unit/test_sys_contracts/module3.py",
    "content": "import module6\nimport module7\n\nprint('{} called from {}, signed by {}'.format(ctx.this, ctx.caller, ctx.signer))"
  },
  {
    "path": "tests/unit/test_sys_contracts/module4.py",
    "content": "print('{} called from {}, signed by {}'.format(ctx.this, ctx.caller, ctx.signer))"
  },
  {
    "path": "tests/unit/test_sys_contracts/module5.py",
    "content": "import module8\n\nprint('{} called from {}, signed by {}'.format(ctx.this, ctx.caller, ctx.signer))"
  },
  {
    "path": "tests/unit/test_sys_contracts/module6.py",
    "content": "print('{} called from {}, signed by {}'.format(ctx.this, ctx.caller, ctx.signer))"
  },
  {
    "path": "tests/unit/test_sys_contracts/module7.py",
    "content": "print('{} called from {}, signed by {}'.format(ctx.this, ctx.caller, ctx.signer))"
  },
  {
    "path": "tests/unit/test_sys_contracts/module8.py",
    "content": "print('{} called from {}, signed by {}'.format(ctx.this, ctx.caller, ctx.signer))"
  },
  {
    "path": "tests/unit/test_sys_contracts/module_func.py",
    "content": "supply = Variable()\nbalances = Hash(default_value=0)\n\n@construct\ndef seed():\n    balances['test'] = 100\n    supply.set(balances['test'])\n\n@export\ndef test_func(status=None):\n    return status\n\n@export\ndef test_keymod(deduct):\n    balances['test'] -= deduct\n    return balances['test']\n"
  },
  {
    "path": "tests/unit/test_timedelta.py",
    "content": "from unittest import TestCase\nfrom contracting.stdlib.bridge.time import Timedelta, WEEKS, DAYS, HOURS, MINUTES, SECONDS, Datetime\nfrom datetime import datetime as dt\nfrom datetime import timedelta\nimport decimal\n\nclass TestTimedelta(TestCase):\n    def test_implementation_mimics_actual_timedelta(self):\n        t = Timedelta(days=10, minutes=10, seconds=10)\n        _t = timedelta(days=10, minutes=10, seconds=10)\n\n        self.assertEqual(t._timedelta, _t)\n\n    def test_constants_work(self):\n        self.assertEqual(WEEKS._timedelta, timedelta(weeks=1))\n        self.assertEqual(DAYS._timedelta, timedelta(days=1))\n        self.assertEqual(HOURS._timedelta, timedelta(hours=1))\n        self.assertEqual(MINUTES._timedelta, timedelta(minutes=1))\n        self.assertEqual(SECONDS._timedelta, timedelta(seconds=1))\n\n    def test_eq_true(self):\n        t = Timedelta(days=1)\n        _t = Timedelta(days=1)\n\n        self.assertTrue(t == _t)\n\n    def test_eq_false(self):\n        t = Timedelta(days=1)\n        _t = Timedelta(days=10)\n\n        self.assertFalse(t == _t)\n\n    def test_gt_true(self):\n        t = Timedelta(days=10)\n        _t = Timedelta(days=1)\n\n        self.assertTrue(t > _t)\n\n    def test_gt_false(self):\n        t = Timedelta(days=1)\n        _t = Timedelta(days=10)\n\n        self.assertFalse(t > _t)\n\n    def test_ge_true(self):\n        t = Timedelta(days=10)\n        _t = Timedelta(days=1)\n\n        self.assertTrue(t >= _t)\n\n    def test_ge_false(self):\n        t = Timedelta(days=1)\n        _t = Timedelta(days=10)\n\n        self.assertFalse(t >= _t)\n\n    def test_ge_true_eq(self):\n        t = Timedelta(days=10)\n        _t = Timedelta(days=10)\n\n        self.assertTrue(t >= _t)\n\n    def test_lt_true(self):\n        t = Timedelta(days=10)\n        _t = Timedelta(days=1)\n\n        self.assertFalse(t < _t)\n\n    def test_lt_false(self):\n        t = Timedelta(days=10)\n        _t = Timedelta(days=1)\n\n        self.assertFalse(t < _t)\n\n    def test_le_true(self):\n        t = Timedelta(days=10)\n        _t = Timedelta(days=1)\n\n        self.assertFalse(t <= _t)\n\n    def test_le_false(self):\n        t = Timedelta(days=10)\n        _t = Timedelta(days=1)\n\n        self.assertFalse(t <= _t)\n\n    def test_le_true_eq(self):\n        t = Timedelta(days=10)\n        _t = Timedelta(days=10)\n\n        self.assertTrue(t <= _t)\n\n    def test_ne_true(self):\n        t = Timedelta(days=10)\n        _t = Timedelta(days=1)\n\n        self.assertTrue(t != _t)\n\n    def test_ne_false(self):\n        t = Timedelta(days=10)\n        _t = Timedelta(days=10)\n\n        self.assertFalse(t != _t)\n\n    def test_addition_works_days(self):\n        t_add = Timedelta(days=10) + Timedelta(days=1)\n        t_done = Timedelta(days=11)\n        org = timedelta(days=11)\n\n        self.assertEqual(t_add, t_done)\n        self.assertEqual(t_add._timedelta, org)\n\n    def test_addition_works_seconds(self):\n        t_add = Timedelta(seconds=10) + Timedelta(seconds=1)\n        t_done = Timedelta(seconds=11)\n        org = timedelta(seconds=11)\n\n        self.assertEqual(t_add, t_done)\n        self.assertEqual(t_add._timedelta, org)\n\n    def test_addition_works_days_and_seconds(self):\n        t_add = Timedelta(days=10, seconds=10) + Timedelta(days=1, seconds=1)\n        t_done = Timedelta(days=11, seconds=11)\n        org = timedelta(days=11, seconds=11)\n\n        self.assertEqual(t_add, t_done)\n        self.assertEqual(t_add._timedelta, org)\n\n    def test_subtraction_works_days(self):\n        t_add = Timedelta(days=10) - Timedelta(days=1)\n        t_done = Timedelta(days=9)\n        org = timedelta(days=9)\n\n        self.assertEqual(t_add, t_done)\n        self.assertEqual(t_add._timedelta, org)\n\n    def test_subtraction_works_seconds(self):\n        t_add = Timedelta(seconds=10) - Timedelta(seconds=1)\n        t_done = Timedelta(seconds=9)\n        org = timedelta(seconds=9)\n\n        self.assertEqual(t_add, t_done)\n        self.assertEqual(t_add._timedelta, org)\n\n    def test_subtraction_works_days_and_seconds(self):\n        t_add = Timedelta(days=10, seconds=10) - Timedelta(days=1, seconds=1)\n        t_done = Timedelta(days=9, seconds=9)\n        org = timedelta(days=9, seconds=9)\n\n        self.assertEqual(t_add, t_done)\n        self.assertEqual(t_add._timedelta, org)\n\n    def test_multiplication_works(self):\n        t_add = Timedelta(days=10) * Timedelta(days=3)\n        t_done = Timedelta(days=30)\n        org = timedelta(days=30)\n\n        self.assertEqual(t_add, t_done)\n        self.assertEqual(t_add._timedelta, org)\n\n    def test_multiplication_works_seconds(self):\n        t_add = Timedelta(seconds=10) * Timedelta(seconds=3)\n        t_done = Timedelta(seconds=30)\n        org = timedelta(seconds=30)\n\n        self.assertEqual(t_add, t_done)\n        self.assertEqual(t_add._timedelta, org)\n\n    def test_multiplication_works_days_and_seconds(self):\n        SECONDS_IN_A_DAY = 86400\n\n        t_add = Timedelta(days=10, seconds=10) * Timedelta(days=3, seconds=3)\n        t_done = Timedelta(seconds=(30 + (30*SECONDS_IN_A_DAY)))\n        org = timedelta(seconds=(30 + (30*SECONDS_IN_A_DAY)))\n\n        self.assertEqual(t_add, t_done)\n        self.assertEqual(t_add._timedelta, org)\n\n    def test_addition_not_implemented(self):\n        with self.assertRaises(TypeError):\n            Timedelta(days=10, seconds=10) + 5\n\n    def test_subtraction_not_implemented(self):\n        with self.assertRaises(TypeError):\n            Timedelta(days=10, seconds=10) - 5\n\n    def test_multiplication_with_int_works(self):\n        self.assertEqual(Timedelta(days=10, seconds=10) * 5, Timedelta(days=50, seconds=50))\n        self.assertEqual((Timedelta(days=10, seconds=10) * 5)._timedelta, timedelta(days=50, seconds=50))\n\n    def test_multiplication_does_not_work_with_decimal(self):\n        with self.assertRaises(TypeError):\n            Timedelta(days=10, seconds=10) * decimal.Decimal(0.1)\n\n    def test_get_seconds_works(self):\n        weeks = 0\n        days = 0\n        hours = 0\n        minutes = 0\n        seconds = 10\n\n        t = Timedelta(weeks, days, hours, minutes, seconds)\n\n        self.assertEqual(t.seconds, 10)\n\n    def test_get_minutes_works(self):\n        weeks = 0\n        days = 0\n        hours = 0\n        minutes = 12\n        seconds = 10\n\n        t = Timedelta(weeks, days, hours, minutes, seconds)\n\n        self.assertEqual(t.minutes, 12)\n\n    def test_get_hours_works(self):\n        weeks = 0\n        days = 0\n        hours = 4\n        minutes = 12\n        seconds = 10\n\n        t = Timedelta(weeks, days, hours, minutes, seconds)\n\n        self.assertEqual(t.hours, 4)\n\n    def test_get_days_works(self):\n        weeks = 0\n        days = 8\n        hours = 4\n        minutes = 12\n        seconds = 10\n\n        t = Timedelta(weeks, days, hours, minutes, seconds)\n\n        self.assertEqual(t.days, 8)\n\n    def test_get_weeks_works(self):\n        weeks = 2\n        days = 1\n        hours = 4\n        minutes = 12\n        seconds = 10\n\n        t = Timedelta(weeks, days, hours, minutes, seconds)\n\n        self.assertEqual(t.weeks, 2)\n\n    def test_larger_components_returns_as_expected(self):\n        weeks = 2\n        days = 1\n        hours = 4\n        minutes = 12\n        seconds = 10\n\n        t = Timedelta(weeks, days, hours, minutes, seconds)\n\n        self.assertEqual(t.days, 15)\n        self.assertEqual(t.hours, 364)\n\n    def test_adding_timedelta_to_datetime_returns_correct(self):\n        t = Timedelta(days=1)\n        d = Datetime(2020, 10, 1)\n        d2 = t + d\n\n        self.assertEqual(d2, Datetime(2020, 10, 2))\n\n    def test_subtracting_timedelta_to_datetime_returns_correct(self):\n        t = Timedelta(days=1)\n        d = Datetime(2020, 10, 1)\n        d2 = t - d\n\n        self.assertEqual(d2, Datetime(2020, 9, 30))\n"
  }
]