Skip to content

Commit 20e3d44

Browse files
committed
bull crap
1 parent e68e7c3 commit 20e3d44

File tree

4 files changed

+264
-4
lines changed

4 files changed

+264
-4
lines changed

eth/db/account.py

+4-4
Original file line numberDiff line numberDiff line change
@@ -239,11 +239,11 @@ def has_root(self, state_root: bytes) -> bool:
239239
#
240240
# Storage
241241
#
242-
def get_storage(self, address, slot):
242+
def get_storage(self, address, slot, original=False):
243243
validate_canonical_address(address, title="Storage Address")
244244
validate_uint256(slot, title="Storage Slot")
245245

246-
account = self._get_account(address)
246+
account = self._get_account(address, original)
247247
storage = HashTrie(HexaryTrie(self._journaldb, account.storage_root))
248248

249249
slot_as_key = pad32(int_to_big_endian(slot))
@@ -375,8 +375,8 @@ def account_is_empty(self, address):
375375
#
376376
# Internal
377377
#
378-
def _get_account(self, address):
379-
rlp_account = self._journaltrie.get(address, b'')
378+
def _get_account(self, address, no_journal=False):
379+
rlp_account = (self._trie if no_journal else self._journaltrie).get(address, b'')
380380
if rlp_account:
381381
account = rlp.decode(rlp_account, sedes=Account)
382382
else:

eth/vm/forks/constantinople/opcodes.py

+6
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
from eth.vm.logic import (
2020
arithmetic,
2121
context,
22+
storage,
2223
system,
2324
)
2425
from eth.vm.opcode import (
@@ -52,6 +53,11 @@
5253
mnemonic=mnemonics.CREATE2,
5354
gas_cost=constants.GAS_CREATE,
5455
)(),
56+
opcode_values.SSTORE: as_opcode(
57+
logic_fn=storage.sstore_eip1283,
58+
mnemonic=mnemonics.SSTORE,
59+
gas_cost=constants.GAS_NULL,
60+
),
5561
}
5662

5763
CONSTANTINOPLE_OPCODES = merge(

eth/vm/logic/storage.py

+65
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,71 @@ def sstore(computation):
4949
)
5050

5151

52+
def sstore_eip1283(computation):
53+
slot, value = computation.stack_pop(num_items=2, type_hint=constants.UINT256)
54+
55+
current_value = computation.state.account_db.get_storage(
56+
address=computation.msg.storage_address,
57+
slot=slot,
58+
)
59+
60+
original_value = computation.state.account_db.get_storage(
61+
address=computation.msg.storage_address,
62+
slot=slot,
63+
original=True
64+
)
65+
66+
is_currently_empty = not bool(current_value)
67+
is_going_to_be_empty = not bool(value)
68+
69+
gas_refund = 0
70+
71+
if current_value == value:
72+
gas_cost = 200
73+
else:
74+
if original_value == current_value:
75+
if original_value == 0:
76+
gas_cost = 20000
77+
else:
78+
gas_cost = 5000
79+
80+
if value == 0:
81+
gas_refund += 15000
82+
else:
83+
gas_cost = 200
84+
85+
if original_value != 0:
86+
if current_value == 0:
87+
gas_refund -= 15000
88+
if value == 0:
89+
gas_refund += 15000
90+
91+
if original_value == value:
92+
if original_value == 0:
93+
gas_refund += 19800
94+
else:
95+
gas_refund += 4800
96+
97+
computation.consume_gas(
98+
gas_cost,
99+
reason="SSTORE: {0}[{1}] -> {2} (current: {3} / original: {4})".format(
100+
encode_hex(computation.msg.storage_address),
101+
slot,
102+
value,
103+
current_value,
104+
original_value,
105+
))
106+
107+
if gas_refund:
108+
computation.refund_gas(gas_refund)
109+
110+
computation.state.account_db.set_storage(
111+
address=computation.msg.storage_address,
112+
slot=slot,
113+
value=value,
114+
)
115+
116+
52117
def sload(computation):
53118
slot = computation.stack_pop(type_hint=constants.UINT256)
54119

tests/core/opcodes/test_opcodes.py

+189
Original file line numberDiff line numberDiff line change
@@ -456,3 +456,192 @@ def test_extcodehash(vm_class, address, expected):
456456

457457
result = computation.stack_pop(type_hint=constants.BYTES)
458458
assert encode_hex(pad32(result)) == expected
459+
460+
461+
@pytest.mark.parametrize(
462+
# Testcases from https://github.com/ethereum/EIPs/blob/master/EIPS/eip-145.md#shl-shift-left
463+
'vm_class, code, gas_used, refund, original',
464+
(
465+
(
466+
ByzantiumVM,
467+
'0x60006000556000600055',
468+
10012,
469+
0,
470+
0,
471+
),
472+
(
473+
ByzantiumVM,
474+
'0x60006000556001600055',
475+
25012,
476+
0,
477+
0,
478+
),
479+
(
480+
ConstantinopleVM,
481+
'0x60006000556000600055',
482+
412,
483+
0,
484+
0,
485+
),
486+
(
487+
ConstantinopleVM,
488+
'0x60006000556001600055',
489+
20212,
490+
0,
491+
0,
492+
),
493+
(
494+
ConstantinopleVM,
495+
'0x60016000556000600055',
496+
20212,
497+
19800,
498+
0,
499+
),
500+
(
501+
ConstantinopleVM,
502+
'0x60016000556002600055',
503+
20212,
504+
0,
505+
0,
506+
),
507+
(
508+
ConstantinopleVM,
509+
'0x60016000556001600055',
510+
20212,
511+
0,
512+
0,
513+
),
514+
(
515+
ConstantinopleVM,
516+
'0x60006000556000600055',
517+
5212,
518+
15000,
519+
1,
520+
),
521+
# (
522+
# ConstantinopleVM,
523+
# '0x60006000556001600055',
524+
# 5212,
525+
# 4800,
526+
# 1,
527+
# ),
528+
# (
529+
# ConstantinopleVM,
530+
# '0x60006000556002600055',
531+
# 5212,
532+
# 0,
533+
# 1,
534+
# ),
535+
(
536+
ConstantinopleVM,
537+
'0x60026000556000600055',
538+
5212,
539+
15000,
540+
1,
541+
),
542+
(
543+
ConstantinopleVM,
544+
'0x60026000556003600055',
545+
5212,
546+
0,
547+
1,
548+
),
549+
(
550+
ConstantinopleVM,
551+
'0x60026000556001600055',
552+
5212,
553+
4800,
554+
1,
555+
),
556+
(
557+
ConstantinopleVM,
558+
'0x60026000556002600055',
559+
5212,
560+
0,
561+
1,
562+
),
563+
(
564+
ConstantinopleVM,
565+
'0x60016000556000600055',
566+
5212,
567+
15000,
568+
1,
569+
),
570+
(
571+
ConstantinopleVM,
572+
'0x60016000556002600055',
573+
5212,
574+
0,
575+
1,
576+
),
577+
(
578+
ConstantinopleVM,
579+
'0x60016000556001600055',
580+
412,
581+
0,
582+
1,
583+
),
584+
(
585+
ConstantinopleVM,
586+
'0x600160005560006000556001600055',
587+
40218,
588+
19800,
589+
0,
590+
),
591+
# (
592+
# ConstantinopleVM,
593+
# '0x600060005560016000556000600055',
594+
# 10218,
595+
# 19800,
596+
# 1,
597+
# ),
598+
)
599+
)
600+
def test_sstore(vm_class, code, gas_used, refund, original):
601+
computation = shit_to_be_refactored(
602+
vm_class,
603+
code=decode_hex(code),
604+
original_storage_value=original
605+
)
606+
607+
comp = computation.apply_message()
608+
assert comp.get_gas_refund() == refund
609+
assert comp.get_gas_used() == gas_used
610+
611+
612+
def shit_to_be_refactored(vm_class,
613+
data=b'',
614+
init_code=b'',
615+
code=b'',
616+
original_storage_value=0,
617+
gas=10000000000000000):
618+
619+
message = Message(
620+
to=CANONICAL_ADDRESS_A,
621+
sender=CANONICAL_ADDRESS_B,
622+
create_address=CANONICAL_ADDRESS_B,
623+
value=100,
624+
data=data,
625+
code=code,
626+
gas=gas,
627+
)
628+
629+
tx_context = vm_class._state_class.transaction_context_class(
630+
gas_price=1,
631+
origin=CANONICAL_ADDRESS_B,
632+
)
633+
634+
#vm = chain.get_vm()
635+
vm = vm_class(GENESIS_HEADER, ChainDB(AtomicDB()))
636+
637+
computation = vm_class._state_class.computation_class(
638+
state=vm.state,
639+
message=message,
640+
transaction_context=tx_context,
641+
)
642+
643+
computation.state.account_db.set_balance(CANONICAL_ADDRESS_B, 100000000000)
644+
computation.state.account_db.set_storage(CANONICAL_ADDRESS_B, 0, original_storage_value)
645+
computation.state.account_db.persist()
646+
647+
return computation

0 commit comments

Comments
 (0)