From fc45d3b132177e5549cd8a17260efc2d49d7a12a Mon Sep 17 00:00:00 2001 From: Roman Khimov Date: Thu, 13 Jan 2022 01:34:46 +0300 Subject: [PATCH] blockchain: properly set invocation counter for verification ctx Fix problem noted in #2270. --- internal/fakechain/fakechain.go | 5 ++--- pkg/core/blockchain.go | 15 ++++++++------- pkg/core/blockchainer/blockchainer.go | 3 +-- pkg/rpc/server/server.go | 8 +------- 4 files changed, 12 insertions(+), 19 deletions(-) diff --git a/internal/fakechain/fakechain.go b/internal/fakechain/fakechain.go index 3704eb234..9d5666d8a 100644 --- a/internal/fakechain/fakechain.go +++ b/internal/fakechain/fakechain.go @@ -22,7 +22,6 @@ import ( "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/util" - "github.com/nspcc-dev/neo-go/pkg/vm" uatomic "go.uber.org/atomic" ) @@ -104,8 +103,8 @@ func (chain *FakeChain) IsTxStillRelevant(t *transaction.Transaction, txpool *me panic("TODO") } -// InitVerificationVM initializes VM for witness check. -func (chain *FakeChain) InitVerificationVM(v *vm.VM, getContract func(util.Uint160) (*state.Contract, error), hash util.Uint160, witness *transaction.Witness) error { +// InitVerificationContext initializes context for witness check. +func (chain *FakeChain) InitVerificationContext(ic *interop.Context, hash util.Uint160, witness *transaction.Witness) error { panic("TODO") } diff --git a/pkg/core/blockchain.go b/pkg/core/blockchain.go index a807a4407..bc93aac6a 100644 --- a/pkg/core/blockchain.go +++ b/pkg/core/blockchain.go @@ -2160,8 +2160,8 @@ var ( ErrInvalidVerificationContract = errors.New("verification contract is missing `verify` method") ) -// InitVerificationVM initializes VM for witness check. -func (bc *Blockchain) InitVerificationVM(v *vm.VM, getContract func(util.Uint160) (*state.Contract, error), hash util.Uint160, witness *transaction.Witness) error { +// InitVerificationContext initializes context for witness check. +func (bc *Blockchain) InitVerificationContext(ic *interop.Context, hash util.Uint160, witness *transaction.Witness) error { if len(witness.VerificationScript) != 0 { if witness.ScriptHash() != hash { return ErrWitnessHashMismatch @@ -2173,9 +2173,9 @@ func (bc *Blockchain) InitVerificationVM(v *vm.VM, getContract func(util.Uint160 if err != nil { return fmt.Errorf("%w: %v", ErrInvalidVerification, err) } - v.LoadScriptWithHash(witness.VerificationScript, hash, callflag.ReadOnly) + ic.VM.LoadScriptWithHash(witness.VerificationScript, hash, callflag.ReadOnly) } else { - cs, err := getContract(hash) + cs, err := ic.GetContract(hash) if err != nil { return ErrUnknownVerificationContract } @@ -2189,7 +2189,8 @@ func (bc *Blockchain) InitVerificationVM(v *vm.VM, getContract func(util.Uint160 if md != nil { 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) } if len(witness.InvocationScript) != 0 { @@ -2197,7 +2198,7 @@ func (bc *Blockchain) InitVerificationVM(v *vm.VM, getContract func(util.Uint160 if err != nil { return fmt.Errorf("%w: %v", ErrInvalidInvocation, err) } - v.LoadScript(witness.InvocationScript) + ic.VM.LoadScript(witness.InvocationScript) } return nil } @@ -2221,7 +2222,7 @@ func (bc *Blockchain) verifyHashAgainstScript(hash util.Uint160, witness *transa vm.SetPriceGetter(interopCtx.GetPrice) vm.LoadToken = contract.LoadToken(interopCtx) 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 } err := interopCtx.Exec() diff --git a/pkg/core/blockchainer/blockchainer.go b/pkg/core/blockchainer/blockchainer.go index 4a45694a5..12605e363 100644 --- a/pkg/core/blockchainer/blockchainer.go +++ b/pkg/core/blockchainer/blockchainer.go @@ -15,7 +15,6 @@ import ( "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/util" - "github.com/nspcc-dev/neo-go/pkg/vm" ) // Blockchainer is an interface that abstract the implementation @@ -26,7 +25,7 @@ type Blockchainer interface { Blockqueuer // Blockqueuer interface CalculateClaimable(h util.Uint160, endHeight uint32) (*big.Int, error) 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 HeaderHeight() uint32 GetBlock(hash util.Uint256) (*block.Block, error) diff --git a/pkg/rpc/server/server.go b/pkg/rpc/server/server.go index ef91bd320..6ea513586 100644 --- a/pkg/rpc/server/server.go +++ b/pkg/rpc/server/server.go @@ -1703,13 +1703,7 @@ func (s *Server) runScriptInVM(t trigger.Type, script []byte, contractScriptHash ic.VM.GasLimit = gasPolicy } - err := s.chain.InitVerificationVM(ic.VM, func(h util.Uint160) (*state.Contract, error) { - 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{}}) + err := s.chain.InitVerificationContext(ic, contractScriptHash, &transaction.Witness{InvocationScript: script, VerificationScript: []byte{}}) if err != nil { return nil, response.NewInternalServerError("can't prepare verification VM", err) }