From c6dbe9dc079eadffea9171b26c41feecc8af6eef Mon Sep 17 00:00:00 2001 From: Taylor Gerring Date: Thu, 25 Jun 2015 16:46:54 +0200 Subject: [PATCH 1/7] Travis and README cleanup --- .travis.yml | 9 +++------ README.md | 7 +++---- 2 files changed, 6 insertions(+), 10 deletions(-) diff --git a/.travis.yml b/.travis.yml index 11daadd413..ff3ff71f71 100644 --- a/.travis.yml +++ b/.travis.yml @@ -2,7 +2,6 @@ language: go go: - 1.4.2 before_install: - - sudo add-apt-repository ppa:beineri/opt-qt541 -y - sudo apt-get update -qq - sudo apt-get install -yqq libgmp3-dev install: @@ -22,14 +21,12 @@ after_success: - if [ "$COVERALLS_TOKEN" ]; then goveralls -coverprofile=profile.cov -service=travis-ci -repotoken $COVERALLS_TOKEN; fi env: global: - - PKG_CONFIG_PATH=/opt/qt54/lib/pkgconfig - - LD_LIBRARY_PATH=/opt/qt54/lib - secure: "U2U1AmkU4NJBgKR/uUAebQY87cNL0+1JHjnLOmmXwxYYyj5ralWb1aSuSH3qSXiT93qLBmtaUkuv9fberHVqrbAeVlztVdUsKAq7JMQH+M99iFkC9UiRMqHmtjWJ0ok4COD1sRYixxi21wb/JrMe3M1iL4QJVS61iltjHhVdM64=" notifications: webhooks: urls: - https://webhooks.gitter.im/e/e09ccdce1048c5e03445 - on_success: change # options: [always|never|change] default: always - on_failure: always # options: [always|never|change] default: always - on_start: false # default: false + on_success: change + on_failure: always + on_start: false diff --git a/README.md b/README.md index a411d9eb89..4093aff647 100644 --- a/README.md +++ b/README.md @@ -44,11 +44,10 @@ Executables Go Ethereum comes with several wrappers/executables found in [the `cmd` directory](https://github.com/ethereum/go-ethereum/tree/develop/cmd): -* `mist` Official Ethereum Browser (ethereum GUI client) * `geth` Ethereum CLI (ethereum command line interface client) * `bootnode` runs a bootstrap node for the Discovery Protocol -* `ethtest` test tool which runs with the [tests](https://github.com/ethereum/testes) suite: - `cat file | ethtest`. +* `ethtest` test tool which runs with the [tests](https://github.com/ethereum/tests) suite: + `/path/to/test.json > ethtest --test BlockTests --stdin`. * `evm` is a generic Ethereum Virtual Machine: `evm -code 60ff60ff -gas 10000 -price 0 -dump`. See `-h` for a detailed description. * `disasm` disassembles EVM code: `echo "6001" | disasm` @@ -57,7 +56,7 @@ Go Ethereum comes with several wrappers/executables found in Command line options ==================== -Both `mist` and `geth` can be configured via command line options, environment variables and config files. +`geth` can be configured via command line options, environment variables and config files. To get the options available: From d84638bd31878f772c6d1de3b491160319ddfc4b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?P=C3=A9ter=20Szil=C3=A1gyi?= Date: Fri, 26 Jun 2015 15:48:50 +0300 Subject: [PATCH 2/7] p2p: support protocol version negotiation --- p2p/peer.go | 11 +++++- p2p/peer_test.go | 95 ++++++++++++++++++++++++++++++++++++++++++++++++ p2p/protocol.go | 10 +++-- 3 files changed, 110 insertions(+), 6 deletions(-) diff --git a/p2p/peer.go b/p2p/peer.go index 40466cf846..e1bda1d036 100644 --- a/p2p/peer.go +++ b/p2p/peer.go @@ -249,15 +249,22 @@ func countMatchingProtocols(protocols []Protocol, caps []Cap) int { // matchProtocols creates structures for matching named subprotocols. func matchProtocols(protocols []Protocol, caps []Cap, rw MsgReadWriter) map[string]*protoRW { - sort.Sort(capsByName(caps)) + sort.Sort(capsByNameAndVersion(caps)) offset := baseProtocolLength result := make(map[string]*protoRW) + outer: for _, cap := range caps { for _, proto := range protocols { - if proto.Name == cap.Name && proto.Version == cap.Version && result[cap.Name] == nil { + if proto.Name == cap.Name && proto.Version == cap.Version { + // If an old protocol version matched, revert it + if old := result[cap.Name]; old != nil { + offset -= old.Length + } + // Assign the new match result[cap.Name] = &protoRW{Protocol: proto, offset: offset, in: make(chan Msg), w: rw} offset += proto.Length + continue outer } } diff --git a/p2p/peer_test.go b/p2p/peer_test.go index 575d0ff793..95167f4a1e 100644 --- a/p2p/peer_test.go +++ b/p2p/peer_test.go @@ -196,3 +196,98 @@ func TestNewPeer(t *testing.T) { p.Disconnect(DiscAlreadyConnected) // Should not hang } + +func TestMatchProtocols(t *testing.T) { + tests := []struct { + Local []Cap + Remote []Protocol + Match map[string]protoRW + }{ + { + // No remote protocols + Local: []Cap{{Name: "a"}}, + }, + { + // No local capabilities + Remote: []Protocol{{Name: "a"}}, + }, + { + // No mutual protocols + Local: []Cap{{Name: "a"}}, + Remote: []Protocol{{Name: "b"}}, + }, + { + // Some matches, some differences + Local: []Cap{{Name: "local"}, {Name: "match1"}, {Name: "match2"}}, + Remote: []Protocol{{Name: "match1"}, {Name: "match2"}, {Name: "remote"}}, + Match: map[string]protoRW{"match1": {Protocol: Protocol{Name: "match1"}}, "match2": {Protocol: Protocol{Name: "match2"}}}, + }, + { + // Various alphabetical ordering + Local: []Cap{{Name: "aa"}, {Name: "ab"}, {Name: "bb"}, {Name: "ba"}}, + Remote: []Protocol{{Name: "ba"}, {Name: "bb"}, {Name: "ab"}, {Name: "aa"}}, + Match: map[string]protoRW{"aa": {Protocol: Protocol{Name: "aa"}}, "ab": {Protocol: Protocol{Name: "ab"}}, "ba": {Protocol: Protocol{Name: "ba"}}, "bb": {Protocol: Protocol{Name: "bb"}}}, + }, + { + // No mutual versions + Local: []Cap{{Version: 1}}, + Remote: []Protocol{{Version: 2}}, + }, + { + // Multiple versions, single common + Local: []Cap{{Version: 1}, {Version: 2}}, + Remote: []Protocol{{Version: 2}, {Version: 3}}, + Match: map[string]protoRW{"": {Protocol: Protocol{Version: 2}}}, + }, + { + // Multiple versions, multiple common + Local: []Cap{{Version: 1}, {Version: 2}, {Version: 3}, {Version: 4}}, + Remote: []Protocol{{Version: 2}, {Version: 3}}, + Match: map[string]protoRW{"": {Protocol: Protocol{Version: 3}}}, + }, + { + // Various version orderings + Local: []Cap{{Version: 4}, {Version: 1}, {Version: 3}, {Version: 2}}, + Remote: []Protocol{{Version: 2}, {Version: 3}, {Version: 1}}, + Match: map[string]protoRW{"": {Protocol: Protocol{Version: 3}}}, + }, + { + // Versions overriding sub-protocol lengths + Local: []Cap{{Version: 1}, {Version: 2}, {Version: 3}, {Name: "a"}}, + Remote: []Protocol{{Version: 1, Length: 1}, {Version: 2, Length: 2}, {Version: 3, Length: 3}, {Name: "a"}}, + Match: map[string]protoRW{"": {Protocol: Protocol{Version: 3}}, "a": {Protocol: Protocol{Name: "a"}, offset: 3}}, + }, + } + + for i, tt := range tests { + result := matchProtocols(tt.Remote, tt.Local, nil) + if len(result) != len(tt.Match) { + t.Errorf("test %d: negotiation mismatch: have %v, want %v", i, len(result), len(tt.Match)) + continue + } + // Make sure all negotiated protocols are needed and correct + for name, proto := range result { + match, ok := tt.Match[name] + if !ok { + t.Errorf("test %d, proto '%s': negotiated but shouldn't have", i, name) + continue + } + if proto.Name != match.Name { + t.Errorf("test %d, proto '%s': name mismatch: have %v, want %v", i, name, proto.Name, match.Name) + } + if proto.Version != match.Version { + t.Errorf("test %d, proto '%s': version mismatch: have %v, want %v", i, name, proto.Version, match.Version) + } + if proto.offset-baseProtocolLength != match.offset { + t.Errorf("test %d, proto '%s': offset mismatch: have %v, want %v", i, name, proto.offset-baseProtocolLength, match.offset) + } + } + // Make sure no protocols missed negotiation + for name, _ := range tt.Match { + if _, ok := result[name]; !ok { + t.Errorf("test %d, proto '%s': not negotiated, should have", i, name) + continue + } + } + } +} diff --git a/p2p/protocol.go b/p2p/protocol.go index 5fa395eda4..a229ba911b 100644 --- a/p2p/protocol.go +++ b/p2p/protocol.go @@ -43,8 +43,10 @@ func (cap Cap) String() string { return fmt.Sprintf("%s/%d", cap.Name, cap.Version) } -type capsByName []Cap +type capsByNameAndVersion []Cap -func (cs capsByName) Len() int { return len(cs) } -func (cs capsByName) Less(i, j int) bool { return cs[i].Name < cs[j].Name } -func (cs capsByName) Swap(i, j int) { cs[i], cs[j] = cs[j], cs[i] } +func (cs capsByNameAndVersion) Len() int { return len(cs) } +func (cs capsByNameAndVersion) Swap(i, j int) { cs[i], cs[j] = cs[j], cs[i] } +func (cs capsByNameAndVersion) Less(i, j int) bool { + return cs[i].Name < cs[j].Name || (cs[i].Name == cs[j].Name && cs[i].Version < cs[j].Version) +} From 216fc267fafa6e27b14f642d0440cbd817a3a2d3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?P=C3=A9ter=20Szil=C3=A1gyi?= Date: Fri, 26 Jun 2015 20:45:13 +0300 Subject: [PATCH 3/7] p2p: fix local/remote cap/protocol mixup --- p2p/peer_test.go | 46 +++++++++++++++++++++++----------------------- 1 file changed, 23 insertions(+), 23 deletions(-) diff --git a/p2p/peer_test.go b/p2p/peer_test.go index 95167f4a1e..d849c925f8 100644 --- a/p2p/peer_test.go +++ b/p2p/peer_test.go @@ -199,68 +199,68 @@ func TestNewPeer(t *testing.T) { func TestMatchProtocols(t *testing.T) { tests := []struct { - Local []Cap - Remote []Protocol + Remote []Cap + Local []Protocol Match map[string]protoRW }{ { - // No remote protocols - Local: []Cap{{Name: "a"}}, + // No remote capabilities + Local: []Protocol{{Name: "a"}}, }, { - // No local capabilities - Remote: []Protocol{{Name: "a"}}, + // No local protocols + Remote: []Cap{{Name: "a"}}, }, { // No mutual protocols - Local: []Cap{{Name: "a"}}, - Remote: []Protocol{{Name: "b"}}, + Remote: []Cap{{Name: "a"}}, + Local: []Protocol{{Name: "b"}}, }, { // Some matches, some differences - Local: []Cap{{Name: "local"}, {Name: "match1"}, {Name: "match2"}}, - Remote: []Protocol{{Name: "match1"}, {Name: "match2"}, {Name: "remote"}}, + Remote: []Cap{{Name: "local"}, {Name: "match1"}, {Name: "match2"}}, + Local: []Protocol{{Name: "match1"}, {Name: "match2"}, {Name: "remote"}}, Match: map[string]protoRW{"match1": {Protocol: Protocol{Name: "match1"}}, "match2": {Protocol: Protocol{Name: "match2"}}}, }, { // Various alphabetical ordering - Local: []Cap{{Name: "aa"}, {Name: "ab"}, {Name: "bb"}, {Name: "ba"}}, - Remote: []Protocol{{Name: "ba"}, {Name: "bb"}, {Name: "ab"}, {Name: "aa"}}, + Remote: []Cap{{Name: "aa"}, {Name: "ab"}, {Name: "bb"}, {Name: "ba"}}, + Local: []Protocol{{Name: "ba"}, {Name: "bb"}, {Name: "ab"}, {Name: "aa"}}, Match: map[string]protoRW{"aa": {Protocol: Protocol{Name: "aa"}}, "ab": {Protocol: Protocol{Name: "ab"}}, "ba": {Protocol: Protocol{Name: "ba"}}, "bb": {Protocol: Protocol{Name: "bb"}}}, }, { // No mutual versions - Local: []Cap{{Version: 1}}, - Remote: []Protocol{{Version: 2}}, + Remote: []Cap{{Version: 1}}, + Local: []Protocol{{Version: 2}}, }, { // Multiple versions, single common - Local: []Cap{{Version: 1}, {Version: 2}}, - Remote: []Protocol{{Version: 2}, {Version: 3}}, + Remote: []Cap{{Version: 1}, {Version: 2}}, + Local: []Protocol{{Version: 2}, {Version: 3}}, Match: map[string]protoRW{"": {Protocol: Protocol{Version: 2}}}, }, { // Multiple versions, multiple common - Local: []Cap{{Version: 1}, {Version: 2}, {Version: 3}, {Version: 4}}, - Remote: []Protocol{{Version: 2}, {Version: 3}}, + Remote: []Cap{{Version: 1}, {Version: 2}, {Version: 3}, {Version: 4}}, + Local: []Protocol{{Version: 2}, {Version: 3}}, Match: map[string]protoRW{"": {Protocol: Protocol{Version: 3}}}, }, { // Various version orderings - Local: []Cap{{Version: 4}, {Version: 1}, {Version: 3}, {Version: 2}}, - Remote: []Protocol{{Version: 2}, {Version: 3}, {Version: 1}}, + Remote: []Cap{{Version: 4}, {Version: 1}, {Version: 3}, {Version: 2}}, + Local: []Protocol{{Version: 2}, {Version: 3}, {Version: 1}}, Match: map[string]protoRW{"": {Protocol: Protocol{Version: 3}}}, }, { // Versions overriding sub-protocol lengths - Local: []Cap{{Version: 1}, {Version: 2}, {Version: 3}, {Name: "a"}}, - Remote: []Protocol{{Version: 1, Length: 1}, {Version: 2, Length: 2}, {Version: 3, Length: 3}, {Name: "a"}}, + Remote: []Cap{{Version: 1}, {Version: 2}, {Version: 3}, {Name: "a"}}, + Local: []Protocol{{Version: 1, Length: 1}, {Version: 2, Length: 2}, {Version: 3, Length: 3}, {Name: "a"}}, Match: map[string]protoRW{"": {Protocol: Protocol{Version: 3}}, "a": {Protocol: Protocol{Name: "a"}, offset: 3}}, }, } for i, tt := range tests { - result := matchProtocols(tt.Remote, tt.Local, nil) + result := matchProtocols(tt.Local, tt.Remote, nil) if len(result) != len(tt.Match) { t.Errorf("test %d: negotiation mismatch: have %v, want %v", i, len(result), len(tt.Match)) continue From 7e69392249b37369a1dd6e10bb31b7e2e655b05d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?P=C3=A9ter=20Szil=C3=A1gyi?= Date: Fri, 26 Jun 2015 21:48:21 +0300 Subject: [PATCH 4/7] cmd/geth: re-scale charts when changing unit magnitudes --- cmd/geth/monitorcmd.go | 62 ++++++++++++++++++++++++++---------------- 1 file changed, 38 insertions(+), 24 deletions(-) diff --git a/cmd/geth/monitorcmd.go b/cmd/geth/monitorcmd.go index bb9c61a008..545ac3274d 100644 --- a/cmd/geth/monitorcmd.go +++ b/cmd/geth/monitorcmd.go @@ -103,33 +103,20 @@ func monitor(ctx *cli.Context) { footer.Height = 3 charts := make([]*termui.LineChart, len(monitored)) + units := make([]int, len(monitored)) data := make([][]float64, len(monitored)) for i := 0; i < len(data); i++ { data[i] = make([]float64, 512) } - for i, metric := range monitored { - charts[i] = termui.NewLineChart() - if runtime.GOOS == "windows" { - charts[i].Mode = "dot" - } - charts[i].Data = make([]float64, 512) - charts[i].DataLabels = []string{""} - charts[i].Height = (termui.TermHeight() - footer.Height) / rows - charts[i].AxesColor = termui.ColorWhite - charts[i].PaddingBottom = -2 - - charts[i].Border.Label = metric - charts[i].Border.LabelFgColor = charts[i].Border.FgColor | termui.AttrBold - charts[i].Border.FgColor = charts[i].Border.BgColor - + for i := 0; i < len(monitored); i++ { + charts[i] = createChart((termui.TermHeight() - footer.Height) / rows) row := termui.Body.Rows[i%rows] row.Cols = append(row.Cols, termui.NewCol(12/cols, 0, charts[i])) } termui.Body.AddRows(termui.NewRow(termui.NewCol(12, 0, footer))) - termui.Body.Align() - termui.Render(termui.Body) - refreshCharts(xeth, monitored, data, charts, ctx, footer) + refreshCharts(xeth, monitored, data, units, charts, ctx, footer) + termui.Body.Align() termui.Render(termui.Body) // Watch for various system events, and periodically refresh the charts @@ -149,7 +136,9 @@ func monitor(ctx *cli.Context) { termui.Render(termui.Body) } case <-refresh: - refreshCharts(xeth, monitored, data, charts, ctx, footer) + if refreshCharts(xeth, monitored, data, units, charts, ctx, footer) { + termui.Body.Align() + } termui.Render(termui.Body) } } @@ -246,18 +235,21 @@ func fetchMetric(metrics map[string]interface{}, metric string) float64 { // refreshCharts retrieves a next batch of metrics, and inserts all the new // values into the active datasets and charts -func refreshCharts(xeth *rpc.Xeth, metrics []string, data [][]float64, charts []*termui.LineChart, ctx *cli.Context, footer *termui.Par) { +func refreshCharts(xeth *rpc.Xeth, metrics []string, data [][]float64, units []int, charts []*termui.LineChart, ctx *cli.Context, footer *termui.Par) (realign bool) { values, err := retrieveMetrics(xeth) for i, metric := range metrics { data[i] = append([]float64{fetchMetric(values, metric)}, data[i][:len(data[i])-1]...) - updateChart(metric, data[i], charts[i], err) + if updateChart(metric, data[i], &units[i], charts[i], err) { + realign = true + } } updateFooter(ctx, err, footer) + return } // updateChart inserts a dataset into a line chart, scaling appropriately as to // not display weird labels, also updating the chart label accordingly. -func updateChart(metric string, data []float64, chart *termui.LineChart, err error) { +func updateChart(metric string, data []float64, base *int, chart *termui.LineChart, err error) (realign bool) { dataUnits := []string{"", "K", "M", "G", "T", "E"} timeUnits := []string{"ns", "µs", "ms", "s", "ks", "ms"} colors := []termui.Attribute{termui.ColorBlue, termui.ColorCyan, termui.ColorGreen, termui.ColorYellow, termui.ColorRed, termui.ColorRed} @@ -274,17 +266,20 @@ func updateChart(metric string, data []float64, chart *termui.LineChart, err err for high >= 1000 { high, unit, scale = high/1000, unit+1, scale*1000 } + // If the unit changes, re-create the chart (hack to set max height...) + if unit != *base { + realign, *base, *chart = true, unit, *createChart(chart.Height) + } // Update the chart's data points with the scaled values for i, value := range data { chart.Data[i] = value / scale } // Update the chart's label with the scale units - chart.Border.Label = metric - units := dataUnits if strings.Contains(metric, "/Percentiles/") || strings.Contains(metric, "/pauses/") { units = timeUnits } + chart.Border.Label = metric if len(units[unit]) > 0 { chart.Border.Label += " [" + units[unit] + "]" } @@ -292,6 +287,25 @@ func updateChart(metric string, data []float64, chart *termui.LineChart, err err if err != nil { chart.LineColor = termui.ColorRed | termui.AttrBold } + return +} + +// createChart creates an empty line chart with the default configs. +func createChart(height int) *termui.LineChart { + chart := termui.NewLineChart() + if runtime.GOOS == "windows" { + chart.Mode = "dot" + } + chart.Data = make([]float64, 512) + chart.DataLabels = []string{""} + chart.Height = height + chart.AxesColor = termui.ColorWhite + chart.PaddingBottom = -2 + + chart.Border.LabelFgColor = chart.Border.FgColor | termui.AttrBold + chart.Border.FgColor = chart.Border.BgColor + + return chart } // updateFooter updates the footer contents based on any encountered errors. From d099a42c8564405f2f08b83ec67e0fd96fb03732 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?P=C3=A9ter=20Szil=C3=A1gyi?= Date: Fri, 26 Jun 2015 22:05:49 +0300 Subject: [PATCH 5/7] cmd/geth: fix monitor panic, don't pre-fill with dummy data --- cmd/geth/monitorcmd.go | 28 ++++++++++++++++++---------- 1 file changed, 18 insertions(+), 10 deletions(-) diff --git a/cmd/geth/monitorcmd.go b/cmd/geth/monitorcmd.go index 545ac3274d..fe771b561f 100644 --- a/cmd/geth/monitorcmd.go +++ b/cmd/geth/monitorcmd.go @@ -105,9 +105,6 @@ func monitor(ctx *cli.Context) { charts := make([]*termui.LineChart, len(monitored)) units := make([]int, len(monitored)) data := make([][]float64, len(monitored)) - for i := 0; i < len(data); i++ { - data[i] = make([]float64, 512) - } for i := 0; i < len(monitored); i++ { charts[i] = createChart((termui.TermHeight() - footer.Height) / rows) row := termui.Body.Rows[i%rows] @@ -238,7 +235,11 @@ func fetchMetric(metrics map[string]interface{}, metric string) float64 { func refreshCharts(xeth *rpc.Xeth, metrics []string, data [][]float64, units []int, charts []*termui.LineChart, ctx *cli.Context, footer *termui.Par) (realign bool) { values, err := retrieveMetrics(xeth) for i, metric := range metrics { - data[i] = append([]float64{fetchMetric(values, metric)}, data[i][:len(data[i])-1]...) + if len(data) < 512 { + data[i] = append([]float64{fetchMetric(values, metric)}, data[i]...) + } else { + data[i] = append([]float64{fetchMetric(values, metric)}, data[i][:len(data[i])-1]...) + } if updateChart(metric, data[i], &units[i], charts[i], err) { realign = true } @@ -255,12 +256,16 @@ func updateChart(metric string, data []float64, base *int, chart *termui.LineCha colors := []termui.Attribute{termui.ColorBlue, termui.ColorCyan, termui.ColorGreen, termui.ColorYellow, termui.ColorRed, termui.ColorRed} // Extract only part of the data that's actually visible - data = data[:chart.Width*2] - + if chart.Width*2 < len(data) { + data = data[:chart.Width*2] + } // Find the maximum value and scale under 1K - high := data[0] - for _, value := range data[1:] { - high = math.Max(high, value) + high := 0.0 + if len(data) > 0 { + high = data[0] + for _, value := range data[1:] { + high = math.Max(high, value) + } } unit, scale := 0, 1.0 for high >= 1000 { @@ -271,6 +276,10 @@ func updateChart(metric string, data []float64, base *int, chart *termui.LineCha realign, *base, *chart = true, unit, *createChart(chart.Height) } // Update the chart's data points with the scaled values + if cap(chart.Data) < len(data) { + chart.Data = make([]float64, len(data)) + } + chart.Data = chart.Data[:len(data)] for i, value := range data { chart.Data[i] = value / scale } @@ -296,7 +305,6 @@ func createChart(height int) *termui.LineChart { if runtime.GOOS == "windows" { chart.Mode = "dot" } - chart.Data = make([]float64, 512) chart.DataLabels = []string{""} chart.Height = height chart.AxesColor = termui.ColorWhite From 29d53b20739645eb6ecab3ef79ecf3518eae6b68 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?P=C3=A9ter=20Szil=C3=A1gyi?= Date: Mon, 29 Jun 2015 13:49:04 +0300 Subject: [PATCH 6/7] eth/fetcher: don't double filter/fetch the same block --- eth/fetcher/fetcher.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/eth/fetcher/fetcher.go b/eth/fetcher/fetcher.go index 07a32b9f1c..69f3cb5d1e 100644 --- a/eth/fetcher/fetcher.go +++ b/eth/fetcher/fetcher.go @@ -323,7 +323,7 @@ func (f *Fetcher) loop() { hash := block.Hash() // Filter explicitly requested blocks from hash announcements - if _, ok := f.fetching[hash]; ok { + if f.fetching[hash] != nil && f.queued[hash] == nil { // Discard if already imported by other means if f.getBlock(hash) == nil { explicit = append(explicit, block) From a7d22658ad81064abad5a12bd38545c98a0c508c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?P=C3=A9ter=20Szil=C3=A1gyi?= Date: Mon, 29 Jun 2015 14:20:13 +0300 Subject: [PATCH 7/7] eth/fetcher: don't drop on future blocks, just not propagate --- eth/fetcher/fetcher.go | 20 ++++++++++++++++---- 1 file changed, 16 insertions(+), 4 deletions(-) diff --git a/eth/fetcher/fetcher.go b/eth/fetcher/fetcher.go index 69f3cb5d1e..5a1509f89d 100644 --- a/eth/fetcher/fetcher.go +++ b/eth/fetcher/fetcher.go @@ -7,6 +7,8 @@ import ( "math/rand" "time" + "github.com/ethereum/go-ethereum/core" + "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/logger" @@ -104,6 +106,7 @@ type Fetcher struct { broadcastMeter metrics.Meter // Counter for metering the inbound propagations broadcastTimer metrics.Timer // Counter and timer for metering the block forwarding discardMeter metrics.Meter // Counter for metering the discarded blocks + futureMeter metrics.Meter // Counter for metering future blocks } // New creates a block fetcher to retrieve blocks based on hash announcements. @@ -131,6 +134,7 @@ func New(getBlock blockRetrievalFn, validateBlock blockValidatorFn, broadcastBlo broadcastMeter: metrics.GetOrRegisterMeter("eth/sync/RemoteBroadcasts", metrics.DefaultRegistry), broadcastTimer: metrics.GetOrRegisterTimer("eth/sync/LocalBroadcasts", metrics.DefaultRegistry), discardMeter: metrics.GetOrRegisterMeter("eth/sync/DiscardedBlocks", metrics.DefaultRegistry), + futureMeter: metrics.GetOrRegisterMeter("eth/sync/FutureBlocks", metrics.DefaultRegistry), } } @@ -416,14 +420,22 @@ func (f *Fetcher) insert(peer string, block *types.Block) { return } // Quickly validate the header and propagate the block if it passes - if err := f.validateBlock(block, parent); err != nil { + switch err := f.validateBlock(block, parent); err { + case nil: + // All ok, quickly propagate to our peers + f.broadcastTimer.UpdateSince(block.ReceivedAt) + go f.broadcastBlock(block, true) + + case core.BlockFutureErr: + f.futureMeter.Mark(1) + // Weird future block, don't fail, but neither propagate + + default: + // Something went very wrong, drop the peer glog.V(logger.Debug).Infof("Peer %s: block #%d [%x] verification failed: %v", peer, block.NumberU64(), hash[:4], err) f.dropPeer(peer) return } - f.broadcastTimer.UpdateSince(block.ReceivedAt) - go f.broadcastBlock(block, true) - // Run the actual import and log any issues if _, err := f.insertChain(types.Blocks{block}); err != nil { glog.V(logger.Warn).Infof("Peer %s: block #%d [%x] import failed: %v", peer, block.NumberU64(), hash[:4], err)