Skip to content
This repository was archived by the owner on May 23, 2023. It is now read-only.

Commit 792b14a

Browse files
committed
Cleaned up some files and added comments
1 parent 72870a5 commit 792b14a

File tree

3 files changed

+56
-26
lines changed

3 files changed

+56
-26
lines changed

ethereum/state.py

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -126,7 +126,6 @@ def to_dict(self):
126126
'0x'+encode_hex(rlp.decode(val)) for key, val in odict.items()} }
127127

128128
#from ethereum.state import State
129-
#class Statu():
130129
class State():
131130

132131
def __init__(self, root=b'', env=Env(), **kwargs):

ethereum/tools/new_statetest_utils.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@ def mk_fake_header(blknum):
4343
#"Metropolis": config_metropolis
4444
}
4545

46+
# Makes a diff between a prev and post state
4647
def mk_state_diff(prev, post):
4748
o = {}
4849
for k in prev.keys():
@@ -69,6 +70,7 @@ def mk_state_diff(prev, post):
6970
o[k] = ok
7071
return o
7172

73+
# Compute a single unit of a state test
7274
def compute_state_test_unit(state, txdata, indices, konfig):
7375
state.env.config = konfig
7476
s = state.snapshot()
@@ -105,6 +107,7 @@ def compute_state_test_unit(state, txdata, indices, konfig):
105107
return output_decl
106108

107109

