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

Commit b9416aa

Browse files
committed
Merge branch 'develop' of https://github.com/ethereum/pyethereum into develop
2 parents ceb0d18 + c58f1b7 commit b9416aa

File tree

6 files changed

+208
-15
lines changed

6 files changed

+208
-15
lines changed

ethereum/_solidity.py

Lines changed: 134 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,134 @@
1+
import subprocess
2+
import os
3+
4+
5+
class CompileError(Exception):
6+
pass
7+
8+
9+
class solc_wrapper(object):
10+
11+
"wraps solc binary"
12+
13+
@classmethod
14+
def compiler_available(cls):
15+
program = 'solc'
16+
17+
def is_exe(fpath):
18+
return os.path.isfile(fpath) and os.access(fpath, os.X_OK)
19+
20+
fpath, fname = os.path.split(program)
21+
if fpath:
22+
if is_exe(program):
23+
return program
24+
else:
25+
for path in os.environ["PATH"].split(os.pathsep):
26+
path = path.strip('"')
27+
exe_file = os.path.join(path, program)
28+
if is_exe(exe_file):
29+
return exe_file
30+
31+
return None
32+
33+
@classmethod
34+
def split_contracts(cls, code):
35+
contracts = []
36+
contract = None
37+
for line in code.split('\n'):
38+
if line.lstrip().startswith('contract '): # FIXME
39+
if contract:
40+
contracts.append('\n'.join(contract))
41+
contract = [line]
42+
elif contract:
43+
contract.append(line)
44+
if contract:
45+
contracts.append('\n'.join(contract))
46+
return contracts
47+
48+
@classmethod
49+
def compile(cls, code):
50+
p = subprocess.Popen(['solc', '--binary', 'stdout'],
51+
stdin=subprocess.PIPE, stdout=subprocess.PIPE)
52+
stdoutdata, stderrdata = p.communicate(input=code)
53+
if p.returncode:
54+
raise CompileError('compilation failed')
55+
56+
hex_code = stdoutdata.rsplit('Binary: \n')[-1].strip()
57+
return hex_code.decode('hex')
58+
59+
@classmethod
60+
def mk_full_signature(cls, code):
61+
p = subprocess.Popen(['solc', '--json-abi', 'stdout'],
62+
stdin=subprocess.PIPE, stdout=subprocess.PIPE)
63+
stdoutdata, stderrdata = p.communicate(input=code)
64+
if p.returncode:
65+
raise CompileError('compilation failed')
66+
jsonabi = stdoutdata.rsplit('Contract JSON ABI\n')[-1].strip()
67+
return jsonabi
68+
69+
70+
def get_solidity():
71+
try:
72+
import solidity
73+
tester.languages['solidity'] = solidity
74+
except ImportError:
75+
if not solc_wrapper.compiler_available():
76+
return None
77+
return solc_wrapper
78+
79+
80+
if __name__ == '__main__':
81+
import tester
82+
assert 'solidity' in tester.languages
83+
84+
one_contract = """
85+
86+
contract foo {
87+
function seven() returns (int256 y) {
88+
y = 7;
89+
}
90+
function mul2(int256 x) returns (int256 y) {
91+
y = x * 2;
92+
}
93+
}
94+
"""
95+
96+
two_contracts = one_contract + """
97+
contract baz {
98+
function echo(address a) returns (address b) {
99+
b = a;
100+
return b;
101+
}
102+
function eight() returns (int256 y) {
103+
y = 8;
104+
}
105+
}
106+
"""
107+
108+
# test
109+
assert 'solidity' in tester.languages
110+
111+
s = tester.state()
112+
113+
c1 = s.abi_contract(one_contract, language='solidity')
114+
assert c1.seven() == 7
115+
assert c1.mul2(2) == 4
116+
assert c1.mul2(-2) == -4
117+
118+
two_codes = solc_wrapper.split_contracts(two_contracts)
119+
assert len(two_codes) == 2
120+
121+
for code in two_codes:
122+
bytecode = solc_wrapper.compile(code)
123+
jsonabi = solc_wrapper.mk_full_signature(code)
124+
c = s.abi_contract(code, language='solidity')
125+
126+
c1 = s.abi_contract(two_codes[0], language='solidity')
127+
assert c1.seven() == 7
128+
assert c1.mul2(2) == 4
129+
assert c1.mul2(-2) == -4
130+
131+
c2 = s.abi_contract(two_codes[1], language='solidity')
132+
a = '\0' * 20
133+
assert c2.echo(a).decode('hex') == a
134+
assert c2.eight() == 8

ethereum/blocks.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1240,7 +1240,7 @@ def chain_difficulty(self):
12401240
return utils.decode_int(encoded)
12411241
else:
12421242
o = self.difficulty + self.get_parent().chain_difficulty()
1243-
o += sum([uncle.difficulty for uncle in self.uncles])
1243+
# o += sum([uncle.difficulty for uncle in self.uncles])
12441244
self.state.db.put(b'difficulty:' + encode_hex(self.hash),
12451245
utils.encode_int(o))
12461246
return o

ethereum/chain.py

