forked from TrueCloudLab/neoneo-go
native: add Oracle.finish reentrancy test
This commit is contained in:
parent
da2db74bc9
commit
8d170a1eb8
5 changed files with 31 additions and 2 deletions
|
@ -1,8 +1,11 @@
|
||||||
package oraclecontract
|
package oraclecontract
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"github.com/nspcc-dev/neo-go/pkg/interop"
|
||||||
|
"github.com/nspcc-dev/neo-go/pkg/interop/contract"
|
||||||
"github.com/nspcc-dev/neo-go/pkg/interop/native/oracle"
|
"github.com/nspcc-dev/neo-go/pkg/interop/native/oracle"
|
||||||
"github.com/nspcc-dev/neo-go/pkg/interop/native/std"
|
"github.com/nspcc-dev/neo-go/pkg/interop/native/std"
|
||||||
|
"github.com/nspcc-dev/neo-go/pkg/interop/runtime"
|
||||||
"github.com/nspcc-dev/neo-go/pkg/interop/storage"
|
"github.com/nspcc-dev/neo-go/pkg/interop/storage"
|
||||||
"github.com/nspcc-dev/neo-go/pkg/interop/util"
|
"github.com/nspcc-dev/neo-go/pkg/interop/util"
|
||||||
)
|
)
|
||||||
|
@ -22,3 +25,18 @@ func Handle(url string, data interface{}, code int, res []byte) {
|
||||||
params := []interface{}{url, data, code, res}
|
params := []interface{}{url, data, code, res}
|
||||||
storage.Put(storage.GetContext(), "lastOracleResponse", std.Serialize(params))
|
storage.Put(storage.GetContext(), "lastOracleResponse", std.Serialize(params))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// HandleRecursive invokes oracle.finish again to test Oracle reentrance.
|
||||||
|
func HandleRecursive(url string, data interface{}, code int, res []byte) {
|
||||||
|
// Regular safety check.
|
||||||
|
callingHash := runtime.GetCallingScriptHash()
|
||||||
|
if !callingHash.Equals(oracle.Hash) {
|
||||||
|
panic("not called from oracle contract")
|
||||||
|
}
|
||||||
|
|
||||||
|
runtime.Notify("Invocation")
|
||||||
|
if runtime.GetInvocationCounter() == 1 {
|
||||||
|
// We provide no wrapper for finish in interops, it's not usually needed.
|
||||||
|
contract.Call(interop.Hash160(oracle.Hash), "finish", contract.All)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -1 +1 @@
|
||||||
{"name":"Oracle test","abi":{"methods":[{"name":"handle","offset":14,"parameters":[{"name":"url","type":"String"},{"name":"data","type":"Any"},{"name":"code","type":"Integer"},{"name":"res","type":"ByteArray"}],"returntype":"Void","safe":false},{"name":"requestURL","offset":0,"parameters":[{"name":"url","type":"String"},{"name":"filter","type":"ByteArray"},{"name":"callback","type":"String"},{"name":"userData","type":"Any"},{"name":"gasForResponse","type":"Integer"}],"returntype":"Void","safe":false}],"events":[]},"features":{},"groups":[],"permissions":[{"contract":"*","methods":["request"]}],"supportedstandards":[],"trusts":[],"extra":null}
|
{"name":"Oracle test","abi":{"methods":[{"name":"handle","offset":14,"parameters":[{"name":"url","type":"String"},{"name":"data","type":"Any"},{"name":"code","type":"Integer"},{"name":"res","type":"ByteArray"}],"returntype":"Void","safe":false},{"name":"handleRecursive","offset":89,"parameters":[{"name":"url","type":"String"},{"name":"data","type":"Any"},{"name":"code","type":"Integer"},{"name":"res","type":"ByteArray"}],"returntype":"Void","safe":false},{"name":"requestURL","offset":0,"parameters":[{"name":"url","type":"String"},{"name":"filter","type":"ByteArray"},{"name":"callback","type":"String"},{"name":"userData","type":"Any"},{"name":"gasForResponse","type":"Integer"}],"returntype":"Void","safe":false}],"events":[{"name":"Invocation","parameters":null}]},"features":{},"groups":[],"permissions":[{"contract":"*","methods":["request","finish"]}],"supportedstandards":[],"trusts":[],"extra":null}
|
Binary file not shown.
|
@ -2,5 +2,6 @@ name: "Oracle test"
|
||||||
sourceurl: https://github.com/nspcc-dev/neo-go/
|
sourceurl: https://github.com/nspcc-dev/neo-go/
|
||||||
supportedstandards: []
|
supportedstandards: []
|
||||||
events:
|
events:
|
||||||
|
- name: Invocation
|
||||||
permissions:
|
permissions:
|
||||||
- methods: ["request"]
|
- methods: ["request", "finish"]
|
||||||
|
|
|
@ -15,6 +15,7 @@ import (
|
||||||
"github.com/nspcc-dev/neo-go/pkg/core/transaction"
|
"github.com/nspcc-dev/neo-go/pkg/core/transaction"
|
||||||
"github.com/nspcc-dev/neo-go/pkg/crypto/keys"
|
"github.com/nspcc-dev/neo-go/pkg/crypto/keys"
|
||||||
"github.com/nspcc-dev/neo-go/pkg/neotest"
|
"github.com/nspcc-dev/neo-go/pkg/neotest"
|
||||||
|
"github.com/nspcc-dev/neo-go/pkg/smartcontract/trigger"
|
||||||
"github.com/nspcc-dev/neo-go/pkg/vm/stackitem"
|
"github.com/nspcc-dev/neo-go/pkg/vm/stackitem"
|
||||||
"github.com/stretchr/testify/require"
|
"github.com/stretchr/testify/require"
|
||||||
)
|
)
|
||||||
|
@ -151,6 +152,15 @@ func TestOracle_Request(t *testing.T) {
|
||||||
require.Error(t, err)
|
require.Error(t, err)
|
||||||
require.True(t, strings.Contains(err.Error(), "oracle tx points to invalid request"))
|
require.True(t, strings.Contains(err.Error(), "oracle tx points to invalid request"))
|
||||||
})
|
})
|
||||||
|
t.Run("Reentrant", func(t *testing.T) {
|
||||||
|
putOracleRequest(t, helperValidatorInvoker, "url", nil, "handleRecursive", []byte{}, gasForResponse)
|
||||||
|
tx := prepareResponseTx(t, 2)
|
||||||
|
e.AddNewBlock(t, tx)
|
||||||
|
// e.CheckFault(t, tx.Hash(), "")
|
||||||
|
aer, err := e.Chain.GetAppExecResults(tx.Hash(), trigger.Application)
|
||||||
|
require.NoError(t, err)
|
||||||
|
require.Equal(t, 2, len(aer[0].Events)) // OracleResponse + Invocation
|
||||||
|
})
|
||||||
t.Run("BadRequest", func(t *testing.T) {
|
t.Run("BadRequest", func(t *testing.T) {
|
||||||
t.Run("non-UTF8 url", func(t *testing.T) {
|
t.Run("non-UTF8 url", func(t *testing.T) {
|
||||||
putOracleRequest(t, helperValidatorInvoker, "\xff", nil, "", []byte{1, 2}, gasForResponse, "invalid value: not UTF-8")
|
putOracleRequest(t, helperValidatorInvoker, "\xff", nil, "", []byte{1, 2}, gasForResponse, "invalid value: not UTF-8")
|
||||||
|
|
Loading…
Add table
Reference in a new issue