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

core/vm: support for various interpreters #17093

Merged
merged 1 commit into from
Jul 25, 2018

Conversation

gballet
Copy link
Member

@gballet gballet commented Jun 27, 2018

This PR turns Interpreter into an interface, so that other interpreters can be chosen. This is intended to support PRs #16957 and #17050.

@gballet gballet requested review from fjl and karalabe June 27, 2018 13:30
@gballet gballet requested a review from holiman as a code owner June 27, 2018 13:30
@gballet
Copy link
Member Author

gballet commented Jul 3, 2018

It is now possible to call contract across interpreters. The solution that I have currently chosen is the naive one: simply have a list of interpreters. There is another possible solution: have one interpreter per EVM but call contracts across EVMs (to be renamed "VM" to differentiate between EVM, EVM-C and eWASM).
It would be less confusing to write it this way, and would for instance avoid a lot of type casting. Let me know what you think.

@gballet gballet force-pushed the interpreter-as-interface branch from d03339c to 0971414 Compare July 3, 2018 19:06
@chfast
Copy link
Member

chfast commented Jul 6, 2018

ping

Copy link
Contributor

@fjl fjl left a comment

Choose a reason for hiding this comment

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

We had a long review call about this and the basic design is OK, but please try to find a way to avoid the type assertion in the instructions.

@@ -41,23 +41,23 @@ func opAdd(pc *uint64, evm *EVM, contract *Contract, memory *Memory, stack *Stac
x, y := stack.pop(), stack.peek()
math.U256(y.Add(x, y))

evm.interpreter.intPool.put(x)
evm.interpreter.(*InterpreterEVM).intPool.put(x)
Copy link
Contributor

Choose a reason for hiding this comment

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

We need to find a way to avoid this type assertion in every instruction, maybe by changing the evm parameter to have type *InterpreterEVM.

core/vm/evm.go Outdated
if evm.interpreter == nil {
evm.interpreter = evm.interpreters[len(evm.interpreters)-1]
}
}
Copy link
Contributor

Choose a reason for hiding this comment

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

This code is weird because evm.interpreters is always nil (the EVM is created just a few lines above).

@gballet gballet force-pushed the interpreter-as-interface branch 3 times, most recently from 9939fc5 to f685634 Compare July 11, 2018 11:47
core/vm/evm.go Outdated
return evm.interpreter.Run(contract, input)
for _, interpreter := range evm.interpreters {
if interpreter.CanRun(contract.Code) {
if evm.Interpreter() != interpreter {
Copy link
Member

Choose a reason for hiding this comment

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

Why method call here? Just access evm.interpreter directly.

@@ -37,45 +37,45 @@ var (
errMaxCodeSizeExceeded = errors.New("evm: max code size exceeded")
)

func opAdd(pc *uint64, evm *EVM, contract *Contract, memory *Memory, stack *Stack) ([]byte, error) {
func opAdd(pc *uint64, interpreter *InterpreterEVM, contract *Contract, memory *Memory, stack *Stack) ([]byte, error) {
Copy link
Member

Choose a reason for hiding this comment

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

Imho rename interpreter to evm throughout this file. Much cleaner and shorter code.

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 have an issue with this, because it's an EVMInterpreter and not an EVM. It is shorter but confusing. What about evmi ?

offset, size := stack.pop(), stack.pop()
data := memory.Get(offset.Int64(), size.Int64())
hash := crypto.Keccak256(data)
evm := interpreter.evm
Copy link
Member

Choose a reason for hiding this comment

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

Are you using this anywhere? Seems like an unused variable? Does this code compile? ;P

Copy link
Member

Choose a reason for hiding this comment

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

Ah, you did use it to add the preimages. Please use it to access the vmConfig too.

}

// InterpreterEVM represents an EVM interpreter
type InterpreterEVM struct {
Copy link
Member

Choose a reason for hiding this comment

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

Please call this EVMInterpreter

// CanRun tells if the contract, passed as an argument, can be
// run by the current interpreter.
// The EVM interpreter will try to interpret any binary file and
// as such, should be tried last.
Copy link
Member

Choose a reason for hiding this comment

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

Please remove

+// The EVM interpreter will try to interpret any binary file and
+// as such, should be tried last.

That will be up to a consensus descision on how to enable it, most probably by having an explicit flag in the accounts specifying whether the code is EVM or EWASM.

@@ -26,4 +26,5 @@ var (
ErrTraceLimitReached = errors.New("the number of logs reached the specified limit")
ErrInsufficientBalance = errors.New("insufficient balance for transfer")
ErrContractAddressCollision = errors.New("contract address collision")
ErrNoCompatibleInterpreter = errors.New("could not find an interpreter to run this contract's code")
Copy link
Member

Choose a reason for hiding this comment

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

errors.New("no compatible interpreter")

No need to make it more verbose than that.

Copy link
Member

@karalabe karalabe left a comment

Choose a reason for hiding this comment

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

LGTM

@karalabe karalabe added this to the 1.8.13 milestone Jul 23, 2018
@gballet gballet force-pushed the interpreter-as-interface branch from e7db76a to 9635a5c Compare July 23, 2018 12:57
 - Define an Interpreter interface
 - One contract can call contracts from other interpreter types.
 - Pass the interpreter to the operands instead of the evm.
   This is meant to prevent type assertions in operands.
@gballet gballet force-pushed the interpreter-as-interface branch from 9635a5c to d0bd10a Compare July 25, 2018 06:41
@gballet gballet merged commit 7abedf9 into ethereum:master Jul 25, 2018
@axic axic mentioned this pull request Jul 25, 2018
@gballet gballet mentioned this pull request Jul 27, 2018
10 tasks
firmianavan pushed a commit to firmianavan/go-ethereum that referenced this pull request Aug 28, 2018
- Define an Interpreter interface
- One contract can call contracts from other interpreter types.
- Pass the interpreter to the operands instead of the evm.
  This is meant to prevent type assertions in operands.
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.

4 participants