blockchain: properly set invocation counter for verification ctx

Fix problem noted in #2270.
This commit is contained in:
Roman Khimov 2022-01-13 01:34:46 +03:00
parent 9f9bd7261c
commit fc45d3b132
4 changed files with 12 additions and 19 deletions

View file

@ -22,7 +22,6 @@ import (
"github.com/nspcc-dev/neo-go/pkg/rpc/response/result/subscriptions" "github.com/nspcc-dev/neo-go/pkg/rpc/response/result/subscriptions"
"github.com/nspcc-dev/neo-go/pkg/smartcontract/trigger" "github.com/nspcc-dev/neo-go/pkg/smartcontract/trigger"
"github.com/nspcc-dev/neo-go/pkg/util" "github.com/nspcc-dev/neo-go/pkg/util"
"github.com/nspcc-dev/neo-go/pkg/vm"
uatomic "go.uber.org/atomic" uatomic "go.uber.org/atomic"
) )
@ -104,8 +103,8 @@ func (chain *FakeChain) IsTxStillRelevant(t *transaction.Transaction, txpool *me
panic("TODO") panic("TODO")
} }
// InitVerificationVM initializes VM for witness check. // InitVerificationContext initializes context for witness check.
func (chain *FakeChain) InitVerificationVM(v *vm.VM, getContract func(util.Uint160) (*state.Contract, error), hash util.Uint160, witness *transaction.Witness) error { func (chain *FakeChain) InitVerificationContext(ic *interop.Context, hash util.Uint160, witness *transaction.Witness) error {
panic("TODO") panic("TODO")
} }

View file

@ -2160,8 +2160,8 @@ var (
ErrInvalidVerificationContract = errors.New("verification contract is missing `verify` method") ErrInvalidVerificationContract = errors.New("verification contract is missing `verify` method")
) )
// InitVerificationVM initializes VM for witness check. // InitVerificationContext initializes context for witness check.
func (bc *Blockchain) InitVerificationVM(v *vm.VM, getContract func(util.Uint160) (*state.Contract, error), hash util.Uint160, witness *transaction.Witness) error { func (bc *Blockchain) InitVerificationContext(ic *interop.Context, hash util.Uint160, witness *transaction.Witness) error {
if len(witness.VerificationScript) != 0 { if len(witness.VerificationScript) != 0 {
if witness.ScriptHash() != hash { if witness.ScriptHash() != hash {
return ErrWitnessHashMismatch return ErrWitnessHashMismatch
@ -2173,9 +2173,9 @@ func (bc *Blockchain) InitVerificationVM(v *vm.VM, getContract func(util.Uint160
if err != nil { if err != nil {
return fmt.Errorf("%w: %v", ErrInvalidVerification, err) return fmt.Errorf("%w: %v", ErrInvalidVerification, err)
} }
v.LoadScriptWithHash(witness.VerificationScript, hash, callflag.ReadOnly) ic.VM.LoadScriptWithHash(witness.VerificationScript, hash, callflag.ReadOnly)
} else { } else {
cs, err := getContract(hash) cs, err := ic.GetContract(hash)
if err != nil { if err != nil {
return ErrUnknownVerificationContract return ErrUnknownVerificationContract
} }
@ -2189,7 +2189,8 @@ func (bc *Blockchain) InitVerificationVM(v *vm.VM, getContract func(util.Uint160
if md != nil { if md != nil {
initOffset = md.Offset initOffset = md.Offset
} }
v.LoadNEFMethod(&cs.NEF, util.Uint160{}, hash, callflag.ReadOnly, ic.Invocations[cs.Hash]++
ic.VM.LoadNEFMethod(&cs.NEF, util.Uint160{}, hash, callflag.ReadOnly,
true, verifyOffset, initOffset) true, verifyOffset, initOffset)
} }
if len(witness.InvocationScript) != 0 { if len(witness.InvocationScript) != 0 {
@ -2197,7 +2198,7 @@ func (bc *Blockchain) InitVerificationVM(v *vm.VM, getContract func(util.Uint160
if err != nil { if err != nil {
return fmt.Errorf("%w: %v", ErrInvalidInvocation, err) return fmt.Errorf("%w: %v", ErrInvalidInvocation, err)
} }
v.LoadScript(witness.InvocationScript) ic.VM.LoadScript(witness.InvocationScript)
} }
return nil return nil
} }
@ -2221,7 +2222,7 @@ func (bc *Blockchain) verifyHashAgainstScript(hash util.Uint160, witness *transa
vm.SetPriceGetter(interopCtx.GetPrice) vm.SetPriceGetter(interopCtx.GetPrice)
vm.LoadToken = contract.LoadToken(interopCtx) vm.LoadToken = contract.LoadToken(interopCtx)
vm.GasLimit = gas vm.GasLimit = gas
if err := bc.InitVerificationVM(vm, interopCtx.GetContract, hash, witness); err != nil { if err := bc.InitVerificationContext(interopCtx, hash, witness); err != nil {
return 0, err return 0, err
} }
err := interopCtx.Exec() err := interopCtx.Exec()

View file

@ -15,7 +15,6 @@ import (
"github.com/nspcc-dev/neo-go/pkg/rpc/response/result/subscriptions" "github.com/nspcc-dev/neo-go/pkg/rpc/response/result/subscriptions"
"github.com/nspcc-dev/neo-go/pkg/smartcontract/trigger" "github.com/nspcc-dev/neo-go/pkg/smartcontract/trigger"
"github.com/nspcc-dev/neo-go/pkg/util" "github.com/nspcc-dev/neo-go/pkg/util"
"github.com/nspcc-dev/neo-go/pkg/vm"
) )
// Blockchainer is an interface that abstract the implementation // Blockchainer is an interface that abstract the implementation
@ -26,7 +25,7 @@ type Blockchainer interface {
Blockqueuer // Blockqueuer interface Blockqueuer // Blockqueuer interface
CalculateClaimable(h util.Uint160, endHeight uint32) (*big.Int, error) CalculateClaimable(h util.Uint160, endHeight uint32) (*big.Int, error)
Close() Close()
InitVerificationVM(v *vm.VM, getContract func(util.Uint160) (*state.Contract, error), hash util.Uint160, witness *transaction.Witness) error InitVerificationContext(ic *interop.Context, hash util.Uint160, witness *transaction.Witness) error
IsTxStillRelevant(t *transaction.Transaction, txpool *mempool.Pool, isPartialTx bool) bool IsTxStillRelevant(t *transaction.Transaction, txpool *mempool.Pool, isPartialTx bool) bool
HeaderHeight() uint32 HeaderHeight() uint32
GetBlock(hash util.Uint256) (*block.Block, error) GetBlock(hash util.Uint256) (*block.Block, error)

View file

@ -1703,13 +1703,7 @@ func (s *Server) runScriptInVM(t trigger.Type, script []byte, contractScriptHash
ic.VM.GasLimit = gasPolicy ic.VM.GasLimit = gasPolicy
} }
err := s.chain.InitVerificationVM(ic.VM, func(h util.Uint160) (*state.Contract, error) { err := s.chain.InitVerificationContext(ic, contractScriptHash, &transaction.Witness{InvocationScript: script, VerificationScript: []byte{}})
res := s.chain.GetContractState(h)
if res == nil {
return nil, fmt.Errorf("unknown contract: %s", h.StringBE())
}
return res, nil
}, contractScriptHash, &transaction.Witness{InvocationScript: script, VerificationScript: []byte{}})
if err != nil { if err != nil {
return nil, response.NewInternalServerError("can't prepare verification VM", err) return nil, response.NewInternalServerError("can't prepare verification VM", err)
} }