Merge branch 'develop' of github.com:ethereum/go-ethereum into limits-changes

This commit is contained in:
Anthony Eufemio 2015-08-21 01:33:34 +09:00
commit eeac2e7a15
92 changed files with 3305 additions and 3460 deletions

View file

@ -5,7 +5,7 @@ install:
# - go get code.google.com/p/go.tools/cmd/goimports # - go get code.google.com/p/go.tools/cmd/goimports
# - go get github.com/golang/lint/golint # - go get github.com/golang/lint/golint
# - go get golang.org/x/tools/cmd/vet # - go get golang.org/x/tools/cmd/vet
- go get golang.org/x/tools/cmd/cover github.com/mattn/goveralls - go get golang.org/x/tools/cmd/cover
before_script: before_script:
# - gofmt -l -w . # - gofmt -l -w .
# - goimports -l -w . # - goimports -l -w .
@ -15,7 +15,7 @@ before_script:
script: script:
- make travis-test-with-coverage - make travis-test-with-coverage
after_success: after_success:
- if [ "$COVERALLS_TOKEN" ]; then goveralls -coverprofile=profile.cov -service=travis-ci -repotoken $COVERALLS_TOKEN; fi - bash <(curl -s https://codecov.io/bash)
env: env:
global: global:
- secure: "U2U1AmkU4NJBgKR/uUAebQY87cNL0+1JHjnLOmmXwxYYyj5ralWb1aSuSH3qSXiT93qLBmtaUkuv9fberHVqrbAeVlztVdUsKAq7JMQH+M99iFkC9UiRMqHmtjWJ0ok4COD1sRYixxi21wb/JrMe3M1iL4QJVS61iltjHhVdM64=" - secure: "U2U1AmkU4NJBgKR/uUAebQY87cNL0+1JHjnLOmmXwxYYyj5ralWb1aSuSH3qSXiT93qLBmtaUkuv9fberHVqrbAeVlztVdUsKAq7JMQH+M99iFkC9UiRMqHmtjWJ0ok4COD1sRYixxi21wb/JrMe3M1iL4QJVS61iltjHhVdM64="

9
CONTRIBUTING.md Normal file
View file

@ -0,0 +1,9 @@
If you'd like to contribute to go-ethereum please fork, fix, commit and
send a pull request. Commits who do not comply with the coding standards
are ignored (use gofmt!). If you send pull requests make absolute sure that you
commit on the `develop` branch and that you do not merge to master.
Commits that are directly based on master are simply ignored.
See [Developers' Guide](https://github.com/ethereum/go-ethereum/wiki/Developers'-Guide)
for more details on configuring your environment, testing, and
dependency management.

18
Godeps/Godeps.json generated
View file

@ -24,14 +24,18 @@
"Comment": "v23.1-227-g8f6ccaa", "Comment": "v23.1-227-g8f6ccaa",
"Rev": "8f6ccaaef9b418553807a73a95cb5f49cd3ea39f" "Rev": "8f6ccaaef9b418553807a73a95cb5f49cd3ea39f"
}, },
{
"ImportPath": "github.com/fatih/color",
"Comment": "v0.1-5-gf773d4c",
"Rev": "f773d4c806cc8e4a5749d6a35e2a4bbcd71443d6"
},
{ {
"ImportPath": "github.com/gizak/termui", "ImportPath": "github.com/gizak/termui",
"Rev": "bab8dce01c193d82bc04888a0a9a7814d505f532" "Rev": "bab8dce01c193d82bc04888a0a9a7814d505f532"
}, },
{ {
"ImportPath": "github.com/howeyc/fsnotify", "ImportPath": "github.com/hashicorp/golang-lru",
"Comment": "v0.9.0-11-g6b1ef89", "Rev": "7f9ef20a0256f494e24126014135cf893ab71e9e"
"Rev": "6b1ef893dc11e0447abda6da20a5203481878dda"
}, },
{ {
"ImportPath": "github.com/huin/goupnp", "ImportPath": "github.com/huin/goupnp",
@ -45,10 +49,6 @@
"ImportPath": "github.com/kardianos/osext", "ImportPath": "github.com/kardianos/osext",
"Rev": "ccfcd0245381f0c94c68f50626665eed3c6b726a" "Rev": "ccfcd0245381f0c94c68f50626665eed3c6b726a"
}, },
{
"ImportPath": "github.com/mattn/go-colorable",
"Rev": "043ae16291351db8465272edf465c9f388161627"
},
{ {
"ImportPath": "github.com/mattn/go-isatty", "ImportPath": "github.com/mattn/go-isatty",
"Rev": "fdbe02a1b44e75977b2690062b83cf507d70c013" "Rev": "fdbe02a1b44e75977b2690062b83cf507d70c013"
@ -78,6 +78,10 @@
"ImportPath": "github.com/rs/cors", "ImportPath": "github.com/rs/cors",
"Rev": "6e0c3cb65fc0fdb064c743d176a620e3ca446dfb" "Rev": "6e0c3cb65fc0fdb064c743d176a620e3ca446dfb"
}, },
{
"ImportPath": "github.com/shiena/ansicolor",
"Rev": "a5e2b567a4dd6cc74545b8a4f27c9d63b9e7735b"
},
{ {
"ImportPath": "github.com/syndtr/goleveldb/leveldb", "ImportPath": "github.com/syndtr/goleveldb/leveldb",
"Rev": "4875955338b0a434238a31165cb87255ab6e9e4a" "Rev": "4875955338b0a434238a31165cb87255ab6e9e4a"

View file

@ -0,0 +1,3 @@
language: go
go: 1.3

View file

@ -0,0 +1,20 @@
The MIT License (MIT)
Copyright (c) 2013 Fatih Arslan
Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal in
the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
the Software, and to permit persons to whom the Software is furnished to do so,
subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

151
Godeps/_workspace/src/github.com/fatih/color/README.md generated vendored Normal file
View file

@ -0,0 +1,151 @@
# Color [![GoDoc](http://img.shields.io/badge/go-documentation-blue.svg?style=flat-square)](http://godoc.org/github.com/fatih/color) [![Build Status](http://img.shields.io/travis/fatih/color.svg?style=flat-square)](https://travis-ci.org/fatih/color)
Color lets you use colorized outputs in terms of [ANSI Escape Codes](http://en.wikipedia.org/wiki/ANSI_escape_code#Colors) in Go (Golang). It has support for Windows too! The API can be used in several ways, pick one that suits you.
![Color](http://i.imgur.com/c1JI0lA.png)
## Install
```bash
go get github.com/fatih/color
```
## Examples
### Standard colors
```go
// Print with default helper functions
color.Cyan("Prints text in cyan.")
// A newline will be appended automatically
color.Blue("Prints %s in blue.", "text")
// These are using the default foreground colors
color.Red("We have red")
color.Magenta("And many others ..")
```
### Mix and reuse colors
```go
// Create a new color object
c := color.New(color.FgCyan).Add(color.Underline)
c.Println("Prints cyan text with an underline.")
// Or just add them to New()
d := color.New(color.FgCyan, color.Bold)
d.Printf("This prints bold cyan %s\n", "too!.")
// Mix up foreground and background colors, create new mixes!
red := color.New(color.FgRed)
boldRed := red.Add(color.Bold)
boldRed.Println("This will print text in bold red.")
whiteBackground := red.Add(color.BgWhite)
whiteBackground.Println("Red text with white background.")
```
### Custom print functions (PrintFunc)
```go
// Create a custom print function for convenience
red := color.New(color.FgRed).PrintfFunc()
red("Warning")
red("Error: %s", err)
// Mix up multiple attributes
notice := color.New(color.Bold, color.FgGreen).PrintlnFunc()
notice("Don't forget this...")
```
### Insert into noncolor strings (SprintFunc)
```go
// Create SprintXxx functions to mix strings with other non-colorized strings:
yellow := color.New(color.FgYellow).SprintFunc()
red := color.New(color.FgRed).SprintFunc()
fmt.Printf("This is a %s and this is %s.\n", yellow("warning"), red("error"))
info := color.New(color.FgWhite, color.BgGreen).SprintFunc()
fmt.Printf("This %s rocks!\n", info("package"))
// Use helper functions
fmt.Printf("This", color.RedString("warning"), "should be not neglected.")
fmt.Printf(color.GreenString("Info:"), "an important message." )
// Windows supported too! Just don't forget to change the output to color.Output
fmt.Fprintf(color.Output, "Windows support: %s", color.GreenString("PASS"))
```
### Plug into existing code
```go
// Use handy standard colors
color.Set(color.FgYellow)
fmt.Println("Existing text will now be in yellow")
fmt.Printf("This one %s\n", "too")
color.Unset() // Don't forget to unset
// You can mix up parameters
color.Set(color.FgMagenta, color.Bold)
defer color.Unset() // Use it in your function
fmt.Println("All text will now be bold magenta.")
```
### Disable color
There might be a case where you want to disable color output (for example to
pipe the standard output of your app to somewhere else). `Color` has support to
disable colors both globally and for single color definition. For example
suppose you have a CLI app and a `--no-color` bool flag. You can easily disable
the color output with:
```go
var flagNoColor = flag.Bool("no-color", false, "Disable color output")
if *flagNoColor {
color.NoColor = true // disables colorized output
}
```
It also has support for single color definitions (local). You can
disable/enable color output on the fly:
```go
c := color.New(color.FgCyan)
c.Println("Prints cyan text")
c.DisableColor()
c.Println("This is printed without any color")
c.EnableColor()
c.Println("This prints again cyan...")
```
## Todo
* Save/Return previous values
* Evaluate fmt.Formatter interface
## Credits
* [Fatih Arslan](https://github.com/fatih)
* Windows support via @shiena: [ansicolor](https://github.com/shiena/ansicolor)
## License
The MIT License (MIT) - see [`LICENSE.md`](https://github.com/fatih/color/blob/master/LICENSE.md) for more details

353
Godeps/_workspace/src/github.com/fatih/color/color.go generated vendored Normal file
View file

@ -0,0 +1,353 @@
package color
import (
"fmt"
"os"
"strconv"
"strings"
"github.com/mattn/go-isatty"
"github.com/shiena/ansicolor"
)
// NoColor defines if the output is colorized or not. It's dynamically set to
// false or true based on the stdout's file descriptor referring to a terminal
// or not. This is a global option and affects all colors. For more control
// over each color block use the methods DisableColor() individually.
var NoColor = !isatty.IsTerminal(os.Stdout.Fd())
// Color defines a custom color object which is defined by SGR parameters.
type Color struct {
params []Attribute
noColor *bool
}
// Attribute defines a single SGR Code
type Attribute int
const escape = "\x1b"
// Base attributes
const (
Reset Attribute = iota
Bold
Faint
Italic
Underline
BlinkSlow
BlinkRapid
ReverseVideo
Concealed
CrossedOut
)
// Foreground text colors
const (
FgBlack Attribute = iota + 30
FgRed
FgGreen
FgYellow
FgBlue
FgMagenta
FgCyan
FgWhite
)
// Background text colors
const (
BgBlack Attribute = iota + 40
BgRed
BgGreen
BgYellow
BgBlue
BgMagenta
BgCyan
BgWhite
)
// New returns a newly created color object.
func New(value ...Attribute) *Color {
c := &Color{params: make([]Attribute, 0)}
c.Add(value...)
return c
}
// Set sets the given parameters immediately. It will change the color of
// output with the given SGR parameters until color.Unset() is called.
func Set(p ...Attribute) *Color {
c := New(p...)
c.Set()
return c
}
// Unset resets all escape attributes and clears the output. Usually should
// be called after Set().
func Unset() {
if NoColor {
return
}
fmt.Fprintf(Output, "%s[%dm", escape, Reset)
}
// Set sets the SGR sequence.
func (c *Color) Set() *Color {
if c.isNoColorSet() {
return c
}
fmt.Fprintf(Output, c.format())
return c
}
func (c *Color) unset() {
if c.isNoColorSet() {
return
}
Unset()
}
// Add is used to chain SGR parameters. Use as many as parameters to combine
// and create custom color objects. Example: Add(color.FgRed, color.Underline).
func (c *Color) Add(value ...Attribute) *Color {
c.params = append(c.params, value...)
return c
}
func (c *Color) prepend(value Attribute) {
c.params = append(c.params, 0)
copy(c.params[1:], c.params[0:])
c.params[0] = value
}
// Output defines the standard output of the print functions. By default
// os.Stdout is used.
var Output = ansicolor.NewAnsiColorWriter(os.Stdout)
// Print formats using the default formats for its operands and writes to
// standard output. Spaces are added between operands when neither is a
// string. It returns the number of bytes written and any write error
// encountered. This is the standard fmt.Print() method wrapped with the given
// color.
func (c *Color) Print(a ...interface{}) (n int, err error) {
c.Set()
defer c.unset()
return fmt.Fprint(Output, a...)
}
// Printf formats according to a format specifier and writes to standard output.
// It returns the number of bytes written and any write error encountered.
// This is the standard fmt.Printf() method wrapped with the given color.
func (c *Color) Printf(format string, a ...interface{}) (n int, err error) {
c.Set()
defer c.unset()
return fmt.Fprintf(Output, format, a...)
}
// Println formats using the default formats for its operands and writes to
// standard output. Spaces are always added between operands and a newline is
// appended. It returns the number of bytes written and any write error
// encountered. This is the standard fmt.Print() method wrapped with the given
// color.
func (c *Color) Println(a ...interface{}) (n int, err error) {
c.Set()
defer c.unset()
return fmt.Fprintln(Output, a...)
}
// PrintFunc returns a new function that prints the passed arguments as
// colorized with color.Print().
func (c *Color) PrintFunc() func(a ...interface{}) {
return func(a ...interface{}) { c.Print(a...) }
}
// PrintfFunc returns a new function that prints the passed arguments as
// colorized with color.Printf().
func (c *Color) PrintfFunc() func(format string, a ...interface{}) {
return func(format string, a ...interface{}) { c.Printf(format, a...) }
}
// PrintlnFunc returns a new function that prints the passed arguments as
// colorized with color.Println().
func (c *Color) PrintlnFunc() func(a ...interface{}) {
return func(a ...interface{}) { c.Println(a...) }
}
// SprintFunc returns a new function that returns colorized strings for the
// given arguments with fmt.Sprint(). Useful to put into or mix into other
// string. Windows users should use this in conjuction with color.Output, example:
//
// put := New(FgYellow).SprintFunc()
// fmt.Fprintf(color.Output, "This is a %s", put("warning"))
func (c *Color) SprintFunc() func(a ...interface{}) string {
return func(a ...interface{}) string {
return c.wrap(fmt.Sprint(a...))
}
}
// SprintfFunc returns a new function that returns colorized strings for the
// given arguments with fmt.Sprintf(). Useful to put into or mix into other
// string. Windows users should use this in conjuction with color.Output.
func (c *Color) SprintfFunc() func(format string, a ...interface{}) string {
return func(format string, a ...interface{}) string {
return c.wrap(fmt.Sprintf(format, a...))
}
}
// SprintlnFunc returns a new function that returns colorized strings for the
// given arguments with fmt.Sprintln(). Useful to put into or mix into other
// string. Windows users should use this in conjuction with color.Output.
func (c *Color) SprintlnFunc() func(a ...interface{}) string {
return func(a ...interface{}) string {
return c.wrap(fmt.Sprintln(a...))
}
}
// sequence returns a formated SGR sequence to be plugged into a "\x1b[...m"
// an example output might be: "1;36" -> bold cyan
func (c *Color) sequence() string {
format := make([]string, len(c.params))
for i, v := range c.params {
format[i] = strconv.Itoa(int(v))
}
return strings.Join(format, ";")
}
// wrap wraps the s string with the colors attributes. The string is ready to
// be printed.
func (c *Color) wrap(s string) string {
if c.isNoColorSet() {
return s
}
return c.format() + s + c.unformat()
}
func (c *Color) format() string {
return fmt.Sprintf("%s[%sm", escape, c.sequence())
}
func (c *Color) unformat() string {
return fmt.Sprintf("%s[%dm", escape, Reset)
}
// DisableColor disables the color output. Useful to not change any existing
// code and still being able to output. Can be used for flags like
// "--no-color". To enable back use EnableColor() method.
func (c *Color) DisableColor() {
c.noColor = boolPtr(true)
}
// EnableColor enables the color output. Use it in conjuction with
// DisableColor(). Otherwise this method has no side effects.
func (c *Color) EnableColor() {
c.noColor = boolPtr(false)
}
func (c *Color) isNoColorSet() bool {
// check first if we have user setted action
if c.noColor != nil {
return *c.noColor
}
// if not return the global option, which is disabled by default
return NoColor
}
func boolPtr(v bool) *bool {
return &v
}
// Black is an convenient helper function to print with black foreground. A
// newline is appended to format by default.
func Black(format string, a ...interface{}) { printColor(format, FgBlack, a...) }
// Red is an convenient helper function to print with red foreground. A
// newline is appended to format by default.
func Red(format string, a ...interface{}) { printColor(format, FgRed, a...) }
// Green is an convenient helper function to print with green foreground. A
// newline is appended to format by default.
func Green(format string, a ...interface{}) { printColor(format, FgGreen, a...) }
// Yellow is an convenient helper function to print with yellow foreground.
// A newline is appended to format by default.
func Yellow(format string, a ...interface{}) { printColor(format, FgYellow, a...) }
// Blue is an convenient helper function to print with blue foreground. A
// newline is appended to format by default.
func Blue(format string, a ...interface{}) { printColor(format, FgBlue, a...) }
// Magenta is an convenient helper function to print with magenta foreground.
// A newline is appended to format by default.
func Magenta(format string, a ...interface{}) { printColor(format, FgMagenta, a...) }
// Cyan is an convenient helper function to print with cyan foreground. A
// newline is appended to format by default.
func Cyan(format string, a ...interface{}) { printColor(format, FgCyan, a...) }
// White is an convenient helper function to print with white foreground. A
// newline is appended to format by default.
func White(format string, a ...interface{}) { printColor(format, FgWhite, a...) }
func printColor(format string, p Attribute, a ...interface{}) {
if !strings.HasSuffix(format, "\n") {
format += "\n"
}
c := &Color{params: []Attribute{p}}
c.Printf(format, a...)
}
// BlackString is an convenient helper function to return a string with black
// foreground.
func BlackString(format string, a ...interface{}) string {
return New(FgBlack).SprintfFunc()(format, a...)
}
// RedString is an convenient helper function to return a string with red
// foreground.
func RedString(format string, a ...interface{}) string {
return New(FgRed).SprintfFunc()(format, a...)
}
// GreenString is an convenient helper function to return a string with green
// foreground.
func GreenString(format string, a ...interface{}) string {
return New(FgGreen).SprintfFunc()(format, a...)
}
// YellowString is an convenient helper function to return a string with yellow
// foreground.
func YellowString(format string, a ...interface{}) string {
return New(FgYellow).SprintfFunc()(format, a...)
}
// BlueString is an convenient helper function to return a string with blue
// foreground.
func BlueString(format string, a ...interface{}) string {
return New(FgBlue).SprintfFunc()(format, a...)
}
// MagentaString is an convenient helper function to return a string with magenta
// foreground.
func MagentaString(format string, a ...interface{}) string {
return New(FgMagenta).SprintfFunc()(format, a...)
}
// CyanString is an convenient helper function to return a string with cyan
// foreground.
func CyanString(format string, a ...interface{}) string {
return New(FgCyan).SprintfFunc()(format, a...)
}
// WhiteString is an convenient helper function to return a string with white
// foreground.
func WhiteString(format string, a ...interface{}) string {
return New(FgWhite).SprintfFunc()(format, a...)
}

View file

@ -0,0 +1,176 @@
package color
import (
"bytes"
"fmt"
"os"
"testing"
"github.com/shiena/ansicolor"
)
// Testing colors is kinda different. First we test for given colors and their
// escaped formatted results. Next we create some visual tests to be tested.
// Each visual test includes the color name to be compared.
func TestColor(t *testing.T) {
rb := new(bytes.Buffer)
Output = rb
testColors := []struct {
text string
code Attribute
}{
{text: "black", code: FgBlack},
{text: "red", code: FgRed},
{text: "green", code: FgGreen},
{text: "yellow", code: FgYellow},
{text: "blue", code: FgBlue},
{text: "magent", code: FgMagenta},
{text: "cyan", code: FgCyan},
{text: "white", code: FgWhite},
}
for _, c := range testColors {
New(c.code).Print(c.text)
line, _ := rb.ReadString('\n')
scannedLine := fmt.Sprintf("%q", line)
colored := fmt.Sprintf("\x1b[%dm%s\x1b[0m", c.code, c.text)
escapedForm := fmt.Sprintf("%q", colored)
fmt.Printf("%s\t: %s\n", c.text, line)
if scannedLine != escapedForm {
t.Errorf("Expecting %s, got '%s'\n", escapedForm, scannedLine)
}
}
}
func TestNoColor(t *testing.T) {
rb := new(bytes.Buffer)
Output = rb
testColors := []struct {
text string
code Attribute
}{
{text: "black", code: FgBlack},
{text: "red", code: FgRed},
{text: "green", code: FgGreen},
{text: "yellow", code: FgYellow},
{text: "blue", code: FgBlue},
{text: "magent", code: FgMagenta},
{text: "cyan", code: FgCyan},
{text: "white", code: FgWhite},
}
for _, c := range testColors {
p := New(c.code)
p.DisableColor()
p.Print(c.text)
line, _ := rb.ReadString('\n')
if line != c.text {
t.Errorf("Expecting %s, got '%s'\n", c.text, line)
}
}
// global check
NoColor = true
defer func() {
NoColor = false
}()
for _, c := range testColors {
p := New(c.code)
p.Print(c.text)
line, _ := rb.ReadString('\n')
if line != c.text {
t.Errorf("Expecting %s, got '%s'\n", c.text, line)
}
}
}
func TestColorVisual(t *testing.T) {
// First Visual Test
fmt.Println("")
Output = ansicolor.NewAnsiColorWriter(os.Stdout)
New(FgRed).Printf("red\t")
New(BgRed).Print(" ")
New(FgRed, Bold).Println(" red")
New(FgGreen).Printf("green\t")
New(BgGreen).Print(" ")
New(FgGreen, Bold).Println(" green")
New(FgYellow).Printf("yellow\t")
New(BgYellow).Print(" ")
New(FgYellow, Bold).Println(" yellow")
New(FgBlue).Printf("blue\t")
New(BgBlue).Print(" ")
New(FgBlue, Bold).Println(" blue")
New(FgMagenta).Printf("magenta\t")
New(BgMagenta).Print(" ")
New(FgMagenta, Bold).Println(" magenta")
New(FgCyan).Printf("cyan\t")
New(BgCyan).Print(" ")
New(FgCyan, Bold).Println(" cyan")
New(FgWhite).Printf("white\t")
New(BgWhite).Print(" ")
New(FgWhite, Bold).Println(" white")
fmt.Println("")
// Second Visual test
Black("black")
Red("red")
Green("green")
Yellow("yellow")
Blue("blue")
Magenta("magenta")
Cyan("cyan")
White("white")
// Third visual test
fmt.Println()
Set(FgBlue)
fmt.Println("is this blue?")
Unset()
Set(FgMagenta)
fmt.Println("and this magenta?")
Unset()
// Fourth Visual test
fmt.Println()
blue := New(FgBlue).PrintlnFunc()
blue("blue text with custom print func")
red := New(FgRed).PrintfFunc()
red("red text with a printf func: %d\n", 123)
put := New(FgYellow).SprintFunc()
warn := New(FgRed).SprintFunc()
fmt.Fprintf(Output, "this is a %s and this is %s.\n", put("warning"), warn("error"))
info := New(FgWhite, BgGreen).SprintFunc()
fmt.Fprintf(Output, "this %s rocks!\n", info("package"))
// Fifth Visual Test
fmt.Println()
fmt.Fprintln(Output, BlackString("black"))
fmt.Fprintln(Output, RedString("red"))
fmt.Fprintln(Output, GreenString("green"))
fmt.Fprintln(Output, YellowString("yellow"))
fmt.Fprintln(Output, BlueString("blue"))
fmt.Fprintln(Output, MagentaString("magenta"))
fmt.Fprintln(Output, CyanString("cyan"))
fmt.Fprintln(Output, WhiteString("white"))
}

114
Godeps/_workspace/src/github.com/fatih/color/doc.go generated vendored Normal file
View file

@ -0,0 +1,114 @@
/*
Package color is an ANSI color package to output colorized or SGR defined
output to the standard output. The API can be used in several way, pick one
that suits you.
Use simple and default helper functions with predefined foreground colors:
color.Cyan("Prints text in cyan.")
// a newline will be appended automatically
color.Blue("Prints %s in blue.", "text")
// More default foreground colors..
color.Red("We have red")
color.Yellow("Yellow color too!")
color.Magenta("And many others ..")
However there are times where custom color mixes are required. Below are some
examples to create custom color objects and use the print functions of each
separate color object.
// Create a new color object
c := color.New(color.FgCyan).Add(color.Underline)
c.Println("Prints cyan text with an underline.")
// Or just add them to New()
d := color.New(color.FgCyan, color.Bold)
d.Printf("This prints bold cyan %s\n", "too!.")
// Mix up foreground and background colors, create new mixes!
red := color.New(color.FgRed)
boldRed := red.Add(color.Bold)
boldRed.Println("This will print text in bold red.")
whiteBackground := red.Add(color.BgWhite)
whiteBackground.Println("Red text with White background.")
You can create PrintXxx functions to simplify even more:
// Create a custom print function for convenient
red := color.New(color.FgRed).PrintfFunc()
red("warning")
red("error: %s", err)
// Mix up multiple attributes
notice := color.New(color.Bold, color.FgGreen).PrintlnFunc()
notice("don't forget this...")
Or create SprintXxx functions to mix strings with other non-colorized strings:
yellow := New(FgYellow).SprintFunc()
red := New(FgRed).SprintFunc()
fmt.Printf("this is a %s and this is %s.\n", yellow("warning"), red("error"))
info := New(FgWhite, BgGreen).SprintFunc()
fmt.Printf("this %s rocks!\n", info("package"))
Windows support is enabled by default. All Print functions works as intended.
However only for color.SprintXXX functions, user should use fmt.FprintXXX and
set the output to color.Output:
fmt.Fprintf(color.Output, "Windows support: %s", color.GreenString("PASS"))
info := New(FgWhite, BgGreen).SprintFunc()
fmt.Fprintf(color.Output, "this %s rocks!\n", info("package"))
Using with existing code is possible. Just use the Set() method to set the
standard output to the given parameters. That way a rewrite of an existing
code is not required.
// Use handy standard colors.
color.Set(color.FgYellow)
fmt.Println("Existing text will be now in Yellow")
fmt.Printf("This one %s\n", "too")
color.Unset() // don't forget to unset
// You can mix up parameters
color.Set(color.FgMagenta, color.Bold)
defer color.Unset() // use it in your function
fmt.Println("All text will be now bold magenta.")
There might be a case where you want to disable color output (for example to
pipe the standard output of your app to somewhere else). `Color` has support to
disable colors both globally and for single color definition. For example
suppose you have a CLI app and a `--no-color` bool flag. You can easily disable
the color output with:
var flagNoColor = flag.Bool("no-color", false, "Disable color output")
if *flagNoColor {
color.NoColor = true // disables colorized output
}
It also has support for single color definitions (local). You can
disable/enable color output on the fly:
c := color.New(color.FgCyan)
c.Println("Prints cyan text")
c.DisableColor()
c.Println("This is printed without any color")
c.EnableColor()
c.Println("This prints again cyan...")
*/
package color

View file

@ -9,8 +9,6 @@ import (
"net/http" "net/http"
"sync" "sync"
"time" "time"
"github.com/ethereum/go-ethereum/fdtrack"
) )
// HTTPUClient is a client for dealing with HTTPU (HTTP over UDP). Its typical // HTTPUClient is a client for dealing with HTTPU (HTTP over UDP). Its typical
@ -27,7 +25,6 @@ func NewHTTPUClient() (*HTTPUClient, error) {
if err != nil { if err != nil {
return nil, err return nil, err
} }
fdtrack.Open("upnp")
return &HTTPUClient{conn: conn}, nil return &HTTPUClient{conn: conn}, nil
} }
@ -36,7 +33,6 @@ func NewHTTPUClient() (*HTTPUClient, error) {
func (httpu *HTTPUClient) Close() error { func (httpu *HTTPUClient) Close() error {
httpu.connLock.Lock() httpu.connLock.Lock()
defer httpu.connLock.Unlock() defer httpu.connLock.Unlock()
fdtrack.Close("upnp")
return httpu.conn.Close() return httpu.conn.Close()
} }

View file

@ -7,12 +7,9 @@ import (
"encoding/xml" "encoding/xml"
"fmt" "fmt"
"io/ioutil" "io/ioutil"
"net"
"net/http" "net/http"
"net/url" "net/url"
"reflect" "reflect"
"github.com/ethereum/go-ethereum/fdtrack"
) )
const ( const (
@ -29,17 +26,6 @@ type SOAPClient struct {
func NewSOAPClient(endpointURL url.URL) *SOAPClient { func NewSOAPClient(endpointURL url.URL) *SOAPClient {
return &SOAPClient{ return &SOAPClient{
EndpointURL: endpointURL, EndpointURL: endpointURL,
HTTPClient: http.Client{
Transport: &http.Transport{
Dial: func(network, addr string) (net.Conn, error) {
c, err := net.Dial(network, addr)
if c != nil {
c = fdtrack.WrapConn("upnp", c)
}
return c, err
},
},
},
} }
} }

View file

@ -5,8 +5,6 @@ import (
"log" "log"
"net" "net"
"time" "time"
"github.com/ethereum/go-ethereum/fdtrack"
) )
// Implement the NAT-PMP protocol, typically supported by Apple routers and open source // Implement the NAT-PMP protocol, typically supported by Apple routers and open source
@ -104,8 +102,6 @@ func (n *Client) rpc(msg []byte, resultSize int) (result []byte, err error) {
if err != nil { if err != nil {
return return
} }
fdtrack.Open("natpmp")
defer fdtrack.Close("natpmp")
defer conn.Close() defer conn.Close()
result = make([]byte, resultSize) result = make([]byte, resultSize)

View file

@ -1,42 +0,0 @@
# go-colorable
Colorable writer for windows.
For example, most of logger packages doesn't show colors on windows. (I know we can do it with ansicon. But I don't want.)
This package is possible to handle escape sequence for ansi color on windows.
## Too Bad!
![](https://raw.githubusercontent.com/mattn/go-colorable/gh-pages/bad.png)
## So Good!
![](https://raw.githubusercontent.com/mattn/go-colorable/gh-pages/good.png)
## Usage
```go
logrus.SetOutput(colorable.NewColorableStdout())
logrus.Info("succeeded")
logrus.Warn("not correct")
logrus.Error("something error")
logrus.Fatal("panic")
```
You can compile above code on non-windows OSs.
## Installation
```
$ go get github.com/mattn/go-colorable
```
# License
MIT
# Author
Yasuhiro Matsumoto (a.k.a mattn)

View file

@ -1,16 +0,0 @@
// +build !windows
package colorable
import (
"io"
"os"
)
func NewColorableStdout() io.Writer {
return os.Stdout
}
func NewColorableStderr() io.Writer {
return os.Stderr
}

View file

@ -1,594 +0,0 @@
package colorable
import (
"bytes"
"fmt"
"io"
"os"
"strconv"
"strings"
"syscall"
"unsafe"
"github.com/mattn/go-isatty"
)
const (
foregroundBlue = 0x1
foregroundGreen = 0x2
foregroundRed = 0x4
foregroundIntensity = 0x8
foregroundMask = (foregroundRed | foregroundBlue | foregroundGreen | foregroundIntensity)
backgroundBlue = 0x10
backgroundGreen = 0x20
backgroundRed = 0x40
backgroundIntensity = 0x80
backgroundMask = (backgroundRed | backgroundBlue | backgroundGreen | backgroundIntensity)
)
type wchar uint16
type short int16
type dword uint32
type word uint16
type coord struct {
x short
y short
}
type smallRect struct {
left short
top short
right short
bottom short
}
type consoleScreenBufferInfo struct {
size coord
cursorPosition coord
attributes word
window smallRect
maximumWindowSize coord
}
var (
kernel32 = syscall.NewLazyDLL("kernel32.dll")
procGetConsoleScreenBufferInfo = kernel32.NewProc("GetConsoleScreenBufferInfo")
procSetConsoleTextAttribute = kernel32.NewProc("SetConsoleTextAttribute")
)
type Writer struct {
out io.Writer
handle syscall.Handle
lastbuf bytes.Buffer
oldattr word
}
func NewColorableStdout() io.Writer {
var csbi consoleScreenBufferInfo
out := os.Stdout
if !isatty.IsTerminal(out.Fd()) {
return out
}
handle := syscall.Handle(out.Fd())
procGetConsoleScreenBufferInfo.Call(uintptr(handle), uintptr(unsafe.Pointer(&csbi)))
return &Writer{out: out, handle: handle, oldattr: csbi.attributes}
}
func NewColorableStderr() io.Writer {
var csbi consoleScreenBufferInfo
out := os.Stderr
if !isatty.IsTerminal(out.Fd()) {
return out
}
handle := syscall.Handle(out.Fd())
procGetConsoleScreenBufferInfo.Call(uintptr(handle), uintptr(unsafe.Pointer(&csbi)))
return &Writer{out: out, handle: handle, oldattr: csbi.attributes}
}
var color256 = map[int]int{
0: 0x000000,
1: 0x800000,
2: 0x008000,
3: 0x808000,
4: 0x000080,
5: 0x800080,
6: 0x008080,
7: 0xc0c0c0,
8: 0x808080,
9: 0xff0000,
10: 0x00ff00,
11: 0xffff00,
12: 0x0000ff,
13: 0xff00ff,
14: 0x00ffff,
15: 0xffffff,
16: 0x000000,
17: 0x00005f,
18: 0x000087,
19: 0x0000af,
20: 0x0000d7,
21: 0x0000ff,
22: 0x005f00,
23: 0x005f5f,
24: 0x005f87,
25: 0x005faf,
26: 0x005fd7,
27: 0x005fff,
28: 0x008700,
29: 0x00875f,
30: 0x008787,
31: 0x0087af,
32: 0x0087d7,
33: 0x0087ff,
34: 0x00af00,
35: 0x00af5f,
36: 0x00af87,
37: 0x00afaf,
38: 0x00afd7,
39: 0x00afff,
40: 0x00d700,
41: 0x00d75f,
42: 0x00d787,
43: 0x00d7af,
44: 0x00d7d7,
45: 0x00d7ff,
46: 0x00ff00,
47: 0x00ff5f,
48: 0x00ff87,
49: 0x00ffaf,
50: 0x00ffd7,
51: 0x00ffff,
52: 0x5f0000,
53: 0x5f005f,
54: 0x5f0087,
55: 0x5f00af,
56: 0x5f00d7,
57: 0x5f00ff,
58: 0x5f5f00,
59: 0x5f5f5f,
60: 0x5f5f87,
61: 0x5f5faf,
62: 0x5f5fd7,
63: 0x5f5fff,
64: 0x5f8700,
65: 0x5f875f,
66: 0x5f8787,
67: 0x5f87af,
68: 0x5f87d7,
69: 0x5f87ff,
70: 0x5faf00,
71: 0x5faf5f,
72: 0x5faf87,
73: 0x5fafaf,
74: 0x5fafd7,
75: 0x5fafff,
76: 0x5fd700,
77: 0x5fd75f,
78: 0x5fd787,
79: 0x5fd7af,
80: 0x5fd7d7,
81: 0x5fd7ff,
82: 0x5fff00,
83: 0x5fff5f,
84: 0x5fff87,
85: 0x5fffaf,
86: 0x5fffd7,
87: 0x5fffff,
88: 0x870000,
89: 0x87005f,
90: 0x870087,
91: 0x8700af,
92: 0x8700d7,
93: 0x8700ff,
94: 0x875f00,
95: 0x875f5f,
96: 0x875f87,
97: 0x875faf,
98: 0x875fd7,
99: 0x875fff,
100: 0x878700,
101: 0x87875f,
102: 0x878787,
103: 0x8787af,
104: 0x8787d7,
105: 0x8787ff,
106: 0x87af00,
107: 0x87af5f,
108: 0x87af87,
109: 0x87afaf,
110: 0x87afd7,
111: 0x87afff,
112: 0x87d700,
113: 0x87d75f,
114: 0x87d787,
115: 0x87d7af,
116: 0x87d7d7,
117: 0x87d7ff,
118: 0x87ff00,
119: 0x87ff5f,
120: 0x87ff87,
121: 0x87ffaf,
122: 0x87ffd7,
123: 0x87ffff,
124: 0xaf0000,
125: 0xaf005f,
126: 0xaf0087,
127: 0xaf00af,
128: 0xaf00d7,
129: 0xaf00ff,
130: 0xaf5f00,
131: 0xaf5f5f,
132: 0xaf5f87,
133: 0xaf5faf,
134: 0xaf5fd7,
135: 0xaf5fff,
136: 0xaf8700,
137: 0xaf875f,
138: 0xaf8787,
139: 0xaf87af,
140: 0xaf87d7,
141: 0xaf87ff,
142: 0xafaf00,
143: 0xafaf5f,
144: 0xafaf87,
145: 0xafafaf,
146: 0xafafd7,
147: 0xafafff,
148: 0xafd700,
149: 0xafd75f,
150: 0xafd787,
151: 0xafd7af,
152: 0xafd7d7,
153: 0xafd7ff,
154: 0xafff00,
155: 0xafff5f,
156: 0xafff87,
157: 0xafffaf,
158: 0xafffd7,
159: 0xafffff,
160: 0xd70000,
161: 0xd7005f,
162: 0xd70087,
163: 0xd700af,
164: 0xd700d7,
165: 0xd700ff,
166: 0xd75f00,
167: 0xd75f5f,
168: 0xd75f87,
169: 0xd75faf,
170: 0xd75fd7,
171: 0xd75fff,
172: 0xd78700,
173: 0xd7875f,
174: 0xd78787,
175: 0xd787af,
176: 0xd787d7,
177: 0xd787ff,
178: 0xd7af00,
179: 0xd7af5f,
180: 0xd7af87,
181: 0xd7afaf,
182: 0xd7afd7,
183: 0xd7afff,
184: 0xd7d700,
185: 0xd7d75f,
186: 0xd7d787,
187: 0xd7d7af,
188: 0xd7d7d7,
189: 0xd7d7ff,
190: 0xd7ff00,
191: 0xd7ff5f,
192: 0xd7ff87,
193: 0xd7ffaf,
194: 0xd7ffd7,
195: 0xd7ffff,
196: 0xff0000,
197: 0xff005f,
198: 0xff0087,
199: 0xff00af,
200: 0xff00d7,
201: 0xff00ff,
202: 0xff5f00,
203: 0xff5f5f,
204: 0xff5f87,
205: 0xff5faf,
206: 0xff5fd7,
207: 0xff5fff,
208: 0xff8700,
209: 0xff875f,
210: 0xff8787,
211: 0xff87af,
212: 0xff87d7,
213: 0xff87ff,
214: 0xffaf00,
215: 0xffaf5f,
216: 0xffaf87,
217: 0xffafaf,
218: 0xffafd7,
219: 0xffafff,
220: 0xffd700,
221: 0xffd75f,
222: 0xffd787,
223: 0xffd7af,
224: 0xffd7d7,
225: 0xffd7ff,
226: 0xffff00,
227: 0xffff5f,
228: 0xffff87,
229: 0xffffaf,
230: 0xffffd7,
231: 0xffffff,
232: 0x080808,
233: 0x121212,
234: 0x1c1c1c,
235: 0x262626,
236: 0x303030,
237: 0x3a3a3a,
238: 0x444444,
239: 0x4e4e4e,
240: 0x585858,
241: 0x626262,
242: 0x6c6c6c,
243: 0x767676,
244: 0x808080,
245: 0x8a8a8a,
246: 0x949494,
247: 0x9e9e9e,
248: 0xa8a8a8,
249: 0xb2b2b2,
250: 0xbcbcbc,
251: 0xc6c6c6,
252: 0xd0d0d0,
253: 0xdadada,
254: 0xe4e4e4,
255: 0xeeeeee,
}
func (w *Writer) Write(data []byte) (n int, err error) {
var csbi consoleScreenBufferInfo
procGetConsoleScreenBufferInfo.Call(uintptr(w.handle), uintptr(unsafe.Pointer(&csbi)))
er := bytes.NewBuffer(data)
loop:
for {
r1, _, err := procGetConsoleScreenBufferInfo.Call(uintptr(w.handle), uintptr(unsafe.Pointer(&csbi)))
if r1 == 0 {
break loop
}
c1, _, err := er.ReadRune()
if err != nil {
break loop
}
if c1 != 0x1b {
fmt.Fprint(w.out, string(c1))
continue
}
c2, _, err := er.ReadRune()
if err != nil {
w.lastbuf.WriteRune(c1)
break loop
}
if c2 != 0x5b {
w.lastbuf.WriteRune(c1)
w.lastbuf.WriteRune(c2)
continue
}
var buf bytes.Buffer
var m rune
for {
c, _, err := er.ReadRune()
if err != nil {
w.lastbuf.WriteRune(c1)
w.lastbuf.WriteRune(c2)
w.lastbuf.Write(buf.Bytes())
break loop
}
if ('a' <= c && c <= 'z') || ('A' <= c && c <= 'Z') || c == '@' {
m = c
break
}
buf.Write([]byte(string(c)))
}
switch m {
case 'm':
attr := csbi.attributes
cs := buf.String()
if cs == "" {
procSetConsoleTextAttribute.Call(uintptr(w.handle), uintptr(w.oldattr))
continue
}
token := strings.Split(cs, ";")
for i, ns := range token {
if n, err = strconv.Atoi(ns); err == nil {
switch {
case n == 0 || n == 100:
attr = w.oldattr
case 1 <= n && n <= 5:
attr |= foregroundIntensity
case n == 7:
attr = ((attr & foregroundMask) << 4) | ((attr & backgroundMask) >> 4)
case 22 == n || n == 25 || n == 25:
attr |= foregroundIntensity
case n == 27:
attr = ((attr & foregroundMask) << 4) | ((attr & backgroundMask) >> 4)
case 30 <= n && n <= 37:
attr = (attr & backgroundMask)
if (n-30)&1 != 0 {
attr |= foregroundRed
}
if (n-30)&2 != 0 {
attr |= foregroundGreen
}
if (n-30)&4 != 0 {
attr |= foregroundBlue
}
case n == 38: // set foreground color.
if i < len(token)-2 && token[i+1] == "5" {
if n256, err := strconv.Atoi(token[i+2]); err == nil {
if n256foreAttr == nil {
n256setup()
}
attr &= backgroundMask
attr |= n256foreAttr[n256]
i += 2
}
} else {
attr = attr & (w.oldattr & backgroundMask)
}
case n == 39: // reset foreground color.
attr &= backgroundMask
attr |= w.oldattr & foregroundMask
case 40 <= n && n <= 47:
attr = (attr & foregroundMask)
if (n-40)&1 != 0 {
attr |= backgroundRed
}
if (n-40)&2 != 0 {
attr |= backgroundGreen
}
if (n-40)&4 != 0 {
attr |= backgroundBlue
}
case n == 48: // set background color.
if i < len(token)-2 && token[i+1] == "5" {
if n256, err := strconv.Atoi(token[i+2]); err == nil {
if n256backAttr == nil {
n256setup()
}
attr &= foregroundMask
attr |= n256backAttr[n256]
i += 2
}
} else {
attr = attr & (w.oldattr & foregroundMask)
}
case n == 49: // reset foreground color.
attr &= foregroundMask
attr |= w.oldattr & backgroundMask
}
procSetConsoleTextAttribute.Call(uintptr(w.handle), uintptr(attr))
}
}
}
}
return len(data) - w.lastbuf.Len(), nil
}
type consoleColor struct {
red bool
green bool
blue bool
intensity bool
}
func minmax3(a, b, c int) (min, max int) {
if a < b {
if b < c {
return a, c
} else if a < c {
return a, b
} else {
return c, b
}
} else {
if a < c {
return b, c
} else if b < c {
return b, a
} else {
return c, a
}
}
}
func toConsoleColor(rgb int) (c consoleColor) {
r, g, b := (rgb&0xFF0000)>>16, (rgb&0x00FF00)>>8, rgb&0x0000FF
min, max := minmax3(r, g, b)
a := (min + max) / 2
if r < 128 && g < 128 && b < 128 {
if r >= a {
c.red = true
}
if g >= a {
c.green = true
}
if b >= a {
c.blue = true
}
// non-intensed white is lighter than intensed black, so swap those.
if c.red && c.green && c.blue {
c.red, c.green, c.blue = false, false, false
c.intensity = true
}
} else {
if min < 128 {
min = 128
a = (min + max) / 2
}
if r >= a {
c.red = true
}
if g >= a {
c.green = true
}
if b >= a {
c.blue = true
}
c.intensity = true
// intensed black is darker than non-intensed white, so swap those.
if !c.red && !c.green && !c.blue {
c.red, c.green, c.blue = true, true, true
c.intensity = false
}
}
return c
}
func (c consoleColor) foregroundAttr() (attr word) {
if c.red {
attr |= foregroundRed
}
if c.green {
attr |= foregroundGreen
}
if c.blue {
attr |= foregroundBlue
}
if c.intensity {
attr |= foregroundIntensity
}
return
}
func (c consoleColor) backgroundAttr() (attr word) {
if c.red {
attr |= backgroundRed
}
if c.green {
attr |= backgroundGreen
}
if c.blue {
attr |= backgroundBlue
}
if c.intensity {
attr |= backgroundIntensity
}
return
}
var n256foreAttr []word
var n256backAttr []word
func n256setup() {
n256foreAttr = make([]word, 256)
n256backAttr = make([]word, 256)
for i, rgb := range color256 {
c := toConsoleColor(rgb)
n256foreAttr[i] = c.foregroundAttr()
n256backAttr[i] = c.backgroundAttr()
}
}

View file

@ -0,0 +1,27 @@
# Created by http://www.gitignore.io
### Go ###
# Compiled Object files, Static and Dynamic libs (Shared Objects)
*.o
*.a
*.so
# Folders
_obj
_test
# Architecture specific extensions/prefixes
*.[568vq]
[568vq].out
*.cgo1.go
*.cgo2.c
_cgo_defun.c
_cgo_gotypes.go
_cgo_export.*
_testmain.go
*.exe
*.test

View file

@ -0,0 +1,21 @@
The MIT License (MIT)
Copyright (c) [2014] [shiena]
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

View file

@ -0,0 +1,100 @@
[![GoDoc](https://godoc.org/github.com/shiena/ansicolor?status.svg)](https://godoc.org/github.com/shiena/ansicolor)
# ansicolor
Ansicolor library provides color console in Windows as ANSICON for Golang.
## Features
|Escape sequence|Text attributes|
|---------------|----|
|\x1b[0m|All attributes off(color at startup)|
|\x1b[1m|Bold on(enable foreground intensity)|
|\x1b[4m|Underline on|
|\x1b[5m|Blink on(enable background intensity)|
|\x1b[21m|Bold off(disable foreground intensity)|
|\x1b[24m|Underline off|
|\x1b[25m|Blink off(disable background intensity)|
|Escape sequence|Foreground colors|
|---------------|----|
|\x1b[30m|Black|
|\x1b[31m|Red|
|\x1b[32m|Green|
|\x1b[33m|Yellow|
|\x1b[34m|Blue|
|\x1b[35m|Magenta|
|\x1b[36m|Cyan|
|\x1b[37m|White|
|\x1b[39m|Default(foreground color at startup)|
|\x1b[90m|Light Gray|
|\x1b[91m|Light Red|
|\x1b[92m|Light Green|
|\x1b[93m|Light Yellow|
|\x1b[94m|Light Blue|
|\x1b[95m|Light Magenta|
|\x1b[96m|Light Cyan|
|\x1b[97m|Light White|
|Escape sequence|Background colors|
|---------------|----|
|\x1b[40m|Black|
|\x1b[41m|Red|
|\x1b[42m|Green|
|\x1b[43m|Yellow|
|\x1b[44m|Blue|
|\x1b[45m|Magenta|
|\x1b[46m|Cyan|
|\x1b[47m|White|
|\x1b[49m|Default(background color at startup)|
|\x1b[100m|Light Gray|
|\x1b[101m|Light Red|
|\x1b[102m|Light Green|
|\x1b[103m|Light Yellow|
|\x1b[104m|Light Blue|
|\x1b[105m|Light Magenta|
|\x1b[106m|Light Cyan|
|\x1b[107m|Light White|
## Example
```go
package main
import (
"fmt"
"os"
"github.com/shiena/ansicolor"
)
func main() {
w := ansicolor.NewAnsiColorWriter(os.Stdout)
text := "%sforeground %sbold%s %sbackground%s\n"
fmt.Fprintf(w, text, "\x1b[31m", "\x1b[1m", "\x1b[21m", "\x1b[41;32m", "\x1b[0m")
fmt.Fprintf(w, text, "\x1b[32m", "\x1b[1m", "\x1b[21m", "\x1b[42;31m", "\x1b[0m")
fmt.Fprintf(w, text, "\x1b[33m", "\x1b[1m", "\x1b[21m", "\x1b[43;34m", "\x1b[0m")
fmt.Fprintf(w, text, "\x1b[34m", "\x1b[1m", "\x1b[21m", "\x1b[44;33m", "\x1b[0m")
fmt.Fprintf(w, text, "\x1b[35m", "\x1b[1m", "\x1b[21m", "\x1b[45;36m", "\x1b[0m")
fmt.Fprintf(w, text, "\x1b[36m", "\x1b[1m", "\x1b[21m", "\x1b[46;35m", "\x1b[0m")
fmt.Fprintf(w, text, "\x1b[37m", "\x1b[1m", "\x1b[21m", "\x1b[47;30m", "\x1b[0m")
}
```
![screenshot](https://gist.githubusercontent.com/shiena/a1bada24b525314a7d5e/raw/c763aa7cda6e4fefaccf831e2617adc40b6151c7/main.png)
## See also:
- https://github.com/daviddengcn/go-colortext
- https://github.com/adoxa/ansicon
- https://github.com/aslakhellesoy/wac
- https://github.com/wsxiaoys/terminal
## Contributing
1. Fork it
2. Create your feature branch (`git checkout -b my-new-feature`)
3. Commit your changes (`git commit -am 'Add some feature'`)
4. Push to the branch (`git push origin my-new-feature`)
5. Create new Pull Request

View file

@ -0,0 +1,20 @@
// Copyright 2014 shiena Authors. All rights reserved.
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file.
// Package ansicolor provides color console in Windows as ANSICON.
package ansicolor
import "io"
// NewAnsiColorWriter creates and initializes a new ansiColorWriter
// using io.Writer w as its initial contents.
// In the console of Windows, which change the foreground and background
// colors of the text by the escape sequence.
// In the console of other systems, which writes to w all text.
func NewAnsiColorWriter(w io.Writer) io.Writer {
if _, ok := w.(*ansiColorWriter); !ok {
return &ansiColorWriter{w: w}
}
return w
}

View file

@ -0,0 +1,27 @@
// Copyright 2014 shiena Authors. All rights reserved.
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file.
/*
The ansicolor command colors a console text by ANSI escape sequence like wac.
$ go get github.com/shiena/ansicolor/ansicolor
See also:
https://github.com/aslakhellesoy/wac
*/
package main
import (
"io"
"os"
"github.com/shiena/ansicolor"
)
func main() {
w := ansicolor.NewAnsiColorWriter(os.Stdout)
io.Copy(w, os.Stdin)
}

View file

@ -0,0 +1,17 @@
// Copyright 2014 shiena Authors. All rights reserved.
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file.
// +build !windows
package ansicolor
import "io"
type ansiColorWriter struct {
w io.Writer
}
func (cw *ansiColorWriter) Write(p []byte) (int, error) {
return cw.w.Write(p)
}

View file

@ -0,0 +1,25 @@
package ansicolor_test
import (
"bytes"
"testing"
"github.com/shiena/ansicolor"
)
func TestNewAnsiColor1(t *testing.T) {
inner := bytes.NewBufferString("")
w := ansicolor.NewAnsiColorWriter(inner)
if w == inner {
t.Errorf("Get %#v, want %#v", w, inner)
}
}
func TestNewAnsiColor2(t *testing.T) {
inner := bytes.NewBufferString("")
w1 := ansicolor.NewAnsiColorWriter(inner)
w2 := ansicolor.NewAnsiColorWriter(w1)
if w1 != w2 {
t.Errorf("Get %#v, want %#v", w1, w2)
}
}

View file

@ -0,0 +1,351 @@
// Copyright 2014 shiena Authors. All rights reserved.
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file.
// +build windows
package ansicolor
import (
"bytes"
"io"
"strings"
"syscall"
"unsafe"
)
type csiState int
const (
outsideCsiCode csiState = iota
firstCsiCode
secondCsiCode
)
type ansiColorWriter struct {
w io.Writer
state csiState
paramBuf bytes.Buffer
}
const (
firstCsiChar byte = '\x1b'
secondeCsiChar byte = '['
separatorChar byte = ';'
sgrCode byte = 'm'
)
const (
foregroundBlue = uint16(0x0001)
foregroundGreen = uint16(0x0002)
foregroundRed = uint16(0x0004)
foregroundIntensity = uint16(0x0008)
backgroundBlue = uint16(0x0010)
backgroundGreen = uint16(0x0020)
backgroundRed = uint16(0x0040)
backgroundIntensity = uint16(0x0080)
underscore = uint16(0x8000)
foregroundMask = foregroundBlue | foregroundGreen | foregroundRed | foregroundIntensity
backgroundMask = backgroundBlue | backgroundGreen | backgroundRed | backgroundIntensity
)
const (
ansiReset = "0"
ansiIntensityOn = "1"
ansiIntensityOff = "21"
ansiUnderlineOn = "4"
ansiUnderlineOff = "24"
ansiBlinkOn = "5"
ansiBlinkOff = "25"
ansiForegroundBlack = "30"
ansiForegroundRed = "31"
ansiForegroundGreen = "32"
ansiForegroundYellow = "33"
ansiForegroundBlue = "34"
ansiForegroundMagenta = "35"
ansiForegroundCyan = "36"
ansiForegroundWhite = "37"
ansiForegroundDefault = "39"
ansiBackgroundBlack = "40"
ansiBackgroundRed = "41"
ansiBackgroundGreen = "42"
ansiBackgroundYellow = "43"
ansiBackgroundBlue = "44"
ansiBackgroundMagenta = "45"
ansiBackgroundCyan = "46"
ansiBackgroundWhite = "47"
ansiBackgroundDefault = "49"
ansiLightForegroundGray = "90"
ansiLightForegroundRed = "91"
ansiLightForegroundGreen = "92"
ansiLightForegroundYellow = "93"
ansiLightForegroundBlue = "94"
ansiLightForegroundMagenta = "95"
ansiLightForegroundCyan = "96"
ansiLightForegroundWhite = "97"
ansiLightBackgroundGray = "100"
ansiLightBackgroundRed = "101"
ansiLightBackgroundGreen = "102"
ansiLightBackgroundYellow = "103"
ansiLightBackgroundBlue = "104"
ansiLightBackgroundMagenta = "105"
ansiLightBackgroundCyan = "106"
ansiLightBackgroundWhite = "107"
)
type drawType int
const (
foreground drawType = iota
background
)
type winColor struct {
code uint16
drawType drawType
}
var colorMap = map[string]winColor{
ansiForegroundBlack: {0, foreground},
ansiForegroundRed: {foregroundRed, foreground},
ansiForegroundGreen: {foregroundGreen, foreground},
ansiForegroundYellow: {foregroundRed | foregroundGreen, foreground},
ansiForegroundBlue: {foregroundBlue, foreground},
ansiForegroundMagenta: {foregroundRed | foregroundBlue, foreground},
ansiForegroundCyan: {foregroundGreen | foregroundBlue, foreground},
ansiForegroundWhite: {foregroundRed | foregroundGreen | foregroundBlue, foreground},
ansiForegroundDefault: {foregroundRed | foregroundGreen | foregroundBlue, foreground},
ansiBackgroundBlack: {0, background},
ansiBackgroundRed: {backgroundRed, background},
ansiBackgroundGreen: {backgroundGreen, background},
ansiBackgroundYellow: {backgroundRed | backgroundGreen, background},
ansiBackgroundBlue: {backgroundBlue, background},
ansiBackgroundMagenta: {backgroundRed | backgroundBlue, background},
ansiBackgroundCyan: {backgroundGreen | backgroundBlue, background},
ansiBackgroundWhite: {backgroundRed | backgroundGreen | backgroundBlue, background},
ansiBackgroundDefault: {0, background},
ansiLightForegroundGray: {foregroundIntensity, foreground},
ansiLightForegroundRed: {foregroundIntensity | foregroundRed, foreground},
ansiLightForegroundGreen: {foregroundIntensity | foregroundGreen, foreground},
ansiLightForegroundYellow: {foregroundIntensity | foregroundRed | foregroundGreen, foreground},
ansiLightForegroundBlue: {foregroundIntensity | foregroundBlue, foreground},
ansiLightForegroundMagenta: {foregroundIntensity | foregroundRed | foregroundBlue, foreground},
ansiLightForegroundCyan: {foregroundIntensity | foregroundGreen | foregroundBlue, foreground},
ansiLightForegroundWhite: {foregroundIntensity | foregroundRed | foregroundGreen | foregroundBlue, foreground},
ansiLightBackgroundGray: {backgroundIntensity, background},
ansiLightBackgroundRed: {backgroundIntensity | backgroundRed, background},
ansiLightBackgroundGreen: {backgroundIntensity | backgroundGreen, background},
ansiLightBackgroundYellow: {backgroundIntensity | backgroundRed | backgroundGreen, background},
ansiLightBackgroundBlue: {backgroundIntensity | backgroundBlue, background},
ansiLightBackgroundMagenta: {backgroundIntensity | backgroundRed | backgroundBlue, background},
ansiLightBackgroundCyan: {backgroundIntensity | backgroundGreen | backgroundBlue, background},
ansiLightBackgroundWhite: {backgroundIntensity | backgroundRed | backgroundGreen | backgroundBlue, background},
}
var (
kernel32 = syscall.NewLazyDLL("kernel32.dll")
procSetConsoleTextAttribute = kernel32.NewProc("SetConsoleTextAttribute")
procGetConsoleScreenBufferInfo = kernel32.NewProc("GetConsoleScreenBufferInfo")
defaultAttr *textAttributes
)
func init() {
screenInfo := getConsoleScreenBufferInfo(uintptr(syscall.Stdout))
if screenInfo != nil {
colorMap[ansiForegroundDefault] = winColor{
screenInfo.WAttributes & (foregroundRed | foregroundGreen | foregroundBlue),
foreground,
}
colorMap[ansiBackgroundDefault] = winColor{
screenInfo.WAttributes & (backgroundRed | backgroundGreen | backgroundBlue),
background,
}
defaultAttr = convertTextAttr(screenInfo.WAttributes)
}
}
type coord struct {
X, Y int16
}
type smallRect struct {
Left, Top, Right, Bottom int16
}
type consoleScreenBufferInfo struct {
DwSize coord
DwCursorPosition coord
WAttributes uint16
SrWindow smallRect
DwMaximumWindowSize coord
}
func getConsoleScreenBufferInfo(hConsoleOutput uintptr) *consoleScreenBufferInfo {
var csbi consoleScreenBufferInfo
ret, _, _ := procGetConsoleScreenBufferInfo.Call(
hConsoleOutput,
uintptr(unsafe.Pointer(&csbi)))
if ret == 0 {
return nil
}
return &csbi
}
func setConsoleTextAttribute(hConsoleOutput uintptr, wAttributes uint16) bool {
ret, _, _ := procSetConsoleTextAttribute.Call(
hConsoleOutput,
uintptr(wAttributes))
return ret != 0
}
type textAttributes struct {
foregroundColor uint16
backgroundColor uint16
foregroundIntensity uint16
backgroundIntensity uint16
underscore uint16
otherAttributes uint16
}
func convertTextAttr(winAttr uint16) *textAttributes {
fgColor := winAttr & (foregroundRed | foregroundGreen | foregroundBlue)
bgColor := winAttr & (backgroundRed | backgroundGreen | backgroundBlue)
fgIntensity := winAttr & foregroundIntensity
bgIntensity := winAttr & backgroundIntensity
underline := winAttr & underscore
otherAttributes := winAttr &^ (foregroundMask | backgroundMask | underscore)
return &textAttributes{fgColor, bgColor, fgIntensity, bgIntensity, underline, otherAttributes}
}
func convertWinAttr(textAttr *textAttributes) uint16 {
var winAttr uint16 = 0
winAttr |= textAttr.foregroundColor
winAttr |= textAttr.backgroundColor
winAttr |= textAttr.foregroundIntensity
winAttr |= textAttr.backgroundIntensity
winAttr |= textAttr.underscore
winAttr |= textAttr.otherAttributes
return winAttr
}
func changeColor(param []byte) {
if defaultAttr == nil {
return
}
screenInfo := getConsoleScreenBufferInfo(uintptr(syscall.Stdout))
if screenInfo == nil {
return
}
winAttr := convertTextAttr(screenInfo.WAttributes)
strParam := string(param)
if len(strParam) <= 0 {
strParam = "0"
}
csiParam := strings.Split(strParam, string(separatorChar))
for _, p := range csiParam {
c, ok := colorMap[p]
switch {
case !ok:
switch p {
case ansiReset:
winAttr.foregroundColor = defaultAttr.foregroundColor
winAttr.backgroundColor = defaultAttr.backgroundColor
winAttr.foregroundIntensity = defaultAttr.foregroundIntensity
winAttr.backgroundIntensity = defaultAttr.backgroundIntensity
winAttr.underscore = 0
winAttr.otherAttributes = 0
case ansiIntensityOn:
winAttr.foregroundIntensity = foregroundIntensity
case ansiIntensityOff:
winAttr.foregroundIntensity = 0
case ansiUnderlineOn:
winAttr.underscore = underscore
case ansiUnderlineOff:
winAttr.underscore = 0
case ansiBlinkOn:
winAttr.backgroundIntensity = backgroundIntensity
case ansiBlinkOff:
winAttr.backgroundIntensity = 0
default:
// unknown code
}
case c.drawType == foreground:
winAttr.foregroundColor = c.code
case c.drawType == background:
winAttr.backgroundColor = c.code
}
}
winTextAttribute := convertWinAttr(winAttr)
setConsoleTextAttribute(uintptr(syscall.Stdout), winTextAttribute)
}
func parseEscapeSequence(command byte, param []byte) {
switch command {
case sgrCode:
changeColor(param)
}
}
func isParameterChar(b byte) bool {
return ('0' <= b && b <= '9') || b == separatorChar
}
func (cw *ansiColorWriter) Write(p []byte) (int, error) {
r, nw, nc, first, last := 0, 0, 0, 0, 0
var err error
for i, ch := range p {
switch cw.state {
case outsideCsiCode:
if ch == firstCsiChar {
nc++
cw.state = firstCsiCode
}
case firstCsiCode:
switch ch {
case firstCsiChar:
nc++
break
case secondeCsiChar:
nc++
cw.state = secondCsiCode
last = i - 1
default:
cw.state = outsideCsiCode
}
case secondCsiCode:
nc++
if isParameterChar(ch) {
cw.paramBuf.WriteByte(ch)
} else {
nw, err = cw.w.Write(p[first:last])
r += nw
if err != nil {
return r, err
}
first = i + 1
param := cw.paramBuf.Bytes()
cw.paramBuf.Reset()
parseEscapeSequence(ch, param)
cw.state = outsideCsiCode
}
default:
cw.state = outsideCsiCode
}
}
if cw.state == outsideCsiCode {
nw, err = cw.w.Write(p[first:len(p)])
}
return r + nw + nc, err
}

View file

@ -0,0 +1,236 @@
// Copyright 2014 shiena Authors. All rights reserved.
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file.
// +build windows
package ansicolor_test
import (
"bytes"
"fmt"
"syscall"
"testing"
"github.com/shiena/ansicolor"
. "github.com/shiena/ansicolor"
)
func TestWritePlanText(t *testing.T) {
inner := bytes.NewBufferString("")
w := ansicolor.NewAnsiColorWriter(inner)
expected := "plain text"
fmt.Fprintf(w, expected)
actual := inner.String()
if actual != expected {
t.Errorf("Get %s, want %s", actual, expected)
}
}
func TestWriteParseText(t *testing.T) {
inner := bytes.NewBufferString("")
w := ansicolor.NewAnsiColorWriter(inner)
inputTail := "\x1b[0mtail text"
expectedTail := "tail text"
fmt.Fprintf(w, inputTail)
actualTail := inner.String()
inner.Reset()
if actualTail != expectedTail {
t.Errorf("Get %s, want %s", actualTail, expectedTail)
}
inputHead := "head text\x1b[0m"
expectedHead := "head text"
fmt.Fprintf(w, inputHead)
actualHead := inner.String()
inner.Reset()
if actualHead != expectedHead {
t.Errorf("Get %s, want %s", actualHead, expectedHead)
}
inputBothEnds := "both ends \x1b[0m text"
expectedBothEnds := "both ends text"
fmt.Fprintf(w, inputBothEnds)
actualBothEnds := inner.String()
inner.Reset()
if actualBothEnds != expectedBothEnds {
t.Errorf("Get %s, want %s", actualBothEnds, expectedBothEnds)
}
inputManyEsc := "\x1b\x1b\x1b\x1b[0m many esc"
expectedManyEsc := "\x1b\x1b\x1b many esc"
fmt.Fprintf(w, inputManyEsc)
actualManyEsc := inner.String()
inner.Reset()
if actualManyEsc != expectedManyEsc {
t.Errorf("Get %s, want %s", actualManyEsc, expectedManyEsc)
}
expectedSplit := "split text"
for _, ch := range "split \x1b[0m text" {
fmt.Fprintf(w, string(ch))
}
actualSplit := inner.String()
inner.Reset()
if actualSplit != expectedSplit {
t.Errorf("Get %s, want %s", actualSplit, expectedSplit)
}
}
type screenNotFoundError struct {
error
}
func writeAnsiColor(expectedText, colorCode string) (actualText string, actualAttributes uint16, err error) {
inner := bytes.NewBufferString("")
w := ansicolor.NewAnsiColorWriter(inner)
fmt.Fprintf(w, "\x1b[%sm%s", colorCode, expectedText)
actualText = inner.String()
screenInfo := GetConsoleScreenBufferInfo(uintptr(syscall.Stdout))
if screenInfo != nil {
actualAttributes = screenInfo.WAttributes
} else {
err = &screenNotFoundError{}
}
return
}
type testParam struct {
text string
attributes uint16
ansiColor string
}
func TestWriteAnsiColorText(t *testing.T) {
screenInfo := GetConsoleScreenBufferInfo(uintptr(syscall.Stdout))
if screenInfo == nil {
t.Fatal("Could not get ConsoleScreenBufferInfo")
}
defer ChangeColor(screenInfo.WAttributes)
defaultFgColor := screenInfo.WAttributes & uint16(0x0007)
defaultBgColor := screenInfo.WAttributes & uint16(0x0070)
defaultFgIntensity := screenInfo.WAttributes & uint16(0x0008)
defaultBgIntensity := screenInfo.WAttributes & uint16(0x0080)
fgParam := []testParam{
{"foreground black ", uint16(0x0000 | 0x0000), "30"},
{"foreground red ", uint16(0x0004 | 0x0000), "31"},
{"foreground green ", uint16(0x0002 | 0x0000), "32"},
{"foreground yellow ", uint16(0x0006 | 0x0000), "33"},
{"foreground blue ", uint16(0x0001 | 0x0000), "34"},
{"foreground magenta", uint16(0x0005 | 0x0000), "35"},
{"foreground cyan ", uint16(0x0003 | 0x0000), "36"},
{"foreground white ", uint16(0x0007 | 0x0000), "37"},
{"foreground default", defaultFgColor | 0x0000, "39"},
{"foreground light gray ", uint16(0x0000 | 0x0008 | 0x0000), "90"},
{"foreground light red ", uint16(0x0004 | 0x0008 | 0x0000), "91"},
{"foreground light green ", uint16(0x0002 | 0x0008 | 0x0000), "92"},
{"foreground light yellow ", uint16(0x0006 | 0x0008 | 0x0000), "93"},
{"foreground light blue ", uint16(0x0001 | 0x0008 | 0x0000), "94"},
{"foreground light magenta", uint16(0x0005 | 0x0008 | 0x0000), "95"},
{"foreground light cyan ", uint16(0x0003 | 0x0008 | 0x0000), "96"},
{"foreground light white ", uint16(0x0007 | 0x0008 | 0x0000), "97"},
}
bgParam := []testParam{
{"background black ", uint16(0x0007 | 0x0000), "40"},
{"background red ", uint16(0x0007 | 0x0040), "41"},
{"background green ", uint16(0x0007 | 0x0020), "42"},
{"background yellow ", uint16(0x0007 | 0x0060), "43"},
{"background blue ", uint16(0x0007 | 0x0010), "44"},
{"background magenta", uint16(0x0007 | 0x0050), "45"},
{"background cyan ", uint16(0x0007 | 0x0030), "46"},
{"background white ", uint16(0x0007 | 0x0070), "47"},
{"background default", uint16(0x0007) | defaultBgColor, "49"},
{"background light gray ", uint16(0x0007 | 0x0000 | 0x0080), "100"},
{"background light red ", uint16(0x0007 | 0x0040 | 0x0080), "101"},
{"background light green ", uint16(0x0007 | 0x0020 | 0x0080), "102"},
{"background light yellow ", uint16(0x0007 | 0x0060 | 0x0080), "103"},
{"background light blue ", uint16(0x0007 | 0x0010 | 0x0080), "104"},
{"background light magenta", uint16(0x0007 | 0x0050 | 0x0080), "105"},
{"background light cyan ", uint16(0x0007 | 0x0030 | 0x0080), "106"},
{"background light white ", uint16(0x0007 | 0x0070 | 0x0080), "107"},
}
resetParam := []testParam{
{"all reset", defaultFgColor | defaultBgColor | defaultFgIntensity | defaultBgIntensity, "0"},
{"all reset", defaultFgColor | defaultBgColor | defaultFgIntensity | defaultBgIntensity, ""},
}
boldParam := []testParam{
{"bold on", uint16(0x0007 | 0x0008), "1"},
{"bold off", uint16(0x0007), "21"},
}
underscoreParam := []testParam{
{"underscore on", uint16(0x0007 | 0x8000), "4"},
{"underscore off", uint16(0x0007), "24"},
}
blinkParam := []testParam{
{"blink on", uint16(0x0007 | 0x0080), "5"},
{"blink off", uint16(0x0007), "25"},
}
mixedParam := []testParam{
{"both black, bold, underline, blink", uint16(0x0000 | 0x0000 | 0x0008 | 0x8000 | 0x0080), "30;40;1;4;5"},
{"both red, bold, underline, blink", uint16(0x0004 | 0x0040 | 0x0008 | 0x8000 | 0x0080), "31;41;1;4;5"},
{"both green, bold, underline, blink", uint16(0x0002 | 0x0020 | 0x0008 | 0x8000 | 0x0080), "32;42;1;4;5"},
{"both yellow, bold, underline, blink", uint16(0x0006 | 0x0060 | 0x0008 | 0x8000 | 0x0080), "33;43;1;4;5"},
{"both blue, bold, underline, blink", uint16(0x0001 | 0x0010 | 0x0008 | 0x8000 | 0x0080), "34;44;1;4;5"},
{"both magenta, bold, underline, blink", uint16(0x0005 | 0x0050 | 0x0008 | 0x8000 | 0x0080), "35;45;1;4;5"},
{"both cyan, bold, underline, blink", uint16(0x0003 | 0x0030 | 0x0008 | 0x8000 | 0x0080), "36;46;1;4;5"},
{"both white, bold, underline, blink", uint16(0x0007 | 0x0070 | 0x0008 | 0x8000 | 0x0080), "37;47;1;4;5"},
{"both default, bold, underline, blink", uint16(defaultFgColor | defaultBgColor | 0x0008 | 0x8000 | 0x0080), "39;49;1;4;5"},
}
assertTextAttribute := func(expectedText string, expectedAttributes uint16, ansiColor string) {
actualText, actualAttributes, err := writeAnsiColor(expectedText, ansiColor)
if actualText != expectedText {
t.Errorf("Get %s, want %s", actualText, expectedText)
}
if err != nil {
t.Fatal("Could not get ConsoleScreenBufferInfo")
}
if actualAttributes != expectedAttributes {
t.Errorf("Text: %s, Get 0x%04x, want 0x%04x", expectedText, actualAttributes, expectedAttributes)
}
}
for _, v := range fgParam {
ResetColor()
assertTextAttribute(v.text, v.attributes, v.ansiColor)
}
for _, v := range bgParam {
ChangeColor(uint16(0x0070 | 0x0007))
assertTextAttribute(v.text, v.attributes, v.ansiColor)
}
for _, v := range resetParam {
ChangeColor(uint16(0x0000 | 0x0070 | 0x0008))
assertTextAttribute(v.text, v.attributes, v.ansiColor)
}
ResetColor()
for _, v := range boldParam {
assertTextAttribute(v.text, v.attributes, v.ansiColor)
}
ResetColor()
for _, v := range underscoreParam {
assertTextAttribute(v.text, v.attributes, v.ansiColor)
}
ResetColor()
for _, v := range blinkParam {
assertTextAttribute(v.text, v.attributes, v.ansiColor)
}
for _, v := range mixedParam {
ResetColor()
assertTextAttribute(v.text, v.attributes, v.ansiColor)
}
}

View file

@ -0,0 +1,24 @@
// Copyright 2014 shiena Authors. All rights reserved.
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file.
package ansicolor_test
import (
"fmt"
"os"
"github.com/shiena/ansicolor"
)
func ExampleNewAnsiColorWriter() {
w := ansicolor.NewAnsiColorWriter(os.Stdout)
text := "%sforeground %sbold%s %sbackground%s\n"
fmt.Fprintf(w, text, "\x1b[31m", "\x1b[1m", "\x1b[21m", "\x1b[41;32m", "\x1b[0m")
fmt.Fprintf(w, text, "\x1b[32m", "\x1b[1m", "\x1b[21m", "\x1b[42;31m", "\x1b[0m")
fmt.Fprintf(w, text, "\x1b[33m", "\x1b[1m", "\x1b[21m", "\x1b[43;34m", "\x1b[0m")
fmt.Fprintf(w, text, "\x1b[34m", "\x1b[1m", "\x1b[21m", "\x1b[44;33m", "\x1b[0m")
fmt.Fprintf(w, text, "\x1b[35m", "\x1b[1m", "\x1b[21m", "\x1b[45;36m", "\x1b[0m")
fmt.Fprintf(w, text, "\x1b[36m", "\x1b[1m", "\x1b[21m", "\x1b[46;35m", "\x1b[0m")
fmt.Fprintf(w, text, "\x1b[37m", "\x1b[1m", "\x1b[21m", "\x1b[47;30m", "\x1b[0m")
}

View file

@ -0,0 +1,19 @@
// Copyright 2014 shiena Authors. All rights reserved.
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file.
// +build windows
package ansicolor
import "syscall"
var GetConsoleScreenBufferInfo = getConsoleScreenBufferInfo
func ChangeColor(color uint16) {
setConsoleTextAttribute(uintptr(syscall.Stdout), color)
}
func ResetColor() {
ChangeColor(uint16(0x0007))
}

View file

@ -18,7 +18,6 @@ import (
"sync" "sync"
"time" "time"
"github.com/ethereum/go-ethereum/fdtrack"
"github.com/syndtr/goleveldb/leveldb/util" "github.com/syndtr/goleveldb/leveldb/util"
) )
@ -370,8 +369,6 @@ func (fw fileWrap) Close() error {
err := fw.File.Close() err := fw.File.Close()
if err != nil { if err != nil {
f.fs.log(fmt.Sprintf("close %s.%d: %v", f.Type(), f.Num(), err)) f.fs.log(fmt.Sprintf("close %s.%d: %v", f.Type(), f.Num(), err))
} else {
fdtrack.Close("leveldb")
} }
return err return err
} }
@ -403,7 +400,6 @@ func (f *file) Open() (Reader, error) {
return nil, err return nil, err
} }
ok: ok:
fdtrack.Open("leveldb")
f.open = true f.open = true
f.fs.open++ f.fs.open++
return fileWrap{of, f}, nil return fileWrap{of, f}, nil
@ -422,7 +418,6 @@ func (f *file) Create() (Writer, error) {
if err != nil { if err != nil {
return nil, err return nil, err
} }
fdtrack.Open("leveldb")
f.open = true f.open = true
f.fs.open++ f.fs.open++
return fileWrap{of, f}, nil return fileWrap{of, f}, nil

View file

@ -1,19 +1,18 @@
## Ethereum Go ## Ethereum Go
Ethereum Go Client, by Jeffrey Wilcke (and some other people). Official golang implementation of the Ethereum protocol
| Linux | OSX | ARM | Windows | Tests | Linux | OSX | ARM | Windows | Tests
----------|---------|-----|-----|---------|------ ----------|---------|-----|-----|---------|------
develop | [![Build+Status](https://build.ethdev.com/buildstatusimage?builder=Linux%20Go%20develop%20branch)](https://build.ethdev.com/builders/Linux%20Go%20develop%20branch/builds/-1) | [![Build+Status](https://build.ethdev.com/buildstatusimage?builder=Linux%20Go%20develop%20branch)](https://build.ethdev.com/builders/OSX%20Go%20develop%20branch/builds/-1) | [![Build+Status](https://build.ethdev.com/buildstatusimage?builder=ARM%20Go%20develop%20branch)](https://build.ethdev.com/builders/ARM%20Go%20develop%20branch/builds/-1) | [![Build+Status](https://build.ethdev.com/buildstatusimage?builder=Windows%20Go%20develop%20branch)](https://build.ethdev.com/builders/Windows%20Go%20develop%20branch/builds/-1) | [![Buildr+Status](https://travis-ci.org/ethereum/go-ethereum.svg?branch=develop)](https://travis-ci.org/ethereum/go-ethereum) [![Coverage Status](https://coveralls.io/repos/ethereum/go-ethereum/badge.svg?branch=develop)](https://coveralls.io/r/ethereum/go-ethereum?branch=develop) develop | [![Build+Status](https://build.ethdev.com/buildstatusimage?builder=Linux%20Go%20develop%20branch)](https://build.ethdev.com/builders/Linux%20Go%20develop%20branch/builds/-1) | [![Build+Status](https://build.ethdev.com/buildstatusimage?builder=Linux%20Go%20develop%20branch)](https://build.ethdev.com/builders/OSX%20Go%20develop%20branch/builds/-1) | [![Build+Status](https://build.ethdev.com/buildstatusimage?builder=ARM%20Go%20develop%20branch)](https://build.ethdev.com/builders/ARM%20Go%20develop%20branch/builds/-1) | [![Build+Status](https://build.ethdev.com/buildstatusimage?builder=Windows%20Go%20develop%20branch)](https://build.ethdev.com/builders/Windows%20Go%20develop%20branch/builds/-1) | [![Buildr+Status](https://travis-ci.org/ethereum/go-ethereum.svg?branch=develop)](https://travis-ci.org/ethereum/go-ethereum) [![codecov.io](http://codecov.io/github/ethereum/go-ethereum/coverage.svg?branch=develop)](http://codecov.io/github/ethereum/go-ethereum?branch=develop)
master | [![Build+Status](https://build.ethdev.com/buildstatusimage?builder=Linux%20Go%20master%20branch)](https://build.ethdev.com/builders/Linux%20Go%20master%20branch/builds/-1) | [![Build+Status](https://build.ethdev.com/buildstatusimage?builder=OSX%20Go%20master%20branch)](https://build.ethdev.com/builders/OSX%20Go%20master%20branch/builds/-1) | [![Build+Status](https://build.ethdev.com/buildstatusimage?builder=ARM%20Go%20master%20branch)](https://build.ethdev.com/builders/ARM%20Go%20master%20branch/builds/-1) | [![Build+Status](https://build.ethdev.com/buildstatusimage?builder=Windows%20Go%20master%20branch)](https://build.ethdev.com/builders/Windows%20Go%20master%20branch/builds/-1) | [![Buildr+Status](https://travis-ci.org/ethereum/go-ethereum.svg?branch=master)](https://travis-ci.org/ethereum/go-ethereum) [![Coverage Status](https://coveralls.io/repos/ethereum/go-ethereum/badge.svg?branch=master)](https://coveralls.io/r/ethereum/go-ethereum?branch=master) master | [![Build+Status](https://build.ethdev.com/buildstatusimage?builder=Linux%20Go%20master%20branch)](https://build.ethdev.com/builders/Linux%20Go%20master%20branch/builds/-1) | [![Build+Status](https://build.ethdev.com/buildstatusimage?builder=OSX%20Go%20master%20branch)](https://build.ethdev.com/builders/OSX%20Go%20master%20branch/builds/-1) | [![Build+Status](https://build.ethdev.com/buildstatusimage?builder=ARM%20Go%20master%20branch)](https://build.ethdev.com/builders/ARM%20Go%20master%20branch/builds/-1) | [![Build+Status](https://build.ethdev.com/buildstatusimage?builder=Windows%20Go%20master%20branch)](https://build.ethdev.com/builders/Windows%20Go%20master%20branch/builds/-1) | [![Buildr+Status](https://travis-ci.org/ethereum/go-ethereum.svg?branch=master)](https://travis-ci.org/ethereum/go-ethereum) [![codecov.io](http://codecov.io/github/ethereum/go-ethereum/coverage.svg?branch=master)](http://codecov.io/github/ethereum/go-ethereum?branch=master)
[![Bugs](https://badge.waffle.io/ethereum/go-ethereum.png?label=bug&title=Bugs)](https://waffle.io/ethereum/go-ethereum) [![API Reference](
[![Stories in Ready](https://badge.waffle.io/ethereum/go-ethereum.png?label=ready&title=Ready)](https://waffle.io/ethereum/go-ethereum) https://camo.githubusercontent.com/915b7be44ada53c290eb157634330494ebe3e30a/68747470733a2f2f676f646f632e6f72672f6769746875622e636f6d2f676f6c616e672f6764646f3f7374617475732e737667
[![Stories in Progress](https://badge.waffle.io/ethereum/go-ethereum.svg?label=in%20progress&title=In Progress)](http://waffle.io/ethereum/go-ethereum) )](https://godoc.org/github.com/ethereum/go-ethereum)
[![Gitter](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/ethereum/go-ethereum?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge) [![Gitter](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/ethereum/go-ethereum?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge)
Automated development builds ## Automated development builds
======================
The following builds are build automatically by our build servers after each push to the [develop](https://github.com/ethereum/go-ethereum/tree/develop) branch. The following builds are build automatically by our build servers after each push to the [develop](https://github.com/ethereum/go-ethereum/tree/develop) branch.
@ -25,8 +24,7 @@ The following builds are build automatically by our build servers after each pus
* [Windows 64-bit](https://build.ethdev.com/builds/Windows%20Go%20develop%20branch/Geth-Win64-latest.zip) * [Windows 64-bit](https://build.ethdev.com/builds/Windows%20Go%20develop%20branch/Geth-Win64-latest.zip)
* [ARM](https://build.ethdev.com/builds/ARM%20Go%20develop%20branch/geth-ARM-latest.tar.bz2) * [ARM](https://build.ethdev.com/builds/ARM%20Go%20develop%20branch/geth-ARM-latest.tar.bz2)
Building the source ## Building the source
===================
For prerequisites and detailed build instructions please read the For prerequisites and detailed build instructions please read the
[Installation Instructions](https://github.com/ethereum/go-ethereum/wiki/Building-Ethereum) [Installation Instructions](https://github.com/ethereum/go-ethereum/wiki/Building-Ethereum)
@ -38,34 +36,31 @@ Once the dependencies are installed, run
make geth make geth
Executables ## Executables
===========
Go Ethereum comes with several wrappers/executables found in Go Ethereum comes with several wrappers/executables found in
[the `cmd` directory](https://github.com/ethereum/go-ethereum/tree/develop/cmd): [the `cmd` directory](https://github.com/ethereum/go-ethereum/tree/develop/cmd):
* `geth` Ethereum CLI (ethereum command line interface client) Command | |
* `bootnode` runs a bootstrap node for the Discovery Protocol ----------|---------|
* `ethtest` test tool which runs with the [tests](https://github.com/ethereum/tests) suite: `geth` | Ethereum CLI (ethereum command line interface client) |
`/path/to/test.json > ethtest --test BlockTests --stdin`. `bootnode` | runs a bootstrap node for the Discovery Protocol |
* `evm` is a generic Ethereum Virtual Machine: `evm -code 60ff60ff -gas `ethtest` | test tool which runs with the [tests](https://github.com/ethereum/tests) suite: `/path/to/test.json > ethtest --test BlockTests --stdin`.
10000 -price 0 -dump`. See `-h` for a detailed description. `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` `disasm` | disassembles EVM code: `echo "6001" | disasm` |
* `rlpdump` prints RLP structures `rlpdump` | prints RLP structures |
Command line options ## Command line options
====================
`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: To get the options available:
geth --help geth help
For further details on options, see the [wiki](https://github.com/ethereum/go-ethereum/wiki/Command-Line-Options) For further details on options, see the [wiki](https://github.com/ethereum/go-ethereum/wiki/Command-Line-Options)
Contribution ## Contribution
============
If you'd like to contribute to go-ethereum please fork, fix, commit and If you'd like to contribute to go-ethereum please fork, fix, commit and
send a pull request. Commits who do not comply with the coding standards send a pull request. Commits who do not comply with the coding standards

View file

@ -1,26 +1,15 @@
#!/bin/bash #!/usr/bin/env bash
# This script runs all package tests and merges the resulting coverage
# profiles. Coverage is accounted per package under test.
set -e set -e
echo "" > coverage.txt
if [ ! -f "build/env.sh" ]; then for d in $(find ./* -maxdepth 10 -type d -not -path "./build" -not -path "./Godeps/*" ); do
echo "$0 must be run from the root of the repository." if ls $d/*.go &> /dev/null; then
exit 2 go test -coverprofile=profile.out -covermode=atomic $d
fi if [ -f profile.out ]; then
cat profile.out >> coverage.txt
echo "mode: count" > profile.cov echo '<<<<<< EOF' >> coverage.txt
rm profile.out
for pkg in $(go list ./...); do fi
# drop the namespace prefix.
dir=${pkg##github.com/ethereum/go-ethereum/}
if [[ $dir != "tests" ]]; then
go test -covermode=count -coverprofile=$dir/profile.tmp $pkg
fi
if [[ -f $dir/profile.tmp ]]; then
tail -n +2 $dir/profile.tmp >> profile.cov
rm $dir/profile.tmp
fi fi
done done

View file

@ -102,7 +102,7 @@ func init() {
func run(ctx *cli.Context) { func run(ctx *cli.Context) {
vm.Debug = ctx.GlobalBool(DebugFlag.Name) vm.Debug = ctx.GlobalBool(DebugFlag.Name)
vm.ForceJit = ctx.GlobalBool(ForceJitFlag.Name) vm.ForceJit = ctx.GlobalBool(ForceJitFlag.Name)
vm.DisableJit = ctx.GlobalBool(DisableJitFlag.Name) vm.EnableJit = !ctx.GlobalBool(DisableJitFlag.Name)
glog.SetToStderr(true) glog.SetToStderr(true)

View file

@ -115,17 +115,16 @@ func exportChain(ctx *cli.Context) {
} }
func removeDB(ctx *cli.Context) { func removeDB(ctx *cli.Context) {
confirm, err := utils.PromptConfirm("Remove local databases?") confirm, err := utils.PromptConfirm("Remove local database?")
if err != nil { if err != nil {
utils.Fatalf("%v", err) utils.Fatalf("%v", err)
} }
if confirm { if confirm {
fmt.Println("Removing chain and state databases...") fmt.Println("Removing chaindata...")
start := time.Now() start := time.Now()
os.RemoveAll(filepath.Join(ctx.GlobalString(utils.DataDirFlag.Name), "blockchain")) os.RemoveAll(filepath.Join(ctx.GlobalString(utils.DataDirFlag.Name), "chaindata"))
os.RemoveAll(filepath.Join(ctx.GlobalString(utils.DataDirFlag.Name), "state"))
fmt.Printf("Removed in %v\n", time.Since(start)) fmt.Printf("Removed in %v\n", time.Since(start))
} else { } else {

View file

@ -145,19 +145,15 @@ func apiWordCompleter(line string, pos int) (head string, completions []string,
return begin, completionWords, end return begin, completionWords, end
} }
func newLightweightJSRE(libPath string, client comms.EthereumClient, interactive bool, f xeth.Frontend) *jsre { func newLightweightJSRE(libPath string, client comms.EthereumClient, interactive bool) *jsre {
js := &jsre{ps1: "> "} js := &jsre{ps1: "> "}
js.wait = make(chan *big.Int) js.wait = make(chan *big.Int)
js.client = client js.client = client
js.ds = docserver.New("/") js.ds = docserver.New("/")
if f == nil {
f = js
}
// update state in separare forever blocks // update state in separare forever blocks
js.re = re.New(libPath) js.re = re.New(libPath)
if err := js.apiBindings(f); err != nil { if err := js.apiBindings(js); err != nil {
utils.Fatalf("Unable to initialize console - %v", err) utils.Fatalf("Unable to initialize console - %v", err)
} }
@ -232,15 +228,10 @@ func (self *jsre) loadAutoCompletion() {
} }
func (self *jsre) batch(statement string) { func (self *jsre) batch(statement string) {
val, err := self.re.Run(statement) err := self.re.EvalAndPrettyPrint(statement)
if err != nil { if err != nil {
fmt.Printf("error: %v", err) fmt.Printf("error: %v", err)
} else if val.IsDefined() && val.IsObject() {
obj, _ := self.re.Get("ret_result")
fmt.Printf("%v", obj)
} else if val.IsDefined() {
fmt.Printf("%v", val)
} }
if self.atexit != nil { if self.atexit != nil {
@ -252,22 +243,22 @@ func (self *jsre) batch(statement string) {
// show summary of current geth instance // show summary of current geth instance
func (self *jsre) welcome() { func (self *jsre) welcome() {
self.re.Eval(`console.log('instance: ' + web3.version.client);`) self.re.Run(`
self.re.Eval(`console.log(' datadir: ' + admin.datadir);`) (function () {
self.re.Eval(`console.log("coinbase: " + eth.coinbase);`) console.log('instance: ' + web3.version.client);
self.re.Eval(`var lastBlockTimestamp = 1000 * eth.getBlock(eth.blockNumber).timestamp`) console.log(' datadir: ' + admin.datadir);
self.re.Eval(`console.log("at block: " + eth.blockNumber + " (" + new Date(lastBlockTimestamp).toLocaleDateString() console.log("coinbase: " + eth.coinbase);
+ " " + new Date(lastBlockTimestamp).toLocaleTimeString() + ")");`) var ts = 1000 * eth.getBlock(eth.blockNumber).timestamp;
console.log("at block: " + eth.blockNumber + " (" + new Date(ts) + ")");
})();
`)
if modules, err := self.supportedApis(); err == nil { if modules, err := self.supportedApis(); err == nil {
loadedModules := make([]string, 0) loadedModules := make([]string, 0)
for api, version := range modules { for api, version := range modules {
loadedModules = append(loadedModules, fmt.Sprintf("%s:%s", api, version)) loadedModules = append(loadedModules, fmt.Sprintf("%s:%s", api, version))
} }
sort.Strings(loadedModules) sort.Strings(loadedModules)
fmt.Println("modules:", strings.Join(loadedModules, " "))
self.re.Eval(fmt.Sprintf("var modules = '%s';", strings.Join(loadedModules, " ")))
self.re.Eval(`console.log(" modules: " + modules);`)
} }
} }
@ -291,7 +282,7 @@ func (js *jsre) apiBindings(f xeth.Frontend) error {
utils.Fatalf("Unable to determine supported api's: %v", err) utils.Fatalf("Unable to determine supported api's: %v", err)
} }
jeth := rpc.NewJeth(api.Merge(apiImpl...), js.re, js.client) jeth := rpc.NewJeth(api.Merge(apiImpl...), js.re, js.client, f)
js.re.Set("jeth", struct{}{}) js.re.Set("jeth", struct{}{})
t, _ := js.re.Get("jeth") t, _ := js.re.Get("jeth")
jethObj := t.Object() jethObj := t.Object()
@ -309,12 +300,12 @@ func (js *jsre) apiBindings(f xeth.Frontend) error {
utils.Fatalf("Error loading web3.js: %v", err) utils.Fatalf("Error loading web3.js: %v", err)
} }
_, err = js.re.Eval("var web3 = require('web3');") _, err = js.re.Run("var web3 = require('web3');")
if err != nil { if err != nil {
utils.Fatalf("Error requiring web3: %v", err) utils.Fatalf("Error requiring web3: %v", err)
} }
_, err = js.re.Eval("web3.setProvider(jeth)") _, err = js.re.Run("web3.setProvider(jeth)")
if err != nil { if err != nil {
utils.Fatalf("Error setting web3 provider: %v", err) utils.Fatalf("Error setting web3 provider: %v", err)
} }
@ -333,13 +324,13 @@ func (js *jsre) apiBindings(f xeth.Frontend) error {
} }
} }
_, err = js.re.Eval(shortcuts) _, err = js.re.Run(shortcuts)
if err != nil { if err != nil {
utils.Fatalf("Error setting namespaces: %v", err) utils.Fatalf("Error setting namespaces: %v", err)
} }
js.re.Eval(`var GlobalRegistrar = eth.contract(` + registrar.GlobalRegistrarAbi + `); registrar = GlobalRegistrar.at("` + registrar.GlobalRegistrarAddr + `");`) js.re.Run(`var GlobalRegistrar = eth.contract(` + registrar.GlobalRegistrarAbi + `); registrar = GlobalRegistrar.at("` + registrar.GlobalRegistrarAddr + `");`)
return nil return nil
} }
@ -387,6 +378,11 @@ func (self *jsre) interactive() {
for { for {
line, err := self.Prompt(<-prompt) line, err := self.Prompt(<-prompt)
if err != nil { if err != nil {
if err == liner.ErrPromptAborted { // ctrl-C
self.resetPrompt()
inputln <- ""
continue
}
return return
} }
inputln <- line inputln <- line
@ -458,8 +454,7 @@ func (self *jsre) parseInput(code string) {
fmt.Println("[native] error", r) fmt.Println("[native] error", r)
} }
}() }()
value, err := self.re.Run(code) if err := self.re.EvalAndPrettyPrint(code); err != nil {
if err != nil {
if ottoErr, ok := err.(*otto.Error); ok { if ottoErr, ok := err.(*otto.Error); ok {
fmt.Println(ottoErr.String()) fmt.Println(ottoErr.String())
} else { } else {
@ -467,12 +462,17 @@ func (self *jsre) parseInput(code string) {
} }
return return
} }
self.printValue(value)
} }
var indentCount = 0 var indentCount = 0
var str = "" var str = ""
func (self *jsre) resetPrompt() {
indentCount = 0
str = ""
self.ps1 = "> "
}
func (self *jsre) setIndent() { func (self *jsre) setIndent() {
open := strings.Count(str, "{") open := strings.Count(str, "{")
open += strings.Count(str, "(") open += strings.Count(str, "(")
@ -486,10 +486,3 @@ func (self *jsre) setIndent() {
self.ps1 += " " self.ps1 += " "
} }
} }
func (self *jsre) printValue(v interface{}) {
val, err := self.re.PrettyPrint(v)
if err == nil {
fmt.Printf("%v", val)
}
}

View file

@ -19,7 +19,6 @@ package main
import ( import (
"fmt" "fmt"
"io"
"io/ioutil" "io/ioutil"
_ "net/http/pprof" _ "net/http/pprof"
"os" "os"
@ -38,7 +37,6 @@ import (
"github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/eth" "github.com/ethereum/go-ethereum/eth"
"github.com/ethereum/go-ethereum/ethdb" "github.com/ethereum/go-ethereum/ethdb"
"github.com/ethereum/go-ethereum/fdtrack"
"github.com/ethereum/go-ethereum/logger" "github.com/ethereum/go-ethereum/logger"
"github.com/ethereum/go-ethereum/logger/glog" "github.com/ethereum/go-ethereum/logger/glog"
"github.com/ethereum/go-ethereum/metrics" "github.com/ethereum/go-ethereum/metrics"
@ -46,16 +44,14 @@ import (
"github.com/ethereum/go-ethereum/rlp" "github.com/ethereum/go-ethereum/rlp"
"github.com/ethereum/go-ethereum/rpc/codec" "github.com/ethereum/go-ethereum/rpc/codec"
"github.com/ethereum/go-ethereum/rpc/comms" "github.com/ethereum/go-ethereum/rpc/comms"
"github.com/mattn/go-colorable"
"github.com/mattn/go-isatty"
) )
const ( const (
ClientIdentifier = "Geth" ClientIdentifier = "Geth"
Version = "1.0.1" Version = "1.0.3"
VersionMajor = 1 VersionMajor = 1
VersionMinor = 0 VersionMinor = 0
VersionPatch = 1 VersionPatch = 3
) )
var ( var (
@ -398,14 +394,6 @@ func run(ctx *cli.Context) {
func attach(ctx *cli.Context) { func attach(ctx *cli.Context) {
utils.CheckLegalese(ctx.GlobalString(utils.DataDirFlag.Name)) utils.CheckLegalese(ctx.GlobalString(utils.DataDirFlag.Name))
// Wrap the standard output with a colorified stream (windows)
if isatty.IsTerminal(os.Stdout.Fd()) {
if pr, pw, err := os.Pipe(); err == nil {
go io.Copy(colorable.NewColorableStdout(), pr)
os.Stdout = pw
}
}
var client comms.EthereumClient var client comms.EthereumClient
var err error var err error
if ctx.Args().Present() { if ctx.Args().Present() {
@ -425,7 +413,7 @@ func attach(ctx *cli.Context) {
ctx.GlobalString(utils.JSpathFlag.Name), ctx.GlobalString(utils.JSpathFlag.Name),
client, client,
true, true,
nil) )
if ctx.GlobalString(utils.ExecFlag.Name) != "" { if ctx.GlobalString(utils.ExecFlag.Name) != "" {
repl.batch(ctx.GlobalString(utils.ExecFlag.Name)) repl.batch(ctx.GlobalString(utils.ExecFlag.Name))
@ -438,14 +426,6 @@ func attach(ctx *cli.Context) {
func console(ctx *cli.Context) { func console(ctx *cli.Context) {
utils.CheckLegalese(ctx.GlobalString(utils.DataDirFlag.Name)) utils.CheckLegalese(ctx.GlobalString(utils.DataDirFlag.Name))
// Wrap the standard output with a colorified stream (windows)
if isatty.IsTerminal(os.Stdout.Fd()) {
if pr, pw, err := os.Pipe(); err == nil {
go io.Copy(colorable.NewColorableStdout(), pr)
os.Stdout = pw
}
}
cfg := utils.MakeEthConfig(ClientIdentifier, nodeNameVersion, ctx) cfg := utils.MakeEthConfig(ClientIdentifier, nodeNameVersion, ctx)
ethereum, err := eth.New(cfg) ethereum, err := eth.New(cfg)
if err != nil { if err != nil {
@ -565,9 +545,6 @@ func startEth(ctx *cli.Context, eth *eth.Ethereum) {
// Start Ethereum itself // Start Ethereum itself
utils.StartEthereum(eth) utils.StartEthereum(eth)
// Start logging file descriptor stats.
fdtrack.Start()
am := eth.AccountManager() am := eth.AccountManager()
account := ctx.GlobalString(utils.UnlockedAccountFlag.Name) account := ctx.GlobalString(utils.UnlockedAccountFlag.Name)
accounts := strings.Split(account, " ") accounts := strings.Split(account, " ")

View file

@ -21,30 +21,32 @@ import (
"fmt" "fmt"
"log" "log"
"math/big" "math/big"
"net"
"net/http" "net/http"
"os" "os"
"path/filepath" "path/filepath"
"runtime" "runtime"
"strconv" "strconv"
"github.com/ethereum/go-ethereum/core/vm"
"github.com/ethereum/go-ethereum/metrics"
"github.com/codegangsta/cli" "github.com/codegangsta/cli"
"github.com/ethereum/ethash" "github.com/ethereum/ethash"
"github.com/ethereum/go-ethereum/accounts" "github.com/ethereum/go-ethereum/accounts"
"github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core" "github.com/ethereum/go-ethereum/core"
"github.com/ethereum/go-ethereum/core/vm"
"github.com/ethereum/go-ethereum/crypto" "github.com/ethereum/go-ethereum/crypto"
"github.com/ethereum/go-ethereum/eth" "github.com/ethereum/go-ethereum/eth"
"github.com/ethereum/go-ethereum/ethdb" "github.com/ethereum/go-ethereum/ethdb"
"github.com/ethereum/go-ethereum/event" "github.com/ethereum/go-ethereum/event"
"github.com/ethereum/go-ethereum/logger" "github.com/ethereum/go-ethereum/logger"
"github.com/ethereum/go-ethereum/logger/glog" "github.com/ethereum/go-ethereum/logger/glog"
"github.com/ethereum/go-ethereum/metrics"
"github.com/ethereum/go-ethereum/p2p/nat" "github.com/ethereum/go-ethereum/p2p/nat"
"github.com/ethereum/go-ethereum/rpc/api" "github.com/ethereum/go-ethereum/rpc/api"
"github.com/ethereum/go-ethereum/rpc/codec" "github.com/ethereum/go-ethereum/rpc/codec"
"github.com/ethereum/go-ethereum/rpc/comms" "github.com/ethereum/go-ethereum/rpc/comms"
"github.com/ethereum/go-ethereum/rpc/shared"
"github.com/ethereum/go-ethereum/rpc/useragent"
"github.com/ethereum/go-ethereum/xeth" "github.com/ethereum/go-ethereum/xeth"
) )
@ -452,7 +454,7 @@ func SetupLogger(ctx *cli.Context) {
// SetupVM configured the VM package's global settings // SetupVM configured the VM package's global settings
func SetupVM(ctx *cli.Context) { func SetupVM(ctx *cli.Context) {
vm.DisableJit = !ctx.GlobalBool(VMEnableJitFlag.Name) vm.EnableJit = ctx.GlobalBool(VMEnableJitFlag.Name)
vm.ForceJit = ctx.GlobalBool(VMForceJitFlag.Name) vm.ForceJit = ctx.GlobalBool(VMForceJitFlag.Name)
vm.SetJITCacheSize(ctx.GlobalInt(VMJitCacheFlag.Name)) vm.SetJITCacheSize(ctx.GlobalInt(VMJitCacheFlag.Name))
} }
@ -518,15 +520,20 @@ func StartIPC(eth *eth.Ethereum, ctx *cli.Context) error {
Endpoint: IpcSocketPath(ctx), Endpoint: IpcSocketPath(ctx),
} }
xeth := xeth.New(eth, nil) initializer := func(conn net.Conn) (shared.EthereumApi, error) {
codec := codec.JSON fe := useragent.NewRemoteFrontend(conn, eth.AccountManager())
xeth := xeth.New(eth, fe)
codec := codec.JSON
apis, err := api.ParseApiString(ctx.GlobalString(IPCApiFlag.Name), codec, xeth, eth) apis, err := api.ParseApiString(ctx.GlobalString(IPCApiFlag.Name), codec, xeth, eth)
if err != nil { if err != nil {
return err return nil, err
}
return api.Merge(apis...), nil
} }
return comms.StartIpc(config, codec, api.Merge(apis...)) return comms.StartIpc(config, codec.JSON, initializer)
} }
func StartRPC(eth *eth.Ethereum, ctx *cli.Context) error { func StartRPC(eth *eth.Ethereum, ctx *cli.Context) error {

View file

@ -349,23 +349,11 @@ func (sm *BlockProcessor) GetBlockReceipts(bhash common.Hash) types.Receipts {
// the depricated way by re-processing the block. // the depricated way by re-processing the block.
func (sm *BlockProcessor) GetLogs(block *types.Block) (logs state.Logs, err error) { func (sm *BlockProcessor) GetLogs(block *types.Block) (logs state.Logs, err error) {
receipts := GetBlockReceipts(sm.chainDb, block.Hash()) receipts := GetBlockReceipts(sm.chainDb, block.Hash())
if len(receipts) > 0 { // coalesce logs
// coalesce logs for _, receipt := range receipts {
for _, receipt := range receipts { logs = append(logs, receipt.Logs()...)
logs = append(logs, receipt.Logs()...)
}
return
} }
return logs, nil
// TODO: remove backward compatibility
var (
parent = sm.bc.GetBlock(block.ParentHash())
state = state.New(parent.Root(), sm.chainDb)
)
sm.TransitionState(state, parent, block, true)
return state.Logs(), nil
} }
// See YP section 4.3.4. "Block Header Validity" // See YP section 4.3.4. "Block Header Validity"

View file

@ -20,8 +20,5 @@ import "github.com/ethereum/go-ethereum/common"
// Set of manually tracked bad hashes (usually hard forks) // Set of manually tracked bad hashes (usually hard forks)
var BadHashes = map[common.Hash]bool{ var BadHashes = map[common.Hash]bool{
common.HexToHash("f269c503aed286caaa0d114d6a5320e70abbc2febe37953207e76a2873f2ba79"): true, common.HexToHash("0x05bef30ef572270f654746da22639a7a0c97dd97a7050b9e252391996aaeb689"): true,
common.HexToHash("38f5bbbffd74804820ffa4bab0cd540e9de229725afb98c1a7e57936f4a714bc"): true,
common.HexToHash("7064455b364775a16afbdecd75370e912c6e2879f202eda85b9beae547fff3ac"): true,
common.HexToHash("5b7c80070a6eff35f3eb3181edb023465c776d40af2885571e1bc4689f3a44d8"): true,
} }

View file

@ -647,7 +647,9 @@ func (self *ChainManager) InsertChain(chain types.Blocks) (int, error) {
queue[i] = ChainSplitEvent{block, logs} queue[i] = ChainSplitEvent{block, logs}
queueEvent.splitCount++ queueEvent.splitCount++
} }
PutBlockReceipts(self.chainDb, block, receipts) if err := PutBlockReceipts(self.chainDb, block, receipts); err != nil {
glog.V(logger.Warn).Infoln("error writing block receipts:", err)
}
stats.processed++ stats.processed++
} }

View file

@ -22,6 +22,8 @@ import (
"github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core/state" "github.com/ethereum/go-ethereum/core/state"
"github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/logger"
"github.com/ethereum/go-ethereum/logger/glog"
) )
type AccountChange struct { type AccountChange struct {
@ -111,7 +113,7 @@ done:
// Get the logs of the block // Get the logs of the block
unfiltered, err := self.eth.BlockProcessor().GetLogs(block) unfiltered, err := self.eth.BlockProcessor().GetLogs(block)
if err != nil { if err != nil {
chainlogger.Warnln("err: filter get logs ", err) glog.V(logger.Warn).Infoln("err: filter get logs ", err)
break break
} }

View file

@ -82,8 +82,9 @@ type StateObject struct {
// Mark for deletion // Mark for deletion
// When an object is marked for deletion it will be delete from the trie // When an object is marked for deletion it will be delete from the trie
// during the "update" phase of the state transition // during the "update" phase of the state transition
remove bool remove bool
dirty bool deleted bool
dirty bool
} }
func (self *StateObject) Reset() { func (self *StateObject) Reset() {

View file

@ -203,18 +203,20 @@ func (self *StateDB) UpdateStateObject(stateObject *StateObject) {
// Delete the given state object and delete it from the state trie // Delete the given state object and delete it from the state trie
func (self *StateDB) DeleteStateObject(stateObject *StateObject) { func (self *StateDB) DeleteStateObject(stateObject *StateObject) {
stateObject.deleted = true
addr := stateObject.Address() addr := stateObject.Address()
self.trie.Delete(addr[:]) self.trie.Delete(addr[:])
//delete(self.stateObjects, addr.Str())
} }
// Retrieve a state object given my the address. Nil if not found // Retrieve a state object given my the address. Nil if not found
func (self *StateDB) GetStateObject(addr common.Address) *StateObject { func (self *StateDB) GetStateObject(addr common.Address) (stateObject *StateObject) {
//addr = common.Address(addr) stateObject = self.stateObjects[addr.Str()]
stateObject := self.stateObjects[addr.Str()]
if stateObject != nil { if stateObject != nil {
if stateObject.deleted {
stateObject = nil
}
return stateObject return stateObject
} }
@ -236,7 +238,7 @@ func (self *StateDB) SetStateObject(object *StateObject) {
// Retrieve a state object or create a new state object if nil // Retrieve a state object or create a new state object if nil
func (self *StateDB) GetOrNewStateObject(addr common.Address) *StateObject { func (self *StateDB) GetOrNewStateObject(addr common.Address) *StateObject {
stateObject := self.GetStateObject(addr) stateObject := self.GetStateObject(addr)
if stateObject == nil { if stateObject == nil || stateObject.deleted {
stateObject = self.CreateAccount(addr) stateObject = self.CreateAccount(addr)
} }

View file

@ -341,19 +341,19 @@ func opCoinbase(instr instruction, env Environment, context *Context, memory *Me
} }
func opTimestamp(instr instruction, env Environment, context *Context, memory *Memory, stack *stack) { func opTimestamp(instr instruction, env Environment, context *Context, memory *Memory, stack *stack) {
stack.push(new(big.Int).SetUint64(env.Time())) stack.push(U256(new(big.Int).SetUint64(env.Time())))
} }
func opNumber(instr instruction, env Environment, context *Context, memory *Memory, stack *stack) { func opNumber(instr instruction, env Environment, context *Context, memory *Memory, stack *stack) {
stack.push(U256(env.BlockNumber())) stack.push(U256(new(big.Int).Set(env.BlockNumber())))
} }
func opDifficulty(instr instruction, env Environment, context *Context, memory *Memory, stack *stack) { func opDifficulty(instr instruction, env Environment, context *Context, memory *Memory, stack *stack) {
stack.push(new(big.Int).Set(env.Difficulty())) stack.push(U256(new(big.Int).Set(env.Difficulty())))
} }
func opGasLimit(instr instruction, env Environment, context *Context, memory *Memory, stack *stack) { func opGasLimit(instr instruction, env Environment, context *Context, memory *Memory, stack *stack) {
stack.push(new(big.Int).Set(env.GasLimit())) stack.push(U256(new(big.Int).Set(env.GasLimit())))
} }
func opPop(instr instruction, env Environment, context *Context, memory *Memory, stack *stack) { func opPop(instr instruction, env Environment, context *Context, memory *Memory, stack *stack) {
@ -415,15 +415,12 @@ func opSstore(instr instruction, env Environment, context *Context, memory *Memo
env.State().SetState(context.Address(), loc, common.BigToHash(val)) env.State().SetState(context.Address(), loc, common.BigToHash(val))
} }
func opJump(instr instruction, env Environment, context *Context, memory *Memory, stack *stack) { func opJump(instr instruction, env Environment, context *Context, memory *Memory, stack *stack) {}
} func opJumpi(instr instruction, env Environment, context *Context, memory *Memory, stack *stack) {}
func opJumpi(instr instruction, env Environment, context *Context, memory *Memory, stack *stack) { func opJumpdest(instr instruction, env Environment, context *Context, memory *Memory, stack *stack) {}
}
func opJumpdest(instr instruction, env Environment, context *Context, memory *Memory, stack *stack) {
}
func opPc(instr instruction, env Environment, context *Context, memory *Memory, stack *stack) { func opPc(instr instruction, env Environment, context *Context, memory *Memory, stack *stack) {
stack.push(instr.data) stack.push(new(big.Int).Set(instr.data))
} }
func opMsize(instr instruction, env Environment, context *Context, memory *Memory, stack *stack) { func opMsize(instr instruction, env Environment, context *Context, memory *Memory, stack *stack) {

View file

@ -83,6 +83,7 @@ type Program struct {
code []byte code []byte
} }
// NewProgram returns a new JIT program
func NewProgram(code []byte) *Program { func NewProgram(code []byte) *Program {
program := &Program{ program := &Program{
Id: crypto.Sha3Hash(code), Id: crypto.Sha3Hash(code),
@ -113,6 +114,7 @@ func (p *Program) addInstr(op OpCode, pc uint64, fn instrFn, data *big.Int) {
p.mapping[pc] = len(p.instructions) - 1 p.mapping[pc] = len(p.instructions) - 1
} }
// CompileProgram compiles the given program and return an error when it fails
func CompileProgram(program *Program) (err error) { func CompileProgram(program *Program) (err error) {
if progStatus(atomic.LoadInt32(&program.status)) == progCompile { if progStatus(atomic.LoadInt32(&program.status)) == progCompile {
return nil return nil
@ -272,6 +274,8 @@ func CompileProgram(program *Program) (err error) {
return nil return nil
} }
// RunProgram runs the program given the enviroment and context and returns an
// error if the execution failed (non-consensus)
func RunProgram(program *Program, env Environment, context *Context, input []byte) ([]byte, error) { func RunProgram(program *Program, env Environment, context *Context, input []byte) ([]byte, error) {
return runProgram(program, 0, NewMemory(), newstack(), env, context, input) return runProgram(program, 0, NewMemory(), newstack(), env, context, input)
} }
@ -352,6 +356,8 @@ func runProgram(program *Program, pcstart uint64, mem *Memory, stack *stack, env
pc++ pc++
} }
context.Input = nil
return context.Return(nil), nil return context.Return(nil), nil
} }

View file

@ -46,7 +46,7 @@ func runVmBench(test vmBench, b *testing.B) {
} }
env := NewEnv() env := NewEnv()
DisableJit = test.nojit EnableJit = !test.nojit
ForceJit = test.forcejit ForceJit = test.forcejit
b.ResetTimer() b.ResetTimer()

View file

@ -17,9 +17,9 @@
package vm package vm
var ( var (
DisableJit bool = true // Disable the JIT VM EnableJit bool // Enables the JIT VM
ForceJit bool // Force the JIT, skip byte VM ForceJit bool // Force the JIT, skip byte VM
MaxProgSize int // Max cache size for JIT Programs MaxProgSize int // Max cache size for JIT Programs
) )
const defaultJitMaxCache int = 64 const defaultJitMaxCache int = 64

View file

@ -64,7 +64,7 @@ func (self *Vm) Run(context *Context, input []byte) (ret []byte, err error) {
codehash = crypto.Sha3Hash(context.Code) // codehash is used when doing jump dest caching codehash = crypto.Sha3Hash(context.Code) // codehash is used when doing jump dest caching
program *Program program *Program
) )
if !DisableJit { if EnableJit {
// Fetch program status. // Fetch program status.
// * If ready run using JIT // * If ready run using JIT
// * If unknown, compile in a seperate goroutine // * If unknown, compile in a seperate goroutine

View file

@ -1,66 +0,0 @@
// Copyright 2014 The go-ethereum Authors
// This file is part of the go-ethereum library.
//
// The go-ethereum library is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// The go-ethereum library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
package crypto
import (
"strings"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/crypto/secp256k1"
)
type KeyPair struct {
PrivateKey []byte
PublicKey []byte
address []byte
mnemonic string
// The associated account
// account *StateObject
}
func GenerateNewKeyPair() *KeyPair {
_, prv := secp256k1.GenerateKeyPair()
keyPair, _ := NewKeyPairFromSec(prv) // swallow error, this one cannot err
return keyPair
}
func NewKeyPairFromSec(seckey []byte) (*KeyPair, error) {
pubkey, err := secp256k1.GeneratePubKey(seckey)
if err != nil {
return nil, err
}
return &KeyPair{PrivateKey: seckey, PublicKey: pubkey}, nil
}
func (k *KeyPair) Address() []byte {
if k.address == nil {
k.address = Sha3(k.PublicKey[1:])[12:]
}
return k.address
}
func (k *KeyPair) Mnemonic() string {
if k.mnemonic == "" {
k.mnemonic = strings.Join(MnemonicEncode(common.Bytes2Hex(k.PrivateKey)), " ")
}
return k.mnemonic
}
func (k *KeyPair) AsStrings() (string, string, string, string) {
return k.Mnemonic(), common.Bytes2Hex(k.Address()), common.Bytes2Hex(k.PrivateKey), common.Bytes2Hex(k.PublicKey)
}

View file

@ -1,76 +0,0 @@
// Copyright 2014 The go-ethereum Authors
// This file is part of the go-ethereum library.
//
// The go-ethereum library is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// The go-ethereum library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
package crypto
import (
"fmt"
"strconv"
)
// TODO: See if we can refactor this into a shared util lib if we need it multiple times
func IndexOf(slice []string, value string) int64 {
for p, v := range slice {
if v == value {
return int64(p)
}
}
return -1
}
func MnemonicEncode(message string) []string {
var out []string
n := int64(len(MnemonicWords))
for i := 0; i < len(message); i += (len(message) / 8) {
x := message[i : i+8]
bit, _ := strconv.ParseInt(x, 16, 64)
w1 := (bit % n)
w2 := ((bit / n) + w1) % n
w3 := ((bit / n / n) + w2) % n
out = append(out, MnemonicWords[w1], MnemonicWords[w2], MnemonicWords[w3])
}
return out
}
func MnemonicDecode(wordsar []string) string {
var out string
n := int64(len(MnemonicWords))
for i := 0; i < len(wordsar); i += 3 {
word1 := wordsar[i]
word2 := wordsar[i+1]
word3 := wordsar[i+2]
w1 := IndexOf(MnemonicWords, word1)
w2 := IndexOf(MnemonicWords, word2)
w3 := IndexOf(MnemonicWords, word3)
y := (w2 - w1) % n
z := (w3 - w2) % n
// Golang handles modulo with negative numbers different then most languages
// The modulo can be negative, we don't want that.
if z < 0 {
z += n
}
if y < 0 {
y += n
}
x := w1 + n*(y) + n*n*(z)
out += fmt.Sprintf("%08x", x)
}
return out
}

View file

@ -1,90 +0,0 @@
// Copyright 2014 The go-ethereum Authors
// This file is part of the go-ethereum library.
//
// The go-ethereum library is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// The go-ethereum library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
package crypto
import (
"testing"
)
func TestMnDecode(t *testing.T) {
words := []string{
"ink",
"balance",
"gain",
"fear",
"happen",
"melt",
"mom",
"surface",
"stir",
"bottle",
"unseen",
"expression",
"important",
"curl",
"grant",
"fairy",
"across",
"back",
"figure",
"breast",
"nobody",
"scratch",
"worry",
"yesterday",
}
encode := "c61d43dc5bb7a4e754d111dae8105b6f25356492df5e50ecb33b858d94f8c338"
result := MnemonicDecode(words)
if encode != result {
t.Error("We expected", encode, "got", result, "instead")
}
}
func TestMnEncode(t *testing.T) {
encode := "c61d43dc5bb7a4e754d111dae8105b6f25356492df5e50ecb33b858d94f8c338"
result := []string{
"ink",
"balance",
"gain",
"fear",
"happen",
"melt",
"mom",
"surface",
"stir",
"bottle",
"unseen",
"expression",
"important",
"curl",
"grant",
"fairy",
"across",
"back",
"figure",
"breast",
"nobody",
"scratch",
"worry",
"yesterday",
}
words := MnemonicEncode(encode)
for i, word := range words {
if word != result[i] {
t.Error("Mnenonic does not match:", words, result)
}
}
}

File diff suppressed because it is too large Load diff

View file

@ -61,10 +61,11 @@ var (
defaultBootNodes = []*discover.Node{ defaultBootNodes = []*discover.Node{
// ETH/DEV Go Bootnodes // ETH/DEV Go Bootnodes
discover.MustParseNode("enode://a979fb575495b8d6db44f750317d0f4622bf4c2aa3365d6af7c284339968eef29b69ad0dce72a4d8db5ebb4968de0e3bec910127f134779fbcb0cb6d3331163c@52.16.188.185:30303"), discover.MustParseNode("enode://a979fb575495b8d6db44f750317d0f4622bf4c2aa3365d6af7c284339968eef29b69ad0dce72a4d8db5ebb4968de0e3bec910127f134779fbcb0cb6d3331163c@52.16.188.185:30303"), // IE
discover.MustParseNode("enode://de471bccee3d042261d52e9bff31458daecc406142b401d4cd848f677479f73104b9fdeb090af9583d3391b7f10cb2ba9e26865dd5fca4fcdc0fb1e3b723c786@54.94.239.50:30303"), discover.MustParseNode("enode://de471bccee3d042261d52e9bff31458daecc406142b401d4cd848f677479f73104b9fdeb090af9583d3391b7f10cb2ba9e26865dd5fca4fcdc0fb1e3b723c786@54.94.239.50:30303"), // BR
discover.MustParseNode("enode://1118980bf48b0a3640bdba04e0fe78b1add18e1cd99bf22d53daac1fd9972ad650df52176e7c7d89d1114cfef2bc23a2959aa54998a46afcf7d91809f0855082@52.74.57.123:30303"), // SG
// ETH/DEV cpp-ethereum (poc-9.ethdev.com) // ETH/DEV cpp-ethereum (poc-9.ethdev.com)
discover.MustParseNode("enode://487611428e6c99a11a9795a6abe7b529e81315ca6aad66e2a2fc76e3adf263faba0d35466c2f8f68d561dbefa8878d4df5f1f2ddb1fbeab7f42ffb8cd328bd4a@5.1.83.226:30303"), discover.MustParseNode("enode://979b7fa28feeb35a4741660a16076f1943202cb72b6af70d327f053e248bab9ba81760f39d0701ef1d8f89cc1fbd2cacba0710a12cd5314d5e0c9021aa3637f9@5.1.83.226:30303"),
} }
staticNodes = "static-nodes.json" // Path within <datadir> to search for the static node list staticNodes = "static-nodes.json" // Path within <datadir> to search for the static node list

View file

@ -37,12 +37,11 @@ type blockPriceInfo struct {
type GasPriceOracle struct { type GasPriceOracle struct {
eth *Ethereum eth *Ethereum
chain *core.ChainManager chain *core.ChainManager
pool *core.TxPool
events event.Subscription events event.Subscription
blocks map[uint64]*blockPriceInfo blocks map[uint64]*blockPriceInfo
firstProcessed, lastProcessed uint64 firstProcessed, lastProcessed uint64
lastBaseMutex sync.Mutex lastBaseMutex sync.Mutex
lastBase *big.Int lastBase, minBase *big.Int
} }
func NewGasPriceOracle(eth *Ethereum) (self *GasPriceOracle) { func NewGasPriceOracle(eth *Ethereum) (self *GasPriceOracle) {
@ -50,13 +49,15 @@ func NewGasPriceOracle(eth *Ethereum) (self *GasPriceOracle) {
self.blocks = make(map[uint64]*blockPriceInfo) self.blocks = make(map[uint64]*blockPriceInfo)
self.eth = eth self.eth = eth
self.chain = eth.chainManager self.chain = eth.chainManager
self.pool = eth.txPool
self.events = eth.EventMux().Subscribe( self.events = eth.EventMux().Subscribe(
core.ChainEvent{}, core.ChainEvent{},
core.ChainSplitEvent{}, core.ChainSplitEvent{},
core.TxPreEvent{},
core.TxPostEvent{},
) )
minbase := new(big.Int).Mul(self.eth.GpoMinGasPrice, big.NewInt(100))
minbase = minbase.Div(minbase, big.NewInt(int64(self.eth.GpobaseCorrectionFactor)))
self.minBase = minbase
self.processPastBlocks() self.processPastBlocks()
go self.listenLoop() go self.listenLoop()
return return
@ -93,8 +94,6 @@ func (self *GasPriceOracle) listenLoop() {
self.processBlock(ev.Block) self.processBlock(ev.Block)
case core.ChainSplitEvent: case core.ChainSplitEvent:
self.processBlock(ev.Block) self.processBlock(ev.Block)
case core.TxPreEvent:
case core.TxPostEvent:
} }
} }
self.events.Unsubscribe() self.events.Unsubscribe()
@ -131,6 +130,10 @@ func (self *GasPriceOracle) processBlock(block *types.Block) {
newBase := new(big.Int).Mul(lastBase, big.NewInt(1000000+crand)) newBase := new(big.Int).Mul(lastBase, big.NewInt(1000000+crand))
newBase.Div(newBase, big.NewInt(1000000)) newBase.Div(newBase, big.NewInt(1000000))
if newBase.Cmp(self.minBase) < 0 {
newBase = self.minBase
}
bpi := self.blocks[i] bpi := self.blocks[i]
if bpi == nil { if bpi == nil {
bpi = &blockPriceInfo{} bpi = &blockPriceInfo{}
@ -146,7 +149,7 @@ func (self *GasPriceOracle) processBlock(block *types.Block) {
// returns the lowers possible price with which a tx was or could have been included // returns the lowers possible price with which a tx was or could have been included
func (self *GasPriceOracle) lowestPrice(block *types.Block) *big.Int { func (self *GasPriceOracle) lowestPrice(block *types.Block) *big.Int {
gasUsed := new(big.Int) gasUsed := big.NewInt(0)
receipts := self.eth.BlockProcessor().GetBlockReceipts(block.Hash()) receipts := self.eth.BlockProcessor().GetBlockReceipts(block.Hash())
if len(receipts) > 0 { if len(receipts) > 0 {
@ -158,12 +161,12 @@ func (self *GasPriceOracle) lowestPrice(block *types.Block) *big.Int {
if new(big.Int).Mul(gasUsed, big.NewInt(100)).Cmp(new(big.Int).Mul(block.GasLimit(), if new(big.Int).Mul(gasUsed, big.NewInt(100)).Cmp(new(big.Int).Mul(block.GasLimit(),
big.NewInt(int64(self.eth.GpoFullBlockRatio)))) < 0 { big.NewInt(int64(self.eth.GpoFullBlockRatio)))) < 0 {
// block is not full, could have posted a tx with MinGasPrice // block is not full, could have posted a tx with MinGasPrice
return self.eth.GpoMinGasPrice return big.NewInt(0)
} }
txs := block.Transactions() txs := block.Transactions()
if len(txs) == 0 { if len(txs) == 0 {
return self.eth.GpoMinGasPrice return big.NewInt(0)
} }
// block is full, find smallest gasPrice // block is full, find smallest gasPrice
minPrice := txs[0].GasPrice() minPrice := txs[0].GasPrice()

View file

@ -413,10 +413,12 @@ func (pm *ProtocolManager) handleMsg(p *peer) error {
pm.fetcher.Enqueue(p.id, request.Block) pm.fetcher.Enqueue(p.id, request.Block)
// TODO: Schedule a sync to cover potential gaps (this needs proto update) // Update the peers total difficulty if needed, schedule a download if gapped
if request.TD.Cmp(p.Td()) > 0 { if request.TD.Cmp(p.Td()) > 0 {
p.SetTd(request.TD) p.SetTd(request.TD)
go pm.synchronise(p) if request.TD.Cmp(new(big.Int).Add(pm.chainman.Td(), request.Block.Difficulty())) > 0 {
go pm.synchronise(p)
}
} }
case TxMsg: case TxMsg:

View file

@ -1,112 +0,0 @@
// Copyright 2015 The go-ethereum Authors
// This file is part of the go-ethereum library.
//
// The go-ethereum library is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// The go-ethereum library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
// Package fdtrack logs statistics about open file descriptors.
package fdtrack
import (
"fmt"
"net"
"sort"
"sync"
"time"
"github.com/ethereum/go-ethereum/logger/glog"
)
var (
mutex sync.Mutex
all = make(map[string]int)
)
func Open(desc string) {
mutex.Lock()
all[desc] += 1
mutex.Unlock()
}
func Close(desc string) {
mutex.Lock()
defer mutex.Unlock()
if c, ok := all[desc]; ok {
if c == 1 {
delete(all, desc)
} else {
all[desc]--
}
}
}
func WrapListener(desc string, l net.Listener) net.Listener {
Open(desc)
return &wrappedListener{l, desc}
}
type wrappedListener struct {
net.Listener
desc string
}
func (w *wrappedListener) Accept() (net.Conn, error) {
c, err := w.Listener.Accept()
if err == nil {
c = WrapConn(w.desc, c)
}
return c, err
}
func (w *wrappedListener) Close() error {
err := w.Listener.Close()
if err == nil {
Close(w.desc)
}
return err
}
func WrapConn(desc string, conn net.Conn) net.Conn {
Open(desc)
return &wrappedConn{conn, desc}
}
type wrappedConn struct {
net.Conn
desc string
}
func (w *wrappedConn) Close() error {
err := w.Conn.Close()
if err == nil {
Close(w.desc)
}
return err
}
func Start() {
go func() {
for range time.Tick(15 * time.Second) {
mutex.Lock()
var sum, tracked = 0, []string{}
for what, n := range all {
sum += n
tracked = append(tracked, fmt.Sprintf("%s:%d", what, n))
}
mutex.Unlock()
used, _ := fdusage()
sort.Strings(tracked)
glog.Infof("fd usage %d/%d, tracked %d %v", used, fdlimit(), sum, tracked)
}
}()
}

View file

@ -1,72 +0,0 @@
// Copyright 2015 The go-ethereum Authors
// This file is part of the go-ethereum library.
//
// The go-ethereum library is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// The go-ethereum library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
// +build darwin
package fdtrack
import (
"os"
"syscall"
"unsafe"
)
// #cgo CFLAGS: -lproc
// #include <libproc.h>
// #include <stdlib.h>
import "C"
func fdlimit() int {
var nofile syscall.Rlimit
if err := syscall.Getrlimit(syscall.RLIMIT_NOFILE, &nofile); err != nil {
return 0
}
return int(nofile.Cur)
}
func fdusage() (int, error) {
pid := C.int(os.Getpid())
// Query for a rough estimate on the amout of data that
// proc_pidinfo will return.
rlen, err := C.proc_pidinfo(pid, C.PROC_PIDLISTFDS, 0, nil, 0)
if rlen <= 0 {
return 0, err
}
// Load the list of file descriptors. We don't actually care about
// the content, only about the size. Since the number of fds can
// change while we're reading them, the loop enlarges the buffer
// until proc_pidinfo says the result fitted.
var buf unsafe.Pointer
defer func() {
if buf != nil {
C.free(buf)
}
}()
for buflen := rlen; ; buflen *= 2 {
buf, err = C.reallocf(buf, C.size_t(buflen))
if buf == nil {
return 0, err
}
rlen, err = C.proc_pidinfo(pid, C.PROC_PIDLISTFDS, 0, buf, buflen)
if rlen <= 0 {
return 0, err
} else if rlen == buflen {
continue
}
return int(rlen / C.PROC_PIDLISTFD_SIZE), nil
}
panic("unreachable")
}

View file

@ -1,53 +0,0 @@
// Copyright 2015 The go-ethereum Authors
// This file is part of the go-ethereum library.
//
// The go-ethereum library is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// The go-ethereum library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
// +build linux
package fdtrack
import (
"io"
"os"
"syscall"
)
func fdlimit() int {
var nofile syscall.Rlimit
if err := syscall.Getrlimit(syscall.RLIMIT_NOFILE, &nofile); err != nil {
return 0
}
return int(nofile.Cur)
}
func fdusage() (int, error) {
f, err := os.Open("/proc/self/fd")
if err != nil {
return 0, err
}
defer f.Close()
const batchSize = 100
n := 0
for {
list, err := f.Readdirnames(batchSize)
n += len(list)
if err == io.EOF {
break
} else if err != nil {
return 0, err
}
}
return n, nil
}

View file

@ -65,8 +65,8 @@ func New(assetPath string) *JSRE {
} }
re.loopWg.Add(1) re.loopWg.Add(1)
go re.runEventLoop() go re.runEventLoop()
re.Compile("pp.js", pp_js) // load prettyprint func definition
re.Set("loadScript", re.loadScript) re.Set("loadScript", re.loadScript)
re.Set("inspect", prettyPrintJS)
return re return re
} }
@ -255,35 +255,19 @@ func (self *JSRE) loadScript(call otto.FunctionCall) otto.Value {
return otto.TrueValue() return otto.TrueValue()
} }
// PrettyPrint writes v to standard output. // EvalAndPrettyPrint evaluates code and pretty prints the result to
func (self *JSRE) PrettyPrint(v interface{}) (val otto.Value, err error) { // standard output.
var method otto.Value func (self *JSRE) EvalAndPrettyPrint(code string) (err error) {
self.do(func(vm *otto.Otto) { self.do(func(vm *otto.Otto) {
val, err = vm.ToValue(v) var val otto.Value
val, err = vm.Run(code)
if err != nil { if err != nil {
return return
} }
method, err = vm.Get("prettyPrint") prettyPrint(vm, val)
if err != nil { fmt.Println()
return
}
val, err = method.Call(method, val)
}) })
return val, err return err
}
// Eval evaluates JS function and returns result in a pretty printed string format.
func (self *JSRE) Eval(code string) (s string, err error) {
var val otto.Value
val, err = self.Run(code)
if err != nil {
return
}
val, err = self.PrettyPrint(val)
if err != nil {
return
}
return fmt.Sprintf("%v", val), nil
} }
// Compile compiles and then runs a piece of JS code. // Compile compiles and then runs a piece of JS code.

View file

@ -103,19 +103,14 @@ func TestNatto(t *testing.T) {
func TestBind(t *testing.T) { func TestBind(t *testing.T) {
jsre := New("") jsre := New("")
defer jsre.Stop(false)
jsre.Bind("no", &testNativeObjectBinding{}) jsre.Bind("no", &testNativeObjectBinding{})
val, err := jsre.Run(`no.TestMethod("testMsg")`) _, err := jsre.Run(`no.TestMethod("testMsg")`)
if err != nil { if err != nil {
t.Errorf("expected no error, got %v", err) t.Errorf("expected no error, got %v", err)
} }
pp, err := jsre.PrettyPrint(val)
if err != nil {
t.Errorf("expected no error, got %v", err)
}
t.Logf("no: %v", pp)
jsre.Stop(false)
} }
func TestLoadScript(t *testing.T) { func TestLoadScript(t *testing.T) {

View file

@ -1,137 +0,0 @@
// Copyright 2014 The go-ethereum Authors
// This file is part of the go-ethereum library.
//
// The go-ethereum library is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// The go-ethereum library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
package jsre
const pp_js = `
function pp(object, indent) {
try {
JSON.stringify(object)
} catch(e) {
return pp(e, indent);
}
var str = "";
if(object instanceof Array) {
str += "[";
for(var i = 0, l = object.length; i < l; i++) {
str += pp(object[i], indent);
if(i < l-1) {
str += ", ";
}
}
str += " ]";
} else if (object instanceof Error) {
str += "\033[31m" + "Error:\033[0m " + object.message;
} else if (isBigNumber(object)) {
str += "\033[32m'" + object.toString(10) + "'";
} else if(typeof(object) === "object") {
str += "{\n";
indent += " ";
var fields = getFields(object);
var last = fields[fields.length - 1];
fields.forEach(function (key) {
str += indent + key + ": ";
try {
str += pp(object[key], indent);
} catch (e) {
str += pp(e, indent);
}
if(key !== last) {
str += ",";
}
str += "\n";
});
str += indent.substr(2, indent.length) + "}";
} else if(typeof(object) === "string") {
str += "\033[32m'" + object + "'";
} else if(typeof(object) === "undefined") {
str += "\033[1m\033[30m" + object;
} else if(typeof(object) === "number") {
str += "\033[31m" + object;
} else if(typeof(object) === "function") {
str += "\033[35m" + object.toString().split(" {")[0];
} else {
str += object;
}
str += "\033[0m";
return str;
}
var redundantFields = [
'valueOf',
'toString',
'toLocaleString',
'hasOwnProperty',
'isPrototypeOf',
'propertyIsEnumerable',
'constructor'
];
var getFields = function (object) {
var members = Object.getOwnPropertyNames(object);
if (object.constructor && object.constructor.prototype) {
members = members.concat(Object.getOwnPropertyNames(object.constructor.prototype));
}
var fields = members.filter(function (member) {
return !isMemberFunction(object, member)
}).sort()
var funcs = members.filter(function (member) {
return isMemberFunction(object, member)
}).sort()
var results = fields.concat(funcs);
return results.filter(function (field) {
return redundantFields.indexOf(field) === -1;
});
};
var isMemberFunction = function(object, member) {
try {
return typeof(object[member]) === "function";
} catch(e) {
return false;
}
}
var isBigNumber = function (object) {
var result = typeof BigNumber !== 'undefined' && object instanceof BigNumber;
if (!result) {
if (typeof(object) === "object" && object.constructor != null) {
result = object.constructor.toString().indexOf("function BigNumber(") == 0;
}
}
return result
};
function prettyPrint(/* */) {
var args = arguments;
var ret = "";
for(var i = 0, l = args.length; i < l; i++) {
ret += pp(args[i], "") + "\n";
}
return ret;
}
var print = prettyPrint;
`

231
jsre/pretty.go Normal file
View file

@ -0,0 +1,231 @@
// Copyright 2015 The go-ethereum Authors
// This file is part of the go-ethereum library.
//
// The go-ethereum library is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// The go-ethereum library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
package jsre
import (
"fmt"
"sort"
"strconv"
"strings"
"github.com/fatih/color"
"github.com/robertkrimen/otto"
)
const (
maxPrettyPrintLevel = 3
indentString = " "
)
var (
functionColor = color.New(color.FgMagenta)
specialColor = color.New(color.Bold)
numberColor = color.New(color.FgRed)
stringColor = color.New(color.FgGreen)
)
// these fields are hidden when printing objects.
var boringKeys = map[string]bool{
"valueOf": true,
"toString": true,
"toLocaleString": true,
"hasOwnProperty": true,
"isPrototypeOf": true,
"propertyIsEnumerable": true,
"constructor": true,
}
// prettyPrint writes value to standard output.
func prettyPrint(vm *otto.Otto, value otto.Value) {
ppctx{vm}.printValue(value, 0, false)
}
func prettyPrintJS(call otto.FunctionCall) otto.Value {
for _, v := range call.ArgumentList {
prettyPrint(call.Otto, v)
fmt.Println()
}
return otto.UndefinedValue()
}
type ppctx struct{ vm *otto.Otto }
func (ctx ppctx) indent(level int) string {
return strings.Repeat(indentString, level)
}
func (ctx ppctx) printValue(v otto.Value, level int, inArray bool) {
switch {
case v.IsObject():
ctx.printObject(v.Object(), level, inArray)
case v.IsNull():
specialColor.Print("null")
case v.IsUndefined():
specialColor.Print("undefined")
case v.IsString():
s, _ := v.ToString()
stringColor.Printf("%q", s)
case v.IsBoolean():
b, _ := v.ToBoolean()
specialColor.Printf("%t", b)
case v.IsNaN():
numberColor.Printf("NaN")
case v.IsNumber():
s, _ := v.ToString()
numberColor.Printf("%s", s)
default:
fmt.Printf("<unprintable>")
}
}
func (ctx ppctx) printObject(obj *otto.Object, level int, inArray bool) {
switch obj.Class() {
case "Array":
lv, _ := obj.Get("length")
len, _ := lv.ToInteger()
if len == 0 {
fmt.Printf("[]")
return
}
if level > maxPrettyPrintLevel {
fmt.Print("[...]")
return
}
fmt.Print("[")
for i := int64(0); i < len; i++ {
el, err := obj.Get(strconv.FormatInt(i, 10))
if err == nil {
ctx.printValue(el, level+1, true)
}
if i < len-1 {
fmt.Printf(", ")
}
}
fmt.Print("]")
case "Object":
// Print values from bignumber.js as regular numbers.
if ctx.isBigNumber(obj) {
numberColor.Print(toString(obj))
return
}
// Otherwise, print all fields indented, but stop if we're too deep.
keys := ctx.fields(obj)
if len(keys) == 0 {
fmt.Print("{}")
return
}
if level > maxPrettyPrintLevel {
fmt.Print("{...}")
return
}
fmt.Println("{")
for i, k := range keys {
v, _ := obj.Get(k)
fmt.Printf("%s%s: ", ctx.indent(level+1), k)
ctx.printValue(v, level+1, false)
if i < len(keys)-1 {
fmt.Printf(",")
}
fmt.Println()
}
if inArray {
level--
}
fmt.Printf("%s}", ctx.indent(level))
case "Function":
// Use toString() to display the argument list if possible.
if robj, err := obj.Call("toString"); err != nil {
functionColor.Print("function()")
} else {
desc := strings.Trim(strings.Split(robj.String(), "{")[0], " \t\n")
desc = strings.Replace(desc, " (", "(", 1)
functionColor.Print(desc)
}
case "RegExp":
stringColor.Print(toString(obj))
default:
if v, _ := obj.Get("toString"); v.IsFunction() && level <= maxPrettyPrintLevel {
s, _ := obj.Call("toString")
fmt.Printf("<%s %s>", obj.Class(), s.String())
} else {
fmt.Printf("<%s>", obj.Class())
}
}
}
func (ctx ppctx) fields(obj *otto.Object) []string {
var (
vals, methods []string
seen = make(map[string]bool)
)
add := func(k string) {
if seen[k] || boringKeys[k] {
return
}
seen[k] = true
if v, _ := obj.Get(k); v.IsFunction() {
methods = append(methods, k)
} else {
vals = append(vals, k)
}
}
// add own properties
ctx.doOwnProperties(obj.Value(), add)
// add properties of the constructor
if cp := constructorPrototype(obj); cp != nil {
ctx.doOwnProperties(cp.Value(), add)
}
sort.Strings(vals)
sort.Strings(methods)
return append(vals, methods...)
}
func (ctx ppctx) doOwnProperties(v otto.Value, f func(string)) {
Object, _ := ctx.vm.Object("Object")
rv, _ := Object.Call("getOwnPropertyNames", v)
gv, _ := rv.Export()
for _, v := range gv.([]interface{}) {
f(v.(string))
}
}
func (ctx ppctx) isBigNumber(v *otto.Object) bool {
BigNumber, err := ctx.vm.Run("BigNumber.prototype")
if err != nil {
panic(err)
}
cp := constructorPrototype(v)
return cp != nil && cp.Value() == BigNumber
}
func toString(obj *otto.Object) string {
s, _ := obj.Call("toString")
return s.String()
}
func constructorPrototype(obj *otto.Object) *otto.Object {
if v, _ := obj.Get("constructor"); v.Object() != nil {
if v, _ = v.Object().Get("prototype"); v.Object() != nil {
return v.Object()
}
}
return nil
}

View file

@ -297,14 +297,17 @@ func (self *worker) wait() {
} }
// broadcast before waiting for validation // broadcast before waiting for validation
go func(block *types.Block, logs state.Logs) { go func(block *types.Block, logs state.Logs, receipts []*types.Receipt) {
self.mux.Post(core.NewMinedBlockEvent{block}) self.mux.Post(core.NewMinedBlockEvent{block})
self.mux.Post(core.ChainEvent{block, block.Hash(), logs}) self.mux.Post(core.ChainEvent{block, block.Hash(), logs})
if stat == core.CanonStatTy { if stat == core.CanonStatTy {
self.mux.Post(core.ChainHeadEvent{block}) self.mux.Post(core.ChainHeadEvent{block})
self.mux.Post(logs) self.mux.Post(logs)
} }
}(block, work.state.Logs()) if err := core.PutBlockReceipts(self.chainDb, block, receipts); err != nil {
glog.V(logger.Warn).Infoln("error writing block receipts:", err)
}
}(block, work.state.Logs(), work.receipts)
} }
// check staleness and display confirmation // check staleness and display confirmation

View file

@ -23,7 +23,6 @@ import (
"net" "net"
"time" "time"
"github.com/ethereum/go-ethereum/fdtrack"
"github.com/ethereum/go-ethereum/logger" "github.com/ethereum/go-ethereum/logger"
"github.com/ethereum/go-ethereum/logger/glog" "github.com/ethereum/go-ethereum/logger/glog"
"github.com/ethereum/go-ethereum/p2p/discover" "github.com/ethereum/go-ethereum/p2p/discover"
@ -213,7 +212,6 @@ func (t *dialTask) Do(srv *Server) {
glog.V(logger.Detail).Infof("dial error: %v", err) glog.V(logger.Detail).Infof("dial error: %v", err)
return return
} }
fd = fdtrack.WrapConn("p2p", fd)
mfd := newMeteredConn(fd, false) mfd := newMeteredConn(fd, false)
srv.setupConn(mfd, t.flags, t.dest) srv.setupConn(mfd, t.flags, t.dest)

View file

@ -48,6 +48,10 @@ type Node struct {
// In those tests, the content of sha will not actually correspond // In those tests, the content of sha will not actually correspond
// with ID. // with ID.
sha common.Hash sha common.Hash
// whether this node is currently being pinged in order to replace
// it in a bucket
contested bool
} }
func newNode(id NodeID, ip net.IP, udpPort, tcpPort uint16) *Node { func newNode(id NodeID, ip net.IP, udpPort, tcpPort uint16) *Node {

View file

@ -455,24 +455,31 @@ func (tab *Table) ping(id NodeID, addr *net.UDPAddr) error {
func (tab *Table) add(new *Node) { func (tab *Table) add(new *Node) {
b := tab.buckets[logdist(tab.self.sha, new.sha)] b := tab.buckets[logdist(tab.self.sha, new.sha)]
tab.mutex.Lock() tab.mutex.Lock()
defer tab.mutex.Unlock()
if b.bump(new) { if b.bump(new) {
tab.mutex.Unlock()
return return
} }
var oldest *Node var oldest *Node
if len(b.entries) == bucketSize { if len(b.entries) == bucketSize {
oldest = b.entries[bucketSize-1] oldest = b.entries[bucketSize-1]
if oldest.contested {
// The node is already being replaced, don't attempt
// to replace it.
return
}
oldest.contested = true
// Let go of the mutex so other goroutines can access // Let go of the mutex so other goroutines can access
// the table while we ping the least recently active node. // the table while we ping the least recently active node.
tab.mutex.Unlock() tab.mutex.Unlock()
if err := tab.ping(oldest.ID, oldest.addr()); err == nil { err := tab.ping(oldest.ID, oldest.addr())
tab.mutex.Lock()
oldest.contested = false
if err == nil {
// The node responded, don't replace it. // The node responded, don't replace it.
return return
} }
tab.mutex.Lock()
} }
added := b.replace(new, oldest) added := b.replace(new, oldest)
tab.mutex.Unlock()
if added && tab.nodeAddedHook != nil { if added && tab.nodeAddedHook != nil {
tab.nodeAddedHook(new) tab.nodeAddedHook(new)
} }

View file

@ -26,7 +26,6 @@ import (
"time" "time"
"github.com/ethereum/go-ethereum/crypto" "github.com/ethereum/go-ethereum/crypto"
"github.com/ethereum/go-ethereum/fdtrack"
"github.com/ethereum/go-ethereum/logger" "github.com/ethereum/go-ethereum/logger"
"github.com/ethereum/go-ethereum/logger/glog" "github.com/ethereum/go-ethereum/logger/glog"
"github.com/ethereum/go-ethereum/p2p/nat" "github.com/ethereum/go-ethereum/p2p/nat"
@ -200,7 +199,6 @@ func ListenUDP(priv *ecdsa.PrivateKey, laddr string, natm nat.Interface, nodeDBP
if err != nil { if err != nil {
return nil, err return nil, err
} }
fdtrack.Open("p2p")
conn, err := net.ListenUDP("udp", addr) conn, err := net.ListenUDP("udp", addr)
if err != nil { if err != nil {
return nil, err return nil, err
@ -238,7 +236,6 @@ func newUDP(priv *ecdsa.PrivateKey, c conn, natm nat.Interface, nodeDBPath strin
func (t *udp) close() { func (t *udp) close() {
close(t.closing) close(t.closing)
fdtrack.Close("p2p")
t.conn.Close() t.conn.Close()
// TODO: wait for the loops to end. // TODO: wait for the loops to end.
} }
@ -458,6 +455,10 @@ func encodePacket(priv *ecdsa.PrivateKey, ptype byte, req interface{}) ([]byte,
return packet, nil return packet, nil
} }
type tempError interface {
Temporary() bool
}
// readLoop runs in its own goroutine. it handles incoming UDP packets. // readLoop runs in its own goroutine. it handles incoming UDP packets.
func (t *udp) readLoop() { func (t *udp) readLoop() {
defer t.conn.Close() defer t.conn.Close()
@ -467,7 +468,13 @@ func (t *udp) readLoop() {
buf := make([]byte, 1280) buf := make([]byte, 1280)
for { for {
nbytes, from, err := t.conn.ReadFromUDP(buf) nbytes, from, err := t.conn.ReadFromUDP(buf)
if err != nil { if tempErr, ok := err.(tempError); ok && tempErr.Temporary() {
// Ignore temporary read errors.
glog.V(logger.Debug).Infof("Temporary read error: %v", err)
continue
} else if err != nil {
// Shut down the loop for permament errors.
glog.V(logger.Debug).Infof("Read error: %v", err)
return return
} }
t.handlePacket(from, buf[:nbytes]) t.handlePacket(from, buf[:nbytes])

View file

@ -34,7 +34,7 @@ var (
// meteredConn is a wrapper around a network TCP connection that meters both the // meteredConn is a wrapper around a network TCP connection that meters both the
// inbound and outbound network traffic. // inbound and outbound network traffic.
type meteredConn struct { type meteredConn struct {
net.Conn *net.TCPConn // Network connection to wrap with metering
} }
// newMeteredConn creates a new metered connection, also bumping the ingress or // newMeteredConn creates a new metered connection, also bumping the ingress or
@ -45,13 +45,13 @@ func newMeteredConn(conn net.Conn, ingress bool) net.Conn {
} else { } else {
egressConnectMeter.Mark(1) egressConnectMeter.Mark(1)
} }
return &meteredConn{conn} return &meteredConn{conn.(*net.TCPConn)}
} }
// Read delegates a network read to the underlying connection, bumping the ingress // Read delegates a network read to the underlying connection, bumping the ingress
// traffic meter along the way. // traffic meter along the way.
func (c *meteredConn) Read(b []byte) (n int, err error) { func (c *meteredConn) Read(b []byte) (n int, err error) {
n, err = c.Conn.Read(b) n, err = c.TCPConn.Read(b)
ingressTrafficMeter.Mark(int64(n)) ingressTrafficMeter.Mark(int64(n))
return return
} }
@ -59,7 +59,7 @@ func (c *meteredConn) Read(b []byte) (n int, err error) {
// Write delegates a network write to the underlying connection, bumping the // Write delegates a network write to the underlying connection, bumping the
// egress traffic meter along the way. // egress traffic meter along the way.
func (c *meteredConn) Write(b []byte) (n int, err error) { func (c *meteredConn) Write(b []byte) (n int, err error) {
n, err = c.Conn.Write(b) n, err = c.TCPConn.Write(b)
egressTrafficMeter.Mark(int64(n)) egressTrafficMeter.Mark(int64(n))
return return
} }

View file

@ -25,7 +25,6 @@ import (
"sync" "sync"
"time" "time"
"github.com/ethereum/go-ethereum/fdtrack"
"github.com/ethereum/go-ethereum/logger" "github.com/ethereum/go-ethereum/logger"
"github.com/ethereum/go-ethereum/logger/glog" "github.com/ethereum/go-ethereum/logger/glog"
"github.com/ethereum/go-ethereum/p2p/discover" "github.com/ethereum/go-ethereum/p2p/discover"
@ -373,7 +372,7 @@ func (srv *Server) startListening() error {
} }
laddr := listener.Addr().(*net.TCPAddr) laddr := listener.Addr().(*net.TCPAddr)
srv.ListenAddr = laddr.String() srv.ListenAddr = laddr.String()
srv.listener = fdtrack.WrapListener("p2p", listener) srv.listener = listener
srv.loopWG.Add(1) srv.loopWG.Add(1)
go srv.listenLoop() go srv.listenLoop()
// Map the TCP listening port if NAT is configured. // Map the TCP listening port if NAT is configured.
@ -542,6 +541,10 @@ func (srv *Server) encHandshakeChecks(peers map[discover.NodeID]*Peer, c *conn)
} }
} }
type tempError interface {
Temporary() bool
}
// listenLoop runs in its own goroutine and accepts // listenLoop runs in its own goroutine and accepts
// inbound connections. // inbound connections.
func (srv *Server) listenLoop() { func (srv *Server) listenLoop() {
@ -561,16 +564,31 @@ func (srv *Server) listenLoop() {
} }
for { for {
// Wait for a handshake slot before accepting.
<-slots <-slots
fd, err := srv.listener.Accept()
if err != nil {
return
}
mfd := newMeteredConn(fd, true)
glog.V(logger.Debug).Infof("Accepted conn %v\n", mfd.RemoteAddr()) var (
fd net.Conn
err error
)
for {
fd, err = srv.listener.Accept()
if tempErr, ok := err.(tempError); ok && tempErr.Temporary() {
glog.V(logger.Debug).Infof("Temporary read error: %v", err)
continue
} else if err != nil {
glog.V(logger.Debug).Infof("Read error: %v", err)
return
}
break
}
fd = newMeteredConn(fd, true)
glog.V(logger.Debug).Infof("Accepted conn %v\n", fd.RemoteAddr())
// Spawn the handler. It will give the slot back when the connection
// has been established.
go func() { go func() {
srv.setupConn(mfd, inboundConn, nil) srv.setupConn(fd, inboundConn, nil)
slots <- struct{}{} slots <- struct{}{}
}() }()
} }

View file

@ -37,6 +37,7 @@ import (
"github.com/ethereum/go-ethereum/rpc/codec" "github.com/ethereum/go-ethereum/rpc/codec"
"github.com/ethereum/go-ethereum/rpc/comms" "github.com/ethereum/go-ethereum/rpc/comms"
"github.com/ethereum/go-ethereum/rpc/shared" "github.com/ethereum/go-ethereum/rpc/shared"
"github.com/ethereum/go-ethereum/rpc/useragent"
"github.com/ethereum/go-ethereum/xeth" "github.com/ethereum/go-ethereum/xeth"
) )
@ -71,6 +72,7 @@ var (
"admin_httpGet": (*adminApi).HttpGet, "admin_httpGet": (*adminApi).HttpGet,
"admin_sleepBlocks": (*adminApi).SleepBlocks, "admin_sleepBlocks": (*adminApi).SleepBlocks,
"admin_sleep": (*adminApi).Sleep, "admin_sleep": (*adminApi).Sleep,
"admin_enableUserAgent": (*adminApi).EnableUserAgent,
} }
) )
@ -474,3 +476,10 @@ func (self *adminApi) HttpGet(req *shared.Request) (interface{}, error) {
return string(resp), nil return string(resp), nil
} }
func (self *adminApi) EnableUserAgent(req *shared.Request) (interface{}, error) {
if fe, ok := self.xeth.Frontend().(*useragent.RemoteFrontend); ok {
fe.Enable()
}
return true, nil
}

View file

@ -577,10 +577,10 @@ func (self *ethApi) SubmitWork(req *shared.Request) (interface{}, error) {
func (self *ethApi) SubmitHashrate(req *shared.Request) (interface{}, error) { func (self *ethApi) SubmitHashrate(req *shared.Request) (interface{}, error) {
args := new(SubmitHashRateArgs) args := new(SubmitHashRateArgs)
if err := self.codec.Decode(req.Params, &args); err != nil { if err := self.codec.Decode(req.Params, &args); err != nil {
return nil, shared.NewDecodeParamError(err.Error()) return false, shared.NewDecodeParamError(err.Error())
} }
self.xeth.RemoteMining().SubmitHashrate(common.HexToHash(args.Id), args.Rate) self.xeth.RemoteMining().SubmitHashrate(common.HexToHash(args.Id), args.Rate)
return nil, nil return true, nil
} }
func (self *ethApi) Resend(req *shared.Request) (interface{}, error) { func (self *ethApi) Resend(req *shared.Request) (interface{}, error) {

View file

@ -908,14 +908,14 @@ func (args *SubmitWorkArgs) UnmarshalJSON(b []byte) (err error) {
type tx struct { type tx struct {
tx *types.Transaction tx *types.Transaction
To string To string `json:"to"`
From string From string `json:"from"`
Nonce string Nonce string `json:"nonce"`
Value string Value string `json:"value"`
Data string Data string `json:"data"`
GasLimit string GasLimit string `json:"gas"`
GasPrice string GasPrice string `json:"gasPrice"`
Hash string Hash string `json:"hash"`
} }
func newTx(t *types.Transaction) *tx { func newTx(t *types.Transaction) *tx {

View file

@ -32,7 +32,7 @@ var (
netMapping = map[string]nethandler{ netMapping = map[string]nethandler{
"net_peerCount": (*netApi).PeerCount, "net_peerCount": (*netApi).PeerCount,
"net_listening": (*netApi).IsListening, "net_listening": (*netApi).IsListening,
"net_version": (*netApi).Version, "net_version": (*netApi).Version,
} }
) )
@ -97,4 +97,3 @@ func (self *netApi) IsListening(req *shared.Request) (interface{}, error) {
func (self *netApi) Version(req *shared.Request) (interface{}, error) { func (self *netApi) Version(req *shared.Request) (interface{}, error) {
return self.xeth.NetworkVersion(), nil return self.xeth.NetworkVersion(), nil
} }

View file

@ -17,6 +17,7 @@
package api package api
import ( import (
"fmt"
"time" "time"
"github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common"
@ -125,18 +126,17 @@ func (self *personalApi) UnlockAccount(req *shared.Request) (interface{}, error)
return nil, shared.NewDecodeParamError(err.Error()) return nil, shared.NewDecodeParamError(err.Error())
} }
var err error if len(args.Passphrase) == 0 {
fe := self.xeth.Frontend()
if fe == nil {
return false, fmt.Errorf("No password provided")
}
return fe.UnlockAccount(common.HexToAddress(args.Address).Bytes()), nil
}
am := self.ethereum.AccountManager() am := self.ethereum.AccountManager()
addr := common.HexToAddress(args.Address) addr := common.HexToAddress(args.Address)
if args.Duration == -1 { err := am.TimedUnlock(addr, args.Passphrase, time.Duration(args.Duration)*time.Second)
err = am.Unlock(addr, args.Passphrase) return err == nil, err
} else {
err = am.TimedUnlock(addr, args.Passphrase, time.Duration(args.Duration)*time.Second)
}
if err == nil {
return true, nil
}
return false, err
} }

View file

@ -86,10 +86,10 @@ func (args *UnlockAccountArgs) UnmarshalJSON(b []byte) (err error) {
return shared.NewDecodeParamError(err.Error()) return shared.NewDecodeParamError(err.Error())
} }
args.Duration = -1 args.Duration = 0
if len(obj) < 2 { if len(obj) < 1 {
return shared.NewInsufficientParamsError(len(obj), 2) return shared.NewInsufficientParamsError(len(obj), 1)
} }
if addrstr, ok := obj[0].(string); ok { if addrstr, ok := obj[0].(string); ok {
@ -98,10 +98,18 @@ func (args *UnlockAccountArgs) UnmarshalJSON(b []byte) (err error) {
return shared.NewInvalidTypeError("address", "not a string") return shared.NewInvalidTypeError("address", "not a string")
} }
if passphrasestr, ok := obj[1].(string); ok { if len(obj) >= 2 && obj[1] != nil {
args.Passphrase = passphrasestr if passphrasestr, ok := obj[1].(string); ok {
} else { args.Passphrase = passphrasestr
return shared.NewInvalidTypeError("passphrase", "not a string") } else {
return shared.NewInvalidTypeError("passphrase", "not a string")
}
}
if len(obj) >= 3 && obj[2] != nil {
if duration, ok := obj[2].(float64); ok {
args.Duration = int(duration)
}
} }
return nil return nil

View file

@ -31,6 +31,8 @@ type ApiCoder interface {
ReadRequest() ([]*shared.Request, bool, error) ReadRequest() ([]*shared.Request, bool, error)
// Parse response message from underlying stream // Parse response message from underlying stream
ReadResponse() (interface{}, error) ReadResponse() (interface{}, error)
// Read raw message from underlying stream
Recv() (interface{}, error)
// Encode response to encoded form in underlying stream // Encode response to encoded form in underlying stream
WriteResponse(interface{}) error WriteResponse(interface{}) error
// Decode single message from data // Decode single message from data

View file

@ -21,6 +21,7 @@ import (
"fmt" "fmt"
"net" "net"
"time" "time"
"strings"
"github.com/ethereum/go-ethereum/rpc/shared" "github.com/ethereum/go-ethereum/rpc/shared"
) )
@ -73,35 +74,41 @@ func (self *JsonCodec) ReadRequest() (requests []*shared.Request, isBatch bool,
return nil, false, err return nil, false, err
} }
func (self *JsonCodec) ReadResponse() (interface{}, error) { func (self *JsonCodec) Recv() (interface{}, error) {
bytesInBuffer := 0 var msg json.RawMessage
buf := make([]byte, MAX_RESPONSE_SIZE) err := self.d.Decode(&msg)
if err != nil {
deadline := time.Now().Add(READ_TIMEOUT * time.Second) self.c.Close()
if err := self.c.SetDeadline(deadline); err != nil {
return nil, err return nil, err
} }
for { return msg, err
n, err := self.c.Read(buf[bytesInBuffer:]) }
if err != nil {
return nil, err
}
bytesInBuffer += n
var failure shared.ErrorResponse func (self *JsonCodec) ReadResponse() (interface{}, error) {
if err = json.Unmarshal(buf[:bytesInBuffer], &failure); err == nil && failure.Error != nil { in, err := self.Recv()
if err != nil {
return nil, err
}
if msg, ok := in.(json.RawMessage); ok {
var req *shared.Request
if err = json.Unmarshal(msg, &req); err == nil && strings.HasPrefix(req.Method, "agent_") {
return req, nil
}
var failure *shared.ErrorResponse
if err = json.Unmarshal(msg, &failure); err == nil && failure.Error != nil {
return failure, fmt.Errorf(failure.Error.Message) return failure, fmt.Errorf(failure.Error.Message)
} }
var success shared.SuccessResponse var success *shared.SuccessResponse
if err = json.Unmarshal(buf[:bytesInBuffer], &success); err == nil { if err = json.Unmarshal(msg, &success); err == nil {
return success, nil return success, nil
} }
} }
self.c.Close() return in, err
return nil, fmt.Errorf("Unable to read response")
} }
// Decode data // Decode data

View file

@ -49,7 +49,7 @@ var (
) )
type EthereumClient interface { type EthereumClient interface {
// Close underlaying connection // Close underlying connection
Close() Close()
// Send request // Send request
Send(interface{}) error Send(interface{}) error

View file

@ -29,7 +29,6 @@ import (
"io" "io"
"io/ioutil" "io/ioutil"
"github.com/ethereum/go-ethereum/fdtrack"
"github.com/ethereum/go-ethereum/logger" "github.com/ethereum/go-ethereum/logger"
"github.com/ethereum/go-ethereum/logger/glog" "github.com/ethereum/go-ethereum/logger/glog"
"github.com/ethereum/go-ethereum/rpc/codec" "github.com/ethereum/go-ethereum/rpc/codec"
@ -178,7 +177,6 @@ func listenHTTP(addr string, h http.Handler) (*stopServer, error) {
if err != nil { if err != nil {
return nil, err return nil, err
} }
l = fdtrack.WrapListener("rpc", l)
s := &stopServer{l: l, idle: make(map[net.Conn]struct{})} s := &stopServer{l: l, idle: make(map[net.Conn]struct{})}
s.Server = &http.Server{ s.Server = &http.Server{
Addr: addr, Addr: addr,

View file

@ -60,7 +60,7 @@ func (self *InProcClient) Send(req interface{}) error {
} }
func (self *InProcClient) Recv() (interface{}, error) { func (self *InProcClient) Recv() (interface{}, error) {
return self.lastRes, self.lastErr return *shared.NewRpcResponse(self.lastId, self.lastJsonrpc, self.lastRes, self.lastErr), nil
} }
func (self *InProcClient) SupportedModules() (map[string]string, error) { func (self *InProcClient) SupportedModules() (map[string]string, error) {

View file

@ -46,33 +46,18 @@ func (self *ipcClient) Send(req interface{}) error {
var err error var err error
if r, ok := req.(*shared.Request); ok { if r, ok := req.(*shared.Request); ok {
if err = self.coder.WriteResponse(r); err != nil { if err = self.coder.WriteResponse(r); err != nil {
if _, ok := err.(*net.OpError); ok { // connection lost, retry once if err = self.reconnect(); err == nil {
if err = self.reconnect(); err == nil { err = self.coder.WriteResponse(r)
err = self.coder.WriteResponse(r)
}
} }
} }
return err return err
} }
return err
return fmt.Errorf("Invalid request (%T)", req)
} }
func (self *ipcClient) Recv() (interface{}, error) { func (self *ipcClient) Recv() (interface{}, error) {
res, err := self.coder.ReadResponse() return self.coder.ReadResponse()
if err != nil {
return nil, err
}
if r, ok := res.(shared.SuccessResponse); ok {
return r.Result, nil
}
if r, ok := res.(shared.ErrorResponse); ok {
return r.Error, nil
}
return res, err
} }
func (self *ipcClient) SupportedModules() (map[string]string, error) { func (self *ipcClient) SupportedModules() (map[string]string, error) {
@ -91,7 +76,7 @@ func (self *ipcClient) SupportedModules() (map[string]string, error) {
return nil, err return nil, err
} }
if sucRes, ok := res.(shared.SuccessResponse); ok { if sucRes, ok := res.(*shared.SuccessResponse); ok {
data, _ := json.Marshal(sucRes.Result) data, _ := json.Marshal(sucRes.Result)
modules := make(map[string]string) modules := make(map[string]string)
err = json.Unmarshal(data, &modules) err = json.Unmarshal(data, &modules)
@ -109,8 +94,8 @@ func NewIpcClient(cfg IpcConfig, codec codec.Codec) (*ipcClient, error) {
} }
// Start IPC server // Start IPC server
func StartIpc(cfg IpcConfig, codec codec.Codec, offeredApi shared.EthereumApi) error { func StartIpc(cfg IpcConfig, codec codec.Codec, initializer func(conn net.Conn) (shared.EthereumApi, error)) error {
return startIpc(cfg, codec, offeredApi) return startIpc(cfg, codec, initializer)
} }
func newIpcConnId() int { func newIpcConnId() int {

View file

@ -22,7 +22,6 @@ import (
"net" "net"
"os" "os"
"github.com/ethereum/go-ethereum/fdtrack"
"github.com/ethereum/go-ethereum/logger" "github.com/ethereum/go-ethereum/logger"
"github.com/ethereum/go-ethereum/logger/glog" "github.com/ethereum/go-ethereum/logger/glog"
"github.com/ethereum/go-ethereum/rpc/codec" "github.com/ethereum/go-ethereum/rpc/codec"
@ -48,19 +47,18 @@ func (self *ipcClient) reconnect() error {
return err return err
} }
func startIpc(cfg IpcConfig, codec codec.Codec, api shared.EthereumApi) error { func startIpc(cfg IpcConfig, codec codec.Codec, initializer func(conn net.Conn) (shared.EthereumApi, error)) error {
os.Remove(cfg.Endpoint) // in case it still exists from a previous run os.Remove(cfg.Endpoint) // in case it still exists from a previous run
l, err := net.Listen("unix", cfg.Endpoint) l, err := net.ListenUnix("unix", &net.UnixAddr{Name: cfg.Endpoint, Net: "unix"})
if err != nil { if err != nil {
return err return err
} }
l = fdtrack.WrapListener("ipc", l)
os.Chmod(cfg.Endpoint, 0600) os.Chmod(cfg.Endpoint, 0600)
go func() { go func() {
for { for {
conn, err := l.Accept() conn, err := l.AcceptUnix()
if err != nil { if err != nil {
glog.V(logger.Error).Infof("Error accepting ipc connection - %v\n", err) glog.V(logger.Error).Infof("Error accepting ipc connection - %v\n", err)
continue continue
@ -69,6 +67,13 @@ func startIpc(cfg IpcConfig, codec codec.Codec, api shared.EthereumApi) error {
id := newIpcConnId() id := newIpcConnId()
glog.V(logger.Debug).Infof("New IPC connection with id %06d started\n", id) glog.V(logger.Debug).Infof("New IPC connection with id %06d started\n", id)
api, err := initializer(conn)
if err != nil {
glog.V(logger.Error).Infof("Unable to initialize IPC connection - %v\n", err)
conn.Close()
continue
}
go handle(id, conn, api, codec) go handle(id, conn, api, codec)
} }

View file

@ -667,7 +667,7 @@ func (self *ipcClient) reconnect() error {
return err return err
} }
func startIpc(cfg IpcConfig, codec codec.Codec, api shared.EthereumApi) error { func startIpc(cfg IpcConfig, codec codec.Codec, initializer func(conn net.Conn) (shared.EthereumApi, error)) error {
os.Remove(cfg.Endpoint) // in case it still exists from a previous run os.Remove(cfg.Endpoint) // in case it still exists from a previous run
l, err := Listen(cfg.Endpoint) l, err := Listen(cfg.Endpoint)
@ -687,6 +687,13 @@ func startIpc(cfg IpcConfig, codec codec.Codec, api shared.EthereumApi) error {
id := newIpcConnId() id := newIpcConnId()
glog.V(logger.Debug).Infof("New IPC connection with id %06d started\n", id) glog.V(logger.Debug).Infof("New IPC connection with id %06d started\n", id)
api, err := initializer(conn)
if err != nil {
glog.V(logger.Error).Infof("Unable to initialize IPC connection - %v\n", err)
conn.Close()
continue
}
go handle(id, conn, api, codec) go handle(id, conn, api, codec)
} }

View file

@ -18,12 +18,17 @@ package rpc
import ( import (
"encoding/json" "encoding/json"
"fmt" "fmt"
"github.com/ethereum/go-ethereum/cmd/utils"
"github.com/ethereum/go-ethereum/jsre" "github.com/ethereum/go-ethereum/jsre"
"github.com/ethereum/go-ethereum/logger"
"github.com/ethereum/go-ethereum/logger/glog"
"github.com/ethereum/go-ethereum/rpc/comms" "github.com/ethereum/go-ethereum/rpc/comms"
"github.com/ethereum/go-ethereum/rpc/shared" "github.com/ethereum/go-ethereum/rpc/shared"
"github.com/ethereum/go-ethereum/rpc/useragent"
"github.com/ethereum/go-ethereum/xeth"
"github.com/robertkrimen/otto" "github.com/robertkrimen/otto"
) )
@ -31,10 +36,21 @@ type Jeth struct {
ethApi shared.EthereumApi ethApi shared.EthereumApi
re *jsre.JSRE re *jsre.JSRE
client comms.EthereumClient client comms.EthereumClient
fe xeth.Frontend
} }
func NewJeth(ethApi shared.EthereumApi, re *jsre.JSRE, client comms.EthereumClient) *Jeth { func NewJeth(ethApi shared.EthereumApi, re *jsre.JSRE, client comms.EthereumClient, fe xeth.Frontend) *Jeth {
return &Jeth{ethApi, re, client} // enable the jeth as the user agent
req := shared.Request{
Id: 0,
Method: useragent.EnableUserAgentMethod,
Jsonrpc: shared.JsonRpcVersion,
Params: []byte("[]"),
}
client.Send(&req)
client.Recv()
return &Jeth{ethApi, re, client, fe}
} }
func (self *Jeth) err(call otto.FunctionCall, code int, msg string, id interface{}) (response otto.Value) { func (self *Jeth) err(call otto.FunctionCall, code int, msg string, id interface{}) (response otto.Value) {
@ -72,16 +88,34 @@ func (self *Jeth) Send(call otto.FunctionCall) (response otto.Value) {
if err != nil { if err != nil {
return self.err(call, -32603, err.Error(), req.Id) return self.err(call, -32603, err.Error(), req.Id)
} }
respif, err = self.client.Recv()
recv:
respif, err = self.client.Recv()
if err != nil { if err != nil {
return self.err(call, -32603, err.Error(), req.Id) return self.err(call, -32603, err.Error(), req.Id)
} }
agentreq, isRequest := respif.(*shared.Request)
if isRequest {
self.handleRequest(agentreq)
goto recv // receive response after agent interaction
}
sucres, isSuccessResponse := respif.(*shared.SuccessResponse)
errres, isErrorResponse := respif.(*shared.ErrorResponse)
if !isSuccessResponse && !isErrorResponse {
return self.err(call, -32603, fmt.Sprintf("Invalid response type (%T)", respif), req.Id)
}
call.Otto.Set("ret_jsonrpc", shared.JsonRpcVersion) call.Otto.Set("ret_jsonrpc", shared.JsonRpcVersion)
call.Otto.Set("ret_id", req.Id) call.Otto.Set("ret_id", req.Id)
res, _ := json.Marshal(respif) var res []byte
if isSuccessResponse {
res, err = json.Marshal(sucres.Result)
} else if isErrorResponse {
res, err = json.Marshal(errres.Error)
}
call.Otto.Set("ret_result", string(res)) call.Otto.Set("ret_result", string(res))
call.Otto.Set("response_idx", i) call.Otto.Set("response_idx", i)
@ -105,3 +139,48 @@ func (self *Jeth) Send(call otto.FunctionCall) (response otto.Value) {
return return
} }
// handleRequest will handle user agent requests by interacting with the user and sending
// the user response back to the geth service
func (self *Jeth) handleRequest(req *shared.Request) bool {
var err error
var args []interface{}
if err = json.Unmarshal(req.Params, &args); err != nil {
glog.V(logger.Info).Infof("Unable to parse agent request - %v\n", err)
return false
}
switch req.Method {
case useragent.AskPasswordMethod:
return self.askPassword(req.Id, req.Jsonrpc, args)
case useragent.ConfirmTransactionMethod:
return self.confirmTransaction(req.Id, req.Jsonrpc, args)
}
return false
}
// askPassword will ask the user to supply the password for a given account
func (self *Jeth) askPassword(id interface{}, jsonrpc string, args []interface{}) bool {
var err error
var passwd string
if len(args) >= 1 {
if account, ok := args[0].(string); ok {
fmt.Printf("Unlock account %s\n", account)
passwd, err = utils.PromptPassword("Passphrase: ", true)
} else {
return false
}
}
if err = self.client.Send(shared.NewRpcResponse(id, jsonrpc, passwd, err)); err != nil {
glog.V(logger.Info).Infof("Unable to send user agent ask password response - %v\n", err)
}
return err == nil
}
func (self *Jeth) confirmTransaction(id interface{}, jsonrpc string, args []interface{}) bool {
// Accept all tx which are send from this console
return self.client.Send(shared.NewRpcResponse(id, jsonrpc, true, nil)) == nil
}

View file

@ -14,16 +14,11 @@
// You should have received a copy of the GNU Lesser General Public License // You should have received a copy of the GNU Lesser General Public License
// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>. // along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
// +build !linux,!darwin // package user agent provides frontends and agents which can interact with the user
package useragent
package fdtrack var (
AskPasswordMethod = "agent_askPassword"
import "errors" ConfirmTransactionMethod = "agent_confirmTransaction"
EnableUserAgentMethod = "admin_enableUserAgent"
func fdlimit() int { )
return 0
}
func fdusage() (int, error) {
return 0, errors.New("not implemented")
}

View file

@ -0,0 +1,141 @@
// Copyright 2015 The go-ethereum Authors
// This file is part of the go-ethereum library.
//
// The go-ethereum library is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// The go-ethereum library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
package useragent
import (
"encoding/json"
"fmt"
"net"
"github.com/ethereum/go-ethereum/accounts"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/logger"
"github.com/ethereum/go-ethereum/logger/glog"
"github.com/ethereum/go-ethereum/rpc/shared"
)
// remoteFrontend implements xeth.Frontend and will communicate with an external
// user agent over a connection
type RemoteFrontend struct {
enabled bool
mgr *accounts.Manager
d *json.Decoder
e *json.Encoder
n int
}
// NewRemoteFrontend creates a new frontend which will interact with an user agent
// over the given connection
func NewRemoteFrontend(conn net.Conn, mgr *accounts.Manager) *RemoteFrontend {
return &RemoteFrontend{false, mgr, json.NewDecoder(conn), json.NewEncoder(conn), 0}
}
// Enable will enable user interaction
func (fe *RemoteFrontend) Enable() {
fe.enabled = true
}
// UnlockAccount asks the user agent for the user password and tries to unlock the account.
// It will try 3 attempts before giving up.
func (fe *RemoteFrontend) UnlockAccount(address []byte) bool {
if !fe.enabled {
return false
}
err := fe.send(AskPasswordMethod, common.Bytes2Hex(address))
if err != nil {
glog.V(logger.Error).Infof("Unable to send password request to agent - %v\n", err)
return false
}
passwdRes, err := fe.recv()
if err != nil {
glog.V(logger.Error).Infof("Unable to recv password response from agent - %v\n", err)
return false
}
if passwd, ok := passwdRes.Result.(string); ok {
err = fe.mgr.Unlock(common.BytesToAddress(address), passwd)
}
if err == nil {
return true
}
glog.V(logger.Debug).Infoln("3 invalid account unlock attempts")
return false
}
// ConfirmTransaction asks the user for approval
func (fe *RemoteFrontend) ConfirmTransaction(tx string) bool {
if !fe.enabled {
return true // backwards compatibility
}
err := fe.send(ConfirmTransactionMethod, tx)
if err != nil {
glog.V(logger.Error).Infof("Unable to send tx confirmation request to agent - %v\n", err)
return false
}
confirmResponse, err := fe.recv()
if err != nil {
glog.V(logger.Error).Infof("Unable to recv tx confirmation response from agent - %v\n", err)
return false
}
if confirmed, ok := confirmResponse.Result.(bool); ok {
return confirmed
}
return false
}
// send request to the agent
func (fe *RemoteFrontend) send(method string, params ...interface{}) error {
fe.n += 1
p, err := json.Marshal(params)
if err != nil {
glog.V(logger.Info).Infof("Unable to send agent request %v\n", err)
return err
}
req := shared.Request{
Method: method,
Jsonrpc: shared.JsonRpcVersion,
Id: fe.n,
Params: p,
}
return fe.e.Encode(&req)
}
// recv user response from agent
func (fe *RemoteFrontend) recv() (*shared.SuccessResponse, error) {
var res json.RawMessage
if err := fe.d.Decode(&res); err != nil {
return nil, err
}
var response shared.SuccessResponse
if err := json.Unmarshal(res, &response); err == nil {
return &response, nil
}
return nil, fmt.Errorf("Invalid user agent response")
}

View file

@ -53,7 +53,7 @@ func (self *Xeth) Call(method string, params []interface{}) (map[string]interfac
Method: method, Method: method,
Params: data, Params: data,
} }
// Send the request over and process the response // Send the request over and retrieve the response
if err := self.client.Send(req); err != nil { if err := self.client.Send(req); err != nil {
return nil, err return nil, err
} }
@ -61,9 +61,17 @@ func (self *Xeth) Call(method string, params []interface{}) (map[string]interfac
if err != nil { if err != nil {
return nil, err return nil, err
} }
value, ok := res.(map[string]interface{}) // Ensure the response is valid, and extract the results
if !ok { success, isSuccessResponse := res.(*shared.SuccessResponse)
return nil, fmt.Errorf("Invalid response type: have %v, want %v", reflect.TypeOf(res), reflect.TypeOf(make(map[string]interface{}))) failure, isFailureResponse := res.(*shared.ErrorResponse)
switch {
case isFailureResponse:
return nil, fmt.Errorf("Method invocation failed: %v", failure.Error)
case isSuccessResponse:
return success.Result.(map[string]interface{}), nil
default:
return nil, fmt.Errorf("Invalid response type: %v", reflect.TypeOf(res))
} }
return value, nil
} }

View file

@ -150,7 +150,7 @@ func runBlockTests(bt map[string]*BlockTest, skipTests []string) error {
// test the block // test the block
if err := runBlockTest(test); err != nil { if err := runBlockTest(test); err != nil {
return err return fmt.Errorf("%s: %v", name, err)
} }
glog.Infoln("Block test passed: ", name) glog.Infoln("Block test passed: ", name)

File diff suppressed because it is too large Load diff

View file

@ -27,14 +27,13 @@ import (
func init() { func init() {
if os.Getenv("JITVM") == "true" { if os.Getenv("JITVM") == "true" {
vm.ForceJit = true vm.ForceJit = true
} else { vm.EnableJit = true
vm.DisableJit = true
} }
} }
func BenchmarkStateCall1024(b *testing.B) { func BenchmarkStateCall1024(b *testing.B) {
fn := filepath.Join(stateTestDir, "stCallCreateCallCodeTest.json") fn := filepath.Join(stateTestDir, "stCallCreateCallCodeTest.json")
if err := BenchVmTest(fn, bconf{"Call1024BalanceTooLow", true, false}, b); err != nil { if err := BenchVmTest(fn, bconf{"Call1024BalanceTooLow", true, os.Getenv("JITVM") == "true"}, b); err != nil {
b.Error(err) b.Error(err)
} }
} }

View file

@ -71,8 +71,8 @@ func BenchStateTest(p string, conf bconf, b *testing.B) error {
return fmt.Errorf("test not found: %s", conf.name) return fmt.Errorf("test not found: %s", conf.name)
} }
pNoJit := vm.DisableJit pJit := vm.EnableJit
vm.DisableJit = conf.nojit vm.EnableJit = conf.jit
pForceJit := vm.ForceJit pForceJit := vm.ForceJit
vm.ForceJit = conf.precomp vm.ForceJit = conf.precomp
@ -94,7 +94,7 @@ func BenchStateTest(p string, conf bconf, b *testing.B) error {
benchStateTest(test, env, b) benchStateTest(test, env, b)
} }
vm.DisableJit = pNoJit vm.EnableJit = pJit
vm.ForceJit = pForceJit vm.ForceJit = pForceJit
return nil return nil

View file

@ -17,20 +17,21 @@
package tests package tests
import ( import (
"os"
"path/filepath" "path/filepath"
"testing" "testing"
) )
func BenchmarkVmAckermann32Tests(b *testing.B) { func BenchmarkVmAckermann32Tests(b *testing.B) {
fn := filepath.Join(vmTestDir, "vmPerformanceTest.json") fn := filepath.Join(vmTestDir, "vmPerformanceTest.json")
if err := BenchVmTest(fn, bconf{"ackermann32", true, false}, b); err != nil { if err := BenchVmTest(fn, bconf{"ackermann32", true, os.Getenv("JITVM") == "true"}, b); err != nil {
b.Error(err) b.Error(err)
} }
} }
func BenchmarkVmFibonacci16Tests(b *testing.B) { func BenchmarkVmFibonacci16Tests(b *testing.B) {
fn := filepath.Join(vmTestDir, "vmPerformanceTest.json") fn := filepath.Join(vmTestDir, "vmPerformanceTest.json")
if err := BenchVmTest(fn, bconf{"fibonacci16", true, false}, b); err != nil { if err := BenchVmTest(fn, bconf{"fibonacci16", true, os.Getenv("JITVM") == "true"}, b); err != nil {
b.Error(err) b.Error(err)
} }
} }

View file

@ -52,7 +52,7 @@ func RunVmTestWithReader(r io.Reader, skipTests []string) error {
type bconf struct { type bconf struct {
name string name string
precomp bool precomp bool
nojit bool jit bool
} }
func BenchVmTest(p string, conf bconf, b *testing.B) error { func BenchVmTest(p string, conf bconf, b *testing.B) error {
@ -67,8 +67,8 @@ func BenchVmTest(p string, conf bconf, b *testing.B) error {
return fmt.Errorf("test not found: %s", conf.name) return fmt.Errorf("test not found: %s", conf.name)
} }
pNoJit := vm.DisableJit pJit := vm.EnableJit
vm.DisableJit = conf.nojit vm.EnableJit = conf.jit
pForceJit := vm.ForceJit pForceJit := vm.ForceJit
vm.ForceJit = conf.precomp vm.ForceJit = conf.precomp
@ -99,7 +99,7 @@ func BenchVmTest(p string, conf bconf, b *testing.B) error {
benchVmTest(test, env, b) benchVmTest(test, env, b)
} }
vm.DisableJit = pNoJit vm.EnableJit = pJit
vm.ForceJit = pForceJit vm.ForceJit = pForceJit
return nil return nil

View file

@ -89,8 +89,7 @@ type XEth struct {
messagesMu sync.RWMutex messagesMu sync.RWMutex
messages map[int]*whisperFilter messages map[int]*whisperFilter
// regmut sync.Mutex transactMu sync.Mutex
// register map[string][]*interface{} // TODO improve return type
agent *miner.RemoteAgent agent *miner.RemoteAgent
@ -823,18 +822,22 @@ func (self *XEth) Call(fromStr, toStr, valueStr, gasStr, gasPriceStr, dataStr st
} }
from.SetBalance(common.MaxBig) from.SetBalance(common.MaxBig)
from.SetGasLimit(self.backend.ChainManager().GasLimit()) from.SetGasLimit(common.MaxBig)
msg := callmsg{ msg := callmsg{
from: from, from: from,
to: common.HexToAddress(toStr),
gas: common.Big(gasStr), gas: common.Big(gasStr),
gasPrice: common.Big(gasPriceStr), gasPrice: common.Big(gasPriceStr),
value: common.Big(valueStr), value: common.Big(valueStr),
data: common.FromHex(dataStr), data: common.FromHex(dataStr),
} }
if len(toStr) > 0 {
addr := common.HexToAddress(toStr)
msg.to = &addr
}
if msg.gas.Cmp(big.NewInt(0)) == 0 { if msg.gas.Cmp(big.NewInt(0)) == 0 {
msg.gas = DefaultGas() msg.gas = big.NewInt(50000000)
} }
if msg.gasPrice.Cmp(big.NewInt(0)) == 0 { if msg.gasPrice.Cmp(big.NewInt(0)) == 0 {
@ -885,6 +888,10 @@ func isAddress(addr string) bool {
return addrReg.MatchString(addr) return addrReg.MatchString(addr)
} }
func (self *XEth) Frontend() Frontend {
return self.frontend
}
func (self *XEth) Transact(fromStr, toStr, nonceStr, valueStr, gasStr, gasPriceStr, codeStr string) (string, error) { func (self *XEth) Transact(fromStr, toStr, nonceStr, valueStr, gasStr, gasPriceStr, codeStr string) (string, error) {
// this minimalistic recoding is enough (works for natspec.js) // this minimalistic recoding is enough (works for natspec.js)
@ -948,8 +955,9 @@ func (self *XEth) Transact(fromStr, toStr, nonceStr, valueStr, gasStr, gasPriceS
} }
*/ */
// TODO: align default values to have the same type, e.g. not depend on self.transactMu.Lock()
// common.Value conversions later on defer self.transactMu.Unlock()
var nonce uint64 var nonce uint64
if len(nonceStr) != 0 { if len(nonceStr) != 0 {
nonce = common.Big(nonceStr).Uint64() nonce = common.Big(nonceStr).Uint64()
@ -994,7 +1002,7 @@ func (self *XEth) sign(tx *types.Transaction, from common.Address, didUnlock boo
// callmsg is the message type used for call transations. // callmsg is the message type used for call transations.
type callmsg struct { type callmsg struct {
from *state.StateObject from *state.StateObject
to common.Address to *common.Address
gas, gasPrice *big.Int gas, gasPrice *big.Int
value *big.Int value *big.Int
data []byte data []byte
@ -1003,7 +1011,7 @@ type callmsg struct {
// accessor boilerplate to implement core.Message // accessor boilerplate to implement core.Message
func (m callmsg) From() (common.Address, error) { return m.from.Address(), nil } func (m callmsg) From() (common.Address, error) { return m.from.Address(), nil }
func (m callmsg) Nonce() uint64 { return m.from.Nonce() } func (m callmsg) Nonce() uint64 { return m.from.Nonce() }
func (m callmsg) To() *common.Address { return &m.to } func (m callmsg) To() *common.Address { return m.to }
func (m callmsg) GasPrice() *big.Int { return m.gasPrice } func (m callmsg) GasPrice() *big.Int { return m.gasPrice }
func (m callmsg) Gas() *big.Int { return m.gas } func (m callmsg) Gas() *big.Int { return m.gas }
func (m callmsg) Value() *big.Int { return m.value } func (m callmsg) Value() *big.Int { return m.value }