Lines changed: 8 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -270,8 +270,6 @@ def add_transaction(self, transaction):
270270
if the transaction was invalid
271271
"""
272272
assert self.head_candidate is not None
273-
_log = log.bind(tx_hash=transaction)
274-
_log.debug("add transaction")
275273
old_state_root = self.head_candidate.state_root
276274
# revert finalization
277275
self.head_candidate.state_root = self.pre_finalize_state_root
@@ -283,20 +281,18 @@ def add_transaction(self, transaction):
283281
log.debug('invalid tx', tx_hash=transaction, errors=e)
284282
success = False
285283

286-
# finalize
287-
self.pre_finalize_state_root = self.head_candidate.state_root
288-
self.head_candidate.finalize()
289-
290-
if not success:
291-
log.debug('tx not applied', tx_hash=transaction)
292-
assert old_state_root == self.head_candidate.state_root
293-
return False
294-
else:
284+
if success:
295285
assert transaction in self.get_transactions()
296-
log.debug('transaction applied', tx_hash=transaction,
286+
self.pre_finalize_state_root = self.head_candidate.state_root
287+
self.head_candidate.finalize()
288+
log.debug('tx applied', tx_hash=transaction,
297289
block_hash=self.head_candidate, result=output)
298290
assert old_state_root != self.head_candidate.state_root
299291
return True
292+
else:
293+
log.debug('tx not applied', tx_hash=transaction)
294+
self.head_candidate.state_root = old_state_root # reset
295+
return False
300296

301297
def get_transactions(self):
302298
"""Get a list of new transactions not yet included in a mined block

ethereum/tester.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
import ethereum.abi as abi
99
from ethereum.slogging import LogRecorder, configure_logging, set_level
1010
from ethereum.utils import to_string
11+
from ethereum._solidity import get_solidity
1112
import rlp
1213
from rlp.utils import decode_hex, encode_hex, ascii_chr
1314

@@ -31,6 +32,11 @@
3132

3233
languages = {}
3334

35+
_solidity = get_solidity()
36+
if _solidity:
37+
languages['solidity'] = _solidity
38+
39+
3440
seed = 3 ** 160
3541

3642

ethereum/tests/test_solidity.py

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,3 +35,60 @@ def test_interop():
3535
# assert c2.sub2() == 7
3636
# assert c1.main(c2.address) == 14
3737
# assert c2.main(c1.address) == 10
38+
39+
40+
if __name__ == '__main__':
41+
42+
import subprocess
43+
44+
one_solidity_contract = """
45+
46+
contract foo {
47+
function main(address a) returns (address b) {
48+
b = a;
49+
return b;
50+
}
51+
function sub2() returns (int256 y) {
52+
y = 7;
53+
}
54+
}
55+
56+
"""
57+
58+
class CompileError(Exception):
59+
pass
60+
61+
class solc_wrapper(object):
62+
63+
@classmethod
64+
def compile(cls, code):
65+
p = subprocess.Popen(['solc', '--binary', 'stdout'],
66+
stdin=subprocess.PIPE, stdout=subprocess.PIPE)
67+
stdoutdata, stderrdata = p.communicate(input=code)
68+
if p.returncode:
69+
raise CompileError('compilation failed')
70+
71+
hex_code = stdoutdata.rsplit('Binary: \n')[-1].strip()
72+
return hex_code.decode('hex')
73+
74+
@classmethod
75+
def mk_full_signature(cls, code):
76+
p = subprocess.Popen(['solc', '--json-abi', 'stdout'],
77+
stdin=subprocess.PIPE, stdout=subprocess.PIPE)
78+
stdoutdata, stderrdata = p.communicate(input=code)
79+
if p.returncode:
80+
raise CompileError('compilation failed')
81+
jsonabi = stdoutdata.rsplit('Contract JSON ABI\n')[-1].strip()
82+
return jsonabi
83+
84+
tester.languages['solidity'] = solc_wrapper
85+
86+
bytecode = solc_wrapper.compile(one_solidity_contract)
87+
jsonabi = solc_wrapper.mk_full_signature(one_solidity_contract)
88+
89+
# test
90+
s = tester.state()
91+
c2 = s.abi_contract(one_solidity_contract, language='solidity')
92+
a = '\0' * 20
93+
assert c2.main(a).decode('hex') == a
94+
assert c2.sub2() == 7

setup.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ def run_tests(self):
3232
# requirements
3333
install_requires = set(x.strip() for x in open('requirements.txt'))
3434
install_requires_replacements = {
35-
'https://github.com/ethereum/pyrlp/tarball/develop': 'rlp>=0.3.7',
35+
'https://github.com/ethereum/pyrlp/tarball/develop': 'rlp>=0.3.8',
3636
'https://github.com/ethereum/ethash/tarball/master': 'pyethash'}
3737
install_requires = [install_requires_replacements.get(r, r) for r in install_requires]
3838

@@ -51,6 +51,6 @@ def run_tests(self):
5151
install_requires=install_requires,
5252
tests_require=tests_require,
5353
entry_points=dict(console_scripts=console_scripts),
54-
version='0.9.64',
54+
version='0.9.65',
5555
cmdclass=cmdclass
5656
)

0 commit comments

Comments
 (0)