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

Commit d1da7ea

Browse files
vubvub
authored andcommitted
EIP 97
1 parent f78ff08 commit d1da7ea

File tree

4 files changed

+60
-9
lines changed

4 files changed

+60
-9
lines changed

ethereum/blocks.py

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -965,7 +965,7 @@ def reset_storage(self, address):
965965
for k in self.caches[CACHE_KEY]:
966966
self.set_and_journal(CACHE_KEY, k, 0)
967967

968-
def get_storage_data(self, address, index):
968+
def get_storage_bytes(self, address, index):
969969
"""Get a specific item in the storage of an account.
970970
971971
:param address: the address of the account (binary or hex string)
@@ -981,9 +981,16 @@ def get_storage_data(self, address, index):
981981
key = utils.zpad(utils.coerce_to_bytes(index), 32)
982982
storage = self.get_storage(address).get(key)
983983
if storage:
984-
return rlp.decode(storage, big_endian_int)
984+
return rlp.decode(storage)
985+
else:
986+
return ''
987+
988+
def get_storage_data(self, address, index):
989+
bytez = self.get_storage_bytes(address, index)
990+
if len(bytez) >= 32:
991+
return big_endian_to_int(bytez[-32:])
985992
else:
986-
return 0
993+
return big_endian_to_int(bytez) * (1 << (8 * (32 - len(bytes))))
987994

988995
def set_storage_data(self, address, index, value):
989996
"""Set a specific item in the storage of an account.

ethereum/opcodes.py

Lines changed: 16 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,9 @@
6161
0xa2: ['LOG2', 4, 0, 1125],
6262
0xa3: ['LOG3', 5, 0, 1500],
6363
0xa4: ['LOG4', 6, 0, 1875],
64+
0xe1: ['SLOADBYTES', 3, 0, 50],
65+
0xe2: ['SSTOREBYTES', 3, 0, 0],
66+
0xe3: ['SSIZE', 1, 1, 50],
6467
0xf0: ['CREATE', 3, 1, 32000],
6568
0xf1: ['CALL', 7, 1, 40],
6669
0xf2: ['CALLCODE', 7, 1, 40],
@@ -85,10 +88,7 @@
8588
GDEFAULT = 1
8689
GMEMORY = 3
8790
GQUADRATICMEMDENOM = 512 # 1 gas per 512 quadwords
88-
GSTORAGEREFUND = 15000
89-
GSTORAGEKILL = 5000
90-
GSTORAGEMOD = 5000
91-
GSTORAGEADD = 20000
91+
9292
GEXPONENTBYTE = 10 # cost of EXP exponent per byte
9393
GCOPY = 3 # cost to copy one 32 byte word
9494
GCONTRACTBYTE = 200 # one byte of code in contract creation
@@ -111,3 +111,15 @@
111111

112112
GCALLNEWACCOUNT = 25000
113113
GSUICIDEREFUND = 24000
114+
115+
GSTORAGEBASE = 2500
116+
GSTORAGEBYTESTORAGE = 250
117+
GSTORAGEBYTECHANGE = 40
118+
GSTORAGEMIN = 2500
119+
GSSIZE = 50
120+
GSLOADBYTES = 50
121+
122+
GSTORAGEREFUND = 15000
123+
GSTORAGEKILL = 5000
124+
GSTORAGEMOD = 5000
125+
GSTORAGEADD = 20000

ethereum/processblock.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -230,6 +230,7 @@ def __init__(self, block, tx):
230230
self.set_nonce = block.set_nonce
231231
self.set_storage_data = block.set_storage_data
232232
self.get_storage_data = block.get_storage_data
233+
self.get_storage_bytes = block.get_storage_bytes
233234
self.log_storage = lambda x: block.account_to_dict(x)['storage']
234235
self.add_suicide = lambda x: block.suicides.append(x)
235236
self.add_refund = lambda x: \

ethereum/vm.py

Lines changed: 33 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212
import time
1313
from ethereum.slogging import get_logger
1414
from rlp.utils import encode_hex, ascii_chr
15-
from ethereum.utils import to_string
15+
from ethereum.utils import to_string, encode_int, zpad
1616

1717
log_log = get_logger('eth.vm.log')
1818
log_vm_exit = get_logger('eth.vm.exit')
@@ -435,7 +435,7 @@ def vm_execute(ext, msg, code):
435435
return vm_exception('OUT OF GAS')
436436
compustate.gas -= gascost
437437
ext.add_refund(refund) # adds neg gascost as a refund if below zero
438-
ext.set_storage_data(msg.to, s0, s1)
438+
ext.set_storage_data(msg.to, s0, zpad(encode_int(s1), 32))
439439
elif op == 'JUMP':
440440
compustate.pc = stk.pop()
441441
opnew = processed_code[compustate.pc][0] if \
@@ -456,6 +456,37 @@ def vm_execute(ext, msg, code):
456456
stk.append(len(mem))
457457
elif op == 'GAS':
458458
stk.append(compustate.gas) # AFTER subtracting cost 1
459+
elif 0xe0 <= opcode < 0xef:
460+
if not ext.post_metropolis_hardfork():
461+
return vm_exception('OPCODE RANGE INACTIVE', opcode=opcode)
462+
if op == 'SLOADBYTES':
463+
key, mstart, msize = stk.pop(), stk.pop(), stk.pop()
464+
bytez = map(ord, ext.get_storage_bytes(msg.to, key))
465+
if not mem_extend(mem, compustate, op, mstart, min(msize, mstart + len(bytez))):
466+
return vm_exception('OOG EXTENDING MEMORY')
467+
for i in range(min(msize, len(bytez))):
468+
mem[mstart + i] = bytez[i]
469+
stk.append(ext.get_storage_data(msg.to, stk.pop()))
470+
elif op == 'SSTOREBYTES':
471+
key, mstart, msize = stk.pop(), stk.pop(), stk.pop()
472+
if not mem_extend(mem, compustate, op, mstart, min(msize, mstart + len(bytez))):
473+
return vm_exception('OOG EXTENDING MEMORY')
474+
prev_adjbyte_count = len(ext.get_storage_data(msg.to, key))
475+
if prev_adjbyte_count >= 0:
476+
prev_adjbyte_count += 32
477+
post_adjbyte_count = msize + (32 if msize else 0)
478+
gas_cost = opcodes.GSTORAGEBASE + opcodes.GSTORAGEBYTESTORAGE * \
479+
(post_adjbyte_count - prev_adjbyte_count) + opcodes.GSTORAGEBYTECHANGE * post_adjbyte_count
480+
gas_payment = max(opcodes.GSTORAGEMIN, gas_cost)
481+
refund = gas_payment - gas_cost
482+
if compustate.gas < gas_payment:
483+
return vm_exception('OUT OF GAS')
484+
compustate.gas -= gas_payment
485+
data = ''.join(map(chr, mem[mstart: mstart + msize]))
486+
ext.set_storage_data(msg.to, data)
487+
ext.add_refund(refund)
488+
elif op == 'SSIZE':
489+
stk.append(len(ext.get_storage_bytes(msg.to, stk.pop())))
459490
elif op[:4] == 'PUSH':
460491
pushnum = int(op[4:])
461492
compustate.pc += pushnum

0 commit comments

Comments
 (0)