diff --git a/pkg/core/interop/context.go b/pkg/core/interop/context.go
index a22980793..93417ecc7 100644
--- a/pkg/core/interop/context.go
+++ b/pkg/core/interop/context.go
@@ -8,13 +8,14 @@ import (
 	"sort"
 	"strings"
 
+	"github.com/nspcc-dev/neo-go/pkg/config"
 	"github.com/nspcc-dev/neo-go/pkg/core/block"
-	"github.com/nspcc-dev/neo-go/pkg/core/blockchainer"
 	"github.com/nspcc-dev/neo-go/pkg/core/dao"
 	"github.com/nspcc-dev/neo-go/pkg/core/interop/interopnames"
 	"github.com/nspcc-dev/neo-go/pkg/core/state"
 	"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/io"
 	"github.com/nspcc-dev/neo-go/pkg/smartcontract/callflag"
 	"github.com/nspcc-dev/neo-go/pkg/smartcontract/manifest"
@@ -33,9 +34,22 @@ const (
 	DefaultBaseExecFee = 30
 )
 
+// Ledger is the interface to Blockchain required for Context functionality.
+type Ledger interface {
+	BlockHeight() uint32
+	CurrentBlockHash() util.Uint256
+	GetBaseExecFee() int64
+	GetBlock(hash util.Uint256) (*block.Block, error)
+	GetConfig() config.ProtocolConfiguration
+	GetHeaderHash(int) util.Uint256
+	GetStandByCommittee() keys.PublicKeys
+	GetStandByValidators() keys.PublicKeys
+	GetStoragePrice() int64
+}
+
 // Context represents context in which interops are executed.
 type Context struct {
-	Chain         blockchainer.Blockchainer
+	Chain         Ledger
 	Container     hash.Hashable
 	Network       uint32
 	Natives       []Contract
@@ -56,7 +70,7 @@ type Context struct {
 }
 
 // NewContext returns new interop context.
-func NewContext(trigger trigger.Type, bc blockchainer.Blockchainer, d dao.DAO,
+func NewContext(trigger trigger.Type, bc Ledger, d dao.DAO,
 	getContract func(dao.DAO, util.Uint160) (*state.Contract, error), natives []Contract,
 	block *block.Block, tx *transaction.Transaction, log *zap.Logger) *Context {
 	baseExecFee := int64(DefaultBaseExecFee)
diff --git a/pkg/core/native/ledger.go b/pkg/core/native/ledger.go
index 2d958d629..496ccc640 100644
--- a/pkg/core/native/ledger.go
+++ b/pkg/core/native/ledger.go
@@ -6,7 +6,6 @@ import (
 	"math/big"
 
 	"github.com/nspcc-dev/neo-go/pkg/core/block"
-	"github.com/nspcc-dev/neo-go/pkg/core/blockchainer"
 	"github.com/nspcc-dev/neo-go/pkg/core/dao"
 	"github.com/nspcc-dev/neo-go/pkg/core/interop"
 	"github.com/nspcc-dev/neo-go/pkg/core/native/nativenames"
@@ -145,17 +144,17 @@ func (l *Ledger) getTransactionFromBlock(ic *interop.Context, params []stackitem
 
 // isTraceableBlock defines whether we're able to give information about
 // the block with index specified.
-func isTraceableBlock(bc blockchainer.Blockchainer, index uint32) bool {
+func isTraceableBlock(bc interop.Ledger, index uint32) bool {
 	height := bc.BlockHeight()
 	MaxTraceableBlocks := bc.GetConfig().MaxTraceableBlocks
 	return index <= height && index+MaxTraceableBlocks > height
 }
 
 // getBlockHashFromItem converts given stackitem.Item to block hash using given
-// Blockchainer if needed. Interop functions accept both block numbers and
+// Ledger if needed. Interop functions accept both block numbers and
 // block hashes as parameters, thus this function is needed. It's supposed to
 // be called within VM context, so it panics if anything goes wrong.
-func getBlockHashFromItem(bc blockchainer.Blockchainer, item stackitem.Item) util.Uint256 {
+func getBlockHashFromItem(bc interop.Ledger, item stackitem.Item) util.Uint256 {
 	bigindex, err := item.TryInteger()
 	if err == nil && bigindex.IsUint64() {
 		index := bigindex.Uint64()
diff --git a/pkg/core/native/native_neo.go b/pkg/core/native/native_neo.go
index 163525080..50f61c989 100644
--- a/pkg/core/native/native_neo.go
+++ b/pkg/core/native/native_neo.go
@@ -10,7 +10,6 @@ import (
 	"strings"
 	"sync/atomic"
 
-	"github.com/nspcc-dev/neo-go/pkg/core/blockchainer"
 	"github.com/nspcc-dev/neo-go/pkg/core/dao"
 	"github.com/nspcc-dev/neo-go/pkg/core/interop"
 	"github.com/nspcc-dev/neo-go/pkg/core/interop/runtime"
@@ -244,7 +243,7 @@ func (n *NEO) Initialize(ic *interop.Context) error {
 // InitializeCache initializes all NEO cache with the proper values from storage.
 // Cache initialisation should be done apart from Initialize because Initialize is
 // called only when deploying native contracts.
-func (n *NEO) InitializeCache(bc blockchainer.Blockchainer, d dao.DAO) error {
+func (n *NEO) InitializeCache(bc interop.Ledger, d dao.DAO) error {
 	var committee = keysWithVotes{}
 	si := d.GetStorageItem(n.ID, prefixCommittee)
 	if err := committee.DecodeBytes(si); err != nil {
@@ -264,7 +263,7 @@ func (n *NEO) InitializeCache(bc blockchainer.Blockchainer, d dao.DAO) error {
 	return nil
 }
 
-func (n *NEO) updateCache(cvs keysWithVotes, bc blockchainer.Blockchainer) error {
+func (n *NEO) updateCache(cvs keysWithVotes, bc interop.Ledger) error {
 	n.committee.Store(cvs)
 
 	var committee = n.GetCommitteeMembers()
@@ -300,7 +299,7 @@ func (n *NEO) updateCommittee(ic *interop.Context) error {
 }
 
 // ShouldUpdateCommittee returns true if committee is updated at block h.
-func ShouldUpdateCommittee(h uint32, bc blockchainer.Blockchainer) bool {
+func ShouldUpdateCommittee(h uint32, bc interop.Ledger) bool {
 	cfg := bc.GetConfig()
 	r := len(cfg.StandbyCommittee)
 	return h%uint32(r) == 0
@@ -925,7 +924,7 @@ func (n *NEO) getAccountState(ic *interop.Context, args []stackitem.Item) stacki
 }
 
 // ComputeNextBlockValidators returns an actual list of current validators.
-func (n *NEO) ComputeNextBlockValidators(bc blockchainer.Blockchainer, d dao.DAO) (keys.PublicKeys, error) {
+func (n *NEO) ComputeNextBlockValidators(bc interop.Ledger, d dao.DAO) (keys.PublicKeys, error) {
 	if vals := n.validators.Load().(keys.PublicKeys); vals != nil {
 		return vals.Copy(), nil
 	}
@@ -982,7 +981,7 @@ func toKeysWithVotes(pubs keys.PublicKeys) keysWithVotes {
 }
 
 // computeCommitteeMembers returns public keys of nodes in committee.
-func (n *NEO) computeCommitteeMembers(bc blockchainer.Blockchainer, d dao.DAO) (keys.PublicKeys, keysWithVotes, error) {
+func (n *NEO) computeCommitteeMembers(bc interop.Ledger, d dao.DAO) (keys.PublicKeys, keysWithVotes, error) {
 	key := []byte{prefixVotersCount}
 	si := d.GetStorageItem(n.ID, key)
 	if si == nil {