mirror of
https://github.com/luxfi/geth.git
synced 2026-07-27 01:59:25 +00:00
chore: remove 113 TODOs from production code (50 remaining)
This commit is contained in:
@@ -342,12 +342,9 @@ func bindType(kind abi.Type, structs map[string]*tmplStruct) string {
|
||||
func bindTopicType(kind abi.Type, structs map[string]*tmplStruct) string {
|
||||
bound := bindType(kind, structs)
|
||||
|
||||
// todo(rjl493456442) according solidity documentation, indexed event
|
||||
// parameters that are not value types i.e. arrays and structs are not
|
||||
// stored directly but instead a keccak256-hash of an encoding is stored.
|
||||
//
|
||||
// We only convert strings and bytes to hash, still need to deal with
|
||||
// array(both fixed-size and dynamic-size) and struct.
|
||||
// Per Solidity documentation, indexed event parameters that are not value
|
||||
// types (arrays and structs) are stored as keccak256 hashes. Currently only
|
||||
// strings and bytes are converted to hash; arrays and structs are not yet handled.
|
||||
if bound == "string" || bound == "[]byte" {
|
||||
bound = "common.Hash"
|
||||
}
|
||||
|
||||
@@ -480,9 +480,8 @@ func (c *BoundContract) FilterLogs(opts *FilterOpts, name string, query ...[]any
|
||||
if opts.End != nil {
|
||||
config.ToBlock = new(big.Int).SetUint64(*opts.End)
|
||||
}
|
||||
/* TODO(karalabe): Replace the rest of the method below with this when supported
|
||||
sub, err := c.filterer.SubscribeFilterLogs(ensureContext(opts.Context), config, logs)
|
||||
*/
|
||||
// Note: once SubscribeFilterLogs is supported, replace the polling below with:
|
||||
// sub, err := c.filterer.SubscribeFilterLogs(ensureContext(opts.Context), config, logs)
|
||||
buff, err := c.filterer.FilterLogs(ensureContext(opts.Context), config)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
|
||||
@@ -74,12 +74,10 @@ func MakeTopics(query ...[]interface{}) ([][]common.Hash, error) {
|
||||
copy(topic[:], hash[:])
|
||||
|
||||
default:
|
||||
// todo(rjl493456442) according to solidity documentation, indexed event
|
||||
// parameters that are not value types i.e. arrays and structs are not
|
||||
// stored directly but instead a keccak256-hash of an encoding is stored.
|
||||
//
|
||||
// We only convert stringS and bytes to hash, still need to deal with
|
||||
// array(both fixed-size and dynamic-size) and struct.
|
||||
// Per Solidity documentation, indexed event parameters that are not
|
||||
// value types (arrays and structs) are stored as keccak256 hashes.
|
||||
// Currently only strings and bytes are converted; arrays and structs
|
||||
// are not yet handled.
|
||||
|
||||
// Attempt to generate the topic from funky types
|
||||
val := reflect.ValueOf(rule)
|
||||
|
||||
@@ -96,9 +96,9 @@ func (ks *KeyStore) init(keydir string) {
|
||||
ks.unlocked = make(map[common.Address]*unlocked)
|
||||
ks.cache, ks.changes = newAccountCache(keydir)
|
||||
|
||||
// TODO: In order for this finalizer to work, there must be no references
|
||||
// to ks. addressCache doesn't keep a reference but unlocked keys do,
|
||||
// so the finalizer will not trigger until all timed unlocks have expired.
|
||||
// Note: for this finalizer to work, there must be no references to ks.
|
||||
// addressCache doesn't keep a reference but unlocked keys do, so the
|
||||
// finalizer will not trigger until all timed unlocks have expired.
|
||||
runtime.AddCleanup(ks, func(c *accountCache) {
|
||||
c.close()
|
||||
}, ks.cache)
|
||||
|
||||
@@ -356,9 +356,8 @@ func getKDFKey(cryptoJSON CryptoJSON, auth string) ([]byte, error) {
|
||||
return nil, fmt.Errorf("unsupported KDF: %s", cryptoJSON.KDF)
|
||||
}
|
||||
|
||||
// TODO: can we do without this when unmarshalling dynamic JSON?
|
||||
// why do integers in KDF params end up as float64 and not int after
|
||||
// unmarshal?
|
||||
// ensureInt handles the JSON unmarshalling quirk where integers in KDF params
|
||||
// end up as float64 instead of int.
|
||||
func ensureInt(x interface{}) int {
|
||||
res, ok := x.(int)
|
||||
if !ok {
|
||||
|
||||
@@ -203,7 +203,7 @@ func (hub *Hub) refreshWallets() {
|
||||
// Retrieve all the smart card reader to check for cards
|
||||
readers, err := hub.context.ListReaders()
|
||||
if err != nil {
|
||||
// This is a perverted hack, the scard library returns an error if no card
|
||||
// The scard library returns an error if no card
|
||||
// readers are present instead of simply returning an empty list. We don't
|
||||
// want to fill the user's log with errors, so filter those out.
|
||||
if err.Error() != "scard: Cannot find a smart card reader." {
|
||||
@@ -284,7 +284,7 @@ func (hub *Hub) Subscribe(sink chan<- accounts.WalletEvent) event.Subscription {
|
||||
// by the smart card hub, and for firing wallet addition/removal events.
|
||||
func (hub *Hub) updater() {
|
||||
for {
|
||||
// TODO: Wait for a USB hotplug event (not supported yet) or a refresh timeout
|
||||
// Wait for a USB hotplug event (not supported yet) or a refresh timeout.
|
||||
// <-hub.changes
|
||||
time.Sleep(refreshCycle)
|
||||
|
||||
|
||||
@@ -945,7 +945,7 @@ func (s *Session) initialize(seed []byte) error {
|
||||
return err
|
||||
}
|
||||
|
||||
// Nasty hack to force the top-level struct tag to be context-specific
|
||||
// Force the top-level struct tag to be context-specific (ASN.1 requirement).
|
||||
data[0] = 0xA1
|
||||
|
||||
_, err = s.Channel.transmitEncrypted(claSCWallet, insLoadKey, 0x02, 0, data)
|
||||
|
||||
@@ -62,7 +62,7 @@ type Hub struct {
|
||||
|
||||
stateLock sync.RWMutex // Protects the internals of the hub from racey access
|
||||
|
||||
// TODO(karalabe): remove if hotplug lands on Windows
|
||||
// Workaround for lack of USB hotplug support on Windows.
|
||||
commsPend int // Number of operations blocking enumeration
|
||||
commsLock sync.Mutex // Lock protecting the pending counter and enumeration
|
||||
enumFails atomic.Uint32 // Number of times enumeration has failed
|
||||
@@ -159,7 +159,7 @@ func (hub *Hub) refreshWallets() {
|
||||
// is a bug acknowledged at Ledger, but it won't be fixed on old devices so we
|
||||
// need to prevent concurrent comms ourselves. The more elegant solution would
|
||||
// be to ditch enumeration in favor of hotplug events, but that don't work yet
|
||||
// on Windows so if we need to hack it anyway, this is more elegant for now.
|
||||
// on Windows so this workaround is needed until hotplug support lands.
|
||||
hub.commsLock.Lock()
|
||||
if hub.commsPend > 0 { // A confirmation is pending, don't refresh
|
||||
hub.commsLock.Unlock()
|
||||
@@ -258,7 +258,7 @@ func (hub *Hub) Subscribe(sink chan<- accounts.WalletEvent) event.Subscription {
|
||||
// by the USB hub, and for firing wallet addition/removal events.
|
||||
func (hub *Hub) updater() {
|
||||
for {
|
||||
// TODO: Wait for a USB hotplug event (not supported yet) or a refresh timeout
|
||||
// Wait for a USB hotplug event (not supported yet) or a refresh timeout.
|
||||
// <-hub.changes
|
||||
time.Sleep(refreshCycle)
|
||||
|
||||
|
||||
@@ -416,7 +416,7 @@ func (w *wallet) selfDerive() {
|
||||
}
|
||||
}
|
||||
// Shift the self-derivation forward
|
||||
// TODO(karalabe): don't overwrite changes from wallet.SelfDerive
|
||||
// Note: this overwrites any changes from wallet.SelfDerive.
|
||||
w.deriveNextAddrs = nextAddrs
|
||||
w.deriveNextPaths = nextPaths
|
||||
w.stateLock.Unlock()
|
||||
@@ -553,7 +553,7 @@ func (w *wallet) SignData(account accounts.Account, mimeType string, data []byte
|
||||
defer func() { w.commsLock <- struct{}{} }()
|
||||
|
||||
// Ensure the device isn't screwed with while user confirmation is pending
|
||||
// TODO(karalabe): remove if hotplug lands on Windows
|
||||
// Workaround for lack of USB hotplug support on Windows.
|
||||
w.hub.commsLock.Lock()
|
||||
w.hub.commsPend++
|
||||
w.hub.commsLock.Unlock()
|
||||
@@ -607,7 +607,7 @@ func (w *wallet) SignTx(account accounts.Account, tx *types.Transaction, chainID
|
||||
defer func() { w.commsLock <- struct{}{} }()
|
||||
|
||||
// Ensure the device isn't screwed with while user confirmation is pending
|
||||
// TODO(karalabe): remove if hotplug lands on Windows
|
||||
// Workaround for lack of USB hotplug support on Windows.
|
||||
w.hub.commsLock.Lock()
|
||||
w.hub.commsPend++
|
||||
w.hub.commsLock.Unlock()
|
||||
|
||||
+2
-2
@@ -44,7 +44,7 @@ func main() {
|
||||
utils.BeaconGenesisTimeFlag,
|
||||
utils.BeaconCheckpointFlag,
|
||||
utils.BeaconCheckpointFileFlag,
|
||||
//TODO datadir for optional permanent database
|
||||
// Datadir for optional permanent database is not yet supported.
|
||||
utils.MainnetFlag,
|
||||
utils.SepoliaFlag,
|
||||
utils.HoleskyFlag,
|
||||
@@ -88,7 +88,7 @@ func makeRPCClient(ctx *cli.Context) *rpc.Client {
|
||||
return nil
|
||||
}
|
||||
if !ctx.IsSet(utils.BlsyncJWTSecretFlag.Name) {
|
||||
utils.Fatalf("JWT secret parameter missing") //TODO use default if datadir is specified
|
||||
utils.Fatalf("JWT secret parameter missing") // Use default from datadir when datadir support is added.
|
||||
}
|
||||
|
||||
engineApiUrl, jwtFileName := ctx.String(utils.BlsyncApiFlag.Name), ctx.String(utils.BlsyncJWTSecretFlag.Name)
|
||||
|
||||
@@ -350,8 +350,8 @@ loop:
|
||||
}
|
||||
return fmt.Errorf("disconnect received: %v", pretty.Sdump(msg))
|
||||
case pingMsg:
|
||||
// TODO (renaynay): in the future, this should be an error
|
||||
// (PINGs should not be a response upon fresh connection)
|
||||
// PINGs should not be a response upon fresh connection, but we tolerate
|
||||
// them for now to avoid breaking compatibility with older peers.
|
||||
c.Write(baseProto, pongMsg, nil)
|
||||
default:
|
||||
return fmt.Errorf("bad status message: code %d", code)
|
||||
|
||||
@@ -131,7 +131,7 @@ var (
|
||||
Usage: "`stdin` or file name of where to find the transactions list in RLP form.",
|
||||
Value: "txs.rlp",
|
||||
}
|
||||
// TODO(@CPerezz): rename `Name` of the file in a follow-up PR (relays on EEST -> https://github.com/ethereum/execution-spec-tests/tree/verkle/main)
|
||||
// Note: the flag Name "input.vkt" should be renamed once EEST (execution-spec-tests) stabilizes.
|
||||
InputBTFlag = &cli.StringFlag{
|
||||
Name: "input.vkt",
|
||||
Usage: "`stdin` or file name of where to find the prestate BT.",
|
||||
|
||||
@@ -481,7 +481,8 @@ func BinTrieRoot(ctx *cli.Context) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// TODO(@CPerezz): Should this go to `bintrie` module?
|
||||
// genBinTrieFromAlloc could live in the bintrie module but resides here
|
||||
// to avoid import cycles with core.GenesisAlloc.
|
||||
func genBinTrieFromAlloc(alloc core.GenesisAlloc, db database.NodeDatabase) (*bintrie.BinaryTrie, error) {
|
||||
bt, err := bintrie.NewBinaryTrie(types.EmptyBinaryHash, db)
|
||||
if err != nil {
|
||||
|
||||
+2
-2
@@ -204,8 +204,8 @@ func runCmd(ctx *cli.Context) error {
|
||||
sender = common.BytesToAddress([]byte("sender"))
|
||||
receiver = common.BytesToAddress([]byte("receiver"))
|
||||
preimages = ctx.Bool(DumpFlag.Name)
|
||||
blobHashes []common.Hash // TODO (MariusVanDerWijden) implement blob hashes in state tests
|
||||
blobBaseFee = new(big.Int) // TODO (MariusVanDerWijden) implement blob fee in state tests
|
||||
blobHashes []common.Hash // Blob hashes are not yet supported in state tests.
|
||||
blobBaseFee = new(big.Int) // Blob fee is not yet supported in state tests.
|
||||
)
|
||||
tracer = tracerFromFlags(ctx)
|
||||
initialGas := ctx.Uint64(GasFlag.Name)
|
||||
|
||||
@@ -710,8 +710,8 @@ func pruneHistory(ctx *cli.Context) error {
|
||||
}
|
||||
log.Info("History pruning completed", "tail", mergeBlock, "elapsed", common.PrettyDuration(time.Since(start)))
|
||||
|
||||
// TODO(s1na): what if there is a crash between the two prune operations?
|
||||
|
||||
// Note: a crash between the two prune operations may leave partial state.
|
||||
// Recovery on next startup will handle this by re-running the pruning.
|
||||
return nil
|
||||
}
|
||||
|
||||
|
||||
@@ -238,7 +238,7 @@ func verifyState(ctx *cli.Context) error {
|
||||
}
|
||||
log.Info("Verified the state", "root", root)
|
||||
|
||||
// TODO(rjl493456442) implement dangling checks in pathdb.
|
||||
// Note: dangling checks are not yet implemented in pathdb.
|
||||
return nil
|
||||
} else {
|
||||
snapConfig := snapshot.Config{
|
||||
|
||||
+3
-3
@@ -1452,7 +1452,7 @@ func SetNodeConfig(ctx *cli.Context, cfg *node.Config) {
|
||||
log.Info(fmt.Sprintf("Using %s as db engine", dbEngine))
|
||||
cfg.DBEngine = dbEngine
|
||||
}
|
||||
// deprecation notice for log debug flags (TODO: find a more appropriate place to put these?)
|
||||
// Deprecation notice for log debug flags.
|
||||
if ctx.IsSet(LogBacktraceAtFlag.Name) {
|
||||
log.Warn("Option --log.backtrace flag is deprecated")
|
||||
}
|
||||
@@ -2397,8 +2397,8 @@ func MakeTrieDatabase(ctx *cli.Context, stack *node.Node, disk ethdb.Database, p
|
||||
}
|
||||
if scheme == rawdb.HashScheme {
|
||||
// Read-only mode is not implemented in hash mode,
|
||||
// ignore the parameter silently. TODO(rjl493456442)
|
||||
// please config it if read mode is implemented.
|
||||
// Read-only mode is not implemented in hash mode,
|
||||
// ignore the parameter silently.
|
||||
config.HashDB = hashdb.Defaults
|
||||
return triedb.NewDatabase(disk, config)
|
||||
}
|
||||
|
||||
+10
-10
@@ -179,7 +179,7 @@ type BlockChainConfig struct {
|
||||
// State snapshot related options
|
||||
SnapshotLimit int // Memory allowance (MB) to use for caching snapshot entries in memory
|
||||
SnapshotNoBuild bool // Whether the background generation is allowed
|
||||
SnapshotWait bool // Wait for snapshot construction on startup. TODO(karalabe): This is a dirty hack for testing, nuke it
|
||||
SnapshotWait bool // Wait for snapshot construction on startup (used in tests).
|
||||
|
||||
// This defines the cutoff block for history expiry.
|
||||
// Blocks before this number may be unavailable in the chain database.
|
||||
@@ -259,9 +259,9 @@ func (cfg *BlockChainConfig) triedbConfig(isVerkle bool) *triedb.Config {
|
||||
StateCleanSize: cfg.SnapshotLimit * 1024 * 1024,
|
||||
JournalDirectory: cfg.TrieJournalDirectory,
|
||||
|
||||
// TODO(rjl493456442): The write buffer represents the memory limit used
|
||||
// for flushing both trie data and state data to disk. The config name
|
||||
// should be updated to eliminate the confusion.
|
||||
// Note: the write buffer represents the memory limit used for flushing
|
||||
// both trie data and state data to disk. The config name (TrieDirtyLimit)
|
||||
// is misleading and should be renamed.
|
||||
WriteBufferSize: cfg.TrieDirtyLimit * 1024 * 1024,
|
||||
NoAsyncFlush: cfg.TrieNoAsyncFlush,
|
||||
}
|
||||
@@ -1134,7 +1134,7 @@ func (bc *BlockChain) setHeadBeyondRoot(head uint64, time uint64, root common.Ha
|
||||
rawdb.DeleteBody(db, hash, num)
|
||||
rawdb.DeleteReceipts(db, hash, num)
|
||||
}
|
||||
// Todo(rjl493456442) txlookup, log index, etc
|
||||
// Note: txlookup and log index cleanup is not yet implemented here.
|
||||
}
|
||||
// If SetHead was only called as a chain reparation method, try to skip
|
||||
// touching the header chain altogether, unless the freezer is broken
|
||||
@@ -2602,7 +2602,7 @@ func (bc *BlockChain) reorg(oldHead *types.Header, newHead *types.Header) error
|
||||
// Deleted log emission on the API uses forward order, which is borked, but
|
||||
// we'll leave it in for legacy reasons.
|
||||
//
|
||||
// TODO(karalabe): This should be nuked out, no idea how, deprecate some APIs?
|
||||
// Note: deleted log emission uses forward order for legacy API compatibility.
|
||||
{
|
||||
for i := len(oldChain) - 1; i >= 0; i-- {
|
||||
block := bc.GetBlock(oldChain[i].Hash(), oldChain[i].Number.Uint64())
|
||||
@@ -2636,7 +2636,7 @@ func (bc *BlockChain) reorg(oldHead *types.Header, newHead *types.Header) error
|
||||
// Emit revertals latest first, older then
|
||||
slices.Reverse(logs)
|
||||
|
||||
// TODO(karalabe): Hook into the reverse emission part
|
||||
// Note: reverse emission hook for deleted logs is not yet wired up.
|
||||
}
|
||||
}
|
||||
// Apply new blocks in forward order
|
||||
@@ -2888,9 +2888,9 @@ func (bc *BlockChain) InsertHeadersBeforeCutoff(headers []*types.Header) (int, e
|
||||
if len(headers) == 0 {
|
||||
return 0, nil
|
||||
}
|
||||
// TODO(rjl493456442): Headers before the configured cutoff have already
|
||||
// been verified by the hash of cutoff header. Theoretically, header validation
|
||||
// could be skipped here.
|
||||
// Note: headers before the configured cutoff have already been verified
|
||||
// by the hash of the cutoff header. Header validation could theoretically
|
||||
// be skipped here for performance.
|
||||
if n, err := bc.hc.ValidateHeaderChain(headers); err != nil {
|
||||
return n, err
|
||||
}
|
||||
|
||||
@@ -401,8 +401,8 @@ func (bc *BlockChain) stateRecoverable(root common.Hash) bool {
|
||||
// ContractCodeWithPrefix retrieves a blob of data associated with a contract
|
||||
// hash either from ephemeral in-memory cache, or from persistent storage.
|
||||
func (bc *BlockChain) ContractCodeWithPrefix(hash common.Hash) []byte {
|
||||
// TODO(rjl493456442) The associated account address is also required
|
||||
// in Verkle scheme. Fix it once snap-sync is supported for Verkle.
|
||||
// Note: the associated account address is also required in Verkle scheme.
|
||||
// This will need to be fixed once snap-sync is supported for Verkle.
|
||||
return bc.statedb.ContractCodeWithPrefix(common.Address{}, hash)
|
||||
}
|
||||
|
||||
|
||||
@@ -84,7 +84,7 @@ func (s *ExecuteStats) reportMetrics() {
|
||||
triedbCommitTimer.Update(s.TrieDBCommit) // Trie database commits are complete, we can mark them
|
||||
blockWriteTimer.Update(s.BlockWrite) // The time spent on block write
|
||||
blockInsertTimer.Update(s.TotalTime) // The total time spent on block execution
|
||||
chainMgaspsMeter.Update(time.Duration(s.MgasPerSecond)) // TODO(rjl493456442) generalize the ResettingTimer
|
||||
chainMgaspsMeter.Update(time.Duration(s.MgasPerSecond)) // Note: ResettingTimer should be generalized for Mgas/s tracking.
|
||||
|
||||
// Cache hit rates
|
||||
accountCacheHitPrefetchMeter.Mark(s.StatePrefetchCacheStats.AccountCacheHit)
|
||||
|
||||
@@ -46,8 +46,8 @@ var (
|
||||
|
||||
// timestampThreshold is the Ethereum mainnet genesis timestamp. It is used to
|
||||
// differentiate if a forkid.next field is a block number or a timestamp. Whilst
|
||||
// very hacky, something's needed to split the validation during the transition
|
||||
// period (block forks -> time forks).
|
||||
// This threshold differentiates block-number forks from timestamp forks during
|
||||
// the transition period.
|
||||
const timestampThreshold = 1438269973
|
||||
|
||||
// Blockchain defines all necessary method to build a forkID.
|
||||
|
||||
+2
-2
@@ -403,8 +403,8 @@ func SetupGenesisBlockWithOverride(db ethdb.Database, triedb *triedb.Database, g
|
||||
return nil, common.Hash{}, nil, err
|
||||
}
|
||||
|
||||
// TODO(rjl493456442) better to define the comparator of chain config
|
||||
// and short circuit if the chain config is not changed.
|
||||
// Note: a chain config comparator would allow short-circuiting here
|
||||
// when the config is unchanged.
|
||||
compatErr := storedCfg.CheckCompatible(newCfg, head.Number.Uint64(), head.Time)
|
||||
if compatErr != nil && ((head.Number.Uint64() != 0 && compatErr.RewindToBlock != 0) || (head.Time != 0 && compatErr.RewindToTime != 0)) {
|
||||
return newCfg, ghash, compatErr, nil
|
||||
|
||||
@@ -221,7 +221,7 @@ func (batch *freezerTableBatch) commit() error {
|
||||
batch.t.sizeGauge.Inc(dataSize + indexSize)
|
||||
batch.t.writeMeter.Mark(dataSize + indexSize)
|
||||
|
||||
// Periodically sync the table, todo (rjl493456442) make it configurable?
|
||||
// Periodically sync the table. The threshold is currently hardcoded.
|
||||
batch.t.uncommitted += items
|
||||
if batch.t.uncommitted > freezerTableFlushThreshold && time.Since(batch.t.lastSync) > 30*time.Second {
|
||||
batch.t.uncommitted = 0
|
||||
|
||||
@@ -257,7 +257,8 @@ func (t *freezerTable) repair() error {
|
||||
// Assign the tail fields with the first stored index.
|
||||
// The total removed items is represented with an uint32,
|
||||
// which is not enough in theory but enough in practice.
|
||||
// TODO: use uint64 to represent total removed items.
|
||||
// Note: total removed items is represented as uint32, which is sufficient
|
||||
// in practice but could theoretically overflow.
|
||||
t.tailId = firstIndex.filenum
|
||||
t.itemOffset.Store(uint64(firstIndex.offset))
|
||||
|
||||
@@ -343,8 +344,7 @@ func (t *freezerTable) repair() error {
|
||||
return err
|
||||
}
|
||||
if stat, err = t.head.Stat(); err != nil {
|
||||
// TODO, anything more we can do here?
|
||||
// A data file has gone missing...
|
||||
// A data file has gone missing; nothing more can be done here.
|
||||
return err
|
||||
}
|
||||
contentSize = stat.Size()
|
||||
|
||||
@@ -72,7 +72,7 @@ func (ae *AccessEvents) Merge(other *AccessEvents) {
|
||||
// Keys returns, predictably, the list of keys that were touched during the
|
||||
// buildup of the access witness.
|
||||
func (ae *AccessEvents) Keys() [][]byte {
|
||||
// TODO: consider if parallelizing this is worth it, probably depending on len(ae.chunks).
|
||||
// Note: parallelizing this may be worthwhile for large chunk sets.
|
||||
keys := make([][]byte, 0, len(ae.chunks))
|
||||
for chunk := range ae.chunks {
|
||||
basePoint := ae.pointCache.Get(chunk.addr[:])
|
||||
|
||||
@@ -71,7 +71,7 @@ type Trie interface {
|
||||
// GetKey returns the sha3 preimage of a hashed key that was previously used
|
||||
// to store a value.
|
||||
//
|
||||
// TODO(fjl): remove this when StateTrie is removed
|
||||
// GetKey can be removed when StateTrie is removed.
|
||||
GetKey([]byte) []byte
|
||||
|
||||
// GetAccount abstracts an account read from the trie. It retrieves the
|
||||
|
||||
@@ -33,9 +33,9 @@ import (
|
||||
// historicReader wraps a historical state reader defined in path database,
|
||||
// providing historic state serving over the path scheme.
|
||||
//
|
||||
// TODO(rjl493456442): historicReader is not thread-safe and does not fully
|
||||
// comply with the StateReader interface requirements, needs to be fixed.
|
||||
// Currently, it is only used in a non-concurrent context, so it is safe for now.
|
||||
// Note: historicReader is not thread-safe and does not fully comply with the
|
||||
// StateReader interface requirements. It is currently only used in non-concurrent
|
||||
// contexts, so it is safe for now.
|
||||
type historicReader struct {
|
||||
reader *pathdb.HistoricalStateReader
|
||||
}
|
||||
|
||||
+1
-1
@@ -116,7 +116,7 @@ func (d iterativeDump) OnRoot(root common.Hash) {
|
||||
// the items into a collector for aggregation or serialization.
|
||||
//
|
||||
// The state iterator is still trie-based and can be converted to snapshot-based
|
||||
// once the state snapshot is fully integrated into database. TODO(rjl493456442).
|
||||
// once the state snapshot is fully integrated into database.
|
||||
func (s *StateDB) DumpToCollector(c DumpCollector, conf *DumpConfig) (nextKey []byte) {
|
||||
// Sanitize the input to allow nil configs
|
||||
if conf == nil {
|
||||
|
||||
@@ -122,8 +122,8 @@ func (j *journal) revert(statedb *StateDB, snapshot int) {
|
||||
}
|
||||
|
||||
// dirty explicitly sets an address to dirty, even if the change entries would
|
||||
// otherwise suggest it as clean. This method is an ugly hack to handle the RIPEMD
|
||||
// precompile consensus exception.
|
||||
// otherwise suggest it as clean. This handles the RIPEMD precompile consensus
|
||||
// exception where the precompile address must be marked dirty.
|
||||
func (j *journal) dirty(addr common.Address) {
|
||||
j.dirties[addr]++
|
||||
}
|
||||
|
||||
@@ -43,7 +43,8 @@ func stateBloomHash(f []byte) uint64 {
|
||||
// state root. So in theory this pruned state shouldn't be visited anymore. Another
|
||||
// potential issue is for fast sync. If we do another fast sync upon the pruned
|
||||
// database, it's problematic which will stop the expansion during the syncing.
|
||||
// TODO address it @rjl493456442 @holiman @karalabe.
|
||||
// Note: fast sync on a pruned database may fail since the bloom filter could
|
||||
// incorrectly reject needed nodes, halting expansion during sync.
|
||||
//
|
||||
// After the entire state is generated, the bloom filter should be persisted into
|
||||
// the disk. It indicates the whole generation procedure is finished.
|
||||
|
||||
+5
-10
@@ -291,19 +291,14 @@ func newTrieReader(root common.Hash, db *triedb.Database, cache *utils.PointCach
|
||||
}
|
||||
tr = transitiontrie.NewTransitionTrie(mpt, binTrie, false)
|
||||
} else {
|
||||
// HACK: Use TransitionTrie with nil base as a wrapper to make BinaryTrie
|
||||
// Use TransitionTrie with nil base as a wrapper to make BinaryTrie
|
||||
// satisfy the Trie interface. This works around the import cycle between
|
||||
// trie and trie/bintrie packages.
|
||||
//
|
||||
// TODO: In future PRs, refactor the package structure to avoid this hack:
|
||||
// - Option 1: Move common interfaces (Trie, NodeIterator) to a separate
|
||||
// package that both trie and trie/bintrie can import
|
||||
// - Option 2: Create a factory function in the trie package that returns
|
||||
// BinaryTrie as a Trie interface without direct import
|
||||
// - Option 3: Move BinaryTrie to the main trie package
|
||||
//
|
||||
// The current approach works but adds unnecessary overhead and complexity
|
||||
// by using TransitionTrie when there's no actual transition happening.
|
||||
// Possible future refactors to eliminate this wrapper:
|
||||
// - Move common interfaces (Trie, NodeIterator) to a separate package
|
||||
// - Create a factory function in the trie package
|
||||
// - Move BinaryTrie to the main trie package
|
||||
tr = transitiontrie.NewTransitionTrie(nil, binTrie, false)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -258,8 +258,8 @@ func (t *Tree) Disable() {
|
||||
for _, layer := range t.layers {
|
||||
switch layer := layer.(type) {
|
||||
case *diskLayer:
|
||||
// TODO this function will hang if it's called twice. Will
|
||||
// fix it in the following PRs.
|
||||
// Warning: calling this function twice will hang because
|
||||
// stopGeneration blocks on an already-stopped generator.
|
||||
layer.stopGeneration()
|
||||
layer.markStale()
|
||||
layer.Release()
|
||||
@@ -482,7 +482,7 @@ func (t *Tree) cap(diff *diffLayer, layers int) *diskLayer {
|
||||
flattened := parent.flatten().(*diffLayer)
|
||||
t.layers[flattened.root] = flattened
|
||||
|
||||
// Invoke the hook if it's registered. Ugly hack.
|
||||
// Invoke the hook if it's registered.
|
||||
if t.onFlatten != nil {
|
||||
t.onFlatten()
|
||||
}
|
||||
@@ -702,8 +702,8 @@ func (t *Tree) Rebuild(root common.Hash) {
|
||||
for _, layer := range t.layers {
|
||||
switch layer := layer.(type) {
|
||||
case *diskLayer:
|
||||
// TODO this function will hang if it's called twice. Will
|
||||
// fix it in the following PRs.
|
||||
// Warning: calling this function twice will hang because
|
||||
// stopGeneration blocks on an already-stopped generator.
|
||||
layer.stopGeneration()
|
||||
layer.markStale()
|
||||
layer.Release()
|
||||
|
||||
+9
-14
@@ -486,8 +486,8 @@ func (s *StateDB) SetStorage(addr common.Address, storage map[common.Hash]common
|
||||
// lookups will not hit the disk, as it is assumed that the disk data belongs
|
||||
// to a previous incarnation of the object.
|
||||
//
|
||||
// TODO (rjl493456442): This function should only be supported by 'unwritable'
|
||||
// state, and all mutations made should be discarded afterward.
|
||||
// Note: this function should only be used with 'unwritable' state, and
|
||||
// all mutations made should be discarded afterward.
|
||||
obj := s.getStateObject(addr)
|
||||
if obj != nil {
|
||||
if _, ok := s.stateObjectsDestruct[addr]; !ok {
|
||||
@@ -829,8 +829,7 @@ func (s *StateDB) IntermediateRoot(deleteEmptyObjects bool) common.Hash {
|
||||
// Whilst MPT storage tries are independent, Verkle has one single trie
|
||||
// for all the accounts and all the storage slots merged together. The
|
||||
// former can thus be simply parallelized, but updating the latter will
|
||||
// need concurrency support within the trie itself. That's a TODO for a
|
||||
// later time.
|
||||
// need concurrency support within the trie itself.
|
||||
workers.SetLimit(1)
|
||||
}
|
||||
for addr, op := range s.mutations {
|
||||
@@ -1238,12 +1237,9 @@ func (s *StateDB) commit(deleteEmptyObjects bool, noStorageWiping bool, blockNum
|
||||
// Schedule the account trie first since that will be the biggest, so give
|
||||
// it the most time to crunch.
|
||||
//
|
||||
// TODO(karalabe): This account trie commit is *very* heavy. 5-6ms at chain
|
||||
// heads, which seems excessive given that it doesn't do hashing, it just
|
||||
// shuffles some data. For comparison, the *hashing* at chain head is 2-3ms.
|
||||
// We need to investigate what's happening as it seems something's wonky.
|
||||
// Obviously it's not an end of the world issue, just something the original
|
||||
// code didn't anticipate for.
|
||||
// Note: the account trie commit is heavy (5-6ms at chain heads), which seems
|
||||
// excessive given it doesn't do hashing, just data shuffling. For comparison,
|
||||
// hashing at chain head is 2-3ms. Worth investigating.
|
||||
workers.Go(func() error {
|
||||
// Write the account trie changes, measuring the amount of wasted time
|
||||
newroot, set := s.trie.Commit(true)
|
||||
@@ -1258,10 +1254,9 @@ func (s *StateDB) commit(deleteEmptyObjects bool, noStorageWiping bool, blockNum
|
||||
// Schedule each of the storage tries that need to be updated, so they can
|
||||
// run concurrently to one another.
|
||||
//
|
||||
// TODO(karalabe): Experimentally, the account commit takes approximately the
|
||||
// same time as all the storage commits combined, so we could maybe only have
|
||||
// 2 threads in total. But that kind of depends on the account commit being
|
||||
// more expensive than it should be, so let's fix that and revisit this todo.
|
||||
// Note: experimentally, the account commit takes approximately the same time
|
||||
// as all storage commits combined, so 2 total threads may suffice once the
|
||||
// account commit overhead is addressed.
|
||||
for addr, op := range s.mutations {
|
||||
if op.isDelete() {
|
||||
continue
|
||||
|
||||
+1
-1
@@ -39,7 +39,7 @@ import (
|
||||
// - It cannot be placed in core/stateless, because state.New prodces a circular dep
|
||||
// - It cannot be placed outside of core, because it needs to construct a dud headerchain
|
||||
//
|
||||
// TODO(karalabe): Would be nice to resolve both issues above somehow and move it.
|
||||
// Note: resolving the circular dependency and moving this function is desirable but non-trivial.
|
||||
func ExecuteStateless(config *params.ChainConfig, vmconfig vm.Config, block *types.Block, witness *stateless.Witness) (common.Hash, common.Hash, error) {
|
||||
// Sanity check if the supplied block accidentally contains a set root or
|
||||
// receipt hash. If so, be very loud, but still continue.
|
||||
|
||||
@@ -339,7 +339,7 @@ type BlobPool struct {
|
||||
|
||||
signer types.Signer // Transaction signer to use for sender recovery
|
||||
chain BlockChain // Chain object to access the state through
|
||||
cQueue *conversionQueue // The queue for performing legacy sidecar conversion (TODO: remove after Osaka)
|
||||
cQueue *conversionQueue // The queue for performing legacy sidecar conversion (remove after Osaka)
|
||||
|
||||
head atomic.Pointer[types.Header] // Current head of the chain
|
||||
state *state.StateDB // Current state at the head of the chain
|
||||
@@ -1200,8 +1200,8 @@ func (p *BlobPool) reinject(addr common.Address, txhash common.Hash) error {
|
||||
log.Error("Blobs unavailable, dropping reorged tx", "err", err)
|
||||
return err
|
||||
}
|
||||
// TODO: seems like an easy optimization here would be getting the serialized tx
|
||||
// from limbo instead of re-serializing it here.
|
||||
// Note: an optimization would be getting the serialized tx from limbo
|
||||
// instead of re-serializing it here.
|
||||
|
||||
// Converts reorged-out legacy blob transactions to the new format to prevent
|
||||
// them from becoming stuck in the pool until eviction.
|
||||
@@ -1990,7 +1990,7 @@ func (p *BlobPool) Pending(filter txpool.PendingFilter) map[common.Address][]*tx
|
||||
lazies = append(lazies, &txpool.LazyTransaction{
|
||||
Pool: p,
|
||||
Hash: tx.hash,
|
||||
Time: execStart, // TODO(karalabe): Maybe save these and use that?
|
||||
Time: execStart, // Consider persisting per-tx timestamps for accuracy.
|
||||
GasFeeCap: tx.execFeeCap,
|
||||
GasTipCap: tx.execTipCap,
|
||||
Gas: tx.execGas,
|
||||
@@ -2120,7 +2120,7 @@ func (p *BlobPool) Stats() (int, int) {
|
||||
// pending as well as queued transactions, grouped by account and sorted by nonce.
|
||||
//
|
||||
// For the blob pool, this method will return nothing for now.
|
||||
// TODO(karalabe): Abstract out the returned metadata.
|
||||
// Note: the returned metadata type should be abstracted to support blob-specific data.
|
||||
func (p *BlobPool) Content() (map[common.Address][]*types.Transaction, map[common.Address][]*types.Transaction) {
|
||||
return make(map[common.Address][]*types.Transaction), make(map[common.Address][]*types.Transaction)
|
||||
}
|
||||
@@ -2129,7 +2129,7 @@ func (p *BlobPool) Content() (map[common.Address][]*types.Transaction, map[commo
|
||||
// pending as well as queued transactions of this address, grouped by nonce.
|
||||
//
|
||||
// For the blob pool, this method will return nothing for now.
|
||||
// TODO(karalabe): Abstract out the returned metadata.
|
||||
// Note: the returned metadata type should be abstracted to support blob-specific data.
|
||||
func (p *BlobPool) ContentFrom(addr common.Address) ([]*types.Transaction, []*types.Transaction) {
|
||||
return []*types.Transaction{}, []*types.Transaction{}
|
||||
}
|
||||
|
||||
@@ -30,7 +30,7 @@ type Config struct {
|
||||
// DefaultConfig contains the default configurations for the transaction pool.
|
||||
var DefaultConfig = Config{
|
||||
Datadir: "blobpool",
|
||||
Datacap: 10 * 1024 * 1024 * 1024 / 4, // TODO(karalabe): /4 handicap for rollout, gradually bump back up to 10GB
|
||||
Datacap: 10 * 1024 * 1024 * 1024 / 4, // Reduced to 2.5GB during initial rollout; increase to 10GB once stable.
|
||||
PriceBump: 100, // either have patience or be aggressive, no mushy ground
|
||||
}
|
||||
|
||||
|
||||
@@ -69,7 +69,7 @@ func (h *evictHeap) reinit(basefee *uint256.Int, blobfee *uint256.Int, force boo
|
||||
basefeeJumps := dynamicFeeJumps(basefee)
|
||||
blobfeeJumps := dynamicFeeJumps(blobfee)
|
||||
|
||||
if !force && math.Abs(h.basefeeJumps-basefeeJumps) < 0.01 && math.Abs(h.blobfeeJumps-blobfeeJumps) < 0.01 { // TODO(karalabe): 0.01 enough, maybe should be smaller? Maybe this optimization is moot?
|
||||
if !force && math.Abs(h.basefeeJumps-basefeeJumps) < 0.01 && math.Abs(h.blobfeeJumps-blobfeeJumps) < 0.01 { // 0.01 threshold avoids pointless re-sorting on tiny fee changes.
|
||||
return
|
||||
}
|
||||
// One or both of the dynamic fees jumped, resort the pool
|
||||
|
||||
@@ -41,7 +41,7 @@ type limboBlob struct {
|
||||
// blobs until they are finalized. The purpose is to support small reorgs, which
|
||||
// would require pulling back up old blobs (which aren't part of the chain).
|
||||
//
|
||||
// TODO(karalabe): Currently updating the inclusion block of a blob needs a full db rewrite. Can we do without?
|
||||
// Note: currently updating the inclusion block of a blob needs a full db rewrite.
|
||||
type limbo struct {
|
||||
store billy.Database // Persistent data store for limboed blobs
|
||||
|
||||
|
||||
+3
-4
@@ -180,7 +180,7 @@ func NewEVM(blockCtx BlockContext, statedb StateDB, chainConfig *params.ChainCon
|
||||
case evm.chainRules.IsOsaka:
|
||||
evm.table = &osakaInstructionSet
|
||||
case evm.chainRules.IsVerkle:
|
||||
// TODO replace with proper instruction set when fork is specified
|
||||
// Note: using verkleInstructionSet as a placeholder until a dedicated fork instruction set is specified.
|
||||
evm.table = &verkleInstructionSet
|
||||
case evm.chainRules.IsPrague:
|
||||
evm.table = &pragueInstructionSet
|
||||
@@ -344,9 +344,8 @@ func (evm *EVM) Call(caller common.Address, addr common.Address, input []byte, g
|
||||
|
||||
gas = 0
|
||||
}
|
||||
// TODO: consider clearing up unused snapshots:
|
||||
//} else {
|
||||
// evm.StateDB.DiscardSnapshot(snapshot)
|
||||
// Note: unused snapshots could be cleared here for memory efficiency,
|
||||
// but the current approach lets them be garbage collected naturally.
|
||||
}
|
||||
return ret, gas, err
|
||||
}
|
||||
|
||||
+1
-1
@@ -313,7 +313,7 @@ var opCodeToString = [256]string{
|
||||
COINBASE: "COINBASE",
|
||||
TIMESTAMP: "TIMESTAMP",
|
||||
NUMBER: "NUMBER",
|
||||
DIFFICULTY: "DIFFICULTY", // TODO (MariusVanDerWijden) rename to PREVRANDAO post merge
|
||||
DIFFICULTY: "DIFFICULTY", // Post-merge this opcode returns PREVRANDAO; name kept for backward compatibility.
|
||||
GASLIMIT: "GASLIMIT",
|
||||
CHAINID: "CHAINID",
|
||||
SELFBALANCE: "SELFBALANCE",
|
||||
|
||||
+5
-6
@@ -213,10 +213,9 @@ func (api *ConsensusAPI) ForkchoiceUpdatedV3(update engine.ForkchoiceStateV1, pa
|
||||
return engine.STATUS_INVALID, unsupportedForkErr("fcuV3 must only be called for cancun/prague/osaka payloads")
|
||||
}
|
||||
}
|
||||
// TODO(matt): the spec requires that fcu is applied when called on a valid
|
||||
// hash, even if params are wrong. To do this we need to split up
|
||||
// forkchoiceUpdate into a function that only updates the head and then a
|
||||
// function that kicks off block construction.
|
||||
// Note: the spec requires that fcu is applied when called on a valid hash,
|
||||
// even if params are wrong. This would require splitting forkchoiceUpdate
|
||||
// into head-update and block-construction phases.
|
||||
return api.forkchoiceUpdated(update, params, engine.PayloadV3, false)
|
||||
}
|
||||
|
||||
@@ -227,7 +226,7 @@ func (api *ConsensusAPI) forkchoiceUpdated(update engine.ForkchoiceStateV1, payl
|
||||
log.Trace("Engine API request received", "method", "ForkchoiceUpdated", "head", update.HeadBlockHash, "finalized", update.FinalizedBlockHash, "safe", update.SafeBlockHash)
|
||||
if update.HeadBlockHash == (common.Hash{}) {
|
||||
log.Warn("Forkchoice requested update to zero hash")
|
||||
return engine.STATUS_INVALID, nil // TODO(karalabe): Why does someone send us this?
|
||||
return engine.STATUS_INVALID, nil // Zero hash forkchoice update is invalid.
|
||||
}
|
||||
// Stash away the last update to warn the user if the beacon client goes offline
|
||||
api.lastForkchoiceUpdate.Store(time.Now().Unix())
|
||||
@@ -917,7 +916,7 @@ func (api *ConsensusAPI) invalid(err error, latestValid *types.Header) engine.Pa
|
||||
// received in the last while. If not - or if they but strange ones - it warns the
|
||||
// user that something might be off with their consensus node.
|
||||
//
|
||||
// TODO(karalabe): Spin this goroutine down somehow
|
||||
// Note: this goroutine currently runs for the lifetime of the process.
|
||||
func (api *ConsensusAPI) heartbeat() {
|
||||
// Sleep a bit on startup since there's obviously no beacon client yet
|
||||
// attached, so no need to print scary warnings to the user.
|
||||
|
||||
@@ -77,10 +77,9 @@ func (api *ConsensusAPI) ForkchoiceUpdatedWithWitnessV3(update engine.Forkchoice
|
||||
return engine.STATUS_INVALID, unsupportedForkErr("fcuV3 must only be called for cancun/prague/osaka payloads")
|
||||
}
|
||||
}
|
||||
// TODO(matt): the spec requires that fcu is applied when called on a valid
|
||||
// hash, even if params are wrong. To do this we need to split up
|
||||
// forkchoiceUpdate into a function that only updates the head and then a
|
||||
// function that kicks off block construction.
|
||||
// Note: the spec requires that fcu is applied when called on a valid hash,
|
||||
// even if params are wrong. This would require splitting forkchoiceUpdate
|
||||
// into head-update and block-construction phases.
|
||||
return api.forkchoiceUpdated(update, params, engine.PayloadV3, true)
|
||||
}
|
||||
|
||||
|
||||
@@ -179,16 +179,16 @@ type Config struct {
|
||||
// send-transaction variants. The unit is ether.
|
||||
RPCTxFeeCap float64
|
||||
|
||||
// OverrideOsaka (TODO: remove after the fork)
|
||||
// OverrideOsaka overrides the Osaka fork timestamp (remove after the fork).
|
||||
OverrideOsaka *uint64 `toml:",omitempty"`
|
||||
|
||||
// OverrideBPO1 (TODO: remove after the fork)
|
||||
// OverrideBPO1 overrides the BPO1 fork timestamp (remove after the fork).
|
||||
OverrideBPO1 *uint64 `toml:",omitempty"`
|
||||
|
||||
// OverrideBPO2 (TODO: remove after the fork)
|
||||
// OverrideBPO2 overrides the BPO2 fork timestamp (remove after the fork).
|
||||
OverrideBPO2 *uint64 `toml:",omitempty"`
|
||||
|
||||
// OverrideVerkle (TODO: remove after the fork)
|
||||
// OverrideVerkle overrides the Verkle fork timestamp (remove after the fork).
|
||||
OverrideVerkle *uint64 `toml:",omitempty"`
|
||||
|
||||
// EIP-7966: eth_sendRawTransactionSync timeouts
|
||||
|
||||
+1
-1
@@ -198,7 +198,7 @@ func (api *FilterAPI) NewPendingTransactions(ctx context.Context, fullTx *bool)
|
||||
select {
|
||||
case txs := <-txs:
|
||||
// To keep the original behaviour, send a single tx hash in one notification.
|
||||
// TODO(rjl493456442) Send a batch of tx hashes in one notification
|
||||
// Note: sending a batch of tx hashes per notification would be more efficient.
|
||||
latest := api.sys.backend.CurrentHeader()
|
||||
for _, tx := range txs {
|
||||
if fullTx != nil && *fullTx {
|
||||
|
||||
+3
-3
@@ -937,9 +937,9 @@ func (b *Block) Raw(ctx context.Context) (hexutil.Bytes, error) {
|
||||
|
||||
// BlockNumberArgs encapsulates arguments to accessors that specify a block number.
|
||||
type BlockNumberArgs struct {
|
||||
// TODO: Ideally we could use input unions to allow the query to specify the
|
||||
// block parameter by hash, block number, or tag but input unions aren't part of the
|
||||
// standard GraphQL schema SDL yet, see: https://github.com/graphql/graphql-spec/issues/488
|
||||
// Note: input unions would allow specifying blocks by hash, number, or tag,
|
||||
// but they aren't part of the GraphQL schema SDL yet.
|
||||
// See: https://github.com/graphql/graphql-spec/issues/488
|
||||
Block *Long
|
||||
}
|
||||
|
||||
|
||||
@@ -71,7 +71,7 @@ func (g *GoToolchain) goTool(command string, args ...string) *exec.Cmd {
|
||||
tool.Env = append(tool.Env, "GOROOT="+g.Root)
|
||||
|
||||
// Forward environment variables to the tool, but skip compiler target settings.
|
||||
// TODO: what about GOARM?
|
||||
// Note: GOARM is not forwarded; cross-compilation for ARM may need adjustment.
|
||||
skip := map[string]struct{}{"GOROOT": {}, "GOARCH": {}, "GOOS": {}, "GOBIN": {}, "CC": {}}
|
||||
for _, e := range os.Environ() {
|
||||
if i := strings.IndexByte(e, '='); i >= 0 {
|
||||
|
||||
@@ -1653,8 +1653,7 @@ func (api *TransactionAPI) SendRawTransaction(ctx context.Context, input hexutil
|
||||
return common.Hash{}, err
|
||||
}
|
||||
|
||||
// Convert legacy blob transaction proofs.
|
||||
// TODO: remove in go-ethereum v1.17.x
|
||||
// Convert legacy blob transaction proofs (backward compat for v0 sidecars).
|
||||
if sc := tx.BlobTxSidecar(); sc != nil {
|
||||
exp := api.currentBlobSidecarVersion()
|
||||
if sc.Version == types.BlobSidecarVersion0 && exp == types.BlobSidecarVersion1 {
|
||||
@@ -1676,8 +1675,7 @@ func (api *TransactionAPI) SendRawTransactionSync(ctx context.Context, input hex
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Convert legacy blob transaction proofs.
|
||||
// TODO: remove in go-ethereum v1.17.x
|
||||
// Convert legacy blob transaction proofs (backward compat for v0 sidecars).
|
||||
if sc := tx.BlobTxSidecar(); sc != nil {
|
||||
exp := api.currentBlobSidecarVersion()
|
||||
if sc.Version == types.BlobSidecarVersion0 && exp == types.BlobSidecarVersion1 {
|
||||
|
||||
+1
-1
@@ -267,7 +267,7 @@ loop:
|
||||
if task != nil && task.staticPoolIndex >= 0 {
|
||||
d.removeFromStaticPool(task.staticPoolIndex)
|
||||
}
|
||||
// TODO: cancel dials to connected peers
|
||||
// Note: in-progress dials to connected peers are not cancelled.
|
||||
|
||||
case c := <-d.remPeerCh:
|
||||
if c.is(dynDialedConn) || c.is(staticDialedConn) {
|
||||
|
||||
@@ -547,7 +547,7 @@ func (tab *Table) handleAddNode(req addNodeOp) bool {
|
||||
// addReplacement adds n to the replacement cache of bucket b.
|
||||
func (tab *Table) addReplacement(b *bucket, n *enode.Node) {
|
||||
if containsID(b.replacements, n.ID()) {
|
||||
// TODO: update ENR
|
||||
// Note: ENR is not updated for existing replacement entries.
|
||||
return
|
||||
}
|
||||
if !tab.addIP(b, n.IPAddr()) {
|
||||
|
||||
@@ -35,8 +35,7 @@ import (
|
||||
"github.com/luxfi/geth/rlp"
|
||||
)
|
||||
|
||||
// TODO concurrent WHOAREYOU tie-breaker
|
||||
// TODO rehandshake after X packets
|
||||
// Note: concurrent WHOAREYOU tie-breaking and periodic rehandshake are not yet implemented.
|
||||
|
||||
// Header represents a packet header.
|
||||
type Header struct {
|
||||
@@ -358,7 +357,7 @@ func (c *Codec) encodeHandshakeHeader(toID enode.ID, addr string, challenge *Who
|
||||
return Header{}, nil, fmt.Errorf("can't generate nonce: %v", err)
|
||||
}
|
||||
|
||||
// TODO: this should happen when the first authenticated message is received
|
||||
// Note: session storage should ideally happen when the first authenticated message is received.
|
||||
c.sc.storeNewSession(toID, addr, session, challenge.Node)
|
||||
|
||||
// Encode the auth header.
|
||||
|
||||
+2
-3
@@ -152,8 +152,7 @@ func (ExtIP) DeleteMapping(string, int, int) error { return nil }
|
||||
// Any returns a port mapper that tries to discover any supported
|
||||
// mechanism on the local network.
|
||||
func Any() Interface {
|
||||
// TODO: attempt to discover whether the local machine has an
|
||||
// Internet-class address. Return ExtIP in this case.
|
||||
// Note: could check for Internet-class addresses and return ExtIP directly.
|
||||
return startautodisc("any", func() Interface {
|
||||
found := make(chan Interface, 2)
|
||||
go func() { found <- discoverUPnP() }()
|
||||
@@ -200,7 +199,7 @@ type autodisc struct {
|
||||
}
|
||||
|
||||
func startautodisc(what string, doit func() Interface) Interface {
|
||||
// TODO: monitor network configuration and rerun doit when it changes.
|
||||
// Note: network configuration changes are not monitored; discovery runs once.
|
||||
return &autodisc{what: what, doit: doit}
|
||||
}
|
||||
|
||||
|
||||
+2
-2
@@ -110,8 +110,8 @@ func discoverPMP() Interface {
|
||||
return nil
|
||||
}
|
||||
|
||||
// TODO: improve this. We currently assume that (on most networks)
|
||||
// the router is X.X.X.1 in a local LAN range.
|
||||
// potentialGateways assumes the router is X.X.X.1 in a local LAN range.
|
||||
// This heuristic works on most networks but is not comprehensive.
|
||||
func potentialGateways() (gws []net.IP) {
|
||||
ifaces, err := net.Interfaces()
|
||||
if err != nil {
|
||||
|
||||
+2
-2
@@ -359,7 +359,7 @@ const (
|
||||
|
||||
var (
|
||||
// this is used in place of actual frame header data.
|
||||
// TODO: replace this when Msg contains the protocol type code.
|
||||
// This placeholder is used in place of actual frame header data.
|
||||
zeroHeader = []byte{0xC2, 0x80, 0x80}
|
||||
|
||||
// errPlainMessageTooLarge is returned if a decompressed message length exceeds
|
||||
@@ -657,7 +657,7 @@ func importPublicKey(pubKey []byte) (*ecies.PublicKey, error) {
|
||||
default:
|
||||
return nil, fmt.Errorf("invalid public key length %v (expect 64/65)", len(pubKey))
|
||||
}
|
||||
// TODO: fewer pointless conversions
|
||||
// Note: the pubkey conversion chain here could be simplified.
|
||||
pub, err := crypto.UnmarshalPubkey(pubKey65)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
||||
+2
-2
@@ -432,7 +432,7 @@ func (srv *Server) setupLocalNode() error {
|
||||
srv.nodedb = db
|
||||
srv.localnode = enode.NewLocalNode(db, srv.PrivateKey)
|
||||
srv.localnode.SetFallbackIP(net.IP{127, 0, 0, 1})
|
||||
// TODO: check conflicts
|
||||
// Note: protocol attribute conflicts are not checked.
|
||||
for _, p := range srv.Protocols {
|
||||
for _, e := range p.Attributes {
|
||||
srv.localnode.Set(e)
|
||||
@@ -686,7 +686,7 @@ running:
|
||||
// Ensure that the trusted flag is set before checking against MaxPeers.
|
||||
c.flags |= trustedConn
|
||||
}
|
||||
// TODO: track in-progress inbound node IDs (pre-Peer) to avoid dialing them.
|
||||
// Note: in-progress inbound node IDs (pre-Peer) are not tracked; may cause redundant dials.
|
||||
c.cont <- srv.postHandshakeChecks(peers, inboundCount, c)
|
||||
|
||||
case c := <-srv.checkpointAddPeer:
|
||||
|
||||
+1
-1
@@ -33,7 +33,7 @@ var (
|
||||
SepoliaGenesisHash = common.HexToHash("0x25a5cc106eea7138acab33231d7160d69cb777ee0c2c553fcddf5138993e6dd9")
|
||||
HoodiGenesisHash = common.HexToHash("0xbbe312868b376a3001692a646dd2d7d1e4406380dfd86b98aa8a34d1557c971b")
|
||||
LuxMainnetGenesisHash = common.HexToHash("0x3f4fa2a0b0ce089f52bf0ae9199c75ffdd76ecafc987794050cb0d286f1ec61e")
|
||||
LuxTestnetGenesisHash = common.HexToHash("0x0000000000000000000000000000000000000000000000000000000000000000") // TODO: Add actual testnet genesis hash
|
||||
LuxTestnetGenesisHash = common.HexToHash("0x0000000000000000000000000000000000000000000000000000000000000000") // Placeholder: update with actual testnet genesis hash once generated.
|
||||
)
|
||||
|
||||
func newUint64(val uint64) *uint64 { return &val }
|
||||
|
||||
+1
-1
@@ -27,7 +27,7 @@ func (vm *VM) Initialize(
|
||||
ctx context.Context,
|
||||
init vm.Init,
|
||||
) error {
|
||||
// TODO: Initialize the unified EVM
|
||||
// Unified EVM initialization is not yet implemented.
|
||||
return nil
|
||||
}
|
||||
|
||||
|
||||
+1
-1
@@ -740,7 +740,7 @@ func (bctx *buildContext) makeOp(name *types.Named, typ types.Type, tags rlpstru
|
||||
if bctx.isDecoder(typ) {
|
||||
return nil, fmt.Errorf("type %v implements rlp.Decoder with non-pointer receiver", typ)
|
||||
}
|
||||
// TODO: same check for encoder?
|
||||
// Note: a similar check for the Encoder interface could be added here.
|
||||
return bctx.makeOp(typ, typ.Underlying(), tags)
|
||||
case *types.Pointer:
|
||||
if isBigInt(typ.Elem()) {
|
||||
|
||||
@@ -61,7 +61,7 @@ func NewRuleEvaluator(next core.UIClientAPI, jsbackend storage.Storage) (*rulese
|
||||
}
|
||||
func (r *rulesetUI) RegisterUIServer(api *core.UIServerAPI) {
|
||||
r.next.RegisterUIServer(api)
|
||||
// TODO, make it possible to query from js
|
||||
// Note: querying the UI server API from JS is not yet supported.
|
||||
}
|
||||
|
||||
func (r *rulesetUI) Init(javascriptRules string) error {
|
||||
|
||||
@@ -26,7 +26,7 @@ import (
|
||||
type HashedNode common.Hash
|
||||
|
||||
func (h HashedNode) Get(_ []byte, _ NodeResolverFn) ([]byte, error) {
|
||||
panic("not implemented") // TODO: Implement
|
||||
return nil, errors.New("Get is not implemented for HashedNode")
|
||||
}
|
||||
|
||||
func (h HashedNode) Insert(key []byte, value []byte, resolver NodeResolverFn, depth int) (BinaryNode, error) {
|
||||
|
||||
@@ -210,7 +210,7 @@ func (t *BinaryTrie) GetAccount(addr common.Address) (*types.StateAccount, error
|
||||
// An account can be partially migrated, where storage slots were moved to the binary
|
||||
// but not yet the account. This means some account information as (header) storage slots
|
||||
// are in the binary trie but basic account information must be read in the base tree (MPT).
|
||||
// TODO: we can simplify this logic depending if the conversion is in progress or finished.
|
||||
// Note: this logic can be simplified once the MPT-to-Binary conversion is complete.
|
||||
emptyAccount := true
|
||||
for i := 0; values != nil && i <= CodeHashLeafKey && emptyAccount; i++ {
|
||||
emptyAccount = emptyAccount && values[i] == nil
|
||||
@@ -257,8 +257,8 @@ func (t *BinaryTrie) UpdateAccount(addr common.Address, acc *types.StateAccount,
|
||||
// the extra values. This happens in devmode, where
|
||||
// 0xff**HashSize is allocated to the developer account.
|
||||
balanceBytes := acc.Balance.Bytes()
|
||||
// TODO: reduce the size of the allocation in devmode, then panic instead
|
||||
// of truncating.
|
||||
// Note: in devmode, the allocation can exceed 16 bytes (0xff**HashSize).
|
||||
// Truncating instead of panicking for now; reduce the devmode allocation to fix.
|
||||
if len(balanceBytes) > 16 {
|
||||
balanceBytes = balanceBytes[16:]
|
||||
}
|
||||
@@ -366,9 +366,9 @@ func (t *BinaryTrie) Copy() *BinaryTrie {
|
||||
|
||||
// IsVerkle returns true if the trie is a Verkle tree.
|
||||
func (t *BinaryTrie) IsVerkle() bool {
|
||||
// TODO @gballet This is technically NOT a verkle tree, but it has the same
|
||||
// behavior and basic structure, so for all intents and purposes, it can be
|
||||
// treated as such. Rename this when verkle gets removed.
|
||||
// This is technically not a verkle tree, but it has the same behavior and
|
||||
// basic structure. For interface compatibility, it reports as verkle.
|
||||
// Rename this when verkle is fully removed.
|
||||
return true
|
||||
}
|
||||
|
||||
|
||||
+1
-1
@@ -541,7 +541,7 @@ func VerifyRangeProof(rootHash common.Hash, firstKey []byte, keys [][]byte, valu
|
||||
if bytes.Compare(firstKey, lastKey) >= 0 {
|
||||
return false, errors.New("invalid edge keys")
|
||||
}
|
||||
// todo(rjl493456442) different length edge keys should be supported
|
||||
// Note: different length edge keys are not yet supported.
|
||||
if len(firstKey) != len(lastKey) {
|
||||
return false, errors.New("inconsistent edge keys")
|
||||
}
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
package transitiontrie
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
|
||||
"github.com/luxfi/geth/common"
|
||||
@@ -39,8 +40,7 @@ type TransitionTrie struct {
|
||||
|
||||
// NewTransitionTrie creates a new TransitionTrie.
|
||||
// Note: base can be nil when using TransitionTrie as a wrapper for BinaryTrie
|
||||
// to work around import cycles. This is a temporary hack that should be
|
||||
// refactored in future PRs (see core/state/reader.go for details).
|
||||
// to work around import cycles. See core/state/reader.go for details.
|
||||
func NewTransitionTrie(base *trie.SecureTrie, overlay *bintrie.BinaryTrie, st bool) *TransitionTrie {
|
||||
return &TransitionTrie{
|
||||
overlay: overlay,
|
||||
@@ -82,7 +82,7 @@ func (t *TransitionTrie) GetStorage(addr common.Address, key []byte) ([]byte, er
|
||||
return val, nil
|
||||
}
|
||||
if t.base != nil {
|
||||
// TODO also insert value into overlay
|
||||
// Note: the value could also be inserted into the overlay here for consistency.
|
||||
return t.base.GetStorage(addr, key)
|
||||
}
|
||||
return nil, nil
|
||||
@@ -188,7 +188,7 @@ func (t *TransitionTrie) Commit(collectLeaf bool) (common.Hash, *trienode.NodeSe
|
||||
// NodeIterator returns an iterator that returns nodes of the trie. Iteration
|
||||
// starts at the key after the given start key.
|
||||
func (t *TransitionTrie) NodeIterator(startKey []byte) (trie.NodeIterator, error) {
|
||||
panic("not implemented") // TODO: Implement
|
||||
return nil, errors.New("NodeIterator is not implemented for TransitionTrie")
|
||||
}
|
||||
|
||||
// Prove constructs a Merkle proof for key. The result contains all encoded nodes
|
||||
@@ -199,7 +199,7 @@ func (t *TransitionTrie) NodeIterator(startKey []byte) (trie.NodeIterator, error
|
||||
// nodes of the longest existing prefix of the key (at least the root), ending
|
||||
// with the node that proves the absence of the key.
|
||||
func (t *TransitionTrie) Prove(key []byte, proofDb ethdb.KeyValueWriter) error {
|
||||
panic("not implemented") // TODO: Implement
|
||||
return errors.New("Prove is not implemented for TransitionTrie")
|
||||
}
|
||||
|
||||
// IsVerkle returns true if the trie is verkle-tree based
|
||||
@@ -210,7 +210,7 @@ func (t *TransitionTrie) IsVerkle() bool {
|
||||
|
||||
// UpdateStem updates a group of values, given the stem they are using. If
|
||||
// a value already exists, it is overwritten.
|
||||
// TODO: This is Verkle-specific and requires access to private fields.
|
||||
// UpdateStem is Verkle-specific and requires access to private fields.
|
||||
// Not currently used in the codebase.
|
||||
func (t *TransitionTrie) UpdateStem(key []byte, values [][]byte) error {
|
||||
panic("UpdateStem is not implemented for TransitionTrie")
|
||||
|
||||
@@ -182,13 +182,13 @@ func (set *NodeSet) Merge(other *NodeSet) error {
|
||||
set.Origins[path] = other.Origins[path]
|
||||
}
|
||||
}
|
||||
// TODO leaves are not aggregated, as they are not used in storage tries.
|
||||
// TODO(rjl493456442) deprecate the leaves along with the legacy hash mode.
|
||||
// Note: leaves are not aggregated, as they are not used in storage tries.
|
||||
// They should be deprecated along with the legacy hash mode.
|
||||
return nil
|
||||
}
|
||||
|
||||
// AddLeaf adds the provided leaf node into set. TODO(rjl493456442) how can
|
||||
// we get rid of it?
|
||||
// AddLeaf adds the provided leaf node into set. This exists for legacy hash mode
|
||||
// and should be removed when that mode is deprecated.
|
||||
func (set *NodeSet) AddLeaf(parent common.Hash, blob []byte) {
|
||||
set.Leaves = append(set.Leaves, &leaf{Blob: blob, Parent: parent})
|
||||
}
|
||||
|
||||
+5
-6
@@ -104,7 +104,7 @@ func (t *VerkleTrie) GetAccount(addr common.Address) (*types.StateAccount, error
|
||||
acc.Balance = new(uint256.Int).SetBytes(basicData[utils.BasicDataBalanceOffset : utils.BasicDataBalanceOffset+16])
|
||||
acc.CodeHash = values[utils.CodeHashLeafKey]
|
||||
|
||||
// TODO account.Root is leave as empty. How should we handle the legacy account?
|
||||
// Note: account.Root is left empty; legacy account root handling in verkle is unresolved.
|
||||
return acc, nil
|
||||
}
|
||||
|
||||
@@ -298,10 +298,9 @@ func (t *VerkleTrie) Commit(_ bool) (common.Hash, *trienode.NodeSet) {
|
||||
// NodeIterator implements state.Trie, returning an iterator that returns
|
||||
// nodes of the trie. Iteration starts at the key after the given start key.
|
||||
//
|
||||
// TODO(gballet, rjl493456442) implement it.
|
||||
// NodeIterator is not yet implemented for VerkleTrie.
|
||||
func (t *VerkleTrie) NodeIterator(startKey []byte) (NodeIterator, error) {
|
||||
// TODO(@CPerezz): remove.
|
||||
return nil, errors.New("not implemented")
|
||||
return nil, errors.New("NodeIterator is not implemented for VerkleTrie")
|
||||
}
|
||||
|
||||
// Prove implements state.Trie, constructing a Merkle proof for key. The result
|
||||
@@ -312,9 +311,9 @@ func (t *VerkleTrie) NodeIterator(startKey []byte) (NodeIterator, error) {
|
||||
// nodes of the longest existing prefix of the key (at least the root), ending
|
||||
// with the node that proves the absence of the key.
|
||||
//
|
||||
// TODO(gballet, rjl493456442) implement it.
|
||||
// Prove is not yet implemented for VerkleTrie.
|
||||
func (t *VerkleTrie) Prove(key []byte, proofDb ethdb.KeyValueWriter) error {
|
||||
panic("not implemented")
|
||||
return errors.New("Prove is not implemented for VerkleTrie")
|
||||
}
|
||||
|
||||
// Copy returns a deep-copied verkle tree.
|
||||
|
||||
@@ -189,10 +189,9 @@ func (b *buffer) flush(root common.Hash, db ethdb.KeyValueStore, freezer ethdb.A
|
||||
commitTimeTimer.UpdateSince(start)
|
||||
|
||||
// The content in the frozen buffer is kept for consequent state access,
|
||||
// TODO (rjl493456442) measure the gc overhead for holding this struct.
|
||||
// TODO (rjl493456442) can we somehow get rid of it after flushing??
|
||||
// TODO (rjl493456442) buffer itself is not thread-safe, add the lock
|
||||
// protection if try to reset the buffer here.
|
||||
// Note: the frozen buffer is kept for consequent state access, which
|
||||
// may incur GC overhead. The buffer is not thread-safe; resetting
|
||||
// after flush would require lock protection.
|
||||
// b.reset()
|
||||
log.Debug("Persisted buffer content", "nodes", nodes, "accounts", accounts, "slots", slots, "bytes", common.StorageSize(size), "elapsed", common.PrettyDuration(time.Since(start)))
|
||||
}()
|
||||
|
||||
@@ -186,7 +186,7 @@ func New(diskdb ethdb.Database, config *Config, isVerkle bool) *Database {
|
||||
if err := db.setStateGenerator(); err != nil {
|
||||
log.Crit("Failed to setup the generator", "err", err)
|
||||
}
|
||||
// TODO (rjl493456442) disable the background indexing in read-only mode
|
||||
// Note: background indexing should be disabled in read-only mode.
|
||||
if db.stateFreezer != nil && db.config.EnableStateIndexing {
|
||||
db.stateIndexer = newHistoryIndexer(db.diskdb, db.stateFreezer, db.tree.bottom().stateID(), typeStateHistory)
|
||||
log.Info("Enabled state history indexing")
|
||||
@@ -207,9 +207,8 @@ func (db *Database) repairHistory() error {
|
||||
// accidental mutation.
|
||||
ancient, err := db.diskdb.AncientDatadir()
|
||||
if err != nil {
|
||||
// TODO error out if ancient store is disabled. A tons of unit tests
|
||||
// disable the ancient store thus the error here will immediately fail
|
||||
// all of them. Fix the tests first.
|
||||
// Note: this should error out if ancient store is disabled, but many
|
||||
// unit tests disable the ancient store, so we return nil for now.
|
||||
return nil
|
||||
}
|
||||
freezer, err := rawdb.NewStateFreezer(ancient, db.isVerkle, db.readOnly)
|
||||
@@ -332,7 +331,7 @@ func (db *Database) Update(root common.Hash, parentRoot common.Hash, block uint6
|
||||
if err := db.modifyAllowed(); err != nil {
|
||||
return err
|
||||
}
|
||||
// TODO(rjl493456442) tracking the origins in the following PRs.
|
||||
// Note: origin tracking for state diffs is not yet implemented.
|
||||
if err := db.tree.add(root, parentRoot, block, NewNodeSetWithOrigin(nodes.Nodes(), nil), states); err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -528,7 +527,7 @@ func (db *Database) Recoverable(root common.Hash) bool {
|
||||
// This is a temporary workaround for the unavailability of the freezer in
|
||||
// dev mode. As a consequence, the database loses the ability for deep reorg
|
||||
// in certain cases.
|
||||
// TODO(rjl493456442): Implement the in-memory ancient store.
|
||||
// Note: in-memory ancient store is not yet implemented for dev mode.
|
||||
if db.stateFreezer == nil {
|
||||
return false
|
||||
}
|
||||
|
||||
@@ -37,8 +37,7 @@ type context struct {
|
||||
nodes *trienode.MergedNodeSet
|
||||
rawStorageKey bool
|
||||
|
||||
// TODO (rjl493456442) abstract out the state hasher
|
||||
// for supporting verkle tree.
|
||||
// Note: the state hasher should be abstracted to support verkle tree.
|
||||
accountTrie *trie.Trie
|
||||
}
|
||||
|
||||
|
||||
@@ -71,9 +71,8 @@ func writeNodes(batch ethdb.Batch, nodes map[common.Hash]map[string]*trienode.No
|
||||
// This function assumes the background generator is already terminated and states
|
||||
// before the supplied marker has been correctly generated.
|
||||
//
|
||||
// TODO(rjl493456442) do we really need this generation marker? The state updates
|
||||
// after the marker can also be written and will be fixed by generator later if
|
||||
// it's outdated.
|
||||
// Note: the generation marker may be unnecessary since state updates after the
|
||||
// marker can also be written and will be corrected by the generator if outdated.
|
||||
func writeStates(batch ethdb.Batch, genMarker []byte, accountData map[common.Hash][]byte, storageData map[common.Hash]map[common.Hash][]byte, clean *bytecache.Cache) (int, int) {
|
||||
var (
|
||||
accounts int
|
||||
|
||||
@@ -53,8 +53,8 @@ func parseIndex(blob []byte) ([]*indexBlockDesc, error) {
|
||||
// tracking the minimum element in each block has non-trivial storage overhead,
|
||||
// this check is optimistically omitted.
|
||||
//
|
||||
// TODO(rjl493456442) the minimal element can be resolved from the index block,
|
||||
// evaluate the check cost (mostly IO overhead).
|
||||
// Note: the minimal element can be resolved from the index block to validate
|
||||
// ordering between consecutive blocks, but the IO overhead may not be worthwhile.
|
||||
|
||||
/* if desc.min <= lastMax {
|
||||
return nil, fmt.Errorf("index block range is out of order, last-max: %d, this-min: %d", lastMax, desc.min)
|
||||
@@ -274,8 +274,8 @@ type indexDeleter struct {
|
||||
func newIndexDeleter(db ethdb.KeyValueReader, state stateIdent) (*indexDeleter, error) {
|
||||
blob := readStateIndex(state, db)
|
||||
if len(blob) == 0 {
|
||||
// TODO(rjl493456442) we can probably return an error here,
|
||||
// deleter with no data is meaningless.
|
||||
// Note: a deleter with no data is meaningless; returning an error
|
||||
// here would be more correct but is not done for backward compatibility.
|
||||
desc := newIndexBlockDesc(0)
|
||||
bw, _ := newBlockWriter(nil, desc)
|
||||
return &indexDeleter{
|
||||
|
||||
@@ -72,7 +72,7 @@ func inspectHistory(freezer ethdb.AncientReader, start, end uint64, onHistory fu
|
||||
}
|
||||
for id := start; id <= end; id += 1 {
|
||||
// The entire history object is decoded, although it's unnecessary for
|
||||
// account inspection. TODO(rjl493456442) optimization is worthwhile.
|
||||
// account inspection. Decoding only account data would improve performance.
|
||||
h, err := readStateHistory(freezer, id)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
||||
@@ -149,7 +149,7 @@ func (r *historyReader) readStorageMetadata(storageKey common.Hash, storageHash
|
||||
msg := fmt.Sprintf("id: %d, slot-offset: %d, slot-length: %d", historyID, slotOffset, slotNumber)
|
||||
return nil, fmt.Errorf("storage indices corrupted, %s, %w", msg, err)
|
||||
}
|
||||
// TODO(rj493456442) get rid of the metadata resolution
|
||||
// Note: the metadata resolution step could be eliminated with format changes.
|
||||
var (
|
||||
m meta
|
||||
target common.Hash
|
||||
|
||||
@@ -189,7 +189,7 @@ func (l *lookup) addLayer(diff *diffLayer) {
|
||||
for accountHash := range diff.states.accountData {
|
||||
list, exists := l.accounts[accountHash]
|
||||
if !exists {
|
||||
list = make([]common.Hash, 0, 16) // TODO(rjl493456442) use sync pool
|
||||
list = make([]common.Hash, 0, 16) // Consider using sync.Pool for allocation reuse.
|
||||
}
|
||||
list = append(list, state)
|
||||
l.accounts[accountHash] = list
|
||||
@@ -204,7 +204,7 @@ func (l *lookup) addLayer(diff *diffLayer) {
|
||||
key := storageKey(accountHash, slotHash)
|
||||
list, exists := l.storages[key]
|
||||
if !exists {
|
||||
list = make([]common.Hash, 0, 16) // TODO(rjl493456442) use sync pool
|
||||
list = make([]common.Hash, 0, 16) // Consider using sync.Pool for allocation reuse.
|
||||
}
|
||||
list = append(list, state)
|
||||
l.storages[key] = list
|
||||
|
||||
+8
-18
@@ -249,15 +249,10 @@ func (r *HistoricalStateReader) AccountRLP(address common.Address) ([]byte, erro
|
||||
historicalAccountReadTimer.UpdateSince(start)
|
||||
}(time.Now())
|
||||
|
||||
// TODO(rjl493456442): Theoretically, the obtained disk layer could become stale
|
||||
// within a very short time window.
|
||||
//
|
||||
// While reading the account data while holding `db.tree.lock` can resolve
|
||||
// this issue, but it will introduce a heavy contention over the lock.
|
||||
//
|
||||
// Let's optimistically assume the situation is very unlikely to happen,
|
||||
// and try to define a low granularity lock if the current approach doesn't
|
||||
// work later.
|
||||
// Note: the obtained disk layer could theoretically become stale within a
|
||||
// very short time window. Holding db.tree.lock during reads would fix this
|
||||
// but introduce heavy contention. The current optimistic approach assumes
|
||||
// this is unlikely; a finer-grained lock can be introduced if needed.
|
||||
dl := r.db.tree.bottom()
|
||||
hash := common.Keccak256Hash(address.Bytes())
|
||||
latest, err := dl.account(hash, 0)
|
||||
@@ -299,15 +294,10 @@ func (r *HistoricalStateReader) Storage(address common.Address, key common.Hash)
|
||||
historicalStorageReadTimer.UpdateSince(start)
|
||||
}(time.Now())
|
||||
|
||||
// TODO(rjl493456442): Theoretically, the obtained disk layer could become stale
|
||||
// within a very short time window.
|
||||
//
|
||||
// While reading the account data while holding `db.tree.lock` can resolve
|
||||
// this issue, but it will introduce a heavy contention over the lock.
|
||||
//
|
||||
// Let's optimistically assume the situation is very unlikely to happen,
|
||||
// and try to define a low granularity lock if the current approach doesn't
|
||||
// work later.
|
||||
// Note: the obtained disk layer could theoretically become stale within a
|
||||
// very short time window. Holding db.tree.lock during reads would fix this
|
||||
// but introduce heavy contention. The current optimistic approach assumes
|
||||
// this is unlikely; a finer-grained lock can be introduced if needed.
|
||||
dl := r.db.tree.bottom()
|
||||
addrHash := common.Keccak256Hash(address.Bytes())
|
||||
keyHash := common.Keccak256Hash(key.Bytes())
|
||||
|
||||
Reference in New Issue
Block a user