func runBlockTest(homesteadBlock, daoForkBlock *big.Int, test *BlockTest) error {
	// import pre accounts & construct test genesis block & state root
	db, _ := ethdb.NewMemDatabase()
	if _, err := test.InsertPreState(db); err != nil {
		return fmt.Errorf("InsertPreState: %v", err)
	}

	core.WriteTd(db, test.Genesis.Hash(), test.Genesis.Difficulty())
	core.WriteBlock(db, test.Genesis)
	core.WriteCanonicalHash(db, test.Genesis.Hash(), test.Genesis.NumberU64())
	core.WriteHeadBlockHash(db, test.Genesis.Hash())
	evmux := new(event.TypeMux)
	config := &core.ChainConfig{HomesteadBlock: homesteadBlock, DAOForkBlock: daoForkBlock, DAOForkSupport: true}
	chain, err := core.NewBlockChain(db, config, ethash.NewShared(), evmux)
	if err != nil {
		return err
	}

	//vm.Debug = true
	validBlocks, err := test.TryBlocksInsert(chain)
	if err != nil {
		return err
	}

	lastblockhash := common.HexToHash(test.lastblockhash)
	cmlast := chain.LastBlockHash()
	if lastblockhash != cmlast {
		return fmt.Errorf("lastblockhash validation mismatch: want: %x, have: %x", lastblockhash, cmlast)
	}

	newDB, err := chain.State()
	if err != nil {
		return err
	}
	if err = test.ValidatePostState(newDB); err != nil {
		return fmt.Errorf("post state validation failed: %v", err)
	}

	return test.ValidateImportedHeaders(chain, validBlocks)
}
示例#2
0
func New(ctx *node.ServiceContext, config *Config) (*Expanse, error) {
	// Open the chain database and perform any upgrades needed
	chainDb, err := ctx.OpenDatabase("chaindata", config.DatabaseCache, config.DatabaseHandles)
	if err != nil {
		return nil, err
	}
	if db, ok := chainDb.(*ethdb.LDBDatabase); ok {
		db.Meter("exp/db/chaindata/")
	}
	if err := upgradeChainDatabase(chainDb); err != nil {
		return nil, err
	}
	if err := addMipmapBloomBins(chainDb); err != nil {
		return nil, err
	}

	dappDb, err := ctx.OpenDatabase("dapp", config.DatabaseCache, config.DatabaseHandles)
	if err != nil {
		return nil, err
	}
	if db, ok := dappDb.(*ethdb.LDBDatabase); ok {
		db.Meter("exp/db/dapp/")
	}
	glog.V(logger.Info).Infof("Protocol Versions: %v, Network Id: %v", ProtocolVersions, config.NetworkId)

	// Load up any custom genesis block if requested
	if len(config.Genesis) > 0 {
		block, err := core.WriteGenesisBlock(chainDb, strings.NewReader(config.Genesis))
		if err != nil {
			return nil, err
		}
		glog.V(logger.Info).Infof("Successfully wrote custom genesis block: %x", block.Hash())
	}

	// Load up a test setup if directly injected
	if config.TestGenesisState != nil {
		chainDb = config.TestGenesisState
	}
	if config.TestGenesisBlock != nil {
		core.WriteTd(chainDb, config.TestGenesisBlock.Hash(), config.TestGenesisBlock.Difficulty())
		core.WriteBlock(chainDb, config.TestGenesisBlock)
		core.WriteCanonicalHash(chainDb, config.TestGenesisBlock.Hash(), config.TestGenesisBlock.NumberU64())
		core.WriteHeadBlockHash(chainDb, config.TestGenesisBlock.Hash())
	}

	if !config.SkipBcVersionCheck {
		bcVersion := core.GetBlockChainVersion(chainDb)
		if bcVersion != config.BlockChainVersion && bcVersion != 0 {
			return nil, fmt.Errorf("Blockchain DB version mismatch (%d / %d). Run gexp upgradedb.\n", bcVersion, config.BlockChainVersion)
		}
		core.WriteBlockChainVersion(chainDb, config.BlockChainVersion)
	}
	glog.V(logger.Info).Infof("Blockchain DB Version: %d", config.BlockChainVersion)

	exp := &Expanse{
		shutdownChan:            make(chan bool),
		chainDb:                 chainDb,
		dappDb:                  dappDb,
		eventMux:                ctx.EventMux,
		accountManager:          config.AccountManager,
		etherbase:               config.Etherbase,
		netVersionId:            config.NetworkId,
		NatSpec:                 config.NatSpec,
		MinerThreads:            config.MinerThreads,
		SolcPath:                config.SolcPath,
		AutoDAG:                 config.AutoDAG,
		PowTest:                 config.PowTest,
		GpoMinGasPrice:          config.GpoMinGasPrice,
		GpoMaxGasPrice:          config.GpoMaxGasPrice,
		GpoFullBlockRatio:       config.GpoFullBlockRatio,
		GpobaseStepDown:         config.GpobaseStepDown,
		GpobaseStepUp:           config.GpobaseStepUp,
		GpobaseCorrectionFactor: config.GpobaseCorrectionFactor,
		httpclient:              httpclient.New(config.DocRoot),
	}
	switch {
	case config.PowTest:
		glog.V(logger.Info).Infof("ethash used in test mode")
		exp.pow, err = ethash.NewForTesting()
		if err != nil {
			return nil, err
		}
	case config.PowShared:
		glog.V(logger.Info).Infof("ethash used in shared mode")
		exp.pow = ethash.NewShared()

	default:
		exp.pow = ethash.New()
	}

	// load the genesis block or write a new one if no genesis
	// block is prenent in the database.
	genesis := core.GetBlock(chainDb, core.GetCanonicalHash(chainDb, 0))
	if genesis == nil {
		genesis, err = core.WriteDefaultGenesisBlock(chainDb)
		if err != nil {
			return nil, err
		}
		glog.V(logger.Info).Infoln("WARNING: Wrote default expanse genesis block")
	}

	if config.ChainConfig == nil {
		return nil, errors.New("missing chain config")
	}
	core.WriteChainConfig(chainDb, genesis.Hash(), config.ChainConfig)

	exp.chainConfig = config.ChainConfig
	exp.chainConfig.VmConfig = vm.Config{
		EnableJit: config.EnableJit,
		ForceJit:  config.ForceJit,
	}

	exp.blockchain, err = core.NewBlockChain(chainDb, exp.chainConfig, exp.pow, exp.EventMux())
	if err != nil {
		if err == core.ErrNoGenesis {
			return nil, fmt.Errorf(`No chain found. Please initialise a new chain using the "init" subcommand.`)
		}
		return nil, err
	}
	exp.gpo = NewGasPriceOracle(exp)

	newPool := core.NewTxPool(exp.chainConfig, exp.EventMux(), exp.blockchain.State, exp.blockchain.GasLimit)
	exp.txPool = newPool

	if exp.protocolManager, err = NewProtocolManager(exp.chainConfig, config.FastSync, config.NetworkId, exp.eventMux, exp.txPool, exp.pow, exp.blockchain, chainDb); err != nil {
		return nil, err
	}
	exp.miner = miner.New(exp, exp.chainConfig, exp.EventMux(), exp.pow)
	exp.miner.SetGasPrice(config.GasPrice)
	exp.miner.SetExtra(config.ExtraData)

	return exp, nil
}