Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
N
nebula
Project
Project
Details
Activity
Releases
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
exchain
nebula
Commits
9aa079e2
Unverified
Commit
9aa079e2
authored
May 03, 2023
by
protolambda
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
cannon: run with pre-image oracle server
parent
f08f9eb1
Changes
4
Hide whitespace changes
Inline
Side-by-side
Showing
4 changed files
with
155 additions
and
13 deletions
+155
-13
run.go
cmd/run.go
+132
-3
evm_test.go
mipsevm/evm_test.go
+6
-3
unicorn.go
mipsevm/unicorn.go
+15
-5
filechan.go
preimage/filechan.go
+2
-2
No files found.
cmd/run.go
View file @
9aa079e2
...
...
@@ -3,6 +3,8 @@ package cmd
import
(
"fmt"
"os"
"os/exec"
"time"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/common/hexutil"
...
...
@@ -11,6 +13,7 @@ import (
"github.com/urfave/cli/v2"
"cannon/mipsevm"
"github.com/ethereum-optimism/cannon/preimage"
)
var
(
...
...
@@ -71,6 +74,97 @@ type Proof struct {
OracleInput
hexutil
.
Bytes
`json:"oracle-input"`
}
type
rawHint
string
func
(
rh
rawHint
)
Hint
()
string
{
return
string
(
rh
)
}
type
rawKey
[
32
]
byte
func
(
rk
rawKey
)
PreimageKey
()
[
32
]
byte
{
return
rk
}
type
ProcessPreimageOracle
struct
{
pCl
*
preimage
.
OracleClient
hCl
*
preimage
.
HintWriter
cmd
*
exec
.
Cmd
}
func
NewProcessPreimageOracle
(
name
string
,
args
[]
string
)
*
ProcessPreimageOracle
{
if
name
==
""
{
return
&
ProcessPreimageOracle
{}
}
pCh
:=
preimage
.
ClientPreimageChannel
()
hCh
:=
preimage
.
ClientHinterChannel
()
cmd
:=
exec
.
Command
(
name
,
args
...
)
cmd
.
Stdout
=
os
.
Stdout
cmd
.
Stderr
=
os
.
Stderr
cmd
.
ExtraFiles
=
[]
*
os
.
File
{
hCh
.
Reader
(),
hCh
.
Writer
(),
pCh
.
Reader
(),
pCh
.
Writer
(),
}
out
:=
&
ProcessPreimageOracle
{
pCl
:
preimage
.
NewOracleClient
(
pCh
),
hCl
:
preimage
.
NewHintWriter
(
hCh
),
cmd
:
cmd
,
}
return
out
}
func
(
p
*
ProcessPreimageOracle
)
Hint
(
v
[]
byte
)
{
if
p
.
hCl
==
nil
{
// no hint processor
return
}
p
.
hCl
.
Hint
(
rawHint
(
v
))
}
func
(
p
*
ProcessPreimageOracle
)
GetPreimage
(
k
[
32
]
byte
)
[]
byte
{
if
p
.
pCl
==
nil
{
panic
(
"no pre-image retriever available"
)
}
return
p
.
pCl
.
Get
(
rawKey
(
k
))
}
func
(
p
*
ProcessPreimageOracle
)
Start
()
error
{
if
p
.
cmd
==
nil
{
return
nil
}
return
p
.
cmd
.
Start
()
}
func
(
p
*
ProcessPreimageOracle
)
Close
()
error
{
if
p
.
cmd
==
nil
{
return
nil
}
_
=
p
.
cmd
.
Process
.
Signal
(
os
.
Interrupt
)
p
.
cmd
.
WaitDelay
=
time
.
Second
*
10
return
p
.
cmd
.
Wait
()
}
type
StepFn
func
(
proof
bool
)
(
*
mipsevm
.
StepWitness
,
error
)
func
Guard
(
proc
*
os
.
ProcessState
,
fn
StepFn
)
StepFn
{
return
func
(
proof
bool
)
(
*
mipsevm
.
StepWitness
,
error
)
{
wit
,
err
:=
fn
(
proof
)
if
err
!=
nil
{
if
proc
.
Exited
()
{
return
nil
,
fmt
.
Errorf
(
"pre-image server exited with code %d, resulting in err %v"
,
proc
.
ExitCode
(),
err
)
}
else
{
return
nil
,
err
}
}
return
wit
,
nil
}
}
var
_
mipsevm
.
PreimageOracle
=
(
*
ProcessPreimageOracle
)(
nil
)
func
Run
(
ctx
*
cli
.
Context
)
error
{
state
,
err
:=
loadJSON
[
mipsevm
.
State
](
ctx
.
Path
(
RunInputFlag
.
Name
))
if
err
!=
nil
{
...
...
@@ -87,7 +181,24 @@ func Run(ctx *cli.Context) error {
outLog
:=
&
mipsevm
.
LoggingWriter
{
Name
:
"program std-out"
,
Log
:
l
}
errLog
:=
&
mipsevm
.
LoggingWriter
{
Name
:
"program std-err"
,
Log
:
l
}
var
po
mipsevm
.
PreimageOracle
// TODO need to set this up
// split CLI args after first '--'
args
:=
ctx
.
Args
()
.
Slice
()
for
i
,
arg
:=
range
args
{
if
arg
==
"--"
{
args
=
args
[
i
:
]
break
}
}
po
:=
NewProcessPreimageOracle
(
args
[
0
],
args
[
1
:
])
if
err
:=
po
.
Start
();
err
!=
nil
{
return
fmt
.
Errorf
(
"failed to start pre-image oracle server: %w"
,
err
)
}
defer
func
()
{
if
err
:=
po
.
Close
();
err
!=
nil
{
l
.
Error
(
"failed to close pre-image server"
,
"err"
,
err
)
}
}()
stopAt
:=
ctx
.
Generic
(
RunStopAtFlag
.
Name
)
.
(
*
StepMatcherFlag
)
.
Matcher
()
proofAt
:=
ctx
.
Generic
(
RunProofAtFlag
.
Name
)
.
(
*
StepMatcherFlag
)
.
Matcher
()
...
...
@@ -100,9 +211,21 @@ func Run(ctx *cli.Context) error {
proofFmt
:=
ctx
.
String
(
RunProofFmtFlag
.
Name
)
snapshotFmt
:=
ctx
.
String
(
RunSnapshotFmtFlag
.
Name
)
step
:=
us
.
Step
if
po
.
cmd
!=
nil
{
step
=
Guard
(
po
.
cmd
.
ProcessState
,
step
)
}
for
!
state
.
Exited
{
step
:=
state
.
Step
//if infoAt(state) {
// s := lookupSymbol(state.PC)
// var sy elf.Symbol
// l.Info("", "insn", state.Memory.GetMemory(state.PC), "pc", state.PC, "symbol", sy.Name)
// // print name
//}
if
stopAt
(
state
)
{
break
}
...
...
@@ -115,7 +238,10 @@ func Run(ctx *cli.Context) error {
if
proofAt
(
state
)
{
preStateHash
:=
crypto
.
Keccak256Hash
(
state
.
EncodeWitness
())
witness
:=
us
.
Step
(
true
)
witness
,
err
:=
us
.
Step
(
true
)
if
err
!=
nil
{
return
fmt
.
Errorf
(
"failed at proof-gen step %d (PC: %08x): %w"
,
step
,
state
.
PC
,
err
)
}
postStateHash
:=
crypto
.
Keccak256Hash
(
state
.
EncodeWitness
())
proof
:=
&
Proof
{
Step
:
step
,
...
...
@@ -133,7 +259,10 @@ func Run(ctx *cli.Context) error {
return
fmt
.
Errorf
(
"failed to write proof data: %w"
,
err
)
}
}
else
{
_
=
us
.
Step
(
false
)
_
,
err
=
us
.
Step
(
false
)
if
err
!=
nil
{
return
fmt
.
Errorf
(
"failed at step %d (PC: %08x): %w"
,
step
,
state
.
PC
,
err
)
}
}
}
...
...
mipsevm/evm_test.go
View file @
9aa079e2
...
...
@@ -84,7 +84,8 @@ func TestEVM(t *testing.T) {
insn
:=
state
.
Memory
.
GetMemory
(
state
.
PC
)
t
.
Logf
(
"step: %4d pc: 0x%08x insn: 0x%08x"
,
state
.
Step
,
state
.
PC
,
insn
)
stepWitness
:=
us
.
Step
(
true
)
stepWitness
,
err
:=
us
.
Step
(
true
)
require
.
NoError
(
t
,
err
)
input
:=
stepWitness
.
EncodeStepInput
()
startingGas
:=
uint64
(
30
_000_000
)
...
...
@@ -155,7 +156,8 @@ func TestHelloEVM(t *testing.T) {
t
.
Logf
(
"step: %4d pc: 0x%08x insn: 0x%08x"
,
state
.
Step
,
state
.
PC
,
insn
)
}
stepWitness
:=
us
.
Step
(
true
)
stepWitness
,
err
:=
us
.
Step
(
true
)
require
.
NoError
(
t
,
err
)
input
:=
stepWitness
.
EncodeStepInput
()
startingGas
:=
uint64
(
30
_000_000
)
...
...
@@ -230,7 +232,8 @@ func TestClaimEVM(t *testing.T) {
t
.
Logf
(
"step: %4d pc: 0x%08x insn: 0x%08x"
,
state
.
Step
,
state
.
PC
,
insn
)
}
stepWitness
:=
us
.
Step
(
true
)
stepWitness
,
err
:=
us
.
Step
(
true
)
require
.
NoError
(
t
,
err
)
input
:=
stepWitness
.
EncodeStepInput
()
startingGas
:=
uint64
(
30
_000_000
)
...
...
mipsevm/unicorn.go
View file @
9aa079e2
...
...
@@ -299,7 +299,17 @@ func NewUnicornState(mu uc.Unicorn, state *State, po PreimageOracle, stdOut, std
return
m
,
nil
}
func
(
m
*
UnicornState
)
Step
(
proof
bool
)
(
wit
*
StepWitness
)
{
func
(
m
*
UnicornState
)
Step
(
proof
bool
)
(
wit
*
StepWitness
,
err
error
)
{
defer
func
()
{
// pre-image oracle or emulator hooks might panic
if
a
:=
recover
();
a
!=
nil
{
if
ae
,
ok
:=
a
.
(
error
);
ok
{
err
=
ae
}
else
{
err
=
fmt
.
Errorf
(
"panic: %v"
,
a
)
}
}
}()
m
.
memProofEnabled
=
proof
m
.
lastMemAccess
=
^
uint32
(
0
)
m
.
lastPreimageOffset
=
^
uint32
(
0
)
...
...
@@ -352,12 +362,12 @@ func (m *UnicornState) Step(proof bool) (wit *StepWitness) {
// Execute only a single instruction.
// The memory and syscall hooks will update the state with any of the dynamic changes.
err
:
=
m
.
mu
.
StartWithOptions
(
uint64
(
m
.
state
.
PC
),
uint64
(
m
.
state
.
NextPC
),
&
uc
.
UcOptions
{
err
=
m
.
mu
.
StartWithOptions
(
uint64
(
m
.
state
.
PC
),
uint64
(
m
.
state
.
NextPC
),
&
uc
.
UcOptions
{
Timeout
:
0
,
// 0 to disable, value is in ms.
Count
:
1
,
})
if
err
!=
nil
{
panic
(
"failed to run unicorn"
)
return
nil
,
err
}
if
proof
{
...
...
@@ -377,7 +387,7 @@ func (m *UnicornState) Step(proof bool) (wit *StepWitness) {
// 1) match the registers post-state
batch
,
err
:=
m
.
mu
.
RegReadBatch
(
regBatchKeys
)
if
err
!=
nil
{
panic
(
fmt
.
Errorf
(
"failed to read register batch: %w"
,
err
)
)
return
nil
,
fmt
.
Errorf
(
"failed to read register batch: %w"
,
err
)
}
for
i
:=
0
;
i
<
32
;
i
++
{
m
.
state
.
Registers
[
i
]
=
uint32
(
batch
[
i
])
...
...
@@ -393,7 +403,7 @@ func (m *UnicornState) Step(proof bool) (wit *StepWitness) {
m
.
state
.
PC
=
oldNextPC
err
=
m
.
mu
.
RegWrite
(
uc
.
MIPS_REG_PC
,
uint64
(
oldNextPC
))
if
err
!=
nil
{
panic
(
"failed to write PC register"
)
return
nil
,
fmt
.
Errorf
(
"failed to write PC register: %w"
,
err
)
}
m
.
state
.
NextPC
=
newNextPC
...
...
preimage/filechan.go
View file @
9aa079e2
...
...
@@ -67,14 +67,14 @@ const (
PClientWFd
=
6
)
func
ClientHinterChannel
()
FileChannel
{
func
ClientHinterChannel
()
*
ReadWritePair
{
r
:=
os
.
NewFile
(
HClientRFd
,
"preimage-hint-read"
)
w
:=
os
.
NewFile
(
HClientWFd
,
"preimage-hint-write"
)
return
NewReadWritePair
(
r
,
w
)
}
// ClientPreimageChannel returns a FileChannel for the preimage oracle in a detached context
func
ClientPreimageChannel
()
FileChannel
{
func
ClientPreimageChannel
()
*
ReadWritePair
{
r
:=
os
.
NewFile
(
PClientRFd
,
"preimage-oracle-read"
)
w
:=
os
.
NewFile
(
PClientWFd
,
"preimage-oracle-write"
)
return
NewReadWritePair
(
r
,
w
)
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment