func (met *Metropolis) Lock() {
	met.mtx.Lock()
}
Lock locks Metropolis universally
package node
import (
	"bytes"
	"encoding/binary"
	"encoding/gob"
	"encoding/json"
	"fmt"
	"math/big"
	"path"
	"strconv"
	"sync"
	"time"
	"github.com/pkg/errors"
	"github.com/spf13/viper"
	"github.com/tendermint/tmlibs/db"
	"go.uber.org/zap"
	ac "github.com/Baptist-Publication/angine/config"
	pbtypes "github.com/Baptist-Publication/angine/protos/types"
	agtypes "github.com/Baptist-Publication/angine/types"
	cmn "github.com/Baptist-Publication/chorus-module/lib/go-common"
	"github.com/Baptist-Publication/chorus-module/lib/go-crypto"
	"github.com/Baptist-Publication/chorus-module/lib/go-merkle"
	"github.com/Baptist-Publication/chorus-module/xlib"
	acfg "github.com/Baptist-Publication/chorus/src/chain/config"
	"github.com/Baptist-Publication/chorus/src/chain/log"
)
const (
	BASE_APP_NAME = "metropolis"
	StartRedeemHeight = 15000
)
type (
	AppName string
	ChainID string
	MetropolisState struct {
		OrgStateHash   []byte
		OrgHeights     []agtypes.INT
		EventStateHash []byte
		AccStateHash   []byte
		PowerStateHash []byte
	}
	Metropolis struct {
		agtypes.BaseApplication
		mtx  sync.Mutex
		node *Node
		core Core
		config      *viper.Viper
		angineHooks agtypes.Hooks
		logger      *zap.Logger
		state *MetropolisState
		OrgStateDB db.DB
		OrgState *OrgState
		OrgApps  map[ChainID]AppName
		Orgs map[ChainID]*OrgNode
		PendingOrgTxs map[string]*OrgTx
		EventStateDB   db.DB
		EventState     *EventState
		EventWarehouse *EventWarehouse
		EventCodeBase  db.DB
		PendingEventRequestTxs map[string]*EventRequestTx
		accStateDB db.DB
		accState   *AccState
		powerStateDB db.DB
		powerState   *PowerState
		FeeAccum *big.Int
	}
	LastBlockInfo struct {
		Height agtypes.INT `msgpack:"height"`
		Hash []byte `msgpack:"hash"`
	}
)
var (
	ErrUnknownTx = fmt.Errorf("please give me something that I actually know about")
	Big0 = new(big.Int).SetUint64(0)
)
func NewLastBlockInfo() *LastBlockInfo {
	return &LastBlockInfo{
		Height: 0,
		Hash:   make([]byte, 0),
	}
}
func NewMetropolis(logger *zap.Logger, conf *viper.Viper) *Metropolis {
	datadir := conf.GetString("db_dir")
	met := Metropolis{
		config: conf,
		logger: logger,
		state: &MetropolisState{
			OrgHeights:     make([]agtypes.INT, 0),
			OrgStateHash:   make([]byte, 0),
			EventStateHash: make([]byte, 0),
			AccStateHash:   make([]byte, 0),
			PowerStateHash: make([]byte, 0),
		},
		OrgApps: make(map[ChainID]AppName),
		Orgs:    make(map[ChainID]*OrgNode),
		PendingOrgTxs:          make(map[string]*OrgTx),
		PendingEventRequestTxs: make(map[string]*EventRequestTx),
	}
	var err error
	if err = met.BaseApplication.InitBaseApplication(BASE_APP_NAME, datadir); err != nil {
		cmn.PanicCrisis(err)
	}
	if met.OrgStateDB, err = db.NewGoLevelDB("orgStatus", datadir); err != nil {
		cmn.PanicCrisis(err)
	}
	met.OrgState = NewOrgState(met.OrgStateDB)
	if met.EventStateDB, err = db.NewGoLevelDB("eventstate", datadir); err != nil {
		cmn.PanicCrisis(err)
	}
	met.EventState = NewEventState(met.EventStateDB)
	ewhDB, err := db.NewGoLevelDB("eventwarehouse", datadir)
	if err != nil {
		cmn.PanicCrisis(err)
	}
	met.EventWarehouse = NewEventWarehouse(ewhDB)
	met.EventCodeBase, err = db.NewGoLevelDB("eventcodebase", datadir)
	if err != nil {
		cmn.PanicCrisis(err)
	}
	if met.accStateDB, err = db.NewGoLevelDB("accountstate", datadir); err != nil {
		cmn.PanicCrisis(err)
	}
	met.accState = NewAccState(met.accStateDB)
	if met.powerStateDB, err = db.NewGoLevelDB("powerstate", datadir); err != nil {
		cmn.PanicCrisis(err)
	}
	met.powerState = NewPowerState(met.powerStateDB)
	met.angineHooks = agtypes.Hooks{
		OnExecute: agtypes.NewHook(met.OnExecute),
		OnCommit:  agtypes.NewHook(met.OnCommit),
	}
	return &met
}
func (met *Metropolis) Hash() []byte {
	return met.state.Hash()
}