master ded6171d529f cached
195 files
461.8 KB
123.8k tokens
1188 symbols
1 requests
Download .txt
Showing preview only (511K chars total). Download the full file or copy to clipboard to get everything.
Repository: xian-network/xian-contracting
Branch: master
Commit: ded6171d529f
Files: 195
Total size: 461.8 KB

Directory structure:
gitextract_tbpetck0/

├── .github/
│   ├── ISSUE_TEMPLATE/
│   │   └── bug_report.md
│   ├── PULL_REQUEST_TEMPLATE.md
│   ├── dependabot.yml
│   └── workflows/
│       └── publish.yml
├── .gitignore
├── LICENSE
├── README.md
├── examples/
│   ├── 01 A very simple Counter contract.ipynb
│   ├── 02 Ingredients of a Smart Contract.ipynb
│   ├── 03 Interacting with the Client.ipynb
│   ├── 04 Standard Library and Extending Contracting.ipynb
│   ├── 05 Imports and Advanced Data Storage.ipynb
│   └── Rock Paper Scissors Tutorial.ipynb
├── pyproject.toml
├── release.sh
├── src/
│   └── contracting/
│       ├── __init__.py
│       ├── client.py
│       ├── compilation/
│       │   ├── __init__.py
│       │   ├── compiler.py
│       │   ├── linter.py
│       │   ├── parser.py
│       │   └── whitelists.py
│       ├── constants.py
│       ├── contracts/
│       │   ├── __init__.py
│       │   ├── proxythis.py
│       │   ├── submission.s.py
│       │   └── thistest2.py
│       ├── execution/
│       │   ├── __init__.py
│       │   ├── executor.py
│       │   ├── module.py
│       │   ├── runtime.py
│       │   └── tracer.py
│       ├── stdlib/
│       │   ├── __init__.py
│       │   ├── bridge/
│       │   │   ├── __init__.py
│       │   │   ├── access.py
│       │   │   ├── crypto.py
│       │   │   ├── decimal.py
│       │   │   ├── hashing.py
│       │   │   ├── imports.py
│       │   │   ├── orm.py
│       │   │   ├── random.py
│       │   │   └── time.py
│       │   └── env.py
│       └── storage/
│           ├── __init__.py
│           ├── contract.py
│           ├── driver.py
│           ├── encoder.py
│           ├── hdf5.py
│           └── orm.py
└── tests/
    ├── __init__.py
    ├── integration/
    │   ├── __init__.py
    │   ├── test_atomic_swap.py
    │   ├── test_builtins_locked_off.py
    │   ├── test_complex_contracts.py
    │   ├── test_complex_object_setting.py
    │   ├── test_constructor_args.py
    │   ├── test_contracts/
    │   │   ├── __init__.py
    │   │   ├── atomic_swaps.s.py
    │   │   ├── bad_time.s.py
    │   │   ├── bastardcoin.s.py
    │   │   ├── builtin_lib.s.py
    │   │   ├── child_test.s.py
    │   │   ├── client.py
    │   │   ├── con_pass_hash.s.py
    │   │   ├── construct_function_works.s.py
    │   │   ├── constructor_args_contract.s.py
    │   │   ├── contracting.s.py
    │   │   ├── currency.s.py
    │   │   ├── dater.py
    │   │   ├── dynamic_import.py
    │   │   ├── dynamic_import.s.py
    │   │   ├── dynamic_importing.s.py
    │   │   ├── erc20_clone.s.py
    │   │   ├── exception.py
    │   │   ├── float_issue.s.py
    │   │   ├── foreign_thing.s.py
    │   │   ├── hashing_works.s.py
    │   │   ├── i_use_env.s.py
    │   │   ├── import_test.s.py
    │   │   ├── import_this.s.py
    │   │   ├── importing_that.s.py
    │   │   ├── inf_loop.s.py
    │   │   ├── json_tests.s.py
    │   │   ├── leaky.s.py
    │   │   ├── mathtime.s.py
    │   │   ├── modules/
    │   │   │   ├── all_in_one.s.py
    │   │   │   ├── dynamic_import.s.py
    │   │   │   ├── module1.s.py
    │   │   │   ├── module2.s.py
    │   │   │   ├── module3.s.py
    │   │   │   ├── module4.s.py
    │   │   │   ├── module5.s.py
    │   │   │   ├── module6.s.py
    │   │   │   ├── module7.s.py
    │   │   │   └── module8.s.py
    │   │   ├── orm_foreign_hash_contract.s.py
    │   │   ├── orm_foreign_key_contract.s.py
    │   │   ├── orm_hash_contract.s.py
    │   │   ├── orm_no_contract_access.s.py
    │   │   ├── orm_variable_contract.s.py
    │   │   ├── owner_stuff.s.py
    │   │   ├── parent_test.s.py
    │   │   ├── pass_hash.s.py
    │   │   ├── private_methods.s.py
    │   │   ├── stubucks.s.py
    │   │   ├── submission.s.py
    │   │   ├── tejastokens.s.py
    │   │   ├── thing.s.py
    │   │   ├── time.s.py
    │   │   └── time_storage.s.py
    │   ├── test_datetime_contracts.py
    │   ├── test_dynamic_imports.py
    │   ├── test_executor_submission_process.py
    │   ├── test_executor_transaction_writes.py
    │   ├── test_memory_clean_up_after_execution.py
    │   ├── test_misc_contracts.py
    │   ├── test_pixel_game.py
    │   ├── test_rich_ctx_calling.py
    │   ├── test_run_private_function.py
    │   ├── test_senecaCompiler_integration.py
    │   ├── test_seneca_client_randoms.py
    │   ├── test_seneca_client_replaces_executor.py
    │   └── test_stamp_deduction.py
    ├── performance/
    │   ├── __init__.py
    │   ├── prof_transfer.py
    │   ├── test_contracts/
    │   │   ├── __init__.py
    │   │   ├── erc20_clone.s.py
    │   │   ├── modules/
    │   │   │   ├── all_in_one.s.py
    │   │   │   ├── dynamic_import.s.py
    │   │   │   ├── module1.s.py
    │   │   │   ├── module2.s.py
    │   │   │   ├── module3.s.py
    │   │   │   ├── module4.s.py
    │   │   │   ├── module5.s.py
    │   │   │   ├── module6.s.py
    │   │   │   ├── module7.s.py
    │   │   │   └── module8.s.py
    │   │   └── submission.s.py
    │   └── test_transfer.py
    ├── security/
    │   ├── __init__.py
    │   ├── contracts/
    │   │   ├── builtin_hack_token.s.py
    │   │   ├── call_infinate_loop.s.py
    │   │   ├── con_inf_writes.s.py
    │   │   ├── constructor_infinate_loop.s.py
    │   │   ├── double_spend_gas_attack.s.py
    │   │   ├── erc20_clone.s.py
    │   │   ├── get_set_driver.py
    │   │   ├── get_set_driver_2.py
    │   │   ├── hack_tokens.s.py
    │   │   ├── import_hash_from_contract.s.py
    │   │   ├── infinate_loop.s.py
    │   │   └── submission.s.py
    │   └── test_erc20_token_hacks.py
    └── unit/
        ├── __init__.py
        ├── contracts/
        │   ├── currency.s.py
        │   ├── exception.s.py
        │   ├── proxythis.py
        │   ├── submission.s.py
        │   └── thistest2.py
        ├── loop_client_test.sh
        ├── precompiled/
        │   ├── __init__.py
        │   ├── compiled_token.py
        │   └── updated_submission.py
        ├── test_client.py
        ├── test_client_keys_prefix.py
        ├── test_context_data_struct.py
        ├── test_datetime.py
        ├── test_decimal.py
        ├── test_driver_tombstones.py
        ├── test_encode.py
        ├── test_imports_stdlib.py
        ├── test_linter.py
        ├── test_module.py
        ├── test_new_driver.py
        ├── test_orm.py
        ├── test_parser.py
        ├── test_revert_on_exception.py
        ├── test_runtime.py
        ├── test_state_management.py
        ├── test_stdlib_hashing.py
        ├── test_sys_contracts/
        │   ├── __init__.py
        │   ├── bad_lint.s.py
        │   ├── compile_this.s.py
        │   ├── currency.s.py
        │   ├── good_lint.s.py
        │   ├── module1.py
        │   ├── module2.py
        │   ├── module3.py
        │   ├── module4.py
        │   ├── module5.py
        │   ├── module6.py
        │   ├── module7.py
        │   ├── module8.py
        │   └── module_func.py
        └── test_timedelta.py

================================================
FILE CONTENTS
================================================

================================================
FILE: .github/ISSUE_TEMPLATE/bug_report.md
================================================
---
name: Bug report
about: Create a report to help us improve
title: ''
labels: ''
assignees: ''

---

**Describe the bug**
A clear and concise description of what the bug is.

**To Reproduce**
Steps to reproduce the behavior:
1. Go to '...'
2. Click on '....'
3. Scroll down to '....'
4. See error

**Expected behavior**
A clear and concise description of what you expected to happen.

**Screenshots**
If applicable, add screenshots to help explain your problem.

**Desktop (please complete the following information):**
 - OS: [e.g. iOS]
 - Browser [e.g. chrome, safari]
 - Version [e.g. 22]

**Smartphone (please complete the following information):**
 - Device: [e.g. iPhone6]
 - OS: [e.g. iOS8.1]
 - Browser [e.g. stock browser, safari]
 - Version [e.g. 22]

**Additional context**
Add any other context about the problem here.


================================================
FILE: .github/PULL_REQUEST_TEMPLATE.md
================================================
## Description

Please add a brief description of the feature / change / bug-fix you want to merge.

## Type of change

Please delete options that are not relevant.

- [ ] Bug fix (non-breaking change which fixes an issue)
- [ ] New feature (non-breaking change which adds functionality)
- [ ] Breaking change (fix or feature that would require a resync of blockchain state)

## Checklist

- [ ] I have performed a self-review of my own code
- [ ] I have tested this change in my development environment.
- [ ] I have added tests to prove that this change works
- [ ] All existing tests pass after this change
- [ ] I have added / updated documentation related to this change

================================================
FILE: .github/dependabot.yml
================================================
version: 2
updates:
  - package-ecosystem: "pip" # Type of package ecosystem (e.g., "npm", "maven")
    directory: "/" # Location of package manifests
    schedule:
      interval: "daily" # How often to check for updates
    open-pull-requests-limit: 10 # Maximum number of open pull requests Dependabot should have

================================================
FILE: .github/workflows/publish.yml
================================================
name: Publish to PyPI and GitHub Release

on:
  push:
    tags:
      - 'v*'  # Trigger on version tags

