Commit eaa6641c authored by George Hotz's avatar George Hotz

refactor out GetHookedUnicorn

parent c031a4d7
...@@ -49,11 +49,15 @@ func TestCompareUnicornEvm(t *testing.T) { ...@@ -49,11 +49,15 @@ func TestCompareUnicornEvm(t *testing.T) {
}) })
uniram := make(map[uint32](uint32)) uniram := make(map[uint32](uint32))
go RunUnicorn(fn, uniram, steps, true, false, func(step int, mu uc.Unicorn, ram map[uint32](uint32)) { go RunUnicorn(fn, uniram, true, false, func(step int, mu uc.Unicorn, ram map[uint32](uint32)) {
SyncRegs(mu, ram) SyncRegs(mu, ram)
cuni <- RegSerialize(ram) cuni <- RegSerialize(ram)
done.Lock() done.Lock()
done.Unlock() done.Unlock()
// halt at steps
if step == steps {
mu.RegWrite(uc.MIPS_REG_PC, 0x5ead0004)
}
}) })
mismatch := false mismatch := false
......
package main package main
import ( import (
"encoding/binary"
"fmt" "fmt"
"io/ioutil" "io/ioutil"
"log" "log"
...@@ -78,6 +79,26 @@ func RunWithInputAndGas(interpreter *vm.EVMInterpreter, statedb *StateDB, input ...@@ -78,6 +79,26 @@ func RunWithInputAndGas(interpreter *vm.EVMInterpreter, statedb *StateDB, input
return dat, (gas - contract.Gas), err return dat, (gas - contract.Gas), err
} }
func ZeroRegisters(ram map[uint32](uint32)) {
for i := uint32(0xC0000000); i < 0xC0000000+36*4; i += 4 {
WriteRam(ram, i, 0)
}
}
func LoadData(dat []byte, ram map[uint32](uint32), base uint32) {
for i := 0; i < len(dat); i += 4 {
value := binary.BigEndian.Uint32(dat[i : i+4])
if value != 0 {
ram[base+uint32(i)] = value
}
}
}
func LoadMappedFile(fn string, ram map[uint32](uint32), base uint32) {
dat, _ := ioutil.ReadFile(fn)
LoadData(dat, ram, base)
}
func RunFull() { func RunFull() {
interpreter, statedb := GetInterpreter(0, true) interpreter, statedb := GetInterpreter(0, true)
DeployChain(interpreter, statedb) DeployChain(interpreter, statedb)
......
package main package main
import ( import "fmt"
"encoding/binary"
"fmt"
"io/ioutil"
"log"
"os"
"strconv"
"strings"
"time"
)
func LoadData(dat []byte, ram map[uint32](uint32), base uint32) { func main() {
for i := 0; i < len(dat); i += 4 { // step 1, generate the checkpoints every million steps using unicorn
value := binary.BigEndian.Uint32(dat[i : i+4])
if value != 0 {
ram[base+uint32(i)] = value
}
}
}
func LoadMappedFile(fn string, ram map[uint32](uint32), base uint32) {
dat, _ := ioutil.ReadFile(fn)
LoadData(dat, ram, base)
}
func ZeroRegisters(ram map[uint32](uint32)) {
for i := uint32(0xC0000000); i < 0xC0000000+36*4; i += 4 {
WriteRam(ram, i, 0)
}
}
func RunMinigeth(fn string, steps int, debug int) {
ram := make(map[uint32](uint32)) ram := make(map[uint32](uint32))
LoadMappedFile(fn, ram, 0) LoadMappedFile("../mipigo/minigeth", ram, 0)
LoadMappedFile(fmt.Sprintf("/tmp/eth/%d", 13284469), ram, 0xB0000000) LoadMappedFile(fmt.Sprintf("/tmp/eth/%d/input", 13284469), ram, 0xB0000000)
RunWithRam(ram, steps, debug, nil) ZeroRegisters(ram)
}
func runTest(fn string, steps int, debug int) (uint32, uint64) { // step 2 (optional), validate each 1 million chunk in EVM
ram := make(map[uint32](uint32))
ram[0xC000007C] = 0x5EAD0000
LoadMappedFile(fn, ram, 0)
start := time.Now() // step 3 (super optional) validate each 1 million chunk on chain
remainingGas, err := RunWithRam(ram, steps, debug, nil)
elapsed := time.Now().Sub(start)
fmt.Println(err, remainingGas, elapsed, //RunWithRam(ram, steps, debug, nil)
ram[0xbffffff4], ram[0xbffffff8], fmt.Sprintf("%x", ram[0xc0000080]), fn)
if err != nil {
log.Fatal(err)
}
return ram[0xbffffff4] & ram[0xbffffff8], remainingGas
}
func main() {
steps, _ := strconv.Atoi(os.Getenv("STEPS"))
if steps == 0 {
steps = 1000000
}
if len(os.Args) > 1 {
if strings.HasPrefix(os.Args[1], "../mipigo/") {
debug, _ := strconv.Atoi(os.Getenv("DEBUG"))
RunMinigeth(os.Args[1], steps, debug)
} else if os.Args[1] == "unicorn" {
uniram := make(map[uint32](uint32))
RunUnicorn(os.Args[2], uniram, steps, false, false, nil)
} else {
runTest(os.Args[1], 20, 2)
}
} else {
files, err := ioutil.ReadDir("test/bin")
if err != nil {
log.Fatal(err)
}
good := true
gas := uint64(0)
for _, f := range files {
ret, lgas := runTest("test/bin/"+f.Name(), 100, 0)
good = good && (ret == 1)
gas += lgas
}
if !good {
panic("some tests failed")
}
fmt.Println("used", gas, "gas")
}
} }
...@@ -10,7 +10,7 @@ import ( ...@@ -10,7 +10,7 @@ import (
func TestMinigethUnicorn(t *testing.T) { func TestMinigethUnicorn(t *testing.T) {
uniram := make(map[uint32](uint32)) uniram := make(map[uint32](uint32))
RunUnicorn("../mipigo/minigeth.bin", uniram, -1, false, true, nil) RunUnicorn("../mipigo/minigeth.bin", uniram, false, true, nil)
} }
func TestSimpleEVM(t *testing.T) { func TestSimpleEVM(t *testing.T) {
......
...@@ -70,13 +70,10 @@ func SyncRegs(mu uc.Unicorn, ram map[uint32](uint32)) { ...@@ -70,13 +70,10 @@ func SyncRegs(mu uc.Unicorn, ram map[uint32](uint32)) {
WriteRam(ram, REG_HEAP, uint32(heap_start)) WriteRam(ram, REG_HEAP, uint32(heap_start))
} }
// reimplement simple.py in go func GetHookedUnicorn(root string, ram map[uint32](uint32), slowMode bool, callback func(int, uc.Unicorn, map[uint32](uint32))) uc.Unicorn {
func RunUnicorn(fn string, ram map[uint32](uint32), totalSteps int, slowMode bool, checkIO bool, callback func(int, uc.Unicorn, map[uint32](uint32))) {
mu, err := uc.NewUnicorn(uc.ARCH_MIPS, uc.MODE_32|uc.MODE_BIG_ENDIAN) mu, err := uc.NewUnicorn(uc.ARCH_MIPS, uc.MODE_32|uc.MODE_BIG_ENDIAN)
check(err) check(err)
root := "/tmp/eth/13284469"
mu.HookAdd(uc.HOOK_INTR, func(mu uc.Unicorn, intno uint32) { mu.HookAdd(uc.HOOK_INTR, func(mu uc.Unicorn, intno uint32) {
if intno != 17 { if intno != 17 {
log.Fatal("invalid interrupt ", intno, " at step ", steps) log.Fatal("invalid interrupt ", intno, " at step ", steps)
...@@ -161,15 +158,18 @@ func RunUnicorn(fn string, ram map[uint32](uint32), totalSteps int, slowMode boo ...@@ -161,15 +158,18 @@ func RunUnicorn(fn string, ram map[uint32](uint32), totalSteps int, slowMode boo
if callback != nil { if callback != nil {
callback(steps, mu, ram) callback(steps, mu, ram)
} }
if totalSteps == steps {
//os.Exit(0)
// immediate exit
mu.RegWrite(uc.MIPS_REG_PC, 0x5ead0004)
}
steps += 1 steps += 1
}, 0, 0x80000000) }, 0, 0x80000000)
} }
return mu
}
// reimplement simple.py in go
func RunUnicorn(fn string, ram map[uint32](uint32), slowMode bool, checkIO bool, callback func(int, uc.Unicorn, map[uint32](uint32))) {
root := "/tmp/eth/13284469"
mu := GetHookedUnicorn(root, ram, slowMode, callback)
// loop forever to match EVM // loop forever to match EVM
//mu.MemMap(0x5ead0000, 0x1000) //mu.MemMap(0x5ead0000, 0x1000)
//mu.MemWrite(0xdead0000, []byte{0x08, 0x10, 0x00, 0x00}) //mu.MemWrite(0xdead0000, []byte{0x08, 0x10, 0x00, 0x00})
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment