Skip to content

Commit

Permalink
first commit
Browse files Browse the repository at this point in the history
  • Loading branch information
rlkelly committed Jul 13, 2019
0 parents commit 7f9753f
Show file tree
Hide file tree
Showing 4 changed files with 196 additions and 0 deletions.
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
# smart_contract_teaching
Binary file added __pycache__/opcodes.cpython-37.pyc
Binary file not shown.
123 changes: 123 additions & 0 deletions contract.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,123 @@
from typing import Dict, List
from hashlib import sha256
import json

from opcodes import *


class Transaction(object):
def __init__(
self,
sender,
receiver,
amount,
):
self.sender = sender
self.receiver = receiver
self.amount = amount

def dumps(self):
return {
'from': self.sender,
'to': self.receiver,
'amount': self.amount,
}


class Block(object):
def __init__(self, prev_block_hash):
self.nonce = 0
self.transactions = []
self.previous_block_hash = prev_block_hash
self.block_hash = None

def generate_json_string(self):
return json.dumps({
'previous_block_hash': self.previous_block_hash,
'nonce': self.nonce,
'transactions': [t.dumps() for t in self.transactions]
}).encode('utf-8')

def add_transaction(self, transaction: Transaction):
self.transactions.append(transaction)

def increment_nonce(self):
self.nonce += 1

def hash(self):
return sha256(self.generate_json_string()).hexdigest()


class Blockchain(object):
accounts: Dict[str, int] = {}
contracts: Dict[str, int] = {}
blocks: List[Block] = []
difficulty = '000'

def __init__(self):
self.current_block = Block()

def verify_transaction(self, transaction: Transaction) -> bool:
return transaction.sender in self.accounts and transaction.amount < self.accounts[transaction.sender]

def verify_block(self) -> bool:
for transaction in self.current_block.transactions:
if self.sender not in accounts or accounts[self.sender] < self.amount:
return False
return True

def mine_block(self):
block_hash = self.current_block.hash()
if block_hash[:len(difficulty)] != difficulty:
return False
return True


class SmartContract(object):
OPCODES = {
'PUSH': push,
'POP': pop,
'SWAP': swap,
'ADD': add,
'SUB': sub,
'MUL': mul,
'DIV': div,
'MOD': mod,
'GREATER': is_greater,
'STORAGE': store,
}

# the stack has a maximum size of 1024
def __init__(contract, balance: int, code: str, storage: dict):
contract.balance = balance
contract.code = code

contract.stack = Stack(contract)
contract.storage = storage
contract.memory = {}

contract.gas_balance = 0

def update_storage(contract, key, value):
contract.storage[key] = value
return value

def delete_memory(contract):
contract.memory = {}

def return_leftover_gas(contract):
pass

def execute(contract, gas_balance, args: dict):
contract.gas_balance = gas_balance
contract.memory = args
contract.stack = Stack(contract)

contract.delete_memory()


if __name__ == '__main__':
code = '''
PUSH 10
PUSH 20
'''
72 changes: 72 additions & 0 deletions opcodes.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
class Stack(object):
def __init__(self, contract):
self.stack = []
self.contract = contract

def pop(self):
return self.pop(-1)

def push(self, value):
stack.append(value)

class Pair(object):
def __init__(self, left, right):
self.left = left
self.right = right

def push(stack: Stack, *args):
elem = args[0]
stack.push(elem)

def pop(stack: Stack, *args):
return stack.pop()

def add(stack: Stack, *args):
x = stack.pop()
y = stack.pop()
return x + y

def sub(stack: Stack, *args):
x = stack.pop()
y = stack.pop()
return x - y

def mul(stack: Stack, *args):
x = stack.pop()
y = stack.pop()
return x * y

def div(stack: Stack, *args):
x = stack.pop()
y = stack.pop()
return x // y

def mod(stack: Stack, *args):
x = stack.pop()
y = stack.pop()
return x % y

def is_greater(stack: Stack, *args):
x = stack.pop()
y = stack.pop()
return x > y

def concat(stack: Stack, *args):
x = stack.pop()
y = stack.pop()
assert type(x) == type(y) == str
stack.push(f'{x}{y}')

def swap(stack: Stack, *args):
x = stack.pop()
y = stack.pop()
stack.push(x)
stack.push(y)

def store(stack: Stack, *args):
key: str = args[0]
value = args[1]
self.contract.update_storage(key, value)

# SLOAD
# SSTORE

0 comments on commit 7f9753f

Please sign in to comment.