Skip to content

Commit 9d8b512

Browse files
committed
Merge pull request #1356 from Gustav-Simonsson/debug_develop
Debug develop
2 parents b0a5be4 + a7d2265 commit 9d8b512

File tree

7 files changed

+188
-54
lines changed

7 files changed

+188
-54
lines changed

.travis.yml

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@ language: go
22
go:
33
- 1.4.2
44
before_install:
5-
- sudo add-apt-repository ppa:beineri/opt-qt541 -y
65
- sudo apt-get update -qq
76
- sudo apt-get install -yqq libgmp3-dev
87
install:
@@ -22,14 +21,12 @@ after_success:
2221
- if [ "$COVERALLS_TOKEN" ]; then goveralls -coverprofile=profile.cov -service=travis-ci -repotoken $COVERALLS_TOKEN; fi
2322
env:
2423
global:
25-
- PKG_CONFIG_PATH=/opt/qt54/lib/pkgconfig
26-
- LD_LIBRARY_PATH=/opt/qt54/lib
2724
- secure: "U2U1AmkU4NJBgKR/uUAebQY87cNL0+1JHjnLOmmXwxYYyj5ralWb1aSuSH3qSXiT93qLBmtaUkuv9fberHVqrbAeVlztVdUsKAq7JMQH+M99iFkC9UiRMqHmtjWJ0ok4COD1sRYixxi21wb/JrMe3M1iL4QJVS61iltjHhVdM64="
2825

2926
notifications:
3027
webhooks:
3128
urls:
3229
- https://webhooks.gitter.im/e/e09ccdce1048c5e03445
33-
on_success: change # options: [always|never|change] default: always
34-
on_failure: always # options: [always|never|change] default: always
35-
on_start: false # default: false
30+
on_success: change
31+
on_failure: always
32+
on_start: false

