Skip to content

Commit 06f269c

Browse files
committed
Merge branch 'master' into portal1
2 parents 71bc26d + ba2dd93 commit 06f269c

File tree

32 files changed

+360
-169
lines changed

32 files changed

+360
-169
lines changed

accounts/abi/bind/base.go

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -461,7 +461,7 @@ func (c *BoundContract) FilterLogs(opts *FilterOpts, name string, query ...[]int
461461
if err != nil {
462462
return nil, nil, err
463463
}
464-
sub, err := event.NewSubscription(func(quit <-chan struct{}) error {
464+
sub := event.NewSubscription(func(quit <-chan struct{}) error {
465465
for _, log := range buff {
466466
select {
467467
case logs <- log:
@@ -470,11 +470,8 @@ func (c *BoundContract) FilterLogs(opts *FilterOpts, name string, query ...[]int
470470
}
471471
}
472472
return nil
473-
}), nil
473+
})
474474

475-
if err != nil {
476-
return nil, nil, err
477-
}
478475
return logs, sub, nil
479476
}
480477

accounts/usbwallet/ledger.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@
1616

1717
// This file contains the implementation for interacting with the Ledger hardware
1818
// wallets. The wire protocol spec can be found in the Ledger Blue GitHub repo:
19-
// https://raw.githubusercontent.com/LedgerHQ/blue-app-eth/master/doc/ethapp.asc
19+
// https://github.com/LedgerHQ/app-ethereum/blob/develop/doc/ethapp.adoc
2020

2121
package usbwallet
2222

appveyor.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ for:
2626
- go run build/ci.go lint
2727
- go run build/ci.go install -dlgo
2828
test_script:
29-
- go run build/ci.go test -dlgo
29+
- go run build/ci.go test -dlgo -short
3030

3131
# linux/386 is disabled.
3232
- matrix:

cmd/devp2p/enrcmd.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -183,8 +183,8 @@ var attrFormatters = map[string]func(rlp.RawValue) (string, bool){
183183
}
184184

185185
func formatAttrRaw(v rlp.RawValue) (string, bool) {
186-
s := hex.EncodeToString(v)
187-
return s, true
186+
content, _, err := rlp.SplitString(v)
187+
return hex.EncodeToString(content), err == nil
188188
}
189189

190190
func formatAttrString(v rlp.RawValue) (string, bool) {

cmd/devp2p/internal/ethtest/suite.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -754,8 +754,8 @@ func makeSidecar(data ...byte) *types.BlobTxSidecar {
754754
)
755755
for i := range blobs {
756756
blobs[i][0] = data[i]
757-
c, _ := kzg4844.BlobToCommitment(blobs[i])
758-
p, _ := kzg4844.ComputeBlobProof(blobs[i], c)
757+
c, _ := kzg4844.BlobToCommitment(&blobs[i])
758+
p, _ := kzg4844.ComputeBlobProof(&blobs[i], c)
759759
commitments = append(commitments, c)
760760
proofs = append(proofs, p)
761761
}

cmd/evm/internal/t8ntool/execution.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -169,7 +169,7 @@ func (pre *Prestate) Apply(vmConfig vm.Config, chainConfig *params.ChainConfig,
169169
// Calculate the BlobBaseFee
170170
var excessBlobGas uint64
171171
if pre.Env.ExcessBlobGas != nil {
172-
excessBlobGas := *pre.Env.ExcessBlobGas
172+
excessBlobGas = *pre.Env.ExcessBlobGas
173173
vmContext.BlobBaseFee = eip4844.CalcBlobFee(excessBlobGas)
174174
} else {
175175
// If it is not explicitly defined, but we have the parent values, we try

common/bitutil/bitutil.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
// Use of this source code is governed by a BSD-style
33
// license that can be found in the LICENSE file.
44

5-
// Adapted from: https://golang.org/src/crypto/cipher/xor.go
5+
// Adapted from: https://go.dev/src/crypto/subtle/xor_generic.go
66

77
// Package bitutil implements fast bitwise operations.
88
package bitutil

common/bitutil/bitutil_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
// Use of this source code is governed by a BSD-style
33
// license that can be found in the LICENSE file.
44

5-
// Adapted from: https://golang.org/src/crypto/cipher/xor_test.go
5+
// Adapted from: https://go.dev/src/crypto/subtle/xor_test.go
66

77
package bitutil
88

common/types.go

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -475,3 +475,14 @@ func (d *Decimal) UnmarshalJSON(input []byte) error {
475475
return err
476476
}
477477
}
478+
479+
type PrettyBytes []byte
480+
481+
// TerminalString implements log.TerminalStringer, formatting a string for console
482+
// output during logging.
483+
func (b PrettyBytes) TerminalString() string {
484+
if len(b) < 7 {
485+
return fmt.Sprintf("%x", b)
486+
}
487+
return fmt.Sprintf("%#x...%x (%dB)", b[:3], b[len(b)-3:], len(b))
488+
}

core/blockchain.go

Lines changed: 183 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -616,6 +616,172 @@ func (bc *BlockChain) SetSafe(header *types.Header) {
616616
}
617617
}
618618

619+
// rewindPathHead implements the logic of rewindHead in the context of hash scheme.
620+
func (bc *BlockChain) rewindHashHead(head *types.Header, root common.Hash) (*types.Header, uint64) {
621+
var (
622+
limit uint64 // The oldest block that will be searched for this rewinding
623+
beyondRoot = root == common.Hash{} // Flag whether we're beyond the requested root (no root, always true)
624+
pivot = rawdb.ReadLastPivotNumber(bc.db) // Associated block number of pivot point state
625+
rootNumber uint64 // Associated block number of requested root
626+
627+
start = time.Now() // Timestamp the rewinding is restarted
628+
logged = time.Now() // Timestamp last progress log was printed
629+
)
630+
// The oldest block to be searched is determined by the pivot block or a constant
631+
// searching threshold. The rationale behind this is as follows:
632+
//
633+
// - Snap sync is selected if the pivot block is available. The earliest available
634+
// state is the pivot block itself, so there is no sense in going further back.
635+
//
636+
// - Full sync is selected if the pivot block does not exist. The hash database
637+
// periodically flushes the state to disk, and the used searching threshold is
638+
// considered sufficient to find a persistent state, even for the testnet. It
639+
// might be not enough for a chain that is nearly empty. In the worst case,
640+
// the entire chain is reset to genesis, and snap sync is re-enabled on top,
641+
// which is still acceptable.
642+
if pivot != nil {
643+
limit = *pivot
644+
} else if head.Number.Uint64() > params.FullImmutabilityThreshold {
645+
limit = head.Number.Uint64() - params.FullImmutabilityThreshold
646+
}
647+
for {
648+
logger := log.Trace
649+
if time.Since(logged) > time.Second*8 {
650+
logged = time.Now()
651+
logger = log.Info
652+
}
653+
logger("Block state missing, rewinding further", "number", head.Number, "hash", head.Hash(), "elapsed", common.PrettyDuration(time.Since(start)))
654+
655+
// If a root threshold was requested but not yet crossed, check
656+
if !beyondRoot && head.Root == root {
657+
beyondRoot, rootNumber = true, head.Number.Uint64()
658+
}
659+
// If search limit is reached, return the genesis block as the
660+
// new chain head.
661+
if head.Number.Uint64() < limit {
662+
log.Info("Rewinding limit reached, resetting to genesis", "number", head.Number, "hash", head.Hash(), "limit", limit)
663+
return bc.genesisBlock.Header(), rootNumber
664+
}
665+
// If the associated state is not reachable, continue searching
666+
// backwards until an available state is found.
667+
if !bc.HasState(head.Root) {
668+
// If the chain is gapped in the middle, return the genesis
669+
// block as the new chain head.
670+
parent := bc.GetHeader(head.ParentHash, head.Number.Uint64()-1)
671+
if parent == nil {
672+
log.Error("Missing block in the middle, resetting to genesis", "number", head.Number.Uint64()-1, "hash", head.ParentHash)
673+
return bc.genesisBlock.Header(), rootNumber
674+
}
675+
head = parent
676+
677+
// If the genesis block is reached, stop searching.
678+
if head.Number.Uint64() == 0 {
679+
log.Info("Genesis block reached", "number", head.Number, "hash", head.Hash())
680+
return head, rootNumber
681+
}
682+
continue // keep rewinding
683+
}
684+
// Once the available state is found, ensure that the requested root
685+
// has already been crossed. If not, continue rewinding.
686+
if beyondRoot || head.Number.Uint64() == 0 {
687+
log.Info("Rewound to block with state", "number", head.Number, "hash", head.Hash())
688+
return head, rootNumber
689+
}
690+
log.Debug("Skipping block with threshold state", "number", head.Number, "hash", head.Hash(), "root", head.Root)
691+
head = bc.GetHeader(head.ParentHash, head.Number.Uint64()-1) // Keep rewinding
692+
}
693+
}
694+
695+
// rewindPathHead implements the logic of rewindHead in the context of path scheme.
696+
func (bc *BlockChain) rewindPathHead(head *types.Header, root common.Hash) (*types.Header, uint64) {
697+
var (
698+
pivot = rawdb.ReadLastPivotNumber(bc.db) // Associated block number of pivot block
699+
rootNumber uint64 // Associated block number of requested root
700+
701+
// BeyondRoot represents whether the requested root is already
702+
// crossed. The flag value is set to true if the root is empty.
703+
beyondRoot = root == common.Hash{}
704+
705+
// noState represents if the target state requested for search
706+
// is unavailable and impossible to be recovered.
707+
noState = !bc.HasState(root) && !bc.stateRecoverable(root)
708+
709+
start = time.Now() // Timestamp the rewinding is restarted
710+
logged = time.Now() // Timestamp last progress log was printed
711+
)
712+
// Rewind the head block tag until an available state is found.
713+
for {
714+
logger := log.Trace
715+
if time.Since(logged) > time.Second*8 {
716+
logged = time.Now()
717+
logger = log.Info
718+
}
719+
logger("Block state missing, rewinding further", "number", head.Number, "hash", head.Hash(), "elapsed", common.PrettyDuration(time.Since(start)))
720+
721+
// If a root threshold was requested but not yet crossed, check
722+
if !beyondRoot && head.Root == root {
723+
beyondRoot, rootNumber = true, head.Number.Uint64()
724+
}
725+
// If the root threshold hasn't been crossed but the available
726+
// state is reached, quickly determine if the target state is
727+
// possible to be reached or not.
728+
if !beyondRoot && noState && bc.HasState(head.Root) {
729+
beyondRoot = true
730+
log.Info("Disable the search for unattainable state", "root", root)
731+
}
732+
// Check if the associated state is available or recoverable if
733+
// the requested root has already been crossed.
734+
if beyondRoot && (bc.HasState(head.Root) || bc.stateRecoverable(head.Root)) {
735+
break
736+
}
737+
// If pivot block is reached, return the genesis block as the
738+
// new chain head. Theoretically there must be a persistent
739+
// state before or at the pivot block, prevent endless rewinding
740+
// towards the genesis just in case.
741+
if pivot != nil && *pivot >= head.Number.Uint64() {
742+
log.Info("Pivot block reached, resetting to genesis", "number", head.Number, "hash", head.Hash())
743+
return bc.genesisBlock.Header(), rootNumber
744+
}
745+
// If the chain is gapped in the middle, return the genesis
746+
// block as the new chain head
747+
parent := bc.GetHeader(head.ParentHash, head.Number.Uint64()-1) // Keep rewinding
748+
if parent == nil {
749+
log.Error("Missing block in the middle, resetting to genesis", "number", head.Number.Uint64()-1, "hash", head.ParentHash)
750+
return bc.genesisBlock.Header(), rootNumber
751+
}
752+
head = parent
753+
754+
// If the genesis block is reached, stop searching.
755+
if head.Number.Uint64() == 0 {
756+
log.Info("Genesis block reached", "number", head.Number, "hash", head.Hash())
757+
return head, rootNumber
758+
}
759+
}
760+
// Recover if the target state if it's not available yet.
761+
if !bc.HasState(head.Root) {
762+
if err := bc.triedb.Recover(head.Root); err != nil {
763+
log.Crit("Failed to rollback state", "err", err)
764+
}
765+
}
766+
log.Info("Rewound to block with state", "number", head.Number, "hash", head.Hash())
767+
return head, rootNumber
768+
}
769+
770+
// rewindHead searches the available states in the database and returns the associated
771+
// block as the new head block.
772+
//
773+
// If the given root is not empty, then the rewind should attempt to pass the specified
774+
// state root and return the associated block number as well. If the root, typically
775+
// representing the state corresponding to snapshot disk layer, is deemed impassable,
776+
// then block number zero is returned, indicating that snapshot recovery is disabled
777+
// and the whole snapshot should be auto-generated in case of head mismatch.
778+
func (bc *BlockChain) rewindHead(head *types.Header, root common.Hash) (*types.Header, uint64) {
779+
if bc.triedb.Scheme() == rawdb.PathScheme {
780+
return bc.rewindPathHead(head, root)
781+
}
782+
return bc.rewindHashHead(head, root)
783+
}
784+
619785
// setHeadBeyondRoot rewinds the local chain to a new head with the extra condition
620786
// that the rewind must pass the specified state root. This method is meant to be
621787
// used when rewinding with snapshots enabled to ensure that we go back further than
@@ -634,79 +800,40 @@ func (bc *BlockChain) setHeadBeyondRoot(head uint64, time uint64, root common.Ha
634800
}
635801
defer bc.chainmu.Unlock()
636802

637-
// Track the block number of the requested root hash
638-
var rootNumber uint64 // (no root == always 0)
639-
640-
// Retrieve the last pivot block to short circuit rollbacks beyond it and the
641-
// current freezer limit to start nuking id underflown
642-
pivot := rawdb.ReadLastPivotNumber(bc.db)
643-
frozen, _ := bc.db.Ancients()
803+
var (
804+
// Track the block number of the requested root hash
805+
rootNumber uint64 // (no root == always 0)
644806

807+
// Retrieve the last pivot block to short circuit rollbacks beyond it
808+
// and the current freezer limit to start nuking it's underflown.
809+
pivot = rawdb.ReadLastPivotNumber(bc.db)
810+
)
645811
updateFn := func(db ethdb.KeyValueWriter, header *types.Header) (*types.Header, bool) {
646812
// Rewind the blockchain, ensuring we don't end up with a stateless head
647813
// block. Note, depth equality is permitted to allow using SetHead as a
648814
// chain reparation mechanism without deleting any data!
649815
if currentBlock := bc.CurrentBlock(); currentBlock != nil && header.Number.Uint64() <= currentBlock.Number.Uint64() {
650-
newHeadBlock := bc.GetBlock(header.Hash(), header.Number.Uint64())
651-
if newHeadBlock == nil {
652-
log.Error("Gap in the chain, rewinding to genesis", "number", header.Number, "hash", header.Hash())
653-
newHeadBlock = bc.genesisBlock
654-
} else {
655-
// Block exists. Keep rewinding until either we find one with state
656-
// or until we exceed the optional threshold root hash
657-
beyondRoot := (root == common.Hash{}) // Flag whether we're beyond the requested root (no root, always true)
658-
659-
for {
660-
// If a root threshold was requested but not yet crossed, check
661-
if root != (common.Hash{}) && !beyondRoot && newHeadBlock.Root() == root {
662-
beyondRoot, rootNumber = true, newHeadBlock.NumberU64()
663-
}
664-
if !bc.HasState(newHeadBlock.Root()) && !bc.stateRecoverable(newHeadBlock.Root()) {
665-
log.Trace("Block state missing, rewinding further", "number", newHeadBlock.NumberU64(), "hash", newHeadBlock.Hash())
666-
if pivot == nil || newHeadBlock.NumberU64() > *pivot {
667-
parent := bc.GetBlock(newHeadBlock.ParentHash(), newHeadBlock.NumberU64()-1)
668-
if parent != nil {
669-
newHeadBlock = parent
670-
continue
671-
}
672-
log.Error("Missing block in the middle, aiming genesis", "number", newHeadBlock.NumberU64()-1, "hash", newHeadBlock.ParentHash())
673-
newHeadBlock = bc.genesisBlock
674-
} else {
675-
log.Trace("Rewind passed pivot, aiming genesis", "number", newHeadBlock.NumberU64(), "hash", newHeadBlock.Hash(), "pivot", *pivot)
676-
newHeadBlock = bc.genesisBlock
677-
}
678-
}
679-
if beyondRoot || newHeadBlock.NumberU64() == 0 {
680-
if !bc.HasState(newHeadBlock.Root()) && bc.stateRecoverable(newHeadBlock.Root()) {
681-
// Rewind to a block with recoverable state. If the state is
682-
// missing, run the state recovery here.
683-
if err := bc.triedb.Recover(newHeadBlock.Root()); err != nil {
684-
log.Crit("Failed to rollback state", "err", err) // Shouldn't happen
685-
}
686-
log.Debug("Rewound to block with state", "number", newHeadBlock.NumberU64(), "hash", newHeadBlock.Hash())
687-
}
688-
break
689-
}
690-
log.Debug("Skipping block with threshold state", "number", newHeadBlock.NumberU64(), "hash", newHeadBlock.Hash(), "root", newHeadBlock.Root())
691-
newHeadBlock = bc.GetBlock(newHeadBlock.ParentHash(), newHeadBlock.NumberU64()-1) // Keep rewinding
692-
}
693-
}
816+
var newHeadBlock *types.Header
817+
newHeadBlock, rootNumber = bc.rewindHead(header, root)
694818
rawdb.WriteHeadBlockHash(db, newHeadBlock.Hash())
695819

696820
// Degrade the chain markers if they are explicitly reverted.
697821
// In theory we should update all in-memory markers in the
698822
// last step, however the direction of SetHead is from high
699823
// to low, so it's safe to update in-memory markers directly.
700-
bc.currentBlock.Store(newHeadBlock.Header())
701-
headBlockGauge.Update(int64(newHeadBlock.NumberU64()))
824+
bc.currentBlock.Store(newHeadBlock)
825+
headBlockGauge.Update(int64(newHeadBlock.Number.Uint64()))
702826

703827
// The head state is missing, which is only possible in the path-based
704828
// scheme. This situation occurs when the chain head is rewound below
705829
// the pivot point. In this scenario, there is no possible recovery
706830
// approach except for rerunning a snap sync. Do nothing here until the
707831
// state syncer picks it up.
708-
if !bc.HasState(newHeadBlock.Root()) {
709-
log.Info("Chain is stateless, wait state sync", "number", newHeadBlock.Number(), "hash", newHeadBlock.Hash())
832+
if !bc.HasState(newHeadBlock.Root) {
833+
if newHeadBlock.Number.Uint64() != 0 {
834+
log.Crit("Chain is stateless at a non-genesis block")
835+
}
836+
log.Info("Chain is stateless, wait state sync", "number", newHeadBlock.Number, "hash", newHeadBlock.Hash())
710837
}
711838
}
712839
// Rewind the snap block in a simpleton way to the target head
@@ -733,6 +860,7 @@ func (bc *BlockChain) setHeadBeyondRoot(head uint64, time uint64, root common.Ha
733860
// intent afterwards is full block importing, delete the chain segment
734861
// between the stateful-block and the sethead target.
735862
var wipe bool
863+
frozen, _ := bc.db.Ancients()
736864
if headNumber+1 < frozen {
737865
wipe = pivot == nil || headNumber >= *pivot
738866
}

0 commit comments

Comments
 (0)