From dfe1e274c03a5e3fd5472eddce1c11760bddc7e5 Mon Sep 17 00:00:00 2001 From: Ignacio Hagopian Date: Wed, 29 Mar 2023 13:51:51 -0300 Subject: [PATCH 01/22] verkle migration: code rearchitecture Signed-off-by: Ignacio Hagopian --- cmd/geth/verkle.go | 48 ++++++++++++++++++++++++++++++++++------------ go.mod | 2 ++ 2 files changed, 38 insertions(+), 12 deletions(-) diff --git a/cmd/geth/verkle.go b/cmd/geth/verkle.go index a16a716fe014..a6646f5a9a61 100644 --- a/cmd/geth/verkle.go +++ b/cmd/geth/verkle.go @@ -26,6 +26,7 @@ import ( "io/ioutil" "os" "runtime" + "runtime/pprof" "sort" "time" @@ -732,11 +733,33 @@ func dumpKeys(ctx *cli.Context) error { } func sortKeys(ctx *cli.Context) error { + go func() { + for { + time.Sleep(time.Second * 30) + f2, err := os.Create("mem.out") + if err != nil { + panic(err) + } + if err := pprof.WriteHeapProfile(f2); err != nil { + panic(err) + } + f2.Close() + } + }() + + f, err := os.Create("cpu.out") + if err != nil { + panic(err) + } + defer f.Close() + pprof.StartCPUProfile(f) + defer pprof.StopCPUProfile() + // Get list of files files, _ := ioutil.ReadDir(".") start := time.Now() - root := verkle.New() + var leaves []verkle.LeafNode // Iterate over files for _, file := range files { // Check if file is a binary file @@ -778,18 +801,18 @@ func sortKeys(ctx *cli.Context) error { if len(tuples) > 0 { copy(last[:], tuples[0][:31]) } + + var leavesData []verkle.BatchNewLeafNodeData for i := range tuples { copy(stem[:], tuples[i][:31]) if stem != last { binary.Write(file, binary.LittleEndian, last) binary.Write(file, binary.LittleEndian, values) - var istem [31]byte - istem = last - err := root.(*verkle.InternalNode).InsertStem(istem[:], values, nil) - if err != nil { - panic(err) - } + kk := make([]byte, 31) + copy(kk, last[:]) + leavesData = append(leavesData, verkle.BatchNewLeafNodeData{Stem: kk, Values: values}) + copy(last[:], stem[:]) values = make([][]byte, 256) } @@ -801,19 +824,20 @@ func sortKeys(ctx *cli.Context) error { // dump the last group binary.Write(file, binary.LittleEndian, stem) binary.Write(file, binary.LittleEndian, values) - err := root.(*verkle.InternalNode).InsertStem(stem[:], values, nil) - if err != nil { - panic(err) - } + leavesData = append(leavesData, verkle.BatchNewLeafNodeData{Stem: stem[:], Values: values}) + + leaves = append(leaves, verkle.BatchNewLeafNode(leavesData)...) // Committing file log.Info("Committing file", "name", file.Name()) - root.Commit() // Write sorted tuples back to file log.Info("Writing file", "name", file.Name()) file.Close() } + root := verkle.BatchInsertOrderedLeaves(leaves) + root.Commit() + log.Info("Done", "root", fmt.Sprintf("%x", root.Commit().Bytes())) log.Info("Finished", "elapsed", common.PrettyDuration(time.Since(start))) return nil diff --git a/go.mod b/go.mod index 1369c43c71c3..afde2beb413e 100644 --- a/go.mod +++ b/go.mod @@ -106,3 +106,5 @@ require ( gopkg.in/yaml.v2 v2.4.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect ) + +replace github.com/gballet/go-verkle => ../../go-verkle From 7ebb7aa774bd9d19d4d840d9cb4f5d2f04c01f40 Mon Sep 17 00:00:00 2001 From: Ignacio Hagopian Date: Wed, 29 Mar 2023 17:36:50 -0300 Subject: [PATCH 02/22] verkle migration: memory saving optimizations Signed-off-by: Ignacio Hagopian --- cmd/geth/verkle.go | 35 +++++++++++++++++++++++++---------- 1 file changed, 25 insertions(+), 10 deletions(-) diff --git a/cmd/geth/verkle.go b/cmd/geth/verkle.go index a6646f5a9a61..422bb92edf5b 100644 --- a/cmd/geth/verkle.go +++ b/cmd/geth/verkle.go @@ -17,6 +17,7 @@ package main import ( + "bufio" "bytes" "encoding/binary" "encoding/hex" @@ -792,10 +793,11 @@ func sortKeys(ctx *cli.Context) error { // Merge the values log.Info("Merging file", "name", file.Name()) - file, _ := os.Create("sorted-" + file.Name()) + file2, _ := os.Create("sorted-" + file.Name()) + file := bufio.NewWriter(file2) var ( stem [31]byte - values = make([][]byte, 256) + values = make(map[int][]byte, 5) last [31]byte ) if len(tuples) > 0 { @@ -813,12 +815,17 @@ func sortKeys(ctx *cli.Context) error { copy(kk, last[:]) leavesData = append(leavesData, verkle.BatchNewLeafNodeData{Stem: kk, Values: values}) + if len(leavesData) > 1024*1024 { + leaves = append(leaves, verkle.BatchNewLeafNode(leavesData)...) + leavesData = leavesData[:0] + } + copy(last[:], stem[:]) - values = make([][]byte, 256) + values = make(map[int][]byte, 5) } - values[tuples[i][31]] = make([]byte, 32) - copy(values[tuples[i][31]], tuples[i][32:]) + values[int(tuples[i][31])] = make([]byte, 32) + copy(values[int(tuples[i][31])], tuples[i][32:]) } // dump the last group @@ -826,18 +833,26 @@ func sortKeys(ctx *cli.Context) error { binary.Write(file, binary.LittleEndian, values) leavesData = append(leavesData, verkle.BatchNewLeafNodeData{Stem: stem[:], Values: values}) - leaves = append(leaves, verkle.BatchNewLeafNode(leavesData)...) - // Committing file - log.Info("Committing file", "name", file.Name()) + log.Info("Committing file", "name", file2.Name()) + + leaves = append(leaves, verkle.BatchNewLeafNode(leavesData)...) // Write sorted tuples back to file - log.Info("Writing file", "name", file.Name()) - file.Close() + log.Info("Writing file", "name", file2.Name()) + file.Flush() + file2.Close() } + + log.Info("Creating tree") root := verkle.BatchInsertOrderedLeaves(leaves) root.Commit() + log.Info("Serializing tree") + if _, err := root.BatchSerialize(); err != nil { + panic(err) + } + log.Info("Done", "root", fmt.Sprintf("%x", root.Commit().Bytes())) log.Info("Finished", "elapsed", common.PrettyDuration(time.Since(start))) return nil From 47869f5f3dd9e1a41cae37760f5c587415d5154e Mon Sep 17 00:00:00 2001 From: Ignacio Hagopian Date: Thu, 30 Mar 2023 10:39:52 -0300 Subject: [PATCH 03/22] verkle migration: parallelize leaf computation Signed-off-by: Ignacio Hagopian --- cmd/geth/verkle.go | 23 +++++++++++++++++------ 1 file changed, 17 insertions(+), 6 deletions(-) diff --git a/cmd/geth/verkle.go b/cmd/geth/verkle.go index 422bb92edf5b..b65755cce8ee 100644 --- a/cmd/geth/verkle.go +++ b/cmd/geth/verkle.go @@ -734,6 +734,7 @@ func dumpKeys(ctx *cli.Context) error { } func sortKeys(ctx *cli.Context) error { + _ = verkle.GetConfig() go func() { for { time.Sleep(time.Second * 30) @@ -815,11 +816,6 @@ func sortKeys(ctx *cli.Context) error { copy(kk, last[:]) leavesData = append(leavesData, verkle.BatchNewLeafNodeData{Stem: kk, Values: values}) - if len(leavesData) > 1024*1024 { - leaves = append(leaves, verkle.BatchNewLeafNode(leavesData)...) - leavesData = leavesData[:0] - } - copy(last[:], stem[:]) values = make(map[int][]byte, 5) } @@ -836,7 +832,22 @@ func sortKeys(ctx *cli.Context) error { // Committing file log.Info("Committing file", "name", file2.Name()) - leaves = append(leaves, verkle.BatchNewLeafNode(leavesData)...) + batches := runtime.NumCPU() + results := make(chan []verkle.LeafNode) + for i := 0; i < batches; i++ { + i := i + go func() { + start := i * len(leavesData) / batches + end := (i + 1) * len(leavesData) / batches + if i == batches-1 { + end = len(leavesData) + } + results <- verkle.BatchNewLeafNode(leavesData[start:end]) + }() + } + for i := 0; i < batches; i++ { + leaves = append(leaves, <-results...) + } // Write sorted tuples back to file log.Info("Writing file", "name", file2.Name()) From 8deaef256210294a594360a48ff52dbf6df9e573 Mon Sep 17 00:00:00 2001 From: Ignacio Hagopian Date: Thu, 30 Mar 2023 10:52:28 -0300 Subject: [PATCH 04/22] verkle migration: keep ordering in batch results Signed-off-by: Ignacio Hagopian --- cmd/geth/verkle.go | 24 +++++++++++++++--------- 1 file changed, 15 insertions(+), 9 deletions(-) diff --git a/cmd/geth/verkle.go b/cmd/geth/verkle.go index b65755cce8ee..aa3cea34169f 100644 --- a/cmd/geth/verkle.go +++ b/cmd/geth/verkle.go @@ -29,6 +29,7 @@ import ( "runtime" "runtime/pprof" "sort" + "sync" "time" "github.com/ethereum/go-ethereum/cmd/utils" @@ -832,21 +833,26 @@ func sortKeys(ctx *cli.Context) error { // Committing file log.Info("Committing file", "name", file2.Name()) - batches := runtime.NumCPU() - results := make(chan []verkle.LeafNode) - for i := 0; i < batches; i++ { + numBatches := runtime.NumCPU() + batchSize := len(leavesData) / numBatches + results := make([][]verkle.LeafNode, runtime.NumCPU()) + var wg sync.WaitGroup + for i := 0; i < numBatches; i++ { + wg.Add(1) i := i go func() { - start := i * len(leavesData) / batches - end := (i + 1) * len(leavesData) / batches - if i == batches-1 { + defer wg.Done() + start := i * batchSize + end := (i + 1) * batchSize + if i == numBatches-1 { end = len(leavesData) } - results <- verkle.BatchNewLeafNode(leavesData[start:end]) + results[i] = verkle.BatchNewLeafNode(leavesData[start:end]) }() } - for i := 0; i < batches; i++ { - leaves = append(leaves, <-results...) + wg.Wait() + for _, compLeaves := range results { + leaves = append(leaves, compLeaves...) } // Write sorted tuples back to file From 018ce4e767fe07f7eee40c739e38524e1ca07375 Mon Sep 17 00:00:00 2001 From: Ignacio Hagopian Date: Thu, 30 Mar 2023 15:54:00 -0300 Subject: [PATCH 05/22] verkle migration: parallelize tree merging Signed-off-by: Ignacio Hagopian --- cmd/geth/verkle.go | 43 ++++++++++++++++++++++--------------------- 1 file changed, 22 insertions(+), 21 deletions(-) diff --git a/cmd/geth/verkle.go b/cmd/geth/verkle.go index aa3cea34169f..2e85f62d3261 100644 --- a/cmd/geth/verkle.go +++ b/cmd/geth/verkle.go @@ -758,11 +758,12 @@ func sortKeys(ctx *cli.Context) error { pprof.StartCPUProfile(f) defer pprof.StopCPUProfile() + numBatches := 16 // runtime.NumCPU() + // Get list of files files, _ := ioutil.ReadDir(".") start := time.Now() - var leaves []verkle.LeafNode // Iterate over files for _, file := range files { // Check if file is a binary file @@ -802,8 +803,10 @@ func sortKeys(ctx *cli.Context) error { values = make(map[int][]byte, 5) last [31]byte ) + var secondByteIdxs [256]int if len(tuples) > 0 { copy(last[:], tuples[0][:31]) + secondByteIdxs[int(last[1])] = 0 } var leavesData []verkle.BatchNewLeafNodeData @@ -817,6 +820,9 @@ func sortKeys(ctx *cli.Context) error { copy(kk, last[:]) leavesData = append(leavesData, verkle.BatchNewLeafNodeData{Stem: kk, Values: values}) + if stem[1] != last[1] { + secondByteIdxs[int(stem[1])] = len(leavesData) + } copy(last[:], stem[:]) values = make(map[int][]byte, 5) } @@ -833,26 +839,31 @@ func sortKeys(ctx *cli.Context) error { // Committing file log.Info("Committing file", "name", file2.Name()) - numBatches := runtime.NumCPU() - batchSize := len(leavesData) / numBatches - results := make([][]verkle.LeafNode, runtime.NumCPU()) + batchSize := len(secondByteIdxs) / numBatches + roots := make([]*verkle.InternalNode, numBatches) var wg sync.WaitGroup for i := 0; i < numBatches; i++ { wg.Add(1) i := i go func() { defer wg.Done() - start := i * batchSize - end := (i + 1) * batchSize - if i == numBatches-1 { - end = len(leavesData) + start := secondByteIdxs[i*batchSize] + end := len(leavesData) + if i < numBatches-1 { + end = secondByteIdxs[(i+1)*batchSize] } - results[i] = verkle.BatchNewLeafNode(leavesData[start:end]) + leaves := verkle.BatchNewLeafNode(leavesData[start:end]) + roots[i] = verkle.BatchInsertOrderedLeaves(leaves) }() } wg.Wait() - for _, compLeaves := range results { - leaves = append(leaves, compLeaves...) + + root := verkle.MergeLevelTwoPartitions(roots) + log.Info("Merged tree", "root", fmt.Sprintf("%x", root.Commit().Bytes())) + + log.Info("Serializing tree") + if _, err := root.BatchSerialize(); err != nil { + panic(err) } // Write sorted tuples back to file @@ -861,16 +872,6 @@ func sortKeys(ctx *cli.Context) error { file2.Close() } - log.Info("Creating tree") - root := verkle.BatchInsertOrderedLeaves(leaves) - root.Commit() - - log.Info("Serializing tree") - if _, err := root.BatchSerialize(); err != nil { - panic(err) - } - - log.Info("Done", "root", fmt.Sprintf("%x", root.Commit().Bytes())) log.Info("Finished", "elapsed", common.PrettyDuration(time.Since(start))) return nil } From 655a8de1e791c1b292c44744d1448e400c592721 Mon Sep 17 00:00:00 2001 From: Ignacio Hagopian Date: Thu, 30 Mar 2023 16:00:30 -0300 Subject: [PATCH 06/22] verkle migration: remove sorted file & cleanup log messages Signed-off-by: Ignacio Hagopian --- cmd/geth/verkle.go | 27 +++++++-------------------- 1 file changed, 7 insertions(+), 20 deletions(-) diff --git a/cmd/geth/verkle.go b/cmd/geth/verkle.go index 2e85f62d3261..10995931b843 100644 --- a/cmd/geth/verkle.go +++ b/cmd/geth/verkle.go @@ -17,7 +17,6 @@ package main import ( - "bufio" "bytes" "encoding/binary" "encoding/hex" @@ -758,7 +757,7 @@ func sortKeys(ctx *cli.Context) error { pprof.StartCPUProfile(f) defer pprof.StopCPUProfile() - numBatches := 16 // runtime.NumCPU() + numBatches := runtime.NumCPU() // Get list of files files, _ := ioutil.ReadDir(".") @@ -771,8 +770,11 @@ func sortKeys(ctx *cli.Context) error { if !bytes.HasSuffix([]byte(fname), []byte(".bin")) || bytes.HasPrefix([]byte(fname), []byte("sorted-")) || len(fname) != 6 { continue } - log.Info("Processing file", "name", file.Name()) + + log.Info("Reading file", "name", file.Name()) data, _ := ioutil.ReadFile(file.Name()) + + log.Info("Processing file", "name", file.Name()) numTuples := len(data) / 64 tuples := make([][64]byte, 0, numTuples) reader := bytes.NewReader(data) @@ -796,8 +798,6 @@ func sortKeys(ctx *cli.Context) error { // Merge the values log.Info("Merging file", "name", file.Name()) - file2, _ := os.Create("sorted-" + file.Name()) - file := bufio.NewWriter(file2) var ( stem [31]byte values = make(map[int][]byte, 5) @@ -808,14 +808,10 @@ func sortKeys(ctx *cli.Context) error { copy(last[:], tuples[0][:31]) secondByteIdxs[int(last[1])] = 0 } - var leavesData []verkle.BatchNewLeafNodeData for i := range tuples { copy(stem[:], tuples[i][:31]) if stem != last { - binary.Write(file, binary.LittleEndian, last) - binary.Write(file, binary.LittleEndian, values) - kk := make([]byte, 31) copy(kk, last[:]) leavesData = append(leavesData, verkle.BatchNewLeafNodeData{Stem: kk, Values: values}) @@ -830,15 +826,11 @@ func sortKeys(ctx *cli.Context) error { values[int(tuples[i][31])] = make([]byte, 32) copy(values[int(tuples[i][31])], tuples[i][32:]) } - // dump the last group - binary.Write(file, binary.LittleEndian, stem) - binary.Write(file, binary.LittleEndian, values) leavesData = append(leavesData, verkle.BatchNewLeafNodeData{Stem: stem[:], Values: values}) // Committing file - log.Info("Committing file", "name", file2.Name()) - + log.Info("Building tree", "name", file.Name()) batchSize := len(secondByteIdxs) / numBatches roots := make([]*verkle.InternalNode, numBatches) var wg sync.WaitGroup @@ -859,17 +851,12 @@ func sortKeys(ctx *cli.Context) error { wg.Wait() root := verkle.MergeLevelTwoPartitions(roots) - log.Info("Merged tree", "root", fmt.Sprintf("%x", root.Commit().Bytes())) + log.Info("Building tree finished", "root", fmt.Sprintf("%x", root.Commit().Bytes())) log.Info("Serializing tree") if _, err := root.BatchSerialize(); err != nil { panic(err) } - - // Write sorted tuples back to file - log.Info("Writing file", "name", file2.Name()) - file.Flush() - file2.Close() } log.Info("Finished", "elapsed", common.PrettyDuration(time.Since(start))) From d0be88e7c7772aa16168bcbc93adf041faef6312 Mon Sep 17 00:00:00 2001 From: Ignacio Hagopian Date: Thu, 30 Mar 2023 16:12:42 -0300 Subject: [PATCH 07/22] verkle migration: do partial commitment of trees in parallel Signed-off-by: Ignacio Hagopian --- cmd/geth/verkle.go | 3 +++ 1 file changed, 3 insertions(+) diff --git a/cmd/geth/verkle.go b/cmd/geth/verkle.go index 10995931b843..f1fc98314909 100644 --- a/cmd/geth/verkle.go +++ b/cmd/geth/verkle.go @@ -846,6 +846,7 @@ func sortKeys(ctx *cli.Context) error { } leaves := verkle.BatchNewLeafNode(leavesData[start:end]) roots[i] = verkle.BatchInsertOrderedLeaves(leaves) + roots[i].Commit() }() } wg.Wait() @@ -857,6 +858,8 @@ func sortKeys(ctx *cli.Context) error { if _, err := root.BatchSerialize(); err != nil { panic(err) } + + runtime.GC() } log.Info("Finished", "elapsed", common.PrettyDuration(time.Since(start))) From 04df746d87351274a19137cb9a336d1c713d9f9a Mon Sep 17 00:00:00 2001 From: Ignacio Hagopian Date: Fri, 31 Mar 2023 10:29:32 -0300 Subject: [PATCH 08/22] verkle migration: serialize in parallel Signed-off-by: Ignacio Hagopian --- cmd/geth/verkle.go | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/cmd/geth/verkle.go b/cmd/geth/verkle.go index f1fc98314909..b79a0daed77a 100644 --- a/cmd/geth/verkle.go +++ b/cmd/geth/verkle.go @@ -846,7 +846,10 @@ func sortKeys(ctx *cli.Context) error { } leaves := verkle.BatchNewLeafNode(leavesData[start:end]) roots[i] = verkle.BatchInsertOrderedLeaves(leaves) - roots[i].Commit() + + if _, err := roots[i].BatchSerialize(); err != nil { + panic(err) + } }() } wg.Wait() @@ -855,9 +858,6 @@ func sortKeys(ctx *cli.Context) error { log.Info("Building tree finished", "root", fmt.Sprintf("%x", root.Commit().Bytes())) log.Info("Serializing tree") - if _, err := root.BatchSerialize(); err != nil { - panic(err) - } runtime.GC() } From cea9eac6deaa5f0ed5b5b5189f9028aaf87a1d8c Mon Sep 17 00:00:00 2001 From: Ignacio Hagopian Date: Fri, 31 Mar 2023 11:45:03 -0300 Subject: [PATCH 09/22] verkle migration: avoid copying to tuples but use slices Signed-off-by: Ignacio Hagopian --- cmd/geth/verkle.go | 16 +++------------- 1 file changed, 3 insertions(+), 13 deletions(-) diff --git a/cmd/geth/verkle.go b/cmd/geth/verkle.go index b79a0daed77a..a31790aa868a 100644 --- a/cmd/geth/verkle.go +++ b/cmd/geth/verkle.go @@ -22,7 +22,6 @@ import ( "encoding/hex" "errors" "fmt" - "io" "io/ioutil" "os" "runtime" @@ -776,18 +775,9 @@ func sortKeys(ctx *cli.Context) error { log.Info("Processing file", "name", file.Name()) numTuples := len(data) / 64 - tuples := make([][64]byte, 0, numTuples) - reader := bytes.NewReader(data) - for { - var tuple [64]byte - err := binary.Read(reader, binary.LittleEndian, &tuple) - if errors.Is(err, io.EOF) { - break - } - if err != nil { - panic(err) - } - tuples = append(tuples, tuple) + tuples := make([][]byte, numTuples) + for i := 0; i < numTuples; i++ { + tuples[i] = data[i*64 : (i+1)*64] } // Sort tuples by key From 00d77f2197333f4f3ecc9e14f0e334770d2a3fe5 Mon Sep 17 00:00:00 2001 From: Ignacio Hagopian Date: Fri, 31 Mar 2023 12:01:58 -0300 Subject: [PATCH 10/22] verkle migration: more memory saving optimizations Signed-off-by: Ignacio Hagopian --- cmd/geth/verkle.go | 44 +++++++++++++++++++------------------------- 1 file changed, 19 insertions(+), 25 deletions(-) diff --git a/cmd/geth/verkle.go b/cmd/geth/verkle.go index a31790aa868a..6a47c6417064 100644 --- a/cmd/geth/verkle.go +++ b/cmd/geth/verkle.go @@ -734,19 +734,16 @@ func dumpKeys(ctx *cli.Context) error { func sortKeys(ctx *cli.Context) error { _ = verkle.GetConfig() - go func() { - for { - time.Sleep(time.Second * 30) - f2, err := os.Create("mem.out") - if err != nil { - panic(err) - } - if err := pprof.WriteHeapProfile(f2); err != nil { - panic(err) - } - f2.Close() - } - }() + /* + f2, err := os.Create("mem.out") + if err != nil { + panic(err) + } + defer f2.Close() + if err := pprof.WriteHeapProfile(f2); err != nil { + panic(err) + } + */ f, err := os.Create("cpu.out") if err != nil { @@ -789,32 +786,29 @@ func sortKeys(ctx *cli.Context) error { // Merge the values log.Info("Merging file", "name", file.Name()) var ( - stem [31]byte + stem []byte values = make(map[int][]byte, 5) - last [31]byte + last []byte ) var secondByteIdxs [256]int if len(tuples) > 0 { - copy(last[:], tuples[0][:31]) + last = tuples[0][:31] secondByteIdxs[int(last[1])] = 0 } var leavesData []verkle.BatchNewLeafNodeData for i := range tuples { - copy(stem[:], tuples[i][:31]) - if stem != last { - kk := make([]byte, 31) - copy(kk, last[:]) - leavesData = append(leavesData, verkle.BatchNewLeafNodeData{Stem: kk, Values: values}) + stem = tuples[i][:31] + if !bytes.Equal(stem, last) { + leavesData = append(leavesData, verkle.BatchNewLeafNodeData{Stem: last, Values: values}) if stem[1] != last[1] { secondByteIdxs[int(stem[1])] = len(leavesData) } - copy(last[:], stem[:]) - values = make(map[int][]byte, 5) + last = stem + values = make(map[int][]byte) } - values[int(tuples[i][31])] = make([]byte, 32) - copy(values[int(tuples[i][31])], tuples[i][32:]) + values[int(tuples[i][31])] = tuples[i][32:] } // dump the last group leavesData = append(leavesData, verkle.BatchNewLeafNodeData{Stem: stem[:], Values: values}) From b069fa4755be1ec909cfeda7acd6e8bd2a742c08 Mon Sep 17 00:00:00 2001 From: Ignacio Hagopian Date: Sat, 1 Apr 2023 13:58:10 -0300 Subject: [PATCH 11/22] verkle migration: refactor Signed-off-by: Ignacio Hagopian --- cmd/geth/verkle.go | 139 ++++++++++++++++++++++++++------------------- 1 file changed, 82 insertions(+), 57 deletions(-) diff --git a/cmd/geth/verkle.go b/cmd/geth/verkle.go index 6a47c6417064..8a16ced097ac 100644 --- a/cmd/geth/verkle.go +++ b/cmd/geth/verkle.go @@ -753,13 +753,20 @@ func sortKeys(ctx *cli.Context) error { pprof.StartCPUProfile(f) defer pprof.StopCPUProfile() - numBatches := runtime.NumCPU() + // Open database + stack, _ := makeConfigNode(ctx) + defer stack.Close() + chaindb := utils.MakeChainDatabase(ctx, stack, false) + if chaindb == nil { + return errors.New("nil chaindb") + } + // Run setup. + maxCPUs := runtime.NumCPU() - // Get list of files - files, _ := ioutil.ReadDir(".") start := time.Now() - // Iterate over files + // List files and iterate on them + files, _ := ioutil.ReadDir(".") for _, file := range files { // Check if file is a binary file fname := file.Name() @@ -767,73 +774,37 @@ func sortKeys(ctx *cli.Context) error { continue } - log.Info("Reading file", "name", file.Name()) - data, _ := ioutil.ReadFile(file.Name()) - - log.Info("Processing file", "name", file.Name()) - numTuples := len(data) / 64 - tuples := make([][]byte, numTuples) - for i := 0; i < numTuples; i++ { - tuples[i] = data[i*64 : (i+1)*64] - } - - // Sort tuples by key - log.Info("Sorting file", "name", file.Name()) - sort.Slice(tuples, func(i, j int) bool { - return bytes.Compare(tuples[i][:32], tuples[j][:32]) < 0 - }) - - // Merge the values - log.Info("Merging file", "name", file.Name()) - var ( - stem []byte - values = make(map[int][]byte, 5) - last []byte - ) - var secondByteIdxs [256]int - if len(tuples) > 0 { - last = tuples[0][:31] - secondByteIdxs[int(last[1])] = 0 - } - var leavesData []verkle.BatchNewLeafNodeData - for i := range tuples { - stem = tuples[i][:31] - if !bytes.Equal(stem, last) { - leavesData = append(leavesData, verkle.BatchNewLeafNodeData{Stem: last, Values: values}) - - if stem[1] != last[1] { - secondByteIdxs[int(stem[1])] = len(leavesData) - } - last = stem - values = make(map[int][]byte) - } - - values[int(tuples[i][31])] = tuples[i][32:] - } - // dump the last group - leavesData = append(leavesData, verkle.BatchNewLeafNodeData{Stem: stem[:], Values: values}) + // Get a sorted list of all the leaves data ordered by key, + // and a slice of indexes of the second byte of each key for further patitioning. + leavesData, stem2ndByteIdxs := getSortedLeavesData(fname) // Committing file log.Info("Building tree", "name", file.Name()) - batchSize := len(secondByteIdxs) / numBatches - roots := make([]*verkle.InternalNode, numBatches) + batchSize := len(stem2ndByteIdxs) / maxCPUs + roots := make([]*verkle.InternalNode, maxCPUs) + rootsNodes := make([][]verkle.SerializedNode, maxCPUs) var wg sync.WaitGroup - for i := 0; i < numBatches; i++ { + for i := 0; i < maxCPUs; i++ { wg.Add(1) i := i go func() { defer wg.Done() - start := secondByteIdxs[i*batchSize] + start := stem2ndByteIdxs[i*batchSize] end := len(leavesData) - if i < numBatches-1 { - end = secondByteIdxs[(i+1)*batchSize] + if i < maxCPUs-1 { + end = stem2ndByteIdxs[(i+1)*batchSize] } + leaves := verkle.BatchNewLeafNode(leavesData[start:end]) roots[i] = verkle.BatchInsertOrderedLeaves(leaves) - if _, err := roots[i].BatchSerialize(); err != nil { + rootsNodes[i], err = roots[i].BatchSerialize() + if err != nil { panic(err) } + sort.Slice(rootsNodes[i], func(k, j int) bool { + return bytes.Compare(rootsNodes[i][k].CommitmentBytes[:], rootsNodes[i][k].CommitmentBytes[:]) < 0 + }) }() } wg.Wait() @@ -842,10 +813,64 @@ func sortKeys(ctx *cli.Context) error { log.Info("Building tree finished", "root", fmt.Sprintf("%x", root.Commit().Bytes())) log.Info("Serializing tree") - + for k, nodes := range rootsNodes { + for _, node := range nodes { + if err := chaindb.Put(node.CommitmentBytes[:], node.SerializedBytes); err != nil { + log.Crit("put node to disk: %s", err) + } + } + rootsNodes[k] = nil + } runtime.GC() } log.Info("Finished", "elapsed", common.PrettyDuration(time.Since(start))) return nil } + +func getSortedLeavesData(fname string) ([]verkle.BatchNewLeafNodeData, [256]int) { + log.Info("Reading file", "name", fname) + data, _ := ioutil.ReadFile(fname) + + log.Info("Processing file", "name", fname) + numTuples := len(data) / 64 + tuples := make([][]byte, numTuples) + for i := 0; i < numTuples; i++ { + tuples[i] = data[i*64 : (i+1)*64] + } + // Sort tuples by key + log.Info("Sorting file", "name", fname) + sort.Slice(tuples, func(i, j int) bool { + return bytes.Compare(tuples[i][:32], tuples[j][:32]) < 0 + }) + + // Merge the values + log.Info("Merging file", "name", fname) + var ( + stem []byte + values = make(map[int][]byte, 5) + last []byte + ) + var secondByteIdxs [256]int + if len(tuples) > 0 { + last = tuples[0][:31] + secondByteIdxs[int(last[1])] = 0 + } + var leavesData []verkle.BatchNewLeafNodeData + for i := range tuples { + stem = tuples[i][:31] + if !bytes.Equal(stem, last) { + leavesData = append(leavesData, verkle.BatchNewLeafNodeData{Stem: last, Values: values}) + + if stem[1] != last[1] { + secondByteIdxs[int(stem[1])] = len(leavesData) + } + last = stem + values = make(map[int][]byte) + } + + values[int(tuples[i][31])] = tuples[i][32:] + } + // dump the last group + return append(leavesData, verkle.BatchNewLeafNodeData{Stem: stem[:], Values: values}), secondByteIdxs +} From 3afa5be644fd6fbbe59c6cf4099db2533d8c3233 Mon Sep 17 00:00:00 2001 From: Ignacio Hagopian Date: Sat, 1 Apr 2023 18:41:26 -0300 Subject: [PATCH 12/22] verkle migration: pipeline rearchitecture Signed-off-by: Ignacio Hagopian --- cmd/geth/verkle.go | 105 +++++++++++++++++++++++++-------------------- 1 file changed, 59 insertions(+), 46 deletions(-) diff --git a/cmd/geth/verkle.go b/cmd/geth/verkle.go index 8a16ced097ac..f19c678dc129 100644 --- a/cmd/geth/verkle.go +++ b/cmd/geth/verkle.go @@ -18,6 +18,7 @@ package main import ( "bytes" + "context" "encoding/binary" "encoding/hex" "errors" @@ -42,6 +43,7 @@ import ( "github.com/gballet/go-verkle" "github.com/holiman/uint256" cli "github.com/urfave/cli/v2" + "golang.org/x/sync/errgroup" ) var ( @@ -761,8 +763,6 @@ func sortKeys(ctx *cli.Context) error { return errors.New("nil chaindb") } // Run setup. - maxCPUs := runtime.NumCPU() - start := time.Now() // List files and iterate on them @@ -774,53 +774,62 @@ func sortKeys(ctx *cli.Context) error { continue } - // Get a sorted list of all the leaves data ordered by key, - // and a slice of indexes of the second byte of each key for further patitioning. - leavesData, stem2ndByteIdxs := getSortedLeavesData(fname) + // Read the file, partition in second-level subtrees, and push them into the channel to be processed. + secondLvlLeaves := make(chan []verkle.BatchNewLeafNodeData) + go func() { + if err := getSortedLeavesData(fname, secondLvlLeaves); err != nil { + log.Crit("Failed to get sorted leaves data", "error", err) + } + close(secondLvlLeaves) + }() - // Committing file + // Process secondLvlLeaves items and pipe the results to readyToSerializeSubtree. log.Info("Building tree", "name", file.Name()) - batchSize := len(stem2ndByteIdxs) / maxCPUs - roots := make([]*verkle.InternalNode, maxCPUs) - rootsNodes := make([][]verkle.SerializedNode, maxCPUs) - var wg sync.WaitGroup - for i := 0; i < maxCPUs; i++ { - wg.Add(1) - i := i - go func() { - defer wg.Done() - start := stem2ndByteIdxs[i*batchSize] - end := len(leavesData) - if i < maxCPUs-1 { - end = stem2ndByteIdxs[(i+1)*batchSize] - } - - leaves := verkle.BatchNewLeafNode(leavesData[start:end]) - roots[i] = verkle.BatchInsertOrderedLeaves(leaves) - - rootsNodes[i], err = roots[i].BatchSerialize() - if err != nil { - panic(err) - } - sort.Slice(rootsNodes[i], func(k, j int) bool { - return bytes.Compare(rootsNodes[i][k].CommitmentBytes[:], rootsNodes[i][k].CommitmentBytes[:]) < 0 + readyToSerializeSubtree := make(chan []verkle.SerializedNode) + var lock sync.Mutex + var roots []*verkle.InternalNode + go func() { + group, _ := errgroup.WithContext(context.Background()) + group.SetLimit(runtime.NumCPU()) + for leavesData := range secondLvlLeaves { + leavesData := leavesData + group.Go(func() error { + leaves := verkle.BatchNewLeafNode(leavesData) + root := verkle.BatchInsertOrderedLeaves(leaves) + nodes, err := root.BatchSerialize() + if err != nil { + return fmt.Errorf("failed to serialize nodes: %w", err) + } + sort.Slice(nodes, func(i, j int) bool { + return bytes.Compare(nodes[i].CommitmentBytes[:], nodes[j].CommitmentBytes[:]) < 0 + }) + lock.Lock() + roots = append(roots, root) + lock.Unlock() + + readyToSerializeSubtree <- nodes + return nil }) - }() - } - wg.Wait() - - root := verkle.MergeLevelTwoPartitions(roots) - log.Info("Building tree finished", "root", fmt.Sprintf("%x", root.Commit().Bytes())) + } + if err := group.Wait(); err != nil { + log.Crit("Failed to build tree", "error", err) + } + close(readyToSerializeSubtree) + }() + // Serialize items in readyToSerializeSubtree and save them to disk. log.Info("Serializing tree") - for k, nodes := range rootsNodes { + for nodes := range readyToSerializeSubtree { for _, node := range nodes { if err := chaindb.Put(node.CommitmentBytes[:], node.SerializedBytes); err != nil { log.Crit("put node to disk: %s", err) } } - rootsNodes[k] = nil } + + root := verkle.MergeLevelTwoPartitions(roots) + log.Info("Building tree finished", "root", fmt.Sprintf("%x", root.Commit().Bytes())) + runtime.GC() } @@ -828,9 +837,12 @@ func sortKeys(ctx *cli.Context) error { return nil } -func getSortedLeavesData(fname string) ([]verkle.BatchNewLeafNodeData, [256]int) { +func getSortedLeavesData(fname string, secondLvlLeavesData chan []verkle.BatchNewLeafNodeData) error { log.Info("Reading file", "name", fname) - data, _ := ioutil.ReadFile(fname) + data, err := ioutil.ReadFile(fname) + if err != nil { + return fmt.Errorf("failed to read file: %w", err) + } log.Info("Processing file", "name", fname) numTuples := len(data) / 64 @@ -851,19 +863,18 @@ func getSortedLeavesData(fname string) ([]verkle.BatchNewLeafNodeData, [256]int) values = make(map[int][]byte, 5) last []byte ) - var secondByteIdxs [256]int if len(tuples) > 0 { last = tuples[0][:31] - secondByteIdxs[int(last[1])] = 0 } + // TODO(jsign): predict a bit good capacity. var leavesData []verkle.BatchNewLeafNodeData for i := range tuples { stem = tuples[i][:31] if !bytes.Equal(stem, last) { leavesData = append(leavesData, verkle.BatchNewLeafNodeData{Stem: last, Values: values}) - if stem[1] != last[1] { - secondByteIdxs[int(stem[1])] = len(leavesData) + secondLvlLeavesData <- leavesData + leavesData = make([]verkle.BatchNewLeafNodeData, 0, len(leavesData)) } last = stem values = make(map[int][]byte) @@ -871,6 +882,8 @@ func getSortedLeavesData(fname string) ([]verkle.BatchNewLeafNodeData, [256]int) values[int(tuples[i][31])] = tuples[i][32:] } - // dump the last group - return append(leavesData, verkle.BatchNewLeafNodeData{Stem: stem[:], Values: values}), secondByteIdxs + leavesData = append(leavesData, verkle.BatchNewLeafNodeData{Stem: last, Values: values}) + secondLvlLeavesData <- leavesData + + return nil } From cb593b199955fad589029615e2daf42719646e5e Mon Sep 17 00:00:00 2001 From: Ignacio Hagopian Date: Mon, 3 Apr 2023 15:23:03 -0300 Subject: [PATCH 13/22] verkle migration: build top two layers from processed subtrees Signed-off-by: Ignacio Hagopian --- cmd/geth/verkle.go | 36 ++++++++++++++++++++++++++++-------- 1 file changed, 28 insertions(+), 8 deletions(-) diff --git a/cmd/geth/verkle.go b/cmd/geth/verkle.go index f19c678dc129..f8eed2565a0a 100644 --- a/cmd/geth/verkle.go +++ b/cmd/geth/verkle.go @@ -28,7 +28,6 @@ import ( "runtime" "runtime/pprof" "sort" - "sync" "time" "github.com/ethereum/go-ethereum/cmd/utils" @@ -765,6 +764,7 @@ func sortKeys(ctx *cli.Context) error { // Run setup. start := time.Now() + var secondLevelCommitment [256][256][32]byte // List files and iterate on them files, _ := ioutil.ReadDir(".") for _, file := range files { @@ -786,8 +786,8 @@ func sortKeys(ctx *cli.Context) error { // Process secondLvlLeaves items and pipe the results to readyToSerializeSubtree. log.Info("Building tree", "name", file.Name()) readyToSerializeSubtree := make(chan []verkle.SerializedNode) - var lock sync.Mutex - var roots []*verkle.InternalNode + // var lock sync.Mutex + // var roots []*verkle.InternalNode go func() { group, _ := errgroup.WithContext(context.Background()) group.SetLimit(runtime.NumCPU()) @@ -796,6 +796,7 @@ func sortKeys(ctx *cli.Context) error { group.Go(func() error { leaves := verkle.BatchNewLeafNode(leavesData) root := verkle.BatchInsertOrderedLeaves(leaves) + root.Commit() nodes, err := root.BatchSerialize() if err != nil { return fmt.Errorf("failed to serialize nodes: %w", err) @@ -803,10 +804,16 @@ func sortKeys(ctx *cli.Context) error { sort.Slice(nodes, func(i, j int) bool { return bytes.Compare(nodes[i].CommitmentBytes[:], nodes[j].CommitmentBytes[:]) < 0 }) - lock.Lock() - roots = append(roots, root) - lock.Unlock() + // lock.Lock() + // roots = append(roots, root) + // lock.Unlock() + stem := leavesData[0].Stem + point, err := verkle.GetInternalNodeCommitment(root, stem[:2]) + if err != nil { + log.Crit("Failed to get commitment", "error", err) + } + secondLevelCommitment[stem[0]][stem[1]] = point.Bytes() readyToSerializeSubtree <- nodes return nil }) @@ -827,12 +834,25 @@ func sortKeys(ctx *cli.Context) error { } } - root := verkle.MergeLevelTwoPartitions(roots) - log.Info("Building tree finished", "root", fmt.Sprintf("%x", root.Commit().Bytes())) + // root := verkle.MergeLevelTwoPartitions(roots) + // log.Info("Building tree finished", "root", fmt.Sprintf("%x", root.Commit().Bytes())) runtime.GC() } + root := verkle.BuildFirstTwoLayers(secondLevelCommitment) + fmt.Printf("MARK\n") + log.Info("Building tree finished", "root", fmt.Sprintf("%x", root.Commit().Bytes())) + nodes, err := root.BatchSerialize() + if err != nil { + return fmt.Errorf("failed to serialize nodes: %w", err) + } + for _, node := range nodes { + if err := chaindb.Put(node.CommitmentBytes[:], node.SerializedBytes); err != nil { + log.Crit("put node to disk: %s", err) + } + } + log.Info("Finished", "elapsed", common.PrettyDuration(time.Since(start))) return nil } From f451ad0ff0180fac45a10cc45076984b31db1898 Mon Sep 17 00:00:00 2001 From: Ignacio Hagopian Date: Tue, 4 Apr 2023 10:33:46 -0300 Subject: [PATCH 14/22] verkle migraiton: batch database writes Signed-off-by: Ignacio Hagopian --- cmd/geth/verkle.go | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/cmd/geth/verkle.go b/cmd/geth/verkle.go index f8eed2565a0a..dc927fd5404d 100644 --- a/cmd/geth/verkle.go +++ b/cmd/geth/verkle.go @@ -34,6 +34,7 @@ import ( "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/core/rawdb" "github.com/ethereum/go-ethereum/core/state/snapshot" + "github.com/ethereum/go-ethereum/ethdb" "github.com/ethereum/go-ethereum/internal/flags" "github.com/ethereum/go-ethereum/log" "github.com/ethereum/go-ethereum/rlp" @@ -826,11 +827,18 @@ func sortKeys(ctx *cli.Context) error { // Serialize items in readyToSerializeSubtree and save them to disk. log.Info("Serializing tree") + batch := chaindb.NewBatchWithSize(ethdb.IdealBatchSize) for nodes := range readyToSerializeSubtree { for _, node := range nodes { - if err := chaindb.Put(node.CommitmentBytes[:], node.SerializedBytes); err != nil { + if err := batch.Put(node.CommitmentBytes[:], node.SerializedBytes); err != nil { log.Crit("put node to disk: %s", err) } + if batch.ValueSize() > ethdb.IdealBatchSize { + if err := batch.Write(); err != nil { + log.Crit("write batch: %s", err) + } + batch.Reset() + } } } @@ -841,7 +849,6 @@ func sortKeys(ctx *cli.Context) error { } root := verkle.BuildFirstTwoLayers(secondLevelCommitment) - fmt.Printf("MARK\n") log.Info("Building tree finished", "root", fmt.Sprintf("%x", root.Commit().Bytes())) nodes, err := root.BatchSerialize() if err != nil { From 892acbae368398c8e2a8b8e186e54e19ec0be55a Mon Sep 17 00:00:00 2001 From: Ignacio Hagopian Date: Tue, 4 Apr 2023 10:44:16 -0300 Subject: [PATCH 15/22] verkle migration: cleanup Signed-off-by: Ignacio Hagopian --- cmd/geth/verkle.go | 8 -------- 1 file changed, 8 deletions(-) diff --git a/cmd/geth/verkle.go b/cmd/geth/verkle.go index dc927fd5404d..27a0bcbf32ea 100644 --- a/cmd/geth/verkle.go +++ b/cmd/geth/verkle.go @@ -787,8 +787,6 @@ func sortKeys(ctx *cli.Context) error { // Process secondLvlLeaves items and pipe the results to readyToSerializeSubtree. log.Info("Building tree", "name", file.Name()) readyToSerializeSubtree := make(chan []verkle.SerializedNode) - // var lock sync.Mutex - // var roots []*verkle.InternalNode go func() { group, _ := errgroup.WithContext(context.Background()) group.SetLimit(runtime.NumCPU()) @@ -805,9 +803,6 @@ func sortKeys(ctx *cli.Context) error { sort.Slice(nodes, func(i, j int) bool { return bytes.Compare(nodes[i].CommitmentBytes[:], nodes[j].CommitmentBytes[:]) < 0 }) - // lock.Lock() - // roots = append(roots, root) - // lock.Unlock() stem := leavesData[0].Stem point, err := verkle.GetInternalNodeCommitment(root, stem[:2]) @@ -842,9 +837,6 @@ func sortKeys(ctx *cli.Context) error { } } - // root := verkle.MergeLevelTwoPartitions(roots) - // log.Info("Building tree finished", "root", fmt.Sprintf("%x", root.Commit().Bytes())) - runtime.GC() } From e5acacea6b294bff2d90b2104204798b30087594 Mon Sep 17 00:00:00 2001 From: Ignacio Hagopian Date: Tue, 4 Apr 2023 11:03:59 -0300 Subject: [PATCH 16/22] verkle migration: comment code Signed-off-by: Ignacio Hagopian --- cmd/geth/verkle.go | 72 ++++++++++++++++++++++++++-------------------- 1 file changed, 41 insertions(+), 31 deletions(-) diff --git a/cmd/geth/verkle.go b/cmd/geth/verkle.go index 27a0bcbf32ea..ceab7f6946ad 100644 --- a/cmd/geth/verkle.go +++ b/cmd/geth/verkle.go @@ -26,7 +26,6 @@ import ( "io/ioutil" "os" "runtime" - "runtime/pprof" "sort" "time" @@ -735,47 +734,36 @@ func dumpKeys(ctx *cli.Context) error { } func sortKeys(ctx *cli.Context) error { + // Run precomp preparation now to avoid racing in paralell goroutines if the + // precomputed table doesn't exist. _ = verkle.GetConfig() - /* - f2, err := os.Create("mem.out") - if err != nil { - panic(err) - } - defer f2.Close() - if err := pprof.WriteHeapProfile(f2); err != nil { - panic(err) - } - */ - - f, err := os.Create("cpu.out") - if err != nil { - panic(err) - } - defer f.Close() - pprof.StartCPUProfile(f) - defer pprof.StopCPUProfile() - // Open database + // Open database. stack, _ := makeConfigNode(ctx) defer stack.Close() chaindb := utils.MakeChainDatabase(ctx, stack, false) if chaindb == nil { return errors.New("nil chaindb") } - // Run setup. + start := time.Now() + // The migration code converts trees partitioned by the first two bytes of + // the stem. We'll collect in secondLevelCommitment[a][b] the commitment of + // the InternalNode with stem [a, b, ...]. We'll then use this to build the + // first two layers of the tree. var secondLevelCommitment [256][256][32]byte + // List files and iterate on them files, _ := ioutil.ReadDir(".") for _, file := range files { // Check if file is a binary file fname := file.Name() - if !bytes.HasSuffix([]byte(fname), []byte(".bin")) || bytes.HasPrefix([]byte(fname), []byte("sorted-")) || len(fname) != 6 { + if !bytes.HasSuffix([]byte(fname), []byte(".bin")) || len(fname) != 6 { continue } - // Read the file, partition in second-level subtrees, and push them into the channel to be processed. + // Read the file grouping leaves values by the first two bytes of the stem, and send them to secondLvlLeaves. secondLvlLeaves := make(chan []verkle.BatchNewLeafNodeData) go func() { if err := getSortedLeavesData(fname, secondLvlLeaves); err != nil { @@ -784,46 +772,66 @@ func sortKeys(ctx *cli.Context) error { close(secondLvlLeaves) }() - // Process secondLvlLeaves items and pipe the results to readyToSerializeSubtree. + // Process secondLvlLeaves items and pipe the results to serializedTrees. log.Info("Building tree", "name", file.Name()) - readyToSerializeSubtree := make(chan []verkle.SerializedNode) + serializedTrees := make(chan []verkle.SerializedNode) go func() { + // We read from the channel, and allow up to runtime.CPU() goroutines to process the data. + // This tries to use the most amount of CPUs, while also puts some backpressure on the channel + // to avoid using too much memory. group, _ := errgroup.WithContext(context.Background()) group.SetLimit(runtime.NumCPU()) for leavesData := range secondLvlLeaves { leavesData := leavesData group.Go(func() error { + // We generate the LeafNodes in an optimized way. leaves := verkle.BatchNewLeafNode(leavesData) + // We do an optimized tree construction from all the leaves at once. + // Note this is a partial tree since all the keys have hte same first two bytes of the stem. root := verkle.BatchInsertOrderedLeaves(leaves) root.Commit() + + // Serialize all the nodes of the generated tree, which takes advantage of many optimizations. nodes, err := root.BatchSerialize() if err != nil { return fmt.Errorf("failed to serialize nodes: %w", err) } + + // Sort the serialized nodes by their CommitmentBytes, which tries to help the database with + // future compactions when inserting. sort.Slice(nodes, func(i, j int) bool { return bytes.Compare(nodes[i].CommitmentBytes[:], nodes[j].CommitmentBytes[:]) < 0 }) - stem := leavesData[0].Stem + // Remember: this is a partial tree where all the keys have the same first two bytes of the stem. + // We collect now all the commitments of the InternalNodes with stem [a, b, ...] + // in secondLevelCommitment[a][b]. Note that each goroutine is working on a different + // place in the array, so there's no race-condition. + stem := leavesData[0].Stem // All the leaves have the same first 2-byte stem, take the first one. point, err := verkle.GetInternalNodeCommitment(root, stem[:2]) if err != nil { log.Crit("Failed to get commitment", "error", err) } secondLevelCommitment[stem[0]][stem[1]] = point.Bytes() - readyToSerializeSubtree <- nodes + + // Send the nodes to serializedTrees which will write them to disk. + serializedTrees <- nodes return nil }) } if err := group.Wait(); err != nil { log.Crit("Failed to build tree", "error", err) } - close(readyToSerializeSubtree) + close(serializedTrees) }() - // Serialize items in readyToSerializeSubtree and save them to disk. + // We receive serialized nodes from serializedTrees and write them to disk. + // We batch them into presumably optimal batches. Note this also puts backpressure + // to the previous channels if we can't write fast enough. That's useful because + // there's no reason to use more memory if things are lagging behind. Disk is slow. log.Info("Serializing tree") batch := chaindb.NewBatchWithSize(ethdb.IdealBatchSize) - for nodes := range readyToSerializeSubtree { + for nodes := range serializedTrees { for _, node := range nodes { if err := batch.Put(node.CommitmentBytes[:], node.SerializedBytes); err != nil { log.Crit("put node to disk: %s", err) @@ -837,9 +845,12 @@ func sortKeys(ctx *cli.Context) error { } } + // Just make sure to GC before the next file, so there's a bound of ~4GiB of memory used. runtime.GC() } + // From all the commitments of the InternalNodes with stem [a, b, ...] we build + // and save the first two layers of the tree. root := verkle.BuildFirstTwoLayers(secondLevelCommitment) log.Info("Building tree finished", "root", fmt.Sprintf("%x", root.Commit().Bytes())) nodes, err := root.BatchSerialize() @@ -885,7 +896,6 @@ func getSortedLeavesData(fname string, secondLvlLeavesData chan []verkle.BatchNe if len(tuples) > 0 { last = tuples[0][:31] } - // TODO(jsign): predict a bit good capacity. var leavesData []verkle.BatchNewLeafNodeData for i := range tuples { stem = tuples[i][:31] From 5d08fd16f65a76d1f10779491a537dd9bc67e441 Mon Sep 17 00:00:00 2001 From: Ignacio Hagopian Date: Wed, 5 Apr 2023 09:59:10 -0300 Subject: [PATCH 17/22] verkle migration: adjust to byte key Signed-off-by: Ignacio Hagopian --- cmd/geth/verkle.go | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/cmd/geth/verkle.go b/cmd/geth/verkle.go index ceab7f6946ad..cac191f59d6d 100644 --- a/cmd/geth/verkle.go +++ b/cmd/geth/verkle.go @@ -890,7 +890,7 @@ func getSortedLeavesData(fname string, secondLvlLeavesData chan []verkle.BatchNe log.Info("Merging file", "name", fname) var ( stem []byte - values = make(map[int][]byte, 5) + values = make(map[byte][]byte, 5) last []byte ) if len(tuples) > 0 { @@ -906,10 +906,10 @@ func getSortedLeavesData(fname string, secondLvlLeavesData chan []verkle.BatchNe leavesData = make([]verkle.BatchNewLeafNodeData, 0, len(leavesData)) } last = stem - values = make(map[int][]byte) + values = make(map[byte][]byte) } - values[int(tuples[i][31])] = tuples[i][32:] + values[tuples[i][31]] = tuples[i][32:] } leavesData = append(leavesData, verkle.BatchNewLeafNodeData{Stem: last, Values: values}) secondLvlLeavesData <- leavesData From 8c3caf8b8e3a2bcb1b67e873c4f2015ab5b4ab5a Mon Sep 17 00:00:00 2001 From: Ignacio Hagopian Date: Wed, 5 Apr 2023 17:42:24 -0300 Subject: [PATCH 18/22] verkle migration: add duration per file and estimated logs Signed-off-by: Ignacio Hagopian --- cmd/geth/verkle.go | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/cmd/geth/verkle.go b/cmd/geth/verkle.go index cac191f59d6d..1f2840024919 100644 --- a/cmd/geth/verkle.go +++ b/cmd/geth/verkle.go @@ -756,12 +756,13 @@ func sortKeys(ctx *cli.Context) error { // List files and iterate on them files, _ := ioutil.ReadDir(".") - for _, file := range files { + for fileIdx, file := range files { // Check if file is a binary file fname := file.Name() if !bytes.HasSuffix([]byte(fname), []byte(".bin")) || len(fname) != 6 { continue } + startFile := time.Now() // Read the file grouping leaves values by the first two bytes of the stem, and send them to secondLvlLeaves. secondLvlLeaves := make(chan []verkle.BatchNewLeafNodeData) @@ -847,6 +848,10 @@ func sortKeys(ctx *cli.Context) error { // Just make sure to GC before the next file, so there's a bound of ~4GiB of memory used. runtime.GC() + + historyAvgPerFile := time.Since(start) / time.Duration(fileIdx+1) + timeLeft := common.PrettyDuration(historyAvgPerFile * time.Duration(len(files)-fileIdx-1)) + log.Info("Subtree finished", "file", fname, "elapsed", common.PrettyDuration(time.Since(startFile)), "estimated_remaining", timeLeft.String()) } // From all the commitments of the InternalNodes with stem [a, b, ...] we build From ee16580a0f660dab49a0141135cd2eb3ef9b0a5e Mon Sep 17 00:00:00 2001 From: Ignacio Hagopian Date: Thu, 6 Apr 2023 13:18:18 -0300 Subject: [PATCH 19/22] mod: use corresponding go-verkle and go-ipa deps Signed-off-by: Ignacio Hagopian --- go.mod | 4 ++-- go.sum | 8 ++++---- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/go.mod b/go.mod index afde2beb413e..60e1d9326259 100644 --- a/go.mod +++ b/go.mod @@ -23,7 +23,7 @@ require ( github.com/fjl/gencodec v0.0.0-20220412091415-8bb9e558978c github.com/fjl/memsize v0.0.0-20190710130421-bcb5799ab5e5 github.com/gballet/go-libpcsclite v0.0.0-20190607065134-2772fd86a8ff - github.com/gballet/go-verkle v0.0.0-20230413135631-4bea2763ed0f + github.com/gballet/go-verkle v0.0.0-20230406161123-14eaab595ed4 github.com/go-stack/stack v1.8.0 github.com/golang-jwt/jwt/v4 v4.3.0 github.com/golang/protobuf v1.5.2 @@ -107,4 +107,4 @@ require ( gopkg.in/yaml.v3 v3.0.1 // indirect ) -replace github.com/gballet/go-verkle => ../../go-verkle +replace github.com/crate-crypto/go-ipa => github.com/jsign/go-ipa v0.0.0-20230323132738-cd121cd65e68 diff --git a/go.sum b/go.sum index 728030c6ffcb..035558574626 100644 --- a/go.sum +++ b/go.sum @@ -137,10 +137,8 @@ github.com/garslo/gogen v0.0.0-20170306192744-1d203ffc1f61 h1:IZqZOB2fydHte3kUgx github.com/garslo/gogen v0.0.0-20170306192744-1d203ffc1f61/go.mod h1:Q0X6pkwTILDlzrGEckF6HKjXe48EgsY/l7K7vhY4MW8= github.com/gballet/go-libpcsclite v0.0.0-20190607065134-2772fd86a8ff h1:tY80oXqGNY4FhTFhk+o9oFHGINQ/+vhlm8HFzi6znCI= github.com/gballet/go-libpcsclite v0.0.0-20190607065134-2772fd86a8ff/go.mod h1:x7DCsMOv1taUwEWCzT4cmDeAkigA5/QCwUodaVOe8Ww= -github.com/gballet/go-verkle v0.0.0-20230317174103-141354da6b11 h1:x4hiQFgr1SlqR4IoAZiXLFZK4L7KbibqkORqa1fwKp8= -github.com/gballet/go-verkle v0.0.0-20230317174103-141354da6b11/go.mod h1:IyOnn1kujMWaT+wet/6Ix1BtvYwateOBy9puuWH/8sw= -github.com/gballet/go-verkle v0.0.0-20230413135631-4bea2763ed0f h1:gP4uR2/1qx6hsIzbRI28JWcsVuP7xyjyj6SpLnoFobc= -github.com/gballet/go-verkle v0.0.0-20230413135631-4bea2763ed0f/go.mod h1:P3bwGrLhsUNIsUDlq2yzMPvO1c/15oiB3JS85P+hNfw= +github.com/gballet/go-verkle v0.0.0-20230406161123-14eaab595ed4 h1:C7DwAGkiiI07J0BuV2dmp+QSuURjuFlZVFKU0L/uong= +github.com/gballet/go-verkle v0.0.0-20230406161123-14eaab595ed4/go.mod h1:IyOnn1kujMWaT+wet/6Ix1BtvYwateOBy9puuWH/8sw= github.com/getkin/kin-openapi v0.53.0/go.mod h1:7Yn5whZr5kJi6t+kShccXS8ae1APpYTW6yheSwk8Yi4= github.com/getkin/kin-openapi v0.61.0/go.mod h1:7Yn5whZr5kJi6t+kShccXS8ae1APpYTW6yheSwk8Yi4= github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= @@ -257,6 +255,8 @@ github.com/jedisct1/go-minisign v0.0.0-20190909160543-45766022959e h1:UvSe12bq+U github.com/jedisct1/go-minisign v0.0.0-20190909160543-45766022959e/go.mod h1:G1CVv03EnqU1wYL2dFwXxW2An0az9JTl/ZsqXQeBlkU= github.com/jmespath/go-jmespath v0.4.0/go.mod h1:T8mJZnbsbmF+m6zOOFylbeCJqk5+pHWvzYPziyZiYoo= github.com/jmespath/go-jmespath/internal/testify v1.5.1/go.mod h1:L3OGu8Wl2/fWfCI6z80xFu9LTZmf1ZRjMHUOPmWr69U= +github.com/jsign/go-ipa v0.0.0-20230323132738-cd121cd65e68 h1:w0ko/S0wlKJvv0uV70abNCxYd6fkiGUQqT93afrfcmM= +github.com/jsign/go-ipa v0.0.0-20230323132738-cd121cd65e68/go.mod h1:gzbVz57IDJgQ9rLQwfSk696JGWof8ftznEL9GoAv3NI= github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU= github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU= github.com/jstemmer/go-junit-report v0.9.1/go.mod h1:Brl9GWCQeLvo8nXZwPNNblvFj/XSXhF0NWZEnDohbsk= From 57fde22430707014c43638b928d5af34ec6b3428 Mon Sep 17 00:00:00 2001 From: Ignacio Hagopian Date: Thu, 13 Apr 2023 12:03:27 -0300 Subject: [PATCH 20/22] verkle migration: support smaller trees Signed-off-by: Ignacio Hagopian --- cmd/geth/verkle.go | 5 +---- go.mod | 4 +--- go.sum | 8 ++------ 3 files changed, 4 insertions(+), 13 deletions(-) diff --git a/cmd/geth/verkle.go b/cmd/geth/verkle.go index 1f2840024919..6fabbddcc81a 100644 --- a/cmd/geth/verkle.go +++ b/cmd/geth/verkle.go @@ -809,10 +809,7 @@ func sortKeys(ctx *cli.Context) error { // in secondLevelCommitment[a][b]. Note that each goroutine is working on a different // place in the array, so there's no race-condition. stem := leavesData[0].Stem // All the leaves have the same first 2-byte stem, take the first one. - point, err := verkle.GetInternalNodeCommitment(root, stem[:2]) - if err != nil { - log.Crit("Failed to get commitment", "error", err) - } + point := verkle.GetInternalNodeCommitment(root, stem[:2]) secondLevelCommitment[stem[0]][stem[1]] = point.Bytes() // Send the nodes to serializedTrees which will write them to disk. diff --git a/go.mod b/go.mod index 60e1d9326259..4b96f5b2ce5a 100644 --- a/go.mod +++ b/go.mod @@ -23,7 +23,7 @@ require ( github.com/fjl/gencodec v0.0.0-20220412091415-8bb9e558978c github.com/fjl/memsize v0.0.0-20190710130421-bcb5799ab5e5 github.com/gballet/go-libpcsclite v0.0.0-20190607065134-2772fd86a8ff - github.com/gballet/go-verkle v0.0.0-20230406161123-14eaab595ed4 + github.com/gballet/go-verkle v0.0.0-20230413150157-a32ba2800509 github.com/go-stack/stack v1.8.0 github.com/golang-jwt/jwt/v4 v4.3.0 github.com/golang/protobuf v1.5.2 @@ -106,5 +106,3 @@ require ( gopkg.in/yaml.v2 v2.4.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect ) - -replace github.com/crate-crypto/go-ipa => github.com/jsign/go-ipa v0.0.0-20230323132738-cd121cd65e68 diff --git a/go.sum b/go.sum index 035558574626..3c794da73aa2 100644 --- a/go.sum +++ b/go.sum @@ -86,8 +86,6 @@ github.com/consensys/gnark-crypto v0.4.1-0.20210426202927-39ac3d4b3f1f/go.mod h1 github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU= github.com/cpuguy83/go-md2man/v2 v2.0.2 h1:p1EgwI/C7NhT0JmVkwCD2ZBK8j4aeHQX2pMHHBfMQ6w= github.com/cpuguy83/go-md2man/v2 v2.0.2/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= -github.com/crate-crypto/go-ipa v0.0.0-20230315201338-1643fdc2ead8 h1:2EBbIwPDRqlCD2K34Eojyy0x9d3RhOuHAZfbQm508X8= -github.com/crate-crypto/go-ipa v0.0.0-20230315201338-1643fdc2ead8/go.mod h1:gzbVz57IDJgQ9rLQwfSk696JGWof8ftznEL9GoAv3NI= github.com/crate-crypto/go-ipa v0.0.0-20230410135559-ce4a96995014 h1:bbyTlFQ12wkFA6aVL+9HrBZwVl85AN0VS/Bwam7o93U= github.com/crate-crypto/go-ipa v0.0.0-20230410135559-ce4a96995014/go.mod h1:gzbVz57IDJgQ9rLQwfSk696JGWof8ftznEL9GoAv3NI= github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= @@ -137,8 +135,8 @@ github.com/garslo/gogen v0.0.0-20170306192744-1d203ffc1f61 h1:IZqZOB2fydHte3kUgx github.com/garslo/gogen v0.0.0-20170306192744-1d203ffc1f61/go.mod h1:Q0X6pkwTILDlzrGEckF6HKjXe48EgsY/l7K7vhY4MW8= github.com/gballet/go-libpcsclite v0.0.0-20190607065134-2772fd86a8ff h1:tY80oXqGNY4FhTFhk+o9oFHGINQ/+vhlm8HFzi6znCI= github.com/gballet/go-libpcsclite v0.0.0-20190607065134-2772fd86a8ff/go.mod h1:x7DCsMOv1taUwEWCzT4cmDeAkigA5/QCwUodaVOe8Ww= -github.com/gballet/go-verkle v0.0.0-20230406161123-14eaab595ed4 h1:C7DwAGkiiI07J0BuV2dmp+QSuURjuFlZVFKU0L/uong= -github.com/gballet/go-verkle v0.0.0-20230406161123-14eaab595ed4/go.mod h1:IyOnn1kujMWaT+wet/6Ix1BtvYwateOBy9puuWH/8sw= +github.com/gballet/go-verkle v0.0.0-20230413150157-a32ba2800509 h1:x1PgDhyRk2RKDXjLEVhSf2TW2aia9F+aD44GQYbLnvk= +github.com/gballet/go-verkle v0.0.0-20230413150157-a32ba2800509/go.mod h1:P3bwGrLhsUNIsUDlq2yzMPvO1c/15oiB3JS85P+hNfw= github.com/getkin/kin-openapi v0.53.0/go.mod h1:7Yn5whZr5kJi6t+kShccXS8ae1APpYTW6yheSwk8Yi4= github.com/getkin/kin-openapi v0.61.0/go.mod h1:7Yn5whZr5kJi6t+kShccXS8ae1APpYTW6yheSwk8Yi4= github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= @@ -255,8 +253,6 @@ github.com/jedisct1/go-minisign v0.0.0-20190909160543-45766022959e h1:UvSe12bq+U github.com/jedisct1/go-minisign v0.0.0-20190909160543-45766022959e/go.mod h1:G1CVv03EnqU1wYL2dFwXxW2An0az9JTl/ZsqXQeBlkU= github.com/jmespath/go-jmespath v0.4.0/go.mod h1:T8mJZnbsbmF+m6zOOFylbeCJqk5+pHWvzYPziyZiYoo= github.com/jmespath/go-jmespath/internal/testify v1.5.1/go.mod h1:L3OGu8Wl2/fWfCI6z80xFu9LTZmf1ZRjMHUOPmWr69U= -github.com/jsign/go-ipa v0.0.0-20230323132738-cd121cd65e68 h1:w0ko/S0wlKJvv0uV70abNCxYd6fkiGUQqT93afrfcmM= -github.com/jsign/go-ipa v0.0.0-20230323132738-cd121cd65e68/go.mod h1:gzbVz57IDJgQ9rLQwfSk696JGWof8ftznEL9GoAv3NI= github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU= github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU= github.com/jstemmer/go-junit-report v0.9.1/go.mod h1:Brl9GWCQeLvo8nXZwPNNblvFj/XSXhF0NWZEnDohbsk= From e5ee0371f8e5808b603f43487459d49f3024f837 Mon Sep 17 00:00:00 2001 From: Ignacio Hagopian Date: Thu, 13 Apr 2023 16:08:25 -0300 Subject: [PATCH 21/22] mod: use latest PR version of go-verkle Signed-off-by: Ignacio Hagopian --- go.mod | 2 +- go.sum | 6 ++---- 2 files changed, 3 insertions(+), 5 deletions(-) diff --git a/go.mod b/go.mod index 4b96f5b2ce5a..082f8a2a06e8 100644 --- a/go.mod +++ b/go.mod @@ -23,7 +23,7 @@ require ( github.com/fjl/gencodec v0.0.0-20220412091415-8bb9e558978c github.com/fjl/memsize v0.0.0-20190710130421-bcb5799ab5e5 github.com/gballet/go-libpcsclite v0.0.0-20190607065134-2772fd86a8ff - github.com/gballet/go-verkle v0.0.0-20230413150157-a32ba2800509 + github.com/gballet/go-verkle v0.0.0-20230413165055-0ebfd8549906 github.com/go-stack/stack v1.8.0 github.com/golang-jwt/jwt/v4 v4.3.0 github.com/golang/protobuf v1.5.2 diff --git a/go.sum b/go.sum index 3c794da73aa2..bb2cf3e8ab85 100644 --- a/go.sum +++ b/go.sum @@ -135,8 +135,8 @@ github.com/garslo/gogen v0.0.0-20170306192744-1d203ffc1f61 h1:IZqZOB2fydHte3kUgx github.com/garslo/gogen v0.0.0-20170306192744-1d203ffc1f61/go.mod h1:Q0X6pkwTILDlzrGEckF6HKjXe48EgsY/l7K7vhY4MW8= github.com/gballet/go-libpcsclite v0.0.0-20190607065134-2772fd86a8ff h1:tY80oXqGNY4FhTFhk+o9oFHGINQ/+vhlm8HFzi6znCI= github.com/gballet/go-libpcsclite v0.0.0-20190607065134-2772fd86a8ff/go.mod h1:x7DCsMOv1taUwEWCzT4cmDeAkigA5/QCwUodaVOe8Ww= -github.com/gballet/go-verkle v0.0.0-20230413150157-a32ba2800509 h1:x1PgDhyRk2RKDXjLEVhSf2TW2aia9F+aD44GQYbLnvk= -github.com/gballet/go-verkle v0.0.0-20230413150157-a32ba2800509/go.mod h1:P3bwGrLhsUNIsUDlq2yzMPvO1c/15oiB3JS85P+hNfw= +github.com/gballet/go-verkle v0.0.0-20230413165055-0ebfd8549906 h1:T/z0/Xg6VwrTdw6oZcQyw6vLjDF5+g/15ppwSWgBMP8= +github.com/gballet/go-verkle v0.0.0-20230413165055-0ebfd8549906/go.mod h1:P3bwGrLhsUNIsUDlq2yzMPvO1c/15oiB3JS85P+hNfw= github.com/getkin/kin-openapi v0.53.0/go.mod h1:7Yn5whZr5kJi6t+kShccXS8ae1APpYTW6yheSwk8Yi4= github.com/getkin/kin-openapi v0.61.0/go.mod h1:7Yn5whZr5kJi6t+kShccXS8ae1APpYTW6yheSwk8Yi4= github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= @@ -554,8 +554,6 @@ golang.org/x/sys v0.0.0-20211019181941-9d821ace8654/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20211020174200-9d6173849985/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220919091848-fb04ddd9f9c8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.6.0 h1:MVltZSvRTcU2ljQOhs94SXPftV6DCNnZViHeQps87pQ= -golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.7.0 h1:3jlCCIQZPdOYu1h8BkNvLz8Kgwtae2cagcG/VamtZRU= golang.org/x/sys v0.7.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw= From 50c776aa4459fa87f3807b7a09a858b4c68dbeea Mon Sep 17 00:00:00 2001 From: Ignacio Hagopian Date: Mon, 17 Apr 2023 09:45:17 -0300 Subject: [PATCH 22/22] Update cmd/geth/verkle.go Co-authored-by: Guillaume Ballet <3272758+gballet@users.noreply.github.com> --- cmd/geth/verkle.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cmd/geth/verkle.go b/cmd/geth/verkle.go index 6fabbddcc81a..c8b209f2780e 100644 --- a/cmd/geth/verkle.go +++ b/cmd/geth/verkle.go @@ -788,7 +788,7 @@ func sortKeys(ctx *cli.Context) error { // We generate the LeafNodes in an optimized way. leaves := verkle.BatchNewLeafNode(leavesData) // We do an optimized tree construction from all the leaves at once. - // Note this is a partial tree since all the keys have hte same first two bytes of the stem. + // Note this is a partial tree since all the keys have the same first two bytes of the stem. root := verkle.BatchInsertOrderedLeaves(leaves) root.Commit()