110+
# Initialize the state for state tests
108111
def init_state(env, pre):
109112
# Setup env
110113
state = State(
@@ -138,6 +141,7 @@ def init_state(env, pre):
138141
class EnvNotFoundException(Exception):
139142
pass
140143

144+
# Verify a state test
141145
def verify_state_test(test):
142146
print("Verifying state test")
143147
if "env" not in test:

ethereum/vm.py

Lines changed: 52 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,11 @@
3434

3535
MAX_DEPTH = 1024
3636

37+
# Wrapper to store call data. This is needed because it is possible to
38+
# call a contract N times with N bytes of data with a gas cost of O(N);
39+
# if implemented naively this would require O(N**2) bytes of data
40+
# copying. Instead we just copy the reference to the parent memory
41+
# slice plus the start and end of the slice
3742
class CallData(object):
3843

3944
def __init__(self, parent_memory, offset=0, size=None):
@@ -42,18 +47,21 @@ def __init__(self, parent_memory, offset=0, size=None):
4247
self.size = len(self.data) if size is None else size
4348
self.rlimit = self.offset + self.size
4449

50+
# Convert calldata to bytes
4551
def extract_all(self):
4652
d = self.data[self.offset: self.offset + self.size]
4753
d.extend(bytearray(self.size - len(d)))
4854
return bytes(bytearray(d))
4955

56+
# Extract 32 bytes as integer
5057
def extract32(self, i):
5158
if i >= self.size:
5259
return 0
5360
o = self.data[self.offset + i: min(self.offset + i + 32, self.rlimit)]
5461
o.extend(bytearray(32 - len(o)))
5562
return utils.bytearray_to_int(o)
5663

64+
# Extract a slice and copy it to memory
5765
def extract_copy(self, mem, memstart, datastart, size):
5866
for i in range(size):
5967
if datastart + i < self.size:
@@ -62,6 +70,8 @@ def extract_copy(self, mem, memstart, datastart, size):
6270
mem[memstart + i] = 0
6371

6472

73+
# Stores a message object, including context data like sender,
74+
# destination, gas, whether or not it is a STATICCALL, etc
6575
class Message(object):
6676

6777
def __init__(self, sender, to, value=0, gas=1000000, data='', depth=0,
@@ -82,6 +92,7 @@ def __repr__(self):
8292
return '<Message(to:%s...)>' % self.to[:8]
8393

8494

95+
# Virtual machine state of the current EVM instance
8596
class Compustate():
8697

8798
def __init__(self, **kwargs):
@@ -113,6 +124,7 @@ def preprocess_code(code):
113124
return o, pushcache
114125

115126

127+
# Extends memory, and pays gas for it
116128
def mem_extend(mem, compustate, op, start, sz):
117129
if sz and start + sz > len(mem):
118130
oldsize = len(mem) // 32
@@ -131,16 +143,12 @@ def mem_extend(mem, compustate, op, start, sz):
131143
return True
132144

133145

146+
# Pays gas for copying data
134147
def data_copy(compustate, size):
135-
if size:
136-
copyfee = opcodes.GCOPY * utils.ceil32(size) // 32
137-
if compustate.gas < copyfee:
138-
compustate.gas = 0
139-
return False
140-
compustate.gas -= copyfee
141-
return True
148+
return eat_gas(compustate, opcodes.GCOPY * utils.ceil32(size) // 32)
142149

143150

151+
# Consumes a given amount of gas
144152
def eat_gas(compustate, amount):
145153
if compustate.gas < amount:
146154
compustate.gas = 0
@@ -150,48 +158,50 @@ def eat_gas(compustate, amount):
150158
return True
151159

152160

161+
# Used to compute maximum amount of gas for child calls
153162
def all_but_1n(x, n):
154163
return x - x // n
155164

156165

166+
# Throws a VM exception
157167
def vm_exception(error, **kargs):
158168
log_vm_exit.trace('EXCEPTION', cause=error, **kargs)
159169
return 0, 0, []
160170

161171

172+
# Peacefully exits the VM
162173
def peaceful_exit(cause, gas, data, **kargs):
163174
log_vm_exit.trace('EXIT', cause=cause, **kargs)
164175
return 1, gas, data
165176

166177

178+
# Exits with the REVERT opcode
167179
def revert(gas, data, **kargs):
168180
log_vm_exit.trace('REVERT', **kargs)
169181
return 0, gas, data
170182

171-
code_cache = {}
172-
173183

184+
# Main function
174185
def vm_execute(ext, msg, code):
175186
# precompute trace flag
176187
# if we trace vm, we're in slow mode anyway
177188
trace_vm = log_vm_op.is_active('trace')
178189

190+
# Initialize stack, memory, program counter, etc
179191
compustate = Compustate(gas=msg.gas)
180192
stk = compustate.stack
181193
mem = compustate.memory
182194

195+
# Compute
183196
jumpdest_mask, pushcache = preprocess_code(code)
184197
codelen = len(code)
185-
code += b'\x00' * 32
186198

199+
# For tracing purposes
187200
op = None
188201
steps = 0
189202
_prevop = None # for trace only
190203

191204
while compustate.pc < codelen:
192-
# print('op: ', op, time.time() - s)
193-
# s = time.time()
194-
# stack size limit error
195205

196206
opcode = code[compustate.pc]
197207

@@ -211,6 +221,7 @@ def vm_execute(ext, msg, code):
211221
op=op, needed=to_string(in_args),
212222
available=to_string(len(compustate.stack)))
213223

224+
# overfull stack error
214225
if len(compustate.stack) - in_args + out_args > 1024:
215226
return vm_exception('STACK SIZE LIMIT EXCEEDED',
216227
op=op,
@@ -220,6 +231,7 @@ def vm_execute(ext, msg, code):
220231
compustate.gas -= fee
221232
compustate.pc += 1
222233

234+
# Tracing
223235
if trace_vm:
224236
"""
225237
This diverges from normal logging, as we use the logging namespace
@@ -261,6 +273,7 @@ def vm_execute(ext, msg, code):
261273
if 0x60 <= opcode <= 0x7f:
262274
stk.append(pushcache[compustate.pc - 1])
263275
compustate.pc += opcode - 0x5f # Move 1 byte forward for 0x60, up to 32 bytes for 0x7f
276+
# Arithmetic
264277
elif opcode < 0x10:
265278
if op == 'STOP':
266279
return peaceful_exit('STOP', compustate.gas, [])
@@ -313,6 +326,7 @@ def vm_execute(ext, msg, code):
313326
stk.append(s1 & ((1 << testbit) - 1))
314327
else:
315328
stk.append(s1)
329+
# Comparisons
316330
elif opcode < 0x20:
317331
if op == 'LT':
318332
stk.append(1 if stk.pop() < stk.pop() else 0)
@@ -342,6 +356,7 @@ def vm_execute(ext, msg, code):
342356
stk.append(0)
343357
else:
344358
stk.append((s1 // 256 ** (31 - s0)) % 256)
359+
# SHA3 and environment info
345360
elif opcode < 0x40:
346361
if op == 'SHA3':
347362
s0, s1 = stk.pop(), stk.pop()
@@ -426,6 +441,7 @@ def vm_execute(ext, msg, code):
426441
mem[start + i] = utils.safe_ord(extcode[s2 + i])
427442
else:
428443
mem[start + i] = 0
444+
# Block info
429445
elif opcode < 0x50:
430446
if op == 'BLOCKHASH':
431447
if ext.post_metropolis_hardfork() and False:
@@ -443,6 +459,7 @@ def vm_execute(ext, msg, code):
443459
stk.append(ext.block_difficulty)
444460
elif op == 'GASLIMIT':
445461
stk.append(ext.block_gas_limit)
462+
# VM state manipulations
446463
elif opcode < 0x60:
447464
if op == 'POP':
448465
stk.pop()
@@ -497,13 +514,15 @@ def vm_execute(ext, msg, code):
497514
stk.append(len(mem))
498515
elif op == 'GAS':
499516
stk.append(compustate.gas) # AFTER subtracting cost 1
517+
# DUPn (eg. DUP1: a b c -> a b c c, DUP3: a b c -> a b c a)
500518
elif op[:3] == 'DUP':
501519
stk.append(stk[0x7f - opcode]) # 0x7f - opcode is a negative number, -1 for 0x80 ... -16 for 0x8f
520+
# SWAPn (eg. SWAP1: a b c d -> a b d c, SWAP3: a b c d -> d b c a)
502521
elif op[:4] == 'SWAP':
503522
temp = stk[0x8e - opcode] # 0x8e - opcode is a negative number, -2 for 0x90 ... -17 for 0x9f
504523
stk[0x8e - opcode] = stk[-1]
505524
stk[-1] = temp
506-
525+
# Logs (aka "events")
507526
elif op[:3] == 'LOG':
508527
"""
509528
0xa0 ... 0xa4, 32/64/96/128/160 + len(data) gas
@@ -529,7 +548,7 @@ def vm_execute(ext, msg, code):
529548
ext.log(msg.to, topics, data)
530549
log_log.trace('LOG', to=msg.to, topics=topics, data=list(map(utils.safe_ord, data)))
531550
# print('LOG', msg.to, topics, list(map(ord, data)))
532-
551+
# Create a new contract
533552
elif op == 'CREATE':
534553
value, mstart, msz = stk.pop(), stk.pop(), stk.pop()
535554
if not mem_extend(mem, compustate, op, mstart, msz):
@@ -550,6 +569,7 @@ def vm_execute(ext, msg, code):
550569
compustate.gas = compustate.gas - ingas + gas
551570
else:
552571
stk.append(0)
572+
# Calls
553573
elif op in ('CALL', 'CALLCODE', 'DELEGATECALL', 'STATICCALL'):
554574
# Pull arguments from the stack
555575
if op in ('CALL', 'CALLCODE'):
@@ -567,10 +587,17 @@ def vm_execute(ext, msg, code):
567587
not mem_extend(mem, compustate, op, memoutstart, memoutsz):
568588
return vm_exception('OOG EXTENDING MEMORY')
569589
to = utils.int_to_addr(to)
570-
# Extra gas costs based on hard fork-dependent factors
571-
extra_gas = (not ext.account_exists(to)) * (op == 'CALL') * (value > 0 or not ext.post_spurious_dragon_hardfork()) * opcodes.GCALLNEWACCOUNT + \
572-
(value > 0) * opcodes.GCALLVALUETRANSFER + \
573-
ext.post_anti_dos_hardfork() * opcodes.CALL_SUPPLEMENTAL_GAS
590+
# Extra gas costs based on various factors
591+
extra_gas = 0
592+
# Creating a new account
593+
if op == 'CALL' and not ext.account_exists(to) and (value > 0 or not ext.post_spurious_dragon_hardfork()):
594+
extra_gas += opcodes.GCALLNEWACCOUNT
595+
# Value transfer
596+
if value > 0:
597+
extra_gas += opcodes.GCALLVALUETRANSFER
598+
# Cost increased from 40 to 700 in Tangerine Whistle
599+
if ext.post_anti_dos_hardfork():
600+
extra_gas += opcodes.CALL_SUPPLEMENTAL_GAS
574601
# Compute child gas limit
575602
if ext.post_anti_dos_hardfork():
576603
if compustate.gas < extra_gas:
@@ -617,18 +644,21 @@ def vm_execute(ext, msg, code):
617644
mem[memoutstart + i] = data[i]
618645
compustate.gas += gas
619646
compustate.last_returned = bytearray(data)
647+
# Return opcode
620648
elif op == 'RETURN':
621649
s0, s1 = stk.pop(), stk.pop()
622650
if not mem_extend(mem, compustate, op, s0, s1):
623651
return vm_exception('OOG EXTENDING MEMORY')
624652
return peaceful_exit('RETURN', compustate.gas, mem[s0: s0 + s1])
653+
# Revert opcode (Metropolis)
625654
elif op == 'REVERT':
626655
if not ext.post_metropolis_hardfork():
627656
return vm_exception('Opcode not yet enabled')
628657
s0, s1 = stk.pop(), stk.pop()
629658
if not mem_extend(mem, compustate, op, s0, s1):
630659
return vm_exception('OOG EXTENDING MEMORY')
631660
return revert(compustate.gas, mem[s0: s0 + s1])
661+
# SUICIDE opcode (also called SELFDESTRUCT)
632662
elif op == 'SUICIDE':
633663
if msg.static:
634664
return vm_exception('Cannot SUICIDE inside a static context')
@@ -644,16 +674,13 @@ def vm_execute(ext, msg, code):
644674
ext.set_balance(msg.to, 0)
645675
ext.add_suicide(msg.to)
646676
log_msg.debug('SUICIDING', addr=utils.checksum_encode(msg.to), to=utils.checksum_encode(to), xferring=xfer)
647-
return 1, compustate.gas, []
677+
return peaceful_exit('SUICIDED', compustate.gas, [])
648678

649-
# assert utils.is_numeric(compustate.gas)
650-
# this is slow!
651-
# for a in stk:
652-
# assert is_numeric(a), (op, stk)
653-
# assert a >= 0 and a < 2**256, (a, op, stk)
654679
return peaceful_exit('CODE OUT OF RANGE', compustate.gas, [])
655680

656681

682+
# A stub that's mainly here to show what you would need to implement to
683+
# hook into the EVM
657684
class VmExtBase():
658685

659686
def __init__(self):

0 commit comments

Comments
 (0)