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

Commit 2e76eb8

Browse files
author
Jan Xie
committed
Merge branch 'fix-vm-memory-leak' into eth-wire-protocol-p62
2 parents 63802b8 + 80eb9c9 commit 2e76eb8

15 files changed

+278
-141
lines changed

.release_notify.sh

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,6 @@
11
#!/usr/bin/env sh
22
PAYLOAD="{\"text\": \"<https://pypi.python.org/pypi/ethereum|ethereum $TRAVIS_TAG> was released on pypi!\"}"
33
curl -s -X POST --data-urlencode "payload=$PAYLOAD" $SLACK_WEBHOOK_URL
4+
5+
PAYLOAD="{\"attachments\":[{\"text\":\"[ethereum $TRAVIS_TAG](https://pypi.org/project/ethereum) was released on PyPI!\",\"color\":\"good\"}]}"
6+
curl -s -X POST --data-urlencode "payload=$PAYLOAD" $ROCKETCHAT_URL

.travis.yml

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ env:
1414
global:
1515
- COVERAGE_APPEND="--append"
1616
- secure: cKbIgpTJ1yjKLBxpCEiT6IH7NShDWZUE+BvnrAfc+ujCsR6LyLJcKxFQmKnWryJCqg7fp82Ep2bF2oDKzanAROar2xDY1SFGbai42seYMaFCw53YPGJ6u3VNCcfT0rN9BWgE7el/m4fjcD6CRsZYKArNNJbMX8csRt3uXXCFLso=
17+
- secure: "QyFPrxQHd2LlNQ6zNeTFYhgPmZaOHoWuywcgn8qaSOh6PklyFxHbexkwg0bl23JvtgNEZ1mCD8j0x1/ydSdtxgCFwK9SEL0h7aYuAq+OAIa/G18OPeTJMf7ASsb2QZdfkt9reFpUnjbadzHkuv+rqqb4bFnTJBKwB2LWzHPLhWg="
1718
install:
1819
- travis_retry pip install setuptools --upgrade
1920
- travis_retry pip install tox
@@ -27,11 +28,12 @@ script:
2728
after_success:
2829
- travis_retry pip install coveralls
2930
- cd .tox/$TOX_ENV && coveralls
30-
after_script:
31-
- cat .tox/$TOX_ENV/log/*.log; true
3231
notifications:
3332
slack:
3433
secure: W/UAhQ/GgYwMWrl3aiVAVOWr4WGdWrxUOX/rTB3ZgwDwGqDYLzQO5UqbsQlo1JXPZ6JOWfIPMURhHu7DSfue9dBW6xQ+NL+bFHe9lSXG4nqFK3IjezYyTBzNRJRDbGUvSSqgj6D5cwhJ8BjfUIRPbJz3CxL64KmsNXezEaMY60w=
34+
webhooks:
35+
- secure: "KBw4iPJVsw3qv0qbvkZ2tjams/280aEovJ88ylR9ClI2krtxJFoVlAB0YdkztpKxcAxbIZg8nd4S3XpeOUsxfoZq5mZ2wHNU7G8LjqjwZ7eOhj76K+NAnEhRQT2evqZkWqP0h5fxuXQaT4KjwxGkxGNDEMJUVH5RO2cnFUQO98s="
36+
3537
before_deploy:
3638
- cd $TRAVIS_BUILD_DIR
3739
deploy:

ethereum/_solidity.py

Lines changed: 45 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
import re
44
import subprocess
55
import warnings
6+
import shlex
67

78
import yaml
89

@@ -22,6 +23,11 @@ def get_compiler_path():
2223
This funtion will search for the solc binary in the $PATH and return the
2324
path of the first executable occurence.
2425
"""
26+
# If the user provides a specific solc binary let's use that
27+
given_binary = os.environ.get('SOLC_BINARY')
28+
if given_binary:
29+
return given_binary
30+
2531
for path in os.getenv('PATH', '').split(os.pathsep):
2632
path = path.strip('"')
2733
executable_path = os.path.join(path, BINARY)
@@ -40,16 +46,22 @@ def get_solidity():
4046
return solc_wrapper
4147

4248

43-
def solc_arguments(libraries=None, combined='bin,abi', optimize=True):
49+
def solc_arguments(libraries=None, combined='bin,abi', optimize=True, extra_args=None):
4450
""" Build the arguments to call the solc binary. """
4551
args = [
4652
'--combined-json', combined,
47-
'--add-std',
53+
'--add-std'
4854
]
4955

5056
if optimize:
5157
args.append('--optimize')
5258

59+
if extra_args:
60+
try:
61+
args.extend(shlex.split(extra_args))
62+
except: # if not a parseable string then treat it as a list
63+
args.extend(extra_args)
64+
5365
if libraries is not None and len(libraries):
5466
addresses = [
5567
'{name}:{address}'.format(name=name, address=address.decode('utf8'))
@@ -65,6 +77,10 @@ def solc_arguments(libraries=None, combined='bin,abi', optimize=True):
6577

6678
def solc_parse_output(compiler_output):
6779
""" Parses the compiler output. """
80+
# At the moment some solc output like --hashes or -- gas will not output
81+
# json at all so if used with those arguments the logic here will break.
82+
# Perhaps solidity will slowly switch to a json only output and this comment
83+
# can eventually go away and we will not need to add more logic here at all.
6884
result = yaml.safe_load(compiler_output)['contracts']
6985

7086
if 'bin' in tuple(result.values())[0]:
@@ -93,7 +109,7 @@ def solc_parse_output(compiler_output):
93109
def compiler_version():
94110
""" Return the version of the installed solc. """
95111
version_info = subprocess.check_output(['solc', '--version'])
96-
match = re.search('^Version: ([0-9a-z.-]+)/', version_info, re.MULTILINE)
112+
match = re.search(b'^Version: ([0-9a-z.-]+)/', version_info, re.MULTILINE)
97113

98114
if match:
99115
return match.group(1)
@@ -185,7 +201,7 @@ def solidity_resolve_address(hex_code, library_symbol, library_address):
185201
raise ValueError('Address should not contain the 0x prefix')
186202

187203
try:
188-
_ = decode_hex(library_address)
204+
decode_hex(library_address)
189205
except TypeError:
190206
raise ValueError('library_address contains invalid characters, it must be hex encoded.')
191207

@@ -221,7 +237,7 @@ def solidity_unresolved_symbols(hex_code):
221237
return set(re.findall(r"_.{39}", hex_code))
222238

223239

224-
def compile_file(filepath, libraries=None, combined='bin,abi', optimize=True):
240+
def compile_file(filepath, libraries=None, combined='bin,abi', optimize=True, extra_args=None):
225241
""" Return the compile contract code.
226242
227243
Args:
@@ -236,7 +252,7 @@ def compile_file(filepath, libraries=None, combined='bin,abi', optimize=True):
236252

237253
workdir, filename = os.path.split(filepath)
238254

239-
args = solc_arguments(libraries=libraries, combined=combined, optimize=optimize)
255+
args = solc_arguments(libraries=libraries, combined=combined, optimize=optimize, extra_args=extra_args)
240256
args.insert(0, get_compiler_path())
241257
args.append(filename)
242258

@@ -245,18 +261,19 @@ def compile_file(filepath, libraries=None, combined='bin,abi', optimize=True):
245261
return solc_parse_output(output)
246262

247263

248-
def compile_contract(filepath, contract_name, libraries=None, combined='bin,abi', optimize=True):
264+
def compile_contract(filepath, contract_name, libraries=None, combined='bin,abi', optimize=True, extra_args=None):
249265
all_contracts = compile_file(
250266
filepath,
251267
libraries=libraries,
252268
combined=combined,
253269
optimize=optimize,
270+
extra_args=extra_args
254271
)
255272

256273
return all_contracts[contract_name]
257274

258275

259-
def compile_last_contract(filepath, libraries=None, combined='bin,abi', optimize=True):
276+
def compile_last_contract(filepath, libraries=None, combined='bin,abi', optimize=True, extra_args=None):
260277
with open(filepath) as handler:
261278
all_names = solidity_names(handler.read())
262279

@@ -273,11 +290,12 @@ def compile_last_contract(filepath, libraries=None, combined='bin,abi', optimize
273290
libraries=libraries,
274291
combined=combined,
275292
optimize=optimize,
293+
extra_args=extra_args
276294
)
277295

278296

279-
def compile_code(sourcecode, libraries=None, combined='bin,abi', optimize=True):
280-
args = solc_arguments(libraries=libraries, combined=combined, optimize=optimize)
297+
def compile_code(sourcecode, libraries=None, combined='bin,abi', optimize=True, extra_args=None):
298+
args = solc_arguments(libraries=libraries, combined=combined, optimize=optimize, extra_args=extra_args)
281299
args.insert(0, get_compiler_path())
282300

283301
process = subprocess.Popen(args, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
@@ -297,17 +315,17 @@ class Solc(object):
297315
compiler_version = staticmethod(compiler_version)
298316

299317
@staticmethod
300-
def _code_or_path(sourcecode, path, contract_name, libraries, combined):
318+
def _code_or_path(sourcecode, path, contract_name, libraries, combined, extra_args):
301319
warnings.warn('solc_wrapper is deprecated, please use the functions compile_file or compile_code')
302320

303321
if sourcecode and path:
304322
raise ValueError('sourcecode and path are mutually exclusive.')
305323

306324
if path and contract_name:
307-
return compile_contract(path, contract_name, libraries=libraries, combined=combined)
325+
return compile_contract(path, contract_name, libraries=libraries, combined=combined, extra_args=extra_args)
308326

309327
if path:
310-
return compile_last_contract(path, libraries=libraries, combined=combined)
328+
return compile_last_contract(path, libraries=libraries, combined=combined, extra_args=extra_args)
311329

312330
all_names = solidity_names(sourcecode)
313331
all_contract_names = [
@@ -316,41 +334,44 @@ def _code_or_path(sourcecode, path, contract_name, libraries, combined):
316334
]
317335
last_contract = all_contract_names[-1]
318336

319-
result = compile_code(sourcecode, libraries=libraries, combined=combined)
337+
result = compile_code(sourcecode, libraries=libraries, combined=combined, extra_args=extra_args)
320338
return result[last_contract]
321339

322340
@classmethod
323-
def compile(cls, code, path=None, libraries=None, contract_name=''):
341+
def compile(cls, code, path=None, libraries=None, contract_name='', extra_args=None):
324342
""" Return the binary of last contract in code. """
325-
result = cls._code_or_path(code, path, contract_name, libraries, 'bin')
343+
result = cls._code_or_path(code, path, contract_name, libraries, 'bin', extra_args)
326344
return result['bin']
327345

328346
@classmethod
329-
def mk_full_signature(cls, code, path=None, libraries=None, contract_name=''):
347+
def mk_full_signature(cls, code, path=None, libraries=None, contract_name='', extra_args=None):
330348
"returns signature of last contract in code"
331349

332-
result = cls._code_or_path(code, path, contract_name, libraries, 'abi')
350+
result = cls._code_or_path(code, path, contract_name, libraries, 'abi', extra_args)
333351
return result['abi']
334352

335353
@classmethod
336-
def combined(cls, code, path=None):
354+
def combined(cls, code, path=None, extra_args=None):
337355
""" Compile combined-json with abi,bin,devdoc,userdoc.
338356
339357
@param code: literal solidity code as a string.
340-
@param path: absolute path to solidity-file. Note: code & path are exclusive!
358+
@param path: absolute path to solidity-file. Note: code & path are
359+
mutually exclusive!
360+
@param extra_args: Either a space separated string or a list of extra
361+
arguments to be passed to the solidity compiler.
341362
"""
342363

343364
if code and path:
344365
raise ValueError('sourcecode and path are mutually exclusive.')
345366

346367
if path:
347-
contracts = compile_file(path)
368+
contracts = compile_file(path, extra_args=extra_args)
348369

349370
with open(path) as handler:
350371
code = handler.read()
351372

352373
elif code:
353-
contracts = compile_code(code)
374+
contracts = compile_code(code, extra_args=extra_args)
354375

355376
else:
356377
raise ValueError('either code or path needs to be supplied.')
@@ -361,7 +382,7 @@ def combined(cls, code, path=None):
361382
return sorted_contracts
362383

363384
@classmethod
364-
def compile_rich(cls, code, path=None):
385+
def compile_rich(cls, code, path=None, extra_args=None):
365386
"""full format as returned by jsonrpc"""
366387

367388
return {
@@ -378,7 +399,7 @@ def compile_rich(cls, code, path=None):
378399
},
379400
}
380401
for contract_name, contract
381-
in cls.combined(code, path=path)
402+
in cls.combined(code, path=path, extra_args=extra_args)
382403
}
383404

384405

ethereum/config.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,9 @@
6464
DAO_FORK_BLKEXTRA=decode_hex('64616f2d686172642d666f726b'),
6565
CHILD_DAO_LIST=map(utils.normalize_address, child_dao_list),
6666
DAO_WITHDRAWER=utils.normalize_address('0xbf4ed7b27f1d666546e30d74d50d173d20bca754'),
67+
# Anti-DoS fork
68+
ANTI_DOS_FORK_BLKNUM=2457000,
69+
CLEARING_FORK_BLKNUM=2 ** 98,
6770
)
6871
assert default_config['NEPHEW_REWARD'] == \
6972
default_config['BLOCK_REWARD'] // 32

ethereum/fastvm.py

Lines changed: 7 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -8,14 +8,17 @@
88
import sys
99

1010
from ethereum import utils
11-
from ethereum.abi import is_numeric
1211
import copy
1312
from ethereum import opcodes
1413
import time
1514
from ethereum.slogging import get_logger
1615
from rlp.utils import encode_hex, ascii_chr
1716
from ethereum.utils import to_string
18-
import numpy
17+
18+
if sys.version_info.major == 2:
19+
from repoze.lru import lru_cache
20+
else:
21+
from functools import lru_cache
1922

2023
log_log = get_logger('eth.vm.log')
2124
log_vm_exit = get_logger('eth.vm.exit')
@@ -99,6 +102,7 @@ def __init__(self, **kwargs):
99102

100103
# Preprocesses code, and determines which locations are in the middle
101104
# of pushdata and thus invalid
105+
@lru_cache(128)
102106
def preprocess_code(code):
103107
assert isinstance(code, bytes)
104108
code = memoryview(code).tolist()
@@ -185,8 +189,6 @@ def peaceful_exit(cause, gas, data, **kargs):
185189
log_vm_exit.trace('EXIT', cause=cause, **kargs)
186190
return 1, gas, data
187191

188-
code_cache = {}
189-
190192

191193
def vm_execute(ext, msg, code):
192194
# precompute trace flag
@@ -197,11 +199,7 @@ def vm_execute(ext, msg, code):
197199
stk = compustate.stack
198200
mem = compustate.memory
199201

200-
if code in code_cache:
201-
processed_code = code_cache[code]
202-
else:
203-
processed_code = preprocess_code(code)
204-
code_cache[code] = processed_code
202+
processed_code = preprocess_code(code)
205203

206204
s = time.time()
207205
op = None

ethereum/opcodes.py

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -111,3 +111,12 @@
111111

112112
GCALLNEWACCOUNT = 25000
113113
GSUICIDEREFUND = 24000
114+
115+
# Anti-DoS HF changes
116+
SLOAD_SUPPLEMENTAL_GAS = 150
117+
CALL_SUPPLEMENTAL_GAS = 660
118+
EXTCODELOAD_SUPPLEMENTAL_GAS = 680
119+
BALANCE_SUPPLEMENTAL_GAS = 380
120+
CALL_CHILD_LIMIT_NUM = 63
121+
CALL_CHILD_LIMIT_DENOM = 64
122+
SUICIDE_SUPPLEMENTAL_GAS = 5000

ethereum/processblock.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -248,7 +248,8 @@ def __init__(self, block, tx):
248248
self.create = lambda msg: create_contract(self, msg)
249249
self.msg = lambda msg: _apply_msg(self, msg, self.get_code(msg.code_address))
250250
self.account_exists = block.account_exists
251-
self.post_homestead_hardfork = lambda: block.number >= block.config['HOMESTEAD_FORK_BLKNUM']
251+
self.post_homestead_hardfork = block.number >= block.config['HOMESTEAD_FORK_BLKNUM']
252+
self.post_anti_dos_hardfork = block.number >= block.config['ANTI_DOS_FORK_BLKNUM']
252253

253254

254255
def apply_msg(ext, msg):

0 commit comments

Comments
 (0)