aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Godeps/Godeps.json18
-rw-r--r--Godeps/_workspace/src/github.com/fatih/color/.travis.yml3
-rw-r--r--Godeps/_workspace/src/github.com/fatih/color/LICENSE.md20
-rw-r--r--Godeps/_workspace/src/github.com/fatih/color/README.md151
-rw-r--r--Godeps/_workspace/src/github.com/fatih/color/color.go353
-rw-r--r--Godeps/_workspace/src/github.com/fatih/color/color_test.go176
-rw-r--r--Godeps/_workspace/src/github.com/fatih/color/doc.go114
-rw-r--r--Godeps/_workspace/src/github.com/mattn/go-colorable/README.md42
-rw-r--r--Godeps/_workspace/src/github.com/mattn/go-colorable/colorable_others.go16
-rw-r--r--Godeps/_workspace/src/github.com/mattn/go-colorable/colorable_windows.go594
-rw-r--r--Godeps/_workspace/src/github.com/shiena/ansicolor/.gitignore27
-rw-r--r--Godeps/_workspace/src/github.com/shiena/ansicolor/LICENSE21
-rw-r--r--Godeps/_workspace/src/github.com/shiena/ansicolor/README.md100
-rw-r--r--Godeps/_workspace/src/github.com/shiena/ansicolor/ansicolor.go20
-rw-r--r--Godeps/_workspace/src/github.com/shiena/ansicolor/ansicolor/main.go27
-rw-r--r--Godeps/_workspace/src/github.com/shiena/ansicolor/ansicolor_ansi.go17
-rw-r--r--Godeps/_workspace/src/github.com/shiena/ansicolor/ansicolor_test.go25
-rw-r--r--Godeps/_workspace/src/github.com/shiena/ansicolor/ansicolor_windows.go351
-rw-r--r--Godeps/_workspace/src/github.com/shiena/ansicolor/ansicolor_windows_test.go236
-rw-r--r--Godeps/_workspace/src/github.com/shiena/ansicolor/example_test.go24
-rw-r--r--Godeps/_workspace/src/github.com/shiena/ansicolor/export_test.go19
-rw-r--r--cmd/evm/main.go2
-rw-r--r--cmd/geth/js.go67
-rw-r--r--cmd/geth/main.go21
-rw-r--r--cmd/utils/flags.go27
-rw-r--r--core/block_processor.go12
-rw-r--r--core/vm/instructions.go19
-rw-r--r--core/vm/jit.go6
-rw-r--r--core/vm/jit_test.go2
-rw-r--r--core/vm/settings.go6
-rw-r--r--core/vm/vm.go2
-rw-r--r--eth/backend.go41
-rw-r--r--jsre/jsre.go34
-rw-r--r--jsre/jsre_test.go11
-rw-r--r--jsre/pp_js.go137
-rw-r--r--jsre/pretty.go231
-rw-r--r--p2p/rlpx.go16
-rw-r--r--rlp/decode.go29
-rw-r--r--rlp/decode_test.go9
-rw-r--r--rlp/encode.go11
-rw-r--r--rlp/encode_test.go4
-rw-r--r--rpc/api/admin.go9
-rw-r--r--rpc/api/net.go3
-rw-r--r--rpc/api/personal.go22
-rw-r--r--rpc/api/personal_args.go22
-rw-r--r--rpc/api/shh_js.go (renamed from rpc/api/ssh_js.go)0
-rw-r--r--rpc/codec/codec.go2
-rw-r--r--rpc/codec/json.go39
-rw-r--r--rpc/comms/comms.go2
-rw-r--r--rpc/comms/inproc.go2
-rw-r--r--rpc/comms/ipc.go35
-rw-r--r--rpc/comms/ipc_unix.go9
-rw-r--r--rpc/comms/ipc_windows.go9
-rw-r--r--rpc/jeth.go89
-rw-r--r--rpc/useragent/agent.go24
-rw-r--r--rpc/useragent/remote_frontend.go141
-rw-r--r--tests/state_test.go5
-rw-r--r--tests/state_test_util.go6
-rw-r--r--tests/vm_test.go5
-rw-r--r--tests/vm_test_util.go8
-rw-r--r--trie/cache.go4
-rw-r--r--trie/trie.go2
-rw-r--r--xeth/xeth.go26
63 files changed, 2461 insertions, 1044 deletions
diff --git a/Godeps/Godeps.json b/Godeps/Godeps.json
index 199914baa..d5c41227d 100644
--- a/Godeps/Godeps.json
+++ b/Godeps/Godeps.json
@@ -25,13 +25,17 @@
"Rev": "8f6ccaaef9b418553807a73a95cb5f49cd3ea39f"
},
{
+ "ImportPath": "github.com/fatih/color",
+ "Comment": "v0.1-5-gf773d4c",
+ "Rev": "f773d4c806cc8e4a5749d6a35e2a4bbcd71443d6"
+ },
+ {
"ImportPath": "github.com/gizak/termui",
"Rev": "bab8dce01c193d82bc04888a0a9a7814d505f532"
},
{
- "ImportPath": "github.com/howeyc/fsnotify",
- "Comment": "v0.9.0-11-g6b1ef89",
- "Rev": "6b1ef893dc11e0447abda6da20a5203481878dda"
+ "ImportPath": "github.com/hashicorp/golang-lru",
+ "Rev": "7f9ef20a0256f494e24126014135cf893ab71e9e"
},
{
"ImportPath": "github.com/huin/goupnp",
@@ -46,10 +50,6 @@
"Rev": "ccfcd0245381f0c94c68f50626665eed3c6b726a"
},
{
- "ImportPath": "github.com/mattn/go-colorable",
- "Rev": "043ae16291351db8465272edf465c9f388161627"
- },
- {
"ImportPath": "github.com/mattn/go-isatty",
"Rev": "fdbe02a1b44e75977b2690062b83cf507d70c013"
},
@@ -79,6 +79,10 @@
"Rev": "6e0c3cb65fc0fdb064c743d176a620e3ca446dfb"
},
{
+ "ImportPath": "github.com/shiena/ansicolor",
+ "Rev": "a5e2b567a4dd6cc74545b8a4f27c9d63b9e7735b"
+ },
+ {
"ImportPath": "github.com/syndtr/goleveldb/leveldb",
"Rev": "4875955338b0a434238a31165cb87255ab6e9e4a"
},
diff --git a/Godeps/_workspace/src/github.com/fatih/color/.travis.yml b/Godeps/_workspace/src/github.com/fatih/color/.travis.yml
new file mode 100644
index 000000000..2405aef3a
--- /dev/null
+++ b/Godeps/_workspace/src/github.com/fatih/color/.travis.yml
@@ -0,0 +1,3 @@
+language: go
+go: 1.3
+
diff --git a/Godeps/_workspace/src/github.com/fatih/color/LICENSE.md b/Godeps/_workspace/src/github.com/fatih/color/LICENSE.md
new file mode 100644
index 000000000..25fdaf639
--- /dev/null
+++ b/Godeps/_workspace/src/github.com/fatih/color/LICENSE.md
@@ -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.
diff --git a/Godeps/_workspace/src/github.com/fatih/color/README.md b/Godeps/_workspace/src/github.com/fatih/color/README.md
new file mode 100644
index 000000000..d6fb06a3e
--- /dev/null
+++ b/Godeps/_workspace/src/github.com/fatih/color/README.md
@@ -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
+
diff --git a/Godeps/_workspace/src/github.com/fatih/color/color.go b/Godeps/_workspace/src/github.com/fatih/color/color.go
new file mode 100644
index 000000000..c4a10c3c8
--- /dev/null
+++ b/Godeps/_workspace/src/github.com/fatih/color/color.go
@@ -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...)
+}
diff --git a/Godeps/_workspace/src/github.com/fatih/color/color_test.go b/Godeps/_workspace/src/github.com/fatih/color/color_test.go
new file mode 100644
index 000000000..a1192b559
--- /dev/null
+++ b/Godeps/_workspace/src/github.com/fatih/color/color_test.go
@@ -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"))
+}
diff --git a/Godeps/_workspace/src/github.com/fatih/color/doc.go b/Godeps/_workspace/src/github.com/fatih/color/doc.go
new file mode 100644
index 000000000..17908787c
--- /dev/null
+++ b/Godeps/_workspace/src/github.com/fatih/color/doc.go
@@ -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
diff --git a/Godeps/_workspace/src/github.com/mattn/go-colorable/README.md b/Godeps/_workspace/src/github.com/mattn/go-colorable/README.md
deleted file mode 100644
index c69da4a76..000000000
--- a/Godeps/_workspace/src/github.com/mattn/go-colorable/README.md
+++ /dev/null
@@ -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)
diff --git a/Godeps/_workspace/src/github.com/mattn/go-colorable/colorable_others.go b/Godeps/_workspace/src/github.com/mattn/go-colorable/colorable_others.go
deleted file mode 100644
index 219f02f62..000000000
--- a/Godeps/_workspace/src/github.com/mattn/go-colorable/colorable_others.go
+++ /dev/null
@@ -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
-}
diff --git a/Godeps/_workspace/src/github.com/mattn/go-colorable/colorable_windows.go b/Godeps/_workspace/src/github.com/mattn/go-colorable/colorable_windows.go
deleted file mode 100644
index 6a2787808..000000000
--- a/Godeps/_workspace/src/github.com/mattn/go-colorable/colorable_windows.go
+++ /dev/null
@@ -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()
- }
-}
diff --git a/Godeps/_workspace/src/github.com/shiena/ansicolor/.gitignore b/Godeps/_workspace/src/github.com/shiena/ansicolor/.gitignore
new file mode 100644
index 000000000..69cec52c4
--- /dev/null
+++ b/Godeps/_workspace/src/github.com/shiena/ansicolor/.gitignore
@@ -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
+
diff --git a/Godeps/_workspace/src/github.com/shiena/ansicolor/LICENSE b/Godeps/_workspace/src/github.com/shiena/ansicolor/LICENSE
new file mode 100644
index 000000000..e58473ed9
--- /dev/null
+++ b/Godeps/_workspace/src/github.com/shiena/ansicolor/LICENSE
@@ -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.
diff --git a/Godeps/_workspace/src/github.com/shiena/ansicolor/README.md b/Godeps/_workspace/src/github.com/shiena/ansicolor/README.md
new file mode 100644
index 000000000..7797a4f18
--- /dev/null
+++ b/Godeps/_workspace/src/github.com/shiena/ansicolor/README.md
@@ -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
+
diff --git a/Godeps/_workspace/src/github.com/shiena/ansicolor/ansicolor.go b/Godeps/_workspace/src/github.com/shiena/ansicolor/ansicolor.go
new file mode 100644
index 000000000..d3ece8fc0
--- /dev/null
+++ b/Godeps/_workspace/src/github.com/shiena/ansicolor/ansicolor.go
@@ -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
+}
diff --git a/Godeps/_workspace/src/github.com/shiena/ansicolor/ansicolor/main.go b/Godeps/_workspace/src/github.com/shiena/ansicolor/ansicolor/main.go
new file mode 100644
index 000000000..d86cfc0f3
--- /dev/null
+++ b/Godeps/_workspace/src/github.com/shiena/ansicolor/ansicolor/main.go
@@ -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)
+}
diff --git a/Godeps/_workspace/src/github.com/shiena/ansicolor/ansicolor_ansi.go b/Godeps/_workspace/src/github.com/shiena/ansicolor/ansicolor_ansi.go
new file mode 100644
index 000000000..57b4633a7
--- /dev/null
+++ b/Godeps/_workspace/src/github.com/shiena/ansicolor/ansicolor_ansi.go
@@ -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)
+}
diff --git a/Godeps/_workspace/src/github.com/shiena/ansicolor/ansicolor_test.go b/Godeps/_workspace/src/github.com/shiena/ansicolor/ansicolor_test.go
new file mode 100644
index 000000000..4feeb1de6
--- /dev/null
+++ b/Godeps/_workspace/src/github.com/shiena/ansicolor/ansicolor_test.go
@@ -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)
+ }
+}
diff --git a/Godeps/_workspace/src/github.com/shiena/ansicolor/ansicolor_windows.go b/Godeps/_workspace/src/github.com/shiena/ansicolor/ansicolor_windows.go
new file mode 100644
index 000000000..d918ffe91
--- /dev/null
+++ b/Godeps/_workspace/src/github.com/shiena/ansicolor/ansicolor_windows.go
@@ -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
+}
diff --git a/Godeps/_workspace/src/github.com/shiena/ansicolor/ansicolor_windows_test.go b/Godeps/_workspace/src/github.com/shiena/ansicolor/ansicolor_windows_test.go
new file mode 100644
index 000000000..6c126d517
--- /dev/null
+++ b/Godeps/_workspace/src/github.com/shiena/ansicolor/ansicolor_windows_test.go
@@ -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)
+ }
+}
diff --git a/Godeps/_workspace/src/github.com/shiena/ansicolor/example_test.go b/Godeps/_workspace/src/github.com/shiena/ansicolor/example_test.go
new file mode 100644
index 000000000..f2ac67c17
--- /dev/null
+++ b/Godeps/_workspace/src/github.com/shiena/ansicolor/example_test.go
@@ -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")
+}
diff --git a/Godeps/_workspace/src/github.com/shiena/ansicolor/export_test.go b/Godeps/_workspace/src/github.com/shiena/ansicolor/export_test.go
new file mode 100644
index 000000000..6d2f7c074
--- /dev/null
+++ b/Godeps/_workspace/src/github.com/shiena/ansicolor/export_test.go
@@ -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))
+}
diff --git a/cmd/evm/main.go b/cmd/evm/main.go
index be6546c95..6639069b9 100644
--- a/cmd/evm/main.go
+++ b/cmd/evm/main.go
@@ -102,7 +102,7 @@ func init() {
func run(ctx *cli.Context) {
vm.Debug = ctx.GlobalBool(DebugFlag.Name)
vm.ForceJit = ctx.GlobalBool(ForceJitFlag.Name)
- vm.DisableJit = ctx.GlobalBool(DisableJitFlag.Name)
+ vm.EnableJit = !ctx.GlobalBool(DisableJitFlag.Name)
glog.SetToStderr(true)
diff --git a/cmd/geth/js.go b/cmd/geth/js.go
index bf56423ec..c31deefdd 100644
--- a/cmd/geth/js.go
+++ b/cmd/geth/js.go
@@ -145,19 +145,15 @@ func apiWordCompleter(line string, pos int) (head string, completions []string,
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.wait = make(chan *big.Int)
js.client = client
js.ds = docserver.New("/")
- if f == nil {
- f = js
- }
-
// update state in separare forever blocks
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)
}
@@ -232,15 +228,10 @@ func (self *jsre) loadAutoCompletion() {
}
func (self *jsre) batch(statement string) {
- val, err := self.re.Run(statement)
+ err := self.re.EvalAndPrettyPrint(statement)
if err != nil {
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 {
@@ -252,22 +243,22 @@ func (self *jsre) batch(statement string) {
// show summary of current geth instance
func (self *jsre) welcome() {
- self.re.Eval(`console.log('instance: ' + web3.version.client);`)
- self.re.Eval(`console.log(' datadir: ' + admin.datadir);`)
- self.re.Eval(`console.log("coinbase: " + eth.coinbase);`)
- self.re.Eval(`var lastBlockTimestamp = 1000 * eth.getBlock(eth.blockNumber).timestamp`)
- self.re.Eval(`console.log("at block: " + eth.blockNumber + " (" + new Date(lastBlockTimestamp).toLocaleDateString()
- + " " + new Date(lastBlockTimestamp).toLocaleTimeString() + ")");`)
-
+ self.re.Run(`
+ (function () {
+ console.log('instance: ' + web3.version.client);
+ console.log(' datadir: ' + admin.datadir);
+ console.log("coinbase: " + eth.coinbase);
+ var ts = 1000 * eth.getBlock(eth.blockNumber).timestamp;
+ console.log("at block: " + eth.blockNumber + " (" + new Date(ts) + ")");
+ })();
+ `)
if modules, err := self.supportedApis(); err == nil {
loadedModules := make([]string, 0)
for api, version := range modules {
loadedModules = append(loadedModules, fmt.Sprintf("%s:%s", api, version))
}
sort.Strings(loadedModules)
-
- self.re.Eval(fmt.Sprintf("var modules = '%s';", strings.Join(loadedModules, " ")))
- self.re.Eval(`console.log(" modules: " + modules);`)
+ fmt.Println("modules:", strings.Join(loadedModules, " "))
}
}
@@ -291,7 +282,7 @@ func (js *jsre) apiBindings(f xeth.Frontend) error {
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{}{})
t, _ := js.re.Get("jeth")
jethObj := t.Object()
@@ -309,12 +300,12 @@ func (js *jsre) apiBindings(f xeth.Frontend) error {
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 {
utils.Fatalf("Error requiring web3: %v", err)
}
- _, err = js.re.Eval("web3.setProvider(jeth)")
+ _, err = js.re.Run("web3.setProvider(jeth)")
if err != nil {
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 {
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
}
@@ -387,6 +378,11 @@ func (self *jsre) interactive() {
for {
line, err := self.Prompt(<-prompt)
if err != nil {
+ if err == liner.ErrPromptAborted { // ctrl-C
+ self.resetPrompt()
+ inputln <- ""
+ continue
+ }
return
}
inputln <- line
@@ -458,8 +454,7 @@ func (self *jsre) parseInput(code string) {
fmt.Println("[native] error", r)
}
}()
- value, err := self.re.Run(code)
- if err != nil {
+ if err := self.re.EvalAndPrettyPrint(code); err != nil {
if ottoErr, ok := err.(*otto.Error); ok {
fmt.Println(ottoErr.String())
} else {
@@ -467,12 +462,17 @@ func (self *jsre) parseInput(code string) {
}
return
}
- self.printValue(value)
}
var indentCount = 0
var str = ""
+func (self *jsre) resetPrompt() {
+ indentCount = 0
+ str = ""
+ self.ps1 = "> "
+}
+
func (self *jsre) setIndent() {
open := strings.Count(str, "{")
open += strings.Count(str, "(")
@@ -486,10 +486,3 @@ func (self *jsre) setIndent() {
self.ps1 += " "
}
}
-
-func (self *jsre) printValue(v interface{}) {
- val, err := self.re.PrettyPrint(v)
- if err == nil {
- fmt.Printf("%v", val)
- }
-}
diff --git a/cmd/geth/main.go b/cmd/geth/main.go
index 4905d502a..2dc3c438f 100644
--- a/cmd/geth/main.go
+++ b/cmd/geth/main.go
@@ -19,7 +19,6 @@ package main
import (
"fmt"
- "io"
"io/ioutil"
_ "net/http/pprof"
"os"
@@ -46,8 +45,6 @@ import (
"github.com/ethereum/go-ethereum/rlp"
"github.com/ethereum/go-ethereum/rpc/codec"
"github.com/ethereum/go-ethereum/rpc/comms"
- "github.com/mattn/go-colorable"
- "github.com/mattn/go-isatty"
)
const (
@@ -398,14 +395,6 @@ func run(ctx *cli.Context) {
func attach(ctx *cli.Context) {
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 err error
if ctx.Args().Present() {
@@ -425,7 +414,7 @@ func attach(ctx *cli.Context) {
ctx.GlobalString(utils.JSpathFlag.Name),
client,
true,
- nil)
+ )
if ctx.GlobalString(utils.ExecFlag.Name) != "" {
repl.batch(ctx.GlobalString(utils.ExecFlag.Name))
@@ -438,14 +427,6 @@ func attach(ctx *cli.Context) {
func console(ctx *cli.Context) {
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)
ethereum, err := eth.New(cfg)
if err != nil {
diff --git a/cmd/utils/flags.go b/cmd/utils/flags.go
index 462da9305..af2929d10 100644
--- a/cmd/utils/flags.go
+++ b/cmd/utils/flags.go
@@ -21,30 +21,32 @@ import (
"fmt"
"log"
"math/big"
+ "net"
"net/http"
"os"
"path/filepath"
"runtime"
"strconv"
- "github.com/ethereum/go-ethereum/core/vm"
- "github.com/ethereum/go-ethereum/metrics"
-
"github.com/codegangsta/cli"
"github.com/ethereum/ethash"
"github.com/ethereum/go-ethereum/accounts"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core"
+ "github.com/ethereum/go-ethereum/core/vm"
"github.com/ethereum/go-ethereum/crypto"
"github.com/ethereum/go-ethereum/eth"
"github.com/ethereum/go-ethereum/ethdb"
"github.com/ethereum/go-ethereum/event"
"github.com/ethereum/go-ethereum/logger"
"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/rpc/api"
"github.com/ethereum/go-ethereum/rpc/codec"
"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"
)
@@ -452,7 +454,7 @@ func SetupLogger(ctx *cli.Context) {
// SetupVM configured the VM package's global settings
func SetupVM(ctx *cli.Context) {
- vm.DisableJit = !ctx.GlobalBool(VMEnableJitFlag.Name)
+ vm.EnableJit = ctx.GlobalBool(VMEnableJitFlag.Name)
vm.ForceJit = ctx.GlobalBool(VMForceJitFlag.Name)
vm.SetJITCacheSize(ctx.GlobalInt(VMJitCacheFlag.Name))
}
@@ -518,15 +520,20 @@ func StartIPC(eth *eth.Ethereum, ctx *cli.Context) error {
Endpoint: IpcSocketPath(ctx),
}
- xeth := xeth.New(eth, nil)
- codec := codec.JSON
+ initializer := func(conn net.Conn) (shared.EthereumApi, error) {
+ 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)
- if err != nil {
- return err
+ apis, err := api.ParseApiString(ctx.GlobalString(IPCApiFlag.Name), codec, xeth, eth)
+ if err != nil {
+ 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 {
diff --git a/core/block_processor.go b/core/block_processor.go
index 477215356..829e4314c 100644
--- a/core/block_processor.go
+++ b/core/block_processor.go
@@ -354,18 +354,8 @@ func (sm *BlockProcessor) GetLogs(block *types.Block) (logs state.Logs, err erro
for _, receipt := range receipts {
logs = append(logs, receipt.Logs()...)
}
- return
}
-
- // 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
+ return logs, nil
}
// See YP section 4.3.4. "Block Header Validity"
diff --git a/core/vm/instructions.go b/core/vm/instructions.go
index 6b7b41220..2de35a443 100644
--- a/core/vm/instructions.go
+++ b/core/vm/instructions.go
@@ -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) {
- 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) {
- 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) {
- 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) {
- 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) {
@@ -415,15 +415,12 @@ func opSstore(instr instruction, env Environment, context *Context, memory *Memo
env.State().SetState(context.Address(), loc, common.BigToHash(val))
}
-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 opJumpdest(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 opJumpdest(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) {
diff --git a/core/vm/jit.go b/core/vm/jit.go
index d5c2d7830..084d2a3f3 100644
--- a/core/vm/jit.go
+++ b/core/vm/jit.go
@@ -83,6 +83,7 @@ type Program struct {
code []byte
}
+// NewProgram returns a new JIT program
func NewProgram(code []byte) *Program {
program := &Program{
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
}
+// CompileProgram compiles the given program and return an error when it fails
func CompileProgram(program *Program) (err error) {
if progStatus(atomic.LoadInt32(&program.status)) == progCompile {
return nil
@@ -272,6 +274,8 @@ func CompileProgram(program *Program) (err error) {
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) {
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++
}
+ context.Input = nil
+
return context.Return(nil), nil
}
diff --git a/core/vm/jit_test.go b/core/vm/jit_test.go
index 5b3feea99..b9e2c6999 100644
--- a/core/vm/jit_test.go
+++ b/core/vm/jit_test.go
@@ -46,7 +46,7 @@ func runVmBench(test vmBench, b *testing.B) {
}
env := NewEnv()
- DisableJit = test.nojit
+ EnableJit = !test.nojit
ForceJit = test.forcejit
b.ResetTimer()
diff --git a/core/vm/settings.go b/core/vm/settings.go
index 0cd931b6a..f9296f6c8 100644
--- a/core/vm/settings.go
+++ b/core/vm/settings.go
@@ -17,9 +17,9 @@
package vm
var (
- DisableJit bool = true // Disable the JIT VM
- ForceJit bool // Force the JIT, skip byte VM
- MaxProgSize int // Max cache size for JIT Programs
+ EnableJit bool // Enables the JIT VM
+ ForceJit bool // Force the JIT, skip byte VM
+ MaxProgSize int // Max cache size for JIT Programs
)
const defaultJitMaxCache int = 64
diff --git a/core/vm/vm.go b/core/vm/vm.go
index c292b45d1..da764004a 100644
--- a/core/vm/vm.go
+++ b/core/vm/vm.go
@@ -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
program *Program
)
- if !DisableJit {
+ if EnableJit {
// Fetch program status.
// * If ready run using JIT
// * If unknown, compile in a seperate goroutine
diff --git a/eth/backend.go b/eth/backend.go
index c9b71803f..2b21a7c96 100644
--- a/eth/backend.go
+++ b/eth/backend.go
@@ -45,7 +45,6 @@ import (
"github.com/ethereum/go-ethereum/p2p"
"github.com/ethereum/go-ethereum/p2p/discover"
"github.com/ethereum/go-ethereum/p2p/nat"
- "github.com/ethereum/go-ethereum/trie"
"github.com/ethereum/go-ethereum/whisper"
)
@@ -62,10 +61,11 @@ var (
defaultBootNodes = []*discover.Node{
// ETH/DEV Go Bootnodes
- discover.MustParseNode("enode://a979fb575495b8d6db44f750317d0f4622bf4c2aa3365d6af7c284339968eef29b69ad0dce72a4d8db5ebb4968de0e3bec910127f134779fbcb0cb6d3331163c@52.16.188.185:30303"),
- discover.MustParseNode("enode://de471bccee3d042261d52e9bff31458daecc406142b401d4cd848f677479f73104b9fdeb090af9583d3391b7f10cb2ba9e26865dd5fca4fcdc0fb1e3b723c786@54.94.239.50:30303"),
+ discover.MustParseNode("enode://a979fb575495b8d6db44f750317d0f4622bf4c2aa3365d6af7c284339968eef29b69ad0dce72a4d8db5ebb4968de0e3bec910127f134779fbcb0cb6d3331163c@52.16.188.185:30303"), // IE
+ 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)
- 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
@@ -738,48 +738,53 @@ func mergeDatabases(datadir string, newdb func(path string) (common.Database, er
}
defer database.Close()
- glog.Infoln("Merging blockchain database...")
+ // Migrate blocks
chainDb, err := newdb(chainPath)
if err != nil {
return fmt.Errorf("state db err: %v", err)
}
defer chainDb.Close()
- if db, ok := chainDb.(*ethdb.LDBDatabase); ok {
- it := db.NewIterator()
+ if chain, ok := chainDb.(*ethdb.LDBDatabase); ok {
+ glog.Infoln("Merging blockchain database...")
+ it := chain.NewIterator()
for it.Next() {
database.Put(it.Key(), it.Value())
}
+ it.Release()
}
- glog.Infoln("Merging state database...")
- state := filepath.Join(datadir, "state")
- stateDb, err := newdb(state)
+ // Migrate state
+ stateDb, err := newdb(filepath.Join(datadir, "state"))
if err != nil {
return fmt.Errorf("state db err: %v", err)
}
defer stateDb.Close()
- if db, ok := chainDb.(*ethdb.LDBDatabase); ok {
- it := db.NewIterator()
+ if state, ok := stateDb.(*ethdb.LDBDatabase); ok {
+ glog.Infoln("Merging state database...")
+ it := state.NewIterator()
for it.Next() {
- database.Put(append(trie.StatePre, it.Key()...), it.Value())
+ database.Put(it.Key(), it.Value())
}
+ it.Release()
}
- glog.Infoln("Merging transaction database...")
- extra := filepath.Join(datadir, "extra")
- extraDb, err := newdb(extra)
+ // Migrate transaction / receipts
+ extraDb, err := newdb(filepath.Join(datadir, "extra"))
if err != nil {
return fmt.Errorf("state db err: %v", err)
}
defer extraDb.Close()
- if db, ok := chainDb.(*ethdb.LDBDatabase); ok {
- it := db.NewIterator()
+ if extra, ok := extraDb.(*ethdb.LDBDatabase); ok {
+ glog.Infoln("Merging transaction database...")
+
+ it := extra.NewIterator()
for it.Next() {
database.Put(it.Key(), it.Value())
}
+ it.Release()
}
return nil
diff --git a/jsre/jsre.go b/jsre/jsre.go
index d4c982897..0db9e33fc 100644
--- a/jsre/jsre.go
+++ b/jsre/jsre.go
@@ -65,8 +65,8 @@ func New(assetPath string) *JSRE {
}
re.loopWg.Add(1)
go re.runEventLoop()
- re.Compile("pp.js", pp_js) // load prettyprint func definition
re.Set("loadScript", re.loadScript)
+ re.Set("inspect", prettyPrintJS)
return re
}
@@ -255,35 +255,19 @@ func (self *JSRE) loadScript(call otto.FunctionCall) otto.Value {
return otto.TrueValue()
}
-// PrettyPrint writes v to standard output.
-func (self *JSRE) PrettyPrint(v interface{}) (val otto.Value, err error) {
- var method otto.Value
+// EvalAndPrettyPrint evaluates code and pretty prints the result to
+// standard output.
+func (self *JSRE) EvalAndPrettyPrint(code string) (err error) {
self.do(func(vm *otto.Otto) {
- val, err = vm.ToValue(v)
+ var val otto.Value
+ val, err = vm.Run(code)
if err != nil {
return
}
- method, err = vm.Get("prettyPrint")
- if err != nil {
- return
- }
- val, err = method.Call(method, val)
+ prettyPrint(vm, val)
+ fmt.Println()
})
- return val, 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
+ return err
}
// Compile compiles and then runs a piece of JS code.
diff --git a/jsre/jsre_test.go b/jsre/jsre_test.go
index 93dc7d1f9..8450f546c 100644
--- a/jsre/jsre_test.go
+++ b/jsre/jsre_test.go
@@ -103,19 +103,14 @@ func TestNatto(t *testing.T) {
func TestBind(t *testing.T) {
jsre := New("")
+ defer jsre.Stop(false)
jsre.Bind("no", &testNativeObjectBinding{})
- val, err := jsre.Run(`no.TestMethod("testMsg")`)
+ _, err := jsre.Run(`no.TestMethod("testMsg")`)
if err != nil {
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) {
@@ -139,4 +134,4 @@ func TestLoadScript(t *testing.T) {
t.Errorf("expected '%v', got '%v'", exp, got)
}
jsre.Stop(false)
-} \ No newline at end of file
+}
diff --git a/jsre/pp_js.go b/jsre/pp_js.go
deleted file mode 100644
index 80fe523c1..000000000
--- a/jsre/pp_js.go
+++ /dev/null
@@ -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;
-`
diff --git a/jsre/pretty.go b/jsre/pretty.go
new file mode 100644
index 000000000..99aa9b33e
--- /dev/null
+++ b/jsre/pretty.go
@@ -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
+}
diff --git a/p2p/rlpx.go b/p2p/rlpx.go
index fd43f565e..aaa733854 100644
--- a/p2p/rlpx.go
+++ b/p2p/rlpx.go
@@ -267,6 +267,10 @@ func initiatorEncHandshake(conn io.ReadWriter, prv *ecdsa.PrivateKey, remoteID d
}
func newInitiatorHandshake(remoteID discover.NodeID) (*encHandshake, error) {
+ rpub, err := remoteID.Pubkey()
+ if err != nil {
+ return nil, fmt.Errorf("bad remoteID: %v", err)
+ }
// generate random initiator nonce
n := make([]byte, shaLen)
if _, err := rand.Read(n); err != nil {
@@ -277,10 +281,6 @@ func newInitiatorHandshake(remoteID discover.NodeID) (*encHandshake, error) {
if err != nil {
return nil, err
}
- rpub, err := remoteID.Pubkey()
- if err != nil {
- return nil, fmt.Errorf("bad remoteID: %v", err)
- }
h := &encHandshake{
initiator: true,
remoteID: remoteID,
@@ -417,6 +417,14 @@ func decodeAuthMsg(prv *ecdsa.PrivateKey, token []byte, auth []byte) (*encHandsh
if err != nil {
return nil, err
}
+
+ // validate the sha3 of recovered pubkey
+ remoteRandomPubMAC := msg[sigLen : sigLen+shaLen]
+ shaRemoteRandomPub := crypto.Sha3(remoteRandomPub[1:])
+ if !bytes.Equal(remoteRandomPubMAC, shaRemoteRandomPub) {
+ return nil, fmt.Errorf("sha3 of recovered ephemeral pubkey does not match checksum in auth message")
+ }
+
h.remoteRandomPub, _ = importPublicKey(remoteRandomPub)
return h, nil
}
diff --git a/rlp/decode.go b/rlp/decode.go
index c0b5f0699..1381f5274 100644
--- a/rlp/decode.go
+++ b/rlp/decode.go
@@ -183,6 +183,8 @@ func makeDecoder(typ reflect.Type, tags tags) (dec decoder, err error) {
return decodeBigIntNoPtr, nil
case isUint(kind):
return decodeUint, nil
+ case kind == reflect.Bool:
+ return decodeBool, nil
case kind == reflect.String:
return decodeString, nil
case kind == reflect.Slice || kind == reflect.Array:
@@ -211,6 +213,15 @@ func decodeUint(s *Stream, val reflect.Value) error {
return nil
}
+func decodeBool(s *Stream, val reflect.Value) error {
+ b, err := s.Bool()
+ if err != nil {
+ return wrapStreamError(err, val.Type())
+ }
+ val.SetBool(b)
+ return nil
+}
+
func decodeString(s *Stream, val reflect.Value) error {
b, err := s.Bytes()
if err != nil {
@@ -697,6 +708,24 @@ func (s *Stream) uint(maxbits int) (uint64, error) {
}
}
+// Bool reads an RLP string of up to 1 byte and returns its contents
+// as an boolean. If the input does not contain an RLP string, the
+// returned error will be ErrExpectedString.
+func (s *Stream) Bool() (bool, error) {
+ num, err := s.uint(8)
+ if err != nil {
+ return false, err
+ }
+ switch num {
+ case 0:
+ return false, nil
+ case 1:
+ return true, nil
+ default:
+ return false, fmt.Errorf("rlp: invalid boolean value: %d", num)
+ }
+}
+
// List starts decoding an RLP list. If the input does not contain a
// list, the returned error will be ErrExpectedList. When the list's
// end has been reached, any Stream operation will return EOL.
diff --git a/rlp/decode_test.go b/rlp/decode_test.go
index 331faa9d8..d6b0611dd 100644
--- a/rlp/decode_test.go
+++ b/rlp/decode_test.go
@@ -19,6 +19,7 @@ package rlp
import (
"bytes"
"encoding/hex"
+ "errors"
"fmt"
"io"
"math/big"
@@ -116,6 +117,9 @@ func TestStreamErrors(t *testing.T) {
{"817F", calls{"Uint"}, nil, ErrCanonSize},
{"8180", calls{"Uint"}, nil, nil},
+ // Non-valid boolean
+ {"02", calls{"Bool"}, nil, errors.New("rlp: invalid boolean value: 2")},
+
// Size tags must use the smallest possible encoding.
// Leading zero bytes in the size tag are also rejected.
{"8100", calls{"Uint"}, nil, ErrCanonSize},
@@ -315,6 +319,11 @@ var (
)
var decodeTests = []decodeTest{
+ // booleans
+ {input: "01", ptr: new(bool), value: true},
+ {input: "80", ptr: new(bool), value: false},
+ {input: "02", ptr: new(bool), error: "rlp: invalid boolean value: 2"},
+
// integers
{input: "05", ptr: new(uint32), value: uint32(5)},
{input: "80", ptr: new(uint32), value: uint32(0)},
diff --git a/rlp/encode.go b/rlp/encode.go
index 0ddef7bbb..b525ae4e7 100644
--- a/rlp/encode.go
+++ b/rlp/encode.go
@@ -361,6 +361,8 @@ func makeWriter(typ reflect.Type) (writer, error) {
return writeBigIntNoPtr, nil
case isUint(kind):
return writeUint, nil
+ case kind == reflect.Bool:
+ return writeBool, nil
case kind == reflect.String:
return writeString, nil
case kind == reflect.Slice && isByte(typ.Elem()):
@@ -398,6 +400,15 @@ func writeUint(val reflect.Value, w *encbuf) error {
return nil
}
+func writeBool(val reflect.Value, w *encbuf) error {
+ if val.Bool() {
+ w.str = append(w.str, 0x01)
+ } else {
+ w.str = append(w.str, 0x80)
+ }
+ return nil
+}
+
func writeBigIntPtr(val reflect.Value, w *encbuf) error {
ptr := val.Interface().(*big.Int)
if ptr == nil {
diff --git a/rlp/encode_test.go b/rlp/encode_test.go
index e83c76b51..60bd95692 100644
--- a/rlp/encode_test.go
+++ b/rlp/encode_test.go
@@ -71,6 +71,10 @@ type encTest struct {
}
var encTests = []encTest{
+ // booleans
+ {val: true, output: "01"},
+ {val: false, output: "80"},
+
// integers
{val: uint32(0), output: "80"},
{val: uint32(127), output: "7F"},
diff --git a/rpc/api/admin.go b/rpc/api/admin.go
index 29f342ab6..5e392ae32 100644
--- a/rpc/api/admin.go
+++ b/rpc/api/admin.go
@@ -37,6 +37,7 @@ import (
"github.com/ethereum/go-ethereum/rpc/codec"
"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"
)
@@ -71,6 +72,7 @@ var (
"admin_httpGet": (*adminApi).HttpGet,
"admin_sleepBlocks": (*adminApi).SleepBlocks,
"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
}
+
+func (self *adminApi) EnableUserAgent(req *shared.Request) (interface{}, error) {
+ if fe, ok := self.xeth.Frontend().(*useragent.RemoteFrontend); ok {
+ fe.Enable()
+ }
+ return true, nil
+}
diff --git a/rpc/api/net.go b/rpc/api/net.go
index 39c230e14..9c6369615 100644
--- a/rpc/api/net.go
+++ b/rpc/api/net.go
@@ -32,7 +32,7 @@ var (
netMapping = map[string]nethandler{
"net_peerCount": (*netApi).PeerCount,
"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) {
return self.xeth.NetworkVersion(), nil
}
-
diff --git a/rpc/api/personal.go b/rpc/api/personal.go
index e9942c1e5..6c73ac83d 100644
--- a/rpc/api/personal.go
+++ b/rpc/api/personal.go
@@ -17,6 +17,7 @@
package api
import (
+ "fmt"
"time"
"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())
}
- 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()
addr := common.HexToAddress(args.Address)
- if args.Duration == -1 {
- err = am.Unlock(addr, args.Passphrase)
- } else {
- err = am.TimedUnlock(addr, args.Passphrase, time.Duration(args.Duration)*time.Second)
- }
-
- if err == nil {
- return true, nil
- }
- return false, err
+ err := am.TimedUnlock(addr, args.Passphrase, time.Duration(args.Duration)*time.Second)
+ return err == nil, err
}
diff --git a/rpc/api/personal_args.go b/rpc/api/personal_args.go
index 7f00701e3..5a584fb0c 100644
--- a/rpc/api/personal_args.go
+++ b/rpc/api/personal_args.go
@@ -86,10 +86,10 @@ func (args *UnlockAccountArgs) UnmarshalJSON(b []byte) (err error) {
return shared.NewDecodeParamError(err.Error())
}
- args.Duration = -1
+ args.Duration = 0
- if len(obj) < 2 {
- return shared.NewInsufficientParamsError(len(obj), 2)
+ if len(obj) < 1 {
+ return shared.NewInsufficientParamsError(len(obj), 1)
}
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")
}
- if passphrasestr, ok := obj[1].(string); ok {
- args.Passphrase = passphrasestr
- } else {
- return shared.NewInvalidTypeError("passphrase", "not a string")
+ if len(obj) >= 2 && obj[1] != nil {
+ if passphrasestr, ok := obj[1].(string); ok {
+ args.Passphrase = passphrasestr
+ } 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
diff --git a/rpc/api/ssh_js.go b/rpc/api/shh_js.go
index a92ad1644..a92ad1644 100644
--- a/rpc/api/ssh_js.go
+++ b/rpc/api/shh_js.go
diff --git a/rpc/codec/codec.go b/rpc/codec/codec.go
index 2fdb0d8f3..786080b44 100644
--- a/rpc/codec/codec.go
+++ b/rpc/codec/codec.go
@@ -31,6 +31,8 @@ type ApiCoder interface {
ReadRequest() ([]*shared.Request, bool, error)
// Parse response message from underlying stream
ReadResponse() (interface{}, error)
+ // Read raw message from underlying stream
+ Recv() (interface{}, error)
// Encode response to encoded form in underlying stream
WriteResponse(interface{}) error
// Decode single message from data
diff --git a/rpc/codec/json.go b/rpc/codec/json.go
index d811b2096..cfc449143 100644
--- a/rpc/codec/json.go
+++ b/rpc/codec/json.go
@@ -21,6 +21,7 @@ import (
"fmt"
"net"
"time"
+ "strings"
"github.com/ethereum/go-ethereum/rpc/shared"
)
@@ -73,35 +74,41 @@ func (self *JsonCodec) ReadRequest() (requests []*shared.Request, isBatch bool,
return nil, false, err
}
-func (self *JsonCodec) ReadResponse() (interface{}, error) {
- bytesInBuffer := 0
- buf := make([]byte, MAX_RESPONSE_SIZE)
+func (self *JsonCodec) Recv() (interface{}, error) {
+ var msg json.RawMessage
+ err := self.d.Decode(&msg)
+ if err != nil {
+ self.c.Close()
+ return nil, err
+ }
- deadline := time.Now().Add(READ_TIMEOUT * time.Second)
- if err := self.c.SetDeadline(deadline); err != nil {
+ return msg, err
+}
+
+func (self *JsonCodec) ReadResponse() (interface{}, error) {
+ in, err := self.Recv()
+ if err != nil {
return nil, err
}
- for {
- n, err := self.c.Read(buf[bytesInBuffer:])
- 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
}
- bytesInBuffer += n
- var failure shared.ErrorResponse
- if err = json.Unmarshal(buf[:bytesInBuffer], &failure); err == nil && failure.Error != nil {
+ var failure *shared.ErrorResponse
+ if err = json.Unmarshal(msg, &failure); err == nil && failure.Error != nil {
return failure, fmt.Errorf(failure.Error.Message)
}
- var success shared.SuccessResponse
- if err = json.Unmarshal(buf[:bytesInBuffer], &success); err == nil {
+ var success *shared.SuccessResponse
+ if err = json.Unmarshal(msg, &success); err == nil {
return success, nil
}
}
- self.c.Close()
- return nil, fmt.Errorf("Unable to read response")
+ return in, err
}
// Decode data
diff --git a/rpc/comms/comms.go b/rpc/comms/comms.go
index f5eeae84f..731b2f62e 100644
--- a/rpc/comms/comms.go
+++ b/rpc/comms/comms.go
@@ -49,7 +49,7 @@ var (
)
type EthereumClient interface {
- // Close underlaying connection
+ // Close underlying connection
Close()
// Send request
Send(interface{}) error
diff --git a/rpc/comms/inproc.go b/rpc/comms/inproc.go
index f279f0163..e8058e32b 100644
--- a/rpc/comms/inproc.go
+++ b/rpc/comms/inproc.go
@@ -60,7 +60,7 @@ func (self *InProcClient) Send(req 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) {
diff --git a/rpc/comms/ipc.go b/rpc/comms/ipc.go
index 0250aa01e..e982ada13 100644
--- a/rpc/comms/ipc.go
+++ b/rpc/comms/ipc.go
@@ -44,35 +44,18 @@ func (self *ipcClient) Close() {
func (self *ipcClient) Send(req interface{}) error {
var err error
- if r, ok := req.(*shared.Request); ok {
- if err = self.coder.WriteResponse(r); err != nil {
- if _, ok := err.(*net.OpError); ok { // connection lost, retry once
- if err = self.reconnect(); err == nil {
- err = self.coder.WriteResponse(r)
- }
+ if err = self.coder.WriteResponse(req); err != nil {
+ if _, ok := err.(*net.OpError); ok { // connection lost, retry once
+ if err = self.reconnect(); err == nil {
+ err = self.coder.WriteResponse(req)
}
}
- return err
}
-
- return fmt.Errorf("Invalid request (%T)", req)
+ return err
}
func (self *ipcClient) Recv() (interface{}, error) {
- res, err := 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
+ return self.coder.ReadResponse()
}
func (self *ipcClient) SupportedModules() (map[string]string, error) {
@@ -91,7 +74,7 @@ func (self *ipcClient) SupportedModules() (map[string]string, error) {
return nil, err
}
- if sucRes, ok := res.(shared.SuccessResponse); ok {
+ if sucRes, ok := res.(*shared.SuccessResponse); ok {
data, _ := json.Marshal(sucRes.Result)
modules := make(map[string]string)
err = json.Unmarshal(data, &modules)
@@ -109,8 +92,8 @@ func NewIpcClient(cfg IpcConfig, codec codec.Codec) (*ipcClient, error) {
}
// Start IPC server
-func StartIpc(cfg IpcConfig, codec codec.Codec, offeredApi shared.EthereumApi) error {
- return startIpc(cfg, codec, offeredApi)
+func StartIpc(cfg IpcConfig, codec codec.Codec, initializer func(conn net.Conn) (shared.EthereumApi, error)) error {
+ return startIpc(cfg, codec, initializer)
}
func newIpcConnId() int {
diff --git a/rpc/comms/ipc_unix.go b/rpc/comms/ipc_unix.go
index 432bf93b5..6968fa844 100644
--- a/rpc/comms/ipc_unix.go
+++ b/rpc/comms/ipc_unix.go
@@ -48,7 +48,7 @@ func (self *ipcClient) reconnect() error {
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
l, err := net.Listen("unix", cfg.Endpoint)
@@ -69,6 +69,13 @@ func startIpc(cfg IpcConfig, codec codec.Codec, api shared.EthereumApi) error {
id := newIpcConnId()
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)
}
diff --git a/rpc/comms/ipc_windows.go b/rpc/comms/ipc_windows.go
index ee49f069b..b2fe2b29d 100644
--- a/rpc/comms/ipc_windows.go
+++ b/rpc/comms/ipc_windows.go
@@ -667,7 +667,7 @@ func (self *ipcClient) reconnect() error {
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
l, err := Listen(cfg.Endpoint)
@@ -687,6 +687,13 @@ func startIpc(cfg IpcConfig, codec codec.Codec, api shared.EthereumApi) error {
id := newIpcConnId()
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)
}
diff --git a/rpc/jeth.go b/rpc/jeth.go
index 07add2bad..158bfb64c 100644
--- a/rpc/jeth.go
+++ b/rpc/jeth.go
@@ -18,12 +18,17 @@ package rpc
import (
"encoding/json"
-
"fmt"
+ "github.com/ethereum/go-ethereum/cmd/utils"
"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/shared"
+ "github.com/ethereum/go-ethereum/rpc/useragent"
+ "github.com/ethereum/go-ethereum/xeth"
+
"github.com/robertkrimen/otto"
)
@@ -31,10 +36,21 @@ type Jeth struct {
ethApi shared.EthereumApi
re *jsre.JSRE
client comms.EthereumClient
+ fe xeth.Frontend
}
-func NewJeth(ethApi shared.EthereumApi, re *jsre.JSRE, client comms.EthereumClient) *Jeth {
- return &Jeth{ethApi, re, client}
+func NewJeth(ethApi shared.EthereumApi, re *jsre.JSRE, client comms.EthereumClient, fe xeth.Frontend) *Jeth {
+ // 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) {
@@ -72,16 +88,34 @@ func (self *Jeth) Send(call otto.FunctionCall) (response otto.Value) {
if err != nil {
return self.err(call, -32603, err.Error(), req.Id)
}
- respif, err = self.client.Recv()
+ recv:
+ respif, err = self.client.Recv()
if err != nil {
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_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("response_idx", i)
@@ -105,3 +139,48 @@ func (self *Jeth) Send(call otto.FunctionCall) (response otto.Value) {
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
+}
diff --git a/rpc/useragent/agent.go b/rpc/useragent/agent.go
new file mode 100644
index 000000000..df0739e65
--- /dev/null
+++ b/rpc/useragent/agent.go
@@ -0,0 +1,24 @@
+// 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 user agent provides frontends and agents which can interact with the user
+package useragent
+
+var (
+ AskPasswordMethod = "agent_askPassword"
+ ConfirmTransactionMethod = "agent_confirmTransaction"
+ EnableUserAgentMethod = "admin_enableUserAgent"
+)
diff --git a/rpc/useragent/remote_frontend.go b/rpc/useragent/remote_frontend.go
new file mode 100644
index 000000000..0dd4a6049
--- /dev/null
+++ b/rpc/useragent/remote_frontend.go
@@ -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")
+}
diff --git a/tests/state_test.go b/tests/state_test.go
index eb1900e1b..7090b0541 100644
--- a/tests/state_test.go
+++ b/tests/state_test.go
@@ -27,14 +27,13 @@ import (
func init() {
if os.Getenv("JITVM") == "true" {
vm.ForceJit = true
- } else {
- vm.DisableJit = true
+ vm.EnableJit = true
}
}
func BenchmarkStateCall1024(b *testing.B) {
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)
}
}
diff --git a/tests/state_test_util.go b/tests/state_test_util.go
index 695e50852..def9b0c36 100644
--- a/tests/state_test_util.go
+++ b/tests/state_test_util.go
@@ -71,8 +71,8 @@ func BenchStateTest(p string, conf bconf, b *testing.B) error {
return fmt.Errorf("test not found: %s", conf.name)
}
- pNoJit := vm.DisableJit
- vm.DisableJit = conf.nojit
+ pJit := vm.EnableJit
+ vm.EnableJit = conf.jit
pForceJit := vm.ForceJit
vm.ForceJit = conf.precomp
@@ -94,7 +94,7 @@ func BenchStateTest(p string, conf bconf, b *testing.B) error {
benchStateTest(test, env, b)
}
- vm.DisableJit = pNoJit
+ vm.EnableJit = pJit
vm.ForceJit = pForceJit
return nil
diff --git a/tests/vm_test.go b/tests/vm_test.go
index afa1424d5..96718db3c 100644
--- a/tests/vm_test.go
+++ b/tests/vm_test.go
@@ -17,20 +17,21 @@
package tests
import (
+ "os"
"path/filepath"
"testing"
)
func BenchmarkVmAckermann32Tests(b *testing.B) {
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)
}
}
func BenchmarkVmFibonacci16Tests(b *testing.B) {
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)
}
}
diff --git a/tests/vm_test_util.go b/tests/vm_test_util.go
index b29dcd20f..71a4f5e33 100644
--- a/tests/vm_test_util.go
+++ b/tests/vm_test_util.go
@@ -52,7 +52,7 @@ func RunVmTestWithReader(r io.Reader, skipTests []string) error {
type bconf struct {
name string
precomp bool
- nojit bool
+ jit bool
}
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)
}
- pNoJit := vm.DisableJit
- vm.DisableJit = conf.nojit
+ pJit := vm.EnableJit
+ vm.EnableJit = conf.jit
pForceJit := vm.ForceJit
vm.ForceJit = conf.precomp
@@ -99,7 +99,7 @@ func BenchVmTest(p string, conf bconf, b *testing.B) error {
benchVmTest(test, env, b)
}
- vm.DisableJit = pNoJit
+ vm.EnableJit = pJit
vm.ForceJit = pForceJit
return nil
diff --git a/trie/cache.go b/trie/cache.go
index 99d8033a6..e475fc861 100644
--- a/trie/cache.go
+++ b/trie/cache.go
@@ -38,8 +38,6 @@ func NewCache(backend Backend) *Cache {
}
func (self *Cache) Get(key []byte) []byte {
- key = append(StatePre, key...)
-
data := self.store[string(key)]
if data == nil {
data, _ = self.backend.Get(key)
@@ -49,8 +47,6 @@ func (self *Cache) Get(key []byte) []byte {
}
func (self *Cache) Put(key []byte, data []byte) {
- key = append(StatePre, key...)
-
self.batch.Put(key, data)
self.store[string(key)] = data
}
diff --git a/trie/trie.go b/trie/trie.go
index 2970bc185..abf48a850 100644
--- a/trie/trie.go
+++ b/trie/trie.go
@@ -27,8 +27,6 @@ import (
"github.com/ethereum/go-ethereum/crypto"
)
-var StatePre = []byte("state-")
-
func ParanoiaCheck(t1 *Trie, backend Backend) (bool, *Trie) {
t2 := New(nil, backend)
diff --git a/xeth/xeth.go b/xeth/xeth.go
index 5110aa62c..8bd45998f 100644
--- a/xeth/xeth.go
+++ b/xeth/xeth.go
@@ -89,8 +89,7 @@ type XEth struct {
messagesMu sync.RWMutex
messages map[int]*whisperFilter
- // regmut sync.Mutex
- // register map[string][]*interface{} // TODO improve return type
+ transactMu sync.Mutex
agent *miner.RemoteAgent
@@ -823,18 +822,22 @@ func (self *XEth) Call(fromStr, toStr, valueStr, gasStr, gasPriceStr, dataStr st
}
from.SetBalance(common.MaxBig)
- from.SetGasLimit(self.backend.ChainManager().GasLimit())
+ from.SetGasLimit(common.MaxBig)
+
msg := callmsg{
from: from,
- to: common.HexToAddress(toStr),
gas: common.Big(gasStr),
gasPrice: common.Big(gasPriceStr),
value: common.Big(valueStr),
data: common.FromHex(dataStr),
}
+ if len(toStr) > 0 {
+ addr := common.HexToAddress(toStr)
+ msg.to = &addr
+ }
if msg.gas.Cmp(big.NewInt(0)) == 0 {
- msg.gas = DefaultGas()
+ msg.gas = big.NewInt(50000000)
}
if msg.gasPrice.Cmp(big.NewInt(0)) == 0 {
@@ -885,6 +888,10 @@ func isAddress(addr string) bool {
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) {
// 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
- // common.Value conversions later on
+ self.transactMu.Lock()
+ defer self.transactMu.Unlock()
+
var nonce uint64
if len(nonceStr) != 0 {
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.
type callmsg struct {
from *state.StateObject
- to common.Address
+ to *common.Address
gas, gasPrice *big.Int
value *big.Int
data []byte
@@ -1003,7 +1011,7 @@ type callmsg struct {
// accessor boilerplate to implement core.Message
func (m callmsg) From() (common.Address, error) { return m.from.Address(), nil }
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) Gas() *big.Int { return m.gas }
func (m callmsg) Value() *big.Int { return m.value }