README.md

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -44,11 +44,10 @@ Executables
4444
Go Ethereum comes with several wrappers/executables found in
4545
[the `cmd` directory](https://github.com/ethereum/go-ethereum/tree/develop/cmd):
4646

47-
* `mist` Official Ethereum Browser (ethereum GUI client)
4847
* `geth` Ethereum CLI (ethereum command line interface client)
4948
* `bootnode` runs a bootstrap node for the Discovery Protocol
50-
* `ethtest` test tool which runs with the [tests](https://github.com/ethereum/testes) suite:
51-
`cat file | ethtest`.
49+
* `ethtest` test tool which runs with the [tests](https://github.com/ethereum/tests) suite:
50+
`/path/to/test.json > ethtest --test BlockTests --stdin`.
5251
* `evm` is a generic Ethereum Virtual Machine: `evm -code 60ff60ff -gas
5352
10000 -price 0 -dump`. See `-h` for a detailed description.
5453
* `disasm` disassembles EVM code: `echo "6001" | disasm`
@@ -57,7 +56,7 @@ Go Ethereum comes with several wrappers/executables found in
5756
Command line options
5857
====================
5958

60-
Both `mist` and `geth` can be configured via command line options, environment variables and config files.
59+
`geth` can be configured via command line options, environment variables and config files.
6160

6261
To get the options available:
6362

cmd/geth/monitorcmd.go

Lines changed: 55 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -103,33 +103,17 @@ func monitor(ctx *cli.Context) {
103103
footer.Height = 3
104104

105105
charts := make([]*termui.LineChart, len(monitored))
106+
units := make([]int, len(monitored))
106107
data := make([][]float64, len(monitored))
107-
for i := 0; i < len(data); i++ {
108-
data[i] = make([]float64, 512)
109-
}
110-
for i, metric := range monitored {
111-
charts[i] = termui.NewLineChart()
112-
if runtime.GOOS == "windows" {
113-
charts[i].Mode = "dot"
114-
}
115-
charts[i].Data = make([]float64, 512)
116-
charts[i].DataLabels = []string{""}
117-
charts[i].Height = (termui.TermHeight() - footer.Height) / rows
118-
charts[i].AxesColor = termui.ColorWhite
119-
charts[i].PaddingBottom = -2
120-
121-
charts[i].Border.Label = metric
122-
charts[i].Border.LabelFgColor = charts[i].Border.FgColor | termui.AttrBold
123-
charts[i].Border.FgColor = charts[i].Border.BgColor
124-
108+
for i := 0; i < len(monitored); i++ {
109+
charts[i] = createChart((termui.TermHeight() - footer.Height) / rows)
125110
row := termui.Body.Rows[i%rows]
126111
row.Cols = append(row.Cols, termui.NewCol(12/cols, 0, charts[i]))
127112
}
128113
termui.Body.AddRows(termui.NewRow(termui.NewCol(12, 0, footer)))
129-
termui.Body.Align()
130-
termui.Render(termui.Body)
131114

132-
refreshCharts(xeth, monitored, data, charts, ctx, footer)
115+
refreshCharts(xeth, monitored, data, units, charts, ctx, footer)
116+
termui.Body.Align()
133117
termui.Render(termui.Body)
134118

135119
// Watch for various system events, and periodically refresh the charts
@@ -149,7 +133,9 @@ func monitor(ctx *cli.Context) {
149133
termui.Render(termui.Body)
150134
}
151135
case <-refresh:
152-
refreshCharts(xeth, monitored, data, charts, ctx, footer)
136+
if refreshCharts(xeth, monitored, data, units, charts, ctx, footer) {
137+
termui.Body.Align()
138+
}
153139
termui.Render(termui.Body)
154140
}
155141
}
@@ -246,52 +232,88 @@ func fetchMetric(metrics map[string]interface{}, metric string) float64 {
246232

247233
// refreshCharts retrieves a next batch of metrics, and inserts all the new
248234
// values into the active datasets and charts
249-
func refreshCharts(xeth *rpc.Xeth, metrics []string, data [][]float64, charts []*termui.LineChart, ctx *cli.Context, footer *termui.Par) {
235+
func refreshCharts(xeth *rpc.Xeth, metrics []string, data [][]float64, units []int, charts []*termui.LineChart, ctx *cli.Context, footer *termui.Par) (realign bool) {
250236
values, err := retrieveMetrics(xeth)
251237
for i, metric := range metrics {
252-
data[i] = append([]float64{fetchMetric(values, metric)}, data[i][:len(data[i])-1]...)
253-
updateChart(metric, data[i], charts[i], err)
238+
if len(data) < 512 {
239+
data[i] = append([]float64{fetchMetric(values, metric)}, data[i]...)
240+
} else {
241+
data[i] = append([]float64{fetchMetric(values, metric)}, data[i][:len(data[i])-1]...)
242+
}
243+
if updateChart(metric, data[i], &units[i], charts[i], err) {
244+
realign = true
245+
}
254246
}
255247
updateFooter(ctx, err, footer)
248+
return
256249
}
257250

258251
// updateChart inserts a dataset into a line chart, scaling appropriately as to
259252
// not display weird labels, also updating the chart label accordingly.
260-
func updateChart(metric string, data []float64, chart *termui.LineChart, err error) {
253+
func updateChart(metric string, data []float64, base *int, chart *termui.LineChart, err error) (realign bool) {
261254
dataUnits := []string{"", "K", "M", "G", "T", "E"}
262255
timeUnits := []string{"ns", "µs", "ms", "s", "ks", "ms"}
263256
colors := []termui.Attribute{termui.ColorBlue, termui.ColorCyan, termui.ColorGreen, termui.ColorYellow, termui.ColorRed, termui.ColorRed}
264257

265258
// Extract only part of the data that's actually visible
266-
data = data[:chart.Width*2]
267-
259+
if chart.Width*2 < len(data) {
260+
data = data[:chart.Width*2]
261+
}
268262
// Find the maximum value and scale under 1K
269-
high := data[0]
270-
for _, value := range data[1:] {
271-
high = math.Max(high, value)
263+
high := 0.0
264+
if len(data) > 0 {
265+
high = data[0]
266+
for _, value := range data[1:] {
267+
high = math.Max(high, value)
268+
}
272269
}
273270
unit, scale := 0, 1.0
274271
for high >= 1000 {
275272
high, unit, scale = high/1000, unit+1, scale*1000
276273
}
274+
// If the unit changes, re-create the chart (hack to set max height...)
275+
if unit != *base {
276+
realign, *base, *chart = true, unit, *createChart(chart.Height)
277+
}
277278
// Update the chart's data points with the scaled values
279+
if cap(chart.Data) < len(data) {
280+
chart.Data = make([]float64, len(data))
281+
}
282+
chart.Data = chart.Data[:len(data)]
278283
for i, value := range data {
279284
chart.Data[i] = value / scale
280285
}
281286
// Update the chart's label with the scale units
282-
chart.Border.Label = metric
283-
284287
units := dataUnits
285288
if strings.Contains(metric, "/Percentiles/") || strings.Contains(metric, "/pauses/") {
286289
units = timeUnits
287290
}
291+
chart.Border.Label = metric
288292
if len(units[unit]) > 0 {
289293
chart.Border.Label += " [" + units[unit] + "]"
290294
}
291295
chart.LineColor = colors[unit] | termui.AttrBold
292296
if err != nil {
293297
chart.LineColor = termui.ColorRed | termui.AttrBold
294298
}
299+
return
300+
}
301+
302+
// createChart creates an empty line chart with the default configs.
303+
func createChart(height int) *termui.LineChart {
304+
chart := termui.NewLineChart()
305+
if runtime.GOOS == "windows" {
306+
chart.Mode = "dot"
307+
}
308+
chart.DataLabels = []string{""}
309+
chart.Height = height
310+
chart.AxesColor = termui.ColorWhite
311+
chart.PaddingBottom = -2
312+
313+
chart.Border.LabelFgColor = chart.Border.FgColor | termui.AttrBold
314+
chart.Border.FgColor = chart.Border.BgColor
315+
316+
return chart
295317
}
296318

297319
// updateFooter updates the footer contents based on any encountered errors.

eth/fetcher/fetcher.go

Lines changed: 17 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,8 @@ import (
77
"math/rand"
88
"time"
99

10+
"github.com/ethereum/go-ethereum/core"
11+
1012
"github.com/ethereum/go-ethereum/common"
1113
"github.com/ethereum/go-ethereum/core/types"
1214
"github.com/ethereum/go-ethereum/logger"
@@ -104,6 +106,7 @@ type Fetcher struct {
104106
broadcastMeter metrics.Meter // Counter for metering the inbound propagations
105107
broadcastTimer metrics.Timer // Counter and timer for metering the block forwarding
106108
discardMeter metrics.Meter // Counter for metering the discarded blocks
109+
futureMeter metrics.Meter // Counter for metering future blocks
107110
}
108111

109112
// New creates a block fetcher to retrieve blocks based on hash announcements.
@@ -131,6 +134,7 @@ func New(getBlock blockRetrievalFn, validateBlock blockValidatorFn, broadcastBlo
131134
broadcastMeter: metrics.GetOrRegisterMeter("eth/sync/RemoteBroadcasts", metrics.DefaultRegistry),
132135
broadcastTimer: metrics.GetOrRegisterTimer("eth/sync/LocalBroadcasts", metrics.DefaultRegistry),
133136
discardMeter: metrics.GetOrRegisterMeter("eth/sync/DiscardedBlocks", metrics.DefaultRegistry),
137+
futureMeter: metrics.GetOrRegisterMeter("eth/sync/FutureBlocks", metrics.DefaultRegistry),
134138
}
135139
}
136140

@@ -323,7 +327,7 @@ func (f *Fetcher) loop() {
323327
hash := block.Hash()
324328

325329
// Filter explicitly requested blocks from hash announcements
326-
if _, ok := f.fetching[hash]; ok {
330+
if f.fetching[hash] != nil && f.queued[hash] == nil {
327331
// Discard if already imported by other means
328332
if f.getBlock(hash) == nil {
329333
explicit = append(explicit, block)
@@ -416,14 +420,22 @@ func (f *Fetcher) insert(peer string, block *types.Block) {
416420
return
417421
}
418422
// Quickly validate the header and propagate the block if it passes
419-
if err := f.validateBlock(block, parent); err != nil {
423+
switch err := f.validateBlock(block, parent); err {
424+
case nil:
425+
// All ok, quickly propagate to our peers
426+
f.broadcastTimer.UpdateSince(block.ReceivedAt)
427+
go f.broadcastBlock(block, true)
428+
429+
case core.BlockFutureErr:
430+
f.futureMeter.Mark(1)
431+
// Weird future block, don't fail, but neither propagate
432+
433+
default:
434+
// Something went very wrong, drop the peer
420435
glog.V(logger.Debug).Infof("Peer %s: block #%d [%x] verification failed: %v", peer, block.NumberU64(), hash[:4], err)
421436
f.dropPeer(peer)
422437
return
423438
}
424-
f.broadcastTimer.UpdateSince(block.ReceivedAt)
425-
go f.broadcastBlock(block, true)
426-
427439
// Run the actual import and log any issues
428440
if _, err := f.insertChain(types.Blocks{block}); err != nil {
429441
glog.V(logger.Warn).Infof("Peer %s: block #%d [%x] import failed: %v", peer, block.NumberU64(), hash[:4], err)

p2p/peer.go

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -249,15 +249,22 @@ func countMatchingProtocols(protocols []Protocol, caps []Cap) int {
249249

250250
// matchProtocols creates structures for matching named subprotocols.
251251
func matchProtocols(protocols []Protocol, caps []Cap, rw MsgReadWriter) map[string]*protoRW {
252-
sort.Sort(capsByName(caps))
252+
sort.Sort(capsByNameAndVersion(caps))
253253
offset := baseProtocolLength
254254
result := make(map[string]*protoRW)
255+
255256
outer:
256257
for _, cap := range caps {
257258
for _, proto := range protocols {
258-
if proto.Name == cap.Name && proto.Version == cap.Version && result[cap.Name] == nil {
259+
if proto.Name == cap.Name && proto.Version == cap.Version {
260+
// If an old protocol version matched, revert it
261+
if old := result[cap.Name]; old != nil {
262+
offset -= old.Length
263+
}
264+
// Assign the new match
259265
result[cap.Name] = &protoRW{Protocol: proto, offset: offset, in: make(chan Msg), w: rw}
260266
offset += proto.Length
267+
261268
continue outer
262269
}
263270
}

p2p/peer_test.go

Lines changed: 95 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -196,3 +196,98 @@ func TestNewPeer(t *testing.T) {
196196

197197
p.Disconnect(DiscAlreadyConnected) // Should not hang
198198
}
199+
200+
func TestMatchProtocols(t *testing.T) {
201+
tests := []struct {
202+
Remote []Cap
203+
Local []Protocol
204+
Match map[string]protoRW
205+
}{
206+
{
207+
// No remote capabilities
208+
Local: []Protocol{{Name: "a"}},
209+
},
210+
{
211+
// No local protocols
212+
Remote: []Cap{{Name: "a"}},
213+
},
214+
{
215+
// No mutual protocols
216+
Remote: []Cap{{Name: "a"}},
217+
Local: []Protocol{{Name: "b"}},
218+
},
219+
{
220+
// Some matches, some differences
221+
Remote: []Cap{{Name: "local"}, {Name: "match1"}, {Name: "match2"}},
222+
Local: []Protocol{{Name: "match1"}, {Name: "match2"}, {Name: "remote"}},
223+
Match: map[string]protoRW{"match1": {Protocol: Protocol{Name: "match1"}}, "match2": {Protocol: Protocol{Name: "match2"}}},
224+
},
225+
{
226+
// Various alphabetical ordering
227+
Remote: []Cap{{Name: "aa"}, {Name: "ab"}, {Name: "bb"}, {Name: "ba"}},
228+
Local: []Protocol{{Name: "ba"}, {Name: "bb"}, {Name: "ab"}, {Name: "aa"}},
229+
Match: map[string]protoRW{"aa": {Protocol: Protocol{Name: "aa"}}, "ab": {Protocol: Protocol{Name: "ab"}}, "ba": {Protocol: Protocol{Name: "ba"}}, "bb": {Protocol: Protocol{Name: "bb"}}},
230+
},
231+
{
232+
// No mutual versions
233+
Remote: []Cap{{Version: 1}},
234+
Local: []Protocol{{Version: 2}},
235+
},
236+
{
237+
// Multiple versions, single common
238+
Remote: []Cap{{Version: 1}, {Version: 2}},
239+
Local: []Protocol{{Version: 2}, {Version: 3}},
240+
Match: map[string]protoRW{"": {Protocol: Protocol{Version: 2}}},
241+
},
242+
{
243+
// Multiple versions, multiple common
244+
Remote: []Cap{{Version: 1}, {Version: 2}, {Version: 3}, {Version: 4}},
245+
Local: []Protocol{{Version: 2}, {Version: 3}},
246+
Match: map[string]protoRW{"": {Protocol: Protocol{Version: 3}}},
247+
},
248+
{
249+
// Various version orderings
250+
Remote: []Cap{{Version: 4}, {Version: 1}, {Version: 3}, {Version: 2}},
251+
Local: []Protocol{{Version: 2}, {Version: 3}, {Version: 1}},
252+
Match: map[string]protoRW{"": {Protocol: Protocol{Version: 3}}},
253+
},
254+
{
255+
// Versions overriding sub-protocol lengths
256+
Remote: []Cap{{Version: 1}, {Version: 2}, {Version: 3}, {Name: "a"}},
257+
Local: []Protocol{{Version: 1, Length: 1}, {Version: 2, Length: 2}, {Version: 3, Length: 3}, {Name: "a"}},
258+
Match: map[string]protoRW{"": {Protocol: Protocol{Version: 3}}, "a": {Protocol: Protocol{Name: "a"}, offset: 3}},
259+
},
260+
}
261+
262+
for i, tt := range tests {
263+
result := matchProtocols(tt.Local, tt.Remote, nil)
264+
if len(result) != len(tt.Match) {
265+
t.Errorf("test %d: negotiation mismatch: have %v, want %v", i, len(result), len(tt.Match))
266+
continue
267+
}
268+
// Make sure all negotiated protocols are needed and correct
269+
for name, proto := range result {
270+
match, ok := tt.Match[name]
271+
if !ok {
272+
t.Errorf("test %d, proto '%s': negotiated but shouldn't have", i, name)
273+
continue
274+
}
275+
if proto.Name != match.Name {
276+
t.Errorf("test %d, proto '%s': name mismatch: have %v, want %v", i, name, proto.Name, match.Name)
277+
}
278+
if proto.Version != match.Version {
279+
t.Errorf("test %d, proto '%s': version mismatch: have %v, want %v", i, name, proto.Version, match.Version)
280+
}
281+
if proto.offset-baseProtocolLength != match.offset {
282+
t.Errorf("test %d, proto '%s': offset mismatch: have %v, want %v", i, name, proto.offset-baseProtocolLength, match.offset)
283+
}
284+
}
285+
// Make sure no protocols missed negotiation
286+
for name, _ := range tt.Match {
287+
if _, ok := result[name]; !ok {
288+
t.Errorf("test %d, proto '%s': not negotiated, should have", i, name)
289+
continue
290+
}
291+
}
292+
}
293+
}

p2p/protocol.go

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -43,8 +43,10 @@ func (cap Cap) String() string {
4343
return fmt.Sprintf("%s/%d", cap.Name, cap.Version)
4444
}
4545

46-
type capsByName []Cap
46+
type capsByNameAndVersion []Cap
4747

48-
func (cs capsByName) Len() int { return len(cs) }
49-
func (cs capsByName) Less(i, j int) bool { return cs[i].Name < cs[j].Name }
50-
func (cs capsByName) Swap(i, j int) { cs[i], cs[j] = cs[j], cs[i] }
48+
func (cs capsByNameAndVersion) Len() int { return len(cs) }
49+
func (cs capsByNameAndVersion) Swap(i, j int) { cs[i], cs[j] = cs[j], cs[i] }
50+
func (cs capsByNameAndVersion) Less(i, j int) bool {
51+
return cs[i].Name < cs[j].Name || (cs[i].Name == cs[j].Name && cs[i].Version < cs[j].Version)
52+
}

0 commit comments

Comments
 (0)