func (b *BlockChain) GetTransaction(hash common.Uint256) (*types.Transaction, uint32, error) {
	return b.db.GetTransaction(hash)
}
Get transaction with hash.
package blockchain
import (
	"container/list"
	"errors"
	"fmt"
	"math/big"
	"sort"
	"sync"
	"time"
	"github.com/elastos/Elastos.ELA.SideChain/config"
	"github.com/elastos/Elastos.ELA.SideChain/events"
	"github.com/elastos/Elastos.ELA.SideChain/types"
	"github.com/elastos/Elastos.ELA.SideChain/interfaces"
	"github.com/elastos/Elastos.ELA/common"
)
const (
	maxOrphanBlocks  = 10000
	minMemoryNodes   = 20160
	maxBlockLocators = 500
	medianTimeBlocks = 11
)
var (
	oneLsh256 = new(big.Int).Lsh(big.NewInt(1), 256)
)
type Config struct {
	ChainStore     *ChainStore
	ChainParams    *config.Params
	Validator      *Validator
	CheckTxSanity  func(*types.Transaction) error
	CheckTxContext func(*types.Transaction) error
	GetTxFee       func(tx *types.Transaction, assetId common.Uint256) (common.Fixed64, error)
	GetHeader      func(hash common.Uint256) (interfaces.Header, error)
	GetBlock       func(hash common.Uint256) (*types.Block, error)
}
type BlockChain struct {
	cfg         *Config
	chainParams *config.Params
	db          *ChainStore
	GenesisHash common.Uint256
	minRetargetTimespan int64   
	maxRetargetTimespan int64   
	blocksPerRetarget   uint32  
	mutex          sync.RWMutex
	BestChain      *BlockNode
	Root           *BlockNode
	Index          map[common.Uint256]*BlockNode
	IndexLock      sync.RWMutex
	DepNodes       map[common.Uint256][]*BlockNode
	Orphans        map[common.Uint256]*OrphanBlock
	PrevOrphans    map[common.Uint256][]*OrphanBlock
	OldestOrphan   *OrphanBlock
	BlockCache     map[common.Uint256]*types.Block
	TimeSource     MedianTimeSource
	MedianTimePast time.Time
	OrphanLock     sync.RWMutex
}
func New(cfg *Config) (*BlockChain, error) {
	genesisHash, err := cfg.ChainStore.GetBlockHash(0)
	if err != nil {
		return nil, fmt.Errorf("query genesis block hash failed, error %s", err)
	}
	chainParams := cfg.ChainParams
	targetTimespan := int64(chainParams.TargetTimespan / time.Second)
	targetTimePerBlock := int64(chainParams.TargetTimePerBlock / time.Second)
	adjustmentFactor := chainParams.AdjustmentFactor
	chain := BlockChain{
		cfg:                 cfg,
		chainParams:         chainParams,
		db:                  cfg.ChainStore,
		GenesisHash:         genesisHash,
		minRetargetTimespan: targetTimespan / adjustmentFactor,
		maxRetargetTimespan: targetTimespan * adjustmentFactor,
		blocksPerRetarget:   uint32(targetTimespan / targetTimePerBlock),
		Root:                nil,
		BestChain:           nil,
		Index:               make(map[common.Uint256]*BlockNode),
		DepNodes:            make(map[common.Uint256][]*BlockNode),
		OldestOrphan:        nil,
		Orphans:             make(map[common.Uint256]*OrphanBlock),
		PrevOrphans:         make(map[common.Uint256][]*OrphanBlock),
		BlockCache:          make(map[common.Uint256]*types.Block),
		TimeSource:          NewMedianTime(),
	}
	endHeight := cfg.ChainStore.GetHeight()
	startHeight := uint32(0)
	if endHeight > minMemoryNodes {
		startHeight = endHeight - minMemoryNodes
	}
	for start := startHeight; start <= endHeight; start++ {
		hash, err := chain.db.GetBlockHash(start)
		if err != nil {
			return nil, err
		}
		var header interfaces.Header
		if cfg.GetHeader != nil {
			header, err = cfg.GetHeader(hash)
		} else {
			header, err = chain.db.GetHeader(hash)
		}
		if err != nil {
			return nil, err
		}
		node, err := chain.LoadBlockNode(header, &hash)
		if err != nil {
			return nil, err
		}
		chain.BestChain = node
	}
	return &chain, nil
}
func (b *BlockChain) GetBestHeight() uint32 {
	return b.db.GetHeight()
}
func (b *BlockChain) IsDoubleSpend(tx *types.Transaction) bool {
	return b.db.IsDoubleSpend(tx)
}
func (b *BlockChain) GetAsset(assetId common.Uint256) (*types.Asset, error) {
	asset, err := b.db.GetAsset(assetId)
	if err != nil {
		return nil, errors.New("[Ledger],GetAsset failed with assetId =" + assetId.String())
	}
	return asset, nil
}
func (b *BlockChain) GetBlockHash(height uint32) (common.Uint256, error) {
	return b.db.GetBlockHash(height)
}
func (b *BlockChain) GetBlockWithHeight(height uint32) (*types.Block, error) {
	temp, err := b.db.GetBlockHash(height)
	if err != nil {
		return nil, errors.New("[Ledger],GetBlockWithHeight failed with height=" + string(height))
	}
	var bk *types.Block
	if b.cfg.GetBlock != nil {
		bk, err = b.cfg.GetBlock(temp)
	} else {
		bk, err = b.db.GetBlock(temp)
	}
	if err != nil {
		return nil, errors.New("[Ledger],GetBlockWithHeight failed with hash=" + temp.String())
	}
	return bk, nil
}
func (b *BlockChain) GetBlockByHash(hash common.Uint256) (*types.Block, error) {
	var bk *types.Block
	var err error
	if b.cfg.GetBlock != nil {
		bk, err = b.cfg.GetBlock(hash)
	} else {
		bk, err = b.db.GetBlock(hash)
	}
	if err != nil {
		return nil, errors.New("[Ledger],GetBlockWithHeight failed with hash=" + hash.String())
	}
	return bk, nil
}
func (b *BlockChain) IsDuplicateTx(txId common.Uint256) bool {
	return b.db.IsDuplicateTx(txId)
}
func (b *BlockChain) IsDuplicateMainchainTx(txId common.Uint256) bool {
	return b.db.IsDuplicateMainchainTx(txId)
}