Merge pull request #1508 from nspcc-dev/core/check_witness_tests
core: add CheckWitness tests
This commit is contained in:
commit
0eb4ad8564
2 changed files with 199 additions and 3 deletions
|
@ -25,9 +25,6 @@ func CheckHashedWitness(ic *interop.Context, hash util.Uint160) (bool, error) {
|
|||
return checkScope(ic.DAO, tx, ic.VM, hash)
|
||||
}
|
||||
|
||||
if !ic.VM.Context().GetCallFlags().Has(smartcontract.AllowStates) {
|
||||
return false, errors.New("missing AllowStates call flag")
|
||||
}
|
||||
return false, errors.New("script container is not a transaction")
|
||||
}
|
||||
|
||||
|
|
|
@ -16,6 +16,7 @@ import (
|
|||
"github.com/nspcc-dev/neo-go/pkg/core/transaction"
|
||||
"github.com/nspcc-dev/neo-go/pkg/crypto/hash"
|
||||
"github.com/nspcc-dev/neo-go/pkg/crypto/keys"
|
||||
"github.com/nspcc-dev/neo-go/pkg/internal/random"
|
||||
"github.com/nspcc-dev/neo-go/pkg/io"
|
||||
"github.com/nspcc-dev/neo-go/pkg/smartcontract"
|
||||
"github.com/nspcc-dev/neo-go/pkg/smartcontract/manifest"
|
||||
|
@ -514,6 +515,16 @@ func loadScript(ic *interop.Context, script []byte, args ...interface{}) {
|
|||
ic.VM = v
|
||||
}
|
||||
|
||||
func loadScriptWithHashAndFlags(ic *interop.Context, script []byte, hash util.Uint160, f smartcontract.CallFlag, args ...interface{}) {
|
||||
v := vm.New()
|
||||
v.LoadScriptWithHash(script, hash, f)
|
||||
for i := range args {
|
||||
v.Estack().PushVal(args[i])
|
||||
}
|
||||
v.GasLimit = -1
|
||||
ic.VM = v
|
||||
}
|
||||
|
||||
func TestContractCall(t *testing.T) {
|
||||
_, ic, bc := createVM(t)
|
||||
defer bc.Close()
|
||||
|
@ -1093,3 +1104,191 @@ func TestSyscallCallback(t *testing.T) {
|
|||
})
|
||||
})
|
||||
}
|
||||
|
||||
func TestRuntimeCheckWitness(t *testing.T) {
|
||||
_, ic, bc := createVM(t)
|
||||
defer bc.Close()
|
||||
|
||||
script := []byte{byte(opcode.RET)}
|
||||
scriptHash := hash.Hash160(script)
|
||||
check := func(t *testing.T, ic *interop.Context, arg interface{}, shouldFail bool, expected ...bool) {
|
||||
ic.VM.Estack().PushVal(arg)
|
||||
err := runtime.CheckWitness(ic)
|
||||
if shouldFail {
|
||||
require.Error(t, err)
|
||||
} else {
|
||||
require.NoError(t, err)
|
||||
require.NotNil(t, expected)
|
||||
actual, ok := ic.VM.Estack().Pop().Value().(bool)
|
||||
require.True(t, ok)
|
||||
require.Equal(t, expected[0], actual)
|
||||
}
|
||||
}
|
||||
t.Run("error", func(t *testing.T) {
|
||||
t.Run("not a hash or key", func(t *testing.T) {
|
||||
check(t, ic, []byte{1, 2, 3}, true)
|
||||
})
|
||||
t.Run("script container is not a transaction", func(t *testing.T) {
|
||||
loadScriptWithHashAndFlags(ic, script, scriptHash, smartcontract.AllowStates)
|
||||
check(t, ic, random.Uint160().BytesBE(), true)
|
||||
})
|
||||
t.Run("check scope", func(t *testing.T) {
|
||||
t.Run("CustomGroups, missing AllowStates flag", func(t *testing.T) {
|
||||
hash := random.Uint160()
|
||||
tx := &transaction.Transaction{
|
||||
Signers: []transaction.Signer{
|
||||
{
|
||||
Account: hash,
|
||||
Scopes: transaction.CustomGroups,
|
||||
AllowedGroups: []*keys.PublicKey{},
|
||||
},
|
||||
},
|
||||
}
|
||||
ic.Container = tx
|
||||
callingScriptHash := scriptHash
|
||||
loadScriptWithHashAndFlags(ic, script, callingScriptHash, smartcontract.All)
|
||||
ic.VM.LoadScriptWithHash([]byte{0x1}, random.Uint160(), smartcontract.AllowCall)
|
||||
check(t, ic, hash.BytesBE(), true)
|
||||
})
|
||||
t.Run("CustomGroups, unknown contract", func(t *testing.T) {
|
||||
hash := random.Uint160()
|
||||
tx := &transaction.Transaction{
|
||||
Signers: []transaction.Signer{
|
||||
{
|
||||
Account: hash,
|
||||
Scopes: transaction.CustomGroups,
|
||||
AllowedGroups: []*keys.PublicKey{},
|
||||
},
|
||||
},
|
||||
}
|
||||
ic.Container = tx
|
||||
callingScriptHash := scriptHash
|
||||
loadScriptWithHashAndFlags(ic, script, callingScriptHash, smartcontract.All)
|
||||
ic.VM.LoadScriptWithHash([]byte{0x1}, random.Uint160(), smartcontract.AllowStates)
|
||||
check(t, ic, hash.BytesBE(), true)
|
||||
})
|
||||
})
|
||||
})
|
||||
t.Run("positive", func(t *testing.T) {
|
||||
t.Run("calling scripthash", func(t *testing.T) {
|
||||
t.Run("hashed witness", func(t *testing.T) {
|
||||
callingScriptHash := scriptHash
|
||||
loadScriptWithHashAndFlags(ic, script, callingScriptHash, smartcontract.All)
|
||||
ic.VM.LoadScriptWithHash([]byte{0x1}, random.Uint160(), smartcontract.All)
|
||||
check(t, ic, callingScriptHash.BytesBE(), false, true)
|
||||
})
|
||||
t.Run("keyed witness", func(t *testing.T) {
|
||||
pk, err := keys.NewPrivateKey()
|
||||
require.NoError(t, err)
|
||||
callingScriptHash := pk.PublicKey().GetScriptHash()
|
||||
loadScriptWithHashAndFlags(ic, script, callingScriptHash, smartcontract.All)
|
||||
ic.VM.LoadScriptWithHash([]byte{0x1}, random.Uint160(), smartcontract.All)
|
||||
check(t, ic, pk.PublicKey().Bytes(), false, true)
|
||||
})
|
||||
})
|
||||
t.Run("check scope", func(t *testing.T) {
|
||||
t.Run("Global", func(t *testing.T) {
|
||||
hash := random.Uint160()
|
||||
tx := &transaction.Transaction{
|
||||
Signers: []transaction.Signer{
|
||||
{
|
||||
Account: hash,
|
||||
Scopes: transaction.Global,
|
||||
},
|
||||
},
|
||||
}
|
||||
loadScriptWithHashAndFlags(ic, script, scriptHash, smartcontract.AllowStates)
|
||||
ic.Container = tx
|
||||
check(t, ic, hash.BytesBE(), false, true)
|
||||
})
|
||||
t.Run("CalledByEntry", func(t *testing.T) {
|
||||
hash := random.Uint160()
|
||||
tx := &transaction.Transaction{
|
||||
Signers: []transaction.Signer{
|
||||
{
|
||||
Account: hash,
|
||||
Scopes: transaction.CalledByEntry,
|
||||
},
|
||||
},
|
||||
}
|
||||
loadScriptWithHashAndFlags(ic, script, scriptHash, smartcontract.AllowStates)
|
||||
ic.Container = tx
|
||||
check(t, ic, hash.BytesBE(), false, true)
|
||||
})
|
||||
t.Run("CustomContracts", func(t *testing.T) {
|
||||
hash := random.Uint160()
|
||||
tx := &transaction.Transaction{
|
||||
Signers: []transaction.Signer{
|
||||
{
|
||||
Account: hash,
|
||||
Scopes: transaction.CustomContracts,
|
||||
AllowedContracts: []util.Uint160{scriptHash},
|
||||
},
|
||||
},
|
||||
}
|
||||
loadScriptWithHashAndFlags(ic, script, scriptHash, smartcontract.AllowStates)
|
||||
ic.Container = tx
|
||||
check(t, ic, hash.BytesBE(), false, true)
|
||||
})
|
||||
t.Run("CustomGroups", func(t *testing.T) {
|
||||
t.Run("empty calling scripthash", func(t *testing.T) {
|
||||
hash := random.Uint160()
|
||||
tx := &transaction.Transaction{
|
||||
Signers: []transaction.Signer{
|
||||
{
|
||||
Account: hash,
|
||||
Scopes: transaction.CustomGroups,
|
||||
AllowedGroups: []*keys.PublicKey{},
|
||||
},
|
||||
},
|
||||
}
|
||||
loadScriptWithHashAndFlags(ic, script, scriptHash, smartcontract.AllowStates)
|
||||
ic.Container = tx
|
||||
check(t, ic, hash.BytesBE(), false, false)
|
||||
})
|
||||
t.Run("positive", func(t *testing.T) {
|
||||
targetHash := random.Uint160()
|
||||
pk, err := keys.NewPrivateKey()
|
||||
require.NoError(t, err)
|
||||
tx := &transaction.Transaction{
|
||||
Signers: []transaction.Signer{
|
||||
{
|
||||
Account: targetHash,
|
||||
Scopes: transaction.CustomGroups,
|
||||
AllowedGroups: []*keys.PublicKey{pk.PublicKey()},
|
||||
},
|
||||
},
|
||||
}
|
||||
contractScript := []byte{byte(opcode.PUSH1), byte(opcode.RET)}
|
||||
contractScriptHash := hash.Hash160(contractScript)
|
||||
contractState := &state.Contract{
|
||||
ID: 15,
|
||||
Script: contractScript,
|
||||
Manifest: manifest.Manifest{
|
||||
Groups: []manifest.Group{{PublicKey: pk.PublicKey()}},
|
||||
},
|
||||
}
|
||||
require.NoError(t, ic.DAO.PutContractState(contractState))
|
||||
loadScriptWithHashAndFlags(ic, contractScript, contractScriptHash, smartcontract.All)
|
||||
ic.VM.LoadScriptWithHash([]byte{0x1}, random.Uint160(), smartcontract.AllowStates)
|
||||
ic.Container = tx
|
||||
check(t, ic, targetHash.BytesBE(), false, true)
|
||||
})
|
||||
})
|
||||
t.Run("bad scope", func(t *testing.T) {
|
||||
hash := random.Uint160()
|
||||
tx := &transaction.Transaction{
|
||||
Signers: []transaction.Signer{
|
||||
{
|
||||
Account: hash,
|
||||
Scopes: transaction.None,
|
||||
},
|
||||
},
|
||||
}
|
||||
loadScriptWithHashAndFlags(ic, script, scriptHash, smartcontract.AllowStates)
|
||||
ic.Container = tx
|
||||
check(t, ic, hash.BytesBE(), false, false)
|
||||
})
|
||||
})
|
||||
})
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue