Commit c96647f5 authored by protolambda's avatar protolambda

mipsevm: test Go unicorn pre-image oracle integration, fix oracle communication bugs

parent fc3bf6e8
...@@ -12,6 +12,7 @@ contract Oracle { ...@@ -12,6 +12,7 @@ contract Oracle {
require(preimagePartOk[key][offset], "preimage must exist"); require(preimagePartOk[key][offset], "preimage must exist");
datLen = 32; datLen = 32;
uint256 length = preimageLengths[key]; uint256 length = preimageLengths[key];
// TODO: insert length prefix before data
if(offset + 32 >= length) { if(offset + 32 >= length) {
datLen = length - offset; datLen = length - offset;
} }
......
...@@ -15,14 +15,14 @@ func (rh rawHint) Hint() string { ...@@ -15,14 +15,14 @@ func (rh rawHint) Hint() string {
} }
func main() { func main() {
_, _ = os.Stdout.Write([]byte("started!")) _, _ = os.Stderr.Write([]byte("started!"))
po := preimage.NewOracleClient(preimage.ClientPreimageChannel()) po := preimage.NewOracleClient(preimage.ClientPreimageChannel())
hinter := preimage.NewHintWriter(preimage.ClientHinterChannel()) hinter := preimage.NewHintWriter(preimage.ClientHinterChannel())
preHash := po.Get(preimage.LocalIndexKey(0)) preHash := *(*[32]byte)(po.Get(preimage.LocalIndexKey(0)))
diffHash := po.Get(preimage.LocalIndexKey(1)) diffHash := *(*[32]byte)(po.Get(preimage.LocalIndexKey(1)))
claimData := po.Get(preimage.LocalIndexKey(2)) claimData := *(*[8]byte)(po.Get(preimage.LocalIndexKey(2)))
// Hints are used to indicate which things the program will access, // Hints are used to indicate which things the program will access,
// so the server can be prepared to serve the corresponding pre-images. // so the server can be prepared to serve the corresponding pre-images.
...@@ -43,7 +43,7 @@ func main() { ...@@ -43,7 +43,7 @@ func main() {
fmt.Printf("computing %d * %d + %d\n", s, a, b) fmt.Printf("computing %d * %d + %d\n", s, a, b)
sOut := s*a + b sOut := s*a + b
sClaim := binary.BigEndian.Uint64(claimData) sClaim := binary.BigEndian.Uint64(claimData[:])
if sOut != sClaim { if sOut != sClaim {
fmt.Printf("claim %d is bad! Correct result is %d\n", sOut, sClaim) fmt.Printf("claim %d is bad! Correct result is %d\n", sOut, sClaim)
os.Exit(1) os.Exit(1)
......
...@@ -3,8 +3,9 @@ module mipsevm ...@@ -3,8 +3,9 @@ module mipsevm
go 1.20 go 1.20
require ( require (
github.com/ethereum-optimism/cannon/preimage v0.0.0
github.com/ethereum/go-ethereum v1.11.5 github.com/ethereum/go-ethereum v1.11.5
github.com/stretchr/testify v1.8.0 github.com/stretchr/testify v1.8.2
github.com/unicorn-engine/unicorn v0.0.0-20230207094436-7b8c63dfe650 github.com/unicorn-engine/unicorn v0.0.0-20230207094436-7b8c63dfe650
) )
...@@ -50,15 +51,17 @@ require ( ...@@ -50,15 +51,17 @@ require (
github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7 // indirect github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7 // indirect
github.com/tklauser/go-sysconf v0.3.5 // indirect github.com/tklauser/go-sysconf v0.3.5 // indirect
github.com/tklauser/numcpus v0.2.2 // indirect github.com/tklauser/numcpus v0.2.2 // indirect
golang.org/x/crypto v0.1.0 // indirect golang.org/x/crypto v0.8.0 // indirect
golang.org/x/exp v0.0.0-20230206171751-46f607a40771 // indirect golang.org/x/exp v0.0.0-20230206171751-46f607a40771 // indirect
golang.org/x/sys v0.5.0 // indirect golang.org/x/sys v0.7.0 // indirect
golang.org/x/text v0.7.0 // indirect golang.org/x/text v0.9.0 // indirect
google.golang.org/protobuf v1.28.1 // indirect google.golang.org/protobuf v1.28.1 // indirect
gopkg.in/natefinch/npipe.v2 v2.0.0-20160621034901-c1b8fa8bdcce // indirect gopkg.in/natefinch/npipe.v2 v2.0.0-20160621034901-c1b8fa8bdcce // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect
) )
replace github.com/ethereum-optimism/cannon/preimage v0.0.0 => ../preimage
// We need to point to our local Unicorn clone for the shared object to be located correctly in all our Go commands. // We need to point to our local Unicorn clone for the shared object to be located correctly in all our Go commands.
// See https://github.com/unicorn-engine/unicorn/blob/7b8c63dfe650b5d4d2bf684526161971925e6350/bindings/go/unicorn/unicorn.go#L11 // See https://github.com/unicorn-engine/unicorn/blob/7b8c63dfe650b5d4d2bf684526161971925e6350/bindings/go/unicorn/unicorn.go#L11
// The -L../../../ -lunicorn points to the unicorn root directory relative to the unicorn Go bindings. // The -L../../../ -lunicorn points to the unicorn root directory relative to the unicorn Go bindings.
......
...@@ -251,14 +251,16 @@ github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnIn ...@@ -251,14 +251,16 @@ github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnIn
github.com/spf13/viper v1.3.2/go.mod h1:ZiWeW+zYFKm7srdB9IoDzzZXaJaI5eL9QjNiN/DMA2s= github.com/spf13/viper v1.3.2/go.mod h1:ZiWeW+zYFKm7srdB9IoDzzZXaJaI5eL9QjNiN/DMA2s=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo=
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA= github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA=
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.8.0 h1:pSgiaMZlXftHpm5L7V1+rVB+AZJydKsMxsQBIJw4PKk=
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
github.com/stretchr/testify v1.8.2 h1:+h33VjcLVPDHtOdpUCuF+7gSuG3yGIftsP1YvFihtJ8=
github.com/stretchr/testify v1.8.2/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7 h1:epCh84lMvA70Z7CTTCmYQn2CKbY8j86K7/FAIr141uY= github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7 h1:epCh84lMvA70Z7CTTCmYQn2CKbY8j86K7/FAIr141uY=
github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7/go.mod h1:q4W45IWZaF22tdD+VEXcAWRA037jwmWEB5VWYORlTpc= github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7/go.mod h1:q4W45IWZaF22tdD+VEXcAWRA037jwmWEB5VWYORlTpc=
github.com/tklauser/go-sysconf v0.3.5 h1:uu3Xl4nkLzQfXNsWn15rPc/HQCJKObbt1dKJeWp3vU4= github.com/tklauser/go-sysconf v0.3.5 h1:uu3Xl4nkLzQfXNsWn15rPc/HQCJKObbt1dKJeWp3vU4=
...@@ -269,8 +271,6 @@ github.com/ugorji/go v1.1.4/go.mod h1:uQMGLiO92mf5W77hV/PUCpI3pbzQx3CRekS0kk+RGr ...@@ -269,8 +271,6 @@ github.com/ugorji/go v1.1.4/go.mod h1:uQMGLiO92mf5W77hV/PUCpI3pbzQx3CRekS0kk+RGr
github.com/ugorji/go v1.1.7/go.mod h1:kZn38zHttfInRq0xu/PH0az30d+z6vm202qpg1oXVMw= github.com/ugorji/go v1.1.7/go.mod h1:kZn38zHttfInRq0xu/PH0az30d+z6vm202qpg1oXVMw=
github.com/ugorji/go/codec v0.0.0-20181204163529-d75b2dcb6bc8/go.mod h1:VFNgLljTbGfSG7qAOspJ7OScBnGdDN/yBr0sguwnwf0= github.com/ugorji/go/codec v0.0.0-20181204163529-d75b2dcb6bc8/go.mod h1:VFNgLljTbGfSG7qAOspJ7OScBnGdDN/yBr0sguwnwf0=
github.com/ugorji/go/codec v1.1.7/go.mod h1:Ax+UKWsSmolVDwsd+7N3ZtXu+yMGCf907BLYF3GoBXY= github.com/ugorji/go/codec v1.1.7/go.mod h1:Ax+UKWsSmolVDwsd+7N3ZtXu+yMGCf907BLYF3GoBXY=
github.com/unicorn-engine/unicorn v0.0.0-20230207094436-7b8c63dfe650 h1:O8wGQwIFVKk04THvsqbrMi9rXfJwxRU1Bf04NBWvdhI=
github.com/unicorn-engine/unicorn v0.0.0-20230207094436-7b8c63dfe650/go.mod h1:mcHBrigWSHlMZYol9QOFnK7sbltIt/OaKP5CQBZsC+4=
github.com/urfave/negroni v1.0.0/go.mod h1:Meg73S6kFm/4PpbYdq35yYWoCZ9mS/YSx+lKnmiohz4= github.com/urfave/negroni v1.0.0/go.mod h1:Meg73S6kFm/4PpbYdq35yYWoCZ9mS/YSx+lKnmiohz4=
github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc= github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc=
github.com/valyala/fasthttp v1.6.0/go.mod h1:FstJa9V+Pj9vQ7OJie2qMHdwemEDaDiSdBnvPM1Su9w= github.com/valyala/fasthttp v1.6.0/go.mod h1:FstJa9V+Pj9vQ7OJie2qMHdwemEDaDiSdBnvPM1Su9w=
...@@ -296,8 +296,8 @@ golang.org/x/crypto v0.0.0-20191227163750-53104e6ec876/go.mod h1:LzIPMQfyMNhhGPh ...@@ -296,8 +296,8 @@ golang.org/x/crypto v0.0.0-20191227163750-53104e6ec876/go.mod h1:LzIPMQfyMNhhGPh
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/crypto v0.0.0-20210322153248-0c34fe9e7dc2/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4= golang.org/x/crypto v0.0.0-20210322153248-0c34fe9e7dc2/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4=
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
golang.org/x/crypto v0.1.0 h1:MDRAIl0xIo9Io2xV565hzXHw3zVseKrJKodhohM5CjU= golang.org/x/crypto v0.8.0 h1:pd9TJtTueMTVQXzk8E2XESSMQDj/U7OUu0PqJqPXQjQ=
golang.org/x/crypto v0.1.0/go.mod h1:RecgLatLF4+eUMCP1PoPZQb+cVrJcOPbHkTkbkB9sbw= golang.org/x/crypto v0.8.0/go.mod h1:mRqEX+O9/h5TFCrQhkgjo2yKi0yYA+9ecGkdQoHrywE=
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
golang.org/x/exp v0.0.0-20230206171751-46f607a40771 h1:xP7rWLUr1e1n2xkK5YB4LI0hPEy3LJC6Wk+D4pGlOJg= golang.org/x/exp v0.0.0-20230206171751-46f607a40771 h1:xP7rWLUr1e1n2xkK5YB4LI0hPEy3LJC6Wk+D4pGlOJg=
golang.org/x/exp v0.0.0-20230206171751-46f607a40771/go.mod h1:CxIveKay+FTh1D0yPZemJVgC/95VzuuOLq5Qi4xnoYc= golang.org/x/exp v0.0.0-20230206171751-46f607a40771/go.mod h1:CxIveKay+FTh1D0yPZemJVgC/95VzuuOLq5Qi4xnoYc=
...@@ -328,7 +328,7 @@ golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwY ...@@ -328,7 +328,7 @@ golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwY
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM= golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM=
golang.org/x/net v0.0.0-20211008194852-3b03d305991f/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20211008194852-3b03d305991f/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
golang.org/x/net v0.4.0 h1:Q5QPcMlvfxFTAPV0+07Xz/MpK9NTXu2VDUuy0FeMfaU= golang.org/x/net v0.9.0 h1:aWJ/m6xSmxWBx+V0XRHTlrYrPG56jKsLdTFmsSsCzOM=
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
...@@ -368,8 +368,8 @@ golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBc ...@@ -368,8 +368,8 @@ golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBc
golang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20211007075335-d3039528d8ac/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20211007075335-d3039528d8ac/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220209214540-3681064d5158/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220209214540-3681064d5158/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.5.0 h1:MUK/U/4lj1t1oPg0HfuXDN/Z1wv31ZJ/YcPiGccS4DU= golang.org/x/sys v0.7.0 h1:3jlCCIQZPdOYu1h8BkNvLz8Kgwtae2cagcG/VamtZRU=
golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.7.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
...@@ -377,8 +377,8 @@ golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= ...@@ -377,8 +377,8 @@ golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
golang.org/x/text v0.7.0 h1:4BRB4x83lYWy72KwLD/qYDuTu7q9PjSagHvijDw7cLo= golang.org/x/text v0.9.0 h1:2sjJmO8cDvYveuX97RDLsxlyUxLl+GHoLxBiRdHllBE=
golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8=
golang.org/x/time v0.0.0-20201208040808-7e3f01d25324/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20201208040808-7e3f01d25324/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20181221001348-537d06c36207/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20181221001348-537d06c36207/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
......
...@@ -31,6 +31,9 @@ type State struct { ...@@ -31,6 +31,9 @@ type State struct {
// so a VM can start from any state without fetching prior pre-images, // so a VM can start from any state without fetching prior pre-images,
// and instead just repeat the last hint on setup, // and instead just repeat the last hint on setup,
// to make sure pre-image requests can be served. // to make sure pre-image requests can be served.
// The first 4 bytes are a uin32 length prefix.
// Warning: the hint MAY NOT BE COMPLETE. I.e. this is buffered,
// and should only be read when len(LastHint) > 4 && uint32(LastHint[:4]) >= len(LastHint[4:])
LastHint hexutil.Bytes `json:"lastHint,omitempty"` LastHint hexutil.Bytes `json:"lastHint,omitempty"`
} }
......
...@@ -3,12 +3,20 @@ package mipsevm ...@@ -3,12 +3,20 @@ package mipsevm
import ( import (
"bytes" "bytes"
"debug/elf" "debug/elf"
"encoding/binary"
"encoding/hex"
"fmt"
"io" "io"
"os" "os"
"path" "path"
"strings"
"testing" "testing"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/crypto"
"github.com/stretchr/testify/require" "github.com/stretchr/testify/require"
"github.com/ethereum-optimism/cannon/preimage"
) )
// baseAddrStart - baseAddrEnd is used in tests to write the results to // baseAddrStart - baseAddrEnd is used in tests to write the results to
...@@ -108,3 +116,102 @@ func TestHello(t *testing.T) { ...@@ -108,3 +116,102 @@ func TestHello(t *testing.T) {
require.Equal(t, "hello world!", stdOutBuf.String(), "stdout says hello") require.Equal(t, "hello world!", stdOutBuf.String(), "stdout says hello")
require.Equal(t, "", stdErrBuf.String(), "stderr silent") require.Equal(t, "", stdErrBuf.String(), "stderr silent")
} }
type testOracle struct {
hint func(v []byte)
getPreimage func(k [32]byte) []byte
}
func (t *testOracle) Hint(v []byte) {
t.hint(v)
}
func (t *testOracle) GetPreimage(k [32]byte) []byte {
return t.getPreimage(k)
}
var _ PreimageOracle = (*testOracle)(nil)
func TestClaim(t *testing.T) {
elfProgram, err := elf.Open("../example/bin/claim.elf")
require.NoError(t, err, "open ELF file")
state, err := LoadELF(elfProgram)
require.NoError(t, err, "load ELF into state")
err = patchVM(elfProgram, state)
require.NoError(t, err, "apply Go runtime patches")
mu, err := NewUnicorn()
require.NoError(t, err, "load unicorn")
defer mu.Close()
err = LoadUnicorn(state, mu)
require.NoError(t, err, "load state into unicorn")
s := uint64(1000)
a := uint64(3)
b := uint64(4)
encodeU64 := func(x uint64) []byte {
return binary.BigEndian.AppendUint64(nil, x)
}
var diff []byte
diff = append(diff, crypto.Keccak256(encodeU64(a))...)
diff = append(diff, crypto.Keccak256(encodeU64(b))...)
preHash := crypto.Keccak256Hash(encodeU64(s))
diffHash := crypto.Keccak256Hash(diff)
images := make(map[[32]byte][]byte)
images[preimage.LocalIndexKey(0).PreimageKey()] = preHash[:]
images[preimage.LocalIndexKey(1).PreimageKey()] = diffHash[:]
images[preimage.LocalIndexKey(2).PreimageKey()] = encodeU64(s*a + b)
oracle := &testOracle{
hint: func(v []byte) {
parts := strings.Split(string(v), " ")
require.Len(t, parts, 2)
p, err := hex.DecodeString(parts[1])
require.NoError(t, err)
require.Len(t, p, 32)
h := common.Hash(*(*[32]byte)(p))
switch parts[0] {
case "fetch-state":
require.Equal(t, h, preHash, "expecting request for pre-state pre-image")
images[preimage.Keccak256Key(preHash).PreimageKey()] = encodeU64(s)
case "fetch-diff":
require.Equal(t, h, diffHash, "expecting request for diff pre-images")
images[preimage.Keccak256Key(diffHash).PreimageKey()] = diff
images[preimage.Keccak256Key(crypto.Keccak256Hash(encodeU64(a))).PreimageKey()] = encodeU64(a)
images[preimage.Keccak256Key(crypto.Keccak256Hash(encodeU64(b))).PreimageKey()] = encodeU64(b)
default:
t.Fatalf("unexpected hint: %q", parts[0])
}
},
getPreimage: func(k [32]byte) []byte {
p, ok := images[k]
if !ok {
t.Fatalf("missing pre-image %s", k)
}
return p
},
}
var stdOutBuf, stdErrBuf bytes.Buffer
us, err := NewUnicornState(mu, state, oracle, io.MultiWriter(&stdOutBuf, os.Stdout), io.MultiWriter(&stdErrBuf, os.Stderr))
require.NoError(t, err, "hook unicorn to state")
for i := 0; i < 2000_000; i++ {
if us.state.Exited {
break
}
us.Step(false)
}
require.True(t, state.Exited, "must complete program")
require.Equal(t, uint8(0), state.ExitCode, "exit with 0")
require.Equal(t, fmt.Sprintf("computing %d * %d + %d\nclaim %d is good!\n", s, a, b, s*a+b), stdOutBuf.String(), "stdout says hello")
require.Equal(t, "started!", stdErrBuf.String(), "stderr silent")
}
...@@ -32,7 +32,7 @@ type UnicornState struct { ...@@ -32,7 +32,7 @@ type UnicornState struct {
preimageOracle PreimageOracle preimageOracle PreimageOracle
// cached pre-image data // cached pre-image data, including 8 byte length prefix
lastPreimage []byte lastPreimage []byte
// key for above preimage // key for above preimage
lastPreimageKey [32]byte lastPreimageKey [32]byte
...@@ -70,10 +70,16 @@ func NewUnicornState(mu uc.Unicorn, state *State, po PreimageOracle, stdOut, std ...@@ -70,10 +70,16 @@ func NewUnicornState(mu uc.Unicorn, state *State, po PreimageOracle, stdOut, std
readPreimage := func(key [32]byte, offset uint32) (dat [32]byte, datLen uint32) { readPreimage := func(key [32]byte, offset uint32) (dat [32]byte, datLen uint32) {
preimage := m.lastPreimage preimage := m.lastPreimage
if key != m.lastPreimageKey { if key != m.lastPreimageKey {
preimage = po.GetPreimage(key) m.lastPreimageKey = key
data := po.GetPreimage(key)
// add the length prefix
preimage = make([]byte, 0, 8+len(data))
preimage = binary.BigEndian.AppendUint64(preimage, uint64(len(data)))
preimage = append(preimage, data...)
m.lastPreimage = preimage
} }
m.lastPreimageOffset = offset m.lastPreimageOffset = offset
datLen = uint32(copy(dat[:], preimage)) datLen = uint32(copy(dat[:], preimage[offset:]))
return return
} }
...@@ -130,8 +136,10 @@ func NewUnicornState(mu uc.Unicorn, state *State, po PreimageOracle, stdOut, std ...@@ -130,8 +136,10 @@ func NewUnicornState(mu uc.Unicorn, state *State, po PreimageOracle, stdOut, std
case fdStdin: case fdStdin:
// leave v0 and v1 zero: read nothing, no error // leave v0 and v1 zero: read nothing, no error
case fdPreimageRead: // pre-image oracle case fdPreimageRead: // pre-image oracle
mem := st.Memory.GetMemory(a1 & 0xFFffFFfc) effAddr := a1 & 0xFFffFFfc
mem := st.Memory.GetMemory(effAddr)
dat, datLen := readPreimage(st.PreimageKey, st.PreimageOffset) dat, datLen := readPreimage(st.PreimageKey, st.PreimageOffset)
fmt.Printf("reading pre-image data: addr: %08x, offset: %d, datLen: %d, data: %x, key: %s count: %d\n", a1, st.PreimageOffset, datLen, dat[:datLen], st.PreimageKey, a2)
alignment := a1 & 3 alignment := a1 & 3
space := 4 - alignment space := 4 - alignment
if space < datLen { if space < datLen {
...@@ -143,9 +151,13 @@ func NewUnicornState(mu uc.Unicorn, state *State, po PreimageOracle, stdOut, std ...@@ -143,9 +151,13 @@ func NewUnicornState(mu uc.Unicorn, state *State, po PreimageOracle, stdOut, std
var outMem [4]byte var outMem [4]byte
binary.BigEndian.PutUint32(outMem[:], mem) binary.BigEndian.PutUint32(outMem[:], mem)
copy(outMem[alignment:], dat[:datLen]) copy(outMem[alignment:], dat[:datLen])
st.Memory.SetMemory(a1&0xFFffFFfc, binary.BigEndian.Uint32(outMem[:])) st.Memory.SetMemory(effAddr, binary.BigEndian.Uint32(outMem[:]))
if err := mu.MemWrite(uint64(effAddr), outMem[:]); err != nil {
log.Fatalf("failed to write pre-image data to memory: %v", err)
}
st.PreimageOffset += datLen st.PreimageOffset += datLen
v0 = datLen v0 = datLen
fmt.Printf("read %d pre-image bytes, new offset: %d, eff addr: %08x mem: %08x\n", datLen, st.PreimageOffset, effAddr, outMem)
case fdHintRead: // hint response case fdHintRead: // hint response
// don't actually read into memory, just say we read it all, we ignore the result anyway // don't actually read into memory, just say we read it all, we ignore the result anyway
v0 = a2 v0 = a2
...@@ -164,9 +176,19 @@ func NewUnicornState(mu uc.Unicorn, state *State, po PreimageOracle, stdOut, std ...@@ -164,9 +176,19 @@ func NewUnicornState(mu uc.Unicorn, state *State, po PreimageOracle, stdOut, std
_, _ = io.Copy(stdErr, st.Memory.ReadMemoryRange(a1, a2)) _, _ = io.Copy(stdErr, st.Memory.ReadMemoryRange(a1, a2))
v0 = a2 v0 = a2
case fdHintWrite: case fdHintWrite:
hint, _ := io.ReadAll(st.Memory.ReadMemoryRange(a1, a2)) hintData, _ := io.ReadAll(st.Memory.ReadMemoryRange(a1, a2))
v0 = a2 st.LastHint = append(st.LastHint, hintData...)
for len(st.LastHint) >= 4 { // process while there is enough data to check if there are any hints
hintLen := binary.BigEndian.Uint32(st.LastHint[:4])
if hintLen >= uint32(len(st.LastHint[4:])) {
hint := st.LastHint[4 : 4+hintLen] // without the length prefix
st.LastHint = st.LastHint[4+hintLen:]
po.Hint(hint) po.Hint(hint)
} else {
break // stop processing hints if there is incomplete data buffered
}
}
v0 = a2
case fdPreimageWrite: case fdPreimageWrite:
mem := st.Memory.GetMemory(a1 & 0xFFffFFfc) mem := st.Memory.GetMemory(a1 & 0xFFffFFfc)
key := st.PreimageKey key := st.PreimageKey
...@@ -181,6 +203,7 @@ func NewUnicornState(mu uc.Unicorn, state *State, po PreimageOracle, stdOut, std ...@@ -181,6 +203,7 @@ func NewUnicornState(mu uc.Unicorn, state *State, po PreimageOracle, stdOut, std
copy(key[32-a2:], tmp[:]) copy(key[32-a2:], tmp[:])
st.PreimageKey = key st.PreimageKey = key
st.PreimageOffset = 0 st.PreimageOffset = 0
fmt.Printf("updating pre-image key: %s\n", st.PreimageKey)
v0 = a2 v0 = a2
default: default:
v0 = 0xFFffFFff v0 = 0xFFffFFff
......
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