core: add extra db table for code size

Co-authored-by: lightclient <lightclient@proton.com>
Co-authored-by: Qi Zhou <qizhou@ethstorage.io>
This commit is contained in:
lightclient 2025-06-10 13:53:47 +02:00
parent 1dc22c64ec
commit d92543bdc2
No known key found for this signature in database
GPG key ID: 657913021EF45A6A
3 changed files with 28 additions and 1 deletions

View file

@ -65,6 +65,16 @@ func ReadCodeWithPrefix(db ethdb.KeyValueReader, hash common.Hash) []byte {
return data return data
} }
// ReadCodeWithPrefix retrieves the contract code of the provided code hash.
// Return -1 if not found for legacy db.
func ReadCodeSizeWithPrefix(db ethdb.KeyValueReader, hash common.Hash) int {
data, _ := db.Get(codeSizeKey(hash))
if len(data) != 4 {
return -1
}
return int(binary.BigEndian.Uint32(data))
}
// HasCode checks if the contract code corresponding to the // HasCode checks if the contract code corresponding to the
// provided code hash is present in the db. // provided code hash is present in the db.
func HasCode(db ethdb.KeyValueReader, hash common.Hash) bool { func HasCode(db ethdb.KeyValueReader, hash common.Hash) bool {
@ -90,12 +100,19 @@ func WriteCode(db ethdb.KeyValueWriter, hash common.Hash, code []byte) {
if err := db.Put(codeKey(hash), code); err != nil { if err := db.Put(codeKey(hash), code); err != nil {
log.Crit("Failed to store contract code", "err", err) log.Crit("Failed to store contract code", "err", err)
} }
var sizeData [4]byte
binary.BigEndian.PutUint32(sizeData[:], uint32(len(code)))
if err := db.Put(codeSizeKey(hash), sizeData[:]); err != nil {
log.Crit("Failed to store contract code size", "err", err)
}
} }
// DeleteCode deletes the specified contract code from the database. // DeleteCode deletes the specified contract code from the database.
func DeleteCode(db ethdb.KeyValueWriter, hash common.Hash) { func DeleteCode(db ethdb.KeyValueWriter, hash common.Hash) {
if err := db.Delete(codeKey(hash)); err != nil { if err := db.Delete(codeKey(hash)); err != nil {
log.Crit("Failed to delete contract code", "err", err) log.Crit("Failed to delete contract code", "err", err)
// Ignore error since the legacy db may not contain the size.
db.Delete(codeSizeKey(hash))
} }
} }

View file

@ -110,6 +110,7 @@ var (
SnapshotAccountPrefix = []byte("a") // SnapshotAccountPrefix + account hash -> account trie value SnapshotAccountPrefix = []byte("a") // SnapshotAccountPrefix + account hash -> account trie value
SnapshotStoragePrefix = []byte("o") // SnapshotStoragePrefix + account hash + storage hash -> storage trie value SnapshotStoragePrefix = []byte("o") // SnapshotStoragePrefix + account hash + storage hash -> storage trie value
CodePrefix = []byte("c") // CodePrefix + code hash -> account code CodePrefix = []byte("c") // CodePrefix + code hash -> account code
CodeSizePrefix = []byte("s") /// CodeSizePrefx + code hash -> code size
skeletonHeaderPrefix = []byte("S") // skeletonHeaderPrefix + num (uint64 big endian) -> header skeletonHeaderPrefix = []byte("S") // skeletonHeaderPrefix + num (uint64 big endian) -> header
// Path-based storage scheme of merkle patricia trie. // Path-based storage scheme of merkle patricia trie.
@ -233,6 +234,11 @@ func codeKey(hash common.Hash) []byte {
return append(CodePrefix, hash.Bytes()...) return append(CodePrefix, hash.Bytes()...)
} }
// codeSizeKey = CodeSizePrefix + hash
func codeSizeKey(hash common.Hash) []byte {
return append(CodeSizePrefix, hash.Bytes()...)
}
// IsCodeKey reports whether the given byte slice is the key of contract code, // IsCodeKey reports whether the given byte slice is the key of contract code,
// if so return the raw code hash as well. // if so return the raw code hash as well.
func IsCodeKey(key []byte) (bool, []byte) { func IsCodeKey(key []byte) (bool, []byte) {

View file

@ -140,7 +140,11 @@ func (r *cachingCodeReader) CodeSize(addr common.Address, codeHash common.Hash)
if cached, ok := r.codeSizeCache.Get(codeHash); ok { if cached, ok := r.codeSizeCache.Get(codeHash); ok {
return cached, nil return cached, nil
} }
codeSize := rawdb.ReadCodeSizeWithPrefix(r.db, codeHash)
if codeSize != -1 {
r.codeSizeCache.Add(codeHash, codeSize)
return codeSize, nil
}
code, err := r.Code(addr, codeHash) code, err := r.Code(addr, codeHash)
if err != nil { if err != nil {
return 0, err return 0, err