Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix quaiclient tests #1174

Closed
3 changes: 2 additions & 1 deletion consensus/progpow/consensus.go
Original file line number Diff line number Diff line change
Expand Up @@ -423,7 +423,8 @@ func (progpow *Progpow) verifySeal(header *types.Header) (common.Hash, error) {
if progpow.fakeFail == header.Number().Uint64() {
return common.Hash{}, errInvalidPoW
}
return common.Hash{}, nil
//if hash is empty here, it fails because of div / 0 on poem.go: IntrinsicLogS()
return common.HexToHash("0xf5d8c9fb1a61e47c6dd4b5d0a1a0d6c0f7bce9cfae0e2a9d8a9c8d6d6f8f4f7"), nil
gameofpointers marked this conversation as resolved.
Show resolved Hide resolved
}
// If we're running a shared PoW, delegate verification to it
if progpow.shared != nil {
Expand Down
23 changes: 13 additions & 10 deletions core/chain_makers.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,11 +23,13 @@ import (
"github.com/dominant-strategies/go-quai/common"
"github.com/dominant-strategies/go-quai/consensus"
"github.com/dominant-strategies/go-quai/consensus/misc"
"github.com/dominant-strategies/go-quai/core/rawdb"
"github.com/dominant-strategies/go-quai/core/state"
"github.com/dominant-strategies/go-quai/core/types"
"github.com/dominant-strategies/go-quai/core/vm"
"github.com/dominant-strategies/go-quai/ethdb"
"github.com/dominant-strategies/go-quai/params"
"github.com/dominant-strategies/go-quai/trie"
)

// BlockGen creates blocks for testing.
Expand Down Expand Up @@ -215,7 +217,7 @@ func GenerateChain(config *params.ChainConfig, parent *types.Block, engine conse
chainreader := &fakeChainReader{config: config}
genblock := func(i int, parent *types.Block, statedb *state.StateDB) (*types.Block, types.Receipts) {
b := &BlockGen{i: i, chain: blocks, parent: parent, statedb: statedb, config: config, engine: engine}
b.header = makeHeader(chainreader, parent, statedb, b.engine)
b.header = makeHeader(chainreader, parent, statedb, b.engine, config.GenesisHash)

// Execute any user modifications to the block
if gen != nil {
Expand Down Expand Up @@ -243,38 +245,39 @@ func GenerateChain(config *params.ChainConfig, parent *types.Block, engine conse
panic(err)
}
block, receipt := genblock(i, parent, statedb)
rawdb.WriteBlock(db, block)
blocks[i] = block
receipts[i] = receipt
parent = block
}
return blocks, receipts
}

func makeHeader(chain consensus.ChainReader, parent *types.Block, state *state.StateDB, engine consensus.Engine) *types.Header {
func makeHeader(chain consensus.ChainReader, parent *types.Block, state *state.StateDB, engine consensus.Engine, genesisHash common.Hash) *types.Header {
var time uint64
if parent.Time() == 0 {
time = 10
} else {
time = parent.Time() + 10 // block time is fixed at 10 seconds
}

// Temporary header values just to calc difficulty
diffheader := types.EmptyHeader()
diffheader.SetDifficulty(parent.Difficulty())
diffheader.SetNumber(parent.Number())
diffheader.SetTime(time - 10)
diffheader.SetUncleHash(parent.UncleHash())

// Make new header
header := types.EmptyHeader()
header.SetRoot(state.IntermediateRoot(true))
header.SetParentHash(parent.Hash())
header.SetCoinbase(parent.Coinbase())
header.SetDifficulty(engine.CalcDifficulty(chain, diffheader))
header.SetDifficulty(engine.CalcDifficulty(chain, parent.Header()))
header.SetGasLimit(parent.GasLimit())
header.SetNumber(new(big.Int).Add(parent.Number(), common.Big1))
header.SetTime(time)
header.SetBaseFee(misc.CalcBaseFee(chain.Config(), parent.Header()))

//new array receive its first value as genesisHash
manifest := types.BlockManifest{genesisHash}
header.SetManifestHash(types.DeriveSha(manifest, trie.NewStackTrie(nil)))

header.SetLocation(common.Location{0,0})

return header
}

Expand Down
30 changes: 29 additions & 1 deletion core/core.go
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,35 @@ func NewCore(db ethdb.Database, config *Config, isLocalBlock func(block *types.H
// Initialize the sync target to current header parent entropy
c.syncTarget = c.CurrentHeader()

c.AppendQueueProcessCache()

return c, nil
}

// Used on unit testing
func NewFakeCore(db ethdb.Database, config *Config, isLocalBlock func(block *types.Header) bool, txConfig *TxPoolConfig, txLookupLimit *uint64, chainConfig *params.ChainConfig, slicesRunning []common.Location, domClientUrl string, subClientUrls []string, engine consensus.Engine, cacheConfig *CacheConfig, vmConfig vm.Config, genesis *Genesis) (*Core, error) {
slice, err := NewFakeSlice(db, config, txConfig, txLookupLimit, isLocalBlock, chainConfig, slicesRunning, domClientUrl, subClientUrls, engine, cacheConfig, vmConfig, genesis)
if err != nil {
return nil, err
}

c := &Core{
sl: slice,
engine: engine,
quit: make(chan struct{}),
procCounter: 0,
normalListBackoff: 1,
}

// Initialize the sync target to current header parent entropy
c.syncTarget = c.CurrentHeader()

c.AppendQueueProcessCache()

return c, nil
}

func (c *Core) AppendQueueProcessCache() {
appendQueue, _ := lru.New(c_maxAppendQueue)
c.appendQueue = appendQueue

Expand All @@ -107,7 +136,6 @@ func NewCore(db ethdb.Database, config *Config, isLocalBlock func(block *types.H
go c.updateAppendQueue()
go c.startStatsTimer()
go c.checkSyncTarget()
return c, nil
}

// InsertChain attempts to append a list of blocks to the slice, optionally
Expand Down
56 changes: 55 additions & 1 deletion core/slice.go
Original file line number Diff line number Diff line change
Expand Up @@ -125,7 +125,61 @@ func NewSlice(db ethdb.Database, config *Config, txConfig *TxPoolConfig, txLooku
if nodeCtx != common.PRIME_CTX {
go func() {
sl.domClient = makeDomClient(domClientUrl)
}()
}()
}

if err := sl.init(genesis); err != nil {
return nil, err
}

sl.CheckForBadHashAndRecover()

if nodeCtx == common.ZONE_CTX && sl.ProcessingState() {
go sl.asyncPendingHeaderLoop()
}

return sl, nil
}

func NewFakeSlice(db ethdb.Database, config *Config, txConfig *TxPoolConfig, txLookupLimit *uint64, isLocalBlock func(block *types.Header) bool, chainConfig *params.ChainConfig, slicesRunning []common.Location, domClientUrl string, subClientUrls []string, engine consensus.Engine, cacheConfig *CacheConfig, vmConfig vm.Config, genesis *Genesis) (*Slice, error) {
nodeCtx := common.NodeLocation.Context()
sl := &Slice{
config: chainConfig,
engine: engine,
sliceDb: db,
quit: make(chan struct{}),
badHashesCache: make(map[common.Hash]bool),
}

var err error
sl.hc, err = NewHeaderChain(db, engine, sl.GetPEtxRollupAfterRetryThreshold, sl.GetPEtxAfterRetryThreshold, chainConfig, cacheConfig, txLookupLimit, vmConfig, slicesRunning)
if err != nil {
return nil, err
}

sl.validator = NewBlockValidator(chainConfig, sl.hc, engine)

// tx pool is only used in zone
if nodeCtx == common.ZONE_CTX && sl.ProcessingState() {
sl.txPool = NewTxPool(*txConfig, chainConfig, sl.hc)
sl.hc.pool = sl.txPool
}

sl.miner = New(sl.hc, sl.txPool, config, db, chainConfig, engine, isLocalBlock, sl.ProcessingState())

sl.phCache, _ = lru.New(c_phCacheSize)

// only set the subClients if the chain is not Zone
sl.subClients = make([]*quaiclient.Client, 3)
if nodeCtx != common.ZONE_CTX {
sl.subClients = makeSubClients(subClientUrls)
}

// only set domClient if the chain is not Prime.
if nodeCtx != common.PRIME_CTX {
go func () {
sl.domClient = quaiclient.NewClient(&quaiclient.TestRpcClient{})
}()
}

if err := sl.init(genesis); err != nil {
Expand Down
162 changes: 162 additions & 0 deletions eth/backend.go
Original file line number Diff line number Diff line change
Expand Up @@ -184,6 +184,168 @@ func New(stack *node.Node, config *ethconfig.Config) (*Quai, error) {
}

eth.core, err = core.NewCore(chainDb, &config.Miner, eth.isLocalBlock, &config.TxPool, &config.TxLookupLimit, chainConfig, eth.config.SlicesRunning, eth.config.DomUrl, eth.config.SubUrls, eth.engine, cacheConfig, vmConfig, config.Genesis)

if err != nil {
return nil, err
}

// Only index bloom if processing state
if eth.core.ProcessingState() && nodeCtx == common.ZONE_CTX {
eth.bloomIndexer = core.NewBloomIndexer(chainDb, params.BloomBitsBlocks, params.BloomConfirms)
eth.bloomIndexer.Start(eth.Core().Slice().HeaderChain())
}

// Permit the downloader to use the trie cache allowance during fast sync
cacheLimit := cacheConfig.TrieCleanLimit + cacheConfig.TrieDirtyLimit + cacheConfig.SnapshotLimit
if eth.handler, err = newHandler(&handlerConfig{
gameofpointers marked this conversation as resolved.
Show resolved Hide resolved
Database: chainDb,
Core: eth.core,
TxPool: eth.core.TxPool(),
Network: config.NetworkId,
Sync: config.SyncMode,
BloomCache: uint64(cacheLimit),
EventMux: eth.eventMux,
Whitelist: config.Whitelist,
SlicesRunning: config.SlicesRunning,
}); err != nil {
return nil, err
}

eth.APIBackend = &QuaiAPIBackend{stack.Config().ExtRPCEnabled(), eth, nil}
// Gasprice oracle is only initiated in zone chains
if nodeCtx == common.ZONE_CTX && eth.core.ProcessingState() {
gpoParams := config.GPO
if gpoParams.Default == nil {
gpoParams.Default = config.Miner.GasPrice
}
eth.APIBackend.gpo = gasprice.NewOracle(eth.APIBackend, gpoParams)
}

// Setup DNS discovery iterators.
dnsclient := dnsdisc.NewClient(dnsdisc.Config{})
gameofpointers marked this conversation as resolved.
Show resolved Hide resolved
eth.ethDialCandidates, err = dnsclient.NewIterator(eth.config.EthDiscoveryURLs...)
if err != nil {
return nil, err
}

// Start the RPC service
eth.netRPCService = quaiapi.NewPublicNetAPI(eth.p2pServer, config.NetworkId)

// Register the backend on the node
stack.RegisterAPIs(eth.APIs())
stack.RegisterProtocols(eth.Protocols())
stack.RegisterLifecycle(eth)
// Check for unclean shutdown
if uncleanShutdowns, discards, err := rawdb.PushUncleanShutdownMarker(chainDb); err != nil {
log.Error("Could not update unclean-shutdown-marker list", "error", err)
} else {
if discards > 0 {
log.Warn("Old unclean shutdowns found", "count", discards)
}
for _, tstamp := range uncleanShutdowns {
t := time.Unix(int64(tstamp), 0)
log.Warn("Unclean shutdown detected", "booted", t,
"age", common.PrettyAge(t))
}
}
return eth, nil
}

// New creates a new Fake Quai object to be used on tests (including the
// initialisation of the common Quai object)
func NewFake(stack *node.Node, config *ethconfig.Config, chainDb ethdb.Database) (*Quai, error) {
nodeCtx := common.NodeLocation.Context()
// Ensure configuration values are compatible and sane
if !config.SyncMode.IsValid() {
return nil, fmt.Errorf("invalid sync mode %d", config.SyncMode)
}
if config.Miner.GasPrice == nil || config.Miner.GasPrice.Cmp(common.Big0) <= 0 {
log.Warn("Sanitizing invalid miner gas price", "provided", config.Miner.GasPrice, "updated", ethconfig.Defaults.Miner.GasPrice)
config.Miner.GasPrice = new(big.Int).Set(ethconfig.Defaults.Miner.GasPrice)
}
if config.NoPruning && config.TrieDirtyCache > 0 {
if config.SnapshotCache > 0 {
config.TrieCleanCache += config.TrieDirtyCache * 3 / 5
config.SnapshotCache += config.TrieDirtyCache * 2 / 5
} else {
config.TrieCleanCache += config.TrieDirtyCache
}
config.TrieDirtyCache = 0
}
log.Info("Allocated trie memory caches", "clean", common.StorageSize(config.TrieCleanCache)*1024*1024, "dirty", common.StorageSize(config.TrieDirtyCache)*1024*1024)

// Assemble the Quai object
chainConfig, _, genesisErr := core.SetupGenesisBlockWithOverride(chainDb, config.Genesis)
if genesisErr != nil {
return nil, genesisErr
}

if err := pruner.RecoverPruning(stack.ResolvePath(""), chainDb, stack.ResolvePath(config.TrieCleanCacheJournal)); err != nil {
log.Error("Failed to recover state", "error", err)
}
eth := &Quai{
config: config,
chainDb: chainDb,
eventMux: stack.EventMux(),
closeBloomHandler: make(chan struct{}),
networkID: config.NetworkId,
gasPrice: config.Miner.GasPrice,
etherbase: config.Miner.Etherbase,
bloomRequests: make(chan chan *bloombits.Retrieval),
p2pServer: stack.Server(),
}

if config.ConsensusEngine == "blake3" {
blake3Config := config.Blake3Pow
blake3Config.NotifyFull = config.Miner.NotifyFull
eth.engine = ethconfig.CreateBlake3ConsensusEngine(stack, chainConfig, &blake3Config, config.Miner.Notify, config.Miner.Noverify, chainDb)
} else {
// Transfer mining-related config to the progpow config.
progpowConfig := config.Progpow
progpowConfig.NotifyFull = config.Miner.NotifyFull
eth.engine = ethconfig.CreateProgpowConsensusEngine(stack, chainConfig, &progpowConfig, config.Miner.Notify, config.Miner.Noverify, chainDb)
}
log.Info("Initialised chain configuration", "config", chainConfig)

bcVersion := rawdb.ReadDatabaseVersion(chainDb)
var dbVer = "<nil>"
if bcVersion != nil {
dbVer = fmt.Sprintf("%d", *bcVersion)
}
log.Info("Initialising Quai protocol", "network", config.NetworkId, "dbversion", dbVer)

if !config.SkipBcVersionCheck {
if bcVersion != nil && *bcVersion > core.BlockChainVersion {
return nil, fmt.Errorf("database version is v%d, Quai %s only supports v%d", *bcVersion, params.Version.Full(), core.BlockChainVersion)
} else if bcVersion == nil || *bcVersion < core.BlockChainVersion {
if bcVersion != nil { // only print warning on upgrade, not on init
log.Warn("Upgrade blockchain database version", "from", dbVer, "to", core.BlockChainVersion)
}
rawdb.WriteDatabaseVersion(chainDb, core.BlockChainVersion)
}
}
var (
vmConfig = vm.Config{
EnablePreimageRecording: config.EnablePreimageRecording,
}
cacheConfig = &core.CacheConfig{
TrieCleanLimit: config.TrieCleanCache,
TrieCleanJournal: stack.ResolvePath(config.TrieCleanCacheJournal),
TrieCleanRejournal: config.TrieCleanCacheRejournal,
TrieCleanNoPrefetch: config.NoPrefetch,
TrieDirtyLimit: config.TrieDirtyCache,
TrieTimeLimit: config.TrieTimeout,
SnapshotLimit: config.SnapshotCache,
Preimages: config.Preimages,
}
)

if config.TxPool.Journal != "" {
config.TxPool.Journal = stack.ResolvePath(config.TxPool.Journal)
}

var err error
eth.core, err = core.NewFakeCore(chainDb, &config.Miner, eth.isLocalBlock, &config.TxPool, &config.TxLookupLimit, chainConfig, eth.config.SlicesRunning, eth.config.DomUrl, eth.config.SubUrls, eth.engine, cacheConfig, vmConfig, config.Genesis)
if err != nil {
return nil, err
}
Expand Down
Loading
Loading