jobs:
  build-and-publish:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v3
      
      - name: Set up Python 3.11
        uses: actions/setup-python@v4
        with:
          python-version: '3.11'
      
      - name: Install Poetry
        run: |
          curl -sSL https://install.python-poetry.org | python3 -
      
      - name: Build and Publish to PyPI
        env:
          PYPI_TOKEN: ${{ secrets.PYPI_TOKEN }}
        run: |
          poetry config pypi-token.pypi $PYPI_TOKEN
          poetry build
          poetry publish
      
      - name: Create GitHub Release
        uses: softprops/action-gh-release@v1
        with:
          files: dist/*
          generate_release_notes: true


================================================
FILE: .gitignore
================================================
# Python
__pycache__/
*.py[cod]
*$py.class
*.so
.Python
build/
develop-eggs/
dist/
downloads/
eggs/
.eggs/
lib/
lib64/
parts/
sdist/
var/
wheels/
*.egg-info/
.installed.cfg
*.egg

# Virtual Environment
.env
.venv
env/
venv/
ENV/

# IDE
.idea/
.vscode/
*.swp
*.swo

# Testing
.coverage
.pytest_cache/
htmlcov/

# Poetry
poetry.lock__pycache__/
dist
xian_contracting.egg-info
contracting.egg-info
build
.idea
logs
*.so
.ccls
*.pyc


================================================
FILE: LICENSE
================================================
Creative Commons Attribution‑NonCommercial 4.0 International

Copyright © 2025 XIAN.org

This work is licensed under CC BY‑NC 4.0.  
You may copy, modify, and share it **for non‑commercial purposes only**, provided that you give appropriate credit.  
Full legal text: https://creativecommons.org/licenses/by-nc/4.0/legalcode


================================================
FILE: README.md
================================================
# Xian Contracting

Xian 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.

## Features

- **Python-Native**: Write smart contracts in standard Python with some additional decorators and constructs
- **Storage System**: Built-in ORM-like system with `Variable` and `Hash` data structures
- **Runtime Security**: Secure execution environment with memory and computation limitations
- **Metering System**: Built-in computation metering to prevent infinite loops and resource abuse
- **Event System**: Built-in logging and event system for contract state changes
- **Import Controls**: Secure import system that prevents access to dangerous system modules

## Installation

```bash
pip install xian-contracting
```

## Quick Start

Here's a complete token contract example with approval system:

```python
def token_contract():
    balances = Hash()
    owner = Variable()
    
    @construct
    def seed():
       owner.set(ctx.caller)
    
    @export
    def approve(amount: float, to: str):
       assert amount > 0, 'Cannot send negative balances.'
       balances[ctx.caller, to] += amount
    
    @export
    def transfer_from(amount: float, to: str, main_account: str):
        approved = allowances[main_account, ctx.caller]
    
        assert amount > 0, 'Cannot send negative balances!'
        assert approved >= amount, f'You approved {approved} but need {amount}'
        assert balances[main_account] >= amount, 'Not enough tokens to send!'
    
        allowances[main_account, ctx.caller] -= amount
        balances[main_account] -= amount
        balances[to] += amount
    
    @export
    def transfer(amount: float, to: str):
       assert amount > 0, 'Cannot send negative balances.'
       assert balances[ctx.caller] >= amount, 'Not enough coins to send.'
    
       balances[ctx.caller] -= amount
       balances[to] += amount
    
    @export
    def mint(to, amount):
       assert ctx.caller == owner.get(), 'Only the original contract author can mint!'
       balances[to] += amount
```

## Core Concepts

### Storage Types

- **Variable**: Single-value storage
  ```python
  counter = Variable()
  counter.set(0)  # Set value
  current = counter.get()  # Get value
  ```

- **Hash**: Key-value storage with support for complex and multi-level keys
  ```python
  balances = Hash()
  # Single-level key
  balances['alice'] = 100
  alice_balance = balances['alice']
  
  # Multi-level keys for complex relationships
  balances['alice', 'bob'] = 50  # e.g., alice approves bob to spend 50 tokens
  approved_amount = balances['alice', 'bob']  # Get the approved amount
  
  # You can use up to 16 dimensions in key tuples
  data['user', 'preferences', 'theme'] = 'dark'
  ```

### Contract Decorators

- **@construct**: Initializes contract state (can only be called once)
  ```python
  @construct
  def seed():
      owner.set(ctx.caller)
  ```

- **@export**: Makes function callable from outside the contract
  ```python
  @export
  def increment(amount: int):
      counter.set(counter.get() + amount)
  ```

### Contract Context

The `ctx` object provides important runtime information:

- `ctx.caller`: Address of the account calling the contract
- `ctx.this`: Current contract's address
- `ctx.signer`: Original transaction signer
- `ctx.owner`: Contract owner's address

## Using the ContractingClient

The `ContractingClient` class is your main interface for deploying and interacting with contracts:

```python
from contracting.client import ContractingClient

# Initialize the client
client = ContractingClient()

# Submit a contract
with open('token.py', 'r') as f:
    contract = f.read()
    
client.submit(name='con_token', code=contract)

# Get contract instance
token = client.get_contract('con_token')

# Call contract methods
token.transfer(amount=100, to='bob')
```

## Storage Driver

The framework includes a powerful storage system:

```python
from contracting.storage.driver import Driver

driver = Driver()

# Direct storage operations
driver.set('key', 'value')
driver.get('key')

# Contract storage
driver.set_contract(name='contract_name', code=contract_code)
driver.get_contract('contract_name')
```

## Event System

Contracts can emit events which can be tracked by external systems:

```python
def token_contract():
    transfer_event = LogEvent(
        'transfer',
        {
            'sender': {'type': str, 'idx': True},
            'receiver': {'type': str, 'idx': True},
            'amount': {'type': float}
        }
    )

    @export
    def transfer(amount: float, to: str):
        # ... transfer logic ...
        
        # Emit event
        transfer_event({
            'sender': ctx.caller,
            'receiver': to,
            'amount': amount
        })
```

## Security Features

- Restricted imports to prevent malicious code execution
- Memory usage tracking and limitations
- Computation metering to prevent infinite loops
- Secure runtime environment
- Type checking and validation
- Private method protection

## Development and Testing

When developing contracts, you can use the linter to check for common issues:

```python
from contracting.client import ContractingClient

client = ContractingClient()
violations = client.lint(contract_code)
```

## License

This project is licensed under the Creative Commons Attribution‑NonCommercial 4.0 International - see the [LICENSE](LICENSE) file for details.
Non‑commercial use only.  See LICENSE for details.


================================================
FILE: examples/01 A very simple Counter contract.ipynb
================================================
{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# A very simple Counter contract\n",
    "\n",
    "Let's start writing a contract in python that stores a number which everyone can increment:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {},
   "outputs": [],
   "source": [
    "def counter_contract():\n",
    "    # introduce a state called count which holds a single value\n",
    "    count = Variable()\n",
    "    \n",
    "    # @construct means that this is the function that will be called when the smart contract is created\n",
    "    @construct\n",
    "    def constructor():\n",
    "        count.set(0)\n",
    "        \n",
    "    # @export makes this function public, so it can be called by anyone on a deployed contract    \n",
    "    @export\n",
    "    def increment():\n",
    "        count.set(count.get() + 1)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "To interact with smart contracts we need a client:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {},
   "outputs": [],
   "source": [
    "from contracting.client import ContractingClient\n",
    "client = ContractingClient(signer='ren')"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Next we will submit the contract to the client:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {},
   "outputs": [],
   "source": [
    "client.submit(counter_contract)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Now we can get the submitted contract to interact with it:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {},
   "outputs": [],
   "source": [
    "contract = client.get_contract('counter_contract')"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Let's investigate the counter:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "0"
      ]
     },
     "execution_count": 5,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "contract.count.get()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "It is 0 as expected because we initialized it to 0 in the constructor function.\n",
    "\n",
    "Everyone can increment the counter by calling the public increment function:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {},
   "outputs": [],
   "source": [
    "contract.increment()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Let's investigate the counter again:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "1"
      ]
     },
     "execution_count": 7,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "contract.count.get()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Seems like our increment function works.\n",
    "\n",
    "This concludes our first look into writing smart contracts in Python on Lamden. Dive deeper by looking at the next example. "
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.6.5"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}


================================================
FILE: examples/02 Ingredients of a Smart Contract.ipynb
================================================
{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# What is inside a smart contract?\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."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "metadata": {},
   "outputs": [],
   "source": [
    "def basic_contract():\n",
    "    # data section\n",
    "    owner = Variable()\n",
    "    balances = Hash(default_value=0)\n",
    "    \n",
    "    @construct\n",
    "    def seed():\n",
    "        owner.set('stuart')\n",
    "        balances['stuart'] = 1000000\n",
    "\n",
    "    @export\n",
    "    def mint(amount, to):\n",
    "        assert_is_owner()\n",
    "        \n",
    "        balances[to] += amount\n",
    "        \n",
    "    def assert_is_owner():\n",
    "        assert ctx.caller == owner.get(), 'You are not the owner! {} is!'.format(owner.get())\n",
    "        \n",
    "    @export\n",
    "    def send(amount, to):\n",
    "        assert balances[ctx.caller] >= amount, 'You do not have enough to send! {} is less than {}'.format(\n",
    "            balances[ctx.caller], amount\n",
    "        )\n",
    "        \n",
    "        balances[ctx.caller] -= amount\n",
    "        balances[to] += amount"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Functions\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",
    "* @construct\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",
    "* @export\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",
    "* everything else\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."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 14,
   "metadata": {},
   "outputs": [],
   "source": [
    "from contracting.client import ContractingClient\n",
    "client = ContractingClient(signer='stuart')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 15,
   "metadata": {},
   "outputs": [],
   "source": [
    "client.submit(basic_contract)\n",
    "contract = client.get_contract('basic_contract')"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Because @constructor sets `stuart`'s balance to 1,000,000, we can access the variable directly from our contract object to check."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 22,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "1000000"
      ]
     },
     "execution_count": 22,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "contract.balances['stuart']"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Because `mint` is an @export function, we can call it from the outside. Remember, the `client` was initialized with the `signer` equal to `stuart`."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 21,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "20000"
      ]
     },
     "execution_count": 21,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "contract.mint(amount=10000, to='raghu')\n",
    "contract.balances['raghu']"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "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."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 18,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "You are not the owner! stuart is!\n"
     ]
    }
   ],
   "source": [
    "try:\n",
    "    contract.mint(amount=500, to='raghu', signer='not_stuart')\n",
    "except AssertionError as e:\n",
    "    print(e)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "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."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 28,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "module 'basic_contract' has no attribute '__assert_is_owner'\n"
     ]
    }
   ],
   "source": [
    "try:\n",
    "    contract.__assert_is_owner()\n",
    "except Exception as e:\n",
    "    print(e)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Data\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",
    "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",
    "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."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 37,
   "metadata": {},
   "outputs": [],
   "source": [
    "def data_contract():\n",
    "    basic_contract_owner = ForeignVariable(foreign_contract='basic_contract', foreign_name='owner')\n",
    "    \n",
    "    variable = Variable()\n",
    "    hash_ = Hash()\n",
    "    \n",
    "    # Demonstration of returning a value in another smart contract's namespace\n",
    "    @export\n",
    "    def whos_the_owner():\n",
    "        return basic_contract_owner.get()\n",
    "    \n",
    "    @export\n",
    "    def set_var(x):\n",
    "        variable.set(x)\n",
    "        \n",
    "    @export\n",
    "    def set_hash(k, v):\n",
    "        hash_[k] = v"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 38,
   "metadata": {},
   "outputs": [],
   "source": [
    "client.submit(data_contract)\n",
    "d_contract = client.get_contract('data_contract')"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "#### Read the Foreign Variable"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 39,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "'stuart'"
      ]
     },
     "execution_count": 39,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "d_contract.whos_the_owner()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "#### Set the Variable via Smart Contract and via Client"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 44,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "1000"
      ]
     },
     "execution_count": 44,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "d_contract.set_var(x=1000)\n",
    "d_contract.variable.get()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 45,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "123"
      ]
     },
     "execution_count": 45,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "d_contract.set_var(x=123)\n",
    "d_contract.variable.get()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 46,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "555"
      ]
     },
     "execution_count": 46,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# Overriding our method to modify the variable directly\n",
    "d_contract.variable.set(555)\n",
    "d_contract.variable.get()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "#### Set the Hash via Smart Contract and via Client"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 52,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "'world'"
      ]
     },
     "execution_count": 52,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "d_contract.set_hash(k='hello', v='world')\n",
    "d_contract.hash_['hello']"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 53,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "'there'"
      ]
     },
     "execution_count": 53,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "d_contract.hash_['hello'] = 'there'\n",
    "d_contract.hash_['hello']"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Behavior Note\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."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 56,
   "metadata": {},
   "outputs": [],
   "source": [
    "def variable_behavior():\n",
    "    invisible_variable = Variable()\n",
    "    \n",
    "    @export\n",
    "    def do_nothing():\n",
    "        return 0"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 57,
   "metadata": {},
   "outputs": [],
   "source": [
    "client.submit(variable_behavior)\n",
    "v_contract = client.get_contract('variable_behavior')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 59,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "'AbstractContract' object has no attribute 'invisible_variable'\n"
     ]
    }
   ],
   "source": [
    "try:\n",
    "    v_contract.invisible_variable\n",
    "except AttributeError as e:\n",
    "    print(e)"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.6.5"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}


================================================
FILE: examples/03 Interacting with the Client.ipynb
================================================
{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# The Main Contracting Client\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",
    "You can change the signer by setting this property on the client, or by overriding the keyword `sender` when calling a function."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {},
   "outputs": [],
   "source": [
    "from contracting.client import ContractingClient\n",
    "client = ContractingClient(signer='stu')"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Viewing contracts\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",
    "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."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "['submission']"
      ]
     },
     "execution_count": 2,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "client.get_contracts()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Interacting with existing smart contracts\n",
    "\n",
    "Contracts can be fetched into their own objects with the `get_contract` method."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "<contracting.client.AbstractContract at 0x10c3643c8>"
      ]
     },
     "execution_count": 3,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "client.get_contract('submission')"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "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."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "[('submit_contract', ['name', 'code'])]"
      ]
     },
     "execution_count": 4,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "submission = client.get_contract('submission')\n",
    "submission.functions"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Submitting new smart contracts\n",
    "\n",
    "Let's use the `submit_contract` function to submit a new smart contract!"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {},
   "outputs": [],
   "source": [
    "code = '''\n",
    "@export\n",
    "def hello_there():\n",
    "    print('howdy')\n",
    "'''\n",
    "\n",
    "name = 'howdy_time'\n",
    "\n",
    "submission.submit_contract(name=name, code=code)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "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."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {},
   "outputs": [],
   "source": [
    "howdy_time = client.get_contract(name)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "['howdy_time.__author__',\n",
       " 'howdy_time.__code__',\n",
       " 'howdy_time.__compiled__',\n",
       " 'howdy_time.__type__']"
      ]
     },
     "execution_count": 7,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "howdy_time.keys()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "def hello_there():\n",
      "    print('howdy')\n",
      "\n"
     ]
    }
   ],
   "source": [
    "print(howdy_time.__code__)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "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."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "metadata": {},
   "outputs": [],
   "source": [
    "code = '''\n",
    "@export\n",
    "def secret():\n",
    "    return abcd()\n",
    "    \n",
    "def abcd():\n",
    "    return 5\n",
    "'''\n",
    "\n",
    "name = 'secret'\n",
    "\n",
    "submission.submit_contract(name=name, code=code)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "metadata": {},
   "outputs": [],
   "source": [
    "secret = client.get_contract('secret')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "[('secret', []), ('__abcd', [])]"
      ]
     },
     "execution_count": 11,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "secret.functions"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "def secret():\n",
      "    return __abcd()\n",
      "\n",
      "\n",
      "def __abcd():\n",
      "    return 5\n",
      "\n"
     ]
    }
   ],
   "source": [
    "print(secret.__code__)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 13,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "5"
      ]
     },
     "execution_count": 13,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "secret.secret()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "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."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Closures and direct submission\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",
    "Contracts submitted this way will be named whatever their closure function is."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 14,
   "metadata": {},
   "outputs": [],
   "source": [
    "def closure_example():\n",
    "    @export\n",
    "    def hello():\n",
    "        return 'How are you?'\n",
    "    \n",
    "    def shh():\n",
    "        return 10"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 15,
   "metadata": {},
   "outputs": [],
   "source": [
    "client.submit(closure_example)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 18,
   "metadata": {},
   "outputs": [],
   "source": [
    "closure = client.get_contract('closure_example')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 20,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "def hello():\n",
      "    return 'How are you?'\n",
      "\n",
      "\n",
      "def __shh():\n",
      "    return 10\n",
      "\n"
     ]
    }
   ],
   "source": [
    "print(closure.__code__)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "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."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.6.5"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}


================================================
FILE: examples/04 Standard Library and Extending Contracting.ipynb
================================================
{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# The Contracting Standard Library\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",
    "To see the basic standard library included at runtime, use `gather()` from the `env` module."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {},
   "outputs": [],
   "source": [
    "from contracting.stdlib import env"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "{'Variable': contracting.db.orm.Variable,\n",
       " 'Hash': contracting.db.orm.Hash,\n",
       " 'ForeignVariable': contracting.db.orm.ForeignVariable,\n",
       " 'ForeignHash': contracting.db.orm.ForeignHash,\n",
       " '__Contract': contracting.db.contract.Contract,\n",
       " 'sha3': <function contracting.stdlib.bridge.hashing.sha3(hex_str:str)>,\n",
       " 'sha256': <function contracting.stdlib.bridge.hashing.sha256(hex_str:str)>,\n",
       " 'datetime': contracting.stdlib.bridge.time.Datetime}"
      ]
     },
     "execution_count": 2,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "env.gather()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "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."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {},
   "outputs": [],
   "source": [
    "def stdlib_environment_examples():\n",
    "    \n",
    "    @export\n",
    "    def sha3_data(s):\n",
    "        return sha3(s)\n",
    "    \n",
    "    @export\n",
    "    def return_env_variable():\n",
    "        return this_will_be_defined_later"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "First, let's try to access the `sha3` function exposed in the `stdlib`."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {},
   "outputs": [],
   "source": [
    "from contracting.client import ContractingClient\n",
    "client = ContractingClient(signer='stu')\n",
    "client.submit(stdlib_environment_examples)\n",
    "contract = client.get_contract('stdlib_environment_examples')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "'a0d5f1e1000980a0ae98cffb12072a41328bbdfebf3f6012aa021b428daea5b7'"
      ]
     },
     "execution_count": 5,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "contract.sha3_data(s='00ff00ff00ff')"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "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."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "name 'this_will_be_defined_later' is not defined\n"
     ]
    }
   ],
   "source": [
    "try:\n",
    "    contract.return_env_variable()\n",
    "except Exception as e:\n",
    "    print(e)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "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."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "42"
      ]
     },
     "execution_count": 7,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "environment = {'this_will_be_defined_later': 42}\n",
    "contract.return_env_variable(environment=environment)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Runtime Context `ctx`\n",
    "At runtime, there is a constant defined called `ctx`. `ctx` contains three fields:\n",
    "\n",
    "* `ctx.signer`\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",
    "* `ctx.caller`\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",
    "* `ctx.this`\n",
    "\n",
    "    This is the name of the smart contract. This is how you will reference a smart contract for ascribing ownership to them."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "metadata": {},
   "outputs": [],
   "source": [
    "def call_me():\n",
    "    @export\n",
    "    def caller():\n",
    "        return ctx.caller\n",
    "    \n",
    "    @export\n",
    "    def this():\n",
    "        return ctx.this\n",
    "\n",
    "def ctx_example():\n",
    "    import call_me\n",
    "    \n",
    "    @export\n",
    "    def ctx_now():\n",
    "        return ctx.signer, ctx.caller, ctx.this\n",
    "    \n",
    "    @export\n",
    "    def ctx_after_call():\n",
    "        c = call_me.caller()\n",
    "        t = call_me.this()\n",
    "        \n",
    "        return ctx.signer, c, t"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "metadata": {},
   "outputs": [],
   "source": [
    "client.submit(call_me)\n",
    "client.submit(ctx_example)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "metadata": {},
   "outputs": [],
   "source": [
    "ctx_contract = client.get_contract('ctx_example')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "('stu', 'stu', 'ctx_example')"
      ]
     },
     "execution_count": 11,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "ctx_contract.ctx_now()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "('stu', 'ctx_example', 'call_me')"
      ]
     },
     "execution_count": 12,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "ctx_contract.ctx_after_call()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "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."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 13,
   "metadata": {},
   "outputs": [],
   "source": [
    "call_me_contract = client.get_contract('call_me')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 14,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "'stu'"
      ]
     },
     "execution_count": 14,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "call_me_contract.caller()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Why does `ctx` being dynamic matter?\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",
    "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",
    "Let's make a token contract to demonstrate this idea."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 15,
   "metadata": {},
   "outputs": [],
   "source": [
    "def coin():\n",
    "    balances = Hash()\n",
    "    token_name = 'Stubucks'\n",
    "    token_symbol = 'SBX'\n",
    "    \n",
    "    @construct\n",
    "    def seed():\n",
    "        # Whoever creates this smart contract is minted 1,000,000 tokens\n",
    "        balances[ctx.caller] = 1000000\n",
    "        \n",
    "    @export\n",
    "    def transfer(amount, to):\n",
    "        # Make sure that the person calling this function has the amount they are trying to transfer\n",
    "        assert balances[ctx.caller] >= amount, \"You don't have enough to spend!\"\n",
    "        \n",
    "        # If so, deduct from their account and send to who they want to send to\n",
    "        balances[ctx.caller] -= amount\n",
    "        balances[to] += amount\n",
    "        \n",
    "    @export\n",
    "    def allow(amount, spender):\n",
    "        # This creates a 'subaccount' to allow the spender to transfer from our account a certain amount\n",
    "        balances[ctx.caller, spender] = amount\n",
    "        \n",
    "    @export\n",
    "    def spend_on_behalf(amount, owner, to):\n",
    "        # We make sure the subaccount has enough coins to spend\n",
    "        assert balances[owner, ctx.caller] >= amount, \"You can't spend that!\"\n",
    "        \n",
    "        # If so, deduct from the amount that the subaccount can spend\n",
    "        balances[owner, ctx.caller] -= amount\n",
    "        \n",
    "        # And then make the transfer\n",
    "        balances[owner] -= amount\n",
    "        balances[to] += amount\n",
    "        \n",
    "def bank():\n",
    "    import coin\n",
    "    \n",
    "    balances = Hash()\n",
    "    \n",
    "    @export\n",
    "    def deposit(amount):\n",
    "        # The bank spends the coins it is allowed to on itself. It takes it from the subaccount and give it to itself\n",
    "        # We don't need an assertion because this will fail\n",
    "        coin.spend_on_behalf(amount=amount, owner=ctx.caller, to=ctx.this)\n",
    "        \n",
    "        # The account that of whoever called the deposit function is incremented accordingly\n",
    "        balances[ctx.caller] += amount\n",
    "        \n",
    "    @export\n",
    "    def withdraw(amount):\n",
    "        # Make sure there is enough in the caller's account to withdraw\n",
    "        assert balances[ctx.caller] >= amount, \"You don't have enough in your account!\"\n",
    "        \n",
    "        # Deduct from the account\n",
    "        balances[ctx.caller] -= amount\n",
    "        \n",
    "        # Transfer the coins out to the caller\n",
    "        coin.transfer(amount=amount, to=ctx.caller)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Here is the idea:\n",
    "\n",
    "1. You must allow a user to spend tokens on your behalf by calling the `allow` function.\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",
    "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",
    "Let's see if it works!"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 16,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "1000000"
      ]
     },
     "execution_count": 16,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "client.submit(coin)\n",
    "client.submit(bank)\n",
    "\n",
    "coin_contract = client.get_contract('coin')\n",
    "bank_contract = client.get_contract('bank')\n",
    "\n",
    "coin_contract.balances['stu'] # Check if things @construct'ed appropriately"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 17,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "['coin.__author__',\n",
       " 'coin.__code__',\n",
       " 'coin.__compiled__',\n",
       " 'coin.__type__',\n",
       " 'coin.balances:stu']"
      ]
     },
     "execution_count": 17,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "coin_contract.keys()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 18,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "balances = Hash(contract='coin', name='balances')\n",
      "token_name = 'Stubucks'\n",
      "token_symbol = 'SBX'\n",
      "\n",
      "\n",
      "def ____():\n",
      "    balances[ctx.caller] = 1000000\n",
      "\n",
      "\n",
      "def transfer(amount, to):\n",
      "    assert balances[ctx.caller] >= amount, \"You don't have enough to spend!\"\n",
      "    balances[ctx.caller] -= amount\n",
      "    balances[to] += amount\n",
      "\n",
      "\n",
      "def allow(amount, spender):\n",
      "    balances[ctx.caller, spender] = amount\n",
      "\n",
      "\n",
      "def spend_on_behalf(amount, owner, to):\n",
      "    assert balances[owner, ctx.caller] >= amount, \"You can't spend that!\"\n",
      "    balances[owner, ctx.caller] -= amount\n",
      "    balances[owner] -= amount\n",
      "    balances[to] += amount\n",
      "\n"
     ]
    }
   ],
   "source": [
    "print(coin_contract.__code__)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 19,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "10"
      ]
     },
     "execution_count": 19,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "coin_contract.transfer(amount=10, to='hi')\n",
    "coin_contract.balances['hi']"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 20,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "0"
      ]
     },
     "execution_count": 20,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# Let's verify that the bank has no coins\n",
    "coin_contract.balances['bank']"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 21,
   "metadata": {},
   "outputs": [],
   "source": [
    "coin_contract.allow(amount=500, spender='bank')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 22,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "500"
      ]
     },
     "execution_count": 22,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "coin_contract.balances['stu', 'bank'] # This is how you access a 'subaccount.' A nice feature of multihashes!"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 23,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "999990"
      ]
     },
     "execution_count": 23,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "coin_contract.balances['stu'] # Notice that it is not affecting the main account. It is just an allowance account."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 24,
   "metadata": {},
   "outputs": [],
   "source": [
    "bank_contract.deposit(amount=450) # This should modify our balance and give bank 450 coins. Let's check!"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 25,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "stu balance: 999540\n",
      "bank balance: 450\n",
      "bank allowance: 50\n"
     ]
    }
   ],
   "source": [
    "stu_balance = coin_contract.balances['stu']\n",
    "bank_balance = coin_contract.balances['bank']\n",
    "\n",
    "# This should only be 50, because 450 were spent on the bank's behalf.\n",
    "bank_allowance = coin_contract.balances['stu', 'bank']\n",
    "\n",
    "print('stu balance: {}\\nbank balance: {}\\nbank allowance: {}'.format(\n",
    "    stu_balance,\n",
    "    bank_balance,\n",
    "    bank_allowance\n",
    "))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 26,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "450"
      ]
     },
     "execution_count": 26,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "bank_contract.balances['stu'] # Our account in the bank reflects the total"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Adding another participant to the equation\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."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 27,
   "metadata": {},
   "outputs": [],
   "source": [
    "# 'stu' will transfer some coins to 'raghu' to put in the bank.\n",
    "coin_contract.transfer(amount=5000, to='raghu')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 28,
   "metadata": {},
   "outputs": [],
   "source": [
    "# Remember, the default signer on this client is 'stu' so we have to set it to 'raghu' to call a function from him.\n",
    "coin_contract.allow(amount=4000, spender='bank', signer='raghu')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 29,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "raghu balance: 5000\n",
      "bank allowance for raghu: 4000\n"
     ]
    }
   ],
   "source": [
    "raghu_balance = coin_contract.balances['raghu']\n",
    "bank_raghu_allowance = coin_contract.balances['raghu', 'bank']\n",
    "\n",
    "print('raghu balance: {}\\nbank allowance for raghu: {}'.format(raghu_balance, bank_raghu_allowance))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 30,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "You can't spend that!\n"
     ]
    }
   ],
   "source": [
    "# If raghu tries to deposit more than 4000, an error will occur\n",
    "try:\n",
    "    bank_contract.deposit(amount=4001, signer='raghu')\n",
    "except AssertionError as e:\n",
    "    print(e)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 31,
   "metadata": {},
   "outputs": [],
   "source": [
    "# Less than 4000 or 4000 will do.\n",
    "bank_contract.deposit(amount=3999, signer='raghu')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 32,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "raghu balance: 1001\n",
      "bank allowance for raghu: 1\n"
     ]
    }
   ],
   "source": [
    "# Updated balances\n",
    "raghu_balance = coin_contract.balances['raghu']\n",
    "bank_raghu_allowance = coin_contract.balances['raghu', 'bank']\n",
    "\n",
    "print('raghu balance: {}\\nbank allowance for raghu: {}'.format(raghu_balance, bank_raghu_allowance))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 33,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "bank balance: 4449\n",
      "stu bank account: 450\n",
      "raghu bank account: 3999\n"
     ]
    }
   ],
   "source": [
    "# The bank will now have 450 + 3999 coins total, with two subaccounts.\n",
    "bank_balance = coin_contract.balances['bank']\n",
    "stu_bank_account = bank_contract.balances['stu']\n",
    "raghu_bank_account = bank_contract.balances['raghu']\n",
    "\n",
    "print('bank balance: {}\\nstu bank account: {}\\nraghu bank account: {}'.format(\n",
    "    bank_balance,\n",
    "    stu_bank_account,\n",
    "    raghu_bank_account\n",
    "))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 34,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "You don't have enough in your account!\n"
     ]
    }
   ],
   "source": [
    "# If we try to withdraw more than our account balance from the bank, then we will have an AssertionError\n",
    "try:\n",
    "    bank_contract.withdraw(amount=500)\n",
    "except AssertionError as e:\n",
    "    print(e)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 35,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "stu prior balance:994540\n",
      "stu after balance: 994640\n"
     ]
    }
   ],
   "source": [
    "stu_prior_balance = coin_contract.balances['stu']\n",
    "bank_contract.withdraw(amount=100)\n",
    "stu_after_balance = coin_contract.balances['stu']\n",
    "\n",
    "print('stu prior balance: {}\\nstu after balance: {}'.format(\n",
    "    stu_prior_balance,\n",
    "    stu_after_balance\n",
    "))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "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!"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.6.5"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}


================================================
FILE: examples/05 Imports and Advanced Data Storage.ipynb
================================================
{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Imports and Advanced Data Storage\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."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "metadata": {},
   "outputs": [],
   "source": [
    "def import_this():\n",
    "    @export\n",
    "    def dumb_func():\n",
    "        return 4\n",
    "    \n",
    "def to_import():\n",
    "    import import_this\n",
    "    @export\n",
    "    def dumber_func():\n",
    "        return import_this.dumb_func()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "metadata": {},
   "outputs": [],
   "source": [
    "from contracting.client import ContractingClient\n",
    "client = ContractingClient(signer='stu')\n",
    "client.flush()\n",
    "client.submit(import_this)\n",
    "client.submit(to_import)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "4"
      ]
     },
     "execution_count": 12,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "ti_contract = client.get_contract('to_import')\n",
    "ti_contract.dumber_func()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "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."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Advanced Data\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",
    "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",
    "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",
    "h = Hash()\n",
    "h['one'] = 15\n",
    "h['one', 'two'] = 20\n",
    "h['two'] = 25\n",
    "h['a', 'b', 'c', 'd', 'e', 'f', 'g'] = 6\n",
    "```\n",
    "\n",
    "Let's try to build that pixel application."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {},
   "outputs": [],
   "source": [
    "def coin():\n",
    "    balances = Hash(default_value=0)\n",
    "    token_name = 'Stubucks'\n",
    "    token_symbol = 'SBX'\n",
    "    \n",
    "    @construct\n",
    "    def seed():\n",
    "        # Whoever creates this smart contract is minted 1,000,000 tokens\n",
    "        balances[ctx.caller] = 1000000\n",
    "        \n",
    "    @export\n",
    "    def transfer(amount, to):\n",
    "        # Make sure that the person calling this function has the amount they are trying to transfer\n",
    "        assert balances[ctx.caller] >= amount, \"You don't have enough to spend!\"\n",
    "        \n",
    "        # If so, deduct from their account and send to who they want to send to\n",
    "        balances[ctx.caller] -= amount\n",
    "        balances[to] += amount\n",
    "        \n",
    "    @export\n",
    "    def allow(amount, spender):\n",
    "        # This creates a 'subaccount' to allow the spender to transfer from our account a certain amount\n",
    "        balances[ctx.caller, spender] = amount\n",
    "        \n",
    "    @export\n",
    "    def spend_on_behalf(amount, owner, to):\n",
    "        # We make sure the subaccount has enough coins to spend\n",
    "        assert balances[owner, ctx.caller] >= amount, \"You can't spend that!\"\n",
    "        \n",
    "        # If so, deduct from the amount that the subaccount can spend\n",
    "        balances[owner, ctx.caller] -= amount\n",
    "        \n",
    "        # And then make the transfer\n",
    "        balances[owner] -= amount\n",
    "        balances[to] += amount\n",
    "\n",
    "def pixel_game():\n",
    "    import coin\n",
    "    \n",
    "    # We set the default value of dictionary values to None for testing if they exist\n",
    "    pixels = Hash(default_value=None)\n",
    "    \n",
    "    # These constants can never be changed. If you want mutable variables, use Variable objects and provide getters\n",
    "    # and setters.\n",
    "    max_x = 256\n",
    "    max_y = 256\n",
    "    \n",
    "    # Just a palette to simplify this\n",
    "    color_min = 0\n",
    "    color_max = 16\n",
    "    \n",
    "    @export\n",
    "    def buy_pixel(x, y, color, amount):\n",
    "        assert x < max_x and x >= 0, 'X out of bounds!'\n",
    "        assert y < max_y and y >= 0, 'Y out of bounds!'\n",
    "        \n",
    "        assert color < color_max and color >= color_min, 'Color is out of bounds!'\n",
    "        \n",
    "        # If we make it to here, we can access the pixel.\n",
    "        pixel = pixels[x, y]\n",
    "        \n",
    "        # If it is None, it's never been bought before, so we can buy it outright\n",
    "        if pixel is None:\n",
    "            # Take the coins and store it in the pixel game's account\n",
    "            overwrite_pixel(x, y, color, amount, ctx.caller)\n",
    "            \n",
    "        else:\n",
    "            # Otherwise, the pixel is a dictionary, so we can access it like such\n",
    "            assert amount > pixel['amount'], 'You must pay at least {} to purchase.'.format(pixel['amount'])\n",
    "            overwrite_pixel(x, y, color, amount, ctx.caller)\n",
    "            \n",
    "    def overwrite_pixel(x, y, color, amount, owner):\n",
    "        coin.spend_on_behalf(amount=amount, owner=ctx.caller, to=ctx.this)\n",
    "            \n",
    "        pixels.set[x, y] = {\n",
    "            'owner': owner,\n",
    "            'amount': amount,\n",
    "            'color': color\n",
    "        }\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "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",
    "Let's try to buy a pixel!"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {},
   "outputs": [],
   "source": [
    "client.submit(coin)\n",
    "client.submit(pixel_game)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {},
   "outputs": [],
   "source": [
    "coin_contract = client.get_contract('coin')\n",
    "pixel_contract = client.get_contract('pixel_game')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "1000000"
      ]
     },
     "execution_count": 7,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "coin_contract.balances['stu'] # Let's make sure we have the coins to make a pixel purchase."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "metadata": {},
   "outputs": [],
   "source": [
    "coin_contract.allow(amount=1, spender='pixel_game')\n",
    "pixel_contract.buy_pixel(x=10, y=10, color=5, amount=1)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "999999"
      ]
     },
     "execution_count": 9,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "coin_contract.balances['stu'] # The balance has deducted properly"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "{'owner': 'stu', 'amount': 1, 'color': 5}"
      ]
     },
     "execution_count": 10,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "pixel_contract.pixels[10, 10] # Now we can access the information and recieve the dictionary back"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "dict"
      ]
     },
     "execution_count": 11,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "type(pixel_contract.pixels[10, 10]) # Proof the dictionary is in fact a dictionary!"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.6.5"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}


================================================
FILE: examples/Rock Paper Scissors Tutorial.ipynb
================================================
{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Rock Paper Scissors"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "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. "
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "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. "
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Important Disclaimer:\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. "
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "First let's import some things we will need later."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {},
   "outputs": [],
   "source": [
    "from contracting.stdlib.bridge.hashing import sha3\n",
    "from contracting.client import ContractingClient\n",
    "import secrets"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "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."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {},
   "outputs": [],
   "source": [
    "def rps_contract():\n",
    "    # This tells the blockchain to make space for data. Variable and Hash are not Python builtins. \n",
    "    # They are globals (globals are something you can access without importing it) made available by contracting. \n",
    "    # Calling Variable() creates a new piece of memory within the blockchain, that can hold a single value. \n",
    "    # If we say \"foo = Variable()\" then we can interact with that piece of memory through \"foo\". \n",
    "    # We can set the piece of memory to 1, for example by calling \"foo.set(1)\".\n",
    "    # Setting the value will change the value for the next call to the smart contract.\n",
    "    # We can get the piece of memory by calling \"foo.get()\".\n",
    "    next_game_id = Variable()\n",
    "    \n",
    "    game_id_to_password_hash = Hash()\n",
    "    \n",
    "    game_id_to_player1_choice_hash = Hash()\n",
    "    game_id_to_player2_choice_hash = Hash()\n",
    "    \n",
    "    game_id_to_player1_choice = Hash()\n",
    "    game_id_to_player2_choice = Hash()\n",
    "            \n",
    "    # @construct means that this is the function that will be called ONCE when the smart contract is created\n",
    "    @construct\n",
    "    def constructor():\n",
    "        # Game id starts at 0.\n",
    "        next_game_id.set(0)\n",
    "        \n",
    "    # @export makes this function public, so it can be called by anyone on a deployed contract.\n",
    "    # By calling start_game player1 creates a game and also submits their hashed and salted choice.\n",
    "    @export\n",
    "    def start_game(password_hash, player1_choice_hash):\n",
    "        # This retrieves unique game Id from the blockchain. \n",
    "        unique_game_id = next_game_id.get()\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",
    "        # This increments the number by 1, so the next game has a unique Id.\n",
    "        next_game_id.set(next_game_id.get() + 1)       \n",
    "        \n",
    "        # Hash throws error on integer keys. That's why we convert to a string\n",
    "        # Remember player1 choice hash, and password hash for this game. \n",
    "        game_id_to_password_hash[str(unique_game_id)] = password_hash\n",
    "\n",
    "        game_id_to_player1_choice_hash[str(unique_game_id)] = player1_choice_hash\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",
    "        return unique_game_id\n",
    "    \n",
    "    # By calling submit_choice player2 submits their hashed and salted choice.\n",
    "    @export\n",
    "    def submit_choice(game_id, game_password, player2_choice_hash):\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",
    "        # Check that this is the right password for the game.\n",
    "        assert hashlib.sha3(game_password) == game_id_to_password_hash[str(game_id)], 'Wrong password!'\n",
    "        \n",
    "        # Remember player2's choice.\n",
    "        game_id_to_player2_choice_hash[str(game_id)] = player2_choice_hash\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",
    "        return\n",
    "    \n",
    "    # Returns 'player1_wins' if player1 is the winner.\n",
    "    # Returns 'player2_wins' if player2 is the winner.\n",
    "    # Returns 'tie' if both players made the same choice.\n",
    "    # Returns 'game_doesnt_exist' if the game doesn't exist\n",
    "    # Returns 'player1_has_submitted' if the game has been started and only player1 has submitted their choice\n",
    "    # Returns 'both_players_have_submitted' if both players have submitted but none has revealed their choice\n",
    "    # Returns 'only_player1_revealed' after player1 but not player2 has revealed their choice\n",
    "    # Returns 'only_player2_revealed' after player2 but not player1 has revealed their choice\n",
    "    \n",
    "    @export\n",
    "    def get_game_state(game_id):\n",
    "        if next_game_id.get() <= game_id:\n",
    "            return \"game_doesnt_exist\"\n",
    "        \n",
    "        player1_hashed_choice = game_id_to_player1_choice_hash[str(game_id)]\n",
    "        player2_hashed_choice = game_id_to_player2_choice_hash[str(game_id)]\n",
    "\n",
    "        if player1_hashed_choice is not None and player2_hashed_choice is None:\n",
    "            return \"only_player1_submitted\"\n",
    "        \n",
    "        player1_choice = game_id_to_player1_choice[str(game_id)]\n",
    "        player2_choice = game_id_to_player2_choice[str(game_id)]\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",
    "            return \"both_players_submitted\"\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",
    "        # For the rest of the function we know that both players have submitted their choices \n",
    "        # and one player has revealed their choice\n",
    "        \n",
    "        if player1_choice is not None and player2_choice is None:\n",
    "            return \"only_player1_revealed\"\n",
    "        \n",
    "        if player1_choice is None and player2_choice is not None:\n",
    "            return \"only_player2_revealed\"\n",
    "        \n",
    "        # Make sure that both players have submitted their choices\n",
    "        assert player1_choice is not None and player2_choice is not None, \"this is a bug in the contract. error code 2\"\n",
    "        # For the rest of the function we know that both players have submitted their choices\n",
    "        \n",
    "        # Now that we have both choices we can resolve the game\n",
    "        \n",
    "        if player1_choice == player2_choice:\n",
    "            return \"tie\"\n",
    "\n",
    "        if beats(player1_choice, player2_choice):\n",
    "            return \"player1_wins\"\n",
    "        \n",
    "        if beats(player2_choice, player1_choice):\n",
    "            return \"player2_wins\"\n",
    "        \n",
    "    @export\n",
    "    def is_valid_choice(choice):\n",
    "        return choice in [\"rock\", \"paper\", \"scissors\"]\n",
    "      \n",
    "    # Returns whether choice1 beats choice2\n",
    "    @export\n",
    "    def beats(choice1, choice2):\n",
    "        assert is_valid_choice(choice1), \"choice1 must be a valid choice\"\n",
    "        assert is_valid_choice(choice2), \"choice2 must be a valid choice\"\n",
    "\n",
    "        if choice1 == \"rock\" and choice2 == \"scissors\":\n",
    "            return True\n",
    "        \n",
    "        if choice1 == \"paper\" and choice2 == \"rock\":\n",
    "            return True\n",
    "        \n",
    "        if choice1 == \"scissors\" and choice2 == \"paper\":\n",
    "            return True\n",
    "        \n",
    "        return False\n",
    "    \n",
    "    # By calling reveal a player can reveal their unhashed choice.\n",
    "    # Player1 has to call the function with is_player1=true.\n",
    "    # Player2 has to call the function with is_player1=false.\n",
    "    @export\n",
    "    def reveal(game_id, choice, choice_salt, is_player1):\n",
    "        if is_player1:\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",
    "        else:\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",
    "        # Make sure players can only reveal valid choices\n",
    "        assert is_valid_choice(choice), \"choice must be rock, paper or scissors\"\n",
    "                \n",
    "        # Now we need to check that the reveal hashes to what was submitted earlier\n",
    "        \n",
    "        salted_choice = choice + choice_salt\n",
    "        hashed_choice = hashlib.sha3(salted_choice)\n",
    "        \n",
    "        if is_player1:\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",
    "        else:\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",
    "        # Now we're sure that the player has revealed the choice they have previously submitted the hashed salted version of\n",
    "        \n",
    "        # Remember the choice\n",
    "        if is_player1:\n",
    "            game_id_to_player1_choice[str(game_id)] = choice\n",
    "        else:\n",
    "            game_id_to_player2_choice[str(game_id)] = choice\n",
    "        \n",
    "        return"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Welcome back! Lets get this contract into the blockchain. To interact with the blockchain we need a client. "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {},
   "outputs": [],
   "source": [
    "client = ContractingClient(signer='ren')"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Get rid of all state of the blockchain so we have a blank slate. Otherwise running this script twice causes problems. "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {},
   "outputs": [],
   "source": [
    "client.flush()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "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, ..."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {},
   "outputs": [],
   "source": [
    "client.submit(rps_contract)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Get a handle for the contract that we can interact with."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "metadata": {},
   "outputs": [],
   "source": [
    "contract = client.get_contract('rps_contract')"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "With the contract in the blockchain we can now play Rock, Paper, Scissors. Our players for this example are Alice and Bob."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "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. "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "metadata": {},
   "outputs": [],
   "source": [
    "alice_game_password = \"trollbridge\""
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "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. "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "'47a5bcfb0d81053f5025ab57e6b94f43751f91bdb16fc0d63595223dc78ec1b4'"
      ]
     },
     "execution_count": 9,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "alice_game_password_hash = sha3(alice_game_password)\n",
    "alice_game_password_hash"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Alice chooses rock."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "metadata": {},
   "outputs": [],
   "source": [
    "alice_choice = \"rock\""
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "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. "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "'bd996e2dc82a7c3e2c2da41291648e852b62b01fb09bcb6ed77975c273f08404'"
      ]
     },
     "execution_count": 11,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "alice_choice_hash = sha3(alice_choice)\n",
    "alice_choice_hash"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "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."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "'88ceef7a2c748432d5a150fcff5df717c8a67298365ae2e1969be4ee856ce39e'"
      ]
     },
     "execution_count": 12,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "alice_choice_salt = secrets.token_hex(32)\n",
    "alice_choice_salt"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "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."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 13,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "'rock88ceef7a2c748432d5a150fcff5df717c8a67298365ae2e1969be4ee856ce39e'"
      ]
     },
     "execution_count": 13,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "alice_salted_choice = alice_choice + alice_choice_salt\n",
    "alice_salted_choice"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 14,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "'dcbd95890db4648405b1e04541b6dcabacc1c3e958172171262dc11d6dacebf7'"
      ]
     },
     "execution_count": 14,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "alice_salted_choice_hash = sha3(alice_salted_choice)\n",
    "alice_salted_choice_hash"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Before a game is started it is in state `\"game_doesnt_exist\"`"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 15,
   "metadata": {},
   "outputs": [],
   "source": [
    "assert contract.get_game_state(game_id=0) == \"game_doesnt_exist\""
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Now Alice starts a game so she can invite Bob to play."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 16,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "0"
      ]
     },
     "execution_count": 16,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "alice_game_id = contract.start_game(password_hash=alice_game_password_hash, player1_choice_hash=alice_salted_choice_hash) \n",
    "alice_game_id"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Alice gets back a game Id."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "The game is now in state \"only_player1_submitted\""
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 17,
   "metadata": {},
   "outputs": [],
   "source": [
    "assert contract.get_game_state(game_id=alice_game_id) == \"only_player1_submitted\""
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "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",
    "Everything that starts with bob_ is only visible to Bob."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 18,
   "metadata": {},
   "outputs": [],
   "source": [
    "bob_game_password = alice_game_password\n",
    "bob_game_id = alice_game_id"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Now it is Bobs turn.\n",
    "Bob chooses scissors."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 19,
   "metadata": {},
   "outputs": [],
   "source": [
    "bob_choice = \"scissors\""
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "And now Bob has to salt his choice."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 20,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "'13729fb6834f46b30046d82ba9e624821a479ed1f7714152c8a4da81b42d1213'"
      ]
     },
     "execution_count": 20,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "bob_choice_salt = secrets.token_hex(32)\n",
    "bob_choice_salt"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "And now we combine bob_choice and bob_choice_salt together and hash them."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 21,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "'scissors13729fb6834f46b30046d82ba9e624821a479ed1f7714152c8a4da81b42d1213'"
      ]
     },
     "execution_count": 21,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "bob_salted_choice = bob_choice + bob_choice_salt\n",
    "bob_salted_choice"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 22,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "'9af37ec1317afab75c13f89f1d4a8b4c39f77ae52e7ad05116a5f8b2f9995125'"
      ]
     },
     "execution_count": 22,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "bob_salted_choice_hash = sha3(bob_salted_choice)\n",
    "bob_salted_choice_hash"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Bob now needs to submit his choice to the blockchain. Only Bob has the game password so only Bob can join Alices game."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 23,
   "metadata": {},
   "outputs": [],
   "source": [
    "contract.submit_choice(game_password=bob_game_password, game_id=bob_game_id, player2_choice_hash=bob_salted_choice_hash)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "The game is now in state \"both_players_submitted\""
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 24,
   "metadata": {},
   "outputs": [],
   "source": [
    "assert contract.get_game_state(game_id=bob_game_id) == \"both_players_submitted\""
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Now that both players have submitted their hashed and salted choices, both players can reveal their choices.\n",
    "The order doesn't matter. Alice goes first in this example."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 25,
   "metadata": {},
   "outputs": [],
   "source": [
    "contract.reveal(game_id=alice_game_id, choice=alice_choice, choice_salt=alice_choice_salt, is_player1=True)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "The game is now in state \"only_player1_revealed\""
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 26,
   "metadata": {},
   "outputs": [],
   "source": [
    "assert contract.get_game_state(game_id=alice_game_id) == \"only_player1_revealed\""
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Bob goes second"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 27,
   "metadata": {},
   "outputs": [],
   "source": [
    "contract.reveal(game_id=bob_game_id, choice=bob_choice, choice_salt=bob_choice_salt, is_player1=False)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Now we can see who won the game"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 28,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "'player1_wins'"
      ]
     },
     "execution_count": 28,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "contract.get_game_state(game_id=alice_game_id)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "As expected Alice, who is player1, wins!"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## tests"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Test function is_valid_choice"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 29,
   "metadata": {},
   "outputs": [],
   "source": [
    "assert contract.is_valid_choice(choice=\"rock\")\n",
    "assert contract.is_valid_choice(choice=\"paper\")\n",
    "assert contract.is_valid_choice(choice=\"scissors\")\n",
    "assert not contract.is_valid_choice(choice=\"airplane\")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Test function beats"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 30,
   "metadata": {},
   "outputs": [],
   "source": [
    "assert contract.beats(choice1=\"rock\", choice2=\"scissors\")\n",
    "assert not contract.beats(choice1=\"rock\", choice2=\"rock\")\n",
    "assert not contract.beats(choice1=\"rock\", choice2=\"paper\")\n",
    "\n",
    "assert contract.beats(choice1=\"paper\", choice2=\"rock\")\n",
    "assert not contract.beats(choice1=\"paper\", choice2=\"paper\")\n",
    "assert not contract.beats(choice1=\"paper\", choice2=\"scissors\")\n",
    "\n",
    "assert contract.beats(choice1=\"scissors\", choice2=\"paper\")\n",
    "assert not contract.beats(choice1=\"scissors\", choice2=\"scissors\")\n",
    "assert not contract.beats(choice1=\"scissors\", choice2=\"rock\")"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.7.3"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}


================================================
FILE: pyproject.toml
================================================
[tool.poetry]
name = "xian-contracting"
version = "1.0.1"
description = "Xian Network Python Contracting Engine"
authors = ["Xian Network <info@xian.org>"]
readme = "README.md"
packages = [{include = "contracting", from = "src"}]
license = "GPL-3.0-only"
repository = "https://github.com/xian-network/xian-contracting"
keywords = ["blockchain", "xian", "contracting", "python"]
classifiers = [
    "Programming Language :: Python :: 3.11",
    "License :: OSI Approved :: GNU General Public License v3 (GPLv3)",
    "Development Status :: 5 - Production/Stable",
]

[tool.poetry.dependencies]
python = "~=3.11.0"
astor = "0.8.1"
pycodestyle = "2.10.0"
autopep8 = "1.5.7"
iso8601 = "*"
h5py = "*"
cachetools = "*"
loguru = "*"
pynacl = "*"
psutil = "*"

[build-system]
requires = ["poetry-core"]
build-backend = "poetry.core.masonry.api"


================================================
FILE: release.sh
================================================
#!/bin/bash

set -e  # Exit on any error

# Colors for output
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
NC='\033[0m' # No Color

# Function to print with color
print_status() {
    echo -e "${GREEN}==>${NC} $1"
}

print_warning() {
    echo -e "${YELLOW}WARNING:${NC} $1"
}

print_error() {
    echo -e "${RED}ERROR:${NC} $1"
}

# Check if a version bump type was provided
if [ -z "$1" ]; then
    print_error "Please provide a version bump type: patch, minor, or major"
    echo "Usage: ./release.sh [patch|minor|major]"
    exit 1
fi

# Validate version bump type
if [ "$1" != "patch" ] && [ "$1" != "minor" ] && [ "$1" != "major" ]; then
    print_error "Invalid version bump type. Please use: patch, minor, or major"
    exit 1
fi

# Make sure we're on the master branch
BRANCH=$(git branch --show-current)
if [ "$BRANCH" != "master" ]; then
    print_error "Please switch to the master branch before creating a release"
    exit 1
fi

# Make sure the working directory is clean
if [ -n "$(git status --porcelain)" ]; then
    print_error "Working directory is not clean. Please commit or stash changes first."
    exit 1
fi

# Check if poetry is installed
if ! command -v poetry &> /dev/null; then
    print_error "Poetry could not be found. Please install it first."
    exit 1
fi

# Check if pytest is installed
if ! poetry run python -c "import pytest" 2>/dev/null; then
    print_warning "pytest is not installed. Skipping tests."
    RUN_TESTS=false
else
    RUN_TESTS=true
fi

# Pull latest changes
print_status "Pulling latest changes from master..."
git pull origin master

# Show what the new version will be and ask for confirmation
CURRENT_VERSION=$(poetry version -s)
NEW_VERSION=$(poetry version $1 --dry-run)
print_status "Current version: $CURRENT_VERSION"
print_status "New version will be: $NEW_VERSION"

# Generate changelog
LAST_TAG=$(git describe --tags --abbrev=0 2>/dev/null || echo "none")
if [ "$LAST_TAG" != "none" ]; then
    print_status "Generating changelog since $LAST_TAG..."
    CHANGELOG=$(git log "$LAST_TAG"..HEAD --oneline --pretty=format:"- %s")
else
    CHANGELOG=$(git log --oneline --pretty=format:"- %s")
fi

echo -e "\nChangelog:"
echo "$CHANGELOG"
echo

# Check dependencies
print_status "Checking for outdated dependencies..."
poetry show --outdated || true

# Run tests if available
if [ "$RUN_TESTS" = true ]; then
    print_status "Running tests..."
    poetry run pytest || {
        print_error "Tests failed!"
        exit 1
    }
fi

# Final confirmation
echo
print_status "Ready to release version $NEW_VERSION"
read -p "Continue? (y/n) " -n 1 -r
echo
if [[ ! $REPLY =~ ^[Yy]$ ]]; then
    print_status "Release cancelled."
    exit 1
fi

# Update version using Poetry
print_status "Bumping version ($1)..."
poetry version $1

# Create release notes file
RELEASE_NOTES="release_notes.md"
echo "# Release Notes for v$NEW_VERSION" > $RELEASE_NOTES
echo "" >> $RELEASE_NOTES
echo "## Changes" >> $RELEASE_NOTES
echo "$CHANGELOG" >> $RELEASE_NOTES

# Stage and commit version bump
print_status "Committing version bump..."
git add pyproject.toml $RELEASE_NOTES
git commit -m "Bump version to $NEW_VERSION

Release Notes:
$CHANGELOG"

# Create and push tag
print_status "Creating and pushing tag v$NEW_VERSION..."
git tag -a "v$NEW_VERSION" -m "Version $NEW_VERSION

$CHANGELOG"
git push && git push --tags

# Cleanup
rm $RELEASE_NOTES

print_status "Release process initiated!"
print_status "Version $NEW_VERSION will be published to PyPI and GitHub releases automatically."
print_status "You can monitor the progress at: https://github.com/xian-network/xian-contracting/actions"

================================================
FILE: src/contracting/__init__.py
================================================


================================================
FILE: src/contracting/client.py
================================================
from contracting.execution.executor import Executor
from contracting.storage.driver import Driver
from contracting.compilation.compiler import ContractingCompiler
from contracting.stdlib.bridge.time import Datetime
from datetime import datetime
from functools import partial
from types import FunctionType

import ast
import inspect
import astor
import autopep8
import os

from . import constants

from .storage.orm import Variable
from .storage.orm import Hash


class AbstractContract:
    def __init__(self, name, signer, environment, executor: Executor, funcs, return_full_output=False):
        self.name = name
        self.signer = signer
        self.environment = environment
        self.executor = executor
        self.functions = funcs

        # set up virtual functions
        for f in funcs:
            # unpack tuple packed in SenecaClient
            func, kwargs = f

            # set the kwargs to None. these will fail if they are not provided
            default_kwargs = {}
            for kwarg in kwargs:
                default_kwargs[kwarg] = None

            # each function is a partial that allows kwarg overloading and overriding
            setattr(self, func, partial(self._abstract_function_call,
                                        signer=self.signer,
                                        contract_name=self.name,
                                        executor=self.executor,
                                        func=func,
                                        return_full_output=return_full_output,
                                        # environment=self.environment,
                                        **default_kwargs))

    def keys(self):
        # Scope strictly to this contract's namespace
        return self.executor.driver.keys(f"{self.name}.")

    # a variable contains a DOT, but no __, and no :
    # a hash contains a DOT, no __, and a :
    # a constant contains __, a DOT, and :

    def quick_read(self, variable, key=None, args=None):
        a = []

        if key is not None:
            a.append(key)

        if args is not None and isinstance(args, list):
            for arg in args:
                a.append(arg)

        k = self.executor.driver.make_key(contract=self.name, variable=variable, args=a)
        return self.executor.driver.get(k)

    def quick_write(self, variable, key=None, value=None, args=None):
        if key is not None:
            a = [key]
        else:
            a = []

        if args is not None and isinstance(args, list):
            for arg in args:
                a.append(arg)

        k = self.executor.driver.make_key(contract=self.name, variable=variable, args=a)

        self.executor.driver.set(k, value)
        self.executor.driver.commit()

    def run_private_function(self, f, signer=None, environment=None, **kwargs):
        # Override kwargs if provided
        signer = signer or self.signer
        environment = environment or self.environment

        # Let executor access private functions
        self.executor.bypass_privates = True

        # Append private method prefix to function name if it isn't there already
        if not f.startswith(constants.PRIVATE_METHOD_PREFIX):
            f = '{}{}'.format(constants.PRIVATE_METHOD_PREFIX, f)

        # Execute
        result = self._abstract_function_call(
            signer=signer,
            executor=self.executor,
            contract_name=self.name,
            environment=environment,
            func=f,
            metering=None,
            now=None,
            **kwargs
        )

        # Set executor back to restricted mode
        self.executor.bypass_privates = False

        return result

    def __getattr__(self, item):
        try:
            # return the attribute if it exists on the instance
            return self.__getattribute__(item)
        except AttributeError as e:

            # otherwise, attempt to resolve it. full name is contract.item
            fullname = '{}.{}'.format(self.name, item)

            # if the raw name exists, it is a __protected__ or a variable, so prepare for those
            if fullname in self.keys():
                variable = Variable(contract=self.name, name=item, driver=self.executor.driver)

                # return just the value if it is __protected__ to prevent sets
                if item.startswith('__'):
                    return variable.get()

                # otherwise, return the variable object with allows sets
                return variable

            # otherwise, see if contract.items: has more than one entry
            if len(self.executor.driver.values(prefix=self.name + '.' + item + ':')) > 0:

                # if so, it is a hash. return the hash object
                return Hash(contract=self.name, name=item, driver=self.executor.driver)

            # otherwise, the attribut does not exist, so throw the error.
            raise e

    def now(self):
        d = datetime.today()
        return Datetime(d.year, d.month, d.day, hour=d.hour, minute=d.minute)

    def _abstract_function_call(
            self,
            signer,
            executor,
            contract_name,
            func,
            environment=None,
            stamps=constants.DEFAULT_STAMPS,
            metering=None,
            now=None,
            return_full_output=False,
            **kwargs
    ):

        # for k, v in kwargs.items():
        #     assert v is not None, 'Keyword "{}" not provided. Must not be None.'.format(k)
        environment = environment or self.environment

        if now is None:
            now = self.now()

        if environment.get('now') is None:
            environment.update({'now': now})

        output = executor.execute(
            sender=signer,
            contract_name=contract_name,
            function_name=func,
            kwargs=kwargs,
            stamps=stamps,
            environment=environment,
            metering=metering
        )

        if executor.production:
            executor.sandbox.terminate()

        if output['status_code'] == 1:
            raise output['result'] if not return_full_output else output
        return output['result'] if not return_full_output else output


class ContractingClient:
    def __init__(
            self,
            signer='sys',
            submission_filename=os.path.join(os.path.dirname(__file__), 'contracts/submission.s.py'),
            storage_home=constants.STORAGE_HOME,
            driver:Driver=None,
            metering=False,
            compiler=ContractingCompiler(),
            environment={},
    ):
        driver = driver if driver is not None else Driver(storage_home=storage_home)
        self.executor = Executor(metering=metering, driver=driver)
        self.raw_driver = driver
        self.signer = signer
        self.compiler = compiler
        self.submission_filename = submission_filename
        self.environment = environment
        # Get submission contract from file
        if submission_filename is not None:
            # Seed the genesis contracts into the instance
            with open(self.submission_filename) as f:
                contract = f.read()

            self.raw_driver.set_contract(name='submission', code=contract)
            self.raw_driver.commit()

        # Get submission contract from state
        self.submission_contract = self.get_contract('submission')

    def set_submission_contract(self, filename=None, commit=True):
        state_contract = self.get_contract('submission')

        if filename is None:
            filename = self.submission_filename

        if filename is None and state_contract is None:
            raise AssertionError("No submission contract provided or found in state.")

        if filename is not None:
            with open(filename) as f:
                contract = f.read()

            self.raw_driver.delete_contract(name='submission')
            self.raw_driver.set_contract(name='submission', code=contract)

            if commit:
                self.raw_driver.commit()

        self.submission_contract = self.get_contract('submission')

    def flush(self):
        # flushes storage and resubmits genesis contracts
        self.raw_driver.flush_full()
        self.raw_driver.flush_cache()

        if self.submission_filename is not None:
            self.set_submission_contract()

    # Returns abstract contract which has partial methods mapped to each exported function.
    def get_contract(self, name):
        contract = self.raw_driver.get_contract(name)

        if contract is None:
            return None

        tree = ast.parse(contract)

        function_defs = [n for n in ast.walk(tree) if isinstance(n, ast.FunctionDef)]

        funcs = []
        for definition in function_defs:
            func_name = definition.name
            kwargs = [arg.arg for arg in definition.args.args]

            funcs.append((func_name, kwargs))

        return AbstractContract(
            name=name,
            signer=self.signer,
            environment=self.environment,
            executor=self.executor,
            funcs=funcs,
        )

    def closure_to_code_string(self, f):
        closure_code = inspect.getsource(f)
        closure_code = autopep8.fix_code(closure_code)
        closure_tree = ast.parse(closure_code)

        # Remove the enclosing function by swapping out the function def node with its children
        assert len(closure_tree.body) == 1, 'Module has multiple body nodes.'
        assert isinstance(closure_tree.body[0], ast.FunctionDef), 'Function definition not found at root.'

        func_def_body = closure_tree.body[0]
        closure_tree.body = func_def_body.body

        contract_code = astor.to_source(closure_tree)
        name = func_def_body.name

        return contract_code, name

    def lint(self, f, raise_errors=False):
        if isinstance(f, FunctionType):
            f, _ = self.closure_to_code_string(f)

        tree = ast.parse(f)
        violations = self.compiler.linter.check(tree)

        if violations is None:
            return None
        else:
            if raise_errors:
                for v in violations:
                    raise Exception(v)
            else:
                return violations

    def compile(self, f):
        if isinstance(f, FunctionType):
            f, _ = self.closure_to_code_string(f)

        code = self.compiler.parse_to_code(f)
        return code

    def submit(self, f, name=None, metering=None, owner=None, constructor_args={}, signer=None):

        assert self.submission_contract is not None, "No submission contract set. Try set_submission_contract first."

        if isinstance(f, FunctionType):
            f, n = self.closure_to_code_string(f)
            if name is None:
                name = n

        assert name is not None, 'No name provided.'

        if signer is None:
            signer = self.signer

        self.submission_contract.submit_contract(
            name=name,
            code=f,
            owner=owner,
            constructor_args=constructor_args,
            metering=metering,
            signer=signer
        )

    def get_contracts(self):
        contracts = []
        for key in self.raw_driver.keys():
            if key.endswith('.__code__'):
                contracts.append(key.replace('.__code__', ''))
        return contracts

    def get_var(self, contract, variable, arguments=[], mark=False):
        return self.raw_driver.get_var(contract, variable, arguments, mark)

    def set_var(self, contract, variable, arguments=[], value=None, mark=False):
        self.raw_driver.set_var(contract, variable, arguments, value, mark)


================================================
FILE: src/contracting/compilation/__init__.py
================================================


================================================
FILE: src/contracting/compilation/compiler.py
================================================
import ast
import astor

from contracting import constants
from contracting.compilation.linter import Linter


class ContractingCompiler(ast.NodeTransformer):
    def __init__(self, module_name='__main__', linter=Linter()):
        self.module_name = module_name
        self.linter = linter
        self.lint_alerts = None
        self.constructor_visited = False
        self.private_names = set()
        self.orm_names = set()
        self.visited_names = set()  # store the method visits

    def parse(self, source: str, lint=True):
        self.constructor_visited = False

        tree = ast.parse(source)

        if lint:
            self.lint_alerts = self.linter.check(tree)
            # compilation.fix_missing_locations(tree)

        tree = self.visit(tree)

        if self.lint_alerts is not None:
            raise Exception(self.lint_alerts)

        # check all visited nodes and see if they are actually private

        # An Expr node can have a value func of compilation.Name, or compilation.
        # Attribute which you much access the value of.
        # TODO: This code branching is not ideal and should be investigated for simplicity.
        for node in self.visited_names:
            if node.id in self.private_names or node.id in self.orm_names:
                node.id = self.privatize(node.id)

        ast.fix_missing_locations(tree)

        # reset state
        self.private_names = set()
        self.orm_names = set()
        self.visited_names = set()

        return tree

    @staticmethod
    def privatize(s):
        return '{}{}'.format(constants.PRIVATE_METHOD_PREFIX, s)

    def compile(self, source: str, lint=True):
        tree = self.parse(source, lint=lint)

        compiled_code = compile(tree, '<compilation>', 'exec')

        return compiled_code

    def parse_to_code(self, source, lint=True):
        tree = self.parse(source, lint=lint)
        code = astor.to_source(tree)
        return code

    def visit_FunctionDef(self, node):

        # Presumes all decorators are valid, as caught by linter.
        if node.decorator_list:
            # Presumes that a single decorator is passed. This is caught by the linter.
            decorator = node.decorator_list.pop()

            # change the name of the init function to '____' so it is uncallable except once
            if decorator.id == constants.INIT_DECORATOR_STRING:
                node.name = '____'

            elif decorator.id == constants.EXPORT_DECORATOR_STRING:
                # Transform @export decorators to @__export(contract_name) decorators
                decorator.id = '{}{}'.format('__', constants.EXPORT_DECORATOR_STRING)

                new_node = ast.Call(
                    func=decorator,
                    args=[ast.Str(s=self.module_name)],
                    keywords=[]
                )

                node.decorator_list.append(new_node)

        else:
            self.private_names.add(node.name)
            node.name = self.privatize(node.name)

        self.generic_visit(node)

        return node

    def visit_Assign(self, node):
        if (isinstance(node.value, ast.Call) and not
            isinstance(node.value.func, ast.Attribute) and
            node.value.func.id in constants.ORM_CLASS_NAMES):

            node.value.keywords.append(ast.keyword('contract', ast.Str(self.module_name)))
            node.value.keywords.append(ast.keyword('name', ast.Str(node.targets[0].id)))
            self.orm_names.add(node.targets[0].id)

        self.generic_visit(node)

        return node

    def visit_Name(self, node):
        self.visited_names.add(node)
        return node

    def visit_Expr(self, node):
        self.generic_visit(node)
        return node

    def visit_Num(self, node):
        if isinstance(node.n, float):
            return ast.Call(func=ast.Name(id='decimal', ctx=ast.Load()),
                            args=[ast.Str(str(node.n))], keywords=[])
        return node


================================================
FILE: src/contracting/compilation/linter.py
================================================
import ast
import sys

from .. import constants

from ..compilation.whitelists import (
    ALLOWED_AST_TYPES,
    ALLOWED_ANNOTATION_TYPES,
    VIOLATION_TRIGGERS,
    ILLEGAL_BUILTINS,
    ILLEGAL_AST_TYPES
)


class Linter(ast.NodeVisitor):

    def __init__(self):
        self._violations = []
        self._functions = []
        self._is_one_export = False
        self._is_success = True
        self._constructor_visited = False
        self.orm_names = set()
        self.visited_args = set()
        self.return_annotation = set()
        self.arg_types = set()

        self.builtins = list(set(list(sys.stdlib_module_names) + list(sys.builtin_module_names)))

    def ast_types(self, t, lnum):
        if type(t) not in ALLOWED_AST_TYPES:
            str = "Line {}".format(lnum) + " : " + VIOLATION_TRIGGERS[0] + " : {}" .format(type(t).__name__)
            self._violations.append(str)
            self._is_success = False

    def not_system_variable(self, v, lnum):
        if v.startswith('_') or v.endswith('_'):
            str = "Line {} : ".format(lnum) + VIOLATION_TRIGGERS[1] + " : {}" .format(v)
            self._violations.append(str)
            self._is_success = False

    def no_nested_imports(self, node):
        for item in node.body:
            if type(item) in [ast.ImportFrom, ast.Import]:
                str = "Line {}: ".format(node.lineno) + VIOLATION_TRIGGERS[2]
                self._violations.append(str)
                self._is_success = False

    def visit_Name(self, node):
        self.not_system_variable(node.id, node.lineno)

        if node.id == 'rt':# or node.id == 'Hash' or node.id == 'Variable':
            self._is_success = False
            str = "Line {}: ".format(node.lineno) + VIOLATION_TRIGGERS[13]
            self._violations.append(str)

        if node.id in ILLEGAL_BUILTINS and node.id != 'float':
            self._is_success = False
            str = "Line {}: ".format(node.lineno) + VIOLATION_TRIGGERS[13]
            self._violations.append(str)

        self.generic_visit(node)
        return node

    def visit_Attribute(self, node):
        self.not_system_variable(node.attr, node.lineno)
        if node.attr == 'rt':
            self._is_success = False
            str = "Line {}: ".format(node.lineno) + VIOLATION_TRIGGERS[13]
            self._violations.append(str)
        self.generic_visit(node)
        return node

    def visit_Import(self, node):
        for n in node.names:
            if n.name in self.builtins:
                self._is_success = False
                str = "Line {}: ".format(node.lineno) + VIOLATION_TRIGGERS[13]
                self._violations.append(str)
        return node

    def visit_ImportFrom(self, node):
        str = "Line {}: ".format(node.lineno) + VIOLATION_TRIGGERS[3]
        self._violations.append(str)
        self._is_success = False

    # TODO: Why are we even doing any logic instead of just failing on visiting these?
    def visit_ClassDef(self, node):
        str = "Line {}: ".format(node.lineno) + VIOLATION_TRIGGERS[5]
        self._violations.append(str)
        self._is_success = False
        self.generic_visit(node)
        return node

    def visit_AsyncFunctionDef(self, node):
        str = "Line {}: ".format(node.lineno) + VIOLATION_TRIGGERS[6]
        self._violations.append(str)

        self._is_success = False
        self.generic_visit(node)
        return node

    def visit_Assign(self, node):
        # resource_names, func_name = Assert.valid_assign(node, Parser.parser_scope)
        if isinstance(node.value, ast.Name):
            if node.value.id == 'Hash' or node.value.id == 'Variable' or node.value.id == 'LogEvent':
                self._is_success = False
                str = "Line {}: ".format(node.lineno) + VIOLATION_TRIGGERS[13]
                self._violations.append(str)

        if (isinstance(node.value, ast.Call) and not
            isinstance(node.value.func, ast.Attribute) and
            node.value.func.id in constants.ORM_CLASS_NAMES):

            if node.value.func.id in ['Variable', 'Hash', 'LogEvent']:
                kwargs = [k.arg for k in node.value.keywords]
                if 'contract' in kwargs or 'name' in kwargs:
                    self._is_success = False
                    str = "Line {}: ".format(node.lineno) + VIOLATION_TRIGGERS[10]
                    self._violations.append(str)
            if ast.Tuple in [type(t) for t in node.targets] or isinstance(node.value, ast.Tuple):
                self._is_success = False
                str = "Line {}: ".format(node.lineno) + VIOLATION_TRIGGERS[11]
                self._violations.append(str)
            try:
                self.orm_names.add(node.targets[0].id)
            except AttributeError:
                pass

        self.generic_visit(node)

        return node

    def visit_AugAssign(self, node):
        # TODO: Checks here?
        self.generic_visit(node)
        return node

    def visit_Call(self, node: ast.Call):
        # Prevent calling of illegal builtins
        if isinstance(node.func, ast.Name):
            if node.func.id in ILLEGAL_BUILTINS:
                self._is_success = False
                str = "Line {}: ".format(node.lineno) + VIOLATION_TRIGGERS[13]
                self._violations.append(str)

        self.generic_visit(node)
        return node

    def generic_visit(self, node):
        # Prevent calling of illegal builtins

        if type(node) in ILLEGAL_AST_TYPES:
            self._is_success = False
            s = "Line {}: ".format(node.lineno) + VIOLATION_TRIGGERS[0]
            self._violations.append(s)

        return super().generic_visit(node)

    def visit_Num(self, node):
        # NOTE: Integers are important for indexing and slicing so we cannot replace them.
        # They also will not suffer from rounding issues.
        # TODO: are any types we don't allow right now?
        self.generic_visit(node)
        return node

    def visit_FunctionDef(self, node):
        self.no_nested_imports(node)

        # Make sure there are no closures
        try:
            for n in node.body:
                if isinstance(n, ast.FunctionDef):
                    str = "Line {}: ".format(node.lineno) + VIOLATION_TRIGGERS[18]
                    self._violations.append(str)
                    self._is_success = False
        except:
            pass

        # Only allow 1 decorator per function definition.
        if len(node.decorator_list) > 1:
            str = "Line {}: ".format(node.lineno) + VIOLATION_TRIGGERS[9] + \
                  ": Detected: {} MAX limit: 1".format(len(node.decorator_list))
            self._violations.append(str)
            self._is_success = False
        export_decorator = False
        for d in node.decorator_list:
            # Only allow decorators from the allowed set.
            if d.id not in constants.VALID_DECORATORS:
                str = "Line {}: ".format(node.lineno) + VIOLATION_TRIGGERS[7] + \
                      ": valid list: {}".format(d.id, constants.VALID_DECORATORS)
                self._violations.append(str)
                self._is_success = False

            if d.id == constants.EXPORT_DECORATOR_STRING:
                self._is_one_export = True
                export_decorator = True

            if d.id == constants.INIT_DECORATOR_STRING:
                if self._constructor_visited:
                    str = "Line {}: ".format(node.lineno) + VIOLATION_TRIGGERS[8]
                    self._violations.append(str)
                    self._is_success = False
                self._constructor_visited = True

        # Add argument names to set to make sure that no ORM variable names are being reused in function def args
        arguments = node.args
        for a in arguments.args:
            self.visited_args.add((a.arg, node.lineno))
            if export_decorator:
                if a.annotation is not None:
                    try:
                        self.arg_types.add((a.annotation.id, node.lineno))
                    except AttributeError:
                        arg = a.annotation.value.id + '.' + a.annotation.attr
                        self.arg_types.add((arg, node.lineno))
                else:
                    self.arg_types.add((None, node.lineno))

        if export_decorator:
            if node.returns is not None:
                try:
                    self.arg_types.add((a.annotation.id, node.lineno))
                except AttributeError:
                    arg = a.annotation.value.id + '.' + a.annotation.attr
                    self.arg_types.add((arg, node.lineno))
            else:
                self.return_annotation.add((None, node.lineno))

        self.generic_visit(node)
        return node

    def annotation_types(self, t, lnum):
        if t is None:
            str = "Line {}".format(lnum) + " : " + VIOLATION_TRIGGERS[16]
            self._violations.append(str)
            self._is_success = False
        elif t not in ALLOWED_ANNOTATION_TYPES:
            str = "Line {}".format(lnum) + " : " + VIOLATION_TRIGGERS[15] + " : {}" .format(t)
            self._violations.append(str)
            self._is_success = False

    def check_return_types(self, t, lnum):
        if t is not None:
            str = "Line {}".format(lnum) + " : " + VIOLATION_TRIGGERS[17] + " : {}" .format(t)
            self._violations.append(str)
            self._is_success = False

    def _reset(self):
        self._violations = []
        self._functions = []
        self._is_one_export = False
        self._is_success = True
        self._constructor_visited = False
        self.orm_names = set()
        self.visited_args = set()
        self.return_annotation = set()
        self.arg_types = set()

    def _final_checks(self):
        for name, lineno in self.visited_args:
            if name in self.orm_names:
                str = "Line {}: ".format(lineno) + VIOLATION_TRIGGERS[14]
                self._violations.append(str)
                self._is_success = False

        if not self._is_one_export:
            str = "Line 0: " + VIOLATION_TRIGGERS[12]
            self._violations.append(str)
            self._is_success = False

        for t, lineno in self.arg_types:
            self.annotation_types(t,lineno)

        for t, lineno in self.return_annotation:
            self.check_return_types(t,lineno)

    def _collect_function_defs(self, root):
        for node in ast.walk(root):
            if isinstance(node, ast.FunctionDef):
                self._functions.append(node.name)
            elif isinstance(node, ast.Import) or isinstance(node, ast.ImportFrom):
                for n in node.names:
                    if n.asname:
                        self._functions.append(n.asname)
                    else:
                        self._functions.append(n.name.split('.')[-1])

    def check(self, ast_tree):
        self._reset()
        # pass 1 - collect function def and imports
        self._collect_function_defs(ast_tree)
        self.visit(ast_tree)
        self._final_checks()
        if self._is_success is False:
            return sorted(self._violations, key=lambda x: int(x.split(':')[0].split()[1]))
        else:
            return None

    def dump_violations(self):
        import pprint
        pp = pprint.PrettyPrinter(indent=4)
        pp.pprint(self._violations)


================================================
FILE: src/contracting/compilation/parser.py
================================================
import ast


def methods_for_contract(contract_code: str):
    tree = ast.parse(contract_code)

    function_defs = [n for n in ast.walk(tree) if isinstance(n, ast.FunctionDef)]

    funcs = []
    for definition in function_defs:
        func_name = definition.name

        if func_name.startswith('__'):
            continue

        kwargs = []

        for arg in definition.args.args:
            try:
                a = arg.annotation.id
            except AttributeError:
                a = arg.annotation.value.id + '.' + arg.annotation.attr

            kwargs.append({
                'name': arg.arg,
                'type': a
            })

        funcs.append({'name': func_name, 'arguments': kwargs})

    return funcs


def variables_for_contract(contract_code: str):
    tree = ast.parse(contract_code)

    assigns = []

    for node in ast.walk(tree):
        if isinstance(node, ast.Assign):
            assigns.append(node)

        if isinstance(node, ast.FunctionDef):
            break

    variables = []
    hashes = []

    for assign in assigns:
        if type(assign.value) == ast.Call:
            if assign.value.func.id == 'Variable':
                variables.append(assign.targets[0].id.lstrip('__'))
            elif assign.value.func.id == 'Hash':
                hashes.append(assign.targets[0].id.lstrip('__'))

    return {
        'variables': variables,
        'hashes': hashes
    }


================================================
FILE: src/contracting/compilation/whitelists.py
================================================
import ast, builtins

ALLOWED_BUILTINS = {'Exception', 'False', 'None', 'True', 'abs', 'all', 'any', 'ascii', 'bin', 'bool', 'bytearray',
                    'bytes', 'chr', 'dict', 'divmod', 'filter', 'format', 'frozenset', 'hex', 'int', 'isinstance',
                    'issubclass', 'import', 'len', 'list', 'map', 'max', 'min', 'oct', 'ord', 'pow', 'range', 'reversed',
                    'round', 'set', 'sorted', 'str', 'sum', 'tuple', 'zip'}

ILLEGAL_BUILTINS = set(dir(builtins)) - ALLOWED_BUILTINS

ALLOWED_AST_TYPES = {ast.Module, ast.Eq, ast.Call, ast.Dict, ast.Attribute, ast.Pow, ast.Index, ast.Not, ast.alias,
                     ast.If, ast.FunctionDef, ast.Global, ast.GtE, ast.LtE, ast.Load, ast.arg, ast.Add, ast.Import,
                     ast.ImportFrom, ast.Name, ast.Num, ast.BinOp, ast.Store, ast.Assert, ast.Assign, ast.AugAssign,
                     ast.Subscript, ast.Compare, ast.Return, ast.NameConstant, ast.Expr, ast.keyword, ast.Sub,
                     ast.arguments, ast.List, ast.Set, ast.Str, ast.UnaryOp, ast.Pass, ast.Tuple, ast.Div, ast.In,
                     ast.NotIn, ast.Gt, ast.Lt, ast.Starred, ast.Mod, ast.NotEq, ast.For, ast.While, ast.ListComp,
                     ast.comprehension, ast.Slice, ast.USub, ast.BoolOp, ast.And, ast.Or, ast.Mult, ast.IsNot, ast.Is, ast.Constant}

ILLEGAL_AST_TYPES = {
    ast.AsyncFor,
    ast.AsyncFunctionDef,
    ast.AsyncWith,
    ast.Await,
    ast.ClassDef,
    ast.Ellipsis,
    ast.GeneratorExp,
    ast.Global,
    ast.ImportFrom,
    ast.Interactive,
    ast.Lambda,
    ast.MatMult,
    ast.Nonlocal,
    ast.Suite,
    ast.Try,
    ast.With,
    ast.Yield,
    ast.YieldFrom,
}

ALLOWED_ANNOTATION_TYPES = {'dict', 'list', 'str', 'int', 'float', 'bool', 'datetime.timedelta', 'datetime.datetime', 'Any'}

VIOLATION_TRIGGERS = [
    "S1- Illegal contracting syntax type used",
    "S2- Illicit use of '_' before variable",
    "S3- Illicit use of Nested imports",
    "S4- ImportFrom compilation nodes not yet supported",
    "S5- Contract not found in lib",
    "S6- Illicit use of classes",
    "S7- Illicit use of Async functions",
    "S8- Invalid decorator used",
    "S9- Multiple use of constructors detected",
    "S10- Illicit use of multiple decorators",
    "S11- Illicit keyword overloading for ORM assignments",
    "S12- Multiple targets to ORM definition detected",
    "S13- No valid contracting decorator found",
    "S14- Illegal use of a builtin",
    "S15- Reuse of ORM name definition in a function definition argument name",
    "S16- Illegal argument annotation used",
    "S17- No valid argument annotation found",
    "S18- Illegal use of return annotation",
    "S19- Illegal use of a nested function definition."
]


================================================
FILE: src/contracting/constants.py
================================================
from pathlib import Path

RECURSION_LIMIT = 1024

DELIMITER = ':'
INDEX_SEPARATOR = '.'
HDF5_GROUP_SEPARATOR = '/'

SUBMISSION_CONTRACT_NAME = 'submission'
PRIVATE_METHOD_PREFIX = '__'
EXPORT_DECORATOR_STRING = 'export'
INIT_DECORATOR_STRING = 'construct'
INIT_FUNC_NAME = '__{}'.format(PRIVATE_METHOD_PREFIX)
VALID_DECORATORS = {EXPORT_DECORATOR_STRING, INIT_DECORATOR_STRING}

ORM_CLASS_NAMES = {'Variable', 'Hash', 'ForeignVariable', 'ForeignHash', 'LogEvent'}

MAX_HASH_DIMENSIONS = 16
MAX_KEY_SIZE = 1024

READ_COST_PER_BYTE = 1
WRITE_COST_PER_BYTE = 25

STAMPS_PER_TAU = 20

BLOCK_NUM_DEFAULT = -1
FILENAME_LEN_MAX = 255

DEFAULT_STAMPS = 1000000

STORAGE_HOME = Path().home().joinpath(".cometbft/xian")


================================================
FILE: src/contracting/contracts/__init__.py
================================================


================================================
FILE: src/contracting/contracts/proxythis.py
================================================
@export
def proxythis(con: str):
    return importlib.import_module(con).getthis()

@export
def nestedproxythis(con: str):
    return importlib.import_module(con).nested_exported()

@export
def noproxy():
    return ctx.this, ctx.caller

================================================
FILE: src/contracting/contracts/submission.s.py
================================================
@__export('submission')
def submit_contract(name: str, code: str, owner: Any=None, constructor_args: dict={}):
    if ctx.caller != 'sys':
        assert name.startswith('con_'), 'Contract must start with con_!'

    assert ctx.caller == ctx.signer, 'Contract cannot be called from another contract!'
    assert len(name) <= 64, 'Contract name length exceeds 64 characters!'
    assert name.islower(), 'Contract name must be lowercase!'

    __Contract().submit(
        name=name,
        code=code,
        owner=owner,
        constructor_args=constructor_args,
        developer=ctx.caller
    )


@__export('submission')
def change_developer(contract: str, new_developer: str):
    d = __Contract()._driver.get_var(contract=contract, variable='__developer__')
    assert ctx.caller == d, 'Sender is not current developer!'

    __Contract()._driver.set_var(
        contract=contract,
        variable='__developer__',
        value=new_developer
    )


================================================
FILE: src/contracting/contracts/thistest2.py
================================================
@export
def exported():
    return ctx.this, ctx.caller

@export
def getthis():
    return ctx.this, ctx.caller

@export
def nested_exported():
    return exported()


================================================
FILE: src/contracting/execution/__init__.py
================================================


================================================
FILE: src/contracting/execution/executor.py
================================================
from contracting.execution import runtime
from contracting.storage.driver import Driver
from contracting.execution.module import install_database_loader, uninstall_builtins, enable_restricted_imports, disable_restricted_imports
from contracting.stdlib.bridge.decimal import ContractingDecimal, CONTEXT
from contracting.stdlib.bridge.random import Seeded
from contracting import constants
from copy import deepcopy

import importlib
import decimal


class Executor:
    def __init__(self,
                 production=False,
                 driver=None,
                 metering=True,
                 currency_contract='currency',
                 balances_hash='balances',
                 bypass_privates=False,
                 bypass_balance_amount=False,
                 bypass_cache=False):

        self.metering = metering
        self.driver = driver

        if not self.driver:
            self.driver = Driver(bypass_cache=bypass_cache)
        self.production = production

        self.currency_contract = currency_contract
        self.balances_hash = balances_hash

        self.bypass_privates = bypass_privates
        self.bypass_balance_amount = bypass_balance_amount  # For Stamp Estimation

        runtime.rt.env.update({'__Driver': self.driver})

    def wipe_modules(self):
        uninstall_builtins()
        install_database_loader()

    def execute(self, sender, contract_name, function_name, kwargs,
                environment={},
                auto_commit=False,
                driver=None,
                stamps=constants.DEFAULT_STAMPS,
                stamp_cost=constants.STAMPS_PER_TAU,
                metering=None) -> dict:

        current_driver_pending_writes = deepcopy(self.driver.pending_writes)
        self.driver.clear_transaction_writes()
        self.driver.clear_events()

        if not self.bypass_privates:
            assert not function_name.startswith(constants.PRIVATE_METHOD_PREFIX), 'Private method not callable.'

        if metering is None:
            metering = self.metering

        runtime.rt.env.update({'__Driver': self.driver})

        if driver:
            runtime.rt.env.update({'__Driver': driver})
        else:
            driver = runtime.rt.env.get('__Driver')

        install_database_loader(driver=driver)

        balances_key = None

        try:
            if metering:
                balances_key = (f'{self.currency_contract}'
                                f'{constants.INDEX_SEPARATOR}'
                                f'{self.balances_hash}'
                                f'{constants.DELIMITER}'
                                f'{sender}')

                if self.bypass_balance_amount:
                    balance = 9999999

                else:
                    balance = driver.get(balances_key)

                    if type(balance) == dict:
                        balance = ContractingDecimal(balance.get('__fixed__'))

                    if balance is None:
                        balance = 0

                assert balance * stamp_cost >= stamps, (f'Sender does not have enough stamps for the transaction. '
                                                        f'Balance at key {balances_key} is {balance}')

            runtime.rt.env.update(environment)
            status_code = 0

            # Multiply stamps by 1000 because we divide by it later
            # runtime.rt.set_up(stmps=stamps * 1000, meter=metering)

            runtime.rt.context._base_state = {
                'signer': sender,
                'caller': sender,
                'this': contract_name,
                'entry': (contract_name, function_name),
                'owner': driver.get_owner(contract_name),
                'submission_name': None
            }

            if runtime.rt.context.owner is not None and runtime.rt.context.owner != runtime.rt.context.caller:
                raise Exception(f'Caller {runtime.rt.context.caller} is not the owner {runtime.rt.context.owner}!')

            decimal.setcontext(CONTEXT)

            module = importlib.import_module(contract_name)
            func = getattr(module, function_name)

            # Add the contract name to the context on a submission call
            if contract_name == constants.SUBMISSION_CONTRACT_NAME:
                runtime.rt.context._base_state['submission_name'] = kwargs.get('name')

            for k, v in kwargs.items():
                if type(v) == float:
                    kwargs[k] = ContractingDecimal(str(v))

            enable_restricted_imports()
            runtime.rt.set_up(stmps=stamps * 1000, meter=metering)
            result = func(**kwargs)
            transaction_writes = deepcopy(driver.transaction_writes)
            events = deepcopy(driver.log_events)
            runtime.rt.tracer.stop()
            disable_restricted_imports()

            if auto_commit:
                driver.commit()

        except Exception as e:
            result = e
            status_code = 1
            # Revert the writes if the transaction fails
            driver.pending_writes = current_driver_pending_writes
            transaction_writes = {}
            events = []
            if auto_commit:
                driver.flush_cache()

        finally:
            driver.clear_events()
            driver.clear_transaction_writes()
            runtime.rt.tracer.stop()

        #runtime.rt.tracer.stop()

        # Deduct the stamps if that is enabled
        stamps_used = runtime.rt.tracer.get_stamp_used()

        stamps_used = stamps_used // 1000
        stamps_used += 5

        if stamps_used > stamps:
            stamps_used = stamps

        if metering:
            assert balances_key is not None, 'Balance key was not set properly. Cannot deduct stamps.'

            to_deduct = stamps_used
            to_deduct /= stamp_cost
            to_deduct = ContractingDecimal(to_deduct)

            balance = driver.get(balances_key)
            if balance is None:
                balance = 0

            balance = max(balance - to_deduct, 0)

            driver.set(balances_key, balance)
            transaction_writes[balances_key] = balance

            if auto_commit:
                driver.commit()

        Seeded.s = False
        runtime.rt.clean_up()
        runtime.rt.env.update({'__Driver': driver})

        output = {
            'status_code': status_code,
            'result': result,
            'stamps_used': stamps_used,
            'writes': transaction_writes,
            'reads': driver.pending_reads,
            'events': events
        }

        disable_restricted_imports()
        return output


================================================
FILE: src/contracting/execution/module.py
================================================
from importlib.abc import Loader
from importlib import invalidate_caches, __import__
from importlib.machinery import ModuleSpec
from contracting.storage.driver import Driver
from contracting.stdlib import env
from contracting.execution.runtime import rt

import marshal
import builtins
import sys
import importlib.util

# This function overrides the __import__ function, which is the builtin function that is called whenever Python runs
# an 'import' statement. If the globals dictionary contains {'__contract__': True}, then this function will make sure
# that the module being imported comes from the database and not from builtins or site packages.
#
# For all exec statements, we add the {'__contract__': True} _key to the globals to protect against unwanted imports.
#
# Note: anything installed with pip or in site-packages will also not work, so contract package names *must* be unique.


def is_valid_import(name):
    spec = importlib.util.find_spec(name)
    if not isinstance(spec.loader, DatabaseLoader):
        raise ImportError("module {} cannot be imported in a smart contract.".format(name))


def restricted_import(name, globals=None, locals=None, fromlist=(), level=0):
    if globals is not None and globals.get('__contract__') is True:
        spec = importlib.util.find_spec(name)
        if spec is None or not isinstance(spec.loader, DatabaseLoader):
            raise ImportError("module {} cannot be imported in a smart contract.".format(name))

    return __import__(name, globals, locals, fromlist, level)


def enable_restricted_imports():
    builtins.__import__ = restricted_import
#    builtins.float = ContractingDecimal


def disable_restricted_imports():
    builtins.__import__ = __import__


def uninstall_builtins():
    sys.meta_path.clear()
    sys.path_hooks.clear()
    sys.path.clear()
    sys.path_importer_cache.clear()
    invalidate_caches()


def install_database_loader(driver=Driver()):
    DatabaseFinder.driver = driver
    if DatabaseFinder not in sys.meta_path:
        sys.meta_path.insert(0, DatabaseFinder)


def uninstall_database_loader():
    sys.meta_path = list(set(sys.meta_path))
    if DatabaseFinder in sys.meta_path:
        sys.meta_path.remove(DatabaseFinder)


def install_system_contracts(directory=''):
    pass


'''
    Is this where interaction with the database occurs with the interface of code strings, etc?
    IE: pushing a contract does sanity checks here?
'''


class DatabaseFinder:
    driver = Driver()

    def find_spec(self, fullname, path=None, target=None):
        if DatabaseFinder.driver.get_contract(self) is None:
            return None
        return ModuleSpec(self, DatabaseLoader(DatabaseFinder.driver))


MODULE_CACHE = {}


class DatabaseLoader(Loader):
    def __init__(self, d=Driver()):
        self.d = d

    def create_module(self, spec):
        return None

    def exec_module(self, module):
        # fetch the individual contract
        code = self.d.get_compiled(module.__name__)
        if code is None:
            raise ImportError("Module {} not found".format(module.__name__))

        if type(code) != bytes:
            code = bytes.fromhex(code)

        code = marshal.loads(code)

        if code is None:
            raise ImportError("Module {} not found".format(module.__name__))

        scope = env.gather()
        scope.update(rt.env)

        scope.update({'__contract__': True})

        # execute the module with the std env and update the module to pass forward
        exec(code, scope)

        # Update the module's attributes with the new scope
        vars(module).update(scope)
        del vars(module)['__builtins__']

        rt.loaded_modules.append(module.__name__)

    def module_repr(self, module):
        return '<module {!r} (smart contract)>'.format(module.__name__)


================================================
FILE: src/contracting/execution/runtime.py
================================================
from contracting import constants
from contracting.execution.tracer import Tracer

import contracting
import sys
import os
import math


class Context:
    def __init__(self, base_state, maxlen=constants.RECURSION_LIMIT):
        self._state = []
        self._depth = []
        self._base_state = base_state
        self._maxlen = maxlen

    def _context_changed(self, contract):
        if self._get_state()['this'] == contract:
            return False
        return True

    def _get_state(self):
        if len(self._state) == 0:
            return self._base_state
        return self._state[-1]

    def _add_state(self, state: dict):
        if self._context_changed(state['this']) and len(self._state) < self._maxlen:
            self._state.append(state)
            self._depth.append(1)

    def _ins_state(self):
        if len(self._depth) > 0:
            self._depth[-1] += 1

    def _pop_state(self):
        if len(self._state) > 0: #len(self._state) should equal len(self._depth)
            self._depth[-1] -= 1
            if self._depth[-1] == 0:
                self._state.pop(-1)
                self._depth.pop(-1)

    def _reset(self):
        self._state = []
        self._depth = []

    @property
    def this(self):
        return self._get_state()['this']

    @property
    def caller(self):
        return self._get_state()['caller']

    @property
    def signer(self):
        return self._get_state()['signer']

    @property
    def owner(self):
        return self._get_state()['owner']

    @property
    def entry(self):
        return self._get_state()['entry']

    @property
    def submission_name(self):
        return self._get_state()['submission_name']

_context = Context({
        'this': None,
        'caller': None,
        'owner': None,
        'signer': None,
        'entry': None,
        'submission_name': None
    })

WRITE_MAX = 1024 * 128


class Runtime:
    cu_path = contracting.__path__[0]
    cu_path = os.path.join(cu_path, 'execution', 'metering', 'cu_costs.const')

    os.environ['CU_COST_FNAME'] = cu_path

    loaded_modules = []

    env = {}
    stamps = 0

    writes = 0

    tracer = Tracer()

    signer = None

    context = _context

    @classmethod
    def set_up(cls, stmps, meter):
        if meter:
            cls.stamps = stmps
            cls.tracer.set_stamp(stmps)
            cls.tracer.start()

        cls.context._reset()

    @classmethod
    def clean_up(cls):
        cls.tracer.stop()
        cls.tracer.reset()
        cls.stamps = 0
        cls.writes = 0

        cls.signer = None

        for mod in cls.loaded_modules:
            if sys.modules.get(mod) is not None:
                del sys.modules[mod]

        cls.loaded_modules = []
        cls.env = {}

    @classmethod
    def deduct_read(cls, key, value):
        if cls.tracer.is_started():
            cost = len(key) + len(value)
            cost *= constants.READ_COST_PER_BYTE
            cls.tracer.add_cost(cost)

    @classmethod
    def deduct_write(cls, key, value):
        if key is not None and cls.tracer.is_started():
            cost = len(key) + len(value)
            cls.writes += cost
            assert cls.writes < WRITE_MAX, 'You have exceeded the maximum write capacity per transaction!'

            stamp_cost = cost * constants.WRITE_COST_PER_BYTE
            cls.tracer.add_cost(stamp_cost)


rt = Runtime()


================================================
FILE: src/contracting/execution/tracer.py
================================================
import sys
import dis
import threading
import psutil
import os

# Define the opcode costs
cu_costs = {
    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,
    13: 4, 14: 4, 15: 4, 16: 4, 17: 4, 18: 4, 19: 4, 20: 2, 21: 4, 22: 8, 23: 6, 24: 6,
    25: 4, 26: 4, 27: 4, 28: 4, 29: 4, 30: 4, 31: 6, 32: 6, 33: 6, 34: 2, 35: 6, 36: 6,
    37: 6, 38: 2, 39: 4, 40: 4, 41: 4, 42: 4, 43: 4, 44: 2, 45: 2, 46: 2, 47: 4, 48: 2,
    49: 6, 50: 6, 51: 6, 52: 6, 53: 4, 54: 6, 55: 4, 56: 4, 57: 4, 58: 4, 59: 4, 60: 4,
    61: 4, 62: 4, 63: 4, 64: 6, 65: 6, 66: 8, 67: 8, 68: 8, 69: 12, 70: 2, 71: 1610, 72: 8,
    73: 6, 74: 4, 75: 6, 76: 6, 77: 4, 78: 4, 79: 4, 80: 6, 81: 6, 82: 4, 83: 2, 84: 126,
    85: 1000, 86: 4, 87: 8, 88: 6, 89: 4, 90: 2, 91: 2, 92: 2, 93: 512, 94: 8, 95: 6, 96: 6,
    97: 4, 98: 4, 99: 2, 100: 2, 101: 2, 102: 2, 103: 6, 104: 8, 105: 8, 106: 4, 107: 4,
    108: 38, 109: 126, 110: 4, 111: 4, 112: 4, 113: 6, 114: 4, 115: 4, 116: 4, 117: 4, 118: 6,
    119: 6, 120: 4, 121: 4, 122: 4, 123: 6, 124: 32, 125: 2, 126: 2, 127: 4, 128: 4, 129: 4,
    130: 6, 131: 10, 132: 8, 133: 12, 134: 4, 135: 4, 136: 8, 137: 2, 138: 2, 139: 2, 140: 4,
    141: 6, 142: 12, 143: 6, 144: 2, 145: 8, 146: 8, 147: 6, 148: 2, 149: 6, 150: 6, 151: 6,
    152: 6, 153: 4, 154: 4, 155: 4, 156: 6, 157: 4, 158: 4, 159: 4, 160: 4, 161: 2, 162: 4,
    163: 6, 164: 6, 165: 6, 166: 6, 167: 2, 168: 4, 169: 4, 170: 2, 171: 8, 172: 2, 173: 4,
    174: 4, 175: 4, 176: 4, 177: 4, 178: 4, 179: 4, 180: 4, 255: 8
}

# Define maximum stamps
MAX_STAMPS = 6500000

class Tracer:
    def __init__(self):
        self.cost = 0
        self.stamp_supplied = 0
        self.last_frame_mem_usage = 0
        self.total_mem_usage = 0
        self.started = False
        self.call_count = 0
        self.max_call_count = 800000
        self.instruction_cache = {}
        self.lock = threading.Lock()

    def start(self):
        sys.settrace(self.trace_func)
        self.cost = 0
        self.call_count = 0
        self.started = True

    def stop(self):
        if self.started:
            sys.settrace(None)
            self.started = False

    def reset(self):
        self.stop()
        self.cost = 0
        self.stamp_supplied = 0
        self.last_frame_mem_usage = 0
        self.total_mem_usage = 0
        self.call_count = 0

    def set_stamp(self, stamp):
        self.stamp_supplied = stamp

    def add_cost(self, new_cost):
        self.cost += new_cost
        if self.cost > self.stamp_supplied or self.cost > MAX_STAMPS:
            self.stop()
            raise AssertionError("The cost has exceeded the stamp supplied!")

    def get_stamp_used(self):
        return self.cost

    def get_last_frame_mem_usage(self):
        return self.last_frame_mem_usage

    def get_total_mem_usage(self):
        return self.total_mem_usage

    def is_started(self):
        return self.started

    def get_memory_usage(self):
        process = psutil.Process(os.getpid())
        mem_info = process.memory_info()
        # Return the RSS (Resident Set Size)
        return mem_info.rss

    def trace_func(self, frame, event, arg):
        if event == 'line':
            self.call_count += 1
            if self.call_count > self.max_call_count:
                self.stop()
                raise AssertionError("Call count exceeded threshold! Infinite Loop?")

            # Check if the function matches the target module and function names
            code = frame.f_code
            current_function_name = code.co_name
            globals_dict = frame.f_globals
            module_name = globals_dict.get('__name__', '')

            # Only trace code within contracts (if '__contract__' in globals)
            if '__contract__' not in globals_dict:
                return

            # Get the opcode at the current instruction
            lasti = frame.f_lasti
            opcode = self.get_opcode(code, lasti)

            # Update memory usage
            if self.last_frame_mem_usage == 0:
                self.last_frame_mem_usage = self.get_memory_usage()

            new_memory_usage = self.get_memory_usage()
            if new_memory_usage > self.last_frame_mem_usage:
                self.total_mem_usage += (new_memory_usage - self.last_frame_mem_usage)
            self.last_frame_mem_usage = new_memory_usage

            # Check for memory usage limit (set an arbitrary limit, e.g., 500MB)
            if self.total_mem_usage > 500 * 1024 * 1024:
                self.stop()
                raise AssertionError(f"Transaction exceeded memory usage! Total usage: {self.total_mem_usage} bytes")

            # Add cost based on opcode
            opcode_cost = cu_costs.get(opcode, 1)  # Default cost if opcode not found
            self.cost += opcode_cost

            if self.cost > self.stamp_supplied or self.cost > MAX_STAMPS:
                self.stop()
                raise AssertionError("The cost has exceeded the stamp supplied!")

        return self.trace_func

    def get_opcode(self, code, offset):
        # Cache the instruction map per code object
        with self.lock:
            instruction_map = self.instruction_cache.get(code)
            if instruction_map is None:
                instruction_map = {}
                for instr in dis.get_instructions(code):
                    instruction_map[instr.offset] = instr.opcode
                self.instruction_cache[code] = instruction_map
            opcode = instruction_map.get(offset, None)
            if opcode is None:
                # Instruction not found; default to 0
                opcode = 0
            return opcode


================================================
FILE: src/contracting/stdlib/__init__.py
================================================


================================================
FILE: src/contracting/stdlib/bridge/__init__.py
================================================


================================================
FILE: src/contracting/stdlib/bridge/access.py
================================================
from contracting.execution.runtime import rt
from contextlib import ContextDecorator
from contracting.storage.driver import Driver
from typing import Any


class __export(ContextDecorator):
    def __init__(self, contract):
        self.contract = contract

    def __enter__(self, *args, **kwargs):
        driver = rt.env.get('__Driver') or Driver()

        if rt.context._context_changed(self.contract):
            current_state = rt.context._get_state()

            state = {
                'owner': driver.get_owner(self.contract),
                'caller': current_state['this'],
                'signer': current_state['signer'],
                'this': self.contract,
                'entry': current_state['entry'],
                'submission_name': current_state['submission_name']
            }

            rt.context._add_state(state)

            if state['owner'] is not None and state['owner'] != state['caller']:
                raise Exception('Caller is not the owner!')
        else:
            rt.context._ins_state()

    def __exit__(self, *args, **kwargs):
        rt.context._pop_state()


exports = {
    '__export': __export,
    'ctx': rt.context,
    'rt': rt,
    'Any': Any
}


================================================
FILE: src/contracting/stdlib/bridge/crypto.py
================================================
from types import ModuleType
import nacl


def verify(vk: str, msg: str, signature: str):
    vk = bytes.fromhex(vk)
    msg = msg.encode()
    signature = bytes.fromhex(signature)

    vk = nacl.signing.VerifyKey(vk)
    try:
        vk.verify(msg, signature)
    except:
        return False
    return True


def key_is_valid(key: str):
    """ Check if the given address is valid.
     Can be used with public and private keys """
    if not len(key) == 64:
        return False
    try:
        int(key, 16)
    except:
        return False
    return True


crypto_module = ModuleType('crypto')
crypto_module.verify = verify
crypto_module.key_is_valid = key_is_valid

exports = {
    'crypto': crypto_module
}


================================================
FILE: src/contracting/stdlib/bridge/decimal.py
================================================
from decimal import Decimal, Context, ROUND_FLOOR
import decimal

# Define precision constants
MAX_UPPER_PRECISION = 30
MAX_LOWER_PRECISION = 30

# Set the decimal context for precision and rounding
CONTEXT = Context(
    prec=MAX_UPPER_PRECISION + MAX_LOWER_PRECISION,
    rounding=ROUND_FLOOR,
    Emin=-100,
    Emax=100
)
decimal.setcontext(CONTEXT)

# Create min and max decimal strings for precision boundaries
def make_min_decimal_str(prec):
    return '0.' + '0' * (prec - 1) + '1'

def make_max_decimal_str(prec):
    return '1' + '0' * (prec - 1)

# Convert scientific notation to non-exponential format if needed
def neg_sci_not(s: str):
    try:
        base, exp = s.split('e-')
        if float(base) > 9:
            return s

        base = base.replace('.', '')
        numbers = ('0' * (int(exp) - 1)) + base

        if int(exp) > 0:
            numbers = '0.' + numbers

        return numbers
    except ValueError:
        return s

# Define maximum and minimum decimal constants
MAX_DECIMAL = Decimal(make_max_decimal_str(MAX_UPPER_PRECISION))
MIN_DECIMAL = Decimal(make_min_decimal_str(MAX_LOWER_PRECISION))

# Ensure the value is within bounds and quantized
def fix_precision(x: Decimal):
    if x > MAX_DECIMAL:
        return MAX_DECIMAL
    return x.quantize(MIN_DECIMAL, rounding=ROUND_FLOOR).normalize()

# Main ContractingDecimal class
class ContractingDecimal:
    def _get_other(self, other):
        if isinstance(other, ContractingDecimal):
            return other._d
        elif isinstance(other, (float, int)):
            return fix_precision(Decimal(neg_sci_not(str(other))))
        return other

    def __init__(self, a):
        if isinstance(a, (float, int)):
            self._d = Decimal(neg_sci_not(str(a)))
        elif isinstance(a, str):
            self._d = Decimal(neg_sci_not(a))
        elif isinstance(a, Decimal):
            self._d = a
        else:
            self._d = Decimal(a)

        # Clamp and quantize during initialization
        self._d = fix_precision(self._d)

    def __bool__(self):
        return self._d > 0

    def __eq__(self, other):
        return self._d == self._get_other(other)

    def __lt__(self, other):
        return self._d < self._get_other(other)

    def __le__(self, other):
        return self._d <= self._get_other(other)

    def __gt__(self, other):
        return self._d > self._get_other(other)

    def __ge__(self, other):
        return self._d >= self._get_other(other)

    def __str__(self):
        return self._d.to_eng_string()

    def __repr__(self):
        return self._d.to_eng_string()

    def __neg__(self):
        return ContractingDecimal(-self._d)

    def __pos__(self):
        return self

    def __abs__(self):
        return ContractingDecimal(abs(self._d))

    def __add__(self, other):
        return ContractingDecimal(fix_precision(self._d + self._get_other(other)))

    def __radd__(self, other):
        return ContractingDecimal(fix_precision(self._get_other(other) + self._d))

    def __sub__(self, other):
        return ContractingDecimal(fix_precision(self._d - self._get_other(other)))

    def __rsub__(self, other):
        return ContractingDecimal(fix_precision(self._get_other(other) - self._d))

    def __mul__(self, other):
        return ContractingDecimal(fix_precision(self._d * self._get_other(other)))

    def __rmul__(self, other):
        return ContractingDecimal(fix_precision(self._get_other(other) * self._d))

    def __truediv__(self, other):
        return ContractingDecimal(fix_precision(self._d / self._get_other(other)))

    def __rtruediv__(self, other):
        return ContractingDecimal(fix_precision(self._get_other(other) / self._d))

    def __mod__(self, other):
        return ContractingDecimal(fix_precision(self._d % self._get_other(other)))

    def __rmod__(self, other):
        return ContractingDecimal(fix_precision(self._get_other(other) % self._d))

    def __floordiv__(self, other):
        return ContractingDecimal(fix_precision(self._d // self._get_other(other)))

    def __rfloordiv__(self, other):
        return ContractingDecimal(fix_precision(self._get_other(other) // self._d))

    def __pow__(self, other):
        return ContractingDecimal(fix_precision(self._d ** self._get_other(other)))

    def __rpow__(self, other):
        return ContractingDecimal(fix_precision(self._get_other(other) ** self._d))

    def __int__(self):
        return int(self._d)

    def __float__(self):
        return float(self._d)

    def __round__(self, n=None):
        return round(self._d, n)

# Export ContractingDecimal for external use
exports = {
    'decimal': ContractingDecimal
}


================================================
FILE: src/contracting/stdlib/bridge/hashing.py
================================================
import hashlib

from types import ModuleType

'''
Bytes can't be stored in JSON so we use hex-strings converted into bytes and back.
'''


def sha3(hex_str: str):
    try:
        byte_str = bytes.fromhex(hex_str)
    except ValueError:
        byte_str = hex_str.encode()

    hasher = hashlib.sha3_256()
    hasher.update(byte_str)

    hashed_bytes = hasher.digest()

    return hashed_bytes.hex()


def sha256(hex_str: str):
    try:
        byte_str = bytes.fromhex(hex_str)
    except ValueError:
        byte_str = hex_str.encode()

    hasher = hashlib.sha256()
    hasher.update(byte_str)

    hashed_bytes = hasher.digest()

    return hashed_bytes.hex()


hashlib_module = ModuleType('hashlib')
hashlib_module.sha3 = sha3
hashlib_module.sha256 = sha256

exports = {
    'hashlib': hashlib_module,
}


================================================
FILE: src/contracting/stdlib/bridge/imports.py
================================================
from types import FunctionType, ModuleType
from contracting.constants import PRIVATE_METHOD_PREFIX
from contracting.storage.orm import Datum
from contracting.storage.driver import Driver, OWNER_KEY
from contracting.execution.runtime import rt

import importlib
import sys


def extract_closure(fn):
    closure = fn.__closure__[0]
    return closure.cell_contents


class Func:
    def __init__(self, name, args=(), private=False):
        self.name = name

        if private:
            self.name = PRIVATE_METHOD_PREFIX + self.name

        self.args = args

    def is_of(self, f: FunctionType):

        if f.__closure__ is not None:
            f = extract_closure(f)

        num_args = f.__code__.co_argcount

        if f.__code__.co_name == self.name and f.__code__.co_varnames[:num_args] == self.args:
            return True

        return False


class Var:
    def __init__(self, name, t):
        self.name = PRIVATE_METHOD_PREFIX + name
        assert issubclass(t, Datum), 'Cannot enforce a variable that is not a Variable, Hash, or Foreign type!'
        self.type = t

    def is_of(self, v):
        if isinstance(v, self.type):
            return True
        return False


def import_module(name):
    assert not name.isdigit() and all(c.isalnum() or c == '_' for c in name), 'Invalid contract name!'
    assert name.islower(), 'Name must be lowercase!'

    _driver = rt.env.get('__Driver') or Driver()

    if name in set(list(sys.stdlib_module_names) + list(sys.builtin_module_names)):
        raise ImportError

    if name.startswith('_'):
        raise ImportError

    if _driver.get_contract(name) is None:
        raise ImportError

    return importlib.import_module(name, package=None)


def enforce_interface(m: ModuleType, interface: list):
    implemented = vars(m)

    for i in interface:
        attribute = implemented.get(i.name)
        if attribute is None:
            return False

        # Branch for data types
        if isinstance(attribute, Datum):
            if not i.is_of(attribute):
                return False

        if isinstance(attribute, FunctionType):
            if not i.is_of(attribute):
                return False

    return True


def owner_of(m: ModuleType):
    _driver = rt.env.get('__Driver') or Driver()
    owner = _driver.get_var(m.__name__, OWNER_KEY)
    return owner


imports_module = ModuleType('importlib')
imports_module.import_module = import_module
imports_module.enforce_interface = enforce_interface
imports_module.Func = Func
imports_module.Var = Var
imports_module.owner_of = owner_of

exports = {
    'importlib': imports_module,
}


================================================
FILE: src/contracting/stdlib/bridge/orm.py
================================================
from contracting.storage.orm import Variable, Hash, ForeignVariable, ForeignHash, LogEvent
from contracting.storage.contract import Contract
from contracting.execution.runtime import rt


class V(Variable):
    def __init__(self, *args, **kwargs):
        if rt.env.get('__Driver') is not None:
            kwargs['driver'] = rt.env.get('__Driver')
        super().__init__(*args, **kwargs)


class H(Hash):
    def __init__(self, *args, **kwargs):
        if rt.env.get('__Driver') is not None:
            kwargs['driver'] = rt.env.get('__Driver')
        super().__init__(*args, **kwargs)


class FV(ForeignVariable):
    def __init__(self, *args, **kwargs):
        if rt.env.get('__Driver') is not None:
            kwargs['driver'] = rt.env.get('__Driver')
        super().__init__(*args, **kwargs)


class FH(ForeignHash):
    def __init__(self, *args, **kwargs):
        if rt.env.get('__Driver') is not None:
            kwargs['driver'] = rt.env.get('__Driver')
        super().__init__(*args, **kwargs)


class C(Contract):
    def __init__(self, *args, **kwargs):
        if rt.env.get('__Driver') is not None:
            kwargs['driver'] = rt.env.get('__Driver')
        super().__init__(*args, **kwargs)
        

class LE(LogEvent):
    def __init__(self, *args, **kwargs):
        if rt.env.get('__Driver') is not None:
            kwargs['driver'] = rt.env.get('__Driver')
        super().__init__(*args, **kwargs)


# Define the locals that will be available for smart contracts at runtime
exports = {
    'Variable': V,
    'Hash': H,
    'ForeignVariable': FV,
    'ForeignHash': FH,
    'LogEvent': LE,
    '__Contract': C
}


================================================
FILE: src/contracting/stdlib/bridge/random.py
================================================
"""
    This module wraps and exposes the Python stdlib random functions that can be made deterministic with a random seed
    and return fixed point precision where possible. This allows some psuedorandom behavior when it is nice to have, but
    with the caveat that it's based on environmental constants such as the last block hash and public information such
    as the sender's address to seed the random state so it's not *really* random.

    It's most likely 'random enough' for most cases, but people can always theoretically reproduce the seed and try to
    front-run a smart contract by testing the seeded randoms for a preferable outcome and submitting a transaction
    before the next block is minted. While this is extremely unlikely and hard to pull off, it's a valid hole in the
    security and needs to be accepted as a flaw when using random numbers on a reproducible transaction log such as a
    blockchain.
"""

import random

from types import ModuleType
from contracting.execution.runtime import rt


class Seeded:
    s = False


def seed(aux_salt=None):
    block_height = '0'
    if rt.env.get('block_num') is not None:
        block_height = str(rt.env.get('block_num'))

    block_hash = rt.env.get('block_hash') or '0'
    __input_hash = rt.env.get('__input_hash') or '0'

    # Auxiliary salt is used to create completely unique random seeds based on some other properties (optional)
    auxiliary_salt = ''
    if aux_salt is not None and rt.env.get(aux_salt):
        auxiliary_salt = str(rt.env.get(aux_salt))
    else:
        if rt.env.get("AUXILIARY_SALT"):
            auxiliary_salt = str(rt.env.get("AUXILIARY_SALT"))

    s = block_height + block_hash + __input_hash + auxiliary_salt

    random.seed(s)
    Seeded.s = True


def getrandbits(k):
    assert Seeded.s, 'Random state not seeded. Call seed().'

    b_str = ''
    for i in range(k):
        if random.random() > 0.5:
            b_str += '1'
        else:
            b_str += '0'

    return int(b_str, 2)


def shuffle(l):
    assert Seeded.s, 'Random state not seeded. Call seed().'
    random.shuffle(l)


def randrange(k):
    assert Seeded.s, 'Random state not seeded. Call seed().'
    return random.randrange(k)


def randint(a, b):
    assert Seeded.s, 'Random state not seeded. Call seed().'
    return random.randint(a, b)


def choice(l):
    assert Seeded.s, 'Random state not seeded. Call seed().'
    return random.choice(l)


def choices(l, k):
    assert Seeded.s, 'Random state not seeded. Call seed().'
    return random.choices(l, k=k)


# Construct module for exposure in the contract runtime
random_module = ModuleType('random')
random_module.seed = seed
random_module.shuffle = shuffle
random_module.getrandbits = getrandbits
random_module.randrange = randrange
random_module.randint = randint
random_module.choice = choice
random_module.choices = choices

# Add it to the export object and it's good to go
exports = {
    'random': random_module
}


================================================
FILE: src/contracting/stdlib/bridge/time.py
================================================
from datetime import datetime as dt
from datetime import timedelta as td
from types import ModuleType


# Redefine a controlled datetime object that feels like a regular Python datetime object but is restricted so that we
# can regulate the user interaction with it to prevent security attack vectors. It may seem redundant, but it guarantees
# security.
SECONDS_IN_MINUTE = 60
SECONDS_IN_HOUR = 3600
SECONDS_IN_DAY = 86400
SECONDS_IN_WEEK = 604800


def get_raw_seconds(weeks, days, hours, minutes, seconds):
    m_sec = minutes * SECONDS_IN_MINUTE
    h_sec = hours * SECONDS_IN_HOUR
    d_sec = days * SECONDS_IN_DAY
    w_sec = weeks * SECONDS_IN_WEEK

    raw_seconds = seconds + m_sec + h_sec + d_sec + w_sec

    return raw_seconds


class Datetime:
    def __init__(self, year, month, day, hour=0, minute=0, second=0, microsecond=0):
        self._datetime = dt(
            year=year,
            month=month,
            day=day,
            hour=hour,
            minute=minute,
            second=second,
            microsecond=microsecond
        )

        self.year = self._datetime.year
        self.month = self._datetime.month
        self.day = self._datetime.day
        self.hour = self._datetime.hour
        self.minute = self._datetime.minute
        self.second = self._datetime.second
        self.microsecond = self._datetime.microsecond

    def __lt__(self, other):
        if type(other) != Datetime:
            raise TypeError(f'{type(other)} is not a Datetime!')
        return self._datetime < other._datetime

    def __le__(self, other):
        if type(other) != Datetime:
            raise TypeError(f'{type(other)} is not a Datetime!')
        return self._datetime <= other._datetime

    def __eq__(self, other):
        if type(other) != Datetime:
            raise TypeError(f'{type(other)} is not a Datetime!')
        return self._datetime == other._datetime

    def __ge__(self, other):
        if type(other) != Datetime:
            raise TypeError(f'{type(other)} is not a Datetime!')
        return self._datetime >= other._datetime

    def __gt__(self, other):
        if type(other) != Datetime:
            raise TypeError(f'{type(other)} is not a Datetime!')
        return self._datetime > other._datetime

    def __ne__(self, other):
        if type(other) != Datetime:
            raise TypeError(f'{type(other)} is not a Datetime!')
        return self._datetime != other._datetime

    def __sub__(self, other):
        if isinstance(other, Datetime):
            delta = self._datetime - other._datetime
            return Timedelta(days=delta.days, seconds=delta.seconds)
        return NotImplemented

    def __add__(self, other):
        if isinstance(other, Timedelta):
            return Datetime._from_datetime(self._datetime + other._timedelta)
        return NotImplemented

    def __str__(self):
        return str(self._datetime)

    def __repr__(self):
        return self.__str__()

    @classmethod
    def _from_datetime(cls, d: dt):
        return cls(year=d.year,
                   month=d.month,
                   day=d.day,
                   hour=d.hour,
                   minute=d.minute,
                   second=d.second,
                   microsecond=d.microsecond)
    
    @classmethod
    def strptime(cls, date_string, format):
        d = dt.strptime(date_string, format)
        return cls._from_datetime(d)

class Timedelta:
    def __init__(self, weeks=0,
                       days=0,
                       hours=0,
                       minutes=0,
                       seconds=0):

        self._timedelta = td(
            weeks=int(weeks), days=int(days), hours=int(hours), minutes=int(minutes), seconds=int(seconds)
        )

        # For fast access to how many hours are in a timedelta.
        self.__raw_seconds = get_raw_seconds(
            weeks=int(weeks), days=int(days), hours=int(hours), minutes=int(minutes), seconds=int(seconds)
        )

    def __lt__(self, other):
        if type(other) != Timedelta:
            raise TypeError(f'{type(other)} is not a Timedelta!')
        return self._timedelta < other._timedelta

    def __le__(self, other):
        if type(other) != Timedelta:
            raise TypeError(f'{type(other)} is not a Timedelta!')
        return self._timedelta <= other._timedelta

    def __eq__(self, other):
        if type(other) != Timedelta:
            raise TypeError(f'{type(other)} is not a Timedelta!')
        return self._timedelta == other._timedelta

    def __ge__(self, other):
        if type(other) != Timedelta:
            raise TypeError(f'{type(other)} is not a Timedelta!')
        return self._timedelta >= other._timedelta

    def __gt__(self, other):
        if type(other) != Timedelta:
            raise TypeError(f'{type(other)} is not a Timedelta!')
        return self._timedelta > other._timedelta

    def __ne__(self, other):
        if type(other) != Timedelta:
            raise TypeError(f'{type(other)} is not a Timedelta!')
        return self._timedelta != other._timedelta

    # Operator implementations inspired by CPython implementations
    def __add__(self, other):
        if isinstance(other, Timedelta):
            return Timedelta(days=self._timedelta.days + other._timedelta.days,
                             seconds=self._timedelta.seconds + other._timedelta.seconds)

        if isinstance(other, Datetime):
            d = other._datetime + self._timedelta
            return Datetime._from_datetime(d)

        return NotImplemented

    def __sub__(self, other):
        if isinstance(other, Timedelta):
            return Timedelta(days=self._timedelta.days - other._timedelta.days,
                             seconds=self._timedelta.seconds - other._timedelta.seconds,)

        if isinstance(other, Datetime):
            d = other._datetime - self._timedelta
            return Datetime._from_datetime(d)

        return NotImplemented

    def __mul__(self, other):
        if isinstance(other, Timedelta):
            return Timedelta(days=self._timedelta.days * other._timedelta.days,
                             seconds=self._timedelta.seconds * other._timedelta.seconds)
        elif isinstance(other, int):
            return Timedelta(days=self._timedelta.days * other,
                             seconds=self._timedelta.seconds * other)

        return NotImplemented

    def __str__(self):
        return str(self._timedelta)

    def __repr__(self):
        return self.__str__()

    # Accesses raw seconds and does a simple modulo to get the number of the component in the total seconds
    @property
    def seconds(self):
        return self.__raw_seconds

    @property
    def minutes(self):
        return self.__raw_seconds // SECONDS_IN_MINUTE

    @property
    def hours(self):
        return self.__raw_seconds // SECONDS_IN_HOUR

    @property
    def days(self):
        return self.__raw_seconds // SECONDS_IN_DAY

    @property
    def weeks(self):
        return self.__raw_seconds // SECONDS_IN_WEEK


WEEKS = Timedelta(weeks=1)
DAYS = Timedelta(days=1)
HOURS = Timedelta(hours=1)
MINUTES = Timedelta(minutes=1)
SECONDS = Timedelta(seconds=1)

datetime_module = ModuleType('datetime')
datetime_module.datetime = Datetime
datetime_module.timedelta = Timedelta
datetime_module.WEEKS = WEEKS
datetime_module.DAYS = DAYS
datetime_module.HOURS = HOURS
datetime_module.MINUTES = MINUTES
datetime_module.SECONDS = SECONDS

exports = {
    'datetime': datetime_module
}


================================================
FILE: src/contracting/stdlib/env.py
================================================
from contracting.stdlib.bridge.orm import exports as orm_exports
from contracting.stdlib.bridge.hashing import exports as hash_exports
from contracting.stdlib.bridge.time import exports as time_exports
from contracting.stdlib.bridge.random import exports as random_exports
from contracting.stdlib.bridge.imports import exports as imports_exports
from contracting.stdlib.bridge.access import exports as access_exports
from contracting.stdlib.bridge.decimal import exports as decimal_exports
from contracting.stdlib.bridge.crypto import exports as crypto_exports

# TODO create a module instead and return it inside of a dictionary like:
# {
#    'stdlib': module
# }
#
# Then stdlib.datetime becomes available, etc


def gather():
    env = {}

    env.update(orm_exports)
    env.update(hash_exports)
    env.update(time_exports)
    env.update(random_exports)
    env.update(imports_exports)
    env.update(access_exports)
    env.update(decimal_exports)
    env.update(crypto_exports)

    return env


================================================
FILE: src/contracting/storage/__init__.py
================================================


================================================
FILE: src/contracting/storage/contract.py
================================================
from contracting.compilation.compiler import ContractingCompiler
from contracting.storage.driver import Driver
from contracting.execution.runtime import rt
from contracting.stdlib import env
from contracting import constants

_driver = rt.env.get('__Driver') or Driver()


class Contract:
    def __init__(self, driver: Driver = _driver):
        self._driver = driver

    def submit(self, name, code, owner=None, constructor_args={}, developer=None):
        if self._driver.get_contract(name) is not None:
            raise Exception('Contract already exists.')

        c = ContractingCompiler(module_name=name)

        code_obj = c.parse_to_code(code, lint=True)

        scope = env.gather()
        scope.update({'__contract__': True})
        scope.update(rt.env)

        exec(code_obj, scope)

        if scope.get(constants.INIT_FUNC_NAME) is not None:
            if constructor_args is None:
                constructor_args = {}
            scope[constants.INIT_FUNC_NAME](**constructor_args)

        now = scope.get('now')
        if now is not None:
            self._driver.set_contract(
                name=name,
                code=code_obj,
                owner=owner,
                overwrite=False,
                timestamp=now,
                developer=developer
            )
        else:
            self._driver.set_contract(
                name=name,
                code=code_obj,
                owner=owner,
                overwrite=False,
                developer=developer
            )


================================================
FILE: src/contracting/storage/driver.py
================================================
from contracting.storage.encoder import encode_kv
from contracting.execution.runtime import rt
from contracting.stdlib.bridge.time import Datetime
from contracting.stdlib.bridge.decimal import ContractingDecimal
from datetime import datetime
from pathlib import Path
from cachetools import TTLCache
from contracting import constants
from contracting.storage import hdf5

import marshal
import decimal
import os
import shutil

FILE_EXT = ".d"
HASH_EXT = ".x"

DELIMITER = "."
HASH_DEPTH_DELIMITER = ":"

CODE_KEY = "__code__"
TYPE_KEY = "__type__"
AUTHOR_KEY = "__author__"
OWNER_KEY = "__owner__"
TIME_KEY = "__submitted__"
COMPILED_KEY = "__compiled__"
DEVELOPER_KEY = "__developer__"


class Driver:
    def __init__(self, bypass_cache=False, storage_home=constants.STORAGE_HOME):
        self.pending_deltas = {}
        self.pending_writes = {}
        self.pending_reads = {}
        self.transaction_writes = {}
        self.log_events = []
        self.cache = TTLCache(maxsize=1000, ttl=6*3600)
        self.bypass_cache = bypass_cache
        self.contract_state = storage_home.joinpath("contract_state")
        self.run_state = storage_home.joinpath("run_state")
        self.__build_directories()

    def __build_directories(self):
        self.contract_state.mkdir(exist_ok=True, parents=True)
        self.run_state.mkdir(exist_ok=True, parents=True)

    def __parse_key(self, key):
        # Split the key into parts (filename, group, etc.)
        parts = key.split(constants.INDEX_SEPARATOR, 1)  # Ensure key contains the INDEX_SEPARATOR
        
        # The first part should be the filename (e.g., "currency")
        filename = parts[0].split(constants.DELIMITER, 1)[0]  # Get only 'currency' from 'currency.balances'
        
        # The rest (after the first '.') becomes the group and attribute inside the HDF5 file
        if len(parts) > 1:
            variable = parts[1].replace(constants.DELIMITER, constants.HDF5_GROUP_SEPARATOR)
        else:
            variable = parts[0].replace(constants.DELIMITER, constants.HDF5_GROUP_SEPARATOR)
        
        return filename, variable


    def __filename_to_path(self, filename):
        if filename.startswith("__"):
            return str(self.run_state.joinpath(filename))
        else:
            return str(self.contract_state.joinpath(filename))

    def __get_files(self):
        return sorted(os.listdir(self.contract_state) + os.listdir(self.run_state))
    
    def is_file(self, filename):
        file_path = Path(self.__filename_to_path(filename))
        return file_path.is_file()

    def get(self, key: str, save: bool = True):
        """
        Get a value from the cache, pending reads, or disk. If save is True, 
        the value will be saved to pending_reads.
        """ 
        # Parse the key to get the filename and group
        value = self.find(key)
        if save and self.pending_reads.get(key) is None:
            self.pending_reads[key] = value
        # if value is not None:
        #     rt.deduct_read(*encode_kv(key, value))
        return value


    def set(self, key, value, is_txn_write=False):
        rt.deduct_write(*encode_kv(key, value))
        if self.pending_reads.get(key) is None:
            self.get(key)
        if type(value) in [decimal.Decimal, float]:
            value = ContractingDecimal(str(value))
        self.pending_writes[key] = value
        if is_txn_write:
            self.transaction_writes[key] = value


    def find(self, key: str):
        """
        Find the value for a given key. If not found in cache or pending writes, 
        it will look it up from the disk.
        """
        if self.bypass_cache:
            # Parse the key to get the filename and group
            filename, variable = self.__parse_key(key)
            value = hdf5.get_value_from_disk(self.__filename_to_path(filename), variable)
            return value

        value = self.pending_writes.get(key)
        if value is None:
            value = self.cache.get(key)
        if value is None:
            # Parse the key to get the filename and group for disk lookup
            filename, variable = self.__parse_key(key)
            value = hdf5.get_value_from_disk(self.__filename_to_path(filename), variable)
        return value


    def __get_keys_from_file(self, filename):
        return hdf5.get_groups(self.__filename_to_path(filename))

    def keys_from_disk(self, prefix=None, length=0):
        """
        Get all keys from disk with a given prefix
        """
        keys = set()
        try:
            for filename in self.__get_files():
                for key in self.__get_keys_from_file(filename):
                    if prefix and key.startswith(prefix):
                        keys.add(key)
                    elif not prefix:
                        keys.add(key)

                    if 0 < length <= len(keys):
                        raise AssertionError("Length threshold has been hit. Continuing.")
        except AssertionError:
            pass

        keys = list(keys)
        keys.sort()
        return keys

    def iter_from_disk(self, prefix="", length=0):
        try:
            filename, _ = self.__parse_key(prefix)
        except Exception:
            return self.keys(prefix=prefix)

        if not self.is_file(filename=filename):
            return []

        keys_from_file = self.__get_keys_from_file(filename)

        keys = [key for key in keys_from_file if key.startswith(prefix)]
        keys.sort()

        return keys if length == 0 else keys[:length]

    def value_from_disk(self, key):
        """
        Retrieve a value from the disk based on the parsed key.
        """
        # Parse the key to get the filename and group
        filename, variable = self.__parse_key(key)
        return hdf5.get_value_from_disk(self.__filename_to_path(filename), variable)

    def items(self, prefix=""):
        """
        Get all existing items with a given prefix.
        """
        _items = {}
        keys = set()

        # Collect pending writes with matching prefix
        for k, v in self.pending_writes.items():
            if k.startswith(prefix):
                # Always mark the key as seen to suppress disk rehydration
                keys.add(k)
                if v is not None:
                    _items[k] = v

        # Collect cache items with matching prefix
        for k, v in self.cache.items():
            if k.startswith(prefix):
                keys.add(k)
                if v is not None:
                    _items[k] = v

        # Collect keys from the disk
        db_keys = set(self.iter_from_disk(prefix=prefix))

        # Subtract already collected keys and add missing ones from disk
        for k in db_keys - keys:
            _items[k] = self.get(k)  # Cache get will add the keys to the cache

        return _items


    def keys(self, prefix=""):
        return list(self.items(prefix).keys())

    def values(self, prefix=""):
        return list(self.items(prefix).values())

    def make_key(self, contract, variable, args=[]):
        contract_variable = DELIMITER.join((contract, variable))
        if args:
            return HASH_DEPTH_DELIMITER.join((contract_variable, *[str(arg) for arg in args]))
        return contract_variable

    def set_var(self, contract, variable, arguments=[], value=None, mark=True):
        """
        Set a variable in a contract.
        """
        # Construct the key and set the value
        key = self.make_key(contract, variable, arguments)
        self.set(key, value)

    def get_var(self, contract, variable, arguments=[], mark=True):
        """
        Get a variable from a contract.
        """
        # Construct the key and get the value
        key = self.make_key(contract, variable, arguments)
        return self.get(key)

    def get_owner(self, name):
        owner = self.get_var(name, OWNER_KEY)
        if owner == "":
            owner = None
        return owner

    def get_time_submitted(self, name):
        return self.get_var(name, TIME_KEY)

    def get_compiled(self, name):
        return self.get_var(name, COMPILED_KEY)

    def get_contract(self, name):
        return self.get_var(name, CODE_KEY)

    def set_contract(
        self,
        name,
        code,
        owner=None,
        overwrite=False,
        timestamp=Datetime._from_datetime(datetime.now()),
        developer=None,
    ):
        if self.get_contract(name) is None:
            code_obj = compile(code, "", "exec")
            code_blob = marshal.dumps(code_obj)

            self.set_var(name, CODE_KEY, value=code)
            self.set_var(name, COMPILED_KEY, value=code_blob)
            self.set_var(name, OWNER_KEY, value=owner)
            self.set_var(name, TIME_KEY, value=timestamp)
            self.set_var(name, DEVELOPER_KEY, value=developer)

    def delete_contract(self, name):
        """
        Fully delete a contract from the caches and disk
        """
        for key in self.keys(name):
            if self.cache.get(key) is not None:
                del self.cache[key]

            if self.pending_writes.get(key) is not None:
                del self.pending_writes[key]

            self.delete_key_from_disk(key)

    def get_contract_files(self):
        """
        Get all contract files as a list of strings
        """
        return sorted(os.listdir(self.contract_state))

    def delete_key_from_disk(self, key):
        """
        Delete a key from the disk by parsing the filename and group from the key.
        """
        # Parse the key to get the filename and group
        filename, variable = self.__parse_key(key)
        if len(filename) < constants.FILENAME_LEN_MAX:
            hdf5.delete_key_from_disk(self.__filename_to_path(filename), variable)

    def flush_cache(self):
        self.pending_writes.clear()
        self.pending_reads.clear()
        self.pending_deltas.clear()
        self.transaction_writes.clear()
        self.log_events.clear()
        self.cache.clear()

    def flush_disk(self):
        shutil.rmtree(self.run_state, ignore_errors=True)
        shutil.rmtree(self.contract_state, ignore_errors=True)
        self.__build_directories()

    def flush_file(self, filename):
        file_path = self.__filename_to_path(filename)
        if os.path.isfile(file_path):
            os.unlink(file_path)
            
    def set_event(self, event):
        self.log_events.append(event)

    def flush_full(self):
        """
        Flush all caches and disk storage.
        """
        self.flush_disk()
        self.flush_cache()

    def delete(self, key):
        """
        Delete a key fully from the caches and queue it for deletion from disk on commit.
        """
        self.set(key, None)  # Setting the value to None will mark it for deletion

    def rollback(self, nanos=None):
        """
        Rollback to a given Nanoseconds in L2 cache or if no Nanoseconds is given, rollback to the latest state on disk.
        """
        if nanos is None:
            # Resets to the latest state on disk
            self.cache.clear()
            self.pending_reads.clear()
            self.pending_writes.clear()
            self.pending_deltas.clear()
        else:
            to_delete = []
            for _nanos, _deltas in sorted(self.pending_deltas.items(), reverse=True):
                if _nanos < nanos:
                    break
                to_delete.append(_nanos)
                for key, delta in _deltas['writes'].items():
                    self.cache[key] = delta[0]  # Restoring the value before the write

            for _nanos in to_delete:
                self.pending_deltas.pop(_nanos, None)

    def commit(self):
        """
        Save the current state to disk and clear the L1 and L2 caches.
        """
        for k, v in self.pending_writes.items():
            # Parse the key before applying to HDF5
            filename, variable = self.__parse_key(k)
            if v is None:
                hdf5.delete_key_from_disk(self.__filename_to_path(filename), variable)
            else:
                hdf5.set_value_to_disk(self.__filename_to_path(filename), variable, v, None)

        self.cache.clear()
        self.pending_writes.clear()
        self.pending_reads.clear()


    def hard_apply(self, nanos):
        """
        Save the current state to disk and L1 cache and clear the L2 cache.
        """

        deltas = {}
        for k, v in self.pending_writes.items():
            current = self.pending_reads.get(k)
            deltas[k] = (current, v)

            self.cache[k] = v

        self.pending_deltas[nanos] = {"writes": deltas, "reads": self.pending_reads}

        # Clear the top cache
        self.pending_reads = {}
        self.pending_writes.clear()

        # Run through the sorted HCLs from oldest to newest applying each one
        to_delete = []
        for _nanos, _deltas in sorted(self.pending_deltas.items()):
            # Run through all state changes, taking the second value, which is the post delta
            for key, delta in _deltas["writes"].items():
                # Parse the key before applying to HDF5
                filename, variable = self.__parse_key(key)
                hdf5.set_value_to_disk(self.__filename_to_path(filename), variable, delta[1], nanos)

            to_delete.append(_nanos)
            if _nanos == nanos:
                break

        # Remove the deltas from the set
        [self.pending_deltas.pop(key) for key in to_delete]


    def get_all_contract_state(self):
        """
        Queries the disk storage and returns a dictionary with all the state from the contract storage directory.
        """
        all_contract_state = {}
        for file_path in self.contract_state.iterdir():
            filename = file_path.name
            keys = hdf5.get_all_keys_from_file(self.__filename_to_path(filename))
            for key in keys:
                full_key = f"{filename}{DELIMITER}{key}"
                value = self.get(full_key)
                all_contract_state[full_key] = value

        return all_contract_state
    

    def get_run_state(self):
        """
        Retrieves the latest state information from the run state directory.
        """
        run_state = {}
        for file_path in self.run_state.iterdir():
            filename = file_path.name
            keys = self.__get_keys_from_file(self.__filename_to_path(filename))
            for key in keys:
                full_key = f"{filename}{DELIMITER}{key}"
                value = hdf5.get_value_from_disk(self.__filename_to_path(filename), key)
                run_state[full_key] = value

        return run_state


    def clear_transaction_writes(self):
        """
        Clear the transaction-specific writes.
        """
        self.transaction_writes.clear()

    def clear_events(self):
        self.log_events.clear()


================================================
FILE: src/contracting/storage/encoder.py
================================================
import json
import decimal

from contracting.stdlib.bridge.time import Datetime, Timedelta
from contracting.stdlib.bridge.decimal import ContractingDecimal, MAX_LOWER_PRECISION, fix_precision
from contracting.constants import INDEX_SEPARATOR, DELIMITER

MONGO_MIN_INT = -(2 ** 63)
MONGO_MAX_INT = 2 ** 63 - 1

##
# ENCODER CLASS
# Add to this to encode Python types for storage.
# Right now, this is only for datetime types. They are passed into the system as ISO strings, cast into Datetime objs
# and stored as dicts. Is there a better way? I don't know, maybe.
##


def safe_repr(obj, max_len=1024):
    try:
        r = obj.__repr__()
        rr = r.split(' at 0x')
        if len(rr) > 1:
            return rr[0] + '>'
        return rr[0][:max_len]
    except:
        return None


class Encoder(json.JSONEncoder):
    def default(self, o, *args):
        if isinstance(o, Datetime) or o.__class__.__name__ == Datetime.__name__:
            return {
                '__time__': [o.year, o.month, o.day, o.hour, o.minute, o.second, o.microsecond]
            }
        elif isinstance(o, Timedelta) or o.__class__.__name__ == Timedelta.__name__:
            return {
                '__delta__': [o._timedelta.days, o._timedelta.seconds]
            }
        elif isinstance(o, bytes):
            return {
                '__bytes__': o.hex()
            }
        elif isinstance(o, decimal.Decimal) or o.__class__.__name__ == decimal.Decimal.__name__:
            #return format(o, f'.{MAX_LOWER_PRECISION}f')
            return {
                '__fixed__': str(fix_precision(o))
            }

        elif isinstance(o, ContractingDecimal) or o.__class__.__name__ == ContractingDecimal.__name__:
            #return format(o._d, f'.{MAX_LOWER_PRECISION}f')
            return {
                '__fixed__': str(fix_precision(o._d))
            }
        #else:
        #    return safe_repr(o)
        return super().default(o)


def encode_int(value: int):
    if MONGO_MIN_INT < value < MONGO_MAX_INT:
        return value

    return {
        '__big_int__': str(value)
    }


def encode_ints_in_dict(data: dict):
    d = dict()
    for k, v in data.items():
        if isinstance(v, int):
            d[k] = encode_int(v)
        elif isinstance(v, dict):
            d[k] = encode_ints_in_dict(v)
        elif isinstance(v, list):
            d[k] = []
            for i in v:
                if isinstance(i, dict):
                    d[k].append(encode_ints_in_dict(i))
                elif isinstance(i, int):
                    d[k].append(encode_int(i))
                else:
                    d[k].append(i)
        else:
            d[k] = v

    return d


# JSON library from Python 3 doesn't let you instantiate your custom Encoder. You have to pass it as an obj to json
def encode(data: str):
    """ NOTE:
    Normally encoding behavior is o
Download .txt
gitextract_tbpetck0/

├── .github/
│   ├── ISSUE_TEMPLATE/
│   │   └── bug_report.md
│   ├── PULL_REQUEST_TEMPLATE.md
│   ├── dependabot.yml
│   └── workflows/
│       └── publish.yml
├── .gitignore
├── LICENSE
├── README.md
├── examples/
│   ├── 01 A very simple Counter contract.ipynb
│   ├── 02 Ingredients of a Smart Contract.ipynb
│   ├── 03 Interacting with the Client.ipynb
│   ├── 04 Standard Library and Extending Contracting.ipynb
│   ├── 05 Imports and Advanced Data Storage.ipynb
│   └── Rock Paper Scissors Tutorial.ipynb
├── pyproject.toml
├── release.sh
├── src/
│   └── contracting/
│       ├── __init__.py
│       ├── client.py
│       ├── compilation/
│       │   ├── __init__.py
│       │   ├── compiler.py
│       │   ├── linter.py
│       │   ├── parser.py
│       │   └── whitelists.py
│       ├── constants.py
│       ├── contracts/
│       │   ├── __init__.py
│       │   ├── proxythis.py
│       │   ├── submission.s.py
│       │   └── thistest2.py
│       ├── execution/
│       │   ├── __init__.py
│       │   ├── executor.py
│       │   ├── module.py
│       │   ├── runtime.py
│       │   └── tracer.py
│       ├── stdlib/
│       │   ├── __init__.py
│       │   ├── bridge/
│       │   │   ├── __init__.py
│       │   │   ├── access.py
│       │   │   ├── crypto.py
│       │   │   ├── decimal.py
│       │   │   ├── hashing.py
│       │   │   ├── imports.py
│       │   │   ├── orm.py
│       │   │   ├── random.py
│       │   │   └── time.py
│       │   └── env.py
│       └── storage/
│           ├── __init__.py
│           ├── contract.py
│           ├── driver.py
│           ├── encoder.py
│           ├── hdf5.py
│           └── orm.py
└── tests/
    ├── __init__.py
    ├── integration/
    │   ├── __init__.py
    │   ├── test_atomic_swap.py
    │   ├── test_builtins_locked_off.py
    │   ├── test_complex_contracts.py
    │   ├── test_complex_object_setting.py
    │   ├── test_constructor_args.py
    │   ├── test_contracts/
    │   │   ├── __init__.py
    │   │   ├── atomic_swaps.s.py
    │   │   ├── bad_time.s.py
    │   │   ├── bastardcoin.s.py
    │   │   ├── builtin_lib.s.py
    │   │   ├── child_test.s.py
    │   │   ├── client.py
    │   │   ├── con_pass_hash.s.py
    │   │   ├── construct_function_works.s.py
    │   │   ├── constructor_args_contract.s.py
    │   │   ├── contracting.s.py
    │   │   ├── currency.s.py
    │   │   ├── dater.py
    │   │   ├── dynamic_import.py
    │   │   ├── dynamic_import.s.py
    │   │   ├── dynamic_importing.s.py
    │   │   ├── erc20_clone.s.py
    │   │   ├── exception.py
    │   │   ├── float_issue.s.py
    │   │   ├── foreign_thing.s.py
    │   │   ├── hashing_works.s.py
    │   │   ├── i_use_env.s.py
    │   │   ├── import_test.s.py
    │   │   ├── import_this.s.py
    │   │   ├── importing_that.s.py
    │   │   ├── inf_loop.s.py
    │   │   ├── json_tests.s.py
    │   │   ├── leaky.s.py
    │   │   ├── mathtime.s.py
    │   │   ├── modules/
    │   │   │   ├── all_in_one.s.py
    │   │   │   ├── dynamic_import.s.py
    │   │   │   ├── module1.s.py
    │   │   │   ├── module2.s.py
    │   │   │   ├── module3.s.py
    │   │   │   ├── module4.s.py
    │   │   │   ├── module5.s.py
    │   │   │   ├── module6.s.py
    │   │   │   ├── module7.s.py
    │   │   │   └── module8.s.py
    │   │   ├── orm_foreign_hash_contract.s.py
    │   │   ├── orm_foreign_key_contract.s.py
    │   │   ├── orm_hash_contract.s.py
    │   │   ├── orm_no_contract_access.s.py
    │   │   ├── orm_variable_contract.s.py
    │   │   ├── owner_stuff.s.py
    │   │   ├── parent_test.s.py
    │   │   ├── pass_hash.s.py
    │   │   ├── private_methods.s.py
    │   │   ├── stubucks.s.py
    │   │   ├── submission.s.py
    │   │   ├── tejastokens.s.py
    │   │   ├── thing.s.py
    │   │   ├── time.s.py
    │   │   └── time_storage.s.py
    │   ├── test_datetime_contracts.py
    │   ├── test_dynamic_imports.py
    │   ├── test_executor_submission_process.py
    │   ├── test_executor_transaction_writes.py
    │   ├── test_memory_clean_up_after_execution.py
    │   ├── test_misc_contracts.py
    │   ├── test_pixel_game.py
    │   ├── test_rich_ctx_calling.py
    │   ├── test_run_private_function.py
    │   ├── test_senecaCompiler_integration.py
    │   ├── test_seneca_client_randoms.py
    │   ├── test_seneca_client_replaces_executor.py
    │   └── test_stamp_deduction.py
    ├── performance/
    │   ├── __init__.py
    │   ├── prof_transfer.py
    │   ├── test_contracts/
    │   │   ├── __init__.py
    │   │   ├── erc20_clone.s.py
    │   │   ├── modules/
    │   │   │   ├── all_in_one.s.py
    │   │   │   ├── dynamic_import.s.py
    │   │   │   ├── module1.s.py
    │   │   │   ├── module2.s.py
    │   │   │   ├── module3.s.py
    │   │   │   ├── module4.s.py
    │   │   │   ├── module5.s.py
    │   │   │   ├── module6.s.py
    │   │   │   ├── module7.s.py
    │   │   │   └── module8.s.py
    │   │   └── submission.s.py
    │   └── test_transfer.py
    ├── security/
    │   ├── __init__.py
    │   ├── contracts/
    │   │   ├── builtin_hack_token.s.py
    │   │   ├── call_infinate_loop.s.py
    │   │   ├── con_inf_writes.s.py
    │   │   ├── constructor_infinate_loop.s.py
    │   │   ├── double_spend_gas_attack.s.py
    │   │   ├── erc20_clone.s.py
    │   │   ├── get_set_driver.py
    │   │   ├── get_set_driver_2.py
    │   │   ├── hack_tokens.s.py
    │   │   ├── import_hash_from_contract.s.py
    │   │   ├── infinate_loop.s.py
    │   │   └── submission.s.py
    │   └── test_erc20_token_hacks.py
    └── unit/
        ├── __init__.py
        ├── contracts/
        │   ├── currency.s.py
        │   ├── exception.s.py
        │   ├── proxythis.py
        │   ├── submission.s.py
        │   └── thistest2.py
        ├── loop_client_test.sh
        ├── precompiled/
        │   ├── __init__.py
        │   ├── compiled_token.py
        │   └── updated_submission.py
        ├── test_client.py
        ├── test_client_keys_prefix.py
        ├── test_context_data_struct.py
        ├── test_datetime.py
        ├── test_decimal.py
        ├── test_driver_tombstones.py
        ├── test_encode.py
        ├── test_imports_stdlib.py
        ├── test_linter.py
        ├── test_module.py
        ├── test_new_driver.py
        ├── test_orm.py
        ├── test_parser.py
        ├── test_revert_on_exception.py
        ├── test_runtime.py
        ├── test_state_management.py
        ├── test_stdlib_hashing.py
        ├── test_sys_contracts/
        │   ├── __init__.py
        │   ├── bad_lint.s.py
        │   ├── compile_this.s.py
        │   ├── currency.s.py
        │   ├── good_lint.s.py
        │   ├── module1.py
        │   ├── module2.py
        │   ├── module3.py
        │   ├── module4.py
        │   ├── module5.py
        │   ├── module6.py
        │   ├── module7.py
        │   ├── module8.py
        │   └── module_func.py
        └── test_timedelta.py
Download .txt
SYMBOL INDEX (1188 symbols across 152 files)

FILE: src/contracting/client.py
  class AbstractContract (line 21) | class AbstractContract:
    method __init__ (line 22) | def __init__(self, name, signer, environment, executor: Executor, func...
    method keys (line 49) | def keys(self):
    method quick_read (line 57) | def quick_read(self, variable, key=None, args=None):
    method quick_write (line 70) | def quick_write(self, variable, key=None, value=None, args=None):
    method run_private_function (line 85) | def run_private_function(self, f, signer=None, environment=None, **kwa...
    method __getattr__ (line 114) | def __getattr__(self, item):
    method now (line 143) | def now(self):
    method _abstract_function_call (line 147) | def _abstract_function_call(
  class ContractingClient (line 189) | class ContractingClient:
    method __init__ (line 190) | def __init__(
    method set_submission_contract (line 219) | def set_submission_contract(self, filename=None, commit=True):
    method flush (line 240) | def flush(self):
    method get_contract (line 249) | def get_contract(self, name):
    method closure_to_code_string (line 274) | def closure_to_code_string(self, f):
    method lint (line 291) | def lint(self, f, raise_errors=False):
    method compile (line 307) | def compile(self, f):
    method submit (line 314) | def submit(self, f, name=None, metering=None, owner=None, constructor_...
    method get_contracts (line 337) | def get_contracts(self):
    method get_var (line 344) | def get_var(self, contract, variable, arguments=[], mark=False):
    method set_var (line 347) | def set_var(self, contract, variable, arguments=[], value=None, mark=F...

FILE: src/contracting/compilation/compiler.py
  class ContractingCompiler (line 8) | class ContractingCompiler(ast.NodeTransformer):
    method __init__ (line 9) | def __init__(self, module_name='__main__', linter=Linter()):
    method parse (line 18) | def parse(self, source: str, lint=True):
    method privatize (line 51) | def privatize(s):
    method compile (line 54) | def compile(self, source: str, lint=True):
    method parse_to_code (line 61) | def parse_to_code(self, source, lint=True):
    method visit_FunctionDef (line 66) | def visit_FunctionDef(self, node):
    method visit_Assign (line 97) | def visit_Assign(self, node):
    method visit_Name (line 110) | def visit_Name(self, node):
    method visit_Expr (line 114) | def visit_Expr(self, node):
    method visit_Num (line 118) | def visit_Num(self, node):

FILE: src/contracting/compilation/linter.py
  class Linter (line 15) | class Linter(ast.NodeVisitor):
    method __init__ (line 17) | def __init__(self):
    method ast_types (line 30) | def ast_types(self, t, lnum):
    method not_system_variable (line 36) | def not_system_variable(self, v, lnum):
    method no_nested_imports (line 42) | def no_nested_imports(self, node):
    method visit_Name (line 49) | def visit_Name(self, node):
    method visit_Attribute (line 65) | def visit_Attribute(self, node):
    method visit_Import (line 74) | def visit_Import(self, node):
    method visit_ImportFrom (line 82) | def visit_ImportFrom(self, node):
    method visit_ClassDef (line 88) | def visit_ClassDef(self, node):
    method visit_AsyncFunctionDef (line 95) | def visit_AsyncFunctionDef(self, node):
    method visit_Assign (line 103) | def visit_Assign(self, node):
    method visit_AugAssign (line 134) | def visit_AugAssign(self, node):
    method visit_Call (line 139) | def visit_Call(self, node: ast.Call):
    method generic_visit (line 150) | def generic_visit(self, node):
    method visit_Num (line 160) | def visit_Num(self, node):
    method visit_FunctionDef (line 167) | def visit_FunctionDef(self, node):
    method annotation_types (line 233) | def annotation_types(self, t, lnum):
    method check_return_types (line 243) | def check_return_types(self, t, lnum):
    method _reset (line 249) | def _reset(self):
    method _final_checks (line 260) | def _final_checks(self):
    method _collect_function_defs (line 278) | def _collect_function_defs(self, root):
    method check (line 289) | def check(self, ast_tree):
    method dump_violations (line 300) | def dump_violations(self):

FILE: src/contracting/compilation/parser.py
  function methods_for_contract (line 4) | def methods_for_contract(contract_code: str):
  function variables_for_contract (line 34) | def variables_for_contract(contract_code: str):

FILE: src/contracting/contracts/proxythis.py
  function proxythis (line 2) | def proxythis(con: str):
  function nestedproxythis (line 6) | def nestedproxythis(con: str):
  function noproxy (line 10) | def noproxy():

FILE: src/contracting/contracts/submission.s.py
  function submit_contract (line 2) | def submit_contract(name: str, code: str, owner: Any=None, constructor_a...
  function change_developer (line 20) | def change_developer(contract: str, new_developer: str):

FILE: src/contracting/contracts/thistest2.py
  function exported (line 2) | def exported():
  function getthis (line 6) | def getthis():
  function nested_exported (line 10) | def nested_exported():

FILE: src/contracting/execution/executor.py
  class Executor (line 13) | class Executor:
    method __init__ (line 14) | def __init__(self,
    method wipe_modules (line 39) | def wipe_modules(self):
    method execute (line 43) | def execute(self, sender, contract_name, function_name, kwargs,

FILE: src/contracting/execution/module.py
  function is_valid_import (line 22) | def is_valid_import(name):
  function restricted_import (line 28) | def restricted_import(name, globals=None, locals=None, fromlist=(), leve...
  function enable_restricted_imports (line 37) | def enable_restricted_imports():
  function disable_restricted_imports (line 42) | def disable_restricted_imports():
  function uninstall_builtins (line 46) | def uninstall_builtins():
  function install_database_loader (line 54) | def install_database_loader(driver=Driver()):
  function uninstall_database_loader (line 60) | def uninstall_database_loader():
  function install_system_contracts (line 66) | def install_system_contracts(directory=''):
  class DatabaseFinder (line 76) | class DatabaseFinder:
    method find_spec (line 79) | def find_spec(self, fullname, path=None, target=None):
  class DatabaseLoader (line 88) | class DatabaseLoader(Loader):
    method __init__ (line 89) | def __init__(self, d=Driver()):
    method create_module (line 92) | def create_module(self, spec):
    method exec_module (line 95) | def exec_module(self, module):
    method module_repr (line 123) | def module_repr(self, module):

FILE: src/contracting/execution/runtime.py
  class Context (line 10) | class Context:
    method __init__ (line 11) | def __init__(self, base_state, maxlen=constants.RECURSION_LIMIT):
    method _context_changed (line 17) | def _context_changed(self, contract):
    method _get_state (line 22) | def _get_state(self):
    method _add_state (line 27) | def _add_state(self, state: dict):
    method _ins_state (line 32) | def _ins_state(self):
    method _pop_state (line 36) | def _pop_state(self):
    method _reset (line 43) | def _reset(self):
    method this (line 48) | def this(self):
    method caller (line 52) | def caller(self):
    method signer (line 56) | def signer(self):
    method owner (line 60) | def owner(self):
    method entry (line 64) | def entry(self):
    method submission_name (line 68) | def submission_name(self):
  class Runtime (line 83) | class Runtime:
    method set_up (line 103) | def set_up(cls, stmps, meter):
    method clean_up (line 112) | def clean_up(cls):
    method deduct_read (line 128) | def deduct_read(cls, key, value):
    method deduct_write (line 135) | def deduct_write(cls, key, value):

FILE: src/contracting/execution/tracer.py
  class Tracer (line 30) | class Tracer:
    method __init__ (line 31) | def __init__(self):
    method start (line 42) | def start(self):
    method stop (line 48) | def stop(self):
    method reset (line 53) | def reset(self):
    method set_stamp (line 61) | def set_stamp(self, stamp):
    method add_cost (line 64) | def add_cost(self, new_cost):
    method get_stamp_used (line 70) | def get_stamp_used(self):
    method get_last_frame_mem_usage (line 73) | def get_last_frame_mem_usage(self):
    method get_total_mem_usage (line 76) | def get_total_mem_usage(self):
    method is_started (line 79) | def is_started(self):
    method get_memory_usage (line 82) | def get_memory_usage(self):
    method trace_func (line 88) | def trace_func(self, frame, event, arg):
    method get_opcode (line 133) | def get_opcode(self, code, offset):

FILE: src/contracting/stdlib/bridge/access.py
  class __export (line 7) | class __export(ContextDecorator):
    method __init__ (line 8) | def __init__(self, contract):
    method __enter__ (line 11) | def __enter__(self, *args, **kwargs):
    method __exit__ (line 33) | def __exit__(self, *args, **kwargs):

FILE: src/contracting/stdlib/bridge/crypto.py
  function verify (line 5) | def verify(vk: str, msg: str, signature: str):
  function key_is_valid (line 18) | def key_is_valid(key: str):

FILE: src/contracting/stdlib/bridge/decimal.py
  function make_min_decimal_str (line 18) | def make_min_decimal_str(prec):
  function make_max_decimal_str (line 21) | def make_max_decimal_str(prec):
  function neg_sci_not (line 25) | def neg_sci_not(s: str):
  function fix_precision (line 46) | def fix_precision(x: Decimal):
  class ContractingDecimal (line 52) | class ContractingDecimal:
    method _get_other (line 53) | def _get_other(self, other):
    method __init__ (line 60) | def __init__(self, a):
    method __bool__ (line 73) | def __bool__(self):
    method __eq__ (line 76) | def __eq__(self, other):
    method __lt__ (line 79) | def __lt__(self, other):
    method __le__ (line 82) | def __le__(self, other):
    method __gt__ (line 85) | def __gt__(self, other):
    method __ge__ (line 88) | def __ge__(self, other):
    method __str__ (line 91) | def __str__(self):
    method __repr__ (line 94) | def __repr__(self):
    method __neg__ (line 97) | def __neg__(self):
    method __pos__ (line 100) | def __pos__(self):
    method __abs__ (line 103) | def __abs__(self):
    method __add__ (line 106) | def __add__(self, other):
    method __radd__ (line 109) | def __radd__(self, other):
    method __sub__ (line 112) | def __sub__(self, other):
    method __rsub__ (line 115) | def __rsub__(self, other):
    method __mul__ (line 118) | def __mul__(self, other):
    method __rmul__ (line 121) | def __rmul__(self, other):
    method __truediv__ (line 124) | def __truediv__(self, other):
    method __rtruediv__ (line 127) | def __rtruediv__(self, other):
    method __mod__ (line 130) | def __mod__(self, other):
    method __rmod__ (line 133) | def __rmod__(self, other):
    method __floordiv__ (line 136) | def __floordiv__(self, other):
    method __rfloordiv__ (line 139) | def __rfloordiv__(self, other):
    method __pow__ (line 142) | def __pow__(self, other):
    method __rpow__ (line 145) | def __rpow__(self, other):
    method __int__ (line 148) | def __int__(self):
    method __float__ (line 151) | def __float__(self):
    method __round__ (line 154) | def __round__(self, n=None):

FILE: src/contracting/stdlib/bridge/hashing.py
  function sha3 (line 10) | def sha3(hex_str: str):
  function sha256 (line 24) | def sha256(hex_str: str):

FILE: src/contracting/stdlib/bridge/imports.py
  function extract_closure (line 11) | def extract_closure(fn):
  class Func (line 16) | class Func:
    method __init__ (line 17) | def __init__(self, name, args=(), private=False):
    method is_of (line 25) | def is_of(self, f: FunctionType):
  class Var (line 38) | class Var:
    method __init__ (line 39) | def __init__(self, name, t):
    method is_of (line 44) | def is_of(self, v):
  function import_module (line 50) | def import_module(name):
  function enforce_interface (line 68) | def enforce_interface(m: ModuleType, interface: list):
  function owner_of (line 88) | def owner_of(m: ModuleType):

FILE: src/contracting/stdlib/bridge/orm.py
  class V (line 6) | class V(Variable):
    method __init__ (line 7) | def __init__(self, *args, **kwargs):
  class H (line 13) | class H(Hash):
    method __init__ (line 14) | def __init__(self, *args, **kwargs):
  class FV (line 20) | class FV(ForeignVariable):
    method __init__ (line 21) | def __init__(self, *args, **kwargs):
  class FH (line 27) | class FH(ForeignHash):
    method __init__ (line 28) | def __init__(self, *args, **kwargs):
  class C (line 34) | class C(Contract):
    method __init__ (line 35) | def __init__(self, *args, **kwargs):
  class LE (line 41) | class LE(LogEvent):
    method __init__ (line 42) | def __init__(self, *args, **kwargs):

FILE: src/contracting/stdlib/bridge/random.py
  class Seeded (line 20) | class Seeded:
  function seed (line 24) | def seed(aux_salt=None):
  function getrandbits (line 46) | def getrandbits(k):
  function shuffle (line 59) | def shuffle(l):
  function randrange (line 64) | def randrange(k):
  function randint (line 69) | def randint(a, b):
  function choice (line 74) | def choice(l):
  function choices (line 79) | def choices(l, k):

FILE: src/contracting/stdlib/bridge/time.py
  function get_raw_seconds (line 15) | def get_raw_seconds(weeks, days, hours, minutes, seconds):
  class Datetime (line 26) | class Datetime:
    method __init__ (line 27) | def __init__(self, year, month, day, hour=0, minute=0, second=0, micro...
    method __lt__ (line 46) | def __lt__(self, other):
    method __le__ (line 51) | def __le__(self, other):
    method __eq__ (line 56) | def __eq__(self, other):
    method __ge__ (line 61) | def __ge__(self, other):
    method __gt__ (line 66) | def __gt__(self, other):
    method __ne__ (line 71) | def __ne__(self, other):
    method __sub__ (line 76) | def __sub__(self, other):
    method __add__ (line 82) | def __add__(self, other):
    method __str__ (line 87) | def __str__(self):
    method __repr__ (line 90) | def __repr__(self):
    method _from_datetime (line 94) | def _from_datetime(cls, d: dt):
    method strptime (line 104) | def strptime(cls, date_string, format):
  class Timedelta (line 108) | class Timedelta:
    method __init__ (line 109) | def __init__(self, weeks=0,
    method __lt__ (line 124) | def __lt__(self, other):
    method __le__ (line 129) | def __le__(self, other):
    method __eq__ (line 134) | def __eq__(self, other):
    method __ge__ (line 139) | def __ge__(self, other):
    method __gt__ (line 144) | def __gt__(self, other):
    method __ne__ (line 149) | def __ne__(self, other):
    method __add__ (line 155) | def __add__(self, other):
    method __sub__ (line 166) | def __sub__(self, other):
    method __mul__ (line 177) | def __mul__(self, other):
    method __str__ (line 187) | def __str__(self):
    method __repr__ (line 190) | def __repr__(self):
    method seconds (line 195) | def seconds(self):
    method minutes (line 199) | def minutes(self):
    method hours (line 203) | def hours(self):
    method days (line 207) | def days(self):
    method weeks (line 211) | def weeks(self):

FILE: src/contracting/stdlib/env.py
  function gather (line 18) | def gather():

FILE: src/contracting/storage/contract.py
  class Contract (line 10) | class Contract:
    method __init__ (line 11) | def __init__(self, driver: Driver = _driver):
    method submit (line 14) | def submit(self, name, code, owner=None, constructor_args={}, develope...

FILE: src/contracting/storage/driver.py
  class Driver (line 31) | class Driver:
    method __init__ (line 32) | def __init__(self, bypass_cache=False, storage_home=constants.STORAGE_...
    method __build_directories (line 44) | def __build_directories(self):
    method __parse_key (line 48) | def __parse_key(self, key):
    method __filename_to_path (line 64) | def __filename_to_path(self, filename):
    method __get_files (line 70) | def __get_files(self):
    method is_file (line 73) | def is_file(self, filename):
    method get (line 77) | def get(self, key: str, save: bool = True):
    method set (line 91) | def set(self, key, value, is_txn_write=False):
    method find (line 102) | def find(self, key: str):
    method __get_keys_from_file (line 123) | def __get_keys_from_file(self, filename):
    method keys_from_disk (line 126) | def keys_from_disk(self, prefix=None, length=0):
    method iter_from_disk (line 148) | def iter_from_disk(self, prefix="", length=0):
    method value_from_disk (line 164) | def value_from_disk(self, key):
    method items (line 172) | def items(self, prefix=""):
    method keys (line 204) | def keys(self, prefix=""):
    method values (line 207) | def values(self, prefix=""):
    method make_key (line 210) | def make_key(self, contract, variable, args=[]):
    method set_var (line 216) | def set_var(self, contract, variable, arguments=[], value=None, mark=T...
    method get_var (line 224) | def get_var(self, contract, variable, arguments=[], mark=True):
    method get_owner (line 232) | def get_owner(self, name):
    method get_time_submitted (line 238) | def get_time_submitted(self, name):
    method get_compiled (line 241) | def get_compiled(self, name):
    method get_contract (line 244) | def get_contract(self, name):
    method set_contract (line 247) | def set_contract(
    method delete_contract (line 266) | def delete_contract(self, name):
    method get_contract_files (line 279) | def get_contract_files(self):
    method delete_key_from_disk (line 285) | def delete_key_from_disk(self, key):
    method flush_cache (line 294) | def flush_cache(self):
    method flush_disk (line 302) | def flush_disk(self):
    method flush_file (line 307) | def flush_file(self, filename):
    method set_event (line 312) | def set_event(self, event):
    method flush_full (line 315) | def flush_full(self):
    method delete (line 322) | def delete(self, key):
    method rollback (line 328) | def rollback(self, nanos=None):
    method commit (line 350) | def commit(self):
    method hard_apply (line 367) | def hard_apply(self, nanos):
    method get_all_contract_state (line 402) | def get_all_contract_state(self):
    method get_run_state (line 418) | def get_run_state(self):
    method clear_transaction_writes (line 434) | def clear_transaction_writes(self):
    method clear_events (line 440) | def clear_events(self):

FILE: src/contracting/storage/encoder.py
  function safe_repr (line 19) | def safe_repr(obj, max_len=1024):
  class Encoder (line 30) | class Encoder(json.JSONEncoder):
    method default (line 31) | def default(self, o, *args):
  function encode_int (line 60) | def encode_int(value: int):
  function encode_ints_in_dict (line 69) | def encode_ints_in_dict(data: dict):
  function encode (line 92) | def encode(data: str):
  function as_object (line 108) | def as_object(d):
  function decode (line 124) | def decode(data):
  function make_key (line 137) | def make_key(contract, variable, args=[]):
  function encode_kv (line 144) | def encode_kv(key, value):
  function decode_kv (line 156) | def decode_kv(key, value):
  function convert (line 167) | def convert(k, v):
  function convert_dict (line 181) | def convert_dict(d):

FILE: src/contracting/storage/hdf5.py
  function get_file_lock (line 17) | def get_file_lock(file_path):
  function get_value (line 22) | def get_value(file_path, group_name):
  function get_block (line 26) | def get_block(file_path, group_name):
  function get_attr (line 30) | def get_attr(file_path, group_name, attr_name):
  function get_groups (line 44) | def get_groups(file_path):
  function set (line 54) | def set(file_path, group_name, value, blocknum, timeout=20):
  function write_attr (line 74) | def write_attr(file_or_path, group_name, attr_name, value, timeout=20):
  function _write_attr_to_file (line 87) | def _write_attr_to_file(file, group_name, attr_name, value, timeout):
  function delete (line 102) | def delete(file_path, group_name, timeout=20):
  function set_value_to_disk (line 118) | def set_value_to_disk(file_path, group_name, value, block_num=None, time...
  function delete_key_from_disk (line 127) | def delete_key_from_disk(file_path, group_name, timeout=20):
  function get_value_from_disk (line 131) | def get_value_from_disk(file_path, group_name):
  function get_all_keys_from_file (line 136) | def get_all_keys_from_file(file_path):

FILE: src/contracting/storage/orm.py
  class Datum (line 11) | class Datum:
    method __init__ (line 12) | def __init__(self, contract, name, driver: Driver):
  class Variable (line 17) | class Variable(Datum):
    method __init__ (line 18) | def __init__(self, contract, name, driver: Driver = driver, t=None, de...
    method set (line 28) | def set(self, value):
    method get (line 37) | def get(self):
  class Hash (line 46) | class Hash(Datum):
    method __init__ (line 47) | def __init__(self, contract, name, driver: Driver = driver, default_va...
    method _set (line 52) | def _set(self, key, value):
    method _get (line 55) | def _get(self, item):
    method _validate_key (line 70) | def _validate_key(self, key):
    method _prefix_for_args (line 100) | def _prefix_for_args(self, args):
    method all (line 108) | def all(self, *args):
    method _items (line 112) | def _items(self, *args):
    method clear (line 116) | def clear(self, *args):
    method __setitem__ (line 122) | def __setitem__(self, key, value):
    method __getitem__ (line 127) | def __getitem__(self, key):
    method __contains__ (line 131) | def __contains__(self, key):
  class ForeignVariable (line 135) | class ForeignVariable(Variable):
    method __init__ (line 136) | def __init__(
    method set (line 142) | def set(self, value):
  class ForeignHash (line 146) | class ForeignHash(Hash):
    method __init__ (line 147) | def __init__(
    method _set (line 153) | def _set(self, key, value):
    method __setitem__ (line 156) | def __setitem__(self, key, value):
    method __getitem__ (line 159) | def __getitem__(self, item):
    method clear (line 162) | def clear(self, *args):
  class LogEvent (line 166) | class LogEvent(Datum):
    method __init__ (line 173) | def __init__(self, contract, name, event, params, driver: Driver = dri...
    method write_event (line 196) | def write_event(self, event_data):
    method __call__ (line 261) | def __call__(self, data):

FILE: tests/integration/test_atomic_swap.py
  function submission_kwargs_for_file (line 7) | def submission_kwargs_for_file(f):
  class TestAtomicSwapContract (line 32) | class TestAtomicSwapContract(TestCase):
    method setUp (line 33) | def setUp(self):
    method tearDown (line 59) | def tearDown(self):
    method test_initiate_not_enough_approved (line 64) | def test_initiate_not_enough_approved(self):
    method test_initiate_transfers_coins_correctly (line 76) | def test_initiate_transfers_coins_correctly(self):
    method test_initiate_writes_to_correct_key_and_properly (line 93) | def test_initiate_writes_to_correct_key_and_properly(self):
    method test_redeem_on_wrong_secret_fails (line 108) | def test_redeem_on_wrong_secret_fails(self):
    method test_redeem_on_wrong_sender_fails (line 122) | def test_redeem_on_wrong_sender_fails(self):
    method test_past_expiration_fails (line 136) | def test_past_expiration_fails(self):
    method test_successful_redeem_transfers_coins_correctly (line 153) | def test_successful_redeem_transfers_coins_correctly(self):
    method test_successful_redeem_deletes_entry (line 173) | def test_successful_redeem_deletes_entry(self):
    method test_refund_works (line 192) | def test_refund_works(self):
    method test_refund_too_early_fails (line 212) | def test_refund_too_early_fails(self):
    method test_refund_participant_is_signer_fails (line 229) | def test_refund_participant_is_signer_fails(self):
    method test_refund_fails_with_wrong_secret (line 246) | def test_refund_fails_with_wrong_secret(self):
    method test_refund_resets_swaps (line 263) | def test_refund_resets_swaps(self):
    method test_trying_to_call_private_function_fails (line 283) | def test_trying_to_call_private_function_fails(self):

FILE: tests/integration/test_builtins_locked_off.py
  class TestBuiltinsLockedOff (line 5) | class TestBuiltinsLockedOff(TestCase):
    method setUp (line 6) | def setUp(self):
    method tearDown (line 9) | def tearDown(self):
    method test_if_builtin_can_be_submitted (line 13) | def test_if_builtin_can_be_submitted(self):
    method test_if_non_builtin_can_be_submitted (line 22) | def test_if_non_builtin_can_be_submitted(self):
  class TestMathBuiltinsLockedOff (line 26) | class TestMathBuiltinsLockedOff(TestCase):
    method setUp (line 27) | def setUp(self):
    method tearDown (line 30) | def tearDown(self):
    method test_if_builtin_can_be_submitted (line 33) | def test_if_builtin_can_be_submitted(self):
  class TestDatabaseLoaderLoadsFirst (line 43) | class TestDatabaseLoaderLoadsFirst(TestCase):
    method setUp (line 44) | def setUp(self):
    method tearDown (line 47) | def tearDown(self):
    method test_if_builtin_can_be_submitted (line 50) | def test_if_builtin_can_be_submitted(self):
  class TestDynamicImport (line 65) | class TestDynamicImport(TestCase):
    method setUp (line 66) | def setUp(self):
    method tearDown (line 69) | def tearDown(self):
    method test_if_builtin_can_be_submitted (line 72) | def test_if_builtin_can_be_submitted(self):
  class TestFloatIssue (line 85) | class TestFloatIssue(TestCase):
    method setUp (line 86) | def setUp(self):
    method tearDown (line 89) | def tearDown(self):
    method test_if_builtin_can_be_submitted (line 92) | def test_if_builtin_can_be_submitted(self):

FILE: tests/integration/test_complex_contracts.py
  function submission_kwargs_for_file (line 9) | def submission_kwargs_for_file(f):
  class TestComplexContracts (line 34) | class TestComplexContracts(TestCase):
    method setUp (line 35) | def setUp(self):
    method tearDown (line 47) | def tearDown(self):
    method test_token_construction_works (line 50) | def test_token_construction_works(self):
    method test_token_transfer_works (line 68) | def test_token_transfer_works(self):
    method test_token_transfer_failure_not_enough_to_send (line 84) | def test_token_transfer_failure_not_enough_to_send(self):
    method test_token_transfer_to_new_account (line 96) | def test_token_transfer_to_new_account(self):
    method test_erc20_clone_construction_works (line 110) | def test_erc20_clone_construction_works(self):
    method test_erc20_clone_transfer_works (line 126) | def test_erc20_clone_transfer_works(self):
    method test_erc20_clone_transfer_fails (line 141) | def test_erc20_clone_transfer_fails(self):
    method test_allowance_of_blank (line 155) | def test_allowance_of_blank(self):
    method test_approve_works_and_allowance_shows (line 166) | def test_approve_works_and_allowance_shows(self):
    method test_approve_and_transfer_from (line 179) | def test_approve_and_transfer_from(self):
    method test_failure_after_data_writes_doesnt_commit (line 197) | def test_failure_after_data_writes_doesnt_commit(self):
    method test_leaky_contract_commits_on_success (line 213) | def test_leaky_contract_commits_on_success(self):
    method test_time_stdlib_works (line 229) | def test_time_stdlib_works(self):
    method test_bad_time_contract_not_submittable (line 252) | def test_bad_time_contract_not_submittable(self):
    method test_json_lists_work (line 268) | def test_json_lists_work(self):
    method test_time_storage_works (line 280) | def test_time_storage_works(self):
    method test_hash_sha3_works (line 296) | def test_hash_sha3_works(self):
    method test_hash_sha256_works (line 311) | def test_hash_sha256_works(self):

FILE: tests/integration/test_complex_object_setting.py
  function contract (line 5) | def contract():
  class TestComplexStorage (line 24) | class TestComplexStorage(TestCase):
    method setUp (line 25) | def setUp(self):
    method tearDown (line 32) | def tearDown(self):
    method test_storage (line 35) | def test_storage(self):
    method test_modify (line 39) | def test_modify(self):

FILE: tests/integration/test_constructor_args.py
  class TestSenecaClientReplacesExecutor (line 6) | class TestSenecaClientReplacesExecutor(TestCase):
    method setUp (line 7) | def setUp(self):
    method test_custom_args_works (line 26) | def test_custom_args_works(self):
    method test_custom_args_overloading (line 35) | def test_custom_args_overloading(self):
    method test_custom_args_not_enough_args (line 39) | def test_custom_args_not_enough_args(self):

FILE: tests/integration/test_contracts/atomic_swaps.s.py
  function initiate (line 6) | def initiate(participant: str, expiration: datetime.datetime, hashlock: ...
  function redeem (line 18) | def redeem(secret: str):
  function refund (line 34) | def refund(participant: str, secret: str):
  function test (line 54) | def test():

FILE: tests/integration/test_contracts/bad_time.s.py
  function ha (line 4) | def ha():

FILE: tests/integration/test_contracts/bastardcoin.s.py
  function seed (line 4) | def seed():
  function transfer (line 9) | def transfer(amount: int, to: str):
  function balance_of (line 17) | def balance_of(account: str):

FILE: tests/integration/test_contracts/builtin_lib.s.py
  function hahaha (line 4) | def hahaha():
  function return_token (line 8) | def return_token():

FILE: tests/integration/test_contracts/child_test.s.py
  function get_value (line 2) | def get_value():

FILE: tests/integration/test_contracts/con_pass_hash.s.py
  function store (line 6) | def store(k: Any, v: Any):
  function get (line 10) | def get(k: Any):

FILE: tests/integration/test_contracts/construct_function_works.s.py
  function get (line 4) | def get():
  function seed (line 8) | def seed():

FILE: tests/integration/test_contracts/constructor_args_contract.s.py
  function seed (line 5) | def seed(a, b):
  function get (line 10) | def get():

FILE: tests/integration/test_contracts/contracting.s.py
  function hello (line 2) | def hello():

FILE: tests/integration/test_contracts/currency.s.py
  function seed (line 4) | def seed():
  function transfer (line 9) | def transfer(amount: int, to: str):
  function balance (line 21) | def balance(account: str):

FILE: tests/integration/test_contracts/dater.py
  function replicate (line 6) | def replicate(d: datetime.datetime):
  function subtract (line 11) | def subtract(d1: datetime.datetime, d2: datetime.datetime):

FILE: tests/integration/test_contracts/dynamic_import.py
  function called_from_a_far (line 2) | def called_from_a_far():

FILE: tests/integration/test_contracts/dynamic_import.s.py
  function import_thing (line 2) | def import_thing(name: str):

FILE: tests/integration/test_contracts/dynamic_importing.s.py
  function balance_for_token (line 2) | def balance_for_token(tok: str, account: str):
  function only_erc20 (line 7) | def only_erc20(tok: str, account: str):
  function is_erc20_compatible (line 14) | def is_erc20_compatible(tok: str):
  function enforce_erc20 (line 30) | def enforce_erc20(m):

FILE: tests/integration/test_contracts/erc20_clone.s.py
  function seed (line 5) | def seed():
  function transfer (line 11) | def transfer(amount: int, to: str):
  function balance_of (line 19) | def balance_of(account: str):
  function total_supply (line 23) | def total_supply():
  function allowance (line 27) | def allowance(owner: str, spender: str):
  function approve (line 31) | def approve(amount: str, to: str):
  function transfer_from (line 37) | def transfer_from(amount: int, to: str, main_account: str):

FILE: tests/integration/test_contracts/exception.py
  function seed (line 4) | def seed():
  function transfer (line 9) | def transfer(amount: int, to: str):
  function balance_of (line 19) | def balance_of(account: str):

FILE: tests/integration/test_contracts/float_issue.s.py
  function rand_vect (line 4) | def rand_vect():
  function dot_prod_grid (line 9) | def dot_prod_grid(x, y, vx, vy):
  function smootherstep (line 21) | def smootherstep(x):
  function interp (line 25) | def interp(x, a, b):
  function seed (line 30) | def seed():
  function get (line 34) | def get(x: float, y: float):

FILE: tests/integration/test_contracts/foreign_thing.s.py
  function read_H_hello (line 5) | def read_H_hello():
  function read_H_something (line 9) | def read_H_something():
  function read_V (line 13) | def read_V():
  function set_H (line 17) | def set_H(k: str, v: Any):
  function set_V (line 21) | def set_V(v: Any):

FILE: tests/integration/test_contracts/hashing_works.s.py
  function t_sha3 (line 2) | def t_sha3(s: str):
  function t_sha256 (line 6) | def t_sha256(s: str):

FILE: tests/integration/test_contracts/i_use_env.s.py
  function env_var (line 2) | def env_var():

FILE: tests/integration/test_contracts/import_test.s.py
  function woo (line 4) | def woo():

FILE: tests/integration/test_contracts/import_this.s.py
  function howdy (line 2) | def howdy():

FILE: tests/integration/test_contracts/importing_that.s.py
  function test (line 4) | def test():

FILE: tests/integration/test_contracts/inf_loop.s.py
  function seed (line 2) | def seed():
  function dummy (line 8) | def dummy():

FILE: tests/integration/test_contracts/json_tests.s.py
  function seed (line 4) | def seed():
  function get_some (line 8) | def get_some():

FILE: tests/integration/test_contracts/leaky.s.py
  function seed (line 5) | def seed():
  function transfer (line 11) | def transfer(amount: int, to: str):
  function balance_of (line 21) | def balance_of(account: str):

FILE: tests/integration/test_contracts/mathtime.s.py
  function seed (line 6) | def seed():
  function get_pi (line 11) | def get_pi():

FILE: tests/integration/test_contracts/modules/all_in_one.s.py
  function call_me (line 2) | def call_me():
  function call_me_again (line 6) | def call_me_again():
  function call_me_again_again (line 10) | def call_me_again_again():

FILE: tests/integration/test_contracts/modules/dynamic_import.s.py
  function called_from_a_far (line 2) | def called_from_a_far():
  function called_from_a_far_stacked (line 7) | def called_from_a_far_stacked():

FILE: tests/integration/test_contracts/modules/module1.s.py
  function get_context (line 19) | def get_context():

FILE: tests/integration/test_contracts/modules/module2.s.py
  function get_context (line 5) | def get_context():

FILE: tests/integration/test_contracts/modules/module3.s.py
  function get_context (line 5) | def get_context():

FILE: tests/integration/test_contracts/modules/module4.s.py
  function get_context (line 2) | def get_context():

FILE: tests/integration/test_contracts/modules/module5.s.py
  function get_context (line 4) | def get_context():

FILE: tests/integration/test_contracts/modules/module6.s.py
  function get_context (line 2) | def get_context():

FILE: tests/integration/test_contracts/modules/module7.s.py
  function get_context (line 2) | def get_context():

FILE: tests/integration/test_contracts/modules/module8.s.py
  function get_context (line 2) | def get_context():

FILE: tests/integration/test_contracts/orm_foreign_hash_contract.s.py
  function set_fh (line 4) | def set_fh(k: str, v: int):
  function get_fh (line 8) | def get_fh(k: str):

FILE: tests/integration/test_contracts/orm_foreign_key_contract.s.py
  function set_fv (line 4) | def set_fv(i: int):
  function get_fv (line 8) | def get_fv():

FILE: tests/integration/test_contracts/orm_hash_contract.s.py
  function set_h (line 4) | def set_h(k: str, v: int):
  function get_h (line 8) | def get_h(k: str):

FILE: tests/integration/test_contracts/orm_no_contract_access.s.py
  function set_c (line 4) | def set_c():

FILE: tests/integration/test_contracts/orm_variable_contract.s.py
  function set_v (line 4) | def set_v(i: int):
  function get_v (line 8) | def get_v():

FILE: tests/integration/test_contracts/owner_stuff.s.py
  function get_owner (line 2) | def get_owner(s: str):
  function owner_of_this (line 7) | def owner_of_this():

FILE: tests/integration/test_contracts/parent_test.s.py
  function get_val_from_child (line 2) | def get_val_from_child(s: str):

FILE: tests/integration/test_contracts/pass_hash.s.py
  function store_on_behalf (line 2) | def store_on_behalf(H: Any, k: Any, v: Any):

FILE: tests/integration/test_contracts/private_methods.s.py
  function call_private (line 4) | def call_private():
  function private (line 7) | def private():
  function set (line 11) | def set(k: str, v: int):
  function set_multi (line 15) | def set_multi(k: str, k2: str, k3: str, v: int):

FILE: tests/integration/test_contracts/stubucks.s.py
  function seed (line 5) | def seed():
  function transfer (line 11) | def transfer(amount: int, to: str):
  function balance_of (line 19) | def balance_of(account: str):
  function total_supply (line 23) | def total_supply():
  function allowance (line 27) | def allowance(owner: str, spender: str):
  function approve (line 31) | def approve(amount: int, to: str):
  function transfer_from (line 37) | def transfer_from(amount: int, to: str, main_account: str):

FILE: tests/integration/test_contracts/submission.s.py
  function submit_contract (line 2) | def submit_contract(name: str, code: str, owner: Any=None, constructor_a...
  function change_developer (line 20) | def change_developer(contract: str, new_developer: str):

FILE: tests/integration/test_contracts/tejastokens.s.py
  function seed (line 5) | def seed():
  function transfer (line 11) | def transfer(amount: int, to: str):
  function balance_of (line 19) | def balance_of(account: str):
  function total_supply (line 23) | def total_supply():
  function allowance (line 27) | def allowance(owner: str, spender: str):
  function approve (line 31) | def approve(amount: int, to: str):
  function transfer_from (line 37) | def transfer_from(amount: int, to: str, main_account: str):

FILE: tests/integration/test_contracts/thing.s.py
  function seed (line 5) | def seed():
  function nop (line 11) | def nop():

FILE: tests/integration/test_contracts/time.s.py
  function gt (line 4) | def gt():
  function lt (line 8) | def lt():
  function eq (line 12) | def eq():

FILE: tests/integration/test_contracts/time_storage.s.py
  function seed (line 4) | def seed():
  function get (line 8) | def get():

FILE: tests/integration/test_datetime_contracts.py
  class TestSenecaClientReplacesExecutor (line 6) | class TestSenecaClientReplacesExecutor(TestCase):
    method setUp (line 7) | def setUp(self):
    method tearDown (line 18) | def tearDown(self):
    method test_datetime_passed_argument_and_now_are_correctly_compared (line 21) | def test_datetime_passed_argument_and_now_are_correctly_compared(self):
    method test_datetime_passed_argument_and_now_are_correctly_compared_json (line 24) | def test_datetime_passed_argument_and_now_are_correctly_compared_json(...
    method test_datetime_subtracts (line 31) | def test_datetime_subtracts(self):

FILE: tests/integration/test_dynamic_imports.py
  class TestDynamicImports (line 6) | class TestDynamicImports(TestCase):
    method setUp (line 7) | def setUp(self):
    method tearDown (line 50) | def tearDown(self):
    method test_successful_submission (line 53) | def test_successful_submission(self):
    method test_get_stubuck_balances (line 63) | def test_get_stubuck_balances(self):
    method test_get_tejastokens_balances (line 70) | def test_get_tejastokens_balances(self):
    method test_get_bastardcoin_balances (line 77) | def test_get_bastardcoin_balances(self):
    method test_is_erc20 (line 84) | def test_is_erc20(self):
    method test_get_balances_erc20_enforced_stubucks (line 89) | def test_get_balances_erc20_enforced_stubucks(self):
    method test_get_balances_erc20_enforced_tejastokens (line 96) | def test_get_balances_erc20_enforced_tejastokens(self):
    method test_erc20_enforced_fails_for_bastardcoin (line 103) | def test_erc20_enforced_fails_for_bastardcoin(self):
    method test_owner_of_returns_default (line 107) | def test_owner_of_returns_default(self):
    method test_ctx_owner_works (line 119) | def test_ctx_owner_works(self):
    method test_incorrect_owner_prevents_function_call (line 130) | def test_incorrect_owner_prevents_function_call(self):
    method test_delegate_call_with_owner_works (line 141) | def test_delegate_call_with_owner_works(self):
    method test_delegate_with_wrong_owner_does_not_work (line 160) | def test_delegate_with_wrong_owner_does_not_work(self):

FILE: tests/integration/test_executor_submission_process.py
  function submission_kwargs_for_file (line 7) | def submission_kwargs_for_file(f):
  class TestExecutor (line 32) | class TestExecutor(TestCase):
    method setUp (line 33) | def setUp(self):
    method tearDown (line 48) | def tearDown(self):
    method test_submission (line 51) | def test_submission(self):
    method test_submission_then_function_call (line 72) | def test_submission_then_function_call(self):
    method test_kwarg_helper (line 91) | def test_kwarg_helper(self):
    method test_orm_variable_sets_in_contract (line 110) | def test_orm_variable_sets_in_contract(self):
    method test_orm_variable_gets_in_contract (line 123) | def test_orm_variable_gets_in_contract(self):
    method test_orm_variable_gets_and_sets_in_contract (line 135) | def test_orm_variable_gets_and_sets_in_contract(self):
    method test_orm_hash_sets_in_contract (line 148) | def test_orm_hash_sets_in_contract(self):
    method test_orm_hash_gets_in_contract (line 165) | def test_orm_hash_gets_in_contract(self):
    method test_orm_hash_gets_and_sets_in_contract (line 177) | def test_orm_hash_gets_and_sets_in_contract(self):
    method test_orm_foreign_variable_sets_in_contract_doesnt_work (line 194) | def test_orm_foreign_variable_sets_in_contract_doesnt_work(self):
    method test_orm_foreign_variable_gets_in_contract (line 215) | def test_orm_foreign_variable_gets_in_contract(self):
    method test_orm_foreign_hash_sets_in_contract_doesnt_work (line 232) | def test_orm_foreign_hash_sets_in_contract_doesnt_work(self):
    method test_orm_foreign_hash_gets_and_sets_in_contract (line 257) | def test_orm_foreign_hash_gets_and_sets_in_contract(self):
    method test_orm_contract_not_accessible (line 278) | def test_orm_contract_not_accessible(self):
    method test_construct_function_sets_properly (line 288) | def test_construct_function_sets_properly(self):
    method test_import_exported_function_works (line 300) | def test_import_exported_function_works(self):
    method test_arbitrary_environment_passing_works_via_executor (line 315) | def test_arbitrary_environment_passing_works_via_executor(self):
    method test_arbitrary_environment_passing_fails_if_not_passed_correctly (line 331) | def test_arbitrary_environment_passing_fails_if_not_passed_correctly(s...

FILE: tests/integration/test_executor_transaction_writes.py
  class TestTransactionWrites (line 8) | class TestTransactionWrites(TestCase):
    method setUp (line 9) | def setUp(self):
    method tearDown (line 22) | def tearDown(self):
    method test_transfers (line 25) | def test_transfers(self):

FILE: tests/integration/test_memory_clean_up_after_execution.py
  function submission_kwargs_for_file (line 11) | def submission_kwargs_for_file(f):
  class TestMetering (line 36) | class TestMetering(TestCase):
    method setUp (line 37) | def setUp(self):
    method tearDown (line 57) | def tearDown(self):

FILE: tests/integration/test_misc_contracts.py
  function too_many_writes (line 8) | def too_many_writes():
  function exploit (line 42) | def exploit():
  class TestMiscContracts (line 57) | class TestMiscContracts(TestCase):
    method setUp (line 58) | def setUp(self):
    method tearDown (line 91) | def tearDown(self):
    method test_H_values_return (line 94) | def test_H_values_return(self):
    method test_cant_modify_H (line 101) | def test_cant_modify_H(self):
    method test_cant_add_H (line 105) | def test_cant_add_H(self):
    method test_cant_set_V (line 109) | def test_cant_set_V(self):
    method test_V_returns (line 113) | def test_V_returns(self):
    method test_single_too_many_writes_fails (line 117) | def test_single_too_many_writes_fails(self):
    method test_multiple_too_many_writes_fails (line 124) | def test_multiple_too_many_writes_fails(self):
    method test_failed_once_doesnt_affect_others (line 132) | def test_failed_once_doesnt_affect_others(self):
    method test_memory_overload (line 141) | def test_memory_overload(self):
    method test_memory_overload2 (line 149) | def test_memory_overload2(self):
    method test_memory_exploit (line 157) | def test_memory_exploit(self):
  class TestPassHash (line 164) | class TestPassHash(TestCase):
    method setUp (line 165) | def setUp(self):
    method test_store_value (line 196) | def test_store_value(self):
  function some_test_contract (line 203) | def some_test_contract():
  function import_submission (line 209) | def import_submission():
  class TestDeveloperSubmission (line 222) | class TestDeveloperSubmission(TestCase):
    method setUp (line 223) | def setUp(self):
    method test_submit_sets_developer (line 236) | def test_submit_sets_developer(self):
    method test_change_developer_if_developer_works (line 243) | def test_change_developer_if_developer_works(self):
    method test_change_developer_prevents_new_change (line 254) | def test_change_developer_prevents_new_change(self):
    method test_cannot_import_submission (line 264) | def test_cannot_import_submission(self):
  function con_float_thing (line 273) | def con_float_thing():
  class TestFloatThing (line 285) | class TestFloatThing(TestCase):
    method setUp (line 286) | def setUp(self):
    method test_can_add (line 299) | def test_can_add(self):
  function a (line 305) | def a():
  function module_hack (line 310) | def module_hack():
  function class_var (line 319) | def class_var():
  function class_hash (line 326) | def class_hash():
  function exec_contract (line 333) | def exec_contract():
  function type_exploit (line 342) | def type_exploit():
  function con_test_one (line 369) | def con_test_one():
  function con_test_two (line 381) | def con_test_two():
  function test_closure (line 388) | def test_closure():
  function test_closure2 (line 401) | def test_closure2():
  class TestHackThing (line 416) | class TestHackThing(TestCase):
    method setUp (line 417) | def setUp(self):
    method test_can_add (line 430) | def test_can_add(self):
    method test_cant_submit_class_var (line 439) | def test_cant_submit_class_var(self):
    method test_cant_submit_class_hash (line 443) | def test_cant_submit_class_hash(self):
    method test_cant_submit_exec (line 447) | def test_cant_submit_exec(self):
    method test_cant_submit_type (line 451) | def test_cant_submit_type(self):
    method test_cant_clear_foreign_hash (line 455) | def test_cant_clear_foreign_hash(self):
    method test_no_closures (line 464) | def test_no_closures(self):
    method test_no_closures_work_around (line 468) | def test_no_closures_work_around(self):
  function con_test_fixed (line 473) | def con_test_fixed():
  class TestFixed (line 485) | class TestFixed(TestCase):
    method setUp (line 486) | def setUp(self):
    method test_can_multiply (line 499) | def test_can_multiply(self):

FILE: tests/integration/test_pixel_game.py
  function con_coin (line 5) | def con_coin():
  class TestCoinContract (line 71) | class TestCoinContract(TestCase):
    method setUp (line 72) | def setUp(self):
    method tearDown (line 79) | def tearDown(self):
    method test_coin_construction (line 82) | def test_coin_construction(self):
    method test_transfer_not_enough (line 85) | def test_transfer_not_enough(self):
    method test_transfer_enough (line 89) | def test_transfer_enough(self):
    method test_balance_of_works (line 93) | def test_balance_of_works(self):
    method test_total_supply_pre_mint (line 97) | def test_total_supply_pre_mint(self):
    method test_approve_modified_balances (line 101) | def test_approve_modified_balances(self):
    method test_allowance_returns_approve (line 105) | def test_allowance_returns_approve(self):
    method test_transfer_from_failure_not_enough_allowance (line 109) | def test_transfer_from_failure_not_enough_allowance(self):
    method test_transfer_from_failure_not_enough_in_main_account (line 114) | def test_transfer_from_failure_not_enough_in_main_account(self):
    method test_transfer_from_success_modified_balance_to_and_allowance (line 119) | def test_transfer_from_success_modified_balance_to_and_allowance(self):
    method test_mint_fails_if_not_owner (line 127) | def test_mint_fails_if_not_owner(self):
    method test_mint_succeeds_if_owner_and_modifies_balance_and_supply (line 131) | def test_mint_succeeds_if_owner_and_modifies_balance_and_supply(self):
    method test_change_ownership_modifies_owner (line 137) | def test_change_ownership_modifies_owner(self):
    method test_change_ownership_only_prior_owner (line 141) | def test_change_ownership_only_prior_owner(self):
    method test_change_ownership_then_mint_succeeds (line 145) | def test_change_ownership_then_mint_succeeds(self):
  function con_pixel_game (line 153) | def con_pixel_game():
  class TestPixelGame (line 216) | class TestPixelGame(TestCase):
    method setUp (line 217) | def setUp(self):
    method tearDown (line 225) | def tearDown(self):
    method test_init (line 228) | def test_init(self):

FILE: tests/integration/test_rich_ctx_calling.py
  function con_module1 (line 5) | def con_module1():
  function con_all_in_one (line 19) | def con_all_in_one():
  function con_dynamic_import (line 41) | def con_dynamic_import():
  function con_submission_name_test (line 63) | def con_submission_name_test():
  class TestRandomsContract (line 85) | class TestRandomsContract(TestCase):
    method setUp (line 86) | def setUp(self):
    method tearDown (line 96) | def tearDown(self):
    method test_ctx2 (line 99) | def test_ctx2(self):
    method test_multi_call_doesnt_affect_parameters (line 113) | def test_multi_call_doesnt_affect_parameters(self):
    method test_submission_name_in_construct_function (line 158) | def test_submission_name_in_construct_function(self):
    method test_entry_context (line 164) | def test_entry_context(self):

FILE: tests/integration/test_run_private_function.py
  class TestRunPrivateFunction (line 5) | class TestRunPrivateFunction(TestCase):
    method setUp (line 6) | def setUp(self):
    method tearDown (line 17) | def tearDown(self):
    method test_can_call_public_func (line 20) | def test_can_call_public_func(self):
    method test_cannot_call_private_func (line 23) | def test_cannot_call_private_func(self):
    method test_cannot_execute_private_func (line 27) | def test_cannot_execute_private_func(self):
    method test_can_call_private_func_if_run_private_function_called (line 36) | def test_can_call_private_func_if_run_private_function_called(self):
    method test_can_call_private_func_if_run_private_function_called_and_no_prefix (line 39) | def test_can_call_private_func_if_run_private_function_called_and_no_p...
    method test_can_call_private_but_then_not (line 42) | def test_can_call_private_but_then_not(self):

FILE: tests/integration/test_senecaCompiler_integration.py
  class TestSenecaCompiler (line 10) | class TestSenecaCompiler(TestCase):
    method test_visit_assign_variable (line 11) | def test_visit_assign_variable(self):
    method test_visit_assign_foreign_variable (line 27) | def test_visit_assign_foreign_variable(self):
    method test_assign_hash_variable (line 43) | def test_assign_hash_variable(self):
    method test_assign_foreign_hash (line 59) | def test_assign_foreign_hash(self):
    method test_private_function_prefixes_properly (line 90) | def test_private_function_prefixes_properly(self):
    method test_private_func_call_in_public_func_properly_renamed (line 102) | def test_private_func_call_in_public_func_properly_renamed(self):
    method test_private_func_call_in_other_private_functions (line 119) | def test_private_func_call_in_other_private_functions(self):
    method test_construct_renames_properly (line 142) | def test_construct_renames_properly(self):
    method test_token_contract_parses_correctly (line 160) | def test_token_contract_parses_correctly(self):
    method test_export_decorator_argument_is_added (line 171) | def test_export_decorator_argument_is_added(self):

FILE: tests/integration/test_seneca_client_randoms.py
  function con_random_contract (line 5) | def con_random_contract():
  class TestRandomsContract (line 64) | class TestRandomsContract(TestCase):
    method setUp (line 65) | def setUp(self):
    method tearDown (line 72) | def tearDown(self):
    method test_basic_shuffle (line 75) | def test_basic_shuffle(self):
    method test_basic_shuffle_different_with_different_seeds (line 81) | def test_basic_shuffle_different_with_different_seeds(self):
    method test_random_num_one_vs_two (line 87) | def test_random_num_one_vs_two(self):
    method test_random_range_int (line 116) | def test_random_range_int(self):
    method test_random_choice (line 127) | def test_random_choice(self):
    method test_auxiliary_salt (line 136) | def test_auxiliary_salt(self):

FILE: tests/integration/test_seneca_client_replaces_executor.py
  class TestSenecaClientReplacesExecutor (line 6) | class TestSenecaClientReplacesExecutor(TestCase):
    method setUp (line 7) | def setUp(self):
    method tearDown (line 38) | def tearDown(self):
    method test_initiate_not_enough_approved (line 41) | def test_initiate_not_enough_approved(self):
    method test_initiate_transfers_coins_correctly (line 50) | def test_initiate_transfers_coins_correctly(self):
    method test_initiate_writes_to_correct_key_and_properly (line 66) | def test_initiate_writes_to_correct_key_and_properly(self):
    method test_redeem_on_wrong_secret_fails (line 80) | def test_redeem_on_wrong_secret_fails(self):
    method test_redeem_on_wrong_sender_fails (line 91) | def test_redeem_on_wrong_sender_fails(self):
    method test_past_expiration_fails (line 101) | def test_past_expiration_fails(self):
    method test_successful_redeem_transfers_coins_correctly (line 116) | def test_successful_redeem_transfers_coins_correctly(self):
    method test_successful_redeem_deletes_entry (line 136) | def test_successful_redeem_deletes_entry(self):
    method test_refund_works (line 155) | def test_refund_works(self):
    method test_refund_too_early_fails (line 174) | def test_refund_too_early_fails(self):
    method test_refund_participant_is_signer_fails (line 188) | def test_refund_participant_is_signer_fails(self):
    method test_refund_fails_with_wrong_secret (line 203) | def test_refund_fails_with_wrong_secret(self):
    method test_refund_resets_swaps (line 218) | def test_refund_resets_swaps(self):

FILE: tests/integration/test_stamp_deduction.py
  function submission_kwargs_for_file (line 9) | def submission_kwargs_for_file(f):
  class TestMetering (line 34) | class TestMetering(TestCase):
    method setUp (line 35) | def setUp(self):
    method tearDown (line 55) | def tearDown(self):
    method test_simple_execution_deducts_stamps (line 58) | def test_simple_execution_deducts_stamps(self):
    method test_too_few_stamps_fails_and_deducts_properly (line 67) | def test_too_few_stamps_fails_and_deducts_properly(self):
    method test_adding_too_many_stamps_throws_error (line 81) | def test_adding_too_many_stamps_throws_error(self):
    method test_adding_all_stamps_with_infinate_loop_eats_all_balance (line 90) | def test_adding_all_stamps_with_infinate_loop_eats_all_balance(self):
    method test_submitting_contract_succeeds_with_enough_stamps (line 114) | def test_submitting_contract_succeeds_with_enough_stamps(self):
    method test_pending_writes_has_deducted_stamp_amount_prior_to_auto_commit (line 131) | def test_pending_writes_has_deducted_stamp_amount_prior_to_auto_commit...

FILE: tests/performance/prof_transfer.py
  function submission_kwargs_for_file (line 5) | def submission_kwargs_for_file(f):

FILE: tests/performance/test_contracts/erc20_clone.s.py
  function seed (line 5) | def seed():
  function transfer (line 11) | def transfer(amount: int, to: str):
  function balance_of (line 19) | def balance_of(account: str):
  function total_supply (line 23) | def total_supply():
  function allowance (line 27) | def allowance(owner: str, spender: str):
  function approve (line 31) | def approve(amount: str, to: str):
  function transfer_from (line 37) | def transfer_from(amount: int, to: str, main_account: str):

FILE: tests/performance/test_contracts/modules/all_in_one.s.py
  function call_me (line 2) | def call_me():
  function call_me_again (line 6) | def call_me_again():
  function call_me_again_again (line 10) | def call_me_again_again():

FILE: tests/performance/test_contracts/modules/dynamic_import.s.py
  function called_from_a_far (line 2) | def called_from_a_far():
  function called_from_a_far_stacked (line 7) | def called_from_a_far_stacked():

FILE: tests/performance/test_contracts/modules/module1.s.py
  function get_context (line 19) | def get_context():

FILE: tests/performance/test_contracts/modules/module2.s.py
  function get_context (line 5) | def get_context():

FILE: tests/performance/test_contracts/modules/module3.s.py
  function get_context (line 5) | def get_context():

FILE: tests/performance/test_contracts/modules/module4.s.py
  function get_context (line 2) | def get_context():

FILE: tests/performance/test_contracts/modules/module5.s.py
  function get_context (line 4) | def get_context():

FILE: tests/performance/test_contracts/modules/module6.s.py
  function get_context (line 2) | def get_context():

FILE: tests/performance/test_contracts/modules/module7.s.py
  function get_context (line 2) | def get_context():

FILE: tests/performance/test_contracts/modules/module8.s.py
  function get_context (line 2) | def get_context():

FILE: tests/performance/test_contracts/submission.s.py
  function submit_contract (line 2) | def submit_contract(name: str, code: str, owner: Any=None, constructor_a...
  function change_developer (line 20) | def change_developer(contract: str, new_developer: str):

FILE: tests/performance/test_transfer.py
  function submission_kwargs_for_file (line 7) | def submission_kwargs_for_file(f):
  class TestSandbox (line 32) | class TestSandbox(TestCase):
    method setUp (line 33) | def setUp(self):
    method tearDown (line 49) | def tearDown(self):
    method test_transfer_performance (line 52) | def test_transfer_performance(self):

FILE: tests/security/contracts/builtin_hack_token.s.py
  function seed (line 4) | def seed():
  function blah (line 9) | def blah():

FILE: tests/security/contracts/call_infinate_loop.s.py
  function call (line 4) | def call():

FILE: tests/security/contracts/con_inf_writes.s.py
  function seed (line 4) | def seed():
  function dummy (line 11) | def dummy():

FILE: tests/security/contracts/constructor_infinate_loop.s.py
  function seed (line 2) | def seed():
  function dummy (line 8) | def dummy():

FILE: tests/security/contracts/double_spend_gas_attack.s.py
  function seed (line 4) | def seed():
  function double_spend (line 8) | def double_spend(receiver: str):

FILE: tests/security/contracts/erc20_clone.s.py
  function seed (line 5) | def seed():
  function transfer (line 11) | def transfer(amount: int, to: str):
  function balance_of (line 19) | def balance_of(account: str):
  function total_supply (line 23) | def total_supply():
  function allowance (line 27) | def allowance(owner: str, spender: str):
  function approve (line 31) | def approve(amount: str, to: str):
  function transfer_from (line 37) | def transfer_from(amount: int, to: str, main_account: str):

FILE: tests/security/contracts/get_set_driver.py
  function seed (line 5) | def seed():
  function dummy (line 12) | def dummy():

FILE: tests/security/contracts/get_set_driver_2.py
  function seed (line 6) | def seed():
  function dummy (line 13) | def dummy():

FILE: tests/security/contracts/hack_tokens.s.py
  function seed (line 4) | def seed():
  function blah (line 9) | def blah():

FILE: tests/security/contracts/import_hash_from_contract.s.py
  function seed (line 4) | def seed():
  function dummy (line 8) | def dummy():

FILE: tests/security/contracts/infinate_loop.s.py
  function loop (line 2) | def loop():
  function eat_stamps (line 8) | def eat_stamps():

FILE: tests/security/contracts/submission.s.py
  function submit_contract (line 2) | def submit_contract(name: str, code: str, owner: Any=None, constructor_a...
  function change_developer (line 20) | def change_developer(contract: str, new_developer: str):

FILE: tests/security/test_erc20_token_hacks.py
  class TestTokenHacks (line 4) | class TestTokenHacks(TestCase):
    method setUp (line 5) | def setUp(self):
    method tearDown (line 29) | def tearDown(self):
    method test_orm_rename_hack (line 32) | def test_orm_rename_hack(self):
    method test_orm_setattr_hack (line 48) | def test_orm_setattr_hack(self):
    method test_double_spend_if_stamps_run_out (line 65) | def test_double_spend_if_stamps_run_out(self):
    method test_stamp_fails_when_calling_infinate_loop_from_another_contract (line 101) | def test_stamp_fails_when_calling_infinate_loop_from_another_contract(...
    method test_constructor_with_infinate_loop_fails (line 115) | def test_constructor_with_infinate_loop_fails(self):
    method test_infinate_loop_of_writes_undos_everything (line 121) | def test_infinate_loop_of_writes_undos_everything(self):
    method test_accessing_variable_on_another_contract (line 127) | def test_accessing_variable_on_another_contract(self):
    method test_get_set_driver (line 143) | def test_get_set_driver(self):
    method test_get_set_driver_2 (line 166) | def test_get_set_driver_2(self):

FILE: tests/unit/contracts/currency.s.py
  function seed (line 4) | def seed():
  function transfer (line 9) | def transfer(amount: int, to: str):
  function balance (line 21) | def balance(account: str):

FILE: tests/unit/contracts/exception.s.py
  function seed (line 4) | def seed():
  function transfer (line 9) | def transfer(amount: int, to: str):
  function balance_of (line 19) | def balance_of(account: str):

FILE: tests/unit/contracts/proxythis.py
  function proxythis (line 2) | def proxythis(con: str):
  function nestedproxythis (line 6) | def nestedproxythis(con: str):
  function noproxy (line 10) | def noproxy():

FILE: tests/unit/contracts/submission.s.py
  function submit_contract (line 2) | def submit_contract(name: str, code: str, owner: Any=None, constructor_a...
  function change_developer (line 20) | def change_developer(contract: str, new_developer: str):

FILE: tests/unit/contracts/thistest2.py
  function exported (line 2) | def exported():
  function getthis (line 6) | def getthis():
  function nested_exported (line 10) | def nested_exported():

FILE: tests/unit/precompiled/compiled_token.py
  class ctx (line 4) | class ctx:
  function ____ (line 11) | def ____():
  function transfer (line 16) | def transfer(amount, to):
  function balance_of (line 22) | def balance_of(account):
  function total_supply (line 25) | def total_supply():
  function allowance (line 28) | def allowance(owner, spender):
  function approve (line 31) | def approve(amount, to):
  function transfer_from (line 36) | def transfer_from(amount, to, main_account):
  function __private_func (line 46) | def __private_func():

FILE: tests/unit/precompiled/updated_submission.py
  function submit_contract (line 2) | def submit_contract(name: str, code: str, owner: Any=None, constructor_a...
  function change_developer (line 20) | def change_developer(contract: str, new_developer: str):

FILE: tests/unit/test_client.py
  class TestClient (line 7) | class TestClient(TestCase):
    method setUp (line 8) | def setUp(self):
    method tearDown (line 19) | def tearDown(self):
    method test_set_submission_updates_contract_file (line 23) | def test_set_submission_updates_contract_file(self):
    method test_can_create_instance_without_submission_contract (line 39) | def test_can_create_instance_without_submission_contract(self):
    method test_gets_submission_contract_from_state_if_no_filename_provided (line 45) | def test_gets_submission_contract_from_state_if_no_filename_provided(s...
    method test_set_submission_contract__sets_from_submission_filename_property (line 53) | def test_set_submission_contract__sets_from_submission_filename_proper...
    method test_set_submission_contract__sets_from_submission_from_state (line 69) | def test_set_submission_contract__sets_from_submission_from_state(self):
    method test_set_submission_contract__no_contract_provided_or_found_raises_AssertionError (line 88) | def test_set_submission_contract__no_contract_provided_or_found_raises...
    method test_submit__raises_AssertionError_if_no_submission_contract_set (line 97) | def test_submit__raises_AssertionError_if_no_submission_contract_set(s...

FILE: tests/unit/test_client_keys_prefix.py
  class TestClientKeysPrefix (line 5) | class TestClientKeysPrefix(unittest.TestCase):
    method setUp (line 7) | def setUp(self):
    method tearDown (line 29) | def tearDown(self):
    method test_keys_scoped_to_exact_contract (line 32) | def test_keys_scoped_to_exact_contract(self):

FILE: tests/unit/test_context_data_struct.py
  class TestContext (line 5) | class TestContext(TestCase):
    method test_get_state (line 6) | def test_get_state(self):
    method test_get_state_after_added_state (line 16) | def test_get_state_after_added_state(self):
    method test_pop_state_doesnt_fail_if_none_added (line 35) | def test_pop_state_doesnt_fail_if_none_added(self):
    method test_pop_state_removes_last_state (line 47) | def test_pop_state_removes_last_state(self):
    method test_add_state_doesnt_work_if_this_is_same (line 70) | def test_add_state_doesnt_work_if_this_is_same(self):
    method test_properties_read (line 89) | def test_properties_read(self):
    method test_properties_cant_be_written (line 102) | def test_properties_cant_be_written(self):

FILE: tests/unit/test_datetime.py
  class TestDatetime (line 7) | class TestDatetime(TestCase):
    method test_datetime_variables_set (line 8) | def test_datetime_variables_set(self):
    method test_datetime_eq_true (line 24) | def test_datetime_eq_true(self):
    method test_datetime_eq_false (line 32) | def test_datetime_eq_false(self):
    method test_datetime_ne_false (line 44) | def test_datetime_ne_false(self):
    method test_datetime_ne_true (line 52) | def test_datetime_ne_true(self):
    method test_datetime_lt_true (line 64) | def test_datetime_lt_true(self):
    method test_datetime_lt_false (line 73) | def test_datetime_lt_false(self):
    method test_datetime_gt_true (line 85) | def test_datetime_gt_true(self):
    method test_datetime_gt_false (line 94) | def test_datetime_gt_false(self):
    method test_datetime_ge_true_g (line 106) | def test_datetime_ge_true_g(self):
    method test_datetime_ge_true_eq (line 115) | def test_datetime_ge_true_eq(self):
    method test_datetime_ge_false_g (line 123) | def test_datetime_ge_false_g(self):
    method test_datetime_le_true (line 135) | def test_datetime_le_true(self):
    method test_datetime_le_true_eq (line 144) | def test_datetime_le_true_eq(self):
    method test_datetime_le_false (line 152) | def test_datetime_le_false(self):
    method test_datetime_subtraction_to_proper_timedelta (line 161) | def test_datetime_subtraction_to_proper_timedelta(self):
    method test_datetime_strptime (line 168) | def test_datetime_strptime(self):
    method test_datetime_strptime_invalid_format (line 173) | def test_datetime_strptime_invalid_format(self):
    method test_datetime_strptime_invalid_date (line 178) | def test_datetime_strptime_invalid_date(self):
    method test_datetime_strptime_invalid_date_format (line 183) | def test_datetime_strptime_invalid_date_format(self):
    method test_datetime_returns_correct_datetime_cls (line 188) | def test_datetime_returns_correct_datetime_cls(self):

FILE: tests/unit/test_decimal.py
  class TestDecimal (line 10) | class TestDecimal(TestCase):
    method test_init (line 11) | def test_init(self):
    method test_init_float (line 14) | def test_init_float(self):
    method test_init_int (line 17) | def test_init_int(self):
    method test_bool_true (line 20) | def test_bool_true(self):
    method test_bool_false (line 23) | def test_bool_false(self):
    method test_eq_whole_numbers (line 26) | def test_eq_whole_numbers(self):
    method test_eq_floats (line 29) | def test_eq_floats(self):
    method test_lt (line 32) | def test_lt(self):
    method test_lte (line 36) | def test_lte(self):
    method test_gt (line 41) | def test_gt(self):
    method test_gte (line 45) | def test_gte(self):
    method test_str (line 50) | def test_str(self):
    method test_neg (line 54) | def test_neg(self):
    method test_pos (line 57) | def test_pos(self):
    method test_other_equality (line 60) | def test_other_equality(self):
    method test_abs (line 64) | def test_abs(self):
    method test_add (line 68) | def test_add(self):
    method test_arbitrarily_large_number (line 74) | def test_arbitrarily_large_number(self):
    method test_zero_equality (line 81) | def test_zero_equality(self):
    method test_sub (line 84) | def test_sub(self):
    method test_add_negs (line 90) | def test_add_negs(self):
    method test_radd (line 93) | def test_radd(self):
    method test_rsub (line 99) | def test_rsub(self):
    method test_mul (line 105) | def test_mul(self):
    method test_rmul (line 111) | def test_rmul(self):
    method test_div (line 117) | def test_div(self):
    method test_div_large_decimals (line 121) | def test_div_large_decimals(self):
    method test_fix_precision_cuts_too_low (line 129) | def test_fix_precision_cuts_too_low(self):
    method test_fix_precision_cuts_too_high (line 135) | def test_fix_precision_cuts_too_high(self):
    method test_fix_precision_doesnt_cut_high (line 139) | def test_fix_precision_doesnt_cut_high(self):
    method test_fix_precision_cuts_all_decimals_if_too_high (line 143) | def test_fix_precision_cuts_all_decimals_if_too_high(self):
    method test_fix_precision_cuts_decimals_if_high_but_not_too_high (line 147) | def test_fix_precision_cuts_decimals_if_high_but_not_too_high(self):
    method test_contracting_decimal_can_round (line 153) | def test_contracting_decimal_can_round(self):
    method test_sci_not_whole_number (line 157) | def test_sci_not_whole_number(self):
    method test_sci_not_decimal (line 163) | def test_sci_not_decimal(self):
    method test_sci_not_e0 (line 169) | def test_sci_not_e0(self):
    method test_sci_not_extra_precision (line 175) | def test_sci_not_extra_precision(self):

FILE: tests/unit/test_driver_tombstones.py
  class TestDriverTombstones (line 5) | class TestDriverTombstones(unittest.TestCase):
    method setUp (line 7) | def setUp(self):
    method tearDown (line 11) | def tearDown(self):
    method test_items_excludes_pending_deletes (line 14) | def test_items_excludes_pending_deletes(self):

FILE: tests/unit/test_encode.py
  class TestEncode (line 8) | class TestEncode(TestCase):
    method test_int_to_bytes (line 9) | def test_int_to_bytes(self):
    method test_str_to_bytes (line 15) | def test_str_to_bytes(self):
    method test_dec_to_bytes (line 21) | def test_dec_to_bytes(self):
    method test_decode_bytes_to_int (line 27) | def test_decode_bytes_to_int(self):
    method test_decode_bytes_to_str (line 33) | def test_decode_bytes_to_str(self):
    method test_decode_bytes_to_dec (line 39) | def test_decode_bytes_to_dec(self):
    method test_decode_failure (line 46) | def test_decode_failure(self):
    method test_date_encode (line 51) | def test_date_encode(self):
    method test_date_decode (line 58) | def test_date_decode(self):
    method test_timedelta_encode (line 65) | def test_timedelta_encode(self):
    method test_timedelta_decode (line 72) | def test_timedelta_decode(self):
    method test_int_encode (line 79) | def test_int_encode(self):
    method test_int_decode (line 84) | def test_int_decode(self):
    method test_bigint_encode (line 89) | def test_bigint_encode(self):
    method test_bigint_decode (line 96) | def test_bigint_decode(self):
    method test_encode_ints_nested_list (line 101) | def test_encode_ints_nested_list(self):
    method test_encode_dict_with_list_containing_different_types (line 107) | def test_encode_dict_with_list_containing_different_types(self):
    method test_encode_ints_nested_dict (line 113) | def test_encode_ints_nested_dict(self):
    method test_safe_repr_non_object (line 119) | def test_safe_repr_non_object(self):
    method test_safe_repr_arbitrary_object (line 125) | def test_safe_repr_arbitrary_object(self):
    method test_safe_repr_decimal_object (line 134) | def test_safe_repr_decimal_object(self):
    method test_safe_repr_decimal_object_different_not_equal (line 140) | def test_safe_repr_decimal_object_different_not_equal(self):
    method test_safe_repr_assertion_error_string (line 146) | def test_safe_repr_assertion_error_string(self):
    method test_contracting_decimal (line 152) | def test_contracting_decimal(self):
    method test_decode_fixed_trailing_doesnt_get_rid_of_zeros_properly (line 158) | def test_decode_fixed_trailing_doesnt_get_rid_of_zeros_properly(self):
    method test_encoding_fixed_trailing_zeros (line 163) | def test_encoding_fixed_trailing_zeros(self):
    method test_convert_returns_normal_dict (line 170) | def test_convert_returns_normal_dict(self):
    method test_convert_bigint (line 179) | def test_convert_bigint(self):
    method test_convert_contracting_decimal (line 185) | def test_convert_contracting_decimal(self):
    method test_convert_contracting_datetime (line 198) | def test_convert_contracting_datetime(self):
    method test_convert_contracting_timedelta (line 219) | def test_convert_contracting_timedelta(self):
    method test_convert_contracting_bytes (line 232) | def test_convert_contracting_bytes(self):
    method test_multiple_conversions (line 245) | def test_multiple_conversions(self):
    method test_nested_dictionaries (line 278) | def test_nested_dictionaries(self):
    method test_lists (line 309) | def test_lists(self):

FILE: tests/unit/test_imports_stdlib.py
  class TestImports (line 7) | class TestImports(TestCase):
    method setUp (line 8) | def setUp(self):
    method test_func_correct_type (line 26) | def test_func_correct_type(self):
    method test_func_incorrect_name (line 34) | def test_func_incorrect_name(self):
    method test_func_incorrect_args (line 42) | def test_func_incorrect_args(self):
    method test_func_correct_with_kwargs (line 50) | def test_func_correct_with_kwargs(self):
    method test_func_correct_with_annotations (line 58) | def test_func_correct_with_annotations(self):
    method test_func_correct_with_kwargs_and_annotations (line 66) | def test_func_correct_with_kwargs_and_annotations(self):
    method test_func_correct_private (line 74) | def test_func_correct_private(self):
    method test_func_false_private (line 82) | def test_func_false_private(self):
    method test_var_fails_if_type_not_of_datum (line 90) | def test_var_fails_if_type_not_of_datum(self):
    method test_enforce_interface_works_all_public_funcs (line 94) | def test_enforce_interface_works_all_public_funcs(self):
    method test_enforce_interface_works_on_subset_funcs (line 106) | def test_enforce_interface_works_on_subset_funcs(self):
    method test_enforce_interface_fails_on_wrong_funcs (line 117) | def test_enforce_interface_fails_on_wrong_funcs(self):
    method test_enforce_interface_on_resources (line 128) | def test_enforce_interface_on_resources(self):
    method test_complete_enforcement (line 136) | def test_complete_enforcement(self):
    method test_private_function_enforcement (line 150) | def test_private_function_enforcement(self):
    method test_complete_enforcement_with_private_func (line 157) | def test_complete_enforcement_with_private_func(self):

FILE: tests/unit/test_linter.py
  class TestLinter (line 7) | class TestLinter(TestCase):
    method setUp (line 8) | def setUp(self):
    method test_linter (line 11) | def test_linter(self):
    method test_good_ast_type (line 32) | def test_good_ast_type(self):
    method test_bad_ast_type (line 47) | def test_bad_ast_type(self):
    method test_not_system_variable (line 54) | def test_not_system_variable(self):
    method test_system_variable (line 60) | def test_system_variable(self):
    method test_not_system_variable_ast (line 70) | def test_not_system_variable_ast(self):
    method test_not_system_variable_ast_success (line 83) | def test_not_system_variable_ast_success(self):
    method test_visit_async_func_def_fail_code (line 103) | def test_visit_async_func_def_fail_code(self):
    method test_visit_class_fail_code (line 128) | def test_visit_class_fail_code(self):
    method test_visit_try_except_fail_code (line 141) | def test_visit_try_except_fail_code(self):
    method test_accessing_system_vars (line 156) | def test_accessing_system_vars(self):
    method test_accessing_attribute (line 169) | def test_accessing_attribute(self):
    method test_no_nested_imports (line 185) | def test_no_nested_imports(self):
    method test_no_nested_imports_works (line 197) | def test_no_nested_imports_works(self):
    method test_augassign (line 211) | def test_augassign(self):
    method test_no_import_from (line 224) | def test_no_import_from(self):
    method test_final_checks_set_properly (line 256) | def test_final_checks_set_properly(self):
    method test_collect_function_defs (line 269) | def test_collect_function_defs(self):
    method test_assignment_of_import (line 292) | def test_assignment_of_import(self):
    method test_good_orm_initialization (line 306) | def test_good_orm_initialization(self):
    method test_bad_orm_initialization (line 318) | def test_bad_orm_initialization(self):
    method test_multi_targets_orm_fails (line 330) | def test_multi_targets_orm_fails(self):
    method test_multi_decorator_fails (line 344) | def test_multi_decorator_fails(self):
    method test_invalid_decorator_fails (line 356) | def test_invalid_decorator_fails(self):
    method test_multiple_constructors_fails (line 367) | def test_multiple_constructors_fails(self):
    method test_function_str_annotation (line 388) | def test_function_str_annotation(self):
    method test_function_dict_annotation (line 399) | def test_function_dict_annotation(self):
    method test_function_bad_annotation (line 410) | def test_function_bad_annotation(self):
    method test_function_none_annotation (line 422) | def test_function_none_annotation(self):
    method test_none_return_annotation (line 434) | def test_none_return_annotation(self):
    method test_contract_annotation (line 446) | def test_contract_annotation(self):
    method test_violations_sorted_by_line_number (line 477) | def test_violations_sorted_by_line_number(self):

FILE: tests/unit/test_module.py
  class TestDatabase (line 8) | class TestDatabase(TestCase):
    method setUp (line 9) | def setUp(self):
    method tearDown (line 13) | def tearDown(self):
    method test_push_and_get_contract (line 16) | def test_push_and_get_contract(self):
    method test_flush (line 25) | def test_flush(self):
  class TestDatabaseLoader (line 36) | class TestDatabaseLoader(TestCase):
    method setUp (line 37) | def setUp(self):
    method test_init (line 40) | def test_init(self):
    method test_create_module (line 43) | def test_create_module(self):
    method test_exec_module (line 46) | def test_exec_module(self):
    method test_exec_module_nonattribute (line 55) | def test_exec_module_nonattribute(self):
    method test_module_representation (line 65) | def test_module_representation(self):
  class TestInstallLoader (line 71) | class TestInstallLoader(TestCase):
    method test_install_loader (line 72) | def test_install_loader(self):
    method test_integration_and_importing (line 85) | def test_integration_and_importing(self):
  class TestModuleLoadingIntegration (line 102) | class TestModuleLoadingIntegration(TestCase):
    method setUp (line 103) | def setUp(self):
    method tearDown (line 119) | def tearDown(self):
    method test_get_code_string (line 123) | def test_get_code_string(self):

FILE: tests/unit/test_new_driver.py
  class TestDriver (line 7) | class TestDriver(unittest.TestCase):
    method setUp (line 9) | def setUp(self):
    method tearDown (line 14) | def tearDown(self):
    method test_set_and_get (line 18) | def test_set_and_get(self):
    method test_find (line 26) | def test_find(self):
    method test_keys_from_disk (line 34) | def test_keys_from_disk(self):
    method test_iter_from_disk (line 45) | def test_iter_from_disk(self):
    method test_items (line 59) | def test_items(self):
    method test_delete_key_from_disk (line 68) | def test_delete_key_from_disk(self):
    method test_flush_cache (line 77) | def test_flush_cache(self):
    method test_flush_disk (line 84) | def test_flush_disk(self):
    method test_commit (line 92) | def test_commit(self):
    method test_get_all_contract_state (line 100) | def test_get_all_contract_state(self):
    method test_transaction_writes (line 109) | def test_transaction_writes(self):
    method test_clear_transaction_writes (line 118) | def test_clear_transaction_writes(self):
    method test_get_run_state (line 127) | def test_get_run_state(self):

FILE: tests/unit/test_orm.py
  class TestDatum (line 17) | class TestDatum(TestCase):
    method setUp (line 18) | def setUp(self):
    method tearDown (line 21) | def tearDown(self):
    method test_init (line 24) | def test_init(self):
  class TestVariable (line 29) | class TestVariable(TestCase):
    method setUp (line 30) | def setUp(self):
    method tearDown (line 33) | def tearDown(self):
    method test_set (line 37) | def test_set(self):
    method test_get (line 49) | def test_get(self):
    method test_set_get (line 62) | def test_set_get(self):
    method test_default_value (line 73) | def test_default_value(self):
    method test_mutable_default_is_copied (line 86) | def test_mutable_default_is_copied(self):
  class TestHash (line 96) | class TestHash(TestCase):
    method setUp (line 97) | def setUp(self):
    method tearDown (line 100) | def tearDown(self):
    method test_set (line 103) | def test_set(self):
    method test_get (line 119) | def test_get(self):
    method test_set_get (line 133) | def test_set_get(self):
    method test_setitem (line 149) | def test_setitem(self):
    method test_getitem (line 164) | def test_getitem(self):
    method test_setitems (line 179) | def test_setitems(self):
    method test_setitem_delimiter_illegal (line 191) | def test_setitem_delimiter_illegal(self):
    method test_setitems_too_many_dimensions_fails (line 199) | def test_setitems_too_many_dimensions_fails(self):
    method test_setitems_key_too_large (line 208) | def test_setitems_key_too_large(self):
    method test_setitem_value_too_large (line 219) | def test_setitem_value_too_large(self):
    method test_setitems_keys_too_large (line 222) | def test_setitems_keys_too_large(self):
    method test_getitems_keys (line 235) | def test_getitems_keys(self):
    method test_getsetitems (line 252) | def test_getsetitems(self):
    method test_getitems_keys_too_large (line 265) | def test_getitems_keys_too_large(self):
    method test_getitems_too_many_dimensions_fails (line 278) | def test_getitems_too_many_dimensions_fails(self):
    method test_getitems_key_too_large (line 287) | def test_getitems_key_too_large(self):
    method test_getitem_returns_default_value_if_none (line 298) | def test_getitem_returns_default_value_if_none(self):
    method test_get_all_when_none_exist (line 306) | def test_get_all_when_none_exist(self):
    method test_get_all_after_setting (line 314) | def test_get_all_after_setting(self):
    method test_items_returns_kv_pairs (line 332) | def test_items_returns_kv_pairs(self):
    method test_items_multi_hash_returns_kv_pairs (line 354) | def test_items_multi_hash_returns_kv_pairs(self):
    method test_items_multi_hash_returns_all (line 380) | def test_items_multi_hash_returns_all(self):
    method test_items_clear_deletes_only_multi_hash (line 409) | def test_items_clear_deletes_only_multi_hash(self):
    method test_all_multihash_returns_values (line 439) | def test_all_multihash_returns_values(self):
    method test_multihash_multiple_dims_clear_behaves_similar_to_single_dim (line 462) | def test_multihash_multiple_dims_clear_behaves_similar_to_single_dim(s...
    method test_multihash_multiple_dims_all_gets_items_similar_to_single_dim (line 492) | def test_multihash_multiple_dims_all_gets_items_similar_to_single_dim(...
    method test_clear_items_deletes_all_key_value_pairs (line 513) | def test_clear_items_deletes_all_key_value_pairs(self):
  class TestForeignVariable (line 544) | class TestForeignVariable(TestCase):
    method setUp (line 545) | def setUp(self):
    method tearDown (line 548) | def tearDown(self):
    method test_set (line 551) | def test_set(self):
    method test_get (line 563) | def test_get(self):
  class TestForeignHash (line 580) | class TestForeignHash(TestCase):
    method setUp (line 581) | def setUp(self):
    method tearDown (line 584) | def tearDown(self):
    method test_set (line 588) | def test_set(self):
    method test_get (line 601) | def test_get(self):
    method test_setitem (line 616) | def test_setitem(self):
    method test_getitem (line 629) | def test_getitem(self):
  class TestLogEvent (line 648) | class TestLogEvent(TestCase):
    method setUp (line 650) | def setUp(self):
    method test_log_event (line 665) | def test_log_event(self):
    method test_log_event_with_max_indexed_args (line 687) | def test_log_event_with_max_indexed_args(self):
    method test_log_event_with_too_many_indexed_args (line 710) | def test_log_event_with_too_many_indexed_args(self):
    method test_write_event_success (line 737) | def test_write_event_success(self):
    method test_write_event_missing_argument (line 750) | def test_write_event_missing_argument(self):
    method test_write_event_wrong_type (line 762) | def test_write_event_wrong_type(self):
    method test_write_event_with_empty_data (line 776) | def test_write_event_with_empty_data(self):
    method test_write_event_with_none (line 785) | def test_write_event_with_none(self):
    method test_write_event_with_invalid_argument_names (line 794) | def test_write_event_with_invalid_argument_names(self):
  class TestLogEventBoundaryIndexedArgs (line 818) | class TestLogEventBoundaryIndexedArgs(TestCase):
    method setUp (line 819) | def setUp(self):
    method test_log_event_with_exactly_three_indexed_args (line 825) | def test_log_event_with_exactly_three_indexed_args(self):
    method test_log_event_with_more_than_three_indexed_args (line 837) | def test_log_event_with_more_than_three_indexed_args(self):
  class TestLogEventTypeEnforcementFuzz (line 855) | class TestLogEventTypeEnforcementFuzz(TestCase):
    method setUp (line 856) | def setUp(self):
    method random_string (line 867) | def random_string(self, length=10):
    method test_write_event_with_random_data (line 870) | def test_write_event_with_random_data(self):
    method test_write_event_with_random_structures (line 884) | def test_write_event_with_random_structures(self):
    method test_write_event_with_random_numeric_types (line 900) | def test_write_event_with_random_numeric_types(self):
  class TestLogEventInvalidArgumentNames (line 921) | class TestLogEventInvalidArgumentNames(TestCase):
    method setUp (line 922) | def setUp(self):
    method test_write_event_with_invalid_argument_names (line 933) | def test_write_event_with_invalid_argument_names(self):
  class TestLogEventLargeData (line 947) | class TestLogEventLargeData(TestCase):
    method setUp (line 948) | def setUp(self):
    method test_write_event_with_large_data (line 959) | def test_write_event_with_large_data(self):
  class TestLogEventInvalidDataTypes (line 984) | class TestLogEventInvalidDataTypes(TestCase):
    method setUp (line 985) | def setUp(self):
    method test_write_event_with_invalid_string_type (line 996) | def test_write_event_with_invalid_string_type(self):
    method test_write_event_with_invalid_numeric_type (line 1010) | def test_write_event_with_invalid_numeric_type(self):
    method test_write_event_with_unexpected_object_type (line 1024) | def test_write_event_with_unexpected_object_type(self):
  class TestLogEventNonStandardTypes (line 1038) | class TestLogEventNonStandardTypes(TestCase):
    method setUp (line 1039) | def setUp(self):
    method test_log_event_with_non_standard_type (line 1045) | def test_log_event_with_non_standard_type(self):
    method test_log_event_with_custom_object_type (line 1059) | def test_log_event_with_custom_object_type(self):

FILE: tests/unit/test_parser.py
  class TestParser (line 6) | class TestParser(TestCase):
    method setUp (line 7) | def setUp(self):
    method test_methods_for_contract_single_function (line 10) | def test_methods_for_contract_single_function(self):
    method test_methods_for_contract_datetime (line 37) | def test_methods_for_contract_datetime(self):
    method test_methods_for_contract_multiple_functions_and_privates (line 64) | def test_methods_for_contract_multiple_functions_and_privates(self):
    method test_variables_for_contract_passes_election_house (line 112) | def test_variables_for_contract_passes_election_house(self):
    method test_variables_for_contract_multiple_variables (line 170) | def test_variables_for_contract_multiple_variables(self):
    method test_variables_for_contract_multiple_hashes (line 192) | def test_variables_for_contract_multiple_hashes(self):
    method test_variables_mix (line 214) | def test_variables_mix(self):

FILE: tests/unit/test_revert_on_exception.py
  function submission_kwargs_for_file (line 20) | def submission_kwargs_for_file(f):
  class MyTestCase (line 43) | class MyTestCase(unittest.TestCase):
    method setUp (line 45) | def setUp(self):
    method test_exception (line 79) | def test_exception(self):
    method test_non_exception (line 97) | def test_non_exception(self):

FILE: tests/unit/test_runtime.py
  class TestRuntime (line 8) | class TestRuntime(TestCase):
    method tearDown (line 9) | def tearDown(self):
    method test_tracer_works_roughly (line 13) | def test_tracer_works_roughly(self):
    method test_tracer_bypass_records_no_stamps (line 25) | def test_tracer_bypass_records_no_stamps(self):
    method test_arbitrary_modification_of_stamps_works (line 35) | def test_arbitrary_modification_of_stamps_works(self):
    method test_starting_and_stopping_tracer_works_roughly (line 50) | def test_starting_and_stopping_tracer_works_roughly(self):
    method test_modifying_stamps_during_tracing (line 73) | def test_modifying_stamps_during_tracing(self):
    method test_add_exists (line 100) | def test_add_exists(self):
    method test_deduct_write_adjusts_total_writes (line 113) | def test_deduct_write_adjusts_total_writes(self):
    method test_deduct_write_fails_if_too_many_writes (line 126) | def test_deduct_write_fails_if_too_many_writes(self):

FILE: tests/unit/test_state_management.py
  class MyTestCase (line 8) | class MyTestCase(unittest.TestCase):
    method setUp (line 10) | def setUp(self):
    method deploy_broken_stuff (line 26) | def deploy_broken_stuff(self):
    method test_submit (line 53) | def test_submit(self):

FILE: tests/unit/test_stdlib_hashing.py
  class TestHashing (line 5) | class TestHashing(TestCase):
    method test_sha3 (line 6) | def test_sha3(self):
    method test_sha256 (line 12) | def test_sha256(self):

FILE: tests/unit/test_sys_contracts/bad_lint.s.py
  function no_exports (line 1) | def no_exports():

FILE: tests/unit/test_sys_contracts/compile_this.s.py
  function good_function (line 2) | def good_function():
  function another_function (line 5) | def another_function():

FILE: tests/unit/test_sys_contracts/currency.s.py
  function seed (line 7) | def seed():
  function assert_stamps (line 25) | def assert_stamps(stamps):
  function submit_stamps (line 30) | def submit_stamps(stamps):
  function transfer (line 37) | def transfer(to, amount):
  function approve (line 45) | def approve(spender, amount):
  function transfer_from (line 49) | def transfer_from(approver, spender, amount):

FILE: tests/unit/test_sys_contracts/good_lint.s.py
  function exports (line 2) | def exports():

FILE: tests/unit/test_sys_contracts/module_func.py
  function seed (line 5) | def seed():
  function test_func (line 10) | def test_func(status=None):
  function test_keymod (line 14) | def test_keymod(deduct):

FILE: tests/unit/test_timedelta.py
  class TestTimedelta (line 7) | class TestTimedelta(TestCase):
    method test_implementation_mimics_actual_timedelta (line 8) | def test_implementation_mimics_actual_timedelta(self):
    method test_constants_work (line 14) | def test_constants_work(self):
    method test_eq_true (line 21) | def test_eq_true(self):
    method test_eq_false (line 27) | def test_eq_false(self):
    method test_gt_true (line 33) | def test_gt_true(self):
    method test_gt_false (line 39) | def test_gt_false(self):
    method test_ge_true (line 45) | def test_ge_true(self):
    method test_ge_false (line 51) | def test_ge_false(self):
    method test_ge_true_eq (line 57) | def test_ge_true_eq(self):
    method test_lt_true (line 63) | def test_lt_true(self):
    method test_lt_false (line 69) | def test_lt_false(self):
    method test_le_true (line 75) | def test_le_true(self):
    method test_le_false (line 81) | def test_le_false(self):
    method test_le_true_eq (line 87) | def test_le_true_eq(self):
    method test_ne_true (line 93) | def test_ne_true(self):
    method test_ne_false (line 99) | def test_ne_false(self):
    method test_addition_works_days (line 105) | def test_addition_works_days(self):
    method test_addition_works_seconds (line 113) | def test_addition_works_seconds(self):
    method test_addition_works_days_and_seconds (line 121) | def test_addition_works_days_and_seconds(self):
    method test_subtraction_works_days (line 129) | def test_subtraction_works_days(self):
    method test_subtraction_works_seconds (line 137) | def test_subtraction_works_seconds(self):
    method test_subtraction_works_days_and_seconds (line 145) | def test_subtraction_works_days_and_seconds(self):
    method test_multiplication_works (line 153) | def test_multiplication_works(self):
    method test_multiplication_works_seconds (line 161) | def test_multiplication_works_seconds(self):
    method test_multiplication_works_days_and_seconds (line 169) | def test_multiplication_works_days_and_seconds(self):
    method test_addition_not_implemented (line 179) | def test_addition_not_implemented(self):
    method test_subtraction_not_implemented (line 183) | def test_subtraction_not_implemented(self):
    method test_multiplication_with_int_works (line 187) | def test_multiplication_with_int_works(self):
    method test_multiplication_does_not_work_with_decimal (line 191) | def test_multiplication_does_not_work_with_decimal(self):
    method test_get_seconds_works (line 195) | def test_get_seconds_works(self):
    method test_get_minutes_works (line 206) | def test_get_minutes_works(self):
    method test_get_hours_works (line 217) | def test_get_hours_works(self):
    method test_get_days_works (line 228) | def test_get_days_works(self):
    method test_get_weeks_works (line 239) | def test_get_weeks_works(self):
    method test_larger_components_returns_as_expected (line 250) | def test_larger_components_returns_as_expected(self):
    method test_adding_timedelta_to_datetime_returns_correct (line 262) | def test_adding_timedelta_to_datetime_returns_correct(self):
    method test_subtracting_timedelta_to_datetime_returns_correct (line 269) | def test_subtracting_timedelta_to_datetime_returns_correct(self):
Condensed preview — 195 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (511K chars).
[
  {
    "path": ".github/ISSUE_TEMPLATE/bug_report.md",
    "chars": 834,
    "preview": "---\nname: Bug report\nabout: Create a report to help us improve\ntitle: ''\nlabels: ''\nassignees: ''\n\n---\n\n**Describe the b"
  },
  {
    "path": ".github/PULL_REQUEST_TEMPLATE.md",
    "chars": 675,
    "preview": "## Description\n\nPlease add a brief description of the feature / change / bug-fix you want to merge.\n\n## Type of change\n\n"
  },
  {
    "path": ".github/dependabot.yml",
    "chars": 316,
    "preview": "version: 2\nupdates:\n  - package-ecosystem: \"pip\" # Type of package ecosystem (e.g., \"npm\", \"maven\")\n    directory: \"/\" #"
  },
  {
    "path": ".github/workflows/publish.yml",
    "chars": 834,
    "preview": "name: Publish to PyPI and GitHub Release\n\non:\n  push:\n    tags:\n      - 'v*'  # Trigger on version tags\n\njobs:\n  build-a"
  },
  {
    "path": ".gitignore",
    "chars": 429,
    "preview": "# Python\n__pycache__/\n*.py[cod]\n*$py.class\n*.so\n.Python\nbuild/\ndevelop-eggs/\ndist/\ndownloads/\neggs/\n.eggs/\nlib/\nlib64/\np"
  },
  {
    "path": "LICENSE",
    "chars": 325,
    "preview": "Creative Commons Attribution‑NonCommercial 4.0 International\n\nCopyright © 2025 XIAN.org\n\nThis work is licensed under CC "
  },
  {
    "path": "README.md",
    "chars": 5665,
    "preview": "# Xian Contracting\n\nXian Contracting is a Python-based smart contract development and execution framework. Unlike tradit"
  },
  {
    "path": "examples/01 A very simple Counter contract.ipynb",
    "chars": 3813,
    "preview": "{\n \"cells\": [\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"# A very simple Counter contract\\n\""
  },
  {
    "path": "examples/02 Ingredients of a Smart Contract.ipynb",
    "chars": 12186,
    "preview": "{\n \"cells\": [\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"# What is inside a smart contract?\\"
  },
  {
    "path": "examples/03 Interacting with the Client.ipynb",
    "chars": 10044,
    "preview": "{\n \"cells\": [\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"# The Main Contracting Client\\n\",\n "
  },
  {
    "path": "examples/04 Standard Library and Extending Contracting.ipynb",
    "chars": 22825,
    "preview": "{\n \"cells\": [\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"# The Contracting Standard Library\\"
  },
  {
    "path": "examples/05 Imports and Advanced Data Storage.ipynb",
    "chars": 9887,
    "preview": "{\n \"cells\": [\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"# Imports and Advanced Data Storage"
  },
  {
    "path": "examples/Rock Paper Scissors Tutorial.ipynb",
    "chars": 25511,
    "preview": "{\n \"cells\": [\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"# Rock Paper Scissors\"\n   ]\n  },\n  "
  },
  {
    "path": "pyproject.toml",
    "chars": 837,
    "preview": "[tool.poetry]\nname = \"xian-contracting\"\nversion = \"1.0.1\"\ndescription = \"Xian Network Python Contracting Engine\"\nauthors"
  },
  {
    "path": "release.sh",
    "chars": 3646,
    "preview": "#!/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"
  },
  {
    "path": "src/contracting/__init__.py",
    "chars": 0,
    "preview": ""
  },
  {
    "path": "src/contracting/client.py",
    "chars": 11746,
    "preview": "from contracting.execution.executor import Executor\nfrom contracting.storage.driver import Driver\nfrom contracting.compi"
  },
  {
    "path": "src/contracting/compilation/__init__.py",
    "chars": 0,
    "preview": ""
  },
  {
    "path": "src/contracting/compilation/compiler.py",
    "chars": 3976,
    "preview": "import ast\nimport astor\n\nfrom contracting import constants\nfrom contracting.compilation.linter import Linter\n\n\nclass Con"
  },
  {
    "path": "src/contracting/compilation/linter.py",
    "chars": 11441,
    "preview": "import ast\nimport sys\n\nfrom .. import constants\n\nfrom ..compilation.whitelists import (\n    ALLOWED_AST_TYPES,\n    ALLOW"
  },
  {
    "path": "src/contracting/compilation/parser.py",
    "chars": 1431,
    "preview": "import ast\n\n\ndef methods_for_contract(contract_code: str):\n    tree = ast.parse(contract_code)\n\n    function_defs = [n f"
  },
  {
    "path": "src/contracting/compilation/whitelists.py",
    "chars": 2741,
    "preview": "import ast, builtins\n\nALLOWED_BUILTINS = {'Exception', 'False', 'None', 'True', 'abs', 'all', 'any', 'ascii', 'bin', 'bo"
  },
  {
    "path": "src/contracting/constants.py",
    "chars": 710,
    "preview": "from pathlib import Path\n\nRECURSION_LIMIT = 1024\n\nDELIMITER = ':'\nINDEX_SEPARATOR = '.'\nHDF5_GROUP_SEPARATOR = '/'\n\nSUBM"
  },
  {
    "path": "src/contracting/contracts/__init__.py",
    "chars": 0,
    "preview": ""
  },
  {
    "path": "src/contracting/contracts/proxythis.py",
    "chars": 246,
    "preview": "@export\r\ndef proxythis(con: str):\r\n    return importlib.import_module(con).getthis()\r\n\r\n@export\r\ndef nestedproxythis(con"
  },
  {
    "path": "src/contracting/contracts/submission.s.py",
    "chars": 958,
    "preview": "@__export('submission')\ndef submit_contract(name: str, code: str, owner: Any=None, constructor_args: dict={}):\n    if ct"
  },
  {
    "path": "src/contracting/contracts/thistest2.py",
    "chars": 177,
    "preview": "@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"
  },
  {
    "path": "src/contracting/execution/__init__.py",
    "chars": 0,
    "preview": ""
  },
  {
    "path": "src/contracting/execution/executor.py",
    "chars": 6654,
    "preview": "from contracting.execution import runtime\nfrom contracting.storage.driver import Driver\nfrom contracting.execution.modul"
  },
  {
    "path": "src/contracting/execution/module.py",
    "chars": 3820,
    "preview": "from importlib.abc import Loader\nfrom importlib import invalidate_caches, __import__\nfrom importlib.machinery import Mod"
  },
  {
    "path": "src/contracting/execution/runtime.py",
    "chars": 3409,
    "preview": "from contracting import constants\nfrom contracting.execution.tracer import Tracer\n\nimport contracting\nimport sys\nimport "
  },
  {
    "path": "src/contracting/execution/tracer.py",
    "chars": 5661,
    "preview": "import sys\nimport dis\nimport threading\nimport psutil\nimport os\n\n# Define the opcode costs\ncu_costs = {\n    0: 2, 1: 2, 2"
  },
  {
    "path": "src/contracting/stdlib/__init__.py",
    "chars": 0,
    "preview": ""
  },
  {
    "path": "src/contracting/stdlib/bridge/__init__.py",
    "chars": 0,
    "preview": ""
  },
  {
    "path": "src/contracting/stdlib/bridge/access.py",
    "chars": 1213,
    "preview": "from contracting.execution.runtime import rt\nfrom contextlib import ContextDecorator\nfrom contracting.storage.driver imp"
  },
  {
    "path": "src/contracting/stdlib/bridge/crypto.py",
    "chars": 716,
    "preview": "from types import ModuleType\nimport nacl\n\n\ndef verify(vk: str, msg: str, signature: str):\n    vk = bytes.fromhex(vk)\n   "
  },
  {
    "path": "src/contracting/stdlib/bridge/decimal.py",
    "chars": 4687,
    "preview": "from decimal import Decimal, Context, ROUND_FLOOR\nimport decimal\n\n# Define precision constants\nMAX_UPPER_PRECISION = 30\n"
  },
  {
    "path": "src/contracting/stdlib/bridge/hashing.py",
    "chars": 810,
    "preview": "import hashlib\n\nfrom types import ModuleType\n\n'''\nBytes can't be stored in JSON so we use hex-strings converted into byt"
  },
  {
    "path": "src/contracting/stdlib/bridge/imports.py",
    "chars": 2629,
    "preview": "from types import FunctionType, ModuleType\nfrom contracting.constants import PRIVATE_METHOD_PREFIX\nfrom contracting.stor"
  },
  {
    "path": "src/contracting/stdlib/bridge/orm.py",
    "chars": 1647,
    "preview": "from contracting.storage.orm import Variable, Hash, ForeignVariable, ForeignHash, LogEvent\nfrom contracting.storage.cont"
  },
  {
    "path": "src/contracting/stdlib/bridge/random.py",
    "chars": 2978,
    "preview": "\"\"\"\n    This module wraps and exposes the Python stdlib random functions that can be made deterministic with a random se"
  },
  {
    "path": "src/contracting/stdlib/bridge/time.py",
    "chars": 7513,
    "preview": "from datetime import datetime as dt\nfrom datetime import timedelta as td\nfrom types import ModuleType\n\n\n# Redefine a con"
  },
  {
    "path": "src/contracting/stdlib/env.py",
    "chars": 1003,
    "preview": "from contracting.stdlib.bridge.orm import exports as orm_exports\nfrom contracting.stdlib.bridge.hashing import exports a"
  },
  {
    "path": "src/contracting/storage/__init__.py",
    "chars": 0,
    "preview": ""
  },
  {
    "path": "src/contracting/storage/contract.py",
    "chars": 1531,
    "preview": "from contracting.compilation.compiler import ContractingCompiler\nfrom contracting.storage.driver import Driver\nfrom cont"
  },
  {
    "path": "src/contracting/storage/driver.py",
    "chars": 14948,
    "preview": "from contracting.storage.encoder import encode_kv\nfrom contracting.execution.runtime import rt\nfrom contracting.stdlib.b"
  },
  {
    "path": "src/contracting/storage/encoder.py",
    "chars": 5528,
    "preview": "import json\nimport decimal\n\nfrom contracting.stdlib.bridge.time import Datetime, Timedelta\nfrom contracting.stdlib.bridg"
  },
  {
    "path": "src/contracting/storage/hdf5.py",
    "chars": 4523,
    "preview": "import h5py\n\nfrom threading import Lock\nfrom collections import defaultdict\nfrom contracting.storage.encoder import enco"
  },
  {
    "path": "src/contracting/storage/orm.py",
    "chars": 8869,
    "preview": "from contracting.storage.driver import Driver\nfrom contracting.execution.runtime import rt\nfrom contracting import const"
  },
  {
    "path": "tests/__init__.py",
    "chars": 0,
    "preview": ""
  },
  {
    "path": "tests/integration/__init__.py",
    "chars": 0,
    "preview": ""
  },
  {
    "path": "tests/integration/test_atomic_swap.py",
    "chars": 12762,
    "preview": "from unittest import TestCase\nfrom contracting.storage.driver import Driver\nfrom contracting.execution.executor import E"
  },
  {
    "path": "tests/integration/test_builtins_locked_off.py",
    "chars": 3117,
    "preview": "from unittest import TestCase\nfrom contracting.client import ContractingClient\nimport os\n\nclass TestBuiltinsLockedOff(Te"
  },
  {
    "path": "tests/integration/test_complex_contracts.py",
    "chars": 12598,
    "preview": "from unittest import TestCase\nfrom contracting.storage.driver import Driver\nfrom contracting.execution.executor import E"
  },
  {
    "path": "tests/integration/test_complex_object_setting.py",
    "chars": 1003,
    "preview": "from contracting.client import ContractingClient\nfrom unittest import TestCase\nimport os\n\ndef contract():\n    storage = "
  },
  {
    "path": "tests/integration/test_constructor_args.py",
    "chars": 1559,
    "preview": "from unittest import TestCase\nfrom contracting.stdlib.bridge.time import Datetime\nfrom contracting.client import Contrac"
  },
  {
    "path": "tests/integration/test_contracts/__init__.py",
    "chars": 0,
    "preview": ""
  },
  {
    "path": "tests/integration/test_contracts/atomic_swaps.s.py",
    "chars": 1474,
    "preview": "import con_erc20_clone\n\nswaps = Hash()\n\n@export\ndef initiate(participant: str, expiration: datetime.datetime, hashlock: "
  },
  {
    "path": "tests/integration/test_contracts/bad_time.s.py",
    "chars": 106,
    "preview": "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",
    "chars": 373,
    "preview": "balances = Hash(default_value=0)\n\n@construct\ndef seed():\n    balances['stu'] = 999\n    balances['colin'] = 555\n\n@export\n"
  },
  {
    "path": "tests/integration/test_contracts/builtin_lib.s.py",
    "chars": 115,
    "preview": "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",
    "chars": 42,
    "preview": "@export\ndef get_value():\n    return 'good'"
  },
  {
    "path": "tests/integration/test_contracts/client.py",
    "chars": 0,
    "preview": ""
  },
  {
    "path": "tests/integration/test_contracts/con_pass_hash.s.py",
    "chars": 172,
    "preview": "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,"
  },
  {
    "path": "tests/integration/test_contracts/construct_function_works.s.py",
    "chars": 92,
    "preview": "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",
    "chars": 173,
    "preview": "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"
  },
  {
    "path": "tests/integration/test_contracts/contracting.s.py",
    "chars": 39,
    "preview": "@export\ndef hello():\n    return 'hello'"
  },
  {
    "path": "tests/integration/test_contracts/currency.s.py",
    "chars": 434,
    "preview": "balances = Hash()\n\n@construct\ndef seed():\n    balances['stu'] = 1000000\n    balances['colin'] = 100\n\n@export\ndef transfe"
  },
  {
    "path": "tests/integration/test_contracts/dater.py",
    "chars": 227,
    "preview": "#import datetime\n\nv = Variable()\n\n@export\ndef replicate(d: datetime.datetime):\n    assert d > now, 'D IS NOT LARGER THAN"
  },
  {
    "path": "tests/integration/test_contracts/dynamic_import.py",
    "chars": 369,
    "preview": "@export\ndef called_from_a_far():\n    m = importlib.import_module('con_all_in_one')\n    res = m.call_me_again_again()\n\n  "
  },
  {
    "path": "tests/integration/test_contracts/dynamic_import.s.py",
    "chars": 77,
    "preview": "@export\ndef import_thing(name: str):\n    return importlib.import_module(name)"
  },
  {
    "path": "tests/integration/test_contracts/dynamic_importing.s.py",
    "chars": 1478,
    "preview": "@export\ndef balance_for_token(tok: str, account: str):\n    t = importlib.import_module(tok)\n    return t.balance_of(acco"
  },
  {
    "path": "tests/integration/test_contracts/erc20_clone.s.py",
    "chars": 1188,
    "preview": "supply = Variable()\nbalances = Hash(default_value=0)\n\n@construct\ndef seed():\n    balances['stu'] = 1000000\n    balances["
  },
  {
    "path": "tests/integration/test_contracts/exception.py",
    "chars": 418,
    "preview": "balances = Hash(default_value=0)\n\n@construct\ndef seed():\n    balances['stu'] = 999\n    balances['colin'] = 555\n\n@export\n"
  },
  {
    "path": "tests/integration/test_contracts/float_issue.s.py",
    "chars": 994,
    "preview": "random.seed()\ngradients = Hash()\n\ndef rand_vect():\n    theta = random.randint(0, 100) / 50 * 3.13\n    return {'x': 5.124"
  },
  {
    "path": "tests/integration/test_contracts/foreign_thing.s.py",
    "chars": 415,
    "preview": "thing_H = ForeignHash(foreign_contract='con_thing', foreign_name='H')\nthing_V = ForeignVariable(foreign_contract='con_th"
  },
  {
    "path": "tests/integration/test_contracts/hashing_works.s.py",
    "chars": 115,
    "preview": "@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",
    "chars": 62,
    "preview": "@export\ndef env_var():\n    return this_is_a_passed_in_variable"
  },
  {
    "path": "tests/integration/test_contracts/import_test.s.py",
    "chars": 105,
    "preview": "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",
    "chars": 37,
    "preview": "@export\ndef howdy():\n    return 12345"
  },
  {
    "path": "tests/integration/test_contracts/importing_that.s.py",
    "chars": 102,
    "preview": "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",
    "chars": 98,
    "preview": "@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",
    "chars": 124,
    "preview": "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"
  },
  {
    "path": "tests/integration/test_contracts/leaky.s.py",
    "chars": 540,
    "preview": "supply = Variable()\nbalances = Hash(default_value=0)\n\n@construct\ndef seed():\n    balances['stu'] = 1000000\n    balances["
  },
  {
    "path": "tests/integration/test_contracts/mathtime.s.py",
    "chars": 116,
    "preview": "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",
    "chars": 281,
    "preview": "@export\ndef call_me():\n    return call_me_again()\n\n@export\ndef call_me_again():\n    return call_me_again_again()\n\n@expor"
  },
  {
    "path": "tests/integration/test_contracts/modules/dynamic_import.s.py",
    "chars": 221,
    "preview": "@export\ndef called_from_a_far():\n    m = importlib.import_module('all_in_one')\n    return m.call_me_again_again()\n\n@expo"
  },
  {
    "path": "tests/integration/test_contracts/modules/module1.s.py",
    "chars": 311,
    "preview": "'''\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\n"
  },
  {
    "path": "tests/integration/test_contracts/modules/module2.s.py",
    "chars": 190,
    "preview": "import module4\nimport module5\n\n@export\ndef get_context():\n    return {\n        'owner': ctx.owner,\n        'this': ctx.t"
  },
  {
    "path": "tests/integration/test_contracts/modules/module3.s.py",
    "chars": 190,
    "preview": "import module6\nimport module7\n\n@export\ndef get_context():\n    return {\n        'owner': ctx.owner,\n        'this': ctx.t"
  },
  {
    "path": "tests/integration/test_contracts/modules/module4.s.py",
    "chars": 159,
    "preview": "@export\ndef get_context():\n    return {\n        'owner': ctx.owner,\n        'this': ctx.this,\n        'signer': ctx.sign"
  },
  {
    "path": "tests/integration/test_contracts/modules/module5.s.py",
    "chars": 175,
    "preview": "import module8\n\n@export\ndef get_context():\n    return {\n        'owner': ctx.owner,\n        'this': ctx.this,\n        's"
  },
  {
    "path": "tests/integration/test_contracts/modules/module6.s.py",
    "chars": 159,
    "preview": "@export\ndef get_context():\n    return {\n        'owner': ctx.owner,\n        'this': ctx.this,\n        'signer': ctx.sign"
  },
  {
    "path": "tests/integration/test_contracts/modules/module7.s.py",
    "chars": 159,
    "preview": "@export\ndef get_context():\n    return {\n        'owner': ctx.owner,\n        'this': ctx.this,\n        'signer': ctx.sign"
  },
  {
    "path": "tests/integration/test_contracts/modules/module8.s.py",
    "chars": 159,
    "preview": "@export\ndef get_context():\n    return {\n        'owner': ctx.owner,\n        'this': ctx.this,\n        'signer': ctx.sign"
  },
  {
    "path": "tests/integration/test_contracts/orm_foreign_hash_contract.s.py",
    "chars": 174,
    "preview": "fh = ForeignHash(foreign_contract='con_orm_hash_contract', foreign_name='h')\n\n@export\ndef set_fh(k: str, v: int):\n    fh"
  },
  {
    "path": "tests/integration/test_contracts/orm_foreign_key_contract.s.py",
    "chars": 171,
    "preview": "fv = ForeignVariable(foreign_contract='con_orm_variable_contract', foreign_name='v')\n\n@export\ndef set_fv(i: int):\n    fv"
  },
  {
    "path": "tests/integration/test_contracts/orm_hash_contract.s.py",
    "chars": 104,
    "preview": "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",
    "chars": 153,
    "preview": "c = __Contract()\n\n@export\ndef set_c():\n    code = '''\n@export\ndef a():\n    print('gottem')    \n'''\n    c.submit(name='ba"
  },
  {
    "path": "tests/integration/test_contracts/orm_variable_contract.s.py",
    "chars": 97,
    "preview": "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",
    "chars": 150,
    "preview": "@export\ndef get_owner(s: str):\n    m = importlib.import_module(s)\n    return importlib.owner_of(m)\n\n@export\ndef owner_of"
  },
  {
    "path": "tests/integration/test_contracts/parent_test.s.py",
    "chars": 100,
    "preview": "@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",
    "chars": 66,
    "preview": "@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",
    "chars": 243,
    "preview": "test_hash = Hash()\n\n@export\ndef call_private():\n    return private()\n\ndef private():\n    return 'abc'\n\n@export\ndef set(k"
  },
  {
    "path": "tests/integration/test_contracts/stubucks.s.py",
    "chars": 1184,
    "preview": "supply = Variable()\nbalances = Hash(default_value=0)\n\n@construct\ndef seed():\n    balances['stu'] = 123\n    balances['col"
  },
  {
    "path": "tests/integration/test_contracts/submission.s.py",
    "chars": 958,
    "preview": "@__export('submission')\ndef submit_contract(name: str, code: str, owner: Any=None, constructor_args: dict={}):\n    if ct"
  },
  {
    "path": "tests/integration/test_contracts/tejastokens.s.py",
    "chars": 1184,
    "preview": "supply = Variable()\nbalances = Hash(default_value=0)\n\n@construct\ndef seed():\n    balances['stu'] = 321\n    balances['col"
  },
  {
    "path": "tests/integration/test_contracts/thing.s.py",
    "chars": 148,
    "preview": "H = Hash()\nV = Variable()\n\n@construct\ndef seed():\n    H['hello'] = 'there'\n    H['something'] = 'else'\n    V.set('hi')\n\n"
  },
  {
    "path": "tests/integration/test_contracts/time.s.py",
    "chars": 177,
    "preview": "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 "
  },
  {
    "path": "tests/integration/test_contracts/time_storage.s.py",
    "chars": 128,
    "preview": "time = Variable()\n\n@construct\ndef seed():\n    time.set(datetime.datetime(2019, 1, 1))\n\n@export\ndef get():\n    return tim"
  },
  {
    "path": "tests/integration/test_datetime_contracts.py",
    "chars": 1179,
    "preview": "from unittest import TestCase\nfrom contracting.client import ContractingClient\nfrom contracting.stdlib.bridge.time impor"
  },
  {
    "path": "tests/integration/test_dynamic_imports.py",
    "chars": 7198,
    "preview": "from unittest import TestCase\nfrom contracting.stdlib.bridge.time import Datetime\nfrom contracting.client import Contrac"
  },
  {
    "path": "tests/integration/test_executor_submission_process.py",
    "chars": 13720,
    "preview": "from unittest import TestCase\nfrom contracting.storage.driver import Driver\nfrom contracting.execution.executor import E"
  },
  {
    "path": "tests/integration/test_executor_transaction_writes.py",
    "chars": 1860,
    "preview": "import importlib\nfrom unittest import TestCase\nfrom contracting.stdlib.bridge.time import Datetime\nfrom contracting.clie"
  },
  {
    "path": "tests/integration/test_memory_clean_up_after_execution.py",
    "chars": 2573,
    "preview": "from unittest import TestCase\nfrom contracting.storage.driver import Driver\nfrom contracting.execution.executor import E"
  },
  {
    "path": "tests/integration/test_misc_contracts.py",
    "chars": 15360,
    "preview": "import importlib\nfrom unittest import TestCase\nfrom contracting.stdlib.bridge.time import Datetime\nfrom contracting.clie"
  },
  {
    "path": "tests/integration/test_pixel_game.py",
    "chars": 7111,
    "preview": "from contracting.client import ContractingClient\nfrom unittest import TestCase\n\n\ndef con_coin():\n    supply = Variable()"
  },
  {
    "path": "tests/integration/test_rich_ctx_calling.py",
    "chars": 4769,
    "preview": "from unittest import TestCase\nfrom contracting.client import ContractingClient\n\n\ndef con_module1():\n    @export\n    def "
  },
  {
    "path": "tests/integration/test_run_private_function.py",
    "chars": 1856,
    "preview": "from unittest import TestCase\nfrom contracting.client import ContractingClient\nimport os\n\nclass TestRunPrivateFunction(T"
  },
  {
    "path": "tests/integration/test_senecaCompiler_integration.py",
    "chars": 4163,
    "preview": "from unittest import TestCase\nfrom contracting.compilation.compiler import ContractingCompiler\nfrom contracting.stdlib i"
  },
  {
    "path": "tests/integration/test_seneca_client_randoms.py",
    "chars": 4437,
    "preview": "from unittest import TestCase\nfrom contracting.client import ContractingClient\nimport random\n\ndef con_random_contract():"
  },
  {
    "path": "tests/integration/test_seneca_client_replaces_executor.py",
    "chars": 10378,
    "preview": "from unittest import TestCase\nfrom contracting.stdlib.bridge.time import Datetime\nfrom contracting.client import Contrac"
  },
  {
    "path": "tests/integration/test_stamp_deduction.py",
    "chars": 5035,
    "preview": "from unittest import TestCase\nfrom contracting.storage.driver import Driver\nfrom contracting.execution.executor import E"
  },
  {
    "path": "tests/performance/__init__.py",
    "chars": 0,
    "preview": ""
  },
  {
    "path": "tests/performance/prof_transfer.py",
    "chars": 1627,
    "preview": "import secrets\nfrom contracting.storage.driver import Driver\nfrom contracting.execution.executor import Executor\n\ndef su"
  },
  {
    "path": "tests/performance/test_contracts/__init__.py",
    "chars": 0,
    "preview": ""
  },
  {
    "path": "tests/performance/test_contracts/erc20_clone.s.py",
    "chars": 1188,
    "preview": "supply = Variable()\nbalances = Hash(default_value=0)\n\n@construct\ndef seed():\n    balances['stu'] = 1000000\n    balances["
  },
  {
    "path": "tests/performance/test_contracts/modules/all_in_one.s.py",
    "chars": 281,
    "preview": "@export\ndef call_me():\n    return call_me_again()\n\n@export\ndef call_me_again():\n    return call_me_again_again()\n\n@expor"
  },
  {
    "path": "tests/performance/test_contracts/modules/dynamic_import.s.py",
    "chars": 221,
    "preview": "@export\ndef called_from_a_far():\n    m = importlib.import_module('all_in_one')\n    return m.call_me_again_again()\n\n@expo"
  },
  {
    "path": "tests/performance/test_contracts/modules/module1.s.py",
    "chars": 311,
    "preview": "'''\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\n"
  },
  {
    "path": "tests/performance/test_contracts/modules/module2.s.py",
    "chars": 190,
    "preview": "import module4\nimport module5\n\n@export\ndef get_context():\n    return {\n        'owner': ctx.owner,\n        'this': ctx.t"
  },
  {
    "path": "tests/performance/test_contracts/modules/module3.s.py",
    "chars": 190,
    "preview": "import module6\nimport module7\n\n@export\ndef get_context():\n    return {\n        'owner': ctx.owner,\n        'this': ctx.t"
  },
  {
    "path": "tests/performance/test_contracts/modules/module4.s.py",
    "chars": 159,
    "preview": "@export\ndef get_context():\n    return {\n        'owner': ctx.owner,\n        'this': ctx.this,\n        'signer': ctx.sign"
  },
  {
    "path": "tests/performance/test_contracts/modules/module5.s.py",
    "chars": 175,
    "preview": "import module8\n\n@export\ndef get_context():\n    return {\n        'owner': ctx.owner,\n        'this': ctx.this,\n        's"
  },
  {
    "path": "tests/performance/test_contracts/modules/module6.s.py",
    "chars": 159,
    "preview": "@export\ndef get_context():\n    return {\n        'owner': ctx.owner,\n        'this': ctx.this,\n        'signer': ctx.sign"
  },
  {
    "path": "tests/performance/test_contracts/modules/module7.s.py",
    "chars": 159,
    "preview": "@export\ndef get_context():\n    return {\n        'owner': ctx.owner,\n        'this': ctx.this,\n        'signer': ctx.sign"
  },
  {
    "path": "tests/performance/test_contracts/modules/module8.s.py",
    "chars": 159,
    "preview": "@export\ndef get_context():\n    return {\n        'owner': ctx.owner,\n        'this': ctx.this,\n        'signer': ctx.sign"
  },
  {
    "path": "tests/performance/test_contracts/submission.s.py",
    "chars": 958,
    "preview": "@__export('submission')\ndef submit_contract(name: str, code: str, owner: Any=None, constructor_args: dict={}):\n    if ct"
  },
  {
    "path": "tests/performance/test_transfer.py",
    "chars": 1778,
    "preview": "from unittest import TestCase\nimport secrets\nfrom contracting.storage.driver import Driver\nfrom contracting.execution.ex"
  },
  {
    "path": "tests/security/__init__.py",
    "chars": 0,
    "preview": ""
  },
  {
    "path": "tests/security/contracts/builtin_hack_token.s.py",
    "chars": 178,
    "preview": "balances = Hash(default_value=0)\n\n@construct\ndef seed():\n    setattr(balances, '_key', 'erc20.balances')\n    balances['s"
  },
  {
    "path": "tests/security/contracts/call_infinate_loop.s.py",
    "chars": 74,
    "preview": "import con_infinate_loop\n\n@export\ndef call():\n    con_infinate_loop.loop()"
  },
  {
    "path": "tests/security/contracts/con_inf_writes.s.py",
    "chars": 212,
    "preview": "hhash = Hash(default_value=0)\n\n@construct\ndef seed():\n    hashed_data = 'woohoo'\n    while True:\n        hashed_data = h"
  },
  {
    "path": "tests/security/contracts/constructor_infinate_loop.s.py",
    "chars": 98,
    "preview": "@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",
    "chars": 290,
    "preview": "import con_erc20\n\n@construct\ndef seed():\n    pass\n\n@export\ndef double_spend(receiver: str):\n    allowance = con_erc20.al"
  },
  {
    "path": "tests/security/contracts/erc20_clone.s.py",
    "chars": 1188,
    "preview": "supply = Variable()\nbalances = Hash(default_value=0)\n\n@construct\ndef seed():\n    balances['stu'] = 1000000\n    balances["
  },
  {
    "path": "tests/security/contracts/get_set_driver.py",
    "chars": 178,
    "preview": "import erc20\ndriver = erc20.rt.env.get('__Driver')\n\n@construct\ndef seed():\n    driver.set(\n        key='erc20.balances:s"
  },
  {
    "path": "tests/security/contracts/get_set_driver_2.py",
    "chars": 184,
    "preview": "import erc20\nz = erc20.rt\ndriver = z.env.get('__Driver')\n\n@construct\ndef seed():\n    driver.set(\n        key='erc20.bala"
  },
  {
    "path": "tests/security/contracts/hack_tokens.s.py",
    "chars": 170,
    "preview": "balances = Hash(default_value=0)\n\n@construct\ndef seed():\n    balances.key = 'con_erc20.balances'\n    balances['stu'] = 9"
  },
  {
    "path": "tests/security/contracts/import_hash_from_contract.s.py",
    "chars": 112,
    "preview": "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",
    "chars": 116,
    "preview": "@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",
    "chars": 958,
    "preview": "@__export('submission')\ndef submit_contract(name: str, code: str, owner: Any=None, constructor_args: dict={}):\n    if ct"
  },
  {
    "path": "tests/security/test_erc20_token_hacks.py",
    "chars": 8148,
    "preview": "from unittest import TestCase\nfrom contracting.client import ContractingClient\nimport os\nclass TestTokenHacks(TestCase):"
  },
  {
    "path": "tests/unit/__init__.py",
    "chars": 0,
    "preview": ""
  },
  {
    "path": "tests/unit/contracts/currency.s.py",
    "chars": 434,
    "preview": "balances = Hash()\n\n@construct\ndef seed():\n    balances['stu'] = 1000000\n    balances['colin'] = 100\n\n@export\ndef transfe"
  },
  {
    "path": "tests/unit/contracts/exception.s.py",
    "chars": 418,
    "preview": "balances = Hash(default_value=0)\n\n@construct\ndef seed():\n    balances['stu'] = 999\n    balances['colin'] = 555\n\n@export\n"
  },
  {
    "path": "tests/unit/contracts/proxythis.py",
    "chars": 246,
    "preview": "@export\r\ndef proxythis(con: str):\r\n    return importlib.import_module(con).getthis()\r\n\r\n@export\r\ndef nestedproxythis(con"
  },
  {
    "path": "tests/unit/contracts/submission.s.py",
    "chars": 958,
    "preview": "@__export('submission')\ndef submit_contract(name: str, code: str, owner: Any=None, constructor_args: dict={}):\n    if ct"
  },
  {
    "path": "tests/unit/contracts/thistest2.py",
    "chars": 177,
    "preview": "@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"
  },
  {
    "path": "tests/unit/loop_client_test.sh",
    "chars": 300,
    "preview": "#!/usr/bin/env bash\ncount=0\nwhile :\ndo\n\toutput=$(python test_client.py TestSenecaClient.test_update_master_db_with_incom"
  },
  {
    "path": "tests/unit/precompiled/__init__.py",
    "chars": 0,
    "preview": ""
  },
  {
    "path": "tests/unit/precompiled/compiled_token.py",
    "chars": 1394,
    "preview": "# Monkey patch for testing, as this is purely for 'interface enforcement' testing\nfrom contracting.storage.orm import Va"
  },
  {
    "path": "tests/unit/precompiled/updated_submission.py",
    "chars": 966,
    "preview": "@__export('submission')\ndef submit_contract(name: str, code: str, owner: Any=None, constructor_args: dict={}):\n    if ct"
  },
  {
    "path": "tests/unit/test_client.py",
    "chars": 3790,
    "preview": "from unittest import TestCase\nfrom contracting.client import ContractingClient\nfrom contracting.storage.driver import Dr"
  },
  {
    "path": "tests/unit/test_client_keys_prefix.py",
    "chars": 1146,
    "preview": "import unittest\nfrom contracting.client import ContractingClient\n\n\nclass TestClientKeysPrefix(unittest.TestCase):\n\n    d"
  },
  {
    "path": "tests/unit/test_context_data_struct.py",
    "chars": 3014,
    "preview": "from unittest import TestCase\nfrom contracting.execution.runtime import Context\n\n\nclass TestContext(TestCase):\n    def t"
  },
  {
    "path": "tests/unit/test_datetime.py",
    "chars": 4987,
    "preview": "from unittest import TestCase\nfrom contracting.stdlib.bridge.time import Datetime, Timedelta\nfrom datetime import dateti"
  },
  {
    "path": "tests/unit/test_decimal.py",
    "chars": 6768,
    "preview": "from decimal import Decimal\nimport decimal\nimport math\n\nfrom contracting.stdlib.bridge.decimal import ContractingDecimal"
  },
  {
    "path": "tests/unit/test_driver_tombstones.py",
    "chars": 889,
    "preview": "import unittest\nfrom contracting.storage.driver import Driver\n\n\nclass TestDriverTombstones(unittest.TestCase):\n\n    def "
  },
  {
    "path": "tests/unit/test_encode.py",
    "chars": 8706,
    "preview": "from unittest import TestCase\nfrom contracting.storage.encoder import encode, decode, safe_repr, convert_dict, MONGO_MAX"
  },
  {
    "path": "tests/unit/test_imports_stdlib.py",
    "chars": 5601,
    "preview": "from unittest import TestCase\nfrom contracting.stdlib.bridge import imports\nfrom types import ModuleType\nfrom contractin"
  },
  {
    "path": "tests/unit/test_linter.py",
    "chars": 12530,
    "preview": "from unittest import TestCase\nfrom contracting.compilation.linter import Linter\nimport ast\nfrom contracting.compilation."
  },
  {
    "path": "tests/unit/test_module.py",
    "chars": 3402,
    "preview": "from unittest import TestCase\nfrom contracting.execution.module import *\nfrom contracting.storage.driver import Driver\ni"
  },
  {
    "path": "tests/unit/test_new_driver.py",
    "chars": 4263,
    "preview": "import unittest\nimport os\nfrom shutil import rmtree\nfrom datetime import datetime\nfrom contracting.storage.driver import"
  },
  {
    "path": "tests/unit/test_orm.py",
    "chars": 30069,
    "preview": "from unittest import TestCase\nfrom contracting import constants\nfrom contracting.storage.driver import Driver\nfrom contr"
  },
  {
    "path": "tests/unit/test_parser.py",
    "chars": 5523,
    "preview": "from contracting.compilation import parser\nfrom contracting.compilation.compiler import ContractingCompiler\nfrom unittes"
  },
  {
    "path": "tests/unit/test_revert_on_exception.py",
    "chars": 3875,
    "preview": "import unittest\nfrom contracting.storage.driver import Driver\nfrom contracting.execution.executor import Executor\nfrom c"
  },
  {
    "path": "tests/unit/test_runtime.py",
    "chars": 4058,
    "preview": "from unittest import TestCase\nfrom contracting.execution import runtime\nimport sys\nimport psutil\nimport os\n\n\nclass TestR"
  },
  {
    "path": "tests/unit/test_state_management.py",
    "chars": 2172,
    "preview": "import unittest\r\nfrom xian.processor import TxProcessor\r\nfrom contracting.client import ContractingClient\r\nfrom xian.ser"
  },
  {
    "path": "tests/unit/test_stdlib_hashing.py",
    "chars": 538,
    "preview": "from unittest import TestCase\nfrom contracting.stdlib.bridge.hashing import sha256, sha3\n\n\nclass TestHashing(TestCase):\n"
  },
  {
    "path": "tests/unit/test_sys_contracts/__init__.py",
    "chars": 0,
    "preview": ""
  },
  {
    "path": "tests/unit/test_sys_contracts/bad_lint.s.py",
    "chars": 37,
    "preview": "def no_exports():\n    return 'hahaha'"
  },
  {
    "path": "tests/unit/test_sys_contracts/compile_this.s.py",
    "chars": 81,
    "preview": "@export\ndef good_function():\n    return 5\n\ndef another_function():\n    return 100"
  },
  {
    "path": "tests/unit/test_sys_contracts/currency.s.py",
    "chars": 1500,
    "preview": "xrate = Variable()\nseed_amount = Variable()\nbalances = Hash()\nallowed = Hash()\n\n@construct\ndef seed():\n    xrate = 1.0\n "
  },
  {
    "path": "tests/unit/test_sys_contracts/good_lint.s.py",
    "chars": 45,
    "preview": "@export\ndef exports():\n    return 'huehuehue'"
  },
  {
    "path": "tests/unit/test_sys_contracts/module1.py",
    "chars": 234,
    "preview": "'''\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\n"
  },
  {
    "path": "tests/unit/test_sys_contracts/module2.py",
    "chars": 112,
    "preview": "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",
    "chars": 112,
    "preview": "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",
    "chars": 81,
    "preview": "print('{} called from {}, signed by {}'.format(ctx.this, ctx.caller, ctx.signer))"
  },
  {
    "path": "tests/unit/test_sys_contracts/module5.py",
    "chars": 97,
    "preview": "import module8\n\nprint('{} called from {}, signed by {}'.format(ctx.this, ctx.caller, ctx.signer))"
  },
  {
    "path": "tests/unit/test_sys_contracts/module6.py",
    "chars": 81,
    "preview": "print('{} called from {}, signed by {}'.format(ctx.this, ctx.caller, ctx.signer))"
  },
  {
    "path": "tests/unit/test_sys_contracts/module7.py",
    "chars": 81,
    "preview": "print('{} called from {}, signed by {}'.format(ctx.this, ctx.caller, ctx.signer))"
  },
  {
    "path": "tests/unit/test_sys_contracts/module8.py",
    "chars": 81,
    "preview": "print('{} called from {}, signed by {}'.format(ctx.this, ctx.caller, ctx.signer))"
  },
  {
    "path": "tests/unit/test_sys_contracts/module_func.py",
    "chars": 285,
    "preview": "supply = Variable()\nbalances = Hash(default_value=0)\n\n@construct\ndef seed():\n    balances['test'] = 100\n    supply.set(b"
  },
  {
    "path": "tests/unit/test_timedelta.py",
    "chars": 7734,
    "preview": "from unittest import TestCase\nfrom contracting.stdlib.bridge.time import Timedelta, WEEKS, DAYS, HOURS, MINUTES, SECONDS"
  }
]

About this extraction

This page contains the full source code of the xian-network/xian-contracting GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 195 files (461.8 KB), approximately 123.8k tokens, and a symbol index with 1188 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.

Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.

Copied to clipboard!