Skip to content
This repository has been archived by the owner on Mar 8, 2024. It is now read-only.

Commit

Permalink
fix quaiclient tests build errors and create a test chain
Browse files Browse the repository at this point in the history
  • Loading branch information
didaunesp committed Feb 19, 2024
1 parent bbd0da3 commit b2b45ee
Show file tree
Hide file tree
Showing 10 changed files with 448 additions and 229 deletions.
3 changes: 2 additions & 1 deletion consensus/progpow/consensus.go
Original file line number Diff line number Diff line change
Expand Up @@ -428,7 +428,8 @@ func (progpow *Progpow) verifySeal(header *types.Header) (common.Hash, error) {
if progpow.fakeFail == header.NumberU64(nodeCtx) {
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
}
// If we're running a shared PoW, delegate verification to it
if progpow.shared != nil {
Expand Down
6 changes: 4 additions & 2 deletions consensus/progpow/progpow.go
Original file line number Diff line number Diff line change
Expand Up @@ -219,11 +219,13 @@ func NewTester(notify []string, noverify bool) *Progpow {
// NewFaker creates a progpow consensus engine with a fake PoW scheme that accepts
// all blocks' seal as valid, though they still have to conform to the Quai
// consensus rules.
func NewFaker() *Progpow {
func NewFaker(logger *log.Logger, nodeLocation common.Location) *Progpow {
return &Progpow{
config: Config{
PowMode: ModeFake,
PowMode: ModeFake,
NodeLocation: nodeLocation,
},
logger: logger,
}
}

Expand Down
22 changes: 13 additions & 9 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,6 +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.subManifest = types.BlockManifest{parent.Hash()}
b.header = makeHeader(chainreader, parent, statedb, b.engine)

// Execute any user modifications to the block
Expand Down Expand Up @@ -243,6 +246,7 @@ func GenerateChain(config *params.ChainConfig, parent *types.Block, engine conse
panic(err)
}
block, receipt := genblock(i, parent, statedb)
rawdb.WriteBlock(db, block, config.Location.Context())
blocks[i] = block
receipts[i] = receipt
parent = block
Expand All @@ -257,25 +261,25 @@ func makeHeader(chain consensus.ChainReader, parent *types.Block, state *state.S
} else {
time = parent.Time() + 10 // block time is fixed at 10 seconds
}
nodeCtx := chain.Config().Location.Context()

// Temporary header values just to calc difficulty
diffheader := types.EmptyHeader()
diffheader.SetDifficulty(parent.Difficulty(nodeCtx))
diffheader.SetNumber(parent.Number(nodeCtx), nodeCtx)
diffheader.SetTime(time - 10)
diffheader.SetUncleHash(parent.UncleHash())
nodeLoc := chain.Config().Location
nodeCtx := nodeLoc.Context()

// Make new header
header := types.EmptyHeader()
header.SetRoot(state.IntermediateRoot(true))
header.SetParentHash(parent.Hash(), nodeCtx)
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(nodeCtx), common.Big1), nodeCtx)
header.SetTime(time)
header.SetBaseFee(misc.CalcBaseFee(chain.Config(), parent.Header()))

header.SetLocation(nodeLoc)

manifest := types.BlockManifest{parent.Hash()}
header.SetManifestHash(types.DeriveSha(manifest, trie.NewStackTrie(nil)), nodeCtx)

return header
}

Expand Down
25 changes: 23 additions & 2 deletions core/core.go
Original file line number Diff line number Diff line change
Expand Up @@ -81,12 +81,18 @@ type Core struct {
logger *log.Logger
}

type NewCoreFunction func(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, logger *log.Logger) (*Core, error)

func NewCore(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, logger *log.Logger) (*Core, error) {
slice, err := NewSlice(db, config, txConfig, txLookupLimit, isLocalBlock, chainConfig, slicesRunning, domClientUrl, subClientUrls, engine, cacheConfig, vmConfig, genesis, logger)
if err != nil {
return nil, err
}

return newCommonCore(slice, engine, logger)
}

func newCommonCore(slice *Slice, engine consensus.Engine, logger *log.Logger) (*Core, error) {
c := &Core{
sl: slice,
engine: engine,
Expand All @@ -99,6 +105,23 @@ 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, logger *log.Logger) (*Core, error) {
slice, err := NewFakeSlice(db, config, txConfig, txLookupLimit, isLocalBlock, chainConfig, slicesRunning, domClientUrl, subClientUrls, engine, cacheConfig, vmConfig, genesis, logger)

if err != nil {
return nil, err
}

return newCommonCore(slice, engine, logger)
}

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

Expand All @@ -111,8 +134,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
42 changes: 35 additions & 7 deletions core/slice.go
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,23 @@ type Slice struct {

func NewSlice(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, logger *log.Logger) (*Slice, error) {
nodeCtx := chainConfig.Location.Context()
sl, err := newSliceCommon(db, config, txConfig, txLookupLimit, isLocalBlock, chainConfig, slicesRunning, domClientUrl, subClientUrls, engine, cacheConfig, vmConfig, genesis, nodeCtx, logger)

if err != nil {
return nil, err
}

// only set domClient if the chain is not Prime.
if nodeCtx != common.PRIME_CTX {
go func() {
sl.domClient = makeDomClient(domClientUrl, logger)
}()
}

return sl, nil
}

func newSliceCommon(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, nodeCtx int, logger *log.Logger) (*Slice, error) {
sl := &Slice{
config: chainConfig,
engine: engine,
Expand Down Expand Up @@ -126,13 +143,6 @@ func NewSlice(db ethdb.Database, config *Config, txConfig *TxPoolConfig, txLooku
}()
}

// only set domClient if the chain is not Prime.
if nodeCtx != common.PRIME_CTX {
go func() {
sl.domClient = makeDomClient(domClientUrl, sl.logger)
}()
}

if err := sl.init(genesis); err != nil {
return nil, err
}
Expand All @@ -146,6 +156,24 @@ func NewSlice(db ethdb.Database, config *Config, txConfig *TxPoolConfig, txLooku
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, logger *log.Logger) (*Slice, error) {
nodeCtx := chainConfig.Location.Context()
sl, err := newSliceCommon(db, config, txConfig, txLookupLimit, isLocalBlock, chainConfig, slicesRunning, domClientUrl, subClientUrls, engine, cacheConfig, vmConfig, genesis, nodeCtx, logger)

if err != nil {
return nil, err
}

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

return sl, nil
}

// Append takes a proposed header and constructs a local block and attempts to hierarchically append it to the block graph.
// If this is called from a dominant context a domTerminus must be provided else a common.Hash{} should be used and domOrigin should be set to true.
// Return of this function is the Etxs generated in the Zone Block, subReorg bool that tells dom if should be mined on, setHead bool that determines if we should set the block as the current head and the error
Expand Down
59 changes: 59 additions & 0 deletions core/types/block.go
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,65 @@ type Header struct {
PowDigest atomic.Value
}

func (h1 *Header) Compare(h2 *Header) error{
if h1 == nil || h2 == nil {
if h1 == h2{
return nil
}
return fmt.Errorf("Headers are not equal expected %v, got %v", h1, h2)
}

fields := map[string][]interface{}{
"parentHash": {h1.parentHash, h2.parentHash},
"uncleHash": {h1.uncleHash, h2.uncleHash},
"coinbase": {h1.coinbase, h2.coinbase},
"root": {h1.root, h2.root},
"txHash": {h1.txHash, h2.txHash},
"etxHash": {h1.etxHash, h2.etxHash},
"etxRollupHash": {h1.etxRollupHash, h2.etxRollupHash},
"manifestHash": {h1.manifestHash, h2.manifestHash},
"receiptHash": {h1.receiptHash, h2.receiptHash},
"difficulty": {h1.difficulty, h2.difficulty},
"number": {h1.number, h2.number},
"gasLimit": {h1.gasLimit, h2.gasLimit},
"gasUsed": {h1.gasUsed, h2.gasUsed},
"baseFee": {h1.baseFee, h2.baseFee},
"location": {h1.location, h2.location},
"time": {h1.time, h2.time},
"extra": {h1.extra, h2.extra},
"mixHash": {h1.mixHash, h2.mixHash},
"nonce": {h1.nonce, h2.nonce},
"hash": {h1.hash, h2.hash},
"sealHash": {h1.sealHash, h2.sealHash},
"PowHash": {h1.PowHash, h2.PowHash},
"PowDigest": {h1.PowDigest, h2.PowDigest},
}

for fieldName, values := range fields {
if !reflect.DeepEqual(values[0], values[1]) {
return fmt.Errorf("Field %s is not equal expected %v, got %v", fieldName, values[0], values[1])
}
}

if len(h1.parentEntropy) != len(h2.parentEntropy) {
return fmt.Errorf("Field parentEntropy is not equal expected %v, got %v", h1.parentEntropy, h2.parentEntropy)
}
for i := range h1.parentEntropy {
if h1.parentEntropy[i].Cmp(h2.parentEntropy[i]) != 0 {
return fmt.Errorf("Field parentEntropy at index %d is not equal expected %v, got %v", i, h1.parentEntropy[i], h2.parentEntropy[i])
}
}
if len(h1.parentDeltaS) != len(h2.parentDeltaS) {
return fmt.Errorf("Field parentEntropy is not equal expected %v, got %v", h1.parentEntropy, h2.parentEntropy)
}
for i := range h1.parentDeltaS {
if h1.parentEntropy[i].Cmp(h2.parentDeltaS[i]) != 0 {
return fmt.Errorf("Field parentDeltaS at index %d is not equal expected %v, got %v", i, h1.parentDeltaS[i], h2.parentDeltaS[i])
}
}
return nil
}

// field type overrides for gencodec
type headerMarshaling struct {
Difficulty *hexutil.Big
Expand Down
68 changes: 49 additions & 19 deletions quai/backend.go
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,33 @@ type Quai struct {
// New creates a new Quai object (including the
// initialisation of the common Quai object)
func New(stack *node.Node, p2p NetworkingAPI, config *quaiconfig.Config, nodeCtx int, logger *log.Logger) (*Quai, error) {
chainDb, err := stack.OpenDatabaseWithFreezer("chaindata", config.DatabaseCache, config.DatabaseHandles, config.DatabaseFreezer, "eth/db/chaindata/", false)

if err != nil {
return nil, err
}

quai, err := newCommon(stack, p2p, config, nodeCtx, logger, chainDb, core.NewCore)

// Set the p2p Networking API
quai.p2p = p2p
// Subscribe to the Blocks subscription
quai.p2p.Subscribe(config.NodeLocation, &types.Block{})
quai.p2p.Subscribe(config.NodeLocation, common.Hash{})
quai.p2p.Subscribe(config.NodeLocation, &types.Transaction{})

quai.handler = newHandler(quai.p2p, quai.core, config.NodeLocation)
// Start the handler
quai.handler.Start()

if err != nil {
return nil, err
}

return quai, nil
}

func newCommon(stack *node.Node, p2p NetworkingAPI, config *quaiconfig.Config, nodeCtx int, logger *log.Logger, chainDb ethdb.Database, coreFunction core.NewCoreFunction) (*Quai, error) {
// Ensure configuration values are compatible and sane
if config.Miner.GasPrice == nil || config.Miner.GasPrice.Cmp(common.Big0) <= 0 {
logger.WithFields(log.Fields{
Expand All @@ -104,10 +131,6 @@ func New(stack *node.Node, p2p NetworkingAPI, config *quaiconfig.Config, nodeCtx
}).Info("Allocated trie memory caches")

// Assemble the Quai object
chainDb, err := stack.OpenDatabaseWithFreezer("chaindata", config.DatabaseCache, config.DatabaseHandles, config.DatabaseFreezer, "eth/db/chaindata/", false)
if err != nil {
return nil, err
}
chainConfig, _, genesisErr := core.SetupGenesisBlockWithOverride(chainDb, config.Genesis, config.NodeLocation, logger)
if genesisErr != nil {
return nil, genesisErr
Expand Down Expand Up @@ -186,6 +209,11 @@ func New(stack *node.Node, p2p NetworkingAPI, config *quaiconfig.Config, nodeCtx
rawdb.WriteDatabaseVersion(chainDb, core.BlockChainVersion)
}
}

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

var (
vmConfig = vm.Config{
EnablePreimageRecording: config.EnablePreimageRecording,
Expand All @@ -202,12 +230,10 @@ func New(stack *node.Node, p2p NetworkingAPI, config *quaiconfig.Config, nodeCtx
}
)

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

logger.WithField("url", quai.config.DomUrl).Info("Dom client")
quai.core, err = core.NewCore(chainDb, &config.Miner, quai.isLocalBlock, &config.TxPool, &config.TxLookupLimit, chainConfig, quai.config.SlicesRunning, quai.config.DomUrl, quai.config.SubUrls, quai.engine, cacheConfig, vmConfig, config.Genesis, logger)
quai.core, err = coreFunction(chainDb, &config.Miner, quai.isLocalBlock, &config.TxPool, &config.TxLookupLimit, chainConfig, quai.config.SlicesRunning, quai.config.DomUrl, quai.config.SubUrls, quai.engine, cacheConfig, vmConfig, config.Genesis, logger)
if err != nil {
return nil, err
}
Expand All @@ -218,17 +244,6 @@ func New(stack *node.Node, p2p NetworkingAPI, config *quaiconfig.Config, nodeCtx
quai.bloomIndexer.Start(quai.Core().Slice().HeaderChain())
}

// Set the p2p Networking API
quai.p2p = p2p
// Subscribe to the Blocks subscription
quai.p2p.Subscribe(config.NodeLocation, &types.Block{})
quai.p2p.Subscribe(config.NodeLocation, common.Hash{})
quai.p2p.Subscribe(config.NodeLocation, &types.Transaction{})

quai.handler = newHandler(quai.p2p, quai.core, config.NodeLocation)
// Start the handler
quai.handler.Start()

quai.APIBackend = &QuaiAPIBackend{stack.Config().ExtRPCEnabled(), quai, nil}
// Gasprice oracle is only initiated in zone chains
if nodeCtx == common.ZONE_CTX && quai.core.ProcessingState() {
Expand Down Expand Up @@ -260,6 +275,21 @@ func New(stack *node.Node, p2p NetworkingAPI, config *quaiconfig.Config, nodeCtx
return quai, nil
}

func NewFake(stack *node.Node, p2p NetworkingAPI, config *quaiconfig.Config, nodeCtx int, logger *log.Logger, chainDb ethdb.Database) (*Quai, error) {

quai, err := newCommon(stack, p2p, config, nodeCtx, logger, chainDb, core.NewFakeCore)

quai.handler = newHandler(quai.p2p, quai.core, config.NodeLocation)
// Start the handler
quai.handler.Start()

if err != nil {
return nil, err
}

return quai, nil
}

// APIs return the collection of RPC services the go-quai package offers.
// NOTE, some of these services probably need to be moved to somewhere else.
func (s *Quai) APIs() []rpc.API {
Expand Down
Loading

0 comments on commit b2b45ee

Please sign in to comment.