Skip to content

Commit

Permalink
bugfix: SetCurrentHeader bug with not updating the current header
Browse files Browse the repository at this point in the history
CurrentHeader is set based on POEM decision
  • Loading branch information
gameofpointers committed Sep 27, 2023
1 parent f6c2acf commit 4992790
Show file tree
Hide file tree
Showing 7 changed files with 48 additions and 57 deletions.
8 changes: 4 additions & 4 deletions core/core.go
Original file line number Diff line number Diff line change
Expand Up @@ -112,7 +112,7 @@ func (c *Core) InsertChain(blocks types.Blocks) (int, error) {
log.Info("Already processing block:", "Number:", block.Header().NumberArray(), "Hash:", block.Hash())
return idx, errors.New("Already in process of appending this block")
}
newPendingEtxs, _, err := c.sl.Append(block.Header(), types.EmptyHeader(), common.Hash{}, false, nil)
newPendingEtxs, _, _, err := c.sl.Append(block.Header(), types.EmptyHeader(), common.Hash{}, false, nil)
c.processingCache.Remove(block.Hash())
if err == nil {
// If we have a dom, send the dom any pending ETXs which will become
Expand Down Expand Up @@ -463,8 +463,8 @@ func (c *Core) WriteBlock(block *types.Block) {
}
}

