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

feat: add clean interpreter.Run integration function #39

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 5 additions & 15 deletions fhevm/contracts_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -3153,16 +3153,6 @@ func TestFheRandEthCall(t *testing.T) {
}
}

func interpreterRunWithStopContract(environment *MockEVMEnvironment, interpreter *vm.EVMInterpreter, contract *vm.Contract, input []byte, readOnly bool) (ret []byte, err error) {
ret, _ = interpreter.Run(contract, input, readOnly)
// the following functions are meant to be ran from within interpreter.run so we increment depth to emulate that
environment.depth++
RemoveVerifiedCipherextsAtCurrentDepth(environment)
err = EvalRemOptReqWhenStopToken(environment)
environment.depth--
return ret, err
}

func newInterpreterFromEnvironment(environment *MockEVMEnvironment) *vm.EVMInterpreter {
cfg := vm.Config{}
evm := &vm.EVM{Config: cfg}
Expand Down Expand Up @@ -3206,7 +3196,7 @@ func TestLibOneTrueOptimisticRequire(t *testing.T) {

interpreter := newInterpreterFromEnvironment(environment)
// Call the interpreter with a single STOP opcode and expect that the optimistic require doesn't revert.
out, err = interpreterRunWithStopContract(environment, interpreter, newStopOpcodeContract(), make([]byte, 0), readOnly)
out, err = InterpreterRun(environment, interpreter, newStopOpcodeContract(), make([]byte, 0), readOnly)
if err != nil {
t.Fatalf(err.Error())
} else if out != nil {
Expand All @@ -3230,7 +3220,7 @@ func TestOneFalseOptimisticRequire(t *testing.T) {
}
interpreter := newInterpreterFromEnvironment(environment)
// Call the interpreter with a single STOP opcode and expect that the optimistic require reverts.
out, err = interpreterRunWithStopContract(environment, interpreter, newStopOpcodeContract(), make([]byte, 0), readOnly)
out, err = InterpreterRun(environment, interpreter, newStopOpcodeContract(), make([]byte, 0), readOnly)
if err == nil || err != ErrExecutionReverted {
t.Fatalf("require expected reversal on value 0")
} else if out != nil {
Expand Down Expand Up @@ -3261,7 +3251,7 @@ func TestTwoTrueOptimisticRequires(t *testing.T) {
}
interpreter := newInterpreterFromEnvironment(environment)
// Call the interpreter with a single STOP opcode and expect that the optimistic require doesn't revert.
out, err = interpreterRunWithStopContract(environment, interpreter, newStopOpcodeContract(), make([]byte, 0), readOnly)
out, err = InterpreterRun(environment, interpreter, newStopOpcodeContract(), make([]byte, 0), readOnly)
if err != nil {
t.Fatalf(err.Error())
} else if out != nil {
Expand Down Expand Up @@ -3292,7 +3282,7 @@ func TestOptimisticRequireTwiceOnSameCiphertext(t *testing.T) {
}
interpreter := newInterpreterFromEnvironment(environment)
// Call the interpreter with a single STOP opcode and expect that the optimistic require doesn't revert.
out, err = interpreterRunWithStopContract(environment, interpreter, newStopOpcodeContract(), make([]byte, 0), readOnly)
out, err = InterpreterRun(environment, interpreter, newStopOpcodeContract(), make([]byte, 0), readOnly)
if err != nil {
t.Fatalf(err.Error())
} else if out != nil {
Expand Down Expand Up @@ -3322,7 +3312,7 @@ func TestOneFalseAndOneTrueOptimisticRequire(t *testing.T) {
}
interpreter := newInterpreterFromEnvironment(environment)
// Call the interpreter with a single STOP opcode and expect that the optimistic require reverts.
out, err = interpreterRunWithStopContract(environment, interpreter, newStopOpcodeContract(), make([]byte, 0), readOnly)
out, err = InterpreterRun(environment, interpreter, newStopOpcodeContract(), make([]byte, 0), readOnly)
if err == nil || err != ErrExecutionReverted {
t.Fatalf("require expected reversal on value 0")
} else if out != nil {
Expand Down
6 changes: 3 additions & 3 deletions fhevm/instructions.go
Original file line number Diff line number Diff line change
Expand Up @@ -335,15 +335,15 @@ func delegateCiphertextHandlesToCaller(env EVMEnvironment, ret []byte) {
}
}

func RemoveVerifiedCipherextsAtCurrentDepth(env EVMEnvironment) {
func RemoveVerifiedCipherextsAtCurrentDepth(env EVMEnvironment, depth int) {
for _, verifiedCiphertext := range env.FhevmData().verifiedCiphertexts {
if env.IsCommitting() {
env.GetLogger().Info("Run removing ciphertext from depth",
"handle", verifiedCiphertext.ciphertext.getHash().Hex(),
"depth", env.GetDepth())
"depth", depth)
}
// Delete the current EVM depth from the set of verified depths.
verifiedCiphertext.verifiedDepths.del(env.GetDepth())
verifiedCiphertext.verifiedDepths.del(depth)
}
}

Expand Down
28 changes: 22 additions & 6 deletions fhevm/interpreter.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package fhevm

import (
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core/vm"
)

type ScopeContext interface {
Expand Down Expand Up @@ -67,17 +68,32 @@ var PrivilegedMempory *PrivilegedMemory = &PrivilegedMemory{
//
// This function is meant to be integrated as part of vm.EVMInterpreter.Run in the case
// there was an errStopToken
func EvalRemOptReqWhenStopToken(env EVMEnvironment) (err error) {
err = nil
func EvalRemOptReqWhenStopToken(env EVMEnvironment, depth int) (err error) {
// If we are finishing execution (about to go to from depth 1 to depth 0), evaluate
// any remaining optimistic requires.
if env.GetDepth() == 1 {
if depth == 1 {
result, evalErr := evaluateRemainingOptimisticRequires(env)
if evalErr != nil {
err = evalErr
return evalErr
} else if !result {
err = ErrExecutionReverted
return ErrExecutionReverted
}
}
return err
return nil
}

// Function meant to be run instead of vm.EVMInterpreter.Run inside an fhEVM
//
// It makes sure to remove ciphertexts used at current depth during interpreter execution, but also evaluate remaining optimistic requires if necessary
func InterpreterRun(environment EVMEnvironment, interpreter *vm.EVMInterpreter, contract *vm.Contract, input []byte, readOnly bool) (ret []byte, err error) {
ret, err = interpreter.Run(contract, input, readOnly)
// the following functions are meant to be ran from within interpreter.Run so we increment depth to emulate that
depth := environment.GetDepth() + 1
RemoveVerifiedCipherextsAtCurrentDepth(environment, depth)
// if contract is not empty and err is nil, then an errStopToken was cleared inside interpreter.Run
if len(contract.Code) != 0 && err == nil {
err = EvalRemOptReqWhenStopToken(environment, depth)
return ret, err
}
return ret, err
}