Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Byzantium Fork Rules #123

Merged
merged 3 commits into from
Nov 20, 2017
Merged

Byzantium Fork Rules #123

merged 3 commits into from
Nov 20, 2017

Conversation

pipermerriam
Copy link
Member

@pipermerriam pipermerriam commented Oct 18, 2017

else:
raise VMNotFound("No vm available for block #{0}".format(block_number))

vm_class = base_vm_class.configure(chaindb=self.chaindb)
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

TODO: undo this. No longer necessary.

@pipermerriam
Copy link
Member Author

maybe green? This is going to get split into about 5 pull requests with some minor refactors extracted into their own pull requests.

Copy link
Member Author

@pipermerriam pipermerriam left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just me annotating the pull request so that I have an indicator on whether I've pulled all the things out.

'IMPORTED_BLOCK: number %s | hash %s',
imported_block.number,
encode_hex(imported_block.hash),
)
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

TODO: extract

evm/constants.py Outdated
GAS_SUICIDE_NEWACCOUNT = 25000
GAS_SELFDESTRUCT = 0
GAS_SELFDESTRUCT_EIP150 = 5000
GAS_SELFDESTRUCT_NEWACCOUNT = 25000
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

TODO: extract

evm/constants.py Outdated
@@ -110,7 +116,8 @@
DIFFICULTY_MINIMUM = 131072

FRONTIER_DIFFICULTY_ADJUSTMENT_CUTOFF = 13
HOMESTEAD_DIFF_ADJUSTMENT_CUTOFF = 10
HOMESTEAD_DIFFICULTY_ADJUSTMENT_CUTOFF = 10
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

TODO: extract

@@ -3,9 +3,7 @@

def blockhash(computation):
block_number = computation.stack.pop(type_hint=constants.UINT256)

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

TODO: undo

else:
code = state_db.get_code(to)

child_msg_kwargs = {
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

TODO: move back into else block

logic_fn=system.suicide_eip161,
mnemonic=mnemonics.SUICIDE,
gas_cost=constants.GAS_SUICIDE_EIP150,
opcode_values.SELFDESTRUCT: as_opcode(
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

TODO: extract

@@ -167,7 +161,7 @@ def test_add_log_entry_raises_if_data_isnt_in_bytes(computation):
def test_add_log_entry(computation):
# Adds log entry to log entries
computation.add_log_entry(CANONICAL_ADDRESS_A, [1, 2, 3], b'')
assert computation.log_entries == [(b'\x0fW.R\x95\xc5\x7f\x15\x88o\x9b&>/m-l{^\xc6',
assert computation.log_entries == [(b'\x0fW.R\x95\xc5\x7f\x15\x88o\x9b&>/m-l\x7b^\xc6',
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

TODO: extract

assert computation.get_log_entries() == ()


def test_get_gas_refund(computation, create_error):
def test_get_gas_refund(computation):
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

TODO: extract

)
elif 'TransitionTests/bcHomesteadToEIP150' in fixture_path:
elif network == 'Homestead':
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

TODO: extract

@@ -185,8 +190,8 @@ def test_state_fixtures(fixture, fixture_vm_class):

try:
computation = vm.apply_transaction(transaction)
except ValidationError:
transaction_error = True
except ValidationError as err:
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

TODO: extract

@pipermerriam pipermerriam force-pushed the piper/byzantium branch 5 times, most recently from b7b1bda to fc77ba5 Compare November 17, 2017 21:23
Copy link
Collaborator

@gsalgado gsalgado left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looking good! I have a few questions/suggestions, but nothing major

# ByzantiumVM
#
BYZANTIUM_MAINNET_BLOCK = 4370000
BYZANTIUM_ROPSTEN_BLOCK = 1700000
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

BYZANTIUM_ROPSTEN_BLOCK is not used anywhere. Should it be in RopstenChain?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, I'm thinking it makes sense to migration the various fork-and-chain-specific block numbers into the fork or chain modules themselves.


class OutOfBoundsRead(VMError):
"""
Error raised to indicate an attempt was made to read data beyond then
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

s/then/the?

@@ -105,14 +109,18 @@ def __call__(self, computation):
if child_computation.error:
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Wouldn't it be better to explicitly check for None here instead?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think so or I'm not understanding your suggestion.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I meant if child_computation.error is not None:, just in case at some point we have an error class that for some reason implements __bool__() and returns False there, this would no longer work as expected. I can't think why we'd have an error class that would do that, but in general I prefer to explicitly check for None

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍 I'm going to file this away in a "Good First Issue" ticket.

@@ -146,6 +154,7 @@ def get_call_params(self, computation):
memory_output_start_position,
memory_output_size,
True, # should_transfer_value,
computation.msg.is_static, # is_static
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd drop this comment as it doesn't add anything

@@ -105,14 +109,18 @@ def __call__(self, computation):
if child_computation.error:
computation.stack.push(0)
else:
computation.stack.push(1)

if not child_computation.error or not child_computation.error.zeros_return_data:
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I wonder if it'd make sense to abstract this into a method on Computation, so that we don't need to reach so many levels down into the exception's attributes. Something like Computation.should_return_data()?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

+1 but going to do this as part of a "good first issue" ticket

)


ZERO = (bn128.FQ2.one(), bn128.FQ2.one(), bn128.FQ2.zero())
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I find this an odd name choice for a 3-tuple with seemingly non-zero items, but maybe I'm missing something?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This code is a refactored version of vitalik's implementation in pyethereum. I'm not familiar enough with what is actually going on here to know what a better name would be :(

def compute_byzantium_difficulty(parent_header, timestamp):
"""
https://github.com/ethereum/EIPs/issues/100
TODO: figure out how to know about uncles in this context...
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this still TODO? If so, it'd be nice if you could expand on what exactly you mean

Copy link
Member Author

@pipermerriam pipermerriam Nov 20, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This was from before I'd put in the optimization to just check if parent_header.uncles_hash != EMPTY_UNCLE_HASH and was thinking that I'd actually need to be able to fetch the uncles to know how many there were.

from evm.vm.forks.spurious_dragon.opcodes import SPURIOUS_DRAGON_OPCODES


def no_static(opcode_fn):
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The name here had me confused at first, but then I realized it's used to ensure a given opcode_fn is not passed a computation with a static msg, right? Maybe rename it to ensure_no_static()?

@functools.wraps(opcode_fn)
def inner(computation):
if computation.msg.is_static:
raise WriteProtection("Cannot modify state while inside of a STATICCALL context")
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also, the exception msg here is quite misleading, as it's saying we cannot modify the state when the msg is actually static? Or have I gotten this backwards?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think the txt is correct.

"Since we are inside of a STATICCALL context, the state cannot be modified

@@ -33,6 +33,7 @@ class Message(object):
create_address = None

should_transfer_value = None
is_static = None
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why does it default to None? To force all message types to define it?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same convention that I think has raised questions previously. This is merely a pattern I use to make it easy to know what properties an object has.

It you have strong feelings about this pattern I'm all ears because it's something that grew organically and I'm not sure it's a good pattern.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not really, I just find it odd for bool attributes to have a default of None, but I think it's more of a gut feeling than anything justifiable

@pipermerriam pipermerriam merged commit dd00cba into master Nov 20, 2017
@pipermerriam pipermerriam deleted the piper/byzantium branch November 20, 2017 16:37
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants