func NewDB(conf *config.Configurations, logger *logger.SugarLogger) (DB, error) {
	localConf := conf.LocalConfig
	if localConf.Server.Database.Name != "leveldb" {
		return nil, errors.New("only leveldb is supported as the state database")
	}
	ledgerDir := localConf.Server.Database.LedgerDirectory
	if err := createLedgerDir(ledgerDir); err != nil {
		return nil, err
	}
	levelDB, err := leveldb.Open(
		&leveldb.Config{
			DBRootDir: constructWorldStatePath(ledgerDir),
			Logger:    logger,
		},
	)
	if err != nil {
		return nil, errors.WithMessage(err, "error while creating the world state database")
	}
	blockStore, err := blockstore.Open(
		&blockstore.Config{
			StoreDir: constructBlockStorePath(ledgerDir),
			Logger:   logger,
		},
	)
	if err != nil {
		return nil, errors.WithMessage(err, "error while creating the block store")
	}
	provenanceStore, err := provenance.Open(
		&provenance.Config{
			StoreDir: constructProvenanceStorePath(ledgerDir),
			Logger:   logger,
		},
	)
	if err != nil {
		return nil, errors.WithMessage(err, "error while creating the block store")
	}
	stateTrieStore, err := mptrieStore.Open(
		&mptrieStore.Config{
			StoreDir: constructStateTrieStorePath(ledgerDir),
			Logger:   logger,
		},
	)
	if err != nil {
		return nil, errors.WithMessage(err, "error while creating the state trie store")
	}
	querier := identity.NewQuerier(levelDB)
	signer, err := crypto.NewSigner(&crypto.SignerOptions{KeyFilePath: localConf.Server.Identity.KeyPath})
	if err != nil {
		return nil, errors.Wrap(err, "can't load private key")
	}
	worldstateQueryProcessor := newWorldstateQueryProcessor(
		&worldstateQueryProcessorConfig{
			nodeID:          localConf.Server.Identity.ID,
			db:              levelDB,
			blockStore:      blockStore,
			identityQuerier: querier,
			logger:          logger,
		},
	)
	ledgerQueryProcessorConfig := &ledgerQueryProcessorConfig{
		db:              levelDB,
		blockStore:      blockStore,
		provenanceStore: provenanceStore,
		trieStore:       stateTrieStore,
		identityQuerier: querier,
		logger:          logger,
	}
	ledgerQueryProcessor := newLedgerQueryProcessor(ledgerQueryProcessorConfig)
	provenanceQueryProcessor := newProvenanceQueryProcessor(
		&provenanceQueryProcessorConfig{
			provenanceStore: provenanceStore,
			logger:          logger,
		},
	)
	txProcessor, err := newTransactionProcessor(
		&txProcessorConfig{
			config:          conf,
			db:              levelDB,
			blockStore:      blockStore,
			provenanceStore: provenanceStore,
			stateTrieStore:  stateTrieStore,
			logger:          logger,
		},
	)
	if err != nil {
		return nil, errors.WithMessage(err, "can't initiate tx processor")
	}
	return &db{
		nodeID:                   localConf.Server.Identity.ID,
		worldstateQueryProcessor: worldstateQueryProcessor,
		ledgerQueryProcessor:     ledgerQueryProcessor,
		provenanceQueryProcessor: provenanceQueryProcessor,
		txProcessor:              txProcessor,
		db:                       levelDB,
		blockStore:               blockStore,
		provenanceStore:          provenanceStore,
		stateTrieStore:           stateTrieStore,
		logger:                   logger,
		signer:                   signer,
	}, nil
}
NewDB creates a new database bcdb which handles both the queries and transactions.
package bcdb
import (
	"context"
	"crypto/x509"
	"encoding/json"
	"encoding/pem"
	"io/ioutil"
	"time"
	"github.com/hyperledger-labs/orion-server/config"
	"github.com/hyperledger-labs/orion-server/internal/blockstore"
	ierrors "github.com/hyperledger-labs/orion-server/internal/errors"
	"github.com/hyperledger-labs/orion-server/internal/fileops"
	"github.com/hyperledger-labs/orion-server/internal/identity"
	mptrieStore "github.com/hyperledger-labs/orion-server/internal/mptrie/store"
	"github.com/hyperledger-labs/orion-server/internal/provenance"
	"github.com/hyperledger-labs/orion-server/internal/worldstate"
	"github.com/hyperledger-labs/orion-server/internal/worldstate/leveldb"
	"github.com/hyperledger-labs/orion-server/pkg/crypto"
	"github.com/hyperledger-labs/orion-server/pkg/logger"
	"github.com/hyperledger-labs/orion-server/pkg/types"
	"github.com/pkg/errors"
)
type DB interface {
	LedgerHeight() (uint64, error)
	Height() (uint64, error)
	IsLeader() *ierrors.NotLeaderError
	DoesUserExist(userID string) (bool, error)
	GetCertificate(userID string) (*x509.Certificate, error)
	GetUser(querierUserID, targetUserID string) (*types.GetUserResponseEnvelope, error)
	GetConfig() (*types.GetConfigResponseEnvelope, error)
	GetNodeConfig(nodeID string) (*types.GetNodeConfigResponseEnvelope, error)
	GetDBStatus(dbName string) (*types.GetDBStatusResponseEnvelope, error)
	GetData(dbName, querierUserID, key string) (*types.GetDataResponseEnvelope, error)
	DataQuery(ctx context.Context, dbName, querierUserID string, query []byte) (*types.DataQueryResponseEnvelope, error)
	GetBlockHeader(userID string, blockNum uint64) (*types.GetBlockResponseEnvelope, error)
	GetTxProof(userID string, blockNum uint64, txIdx uint64) (*types.GetTxProofResponseEnvelope, error)
	GetDataProof(userID string, blockNum uint64, dbname string, key string, deleted bool) (*types.GetDataProofResponseEnvelope, error)
	GetLedgerPath(userID string, start, end uint64) (*types.GetLedgerPathResponseEnvelope, error)
	GetValues(dbName, key string) (*types.GetHistoricalDataResponseEnvelope, error)
	GetDeletedValues(dbname, key string) (*types.GetHistoricalDataResponseEnvelope, error)
	GetValueAt(dbName, key string, version *types.Version) (*types.GetHistoricalDataResponseEnvelope, error)
	GetMostRecentValueAtOrBelow(dbName, key string, version *types.Version) (*types.GetHistoricalDataResponseEnvelope, error)
	GetPreviousValues(dbname, key string, version *types.Version) (*types.GetHistoricalDataResponseEnvelope, error)
	GetNextValues(dbname, key string, version *types.Version) (*types.GetHistoricalDataResponseEnvelope, error)
	GetValuesReadByUser(userID string) (*types.GetDataProvenanceResponseEnvelope, error)
	GetValuesWrittenByUser(userID string) (*types.GetDataProvenanceResponseEnvelope, error)
	GetValuesDeletedByUser(userID string) (*types.GetDataProvenanceResponseEnvelope, error)
	GetReaders(dbName, key string) (*types.GetDataReadersResponseEnvelope, error)
	GetWriters(dbName, key string) (*types.GetDataWritersResponseEnvelope, error)
	GetTxIDsSubmittedByUser(userID string) (*types.GetTxIDsSubmittedByResponseEnvelope, error)
	GetTxReceipt(userId string, txID string) (*types.TxReceiptResponseEnvelope, error)
	SubmitTransaction(tx interface{}, timeout time.Duration) (*types.TxReceiptResponseEnvelope, error)
	IsDBExists(name string) bool
	Close() error
}
type db struct {
	nodeID                   string
	worldstateQueryProcessor *worldstateQueryProcessor
	ledgerQueryProcessor     *ledgerQueryProcessor
	provenanceQueryProcessor *provenanceQueryProcessor
	txProcessor              *transactionProcessor
	db                       worldstate.DB
	blockStore               *blockstore.Store
	provenanceStore          *provenance.Store
	stateTrieStore           *mptrieStore.Store
	signer                   crypto.Signer
	logger                   *logger.SugarLogger
}