-
Notifications
You must be signed in to change notification settings - Fork 13
/
easyweb3.py
145 lines (121 loc) · 5.54 KB
/
easyweb3.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
import threading
import time
import web3
from web3.middleware import geth_poa_middleware
import config as constants
import util
from flask import copy_current_request_context
def new_web3():
"""Return new IPC-based web3 instance"""
return web3.Web3(web3.IPCProvider(constants.GETH_DATADIR + '/geth.ipc'))
class EasyWeb3:
def __init__(self):
"""
Initialise member values
"""
self._web3 = new_web3()
self._web3.middleware_stack.inject(geth_poa_middleware, layer=0)
self._web3.eth.defaultAccount = constants.DEPLOY_FROM_ADDRESS
self._web3.personal.unlockAccount(constants.DEPLOY_FROM_ADDRESS, "")
self._lock = threading.Lock()
self._status = None
self._deployed_address = None
def unlock_default_account(self):
"""
Unlock the default account so that the server can sign and send transactions
"""
self._web3.personal.unlockAccount(constants.DEPLOY_FROM_ADDRESS, "")
def deploy_status(self):
"""
Return deploy status of the given contract that this EasyWeb3 instance is connected to.
:return: status, deployed_address - the status and address (if the status is deployed)
"""
with self._lock:
return self._status, self._deployed_address
def grade_status(self):
"""
Return grade status of the given contract /challenge tuple that this this EasyWeb3 instance
is responsible for
:return: status, deployed_address - the status and address
"""
with self._lock:
return self._status, self._deployed_address
def deploy_named_solidity_contract(self, name, user_address, timeout=180):
"""
Deploys a contract - spins off a thread to deploy the contract
:param name: The challenge/contract name
:param user_address: the address of the end-user that asked for this challenge
:param timeout: how long to wait for things to happen on-chain - in seconds.
"""
def wrapper():
self._deploy_solidity_contract(name, user_address, timeout=timeout)
t = threading.Thread(
target=wrapper,
args=()
)
t.start()
def _deploy_solidity_contract(self, contract_name, user_address, timeout=180):
"""
Deploys solidity contract
:param contract_name: name of the challenge / the contract we're going to deploy
:param user_address: end-user address that asked for this challenge
:param timeout: how long to wait for things to happen on-chain - in seconds
:return: contract_address - address of this newly spawned contract
"""
bytecode, abi = util.get_bytecode_abi(contract_name)
with self._lock:
self._status = "compiled and processing"
contract = self._web3.eth.contract(abi=abi, bytecode=bytecode)
contract_address = None
tx_hash = contract.constructor().transact({'from': constants.DEPLOY_FROM_ADDRESS, 'gas': 2000000})
print("Deployment constructor TX Hash: {} {} {}".format(contract_name, user_address, tx_hash.hex()))
tx_receipt = self._web3.eth.waitForTransactionReceipt(tx_hash, timeout)
contract_address = tx_receipt.contractAddress
with self._lock:
self._status = "mined on-chain, post-processing"
self._deployed_address = contract_address
if (util.contract_exists(contract_name)):
contract_helper = util.get_icontract(user_address, contract_name, contract_address=contract_address)
contract_helper.setup()
with self._lock:
self._status = "deployed"
return contract_address
def grade_challenge(self, contract_name, user_address, contract_address, timeout=180):
"""
grades a challenge - spins off a thread to grade a challenge for a user
:param name: The challenge/contract name
:param user_address: the address of the end-user that asked for this challenge
:param timeout: how long to wait for things to happen on-chain - in seconds.
"""
def wrapper():
self._grade_challenge(contract_name, user_address, contract_address, timeout=timeout)
t = threading.Thread(
target=wrapper,
args=()
)
t.start()
def _grade_challenge(self, contract_name, user_address, contract_address, timeout=180):
"""
Deploys solidity contract
:param contract_name: name of the challenge / the contract we're going to deploy
:param user_address: end-user address that asked for this challenge
:param timeout: how long to wait for things to happen on-chain - in seconds
:return: contract_address - address of this newly spawned contract
"""
with self._lock:
self._status = "started"
contract_number = util.get_contract_number(contract_name)
with self._lock:
self._status = "in-progress"
self._deployed_address = contract_address
util.mark_grading(user_address, contract_number)
if (util.contract_exists(contract_name)):
contract_helper = util.get_icontract(user_address, contract_name, contract_address=contract_address)
hacked = contract_helper.has_been_hacked()
if hacked:
util.mark_finished(user_address, contract_name)
else:
util.mark_in_progress(user_address, contract_number)
with self._lock:
self._status = "graded"
return contract_address