Merge pull request #1476 from nspcc-dev/fix/verify
core: allow to invoke `verify` of native contracts
This commit is contained in:
commit
99e0e346c6
2 changed files with 36 additions and 3 deletions
|
@ -29,6 +29,8 @@ import (
|
|||
"github.com/nspcc-dev/neo-go/pkg/smartcontract/trigger"
|
||||
"github.com/nspcc-dev/neo-go/pkg/util"
|
||||
"github.com/nspcc-dev/neo-go/pkg/vm"
|
||||
"github.com/nspcc-dev/neo-go/pkg/vm/emit"
|
||||
"github.com/nspcc-dev/neo-go/pkg/vm/opcode"
|
||||
"github.com/nspcc-dev/neo-go/pkg/vm/stackitem"
|
||||
"go.uber.org/zap"
|
||||
)
|
||||
|
@ -1478,20 +1480,25 @@ func (bc *Blockchain) GetTestVM(tx *transaction.Transaction) *vm.VM {
|
|||
// Various witness verification errors.
|
||||
var (
|
||||
ErrWitnessHashMismatch = errors.New("witness hash mismatch")
|
||||
ErrNativeContractWitness = errors.New("native contract witness must have empty verification script")
|
||||
ErrVerificationFailed = errors.New("signature check failed")
|
||||
ErrUnknownVerificationContract = errors.New("unknown verification contract")
|
||||
ErrInvalidVerificationContract = errors.New("verification contract is missing `verify` method")
|
||||
)
|
||||
|
||||
// initVerificationVM initializes VM for witness check.
|
||||
func initVerificationVM(ic *interop.Context, hash util.Uint160, witness *transaction.Witness) error {
|
||||
func (bc *Blockchain) initVerificationVM(ic *interop.Context, hash util.Uint160, witness *transaction.Witness) error {
|
||||
var offset int
|
||||
var isNative bool
|
||||
var initMD *manifest.Method
|
||||
verification := witness.VerificationScript
|
||||
if len(verification) != 0 {
|
||||
if witness.ScriptHash() != hash {
|
||||
return ErrWitnessHashMismatch
|
||||
}
|
||||
if bc.contracts.ByHash(hash) != nil {
|
||||
return ErrNativeContractWitness
|
||||
}
|
||||
} else {
|
||||
cs, err := ic.DAO.GetContractState(hash)
|
||||
if err != nil {
|
||||
|
@ -1504,12 +1511,21 @@ func initVerificationVM(ic *interop.Context, hash util.Uint160, witness *transac
|
|||
verification = cs.Script
|
||||
offset = md.Offset
|
||||
initMD = cs.Manifest.ABI.GetMethod(manifest.MethodInit)
|
||||
isNative = cs.ID < 0
|
||||
}
|
||||
|
||||
v := ic.VM
|
||||
v.LoadScriptWithFlags(verification, smartcontract.NoneFlag)
|
||||
v.Jump(v.Context(), offset)
|
||||
if initMD != nil {
|
||||
if isNative {
|
||||
w := io.NewBufBinWriter()
|
||||
emit.Opcodes(w.BinWriter, opcode.DEPTH, opcode.PACK)
|
||||
emit.String(w.BinWriter, manifest.MethodVerify)
|
||||
if w.Err != nil {
|
||||
return w.Err
|
||||
}
|
||||
v.LoadScript(w.Bytes())
|
||||
} else if initMD != nil {
|
||||
v.Call(v.Context(), initMD.Offset)
|
||||
}
|
||||
v.LoadScript(witness.InvocationScript)
|
||||
|
@ -1534,7 +1550,7 @@ func (bc *Blockchain) verifyHashAgainstScript(hash util.Uint160, witness *transa
|
|||
vm := interopCtx.SpawnVM()
|
||||
vm.SetPriceGetter(getPrice)
|
||||
vm.GasLimit = gas
|
||||
if err := initVerificationVM(interopCtx, hash, witness); err != nil {
|
||||
if err := bc.initVerificationVM(interopCtx, hash, witness); err != nil {
|
||||
return 0, err
|
||||
}
|
||||
err := vm.Run()
|
||||
|
|
|
@ -510,6 +510,23 @@ func TestVerifyTx(t *testing.T) {
|
|||
tx := getOracleTx(t)
|
||||
require.NoError(t, oracleAcc.SignTx(tx))
|
||||
require.NoError(t, bc.VerifyTx(tx))
|
||||
|
||||
t.Run("NativeVerify", func(t *testing.T) {
|
||||
tx.Signers = append(tx.Signers, transaction.Signer{
|
||||
Account: bc.contracts.Oracle.Hash,
|
||||
Scopes: transaction.None,
|
||||
})
|
||||
tx.Scripts = append(tx.Scripts, transaction.Witness{})
|
||||
t.Run("NonZeroVerification", func(t *testing.T) {
|
||||
tx.Scripts[len(tx.Scripts)-1].VerificationScript = bc.contracts.Oracle.Script
|
||||
err := bc.VerifyTx(tx)
|
||||
require.True(t, errors.Is(err, ErrNativeContractWitness), "got: %v", err)
|
||||
})
|
||||
t.Run("Good", func(t *testing.T) {
|
||||
tx.Scripts[len(tx.Scripts)-1].VerificationScript = nil
|
||||
require.NoError(t, bc.VerifyTx(tx))
|
||||
})
|
||||
})
|
||||
})
|
||||
t.Run("InvalidRequestID", func(t *testing.T) {
|
||||
tx := getOracleTx(t)
|
||||
|
|
Loading…
Reference in a new issue