Skip to content

Commit

Permalink
Add SHL Opcode for Constantinople
Browse files Browse the repository at this point in the history
Relates to #1104
  • Loading branch information
cburgdorf committed Jul 31, 2018
1 parent 222ef9f commit d2fc10c
Show file tree
Hide file tree
Showing 7 changed files with 140 additions and 4 deletions.
3 changes: 3 additions & 0 deletions eth/constants.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,9 @@
UINT256 = 'uint256'
BYTES = 'bytes'

CONST_256 = 256
CONST_0 = 0

UINT_256_MAX = 2**256 - 1
UINT_256_CEILING = 2**256
UINT_255_MAX = 2**255 - 1
Expand Down
29 changes: 28 additions & 1 deletion eth/vm/forks/constantinople/opcodes.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,35 @@
import copy
from cytoolz import (
merge
)

from eth import (
constants
)
from eth.vm import (
mnemonics,
opcode_values,
)
from eth.vm.forks.byzantium.opcodes import (
BYZANTIUM_OPCODES
)
from eth.vm.logic import (
arithmetic
)
from eth.vm.opcode import (
as_opcode
)


UPDATED_OPCODES = {
opcode_values.SHL: as_opcode(
logic_fn=arithmetic.shl,
mnemonic=mnemonics.SHL,
gas_cost=constants.GAS_VERYLOW,
),
}

CONSTANTINOPLE_OPCODES = copy.deepcopy(BYZANTIUM_OPCODES)
CONSTANTINOPLE_OPCODES = merge(
copy.deepcopy(BYZANTIUM_OPCODES),
UPDATED_OPCODES,
)
18 changes: 18 additions & 0 deletions eth/vm/logic/arithmetic.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
from BitVector import (
BitVector
)
from cytoolz import (
curry,
)
Expand Down Expand Up @@ -177,3 +180,18 @@ def signextend(computation):
result = value

computation.stack_push(result)


def shl(computation):
"""
Bitwise left shift
"""
shift_length, value = computation.stack_pop(num_items=2, type_hint=constants.UINT256)
bit_vector = BitVector(intVal=value, size=constants.CONST_256)

if shift_length >= constants.CONST_256:
result = constants.CONST_0
else:
result = bit_vector.shift_left(shift_length).int_val()

computation.stack_push(result)
1 change: 1 addition & 0 deletions eth/vm/mnemonics.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
MULMOD = 'MULMOD'
EXP = 'EXP'
SIGNEXTEND = 'SIGNEXTEND'
SHL = 'SHL'
#
# Comparisons
#
Expand Down
1 change: 1 addition & 0 deletions eth/vm/opcode_values.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
XOR = 0x18
NOT = 0x19
BYTE = 0x1a
SHL = 0x1b


#
Expand Down
1 change: 1 addition & 0 deletions setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@

deps = {
'eth': [
"BitVector>=3.4.8, <4.0.0",
"cryptography>=2.0.3,<3.0.0",
"cytoolz>=0.9.0,<1.0.0",
"eth-bloom>=1.0.0,<2.0.0",
Expand Down
91 changes: 88 additions & 3 deletions tests/core/opcodes/test_opcodes.py
Original file line number Diff line number Diff line change
@@ -1,19 +1,23 @@
import pytest

from eth_utils import (
decode_hex,
encode_hex,
to_canonical_address,
int_to_big_endian,
)

from eth import (
constants
)
from eth.utils.padding import (
pad32
)
from eth.vm import (
opcode_values
)
from eth.vm.forks.byzantium.opcodes import (
BYZANTIUM_OPCODES
)
from eth.vm.forks import (
ConstantinopleVM,
ByzantiumVM,
SpuriousDragonVM,
TangerineWhistleVM,
Expand Down Expand Up @@ -98,3 +102,84 @@ def test_mul(vm_class, val1, val2, expected):
assert result == expected


@pytest.mark.parametrize(
# Testcases from https://github.com/ethereum/EIPs/blob/master/EIPS/eip-145.md#shl-shift-left
'vm_class, val1, val2, expected',
(
(
ConstantinopleVM,
'0x0000000000000000000000000000000000000000000000000000000000000001',
'0x00',
'0x0000000000000000000000000000000000000000000000000000000000000001',
),
(
ConstantinopleVM,
'0x0000000000000000000000000000000000000000000000000000000000000001',
'0x01',
'0x0000000000000000000000000000000000000000000000000000000000000002',
),
(
ConstantinopleVM,
'0x0000000000000000000000000000000000000000000000000000000000000001',
'0xff',
'0x8000000000000000000000000000000000000000000000000000000000000000',
),
(
ConstantinopleVM,
'0x0000000000000000000000000000000000000000000000000000000000000001',
'0x0100',
'0x0000000000000000000000000000000000000000000000000000000000000000',
),
(
ConstantinopleVM,
'0x0000000000000000000000000000000000000000000000000000000000000001',
'0x0101',
'0x0000000000000000000000000000000000000000000000000000000000000000',
),
(
ConstantinopleVM,
'0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff',
'0x00',
'0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff',
),
(
ConstantinopleVM,
'0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff',
'0x01',
'0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe',
),
(
ConstantinopleVM,
'0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff',
'0xff',
'0x8000000000000000000000000000000000000000000000000000000000000000',
),
(
ConstantinopleVM,
'0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff',
'0x0100',
'0x0000000000000000000000000000000000000000000000000000000000000000',
),
(
ConstantinopleVM,
'0x0000000000000000000000000000000000000000000000000000000000000000',
'0x01',
'0x0000000000000000000000000000000000000000000000000000000000000000',
),
(
ConstantinopleVM,
'0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff',
'0x01',
'0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe',
),
)
)
def test_shl(vm_class, val1, val2, expected):
computation = prepare_computation(vm_class)
computation.stack_push(decode_hex(val1))
computation.stack_push(decode_hex(val2))
computation.opcodes[opcode_values.SHL](computation)

result = computation.stack_pop(type_hint=constants.UINT256)

assert encode_hex(pad32(int_to_big_endian(result))) == expected

0 comments on commit d2fc10c

Please sign in to comment.