diff --git a/cmd/pics/state.go b/cmd/pics/state.go index 149a84d34cbf594457239c8a84eb7d7307799820..d59f66ffe0ad3adbba6d4db30e614de79dffd09a 100644 --- a/cmd/pics/state.go +++ b/cmd/pics/state.go @@ -584,7 +584,7 @@ func initialState1() error { return err } var witness bytes.Buffer - if err = bwb.WriteTo(&witness); err != nil { + if _, err = bwb.WriteTo(&witness); err != nil { return err } var witnessTrie *trie.Trie diff --git a/cmd/state/state.go b/cmd/state/state.go index 005ed3f8065c0f9d0c2bfc20f76663d1a98ac7de..6cf4d1d720fd444586a22e6261f218e5d89374f3 100644 --- a/cmd/state/state.go +++ b/cmd/state/state.go @@ -58,6 +58,7 @@ var preroot = flag.Bool("preroot", false, "Attempt to compute hash of the trie w var snapshotInterval = flag.Uint64("snapshotInterval", 0, "how often to take snapshots (0 - never, 1 - every block, 1000 - every 1000th block, etc)") var snapshotFrom = flag.Uint64("snapshotFrom", 0, "from which block to start snapshots") var witnessInterval = flag.Uint64("witnessInterval", 1, "after which block to extract witness (put a large number like 10000000 to disable)") +var statsfile = flag.String("statsfile", "stateless.csv", "path where to write the stats file") func check(e error) { if e != nil { @@ -1681,26 +1682,11 @@ func main() { return ethdb.NewBoltDatabase(path) } - stateless(*chaindata, *statefile, *triesize, *preroot, *snapshotInterval, *snapshotFrom, *witnessInterval, createDb) + stateless(*chaindata, *statefile, *triesize, *preroot, *snapshotInterval, *snapshotFrom, *witnessInterval, *statsfile, createDb) } if *action == "stateless_chart" { - stateless_chart_key_values("/Users/alexeyakhunov/mygit/go-ethereum/st_1/stateless.csv", []int{21, 20, 19, 18}, "breakdown.png", 2800000, 1) - } - //stateless_chart_key_values("stateless1.csv", []int{17}, "total.png", 1, 0) - //stateless_chart_key_values("stateless1_256.csv", []int{17}, "total256.png", 1, 0) - //stateless_chart_key_values([]int{17}, "total_2675000.png", 2675000, 0) - //stateless_chart_key_values("stateless1.csv", []int{12, 15, 16}, "breakdown.png", 1, 1) - //stateless_chart_key_values("stateless1_256.csv", []int{12, 15, 16}, "breakdown256.png", 1, 1) - //stateless_chart_key_values([]int{12, 15, 16}, "breakdown_2675000.png", 2675000, 1) - //stateless_chart_key_values("stateless1.csv", []int{13,14}, "key_vals.png", 1, 4) - //stateless_chart_key_values("stateless1_256.csv", []int{13,14}, "key_vals256.png", 1, 4) - //stateless_chart_key_values("stateless1.csv", []int{10,11}, "c_key_vals.png", 1, 4) - //stateless_chart_key_values("stateless1_256.csv", []int{10,11}, "c_key_vals256.png", 1, 4) - //stateless_chart_key_values("stateless1.csv", []int{6, 7}, "mask_hash.png", 1, 4) - //stateless_chart_key_values("stateless1_256.csv", []int{6, 7}, "mask_hash256.png", 1, 4) - //stateless_chart_key_values("stateless1.csv", []int{1, 2}, "c_mask_hash.png", 1, 4) - //stateless_chart_key_values("stateless1_256.csv", []int{1, 2}, "c_mask_hash256.png", 1, 4) - //stateless_chart_key_values([]int{12}, "codes_28m.png", 2800000) + statelessDoKVChart(*statsfile, []int{21, 20, 19, 18}, fmt.Sprintf("%s-chart.png", *statsfile), 2800000, 1) + } if *action == "stateSnapshot" { if err := stateSnapshot(); err != nil { fmt.Printf("Error: %v\n", err) diff --git a/cmd/state/stateless.go b/cmd/state/stateless.go index 90d1458b148d5a249a1bccc9fbe02871569c88c6..00a2dcf5a0fc15dedab9a2357b4e90746f5e9b0b 100644 --- a/cmd/state/stateless.go +++ b/cmd/state/stateless.go @@ -1,12 +1,8 @@ package main import ( - "bufio" - "bytes" "context" - "encoding/csv" "fmt" - "io/ioutil" "os" "os/signal" "syscall" @@ -24,6 +20,7 @@ import ( "github.com/ledgerwatch/turbo-geth/core/vm" "github.com/ledgerwatch/turbo-geth/ethdb" "github.com/ledgerwatch/turbo-geth/params" + "github.com/ledgerwatch/turbo-geth/trie" ) var chartColors = []drawing.Color{ @@ -71,41 +68,6 @@ func runBlock(dbstate *state.Stateless, chainConfig *params.ChainConfig, return nil } -/* -func writeStats(w io.Writer, blockNum uint64, blockProof trie.BlockProof) { - var totalCShorts, totalCValues, totalCodes, totalShorts, totalValues int - for _, short := range blockProof.CShortKeys { - l := len(short) - if short[l-1] == 16 { - l -= 1 - } - l = l/2 + 1 - totalCShorts += l - } - for _, value := range blockProof.CValues { - totalCValues += len(value) - } - for _, code := range blockProof.Codes { - totalCodes += len(code) - } - for _, short := range blockProof.ShortKeys { - l := len(short) - if short[l-1] == 16 { - l -= 1 - } - l = l/2 + 1 - totalShorts += l - } - for _, value := range blockProof.Values { - totalValues += len(value) - } - fmt.Fprintf(w, "%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d\n", - blockNum, len(blockProof.Contracts), len(blockProof.CMasks), len(blockProof.CHashes), len(blockProof.CShortKeys), len(blockProof.CValues), len(blockProof.Codes), - len(blockProof.Masks), len(blockProof.Hashes), len(blockProof.ShortKeys), len(blockProof.Values), totalCShorts, totalCValues, totalCodes, totalShorts, totalValues, - ) -} -*/ - type CreateDbFunc func(string) (ethdb.Database, error) func stateless(chaindata string, @@ -115,6 +77,7 @@ func stateless(chaindata string, interval uint64, ignoreOlderThan uint64, witnessThreshold uint64, + statsfile string, createDb CreateDbFunc) { state.MaxTrieCacheGen = uint32(triesize) @@ -132,11 +95,11 @@ func stateless(chaindata string, check(err) defer ethDb.Close() chainConfig := params.MainnetChainConfig - slFile, err := os.OpenFile("stateless.csv", os.O_APPEND|os.O_WRONLY|os.O_CREATE, 0600) + + stats, err := NewStatsFile(statsfile) check(err) - defer slFile.Close() - w := bufio.NewWriter(slFile) - defer w.Flush() + defer stats.Close() + vmConfig := vm.Config{} engine := ethash.NewFullFaker() bcb, err := core.NewBlockChain(ethDb, nil, chainConfig, engine, vm.Config{}, nil) @@ -223,11 +186,15 @@ func stateless(chaindata string, witness = nil if blockNum >= witnessThreshold { // Witness has to be extracted before the state trie is modified - witness, err = tds.ExtractWitness(trace) + var tapeStats trie.WitnessTapeStats + witness, tapeStats, err = tds.ExtractWitness(trace) if err != nil { fmt.Printf("error extracting witness for block %d: %v\n", blockNum, err) return } + + err = stats.AddRow(blockNum, witness, tapeStats) + check(err) } finalRootFail := false if blockNum >= witnessThreshold && witness != nil { // witness == nil means the extraction fails @@ -336,178 +303,3 @@ func stateless(chaindata string, fmt.Printf("Next time specify -block %d\n", blockNum) fmt.Printf("Stateless client analysis took %s\n", time.Since(startTime)) } - -func stateless_chart_key_values(filename string, right []int, chartFileName string, start int, startColor int) { - file, err := os.Open(filename) - check(err) - defer file.Close() - reader := csv.NewReader(bufio.NewReader(file)) - var blocks []float64 - var vals [22][]float64 - count := 0 - for records, _ := reader.Read(); len(records) == 16; records, _ = reader.Read() { - count++ - if count < start { - continue - } - blocks = append(blocks, parseFloat64(records[0])/1000000.0) - for i := 0; i < 22; i++ { - cProofs := 4.0*parseFloat64(records[2]) + 32.0*parseFloat64(records[3]) + parseFloat64(records[11]) + parseFloat64(records[12]) - proofs := 4.0*parseFloat64(records[7]) + 32.0*parseFloat64(records[8]) + parseFloat64(records[14]) + parseFloat64(records[15]) - switch i { - case 1, 6: - vals[i] = append(vals[i], 4.0*parseFloat64(records[i+1])) - case 2, 7: - vals[i] = append(vals[i], 32.0*parseFloat64(records[i+1])) - case 15: - vals[i] = append(vals[i], cProofs) - case 16: - vals[i] = append(vals[i], proofs) - case 17: - vals[i] = append(vals[i], cProofs+proofs+parseFloat64(records[13])) - case 18: - vals[i] = append(vals[i], 4.0*parseFloat64(records[2])+4.0*parseFloat64(records[7])) - case 19: - vals[i] = append(vals[i], 4.0*parseFloat64(records[2])+4.0*parseFloat64(records[7])+ - parseFloat64(records[3])+parseFloat64(records[4])+parseFloat64(records[10])+parseFloat64(records[11])) - case 20: - vals[i] = append(vals[i], 4.0*parseFloat64(records[2])+4.0*parseFloat64(records[7])+ - parseFloat64(records[4])+parseFloat64(records[5])+parseFloat64(records[10])+parseFloat64(records[11])+ - 32.0*parseFloat64(records[3])+32.0*parseFloat64(records[8])) - case 21: - vals[i] = append(vals[i], 4.0*parseFloat64(records[2])+4.0*parseFloat64(records[7])+ - parseFloat64(records[4])+parseFloat64(records[5])+parseFloat64(records[10])+parseFloat64(records[11])+ - 32.0*parseFloat64(records[3])+32.0*parseFloat64(records[8])+parseFloat64(records[13])) - default: - vals[i] = append(vals[i], parseFloat64(records[i+1])) - } - } - } - var windowSums [22]float64 - var window int = 1024 - var movingAvgs [22][]float64 - for i := 0; i < 22; i++ { - movingAvgs[i] = make([]float64, len(blocks)-(window-1)) - } - for j := 0; j < len(blocks); j++ { - for i := 0; i < 22; i++ { - windowSums[i] += vals[i][j] - } - if j >= window { - for i := 0; i < 22; i++ { - windowSums[i] -= vals[i][j-window] - } - } - if j >= window-1 { - for i := 0; i < 22; i++ { - movingAvgs[i][j-window+1] = windowSums[i] / float64(window) - } - } - } - movingBlock := blocks[window-1:] - seriesNames := [22]string{ - "Number of contracts", - "Contract masks", - "Contract hashes", - "Number of contract leaf keys", - "Number of contract leaf vals", - "Number of contract codes", - "Masks", - "Hashes", - "Number of leaf keys", - "Number of leaf values", - "Total size of contract leaf keys", - "Total size of contract leaf vals", - "Total size of codes", - "Total size of leaf keys", - "Total size of leaf vals", - "Block proofs (contracts only)", - "Block proofs (without contracts)", - "Block proofs (total)", - "Structure (total)", - "Leaves (total)", - "Hashes (total)", - "Code (total)", - } - var currentColor int = startColor - var series []chart.Series - for _, r := range right { - s := &chart.ContinuousSeries{ - Name: seriesNames[r], - Style: chart.Style{ - Show: true, - StrokeWidth: 0.0, - StrokeColor: chartColors[currentColor], - FillColor: chartColors[currentColor], - //FillColor: chartColors[currentColor].WithAlpha(100), - }, - XValues: movingBlock, - YValues: movingAvgs[r], - } - currentColor++ - series = append(series, s) - } - - graph1 := chart.Chart{ - Width: 1280, - Height: 720, - Background: chart.Style{ - Padding: chart.Box{ - Top: 50, - }, - }, - YAxis: chart.YAxis{ - Name: "kBytes", - NameStyle: chart.StyleShow(), - Style: chart.StyleShow(), - TickStyle: chart.Style{ - TextRotationDegrees: 45.0, - }, - ValueFormatter: func(v interface{}) string { - return fmt.Sprintf("%d kB", int(v.(float64)/1024.0)) - }, - GridMajorStyle: chart.Style{ - Show: true, - StrokeColor: chart.ColorBlack, - StrokeWidth: 1.0, - }, - //GridLines: days(), - }, - /* - YAxisSecondary: chart.YAxis{ - NameStyle: chart.StyleShow(), - Style: chart.StyleShow(), - TickStyle: chart.Style{ - TextRotationDegrees: 45.0, - }, - ValueFormatter: func(v interface{}) string { - return fmt.Sprintf("%d", int(v.(float64))) - }, - }, - */ - XAxis: chart.XAxis{ - Name: "Blocks, million", - Style: chart.Style{ - Show: true, - }, - ValueFormatter: func(v interface{}) string { - return fmt.Sprintf("%.3fm", v.(float64)) - }, - GridMajorStyle: chart.Style{ - Show: true, - StrokeColor: chart.ColorAlternateGray, - StrokeWidth: 1.0, - }, - //GridLines: blockMillions(), - }, - Series: series, - } - - graph1.Elements = []chart.Renderable{chart.LegendThin(&graph1)} - - buffer := bytes.NewBuffer([]byte{}) - err = graph1.Render(chart.PNG, buffer) - check(err) - err = ioutil.WriteFile(chartFileName, buffer.Bytes(), 0644) - check(err) -} diff --git a/cmd/state/stateless_chart.go b/cmd/state/stateless_chart.go new file mode 100644 index 0000000000000000000000000000000000000000..b4a942e255b3c209b40e3d9c11b0ec8df08b67bb --- /dev/null +++ b/cmd/state/stateless_chart.go @@ -0,0 +1,187 @@ +package main + +import ( + "bufio" + "bytes" + "encoding/csv" + "fmt" + "io/ioutil" + "os" + + chart "github.com/wcharczuk/go-chart" +) + +func statelessDoKVChart(filename string, right []int, chartFileName string, start int, startColor int) { + file, err := os.Open(filename) + check(err) + defer file.Close() + reader := csv.NewReader(bufio.NewReader(file)) + var blocks []float64 + var vals [22][]float64 + count := 0 + for records, _ := reader.Read(); len(records) == 16; records, _ = reader.Read() { + count++ + if count < start { + continue + } + blocks = append(blocks, parseFloat64(records[0])/1000000.0) + for i := 0; i < 22; i++ { + cProofs := 4.0*parseFloat64(records[2]) + 32.0*parseFloat64(records[3]) + parseFloat64(records[11]) + parseFloat64(records[12]) + proofs := 4.0*parseFloat64(records[7]) + 32.0*parseFloat64(records[8]) + parseFloat64(records[14]) + parseFloat64(records[15]) + switch i { + case 1, 6: + vals[i] = append(vals[i], 4.0*parseFloat64(records[i+1])) + case 2, 7: + vals[i] = append(vals[i], 32.0*parseFloat64(records[i+1])) + case 15: + vals[i] = append(vals[i], cProofs) + case 16: + vals[i] = append(vals[i], proofs) + case 17: + vals[i] = append(vals[i], cProofs+proofs+parseFloat64(records[13])) + case 18: + vals[i] = append(vals[i], 4.0*parseFloat64(records[2])+4.0*parseFloat64(records[7])) + case 19: + vals[i] = append(vals[i], 4.0*parseFloat64(records[2])+4.0*parseFloat64(records[7])+ + parseFloat64(records[3])+parseFloat64(records[4])+parseFloat64(records[10])+parseFloat64(records[11])) + case 20: + vals[i] = append(vals[i], 4.0*parseFloat64(records[2])+4.0*parseFloat64(records[7])+ + parseFloat64(records[4])+parseFloat64(records[5])+parseFloat64(records[10])+parseFloat64(records[11])+ + 32.0*parseFloat64(records[3])+32.0*parseFloat64(records[8])) + case 21: + vals[i] = append(vals[i], 4.0*parseFloat64(records[2])+4.0*parseFloat64(records[7])+ + parseFloat64(records[4])+parseFloat64(records[5])+parseFloat64(records[10])+parseFloat64(records[11])+ + 32.0*parseFloat64(records[3])+32.0*parseFloat64(records[8])+parseFloat64(records[13])) + default: + vals[i] = append(vals[i], parseFloat64(records[i+1])) + } + } + } + var windowSums [22]float64 + window := 1024 + var movingAvgs [22][]float64 + for i := 0; i < 22; i++ { + movingAvgs[i] = make([]float64, len(blocks)-(window-1)) + } + for j := 0; j < len(blocks); j++ { + for i := 0; i < 22; i++ { + windowSums[i] += vals[i][j] + } + if j >= window { + for i := 0; i < 22; i++ { + windowSums[i] -= vals[i][j-window] + } + } + if j >= window-1 { + for i := 0; i < 22; i++ { + movingAvgs[i][j-window+1] = windowSums[i] / float64(window) + } + } + } + movingBlock := blocks[window-1:] + seriesNames := [22]string{ + "Number of contracts", + "Contract masks", + "Contract hashes", + "Number of contract leaf keys", + "Number of contract leaf vals", + "Number of contract codes", + "Masks", + "Hashes", + "Number of leaf keys", + "Number of leaf values", + "Total size of contract leaf keys", + "Total size of contract leaf vals", + "Total size of codes", + "Total size of leaf keys", + "Total size of leaf vals", + "Block proofs (contracts only)", + "Block proofs (without contracts)", + "Block proofs (total)", + "Structure (total)", + "Leaves (total)", + "Hashes (total)", + "Code (total)", + } + currentColor := startColor + series := make([]chart.Series, len(right)) + for i, r := range right { + s := &chart.ContinuousSeries{ + Name: seriesNames[r], + Style: chart.Style{ + Show: true, + StrokeWidth: 0.0, + StrokeColor: chartColors[currentColor], + FillColor: chartColors[currentColor], + //FillColor: chartColors[currentColor].WithAlpha(100), + }, + XValues: movingBlock, + YValues: movingAvgs[r], + } + currentColor++ + series[i] = s + } + + graph1 := chart.Chart{ + Width: 1280, + Height: 720, + Background: chart.Style{ + Padding: chart.Box{ + Top: 50, + }, + }, + YAxis: chart.YAxis{ + Name: "kBytes", + NameStyle: chart.StyleShow(), + Style: chart.StyleShow(), + TickStyle: chart.Style{ + TextRotationDegrees: 45.0, + }, + ValueFormatter: func(v interface{}) string { + return fmt.Sprintf("%d kB", int(v.(float64)/1024.0)) + }, + GridMajorStyle: chart.Style{ + Show: true, + StrokeColor: chart.ColorBlack, + StrokeWidth: 1.0, + }, + //GridLines: days(), + }, + /* + YAxisSecondary: chart.YAxis{ + NameStyle: chart.StyleShow(), + Style: chart.StyleShow(), + TickStyle: chart.Style{ + TextRotationDegrees: 45.0, + }, + ValueFormatter: func(v interface{}) string { + return fmt.Sprintf("%d", int(v.(float64))) + }, + }, + */ + XAxis: chart.XAxis{ + Name: "Blocks, million", + Style: chart.Style{ + Show: true, + }, + ValueFormatter: func(v interface{}) string { + return fmt.Sprintf("%.3fm", v.(float64)) + }, + GridMajorStyle: chart.Style{ + Show: true, + StrokeColor: chart.ColorAlternateGray, + StrokeWidth: 1.0, + }, + //GridLines: blockMillions(), + }, + Series: series, + } + + graph1.Elements = []chart.Renderable{chart.LegendThin(&graph1)} + + buffer := bytes.NewBuffer([]byte{}) + err = graph1.Render(chart.PNG, buffer) + check(err) + err = ioutil.WriteFile(chartFileName, buffer.Bytes(), 0644) + check(err) +} diff --git a/cmd/state/stateless_stats.go b/cmd/state/stateless_stats.go new file mode 100644 index 0000000000000000000000000000000000000000..92e049850fa35a44dfa679dad93e30a14b9c83fd --- /dev/null +++ b/cmd/state/stateless_stats.go @@ -0,0 +1,73 @@ +package main + +import ( + "encoding/csv" + "fmt" + "io" + "os" + + "github.com/ledgerwatch/turbo-geth/trie" +) + +var keys = []string{"balances", "codes", "hashes", "keys", "nonces", "structure", "values"} + +type StatsFile struct { + file io.WriteCloser + buffer *csv.Writer + hasHeader bool +} + +func NewStatsFile(path string) (*StatsFile, error) { + _, err := os.Stat(path) + appending := err == nil || !os.IsNotExist(err) + + w, err := os.OpenFile(path, os.O_APPEND|os.O_WRONLY|os.O_CREATE, 0600) + if err != nil { + return nil, err + } + + return &StatsFile{file: w, buffer: csv.NewWriter(w), hasHeader: appending}, nil +} + +func (s *StatsFile) writeHeader() error { + return s.buffer.Write( + append([]string{"block-number", "witness"}, keys...), + ) +} + +func (s *StatsFile) AddRow(blockNum uint64, witness []byte, tapeStats trie.WitnessTapeStats) error { + if !s.hasHeader { + fmt.Println("writing header") + if err := s.writeHeader(); err != nil { + return err + } + s.hasHeader = true + } + fields := make([]string, 2+len(keys)) + fieldIndex := 0 + + fields[fieldIndex] = stringify(blockNum) + fieldIndex++ + + fields[fieldIndex] = stringify(uint64(len(witness))) + fieldIndex++ + + for _, key := range keys { + fields[fieldIndex] = stringify(uint64(tapeStats.GetOrZero(key))) + fieldIndex++ + } + + return s.buffer.Write(fields) +} + +func (s *StatsFile) Close() error { + s.buffer.Flush() + if err := s.buffer.Error(); err != nil { + return err + } + return s.file.Close() +} + +func stringify(v uint64) string { + return fmt.Sprintf("%d", v) +} diff --git a/core/state/database.go b/core/state/database.go index f2e9d010a3f80ac8ab3142cb130d2a89db8411f1..3a647da622ce8a48610549319e6884fd28bf56dc 100644 --- a/core/state/database.go +++ b/core/state/database.go @@ -1131,7 +1131,7 @@ func (dsw *DbStateWriter) WriteAccountStorage(ctx context.Context, address commo } // ExtractWitness produces block witness for the block just been processed, in a serialised form -func (tds *TrieDbState) ExtractWitness(trace bool) ([]byte, error) { +func (tds *TrieDbState) ExtractWitness(trace bool) ([]byte, trie.WitnessTapeStats, error) { bwb := trie.NewBlockWitnessBuilder(trace) rs := trie.NewResolveSet(0) touches, storageTouches := tds.pg.ExtractTouches() @@ -1143,13 +1143,17 @@ func (tds *TrieDbState) ExtractWitness(trace bool) ([]byte, error) { } codeMap := tds.pg.ExtractCodeMap() if err := bwb.MakeBlockWitness(tds.t, rs, codeMap); err != nil { - return nil, err + return nil, nil, err } var b bytes.Buffer - if err := bwb.WriteTo(&b); err != nil { - return nil, err + + stats, err := bwb.WriteTo(&b) + + if err != nil { + return nil, nil, err } - return b.Bytes(), nil + + return b.Bytes(), stats, nil } func (tsw *TrieStateWriter) CreateContract(address common.Address) error { diff --git a/trie/proof_generator.go b/trie/proof_generator.go index 095479bd04e7f0c3ec1b109b4aba8320cff6123b..d6116519d83b0f756bd6e8fe171b49d4e6aaf3c4 100644 --- a/trie/proof_generator.go +++ b/trie/proof_generator.go @@ -28,6 +28,12 @@ import ( "github.com/ugorji/go/codec" ) +type WitnessTapeStats map[string]int + +func (s WitnessTapeStats) GetOrZero(key string) int { + return s[key] +} + // TapeBuilder stores the sequence of values that is getting serialised using CBOR into a byte buffer type TapeBuilder struct { buffer bytes.Buffer // Byte buffer where the CBOR-encoded values end up being written @@ -445,7 +451,8 @@ func (bwb *BlockWitnessBuilder) makeBlockWitness( // WriteTo creates serialised representation of the block witness // and writes it into the given writer -func (bwb *BlockWitnessBuilder) WriteTo(w io.Writer) error { +// returns stats (tape lengths) and stuff +func (bwb *BlockWitnessBuilder) WriteTo(w io.Writer) (WitnessTapeStats, error) { // Calculate the lengths of all the tapes and write them as an array var lens = map[string]int{ KeyTape: bwb.Keys.buffer.Len(), @@ -460,30 +467,30 @@ func (bwb *BlockWitnessBuilder) WriteTo(w io.Writer) error { handle.EncodeOptions.Canonical = true encoder := codec.NewEncoder(w, &handle) if err := encoder.Encode(&lens); err != nil { - return err + return nil, err } if _, err := bwb.Keys.buffer.WriteTo(w); err != nil { - return err + return nil, err } if _, err := bwb.Values.buffer.WriteTo(w); err != nil { - return err + return nil, err } if _, err := bwb.Nonces.buffer.WriteTo(w); err != nil { - return err + return nil, err } if _, err := bwb.Balances.buffer.WriteTo(w); err != nil { - return err + return nil, err } if _, err := bwb.Hashes.buffer.WriteTo(w); err != nil { - return err + return nil, err } if _, err := bwb.Codes.buffer.WriteTo(w); err != nil { - return err + return nil, err } if _, err := bwb.Structure.buffer.WriteTo(w); err != nil { - return err + return nil, err } - return nil + return WitnessTapeStats(lens), nil } // CborBytesTape implements BytesTape and takes values from CBOR-encoded slice of bytes diff --git a/trie/proof_generator_test.go b/trie/proof_generator_test.go index ee84b838d7bcc051708c293339a92922bd617ad8..427f4a6ffc972b40c0a1421a138adfe443d5d941 100644 --- a/trie/proof_generator_test.go +++ b/trie/proof_generator_test.go @@ -179,7 +179,7 @@ func TestSerialiseBlockWitness(t *testing.T) { t.Errorf("Could not make block witness: %v", err) } var b bytes.Buffer - if err := bwb.WriteTo(&b); err != nil { + if _, err := bwb.WriteTo(&b); err != nil { t.Errorf("Could not make block witness: %v", err) }