func (c *Core) Append(header *types.Header, manifest types.BlockManifest, domPendingHeader *types.Header, domTerminus common.Hash, domOrigin bool, newInboundEtxs types.Transactions) (types.Transactions, bool, error) {
newPendingEtxs, subReorg, err := c.sl.Append(header, domPendingHeader, domTerminus, domOrigin, newInboundEtxs)
func (c *Core) Append(header *types.Header, manifest types.BlockManifest, domPendingHeader *types.Header, domTerminus common.Hash, domOrigin bool, newInboundEtxs types.Transactions) (types.Transactions, bool, bool, error) {
newPendingEtxs, subReorg, setHead, err := c.sl.Append(header, domPendingHeader, domTerminus, domOrigin, newInboundEtxs)
if err != nil {
if err.Error() == ErrBodyNotFound.Error() || err.Error() == consensus.ErrUnknownAncestor.Error() || err.Error() == ErrSubNotSyncedToDom.Error() {
// Fetch the blocks for each hash in the manifest
Expand Down Expand Up @@ -499,7 +499,7 @@ func (c *Core) Append(header *types.Header, manifest types.BlockManifest, domPen
}
}
}
return newPendingEtxs, subReorg, err
return newPendingEtxs, subReorg, setHead, err
}

func (c *Core) DownloadBlocksInManifest(manifest types.BlockManifest, entropy *big.Int) {
Expand Down
17 changes: 10 additions & 7 deletions core/headerchain.go
Original file line number Diff line number Diff line change
Expand Up @@ -304,12 +304,10 @@ func (hc *HeaderChain) SetCurrentHeader(head *types.Header) error {
if prevHeader.Hash() == head.Hash() {
return nil
}
//Find a common header
commonHeader := hc.findCommonAncestor(head)
newHeader := head

// write the head block hash to the db
rawdb.WriteHeadBlockHash(hc.headerDb, head.Hash())
log.Info("Setting the current header", "Hash", head.Hash(), "Number", head.NumberArray())
hc.currentHeader.Store(head)

// If head is the normal extension of canonical head, we can return by just wiring the canonical hash.
Expand All @@ -322,6 +320,10 @@ func (hc *HeaderChain) SetCurrentHeader(head *types.Header) error {
return nil
}

//Find a common header
commonHeader := hc.findCommonAncestor(head)
newHeader := head

// Delete each header and rollback state processor until common header
// Accumulate the hash slice stack
var hashStack []*types.Header
Expand Down Expand Up @@ -383,15 +385,16 @@ func (hc *HeaderChain) ReadInboundEtxsAndAppendBlock(header *types.Header) error

// findCommonAncestor
func (hc *HeaderChain) findCommonAncestor(header *types.Header) *types.Header {
current := types.CopyHeader(header)
for {
if header == nil {
if current == nil {
return nil
}
canonicalHash := rawdb.ReadCanonicalHash(hc.headerDb, header.NumberU64())
if canonicalHash == header.Hash() {
canonicalHash := rawdb.ReadCanonicalHash(hc.headerDb, current.NumberU64())
if canonicalHash == current.Hash() {
return hc.GetHeaderByHash(canonicalHash)
}
header = hc.GetHeader(header.ParentHash(), header.NumberU64()-1)
current = hc.GetHeader(current.ParentHash(), current.NumberU64()-1)
}

}
Expand Down
64 changes: 25 additions & 39 deletions core/slice.go
Original file line number Diff line number Diff line change
Expand Up @@ -128,11 +128,11 @@ func NewSlice(db ethdb.Database, config *Config, txConfig *TxPoolConfig, txLooku

// 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.
func (sl *Slice) Append(header *types.Header, domPendingHeader *types.Header, domTerminus common.Hash, domOrigin bool, newInboundEtxs types.Transactions) (types.Transactions, bool, error) {
func (sl *Slice) Append(header *types.Header, domPendingHeader *types.Header, domTerminus common.Hash, domOrigin bool, newInboundEtxs types.Transactions) (types.Transactions, bool, bool, error) {
start := time.Now()

if header.Hash() == sl.config.GenesisHash {
return nil, false, nil
return nil, false, false, nil
}

// Only print in Info level if block is c_startingPrintLimit behind or less
Expand All @@ -145,49 +145,49 @@ func (sl *Slice) Append(header *types.Header, domPendingHeader *types.Header, do
time0_1 := common.PrettyDuration(time.Since(start))
// Check if the header hash exists in the BadHashes list
if sl.IsBlockHashABadHash(header.Hash()) {
return nil, false, ErrBadBlockHash
return nil, false, false, ErrBadBlockHash
}
time0_2 := common.PrettyDuration(time.Since(start))

nodeCtx := common.NodeLocation.Context()
location := header.Location()
_, order, err := sl.engine.CalcOrder(header)
if err != nil {
return nil, false, err
return nil, false, false, err
}
// Don't append the block which already exists in the database.
if sl.hc.HasHeader(header.Hash(), header.NumberU64()) && (sl.hc.GetTerminiByHash(header.Hash()) != nil) {
log.Debug("Block has already been appended: ", "Hash: ", header.Hash())
return nil, false, ErrKnownBlock
return nil, false, false, ErrKnownBlock
}
time1 := common.PrettyDuration(time.Since(start))
// This is to prevent a crash when we try to insert blocks before domClient is on.
// Ideally this check should not exist here and should be fixed before we start the slice.
if sl.domClient == nil && nodeCtx != common.PRIME_CTX {
return nil, false, ErrDomClientNotUp
return nil, false, false, ErrDomClientNotUp
}

batch := sl.sliceDb.NewBatch()

// Run Previous Coincident Reference Check (PCRC)
domTerminus, newTermini, err := sl.pcrc(batch, header, domTerminus, domOrigin)
if err != nil {
return nil, false, err
return nil, false, false, err
}
log.Debug("PCRC done", "hash", header.Hash(), "number", header.NumberArray(), "termini", newTermini)

time2 := common.PrettyDuration(time.Since(start))
// Append the new block
err = sl.hc.AppendHeader(header)
if err != nil {
return nil, false, err
return nil, false, false, err
}

time3 := common.PrettyDuration(time.Since(start))
// Construct the block locally
block, err := sl.ConstructLocalBlock(header)
if err != nil {
return nil, false, err
return nil, false, false, err
}
time4 := common.PrettyDuration(time.Since(start))

Expand All @@ -196,7 +196,7 @@ func (sl *Slice) Append(header *types.Header, domPendingHeader *types.Header, do
// Upate the local pending header
pendingHeaderWithTermini, err = sl.generateSlicePendingHeader(block, newTermini, domPendingHeader, domOrigin, true, false)
if err != nil {
return nil, false, err
return nil, false, false, err
}
}

Expand All @@ -208,24 +208,25 @@ func (sl *Slice) Append(header *types.Header, domPendingHeader *types.Header, do
newInboundEtxs, _, err = sl.CollectNewlyConfirmedEtxs(block, block.Location())
if err != nil {
log.Error("Error collecting newly confirmed etxs: ", "err", err)
return nil, false, ErrSubNotSyncedToDom
return nil, false, false, ErrSubNotSyncedToDom
}
}
time5 := common.PrettyDuration(time.Since(start))

time6 := common.PrettyDuration(time.Since(start))
var subPendingEtxs types.Transactions
var subReorg bool
var setHead bool
var time6_1 common.PrettyDuration
var time6_2 common.PrettyDuration
var time6_3 common.PrettyDuration
// Call my sub to append the block, and collect the rolled up ETXs from that sub
if nodeCtx != common.ZONE_CTX {
// How to get the sub pending etxs if not running the full node?.
if sl.subClients[location.SubIndex()] != nil {
subPendingEtxs, subReorg, err = sl.subClients[location.SubIndex()].Append(context.Background(), header, block.SubManifest(), pendingHeaderWithTermini.Header(), domTerminus, true, newInboundEtxs)
subPendingEtxs, subReorg, setHead, err = sl.subClients[location.SubIndex()].Append(context.Background(), header, block.SubManifest(), pendingHeaderWithTermini.Header(), domTerminus, true, newInboundEtxs)
if err != nil {
return nil, false, err
return nil, false, false, err
}
time6_1 = common.PrettyDuration(time.Since(start))
// Cache the subordinate's pending ETXs
Expand Down Expand Up @@ -264,7 +265,7 @@ func (sl *Slice) Append(header *types.Header, domPendingHeader *types.Header, do

tempPendingHeader, err := sl.generateSlicePendingHeader(block, newTermini, domPendingHeader, domOrigin, false, false)
if err != nil {
return nil, false, err
return nil, false, false, err
}

subReorg = sl.miningStrategy(bestPh, tempPendingHeader)
Expand All @@ -275,17 +276,18 @@ func (sl *Slice) Append(header *types.Header, domPendingHeader *types.Header, do
rawdb.WriteInboundEtxs(sl.sliceDb, block.Hash(), newInboundEtxs.FilterToLocation(common.NodeLocation))
}

if subReorg {
setHead = sl.poem(sl.engine.TotalLogS(block.Header()), sl.engine.TotalLogS(sl.hc.CurrentHeader()))
if setHead {
err := sl.hc.SetCurrentHeader(block.Header())
if err != nil {
log.Error("Error setting current header", "err", err, "Hash", block.Hash())
return nil, false, err
return nil, false, false, err
}
}
// Upate the local pending header
pendingHeaderWithTermini, err = sl.generateSlicePendingHeader(block, newTermini, domPendingHeader, domOrigin, subReorg, false)
if err != nil {
return nil, false, err
return nil, false, false, err
}

time9 = common.PrettyDuration(time.Since(start))
Expand All @@ -305,15 +307,15 @@ func (sl *Slice) Append(header *types.Header, domPendingHeader *types.Header, do

// Append has succeeded write the batch
if err := batch.Write(); err != nil {
return nil, false, err
return nil, false, false, err
}

if subReorg {
if setHead {
if nodeCtx != common.ZONE_CTX {
err := sl.hc.SetCurrentHeader(block.Header())
if err != nil {
log.Error("Error setting current header", "err", err, "Hash", block.Hash())
return nil, false, err
return nil, false, false, err
}
}
sl.hc.chainHeadFeed.Send(ChainHeadEvent{Block: block})
Expand All @@ -340,9 +342,9 @@ func (sl *Slice) Append(header *types.Header, domPendingHeader *types.Header, do
go sl.domClient.UpdateDom(context.Background(), bestPh.Termini().DomTerminus(), pendingHeaderWithTermini, common.NodeLocation)
}
}
return block.ExtTransactions(), subReorg, nil
return block.ExtTransactions(), subReorg, setHead, nil
} else {
return subPendingEtxs, subReorg, nil
return subPendingEtxs, subReorg, setHead, nil
}
}

Expand Down Expand Up @@ -648,7 +650,7 @@ func (sl *Slice) pcrc(batch ethdb.Batch, header *types.Header, domTerminus commo

// POEM compares externS to the currentHead S and returns true if externS is greater
func (sl *Slice) poem(externS *big.Int, currentS *big.Int) bool {
log.Debug("POEM:", "Header hash:", sl.hc.CurrentHeader().Hash(), "currentS:", common.BigBitsToBits(currentS), "externS:", common.BigBitsToBits(externS))
log.Debug("POEM:", "currentS:", common.BigBitsToBits(currentS), "externS:", common.BigBitsToBits(externS))
reorg := currentS.Cmp(externS) <= 0
return reorg
}
Expand Down Expand Up @@ -795,27 +797,14 @@ func (sl *Slice) updatePhCacheFromDom(pendingHeader types.PendingHeader, termini
if (localPendingHeader.Header().Root() != types.EmptyRootHash && nodeCtx == common.ZONE_CTX) || nodeCtx == common.REGION_CTX {
block := sl.hc.GetBlockOrCandidateByHash(localPendingHeader.Header().ParentHash())
if block != nil {
err := sl.hc.SetCurrentHeader(block.Header())
if err != nil {
log.Error("Error setting current header", "err", err, "Hash", block.Hash())
return err
}
log.Info("Choosing phHeader pickPhHead:", "NumberArray:", combinedPendingHeader.NumberArray(), "Number:", combinedPendingHeader.Number(), "ParentHash:", combinedPendingHeader.ParentHash(), "Terminus:", localPendingHeader.Termini().DomTerminus())
sl.WriteBestPhKey(localPendingHeader.Termini().DomTerminus())
if block.Hash() != sl.hc.CurrentHeader().Hash() {
sl.hc.chainHeadFeed.Send(ChainHeadEvent{block})
}
} else {
log.Warn("unable to set the current header after the cord update", "Hash", localPendingHeader.Header().ParentHash())
}
} else {
block := sl.hc.GetBlockOrCandidateByHash(localPendingHeader.Header().ParentHash())
if block != nil {
err := sl.hc.SetCurrentHeader(block.Header())
if err != nil {
log.Error("Error setting current header", "err", err, "Hash", block.Hash())
return err
}
newPendingHeader, err := sl.generateSlicePendingHeader(block, localPendingHeader.Termini(), combinedPendingHeader, true, true, false)
if err != nil {
log.Error("Error generating slice pending header", "err", err)
Expand All @@ -824,9 +813,6 @@ func (sl *Slice) updatePhCacheFromDom(pendingHeader types.PendingHeader, termini
combinedPendingHeader = types.CopyHeader(newPendingHeader.Header())
log.Info("Choosing phHeader pickPhHead:", "NumberArray:", combinedPendingHeader.NumberArray(), "ParentHash:", combinedPendingHeader.ParentHash(), "Terminus:", localPendingHeader.Termini().DomTerminus())
sl.WriteBestPhKey(localPendingHeader.Termini().DomTerminus())
if block.Hash() != sl.hc.CurrentHeader().Hash() {
sl.hc.chainHeadFeed.Send(ChainHeadEvent{block})
}
} else {
log.Warn("unable to set the current header after the cord update", "Hash", localPendingHeader.Header().ParentHash())
}
Expand Down
2 changes: 1 addition & 1 deletion eth/api_backend.go
Original file line number Diff line number Diff line change
Expand Up @@ -448,7 +448,7 @@ func (b *QuaiAPIBackend) SyncProgress() quai.SyncProgress {
return b.eth.Downloader().Progress()
}

func (b *QuaiAPIBackend) Append(header *types.Header, manifest types.BlockManifest, domPendingHeader *types.Header, domTerminus common.Hash, domOrigin bool, newInboundEtxs types.Transactions) (types.Transactions, bool, error) {
func (b *QuaiAPIBackend) Append(header *types.Header, manifest types.BlockManifest, domPendingHeader *types.Header, domTerminus common.Hash, domOrigin bool, newInboundEtxs types.Transactions) (types.Transactions, bool, bool, error) {
return b.eth.core.Append(header, manifest, domPendingHeader, domTerminus, domOrigin, newInboundEtxs)
}

Expand Down
2 changes: 1 addition & 1 deletion internal/quaiapi/backend.go
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ type Backend interface {
SubscribeChainHeadEvent(ch chan<- core.ChainHeadEvent) event.Subscription
SubscribeChainSideEvent(ch chan<- core.ChainSideEvent) event.Subscription
WriteBlock(block *types.Block)
Append(header *types.Header, manifest types.BlockManifest, domPendingHeader *types.Header, domTerminus common.Hash, domOrigin bool, newInboundEtxs types.Transactions) (types.Transactions, bool, error)
Append(header *types.Header, manifest types.BlockManifest, domPendingHeader *types.Header, domTerminus common.Hash, domOrigin bool, newInboundEtxs types.Transactions) (types.Transactions, bool, bool, error)
DownloadBlocksInManifest(manifest types.BlockManifest, entropy *big.Int)
ConstructLocalMinedBlock(header *types.Header) (*types.Block, error)
InsertBlock(ctx context.Context, block *types.Block) (int, error)
Expand Down
3 changes: 2 additions & 1 deletion internal/quaiapi/quai_api.go
Original file line number Diff line number Diff line change
Expand Up @@ -633,14 +633,15 @@ func (s *PublicBlockChainQuaiAPI) Append(ctx context.Context, raw json.RawMessag
return nil, err
}

pendingEtxs, subReorg, err := s.b.Append(body.Header, body.Manifest, body.DomPendingHeader, body.DomTerminus, body.DomOrigin, body.NewInboundEtxs)
pendingEtxs, subReorg, setHead, err := s.b.Append(body.Header, body.Manifest, body.DomPendingHeader, body.DomTerminus, body.DomOrigin, body.NewInboundEtxs)
if err != nil {
return nil, err
}
// Marshal the output for decoding
fields := map[string]interface{}{
"pendingEtxs": pendingEtxs,
"subReorg": subReorg,
"setHead": setHead,
}

return fields, nil
Expand Down
9 changes: 5 additions & 4 deletions quaiclient/quaiclient.go
Original file line number Diff line number Diff line change
Expand Up @@ -86,9 +86,10 @@ type Termini struct {
type appendReturns struct {
Etxs types.Transactions `json:"pendingEtxs"`
SubReorg bool `json:"subReorg"`
SetHead bool `json:"setHead"`
}

func (ec *Client) Append(ctx context.Context, header *types.Header, manifest types.BlockManifest, domPendingHeader *types.Header, domTerminus common.Hash, domOrigin bool, newInboundEtxs types.Transactions) (types.Transactions, bool, error) {
func (ec *Client) Append(ctx context.Context, header *types.Header, manifest types.BlockManifest, domPendingHeader *types.Header, domTerminus common.Hash, domOrigin bool, newInboundEtxs types.Transactions) (types.Transactions, bool, bool, error) {
fields := map[string]interface{}{
"header": header.RPCMarshalHeader(),
"manifest": manifest,
Expand All @@ -101,16 +102,16 @@ func (ec *Client) Append(ctx context.Context, header *types.Header, manifest typ
var raw json.RawMessage
err := ec.c.CallContext(ctx, &raw, "quai_append", fields)
if err != nil {
return nil, false, err
return nil, false, false, err
}

// Decode header and transactions.
var aReturns appendReturns
if err := json.Unmarshal(raw, &aReturns); err != nil {
return nil, false, err
return nil, false, false, err
}

return aReturns.Etxs, aReturns.SubReorg, nil
return aReturns.Etxs, aReturns.SubReorg, aReturns.SetHead, nil
}

func (ec *Client) DownloadBlocksInManifest(ctx context.Context, manifest types.BlockManifest, entropy *big.Int) {
Expand Down

0 comments on commit 4992790

Please sign in to comment.