Skip to content
Open
Show file tree
Hide file tree
Changes from 13 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 5 additions & 1 deletion sc/memiavl/tree.go
Original file line number Diff line number Diff line change
Expand Up @@ -256,7 +256,11 @@ func (t *Tree) ScanPostOrder(callback func(node Node) bool) {
entry := stack[len(stack)-1]

if entry.node.IsLeaf() || entry.expanded {
callback(entry.node)
continueCallback := callback(entry.node)
if !continueCallback {
fmt.Println("continueCallback: ", continueCallback, ", calling return")
return
}
stack = stack[:len(stack)-1]
continue
}
Expand Down
67 changes: 61 additions & 6 deletions tools/cmd/seidb/operations/state_size.go
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,8 @@
ContractSizes: make(map[string]*utils.ContractSizeEntry),
}

deletedOne := false

// Scan the tree to collect statistics
tree.ScanPostOrder(func(node memiavl.Node) bool {
if node.IsLeaf() {
Expand All @@ -94,23 +96,42 @@

prefixKey := fmt.Sprintf("%X", node.Key())
prefix := prefixKey[:2]
if _, exists := result.PrefixSizes[prefix]; !exists {
result.PrefixSizes[prefix] = &utils.PrefixSize{}
if _, exists := result.PrefixSizes[moduleName]; !exists {
result.PrefixSizes[moduleName] = &utils.PrefixSize{}
}
result.PrefixSizes[prefix].KeySize += uint64(keySize)
result.PrefixSizes[prefix].ValueSize += uint64(valueSize)
result.PrefixSizes[prefix].TotalSize += uint64(keySize + valueSize)
result.PrefixSizes[prefix].KeyCount++
result.PrefixSizes[moduleName].KeySize += uint64(keySize)
result.PrefixSizes[moduleName].ValueSize += uint64(valueSize)
result.PrefixSizes[moduleName].TotalSize += uint64(keySize + valueSize)
result.PrefixSizes[moduleName].KeyCount++

// Handle EVM contract analysis
if moduleName == "evm" && prefix == "03" {
result.TotalEVM03Entries++
if isAllZero(node.Value()) {
result.ZeroedEVM03Entries++
result.ZeroedEVM03KeyBytes += uint64(keySize)
result.ZeroedEVM03ValueBytes += uint64(valueSize)
if !deletedOne {
keyCopy := append([]byte(nil), node.Key()...)
fmt.Printf("Found zeroed EVM 0x03 entry; preparing deletion for key %X\n", keyCopy)
fmt.Printf("Deleting zeroed EVM 0x03 entry with key %X\n", keyCopy)
deletedOne = true
// Remove asynchronously to avoid deadlocking the ScanPostOrder read lock.
go func(key []byte) {
tree.Remove(key)
fmt.Printf("Deleted zeroed EVM 0x03 entry with key %X\n", key)
}(keyCopy)
}
}
addr := prefixKey[2:42]
if _, exists := result.ContractSizes[addr]; !exists {
result.ContractSizes[addr] = &utils.ContractSizeEntry{Address: addr}
}
entry := result.ContractSizes[addr]
entry.TotalSize += uint64(len(node.Key()) + len(node.Value()))
entry.KeyCount++
// fmt.Println("returning false in evm 0x03 prefix")
// return false // quick fail for debugging, remove later
}

if result.TotalNumKeys%1000000 == 0 {
Expand Down Expand Up @@ -162,6 +183,11 @@
TotalSize uint64
PrefixSizes map[string]*utils.PrefixSize
ContractSizes map[string]*utils.ContractSizeEntry
// EVM-specific statistics for 0x03 storage prefix
TotalEVM03Entries uint64
ZeroedEVM03Entries uint64
ZeroedEVM03KeyBytes uint64
ZeroedEVM03ValueBytes uint64
}

// collectAllModuleData scans all modules and collects statistics in memory
Expand Down Expand Up @@ -230,6 +256,10 @@
fmt.Printf("Module %s total numKeys:%d, total keySize:%d, total valueSize:%d, totalSize: %d \n",
result.ModuleName, result.TotalNumKeys, result.TotalKeySize, result.TotalValueSize, result.TotalSize)

fmt.Println("prefix sizes: ", result.PrefixSizes)
fmt.Println("module name: ", moduleName)
fmt.Println("Prefix Sizes[moduleName]: ", result.PrefixSizes[moduleName])

prefixKeyResult, _ := json.MarshalIndent(result.PrefixSizes[moduleName].KeySize, "", " ")
fmt.Printf("Module %s prefix key size breakdown (bytes): %s \n", result.ModuleName, prefixKeyResult)

Expand All @@ -242,6 +272,21 @@
numKeysResult, _ := json.MarshalIndent(result.PrefixSizes[moduleName].KeyCount, "", " ")
fmt.Printf("Module %s prefix num of keys breakdown: %s \n", result.ModuleName, numKeysResult)

// EVM-only: zeroed-entry statistics for 0x03 storage
if moduleName == "evm" {
var pct float64
if result.TotalEVM03Entries > 0 {
pct = float64(result.ZeroedEVM03Entries) / float64(result.TotalEVM03Entries) * 100

Check notice

Code scanning / CodeQL

Floating point arithmetic Note

Floating point arithmetic operations are not associative and a possible source of non-determinism

Check notice

Code scanning / CodeQL

Floating point arithmetic Note

Floating point arithmetic operations are not associative and a possible source of non-determinism
}
fmt.Printf("EVM 0x03 entries: total=%d, zeroed=%d (%.2f%%), zeroed_key_bytes=%d, zeroed_value_bytes=%d\n",
result.TotalEVM03Entries,
result.ZeroedEVM03Entries,
pct,
result.ZeroedEVM03KeyBytes,
result.ZeroedEVM03ValueBytes,
)
}

// Display top contracts (already limited to top 100)
fmt.Printf("\nDetailed breakdown for 0x03 prefix (top %d contracts by total size):\n", len(result.ContractSizes))
fmt.Printf("%-42s %15s %10s\n", "Contract Address", "Total Size", "Key Count")
Expand Down Expand Up @@ -290,3 +335,13 @@
ContractBreakdown: string(contractJSON),
}
}

// isAllZero returns true if the provided byte slice is empty or consists entirely of zero bytes.
func isAllZero(b []byte) bool {
for _, by := range b {
if by != 0x00 {
return false
}
}
return true
}
Loading