Merge branch 'develop' into ui
This commit is contained in:
		
							
								
								
									
										13
									
								
								.travis.yml
									
									
									
									
									
								
							
							
						
						
									
										13
									
								
								.travis.yml
									
									
									
									
									
								
							@@ -6,18 +6,15 @@ before_install:
 | 
				
			|||||||
  - sudo apt-get update -qq
 | 
					  - sudo apt-get update -qq
 | 
				
			||||||
  - sudo apt-get install -yqq libgmp3-dev libreadline6-dev qt54quickcontrols qt54webengine
 | 
					  - sudo apt-get install -yqq libgmp3-dev libreadline6-dev qt54quickcontrols qt54webengine
 | 
				
			||||||
install:
 | 
					install:
 | 
				
			||||||
  - go get code.google.com/p/go.tools/cmd/goimports
 | 
					  # - go get code.google.com/p/go.tools/cmd/goimports
 | 
				
			||||||
  - go get github.com/golang/lint/golint
 | 
					  # - go get github.com/golang/lint/golint
 | 
				
			||||||
  # - go get golang.org/x/tools/cmd/vet 
 | 
					  # - go get golang.org/x/tools/cmd/vet 
 | 
				
			||||||
  - if ! go get code.google.com/p/go.tools/cmd/cover; then go get golang.org/x/tools/cmd/cover; fi
 | 
					  - if ! go get code.google.com/p/go.tools/cmd/cover; then go get golang.org/x/tools/cmd/cover; fi
 | 
				
			||||||
  - go get github.com/mattn/goveralls
 | 
					  - go get github.com/mattn/goveralls
 | 
				
			||||||
  - go get gopkg.in/check.v1
 | 
					 | 
				
			||||||
  - go get github.com/tools/godep
 | 
					 | 
				
			||||||
before_script:
 | 
					before_script:
 | 
				
			||||||
  - godep restore
 | 
					  # - gofmt -l -w .
 | 
				
			||||||
  - gofmt -l -w .
 | 
					  # - goimports -l -w .
 | 
				
			||||||
  - goimports -l -w .
 | 
					  # - golint .
 | 
				
			||||||
  - golint .
 | 
					 | 
				
			||||||
  # - go vet ./...
 | 
					  # - go vet ./...
 | 
				
			||||||
  # - go test -race ./...
 | 
					  # - go test -race ./...
 | 
				
			||||||
script:
 | 
					script:
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										46
									
								
								Godeps/Godeps.json
									
									
									
										generated
									
									
									
								
							
							
						
						
									
										46
									
								
								Godeps/Godeps.json
									
									
									
										generated
									
									
									
								
							@@ -1,6 +1,6 @@
 | 
				
			|||||||
{
 | 
					{
 | 
				
			||||||
	"ImportPath": "github.com/ethereum/go-ethereum",
 | 
						"ImportPath": "github.com/ethereum/go-ethereum",
 | 
				
			||||||
	"GoVersion": "go1.4",
 | 
						"GoVersion": "go1.4.1",
 | 
				
			||||||
	"Packages": [
 | 
						"Packages": [
 | 
				
			||||||
		"./..."
 | 
							"./..."
 | 
				
			||||||
	],
 | 
						],
 | 
				
			||||||
@@ -15,26 +15,6 @@
 | 
				
			|||||||
			"Comment": "null-12",
 | 
								"Comment": "null-12",
 | 
				
			||||||
			"Rev": "7dda39b2e7d5e265014674c5af696ba4186679e9"
 | 
								"Rev": "7dda39b2e7d5e265014674c5af696ba4186679e9"
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
			"ImportPath": "code.google.com/p/go.crypto/pbkdf2",
 | 
					 | 
				
			||||||
			"Comment": "null-236",
 | 
					 | 
				
			||||||
			"Rev": "69e2a90ed92d03812364aeb947b7068dc42e561e"
 | 
					 | 
				
			||||||
		},
 | 
					 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
			"ImportPath": "code.google.com/p/go.crypto/ripemd160",
 | 
					 | 
				
			||||||
			"Comment": "null-236",
 | 
					 | 
				
			||||||
			"Rev": "69e2a90ed92d03812364aeb947b7068dc42e561e"
 | 
					 | 
				
			||||||
		},
 | 
					 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
			"ImportPath": "code.google.com/p/go.crypto/scrypt",
 | 
					 | 
				
			||||||
			"Comment": "null-236",
 | 
					 | 
				
			||||||
			"Rev": "69e2a90ed92d03812364aeb947b7068dc42e561e"
 | 
					 | 
				
			||||||
		},
 | 
					 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
			"ImportPath": "code.google.com/p/go.net/websocket",
 | 
					 | 
				
			||||||
			"Comment": "null-173",
 | 
					 | 
				
			||||||
			"Rev": "4231557d7c726df4cf9a4e8cdd8a417c8c200bdb"
 | 
					 | 
				
			||||||
		},
 | 
					 | 
				
			||||||
		{
 | 
							{
 | 
				
			||||||
			"ImportPath": "code.google.com/p/snappy-go/snappy",
 | 
								"ImportPath": "code.google.com/p/snappy-go/snappy",
 | 
				
			||||||
			"Comment": "null-15",
 | 
								"Comment": "null-15",
 | 
				
			||||||
@@ -44,22 +24,18 @@
 | 
				
			|||||||
			"ImportPath": "github.com/ethereum/serpent-go",
 | 
								"ImportPath": "github.com/ethereum/serpent-go",
 | 
				
			||||||
			"Rev": "5767a0dbd759d313df3f404dadb7f98d7ab51443"
 | 
								"Rev": "5767a0dbd759d313df3f404dadb7f98d7ab51443"
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
			"ImportPath": "github.com/fjl/goupnp",
 | 
					 | 
				
			||||||
			"Rev": "fa95df6feb61e136b499d01711fcd410ccaf20c1"
 | 
					 | 
				
			||||||
		},
 | 
					 | 
				
			||||||
		{
 | 
							{
 | 
				
			||||||
			"ImportPath": "github.com/howeyc/fsnotify",
 | 
								"ImportPath": "github.com/howeyc/fsnotify",
 | 
				
			||||||
			"Comment": "v0.9.0-11-g6b1ef89",
 | 
								"Comment": "v0.9.0-11-g6b1ef89",
 | 
				
			||||||
			"Rev": "6b1ef893dc11e0447abda6da20a5203481878dda"
 | 
								"Rev": "6b1ef893dc11e0447abda6da20a5203481878dda"
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
		{
 | 
							{
 | 
				
			||||||
			"ImportPath": "github.com/jackpal/go-nat-pmp",
 | 
								"ImportPath": "github.com/huin/goupnp",
 | 
				
			||||||
			"Rev": "a45aa3d54aef73b504e15eb71bea0e5565b5e6e1"
 | 
								"Rev": "4191d8a85005844ea202fde52799681971b12dfe"
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
		{
 | 
							{
 | 
				
			||||||
			"ImportPath": "github.com/obscuren/ecies",
 | 
								"ImportPath": "github.com/jackpal/go-nat-pmp",
 | 
				
			||||||
			"Rev": "d899334bba7bf4a157cab19d8ad836dcb1de0c34"
 | 
								"Rev": "a45aa3d54aef73b504e15eb71bea0e5565b5e6e1"
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
		{
 | 
							{
 | 
				
			||||||
			"ImportPath": "github.com/obscuren/otto",
 | 
								"ImportPath": "github.com/obscuren/otto",
 | 
				
			||||||
@@ -109,6 +85,18 @@
 | 
				
			|||||||
			"ImportPath": "golang.org/x/crypto/pbkdf2",
 | 
								"ImportPath": "golang.org/x/crypto/pbkdf2",
 | 
				
			||||||
			"Rev": "4ed45ec682102c643324fae5dff8dab085b6c300"
 | 
								"Rev": "4ed45ec682102c643324fae5dff8dab085b6c300"
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								"ImportPath": "golang.org/x/crypto/ripemd160",
 | 
				
			||||||
 | 
								"Rev": "4ed45ec682102c643324fae5dff8dab085b6c300"
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								"ImportPath": "golang.org/x/crypto/scrypt",
 | 
				
			||||||
 | 
								"Rev": "4ed45ec682102c643324fae5dff8dab085b6c300"
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								"ImportPath": "golang.org/x/net/websocket",
 | 
				
			||||||
 | 
								"Rev": "59b0df9b1f7abda5aab0495ee54f408daf182ce7"
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
		{
 | 
							{
 | 
				
			||||||
			"ImportPath": "gopkg.in/check.v1",
 | 
								"ImportPath": "gopkg.in/check.v1",
 | 
				
			||||||
			"Rev": "64131543e7896d5bcc6bd5a76287eb75ea96c673"
 | 
								"Rev": "64131543e7896d5bcc6bd5a76287eb75ea96c673"
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										77
									
								
								Godeps/_workspace/src/code.google.com/p/go.crypto/pbkdf2/pbkdf2.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										77
									
								
								Godeps/_workspace/src/code.google.com/p/go.crypto/pbkdf2/pbkdf2.go
									
									
									
										generated
									
									
										vendored
									
									
								
							@@ -1,77 +0,0 @@
 | 
				
			|||||||
// Copyright 2012 The Go Authors. All rights reserved.
 | 
					 | 
				
			||||||
// Use of this source code is governed by a BSD-style
 | 
					 | 
				
			||||||
// license that can be found in the LICENSE file.
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/*
 | 
					 | 
				
			||||||
Package pbkdf2 implements the key derivation function PBKDF2 as defined in RFC
 | 
					 | 
				
			||||||
2898 / PKCS #5 v2.0.
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
A key derivation function is useful when encrypting data based on a password
 | 
					 | 
				
			||||||
or any other not-fully-random data. It uses a pseudorandom function to derive
 | 
					 | 
				
			||||||
a secure encryption key based on the password.
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
While v2.0 of the standard defines only one pseudorandom function to use,
 | 
					 | 
				
			||||||
HMAC-SHA1, the drafted v2.1 specification allows use of all five FIPS Approved
 | 
					 | 
				
			||||||
Hash Functions SHA-1, SHA-224, SHA-256, SHA-384 and SHA-512 for HMAC. To
 | 
					 | 
				
			||||||
choose, you can pass the `New` functions from the different SHA packages to
 | 
					 | 
				
			||||||
pbkdf2.Key.
 | 
					 | 
				
			||||||
*/
 | 
					 | 
				
			||||||
package pbkdf2
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
import (
 | 
					 | 
				
			||||||
	"crypto/hmac"
 | 
					 | 
				
			||||||
	"hash"
 | 
					 | 
				
			||||||
)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// Key derives a key from the password, salt and iteration count, returning a
 | 
					 | 
				
			||||||
// []byte of length keylen that can be used as cryptographic key. The key is
 | 
					 | 
				
			||||||
// derived based on the method described as PBKDF2 with the HMAC variant using
 | 
					 | 
				
			||||||
// the supplied hash function.
 | 
					 | 
				
			||||||
//
 | 
					 | 
				
			||||||
// For example, to use a HMAC-SHA-1 based PBKDF2 key derivation function, you
 | 
					 | 
				
			||||||
// can get a derived key for e.g. AES-256 (which needs a 32-byte key) by
 | 
					 | 
				
			||||||
// doing:
 | 
					 | 
				
			||||||
//
 | 
					 | 
				
			||||||
// 	dk := pbkdf2.Key([]byte("some password"), salt, 4096, 32, sha1.New)
 | 
					 | 
				
			||||||
//
 | 
					 | 
				
			||||||
// Remember to get a good random salt. At least 8 bytes is recommended by the
 | 
					 | 
				
			||||||
// RFC.
 | 
					 | 
				
			||||||
//
 | 
					 | 
				
			||||||
// Using a higher iteration count will increase the cost of an exhaustive
 | 
					 | 
				
			||||||
// search but will also make derivation proportionally slower.
 | 
					 | 
				
			||||||
func Key(password, salt []byte, iter, keyLen int, h func() hash.Hash) []byte {
 | 
					 | 
				
			||||||
	prf := hmac.New(h, password)
 | 
					 | 
				
			||||||
	hashLen := prf.Size()
 | 
					 | 
				
			||||||
	numBlocks := (keyLen + hashLen - 1) / hashLen
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	var buf [4]byte
 | 
					 | 
				
			||||||
	dk := make([]byte, 0, numBlocks*hashLen)
 | 
					 | 
				
			||||||
	U := make([]byte, hashLen)
 | 
					 | 
				
			||||||
	for block := 1; block <= numBlocks; block++ {
 | 
					 | 
				
			||||||
		// N.B.: || means concatenation, ^ means XOR
 | 
					 | 
				
			||||||
		// for each block T_i = U_1 ^ U_2 ^ ... ^ U_iter
 | 
					 | 
				
			||||||
		// U_1 = PRF(password, salt || uint(i))
 | 
					 | 
				
			||||||
		prf.Reset()
 | 
					 | 
				
			||||||
		prf.Write(salt)
 | 
					 | 
				
			||||||
		buf[0] = byte(block >> 24)
 | 
					 | 
				
			||||||
		buf[1] = byte(block >> 16)
 | 
					 | 
				
			||||||
		buf[2] = byte(block >> 8)
 | 
					 | 
				
			||||||
		buf[3] = byte(block)
 | 
					 | 
				
			||||||
		prf.Write(buf[:4])
 | 
					 | 
				
			||||||
		dk = prf.Sum(dk)
 | 
					 | 
				
			||||||
		T := dk[len(dk)-hashLen:]
 | 
					 | 
				
			||||||
		copy(U, T)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		// U_n = PRF(password, U_(n-1))
 | 
					 | 
				
			||||||
		for n := 2; n <= iter; n++ {
 | 
					 | 
				
			||||||
			prf.Reset()
 | 
					 | 
				
			||||||
			prf.Write(U)
 | 
					 | 
				
			||||||
			U = U[:0]
 | 
					 | 
				
			||||||
			U = prf.Sum(U)
 | 
					 | 
				
			||||||
			for x := range U {
 | 
					 | 
				
			||||||
				T[x] ^= U[x]
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	return dk[:keyLen]
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
							
								
								
									
										157
									
								
								Godeps/_workspace/src/code.google.com/p/go.crypto/pbkdf2/pbkdf2_test.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										157
									
								
								Godeps/_workspace/src/code.google.com/p/go.crypto/pbkdf2/pbkdf2_test.go
									
									
									
										generated
									
									
										vendored
									
									
								
							@@ -1,157 +0,0 @@
 | 
				
			|||||||
// Copyright 2012 The Go Authors. All rights reserved.
 | 
					 | 
				
			||||||
// Use of this source code is governed by a BSD-style
 | 
					 | 
				
			||||||
// license that can be found in the LICENSE file.
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
package pbkdf2
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
import (
 | 
					 | 
				
			||||||
	"bytes"
 | 
					 | 
				
			||||||
	"crypto/sha1"
 | 
					 | 
				
			||||||
	"crypto/sha256"
 | 
					 | 
				
			||||||
	"hash"
 | 
					 | 
				
			||||||
	"testing"
 | 
					 | 
				
			||||||
)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
type testVector struct {
 | 
					 | 
				
			||||||
	password string
 | 
					 | 
				
			||||||
	salt     string
 | 
					 | 
				
			||||||
	iter     int
 | 
					 | 
				
			||||||
	output   []byte
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// Test vectors from RFC 6070, http://tools.ietf.org/html/rfc6070
 | 
					 | 
				
			||||||
var sha1TestVectors = []testVector{
 | 
					 | 
				
			||||||
	{
 | 
					 | 
				
			||||||
		"password",
 | 
					 | 
				
			||||||
		"salt",
 | 
					 | 
				
			||||||
		1,
 | 
					 | 
				
			||||||
		[]byte{
 | 
					 | 
				
			||||||
			0x0c, 0x60, 0xc8, 0x0f, 0x96, 0x1f, 0x0e, 0x71,
 | 
					 | 
				
			||||||
			0xf3, 0xa9, 0xb5, 0x24, 0xaf, 0x60, 0x12, 0x06,
 | 
					 | 
				
			||||||
			0x2f, 0xe0, 0x37, 0xa6,
 | 
					 | 
				
			||||||
		},
 | 
					 | 
				
			||||||
	},
 | 
					 | 
				
			||||||
	{
 | 
					 | 
				
			||||||
		"password",
 | 
					 | 
				
			||||||
		"salt",
 | 
					 | 
				
			||||||
		2,
 | 
					 | 
				
			||||||
		[]byte{
 | 
					 | 
				
			||||||
			0xea, 0x6c, 0x01, 0x4d, 0xc7, 0x2d, 0x6f, 0x8c,
 | 
					 | 
				
			||||||
			0xcd, 0x1e, 0xd9, 0x2a, 0xce, 0x1d, 0x41, 0xf0,
 | 
					 | 
				
			||||||
			0xd8, 0xde, 0x89, 0x57,
 | 
					 | 
				
			||||||
		},
 | 
					 | 
				
			||||||
	},
 | 
					 | 
				
			||||||
	{
 | 
					 | 
				
			||||||
		"password",
 | 
					 | 
				
			||||||
		"salt",
 | 
					 | 
				
			||||||
		4096,
 | 
					 | 
				
			||||||
		[]byte{
 | 
					 | 
				
			||||||
			0x4b, 0x00, 0x79, 0x01, 0xb7, 0x65, 0x48, 0x9a,
 | 
					 | 
				
			||||||
			0xbe, 0xad, 0x49, 0xd9, 0x26, 0xf7, 0x21, 0xd0,
 | 
					 | 
				
			||||||
			0x65, 0xa4, 0x29, 0xc1,
 | 
					 | 
				
			||||||
		},
 | 
					 | 
				
			||||||
	},
 | 
					 | 
				
			||||||
	// // This one takes too long
 | 
					 | 
				
			||||||
	// {
 | 
					 | 
				
			||||||
	// 	"password",
 | 
					 | 
				
			||||||
	// 	"salt",
 | 
					 | 
				
			||||||
	// 	16777216,
 | 
					 | 
				
			||||||
	// 	[]byte{
 | 
					 | 
				
			||||||
	// 		0xee, 0xfe, 0x3d, 0x61, 0xcd, 0x4d, 0xa4, 0xe4,
 | 
					 | 
				
			||||||
	// 		0xe9, 0x94, 0x5b, 0x3d, 0x6b, 0xa2, 0x15, 0x8c,
 | 
					 | 
				
			||||||
	// 		0x26, 0x34, 0xe9, 0x84,
 | 
					 | 
				
			||||||
	// 	},
 | 
					 | 
				
			||||||
	// },
 | 
					 | 
				
			||||||
	{
 | 
					 | 
				
			||||||
		"passwordPASSWORDpassword",
 | 
					 | 
				
			||||||
		"saltSALTsaltSALTsaltSALTsaltSALTsalt",
 | 
					 | 
				
			||||||
		4096,
 | 
					 | 
				
			||||||
		[]byte{
 | 
					 | 
				
			||||||
			0x3d, 0x2e, 0xec, 0x4f, 0xe4, 0x1c, 0x84, 0x9b,
 | 
					 | 
				
			||||||
			0x80, 0xc8, 0xd8, 0x36, 0x62, 0xc0, 0xe4, 0x4a,
 | 
					 | 
				
			||||||
			0x8b, 0x29, 0x1a, 0x96, 0x4c, 0xf2, 0xf0, 0x70,
 | 
					 | 
				
			||||||
			0x38,
 | 
					 | 
				
			||||||
		},
 | 
					 | 
				
			||||||
	},
 | 
					 | 
				
			||||||
	{
 | 
					 | 
				
			||||||
		"pass\000word",
 | 
					 | 
				
			||||||
		"sa\000lt",
 | 
					 | 
				
			||||||
		4096,
 | 
					 | 
				
			||||||
		[]byte{
 | 
					 | 
				
			||||||
			0x56, 0xfa, 0x6a, 0xa7, 0x55, 0x48, 0x09, 0x9d,
 | 
					 | 
				
			||||||
			0xcc, 0x37, 0xd7, 0xf0, 0x34, 0x25, 0xe0, 0xc3,
 | 
					 | 
				
			||||||
		},
 | 
					 | 
				
			||||||
	},
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// Test vectors from
 | 
					 | 
				
			||||||
// http://stackoverflow.com/questions/5130513/pbkdf2-hmac-sha2-test-vectors
 | 
					 | 
				
			||||||
var sha256TestVectors = []testVector{
 | 
					 | 
				
			||||||
	{
 | 
					 | 
				
			||||||
		"password",
 | 
					 | 
				
			||||||
		"salt",
 | 
					 | 
				
			||||||
		1,
 | 
					 | 
				
			||||||
		[]byte{
 | 
					 | 
				
			||||||
			0x12, 0x0f, 0xb6, 0xcf, 0xfc, 0xf8, 0xb3, 0x2c,
 | 
					 | 
				
			||||||
			0x43, 0xe7, 0x22, 0x52, 0x56, 0xc4, 0xf8, 0x37,
 | 
					 | 
				
			||||||
			0xa8, 0x65, 0x48, 0xc9,
 | 
					 | 
				
			||||||
		},
 | 
					 | 
				
			||||||
	},
 | 
					 | 
				
			||||||
	{
 | 
					 | 
				
			||||||
		"password",
 | 
					 | 
				
			||||||
		"salt",
 | 
					 | 
				
			||||||
		2,
 | 
					 | 
				
			||||||
		[]byte{
 | 
					 | 
				
			||||||
			0xae, 0x4d, 0x0c, 0x95, 0xaf, 0x6b, 0x46, 0xd3,
 | 
					 | 
				
			||||||
			0x2d, 0x0a, 0xdf, 0xf9, 0x28, 0xf0, 0x6d, 0xd0,
 | 
					 | 
				
			||||||
			0x2a, 0x30, 0x3f, 0x8e,
 | 
					 | 
				
			||||||
		},
 | 
					 | 
				
			||||||
	},
 | 
					 | 
				
			||||||
	{
 | 
					 | 
				
			||||||
		"password",
 | 
					 | 
				
			||||||
		"salt",
 | 
					 | 
				
			||||||
		4096,
 | 
					 | 
				
			||||||
		[]byte{
 | 
					 | 
				
			||||||
			0xc5, 0xe4, 0x78, 0xd5, 0x92, 0x88, 0xc8, 0x41,
 | 
					 | 
				
			||||||
			0xaa, 0x53, 0x0d, 0xb6, 0x84, 0x5c, 0x4c, 0x8d,
 | 
					 | 
				
			||||||
			0x96, 0x28, 0x93, 0xa0,
 | 
					 | 
				
			||||||
		},
 | 
					 | 
				
			||||||
	},
 | 
					 | 
				
			||||||
	{
 | 
					 | 
				
			||||||
		"passwordPASSWORDpassword",
 | 
					 | 
				
			||||||
		"saltSALTsaltSALTsaltSALTsaltSALTsalt",
 | 
					 | 
				
			||||||
		4096,
 | 
					 | 
				
			||||||
		[]byte{
 | 
					 | 
				
			||||||
			0x34, 0x8c, 0x89, 0xdb, 0xcb, 0xd3, 0x2b, 0x2f,
 | 
					 | 
				
			||||||
			0x32, 0xd8, 0x14, 0xb8, 0x11, 0x6e, 0x84, 0xcf,
 | 
					 | 
				
			||||||
			0x2b, 0x17, 0x34, 0x7e, 0xbc, 0x18, 0x00, 0x18,
 | 
					 | 
				
			||||||
			0x1c,
 | 
					 | 
				
			||||||
		},
 | 
					 | 
				
			||||||
	},
 | 
					 | 
				
			||||||
	{
 | 
					 | 
				
			||||||
		"pass\000word",
 | 
					 | 
				
			||||||
		"sa\000lt",
 | 
					 | 
				
			||||||
		4096,
 | 
					 | 
				
			||||||
		[]byte{
 | 
					 | 
				
			||||||
			0x89, 0xb6, 0x9d, 0x05, 0x16, 0xf8, 0x29, 0x89,
 | 
					 | 
				
			||||||
			0x3c, 0x69, 0x62, 0x26, 0x65, 0x0a, 0x86, 0x87,
 | 
					 | 
				
			||||||
		},
 | 
					 | 
				
			||||||
	},
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func testHash(t *testing.T, h func() hash.Hash, hashName string, vectors []testVector) {
 | 
					 | 
				
			||||||
	for i, v := range vectors {
 | 
					 | 
				
			||||||
		o := Key([]byte(v.password), []byte(v.salt), v.iter, len(v.output), h)
 | 
					 | 
				
			||||||
		if !bytes.Equal(o, v.output) {
 | 
					 | 
				
			||||||
			t.Errorf("%s %d: expected %x, got %x", hashName, i, v.output, o)
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func TestWithHMACSHA1(t *testing.T) {
 | 
					 | 
				
			||||||
	testHash(t, sha1.New, "SHA1", sha1TestVectors)
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func TestWithHMACSHA256(t *testing.T) {
 | 
					 | 
				
			||||||
	testHash(t, sha256.New, "SHA256", sha256TestVectors)
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
@@ -3,7 +3,7 @@ goupnp is a UPnP client library for Go
 | 
				
			|||||||
Installation
 | 
					Installation
 | 
				
			||||||
------------
 | 
					------------
 | 
				
			||||||
 | 
					
 | 
				
			||||||
Run `go get -u github.com/fjl/goupnp`.
 | 
					Run `go get -u github.com/huin/goupnp`.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
Regenerating dcps generated source code:
 | 
					Regenerating dcps generated source code:
 | 
				
			||||||
----------------------------------------
 | 
					----------------------------------------
 | 
				
			||||||
@@ -4,7 +4,7 @@ import (
 | 
				
			|||||||
	"log"
 | 
						"log"
 | 
				
			||||||
	"net/http"
 | 
						"net/http"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	"github.com/fjl/goupnp/httpu"
 | 
						"github.com/huin/goupnp/httpu"
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func main() {
 | 
					func main() {
 | 
				
			||||||
@@ -4,7 +4,7 @@ import (
 | 
				
			|||||||
	"fmt"
 | 
						"fmt"
 | 
				
			||||||
	"log"
 | 
						"log"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	"github.com/fjl/goupnp/dcps/internetgateway1"
 | 
						"github.com/huin/goupnp/dcps/internetgateway1"
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func main() {
 | 
					func main() {
 | 
				
			||||||
@@ -11,8 +11,8 @@ package internetgateway1
 | 
				
			|||||||
import (
 | 
					import (
 | 
				
			||||||
	"time"
 | 
						"time"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	"github.com/fjl/goupnp"
 | 
						"github.com/huin/goupnp"
 | 
				
			||||||
	"github.com/fjl/goupnp/soap"
 | 
						"github.com/huin/goupnp/soap"
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// Hack to avoid Go complaining if time isn't used.
 | 
					// Hack to avoid Go complaining if time isn't used.
 | 
				
			||||||
@@ -11,8 +11,8 @@ package internetgateway2
 | 
				
			|||||||
import (
 | 
					import (
 | 
				
			||||||
	"time"
 | 
						"time"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	"github.com/fjl/goupnp"
 | 
						"github.com/huin/goupnp"
 | 
				
			||||||
	"github.com/fjl/goupnp/soap"
 | 
						"github.com/huin/goupnp/soap"
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// Hack to avoid Go complaining if time isn't used.
 | 
					// Hack to avoid Go complaining if time isn't used.
 | 
				
			||||||
@@ -8,8 +8,8 @@ import (
 | 
				
			|||||||
	"fmt"
 | 
						"fmt"
 | 
				
			||||||
	"net/url"
 | 
						"net/url"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	"github.com/fjl/goupnp/scpd"
 | 
						"github.com/huin/goupnp/scpd"
 | 
				
			||||||
	"github.com/fjl/goupnp/soap"
 | 
						"github.com/huin/goupnp/soap"
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const (
 | 
					const (
 | 
				
			||||||
@@ -2,5 +2,5 @@
 | 
				
			|||||||
//
 | 
					//
 | 
				
			||||||
// To run examples and see the output for your local network, run the following
 | 
					// To run examples and see the output for your local network, run the following
 | 
				
			||||||
// command (specifically including the -v flag):
 | 
					// command (specifically including the -v flag):
 | 
				
			||||||
//     go test -v github.com/fjl/goupnp/example
 | 
					//     go test -v github.com/huin/goupnp/example
 | 
				
			||||||
package example
 | 
					package example
 | 
				
			||||||
@@ -4,8 +4,8 @@ import (
 | 
				
			|||||||
	"fmt"
 | 
						"fmt"
 | 
				
			||||||
	"os"
 | 
						"os"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	"github.com/fjl/goupnp"
 | 
						"github.com/huin/goupnp"
 | 
				
			||||||
	"github.com/fjl/goupnp/dcps/internetgateway1"
 | 
						"github.com/huin/goupnp/dcps/internetgateway1"
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// Use discovered WANPPPConnection1 services to find external IP addresses.
 | 
					// Use discovered WANPPPConnection1 services to find external IP addresses.
 | 
				
			||||||
@@ -17,8 +17,8 @@ import (
 | 
				
			|||||||
	"strings"
 | 
						"strings"
 | 
				
			||||||
	"text/template"
 | 
						"text/template"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	"github.com/fjl/goupnp"
 | 
						"github.com/huin/goupnp"
 | 
				
			||||||
	"github.com/fjl/goupnp/scpd"
 | 
						"github.com/huin/goupnp/scpd"
 | 
				
			||||||
	"github.com/huin/goutil/codegen"
 | 
						"github.com/huin/goutil/codegen"
 | 
				
			||||||
	"github.com/jingweno/gotask/tasking"
 | 
						"github.com/jingweno/gotask/tasking"
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
@@ -38,7 +38,7 @@ var (
 | 
				
			|||||||
//   -s, --spec_filename=<upnpresources.zip>
 | 
					//   -s, --spec_filename=<upnpresources.zip>
 | 
				
			||||||
//     Path to the specification file, available from http://upnp.org/resources/upnpresources.zip
 | 
					//     Path to the specification file, available from http://upnp.org/resources/upnpresources.zip
 | 
				
			||||||
//   -o, --out_dir=<output directory>
 | 
					//   -o, --out_dir=<output directory>
 | 
				
			||||||
//     Path to the output directory. This is is where the DCP source files will be placed. Should normally correspond to the directory for github.com/fjl/goupnp/dcps
 | 
					//     Path to the output directory. This is is where the DCP source files will be placed. Should normally correspond to the directory for github.com/huin/goupnp/dcps
 | 
				
			||||||
//   --nogofmt
 | 
					//   --nogofmt
 | 
				
			||||||
//     Disable passing the output through gofmt. Do this if debugging code output problems and needing to see the generated code prior to being passed through gofmt.
 | 
					//     Disable passing the output through gofmt. Do this if debugging code output problems and needing to see the generated code prior to being passed through gofmt.
 | 
				
			||||||
func TaskSpecgen(t *tasking.T) {
 | 
					func TaskSpecgen(t *tasking.T) {
 | 
				
			||||||
@@ -445,8 +445,8 @@ package {{$name}}
 | 
				
			|||||||
import (
 | 
					import (
 | 
				
			||||||
	"time"
 | 
						"time"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	"github.com/fjl/goupnp"
 | 
						"github.com/huin/goupnp"
 | 
				
			||||||
	"github.com/fjl/goupnp/soap"
 | 
						"github.com/huin/goupnp/soap"
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// Hack to avoid Go complaining if time isn't used.
 | 
					// Hack to avoid Go complaining if time isn't used.
 | 
				
			||||||
@@ -1,11 +1,11 @@
 | 
				
			|||||||
// goupnp is an implementation of a client for various UPnP services.
 | 
					// goupnp is an implementation of a client for various UPnP services.
 | 
				
			||||||
//
 | 
					//
 | 
				
			||||||
// For most uses, it is recommended to use the code-generated packages under
 | 
					// For most uses, it is recommended to use the code-generated packages under
 | 
				
			||||||
// github.com/fjl/goupnp/dcps. Example use is shown at
 | 
					// github.com/huin/goupnp/dcps. Example use is shown at
 | 
				
			||||||
// http://godoc.org/github.com/fjl/goupnp/example
 | 
					// http://godoc.org/github.com/huin/goupnp/example
 | 
				
			||||||
//
 | 
					//
 | 
				
			||||||
// A commonly used client is internetgateway1.WANPPPConnection1:
 | 
					// A commonly used client is internetgateway1.WANPPPConnection1:
 | 
				
			||||||
// http://godoc.org/github.com/fjl/goupnp/dcps/internetgateway1#WANPPPConnection1
 | 
					// http://godoc.org/github.com/huin/goupnp/dcps/internetgateway1#WANPPPConnection1
 | 
				
			||||||
//
 | 
					//
 | 
				
			||||||
// Currently only a couple of schemas have code generated for them from the
 | 
					// Currently only a couple of schemas have code generated for them from the
 | 
				
			||||||
// UPnP example XML specifications. Not all methods will work on these clients,
 | 
					// UPnP example XML specifications. Not all methods will work on these clients,
 | 
				
			||||||
@@ -20,8 +20,8 @@ import (
 | 
				
			|||||||
	"net/http"
 | 
						"net/http"
 | 
				
			||||||
	"net/url"
 | 
						"net/url"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	"github.com/fjl/goupnp/httpu"
 | 
						"github.com/huin/goupnp/httpu"
 | 
				
			||||||
	"github.com/fjl/goupnp/ssdp"
 | 
						"github.com/huin/goupnp/ssdp"
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// ContextError is an error that wraps an error with some context information.
 | 
					// ContextError is an error that wraps an error with some context information.
 | 
				
			||||||
@@ -2,8 +2,7 @@ package goupnp
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
import (
 | 
					import (
 | 
				
			||||||
	"fmt"
 | 
						"fmt"
 | 
				
			||||||
 | 
						"github.com/huin/goupnp/soap"
 | 
				
			||||||
	"github.com/fjl/goupnp/soap"
 | 
					 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// ServiceClient is a SOAP client, root device and the service for the SOAP
 | 
					// ServiceClient is a SOAP client, root device and the service for the SOAP
 | 
				
			||||||
@@ -10,7 +10,7 @@ import (
 | 
				
			|||||||
	"sync"
 | 
						"sync"
 | 
				
			||||||
	"time"
 | 
						"time"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	"github.com/fjl/goupnp/httpu"
 | 
						"github.com/huin/goupnp/httpu"
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const (
 | 
					const (
 | 
				
			||||||
@@ -8,7 +8,7 @@ import (
 | 
				
			|||||||
	"strconv"
 | 
						"strconv"
 | 
				
			||||||
	"time"
 | 
						"time"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	"github.com/fjl/goupnp/httpu"
 | 
						"github.com/huin/goupnp/httpu"
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const (
 | 
					const (
 | 
				
			||||||
							
								
								
									
										24
									
								
								Godeps/_workspace/src/github.com/obscuren/ecies/.gitignore
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										24
									
								
								Godeps/_workspace/src/github.com/obscuren/ecies/.gitignore
									
									
									
										generated
									
									
										vendored
									
									
								
							@@ -1,24 +0,0 @@
 | 
				
			|||||||
# 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
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
*~
 | 
					 | 
				
			||||||
							
								
								
									
										28
									
								
								Godeps/_workspace/src/github.com/obscuren/ecies/LICENSE
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										28
									
								
								Godeps/_workspace/src/github.com/obscuren/ecies/LICENSE
									
									
									
										generated
									
									
										vendored
									
									
								
							@@ -1,28 +0,0 @@
 | 
				
			|||||||
Copyright (c) 2013 Kyle Isom <kyle@tyrfingr.is>
 | 
					 | 
				
			||||||
Copyright (c) 2012 The Go Authors. All rights reserved.
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
Redistribution and use in source and binary forms, with or without
 | 
					 | 
				
			||||||
modification, are permitted provided that the following conditions are
 | 
					 | 
				
			||||||
met:
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
   * Redistributions of source code must retain the above copyright
 | 
					 | 
				
			||||||
notice, this list of conditions and the following disclaimer.
 | 
					 | 
				
			||||||
   * Redistributions in binary form must reproduce the above
 | 
					 | 
				
			||||||
copyright notice, this list of conditions and the following disclaimer
 | 
					 | 
				
			||||||
in the documentation and/or other materials provided with the
 | 
					 | 
				
			||||||
distribution.
 | 
					 | 
				
			||||||
   * Neither the name of Google Inc. nor the names of its
 | 
					 | 
				
			||||||
contributors may be used to endorse or promote products derived from
 | 
					 | 
				
			||||||
this software without specific prior written permission.
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 | 
					 | 
				
			||||||
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 | 
					 | 
				
			||||||
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 | 
					 | 
				
			||||||
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 | 
					 | 
				
			||||||
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 | 
					 | 
				
			||||||
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 | 
					 | 
				
			||||||
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 | 
					 | 
				
			||||||
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 | 
					 | 
				
			||||||
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 | 
					 | 
				
			||||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 | 
					 | 
				
			||||||
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 | 
					 | 
				
			||||||
							
								
								
									
										94
									
								
								Godeps/_workspace/src/github.com/obscuren/ecies/README
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										94
									
								
								Godeps/_workspace/src/github.com/obscuren/ecies/README
									
									
									
										generated
									
									
										vendored
									
									
								
							@@ -1,94 +0,0 @@
 | 
				
			|||||||
# NOTE
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
This implementation is direct fork of Kylom's implementation. I claim no authorship over this code apart from some minor modifications.
 | 
					 | 
				
			||||||
Please be aware this code **has not yet been reviewed**.
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
ecies implements the Elliptic Curve Integrated Encryption Scheme.
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
The package is designed to be compliant with the appropriate NIST
 | 
					 | 
				
			||||||
standards, and therefore doesn't support the full SEC 1 algorithm set.
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
STATUS:
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
ecies should be ready for use. The ASN.1 support is only complete so
 | 
					 | 
				
			||||||
far as to supported the listed algorithms before.
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
CAVEATS
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
1. CMAC support is currently not present.
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
SUPPORTED ALGORITHMS
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        SYMMETRIC CIPHERS               HASH FUNCTIONS
 | 
					 | 
				
			||||||
             AES128                         SHA-1
 | 
					 | 
				
			||||||
             AES192                        SHA-224
 | 
					 | 
				
			||||||
             AES256                        SHA-256
 | 
					 | 
				
			||||||
                                           SHA-384
 | 
					 | 
				
			||||||
        ELLIPTIC CURVE                     SHA-512
 | 
					 | 
				
			||||||
             P256
 | 
					 | 
				
			||||||
             P384		    KEY DERIVATION FUNCTION
 | 
					 | 
				
			||||||
             P521	       NIST SP 800-65a Concatenation KDF
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
Curve P224 isn't supported because it does not provide a minimum security
 | 
					 | 
				
			||||||
level of AES128 with HMAC-SHA1. According to NIST SP 800-57, the security
 | 
					 | 
				
			||||||
level of P224 is 112 bits of security. Symmetric ciphers use CTR-mode;
 | 
					 | 
				
			||||||
message tags are computed using HMAC-<HASH> function.
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
CURVE SELECTION
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
According to NIST SP 800-57, the following curves should be selected:
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    +----------------+-------+
 | 
					 | 
				
			||||||
    | SYMMETRIC SIZE | CURVE |
 | 
					 | 
				
			||||||
    +----------------+-------+
 | 
					 | 
				
			||||||
    |     128-bit    |  P256 |
 | 
					 | 
				
			||||||
    +----------------+-------+
 | 
					 | 
				
			||||||
    |     192-bit    |  P384 |
 | 
					 | 
				
			||||||
    +----------------+-------+
 | 
					 | 
				
			||||||
    |     256-bit    |  P521 |
 | 
					 | 
				
			||||||
    +----------------+-------+
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
TODO
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
1. Look at serialising the parameters with the SEC 1 ASN.1 module.
 | 
					 | 
				
			||||||
2. Validate ASN.1 formats with SEC 1.
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
TEST VECTORS
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
The only test vectors I've found so far date from 1993, predating AES
 | 
					 | 
				
			||||||
and including only 163-bit curves. Therefore, there are no published
 | 
					 | 
				
			||||||
test vectors to compare to.
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
LICENSE
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
ecies is released under the same license as the Go source code. See the
 | 
					 | 
				
			||||||
LICENSE file for details.
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
REFERENCES
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
* SEC (Standard for Efficient Cryptography) 1, version 2.0: Elliptic
 | 
					 | 
				
			||||||
  Curve Cryptography; Certicom, May 2009.
 | 
					 | 
				
			||||||
  http://www.secg.org/sec1-v2.pdf
 | 
					 | 
				
			||||||
* GEC (Guidelines for Efficient Cryptography) 2, version 0.3: Test
 | 
					 | 
				
			||||||
  Vectors for SEC 1; Certicom, September 1999.
 | 
					 | 
				
			||||||
  http://read.pudn.com/downloads168/doc/772358/TestVectorsforSEC%201-gec2.pdf
 | 
					 | 
				
			||||||
* NIST SP 800-56a: Recommendation for Pair-Wise Key Establishment Schemes
 | 
					 | 
				
			||||||
  Using Discrete Logarithm Cryptography. National Institute of Standards
 | 
					 | 
				
			||||||
  and Technology, May 2007.
 | 
					 | 
				
			||||||
  http://csrc.nist.gov/publications/nistpubs/800-56A/SP800-56A_Revision1_Mar08-2007.pdf
 | 
					 | 
				
			||||||
* Suite B Implementer’s Guide to NIST SP 800-56A. National Security
 | 
					 | 
				
			||||||
  Agency, July 28, 2009.
 | 
					 | 
				
			||||||
  http://www.nsa.gov/ia/_files/SuiteB_Implementer_G-113808.pdf
 | 
					 | 
				
			||||||
* NIST SP 800-57: Recommendation for Key Management – Part 1: General
 | 
					 | 
				
			||||||
  (Revision 3). National Institute of Standards and Technology, July
 | 
					 | 
				
			||||||
  2012.
 | 
					 | 
				
			||||||
  http://csrc.nist.gov/publications/nistpubs/800-57/sp800-57_part1_rev3_general.pdf
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
							
								
								
									
										556
									
								
								Godeps/_workspace/src/github.com/obscuren/ecies/asn1.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										556
									
								
								Godeps/_workspace/src/github.com/obscuren/ecies/asn1.go
									
									
									
										generated
									
									
										vendored
									
									
								
							@@ -1,556 +0,0 @@
 | 
				
			|||||||
package ecies
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
import (
 | 
					 | 
				
			||||||
	"bytes"
 | 
					 | 
				
			||||||
	"crypto"
 | 
					 | 
				
			||||||
	"crypto/elliptic"
 | 
					 | 
				
			||||||
	"crypto/sha1"
 | 
					 | 
				
			||||||
	"crypto/sha256"
 | 
					 | 
				
			||||||
	"crypto/sha512"
 | 
					 | 
				
			||||||
	"encoding/asn1"
 | 
					 | 
				
			||||||
	"encoding/pem"
 | 
					 | 
				
			||||||
	"fmt"
 | 
					 | 
				
			||||||
	"hash"
 | 
					 | 
				
			||||||
	"math/big"
 | 
					 | 
				
			||||||
)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
var (
 | 
					 | 
				
			||||||
	secgScheme     = []int{1, 3, 132, 1}
 | 
					 | 
				
			||||||
	shaScheme      = []int{2, 16, 840, 1, 101, 3, 4, 2}
 | 
					 | 
				
			||||||
	ansiX962Scheme = []int{1, 2, 840, 10045}
 | 
					 | 
				
			||||||
	x963Scheme     = []int{1, 2, 840, 63, 0}
 | 
					 | 
				
			||||||
)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
var ErrInvalidPrivateKey = fmt.Errorf("ecies: invalid private key")
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func doScheme(base, v []int) asn1.ObjectIdentifier {
 | 
					 | 
				
			||||||
	var oidInts asn1.ObjectIdentifier
 | 
					 | 
				
			||||||
	oidInts = append(oidInts, base...)
 | 
					 | 
				
			||||||
	return append(oidInts, v...)
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// curve OID code taken from crypto/x509, including
 | 
					 | 
				
			||||||
//	- oidNameCurve*
 | 
					 | 
				
			||||||
//	- namedCurveFromOID
 | 
					 | 
				
			||||||
//	- oidFromNamedCurve
 | 
					 | 
				
			||||||
// RFC 5480, 2.1.1.1. Named Curve
 | 
					 | 
				
			||||||
//
 | 
					 | 
				
			||||||
// secp224r1 OBJECT IDENTIFIER ::= {
 | 
					 | 
				
			||||||
//   iso(1) identified-organization(3) certicom(132) curve(0) 33 }
 | 
					 | 
				
			||||||
//
 | 
					 | 
				
			||||||
// secp256r1 OBJECT IDENTIFIER ::= {
 | 
					 | 
				
			||||||
//   iso(1) member-body(2) us(840) ansi-X9-62(10045) curves(3)
 | 
					 | 
				
			||||||
//   prime(1) 7 }
 | 
					 | 
				
			||||||
//
 | 
					 | 
				
			||||||
// secp384r1 OBJECT IDENTIFIER ::= {
 | 
					 | 
				
			||||||
//   iso(1) identified-organization(3) certicom(132) curve(0) 34 }
 | 
					 | 
				
			||||||
//
 | 
					 | 
				
			||||||
// secp521r1 OBJECT IDENTIFIER ::= {
 | 
					 | 
				
			||||||
//   iso(1) identified-organization(3) certicom(132) curve(0) 35 }
 | 
					 | 
				
			||||||
//
 | 
					 | 
				
			||||||
// NB: secp256r1 is equivalent to prime256v1
 | 
					 | 
				
			||||||
type secgNamedCurve asn1.ObjectIdentifier
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
var (
 | 
					 | 
				
			||||||
	secgNamedCurveP224 = secgNamedCurve{1, 3, 132, 0, 33}
 | 
					 | 
				
			||||||
	secgNamedCurveP256 = secgNamedCurve{1, 2, 840, 10045, 3, 1, 7}
 | 
					 | 
				
			||||||
	secgNamedCurveP384 = secgNamedCurve{1, 3, 132, 0, 34}
 | 
					 | 
				
			||||||
	secgNamedCurveP521 = secgNamedCurve{1, 3, 132, 0, 35}
 | 
					 | 
				
			||||||
	rawCurveP224       = []byte{6, 5, 4, 3, 1, 2, 9, 4, 0, 3, 3}
 | 
					 | 
				
			||||||
	rawCurveP256       = []byte{6, 8, 4, 2, 1, 3, 4, 7, 2, 2, 0, 6, 6, 1, 3, 1, 7}
 | 
					 | 
				
			||||||
	rawCurveP384       = []byte{6, 5, 4, 3, 1, 2, 9, 4, 0, 3, 4}
 | 
					 | 
				
			||||||
	rawCurveP521       = []byte{6, 5, 4, 3, 1, 2, 9, 4, 0, 3, 5}
 | 
					 | 
				
			||||||
)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func rawCurve(curve elliptic.Curve) []byte {
 | 
					 | 
				
			||||||
	switch curve {
 | 
					 | 
				
			||||||
	case elliptic.P224():
 | 
					 | 
				
			||||||
		return rawCurveP224
 | 
					 | 
				
			||||||
	case elliptic.P256():
 | 
					 | 
				
			||||||
		return rawCurveP256
 | 
					 | 
				
			||||||
	case elliptic.P384():
 | 
					 | 
				
			||||||
		return rawCurveP384
 | 
					 | 
				
			||||||
	case elliptic.P521():
 | 
					 | 
				
			||||||
		return rawCurveP521
 | 
					 | 
				
			||||||
	default:
 | 
					 | 
				
			||||||
		return nil
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func (curve secgNamedCurve) Equal(curve2 secgNamedCurve) bool {
 | 
					 | 
				
			||||||
	if len(curve) != len(curve2) {
 | 
					 | 
				
			||||||
		return false
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	for i, _ := range curve {
 | 
					 | 
				
			||||||
		if curve[i] != curve2[i] {
 | 
					 | 
				
			||||||
			return false
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	return true
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func namedCurveFromOID(curve secgNamedCurve) elliptic.Curve {
 | 
					 | 
				
			||||||
	switch {
 | 
					 | 
				
			||||||
	case curve.Equal(secgNamedCurveP224):
 | 
					 | 
				
			||||||
		return elliptic.P224()
 | 
					 | 
				
			||||||
	case curve.Equal(secgNamedCurveP256):
 | 
					 | 
				
			||||||
		return elliptic.P256()
 | 
					 | 
				
			||||||
	case curve.Equal(secgNamedCurveP384):
 | 
					 | 
				
			||||||
		return elliptic.P384()
 | 
					 | 
				
			||||||
	case curve.Equal(secgNamedCurveP521):
 | 
					 | 
				
			||||||
		return elliptic.P521()
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	return nil
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func oidFromNamedCurve(curve elliptic.Curve) (secgNamedCurve, bool) {
 | 
					 | 
				
			||||||
	switch curve {
 | 
					 | 
				
			||||||
	case elliptic.P224():
 | 
					 | 
				
			||||||
		return secgNamedCurveP224, true
 | 
					 | 
				
			||||||
	case elliptic.P256():
 | 
					 | 
				
			||||||
		return secgNamedCurveP256, true
 | 
					 | 
				
			||||||
	case elliptic.P384():
 | 
					 | 
				
			||||||
		return secgNamedCurveP384, true
 | 
					 | 
				
			||||||
	case elliptic.P521():
 | 
					 | 
				
			||||||
		return secgNamedCurveP521, true
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	return nil, false
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// asnAlgorithmIdentifier represents the ASN.1 structure of the same name. See RFC
 | 
					 | 
				
			||||||
// 5280, section 4.1.1.2.
 | 
					 | 
				
			||||||
type asnAlgorithmIdentifier struct {
 | 
					 | 
				
			||||||
	Algorithm  asn1.ObjectIdentifier
 | 
					 | 
				
			||||||
	Parameters asn1.RawValue `asn1:"optional"`
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func (a asnAlgorithmIdentifier) Cmp(b asnAlgorithmIdentifier) bool {
 | 
					 | 
				
			||||||
	if len(a.Algorithm) != len(b.Algorithm) {
 | 
					 | 
				
			||||||
		return false
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	for i, _ := range a.Algorithm {
 | 
					 | 
				
			||||||
		if a.Algorithm[i] != b.Algorithm[i] {
 | 
					 | 
				
			||||||
			return false
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	return true
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
type asnHashFunction asnAlgorithmIdentifier
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
var (
 | 
					 | 
				
			||||||
	oidSHA1   = asn1.ObjectIdentifier{1, 3, 14, 3, 2, 26}
 | 
					 | 
				
			||||||
	oidSHA224 = doScheme(shaScheme, []int{4})
 | 
					 | 
				
			||||||
	oidSHA256 = doScheme(shaScheme, []int{1})
 | 
					 | 
				
			||||||
	oidSHA384 = doScheme(shaScheme, []int{2})
 | 
					 | 
				
			||||||
	oidSHA512 = doScheme(shaScheme, []int{3})
 | 
					 | 
				
			||||||
)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func hashFromOID(oid asn1.ObjectIdentifier) func() hash.Hash {
 | 
					 | 
				
			||||||
	switch {
 | 
					 | 
				
			||||||
	case oid.Equal(oidSHA1):
 | 
					 | 
				
			||||||
		return sha1.New
 | 
					 | 
				
			||||||
	case oid.Equal(oidSHA224):
 | 
					 | 
				
			||||||
		return sha256.New224
 | 
					 | 
				
			||||||
	case oid.Equal(oidSHA256):
 | 
					 | 
				
			||||||
		return sha256.New
 | 
					 | 
				
			||||||
	case oid.Equal(oidSHA384):
 | 
					 | 
				
			||||||
		return sha512.New384
 | 
					 | 
				
			||||||
	case oid.Equal(oidSHA512):
 | 
					 | 
				
			||||||
		return sha512.New
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	return nil
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func oidFromHash(hash crypto.Hash) (asn1.ObjectIdentifier, bool) {
 | 
					 | 
				
			||||||
	switch hash {
 | 
					 | 
				
			||||||
	case crypto.SHA1:
 | 
					 | 
				
			||||||
		return oidSHA1, true
 | 
					 | 
				
			||||||
	case crypto.SHA224:
 | 
					 | 
				
			||||||
		return oidSHA224, true
 | 
					 | 
				
			||||||
	case crypto.SHA256:
 | 
					 | 
				
			||||||
		return oidSHA256, true
 | 
					 | 
				
			||||||
	case crypto.SHA384:
 | 
					 | 
				
			||||||
		return oidSHA384, true
 | 
					 | 
				
			||||||
	case crypto.SHA512:
 | 
					 | 
				
			||||||
		return oidSHA512, true
 | 
					 | 
				
			||||||
	default:
 | 
					 | 
				
			||||||
		return nil, false
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
var (
 | 
					 | 
				
			||||||
	asnAlgoSHA1 = asnHashFunction{
 | 
					 | 
				
			||||||
		Algorithm: oidSHA1,
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	asnAlgoSHA224 = asnHashFunction{
 | 
					 | 
				
			||||||
		Algorithm: oidSHA224,
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	asnAlgoSHA256 = asnHashFunction{
 | 
					 | 
				
			||||||
		Algorithm: oidSHA256,
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	asnAlgoSHA384 = asnHashFunction{
 | 
					 | 
				
			||||||
		Algorithm: oidSHA384,
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	asnAlgoSHA512 = asnHashFunction{
 | 
					 | 
				
			||||||
		Algorithm: oidSHA512,
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// type ASNasnSubjectPublicKeyInfo struct {
 | 
					 | 
				
			||||||
//
 | 
					 | 
				
			||||||
// }
 | 
					 | 
				
			||||||
//
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
type asnSubjectPublicKeyInfo struct {
 | 
					 | 
				
			||||||
	Algorithm   asn1.ObjectIdentifier
 | 
					 | 
				
			||||||
	PublicKey   asn1.BitString
 | 
					 | 
				
			||||||
	Supplements ecpksSupplements `asn1:"optional"`
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
type asnECPKAlgorithms struct {
 | 
					 | 
				
			||||||
	Type asn1.ObjectIdentifier
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
var idPublicKeyType = doScheme(ansiX962Scheme, []int{2})
 | 
					 | 
				
			||||||
var idEcPublicKey = doScheme(idPublicKeyType, []int{1})
 | 
					 | 
				
			||||||
var idEcPublicKeySupplemented = doScheme(idPublicKeyType, []int{0})
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func curveToRaw(curve elliptic.Curve) (rv asn1.RawValue, ok bool) {
 | 
					 | 
				
			||||||
	switch curve {
 | 
					 | 
				
			||||||
	case elliptic.P224(), elliptic.P256(), elliptic.P384(), elliptic.P521():
 | 
					 | 
				
			||||||
		raw := rawCurve(curve)
 | 
					 | 
				
			||||||
		return asn1.RawValue{
 | 
					 | 
				
			||||||
			Tag:       30,
 | 
					 | 
				
			||||||
			Bytes:     raw[2:],
 | 
					 | 
				
			||||||
			FullBytes: raw,
 | 
					 | 
				
			||||||
		}, true
 | 
					 | 
				
			||||||
	default:
 | 
					 | 
				
			||||||
		return rv, false
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func asnECPublicKeyType(curve elliptic.Curve) (algo asnAlgorithmIdentifier, ok bool) {
 | 
					 | 
				
			||||||
	raw, ok := curveToRaw(curve)
 | 
					 | 
				
			||||||
	if !ok {
 | 
					 | 
				
			||||||
		return
 | 
					 | 
				
			||||||
	} else {
 | 
					 | 
				
			||||||
		return asnAlgorithmIdentifier{Algorithm: idEcPublicKey,
 | 
					 | 
				
			||||||
			Parameters: raw}, true
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
type asnECPrivKeyVer int
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
var asnECPrivKeyVer1 asnECPrivKeyVer = 1
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
type asnPrivateKey struct {
 | 
					 | 
				
			||||||
	Version asnECPrivKeyVer
 | 
					 | 
				
			||||||
	Private []byte
 | 
					 | 
				
			||||||
	Curve   secgNamedCurve `asn1:"optional"`
 | 
					 | 
				
			||||||
	Public  asn1.BitString
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
var asnECDH = doScheme(secgScheme, []int{12})
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
type asnECDHAlgorithm asnAlgorithmIdentifier
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
var (
 | 
					 | 
				
			||||||
	dhSinglePass_stdDH_sha1kdf = asnECDHAlgorithm{
 | 
					 | 
				
			||||||
		Algorithm: doScheme(x963Scheme, []int{2}),
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	dhSinglePass_stdDH_sha256kdf = asnECDHAlgorithm{
 | 
					 | 
				
			||||||
		Algorithm: doScheme(secgScheme, []int{11, 1}),
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	dhSinglePass_stdDH_sha384kdf = asnECDHAlgorithm{
 | 
					 | 
				
			||||||
		Algorithm: doScheme(secgScheme, []int{11, 2}),
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	dhSinglePass_stdDH_sha224kdf = asnECDHAlgorithm{
 | 
					 | 
				
			||||||
		Algorithm: doScheme(secgScheme, []int{11, 0}),
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	dhSinglePass_stdDH_sha512kdf = asnECDHAlgorithm{
 | 
					 | 
				
			||||||
		Algorithm: doScheme(secgScheme, []int{11, 3}),
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func (a asnECDHAlgorithm) Cmp(b asnECDHAlgorithm) bool {
 | 
					 | 
				
			||||||
	if len(a.Algorithm) != len(b.Algorithm) {
 | 
					 | 
				
			||||||
		return false
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	for i, _ := range a.Algorithm {
 | 
					 | 
				
			||||||
		if a.Algorithm[i] != b.Algorithm[i] {
 | 
					 | 
				
			||||||
			return false
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	return true
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// asnNISTConcatenation is the only supported KDF at this time.
 | 
					 | 
				
			||||||
type asnKeyDerivationFunction asnAlgorithmIdentifier
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
var asnNISTConcatenationKDF = asnKeyDerivationFunction{
 | 
					 | 
				
			||||||
	Algorithm: doScheme(secgScheme, []int{17, 1}),
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func (a asnKeyDerivationFunction) Cmp(b asnKeyDerivationFunction) bool {
 | 
					 | 
				
			||||||
	if len(a.Algorithm) != len(b.Algorithm) {
 | 
					 | 
				
			||||||
		return false
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	for i, _ := range a.Algorithm {
 | 
					 | 
				
			||||||
		if a.Algorithm[i] != b.Algorithm[i] {
 | 
					 | 
				
			||||||
			return false
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	return true
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
var eciesRecommendedParameters = doScheme(secgScheme, []int{7})
 | 
					 | 
				
			||||||
var eciesSpecifiedParameters = doScheme(secgScheme, []int{8})
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
type asnECIESParameters struct {
 | 
					 | 
				
			||||||
	KDF asnKeyDerivationFunction     `asn1:"optional"`
 | 
					 | 
				
			||||||
	Sym asnSymmetricEncryption       `asn1:"optional"`
 | 
					 | 
				
			||||||
	MAC asnMessageAuthenticationCode `asn1:"optional"`
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
type asnSymmetricEncryption asnAlgorithmIdentifier
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
var (
 | 
					 | 
				
			||||||
	aes128CTRinECIES = asnSymmetricEncryption{
 | 
					 | 
				
			||||||
		Algorithm: doScheme(secgScheme, []int{21, 0}),
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	aes192CTRinECIES = asnSymmetricEncryption{
 | 
					 | 
				
			||||||
		Algorithm: doScheme(secgScheme, []int{21, 1}),
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	aes256CTRinECIES = asnSymmetricEncryption{
 | 
					 | 
				
			||||||
		Algorithm: doScheme(secgScheme, []int{21, 2}),
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func (a asnSymmetricEncryption) Cmp(b asnSymmetricEncryption) bool {
 | 
					 | 
				
			||||||
	if len(a.Algorithm) != len(b.Algorithm) {
 | 
					 | 
				
			||||||
		return false
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	for i, _ := range a.Algorithm {
 | 
					 | 
				
			||||||
		if a.Algorithm[i] != b.Algorithm[i] {
 | 
					 | 
				
			||||||
			return false
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	return true
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
type asnMessageAuthenticationCode asnAlgorithmIdentifier
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
var (
 | 
					 | 
				
			||||||
	hmacFull = asnMessageAuthenticationCode{
 | 
					 | 
				
			||||||
		Algorithm: doScheme(secgScheme, []int{22}),
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func (a asnMessageAuthenticationCode) Cmp(b asnMessageAuthenticationCode) bool {
 | 
					 | 
				
			||||||
	if len(a.Algorithm) != len(b.Algorithm) {
 | 
					 | 
				
			||||||
		return false
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	for i, _ := range a.Algorithm {
 | 
					 | 
				
			||||||
		if a.Algorithm[i] != b.Algorithm[i] {
 | 
					 | 
				
			||||||
			return false
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	return true
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
type ecpksSupplements struct {
 | 
					 | 
				
			||||||
	ECDomain      secgNamedCurve
 | 
					 | 
				
			||||||
	ECCAlgorithms eccAlgorithmSet
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
type eccAlgorithmSet struct {
 | 
					 | 
				
			||||||
	ECDH  asnECDHAlgorithm   `asn1:"optional"`
 | 
					 | 
				
			||||||
	ECIES asnECIESParameters `asn1:"optional"`
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func marshalSubjectPublicKeyInfo(pub *PublicKey) (subj asnSubjectPublicKeyInfo, err error) {
 | 
					 | 
				
			||||||
	subj.Algorithm = idEcPublicKeySupplemented
 | 
					 | 
				
			||||||
	curve, ok := oidFromNamedCurve(pub.Curve)
 | 
					 | 
				
			||||||
	if !ok {
 | 
					 | 
				
			||||||
		err = ErrInvalidPublicKey
 | 
					 | 
				
			||||||
		return
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	subj.Supplements.ECDomain = curve
 | 
					 | 
				
			||||||
	if pub.Params != nil {
 | 
					 | 
				
			||||||
		subj.Supplements.ECCAlgorithms.ECDH = paramsToASNECDH(pub.Params)
 | 
					 | 
				
			||||||
		subj.Supplements.ECCAlgorithms.ECIES = paramsToASNECIES(pub.Params)
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	pubkey := elliptic.Marshal(pub.Curve, pub.X, pub.Y)
 | 
					 | 
				
			||||||
	subj.PublicKey = asn1.BitString{
 | 
					 | 
				
			||||||
		BitLength: len(pubkey) * 8,
 | 
					 | 
				
			||||||
		Bytes:     pubkey,
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	return
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// Encode a public key to DER format.
 | 
					 | 
				
			||||||
func MarshalPublic(pub *PublicKey) ([]byte, error) {
 | 
					 | 
				
			||||||
	subj, err := marshalSubjectPublicKeyInfo(pub)
 | 
					 | 
				
			||||||
	if err != nil {
 | 
					 | 
				
			||||||
		return nil, err
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	return asn1.Marshal(subj)
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// Decode a DER-encoded public key.
 | 
					 | 
				
			||||||
func UnmarshalPublic(in []byte) (pub *PublicKey, err error) {
 | 
					 | 
				
			||||||
	var subj asnSubjectPublicKeyInfo
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	if _, err = asn1.Unmarshal(in, &subj); err != nil {
 | 
					 | 
				
			||||||
		return
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	if !subj.Algorithm.Equal(idEcPublicKeySupplemented) {
 | 
					 | 
				
			||||||
		err = ErrInvalidPublicKey
 | 
					 | 
				
			||||||
		return
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	pub = new(PublicKey)
 | 
					 | 
				
			||||||
	pub.Curve = namedCurveFromOID(subj.Supplements.ECDomain)
 | 
					 | 
				
			||||||
	x, y := elliptic.Unmarshal(pub.Curve, subj.PublicKey.Bytes)
 | 
					 | 
				
			||||||
	if x == nil {
 | 
					 | 
				
			||||||
		err = ErrInvalidPublicKey
 | 
					 | 
				
			||||||
		return
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	pub.X = x
 | 
					 | 
				
			||||||
	pub.Y = y
 | 
					 | 
				
			||||||
	pub.Params = new(ECIESParams)
 | 
					 | 
				
			||||||
	asnECIEStoParams(subj.Supplements.ECCAlgorithms.ECIES, pub.Params)
 | 
					 | 
				
			||||||
	asnECDHtoParams(subj.Supplements.ECCAlgorithms.ECDH, pub.Params)
 | 
					 | 
				
			||||||
	if pub.Params == nil {
 | 
					 | 
				
			||||||
		if pub.Params = ParamsFromCurve(pub.Curve); pub.Params == nil {
 | 
					 | 
				
			||||||
			err = ErrInvalidPublicKey
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	return
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func marshalPrivateKey(prv *PrivateKey) (ecprv asnPrivateKey, err error) {
 | 
					 | 
				
			||||||
	ecprv.Version = asnECPrivKeyVer1
 | 
					 | 
				
			||||||
	ecprv.Private = prv.D.Bytes()
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	var ok bool
 | 
					 | 
				
			||||||
	ecprv.Curve, ok = oidFromNamedCurve(prv.PublicKey.Curve)
 | 
					 | 
				
			||||||
	if !ok {
 | 
					 | 
				
			||||||
		err = ErrInvalidPrivateKey
 | 
					 | 
				
			||||||
		return
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	var pub []byte
 | 
					 | 
				
			||||||
	if pub, err = MarshalPublic(&prv.PublicKey); err != nil {
 | 
					 | 
				
			||||||
		return
 | 
					 | 
				
			||||||
	} else {
 | 
					 | 
				
			||||||
		ecprv.Public = asn1.BitString{
 | 
					 | 
				
			||||||
			BitLength: len(pub) * 8,
 | 
					 | 
				
			||||||
			Bytes:     pub,
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	return
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// Encode a private key to DER format.
 | 
					 | 
				
			||||||
func MarshalPrivate(prv *PrivateKey) ([]byte, error) {
 | 
					 | 
				
			||||||
	ecprv, err := marshalPrivateKey(prv)
 | 
					 | 
				
			||||||
	if err != nil {
 | 
					 | 
				
			||||||
		return nil, err
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	return asn1.Marshal(ecprv)
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// Decode a private key from a DER-encoded format.
 | 
					 | 
				
			||||||
func UnmarshalPrivate(in []byte) (prv *PrivateKey, err error) {
 | 
					 | 
				
			||||||
	var ecprv asnPrivateKey
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	if _, err = asn1.Unmarshal(in, &ecprv); err != nil {
 | 
					 | 
				
			||||||
		return
 | 
					 | 
				
			||||||
	} else if ecprv.Version != asnECPrivKeyVer1 {
 | 
					 | 
				
			||||||
		err = ErrInvalidPrivateKey
 | 
					 | 
				
			||||||
		return
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	privateCurve := namedCurveFromOID(ecprv.Curve)
 | 
					 | 
				
			||||||
	if privateCurve == nil {
 | 
					 | 
				
			||||||
		err = ErrInvalidPrivateKey
 | 
					 | 
				
			||||||
		return
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	prv = new(PrivateKey)
 | 
					 | 
				
			||||||
	prv.D = new(big.Int).SetBytes(ecprv.Private)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	if pub, err := UnmarshalPublic(ecprv.Public.Bytes); err != nil {
 | 
					 | 
				
			||||||
		return nil, err
 | 
					 | 
				
			||||||
	} else {
 | 
					 | 
				
			||||||
		prv.PublicKey = *pub
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	return
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// Export a public key to PEM format.
 | 
					 | 
				
			||||||
func ExportPublicPEM(pub *PublicKey) (out []byte, err error) {
 | 
					 | 
				
			||||||
	der, err := MarshalPublic(pub)
 | 
					 | 
				
			||||||
	if err != nil {
 | 
					 | 
				
			||||||
		return
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	var block pem.Block
 | 
					 | 
				
			||||||
	block.Type = "ELLIPTIC CURVE PUBLIC KEY"
 | 
					 | 
				
			||||||
	block.Bytes = der
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	buf := new(bytes.Buffer)
 | 
					 | 
				
			||||||
	err = pem.Encode(buf, &block)
 | 
					 | 
				
			||||||
	if err != nil {
 | 
					 | 
				
			||||||
		return
 | 
					 | 
				
			||||||
	} else {
 | 
					 | 
				
			||||||
		out = buf.Bytes()
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	return
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// Export a private key to PEM format.
 | 
					 | 
				
			||||||
func ExportPrivatePEM(prv *PrivateKey) (out []byte, err error) {
 | 
					 | 
				
			||||||
	der, err := MarshalPrivate(prv)
 | 
					 | 
				
			||||||
	if err != nil {
 | 
					 | 
				
			||||||
		return
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	var block pem.Block
 | 
					 | 
				
			||||||
	block.Type = "ELLIPTIC CURVE PRIVATE KEY"
 | 
					 | 
				
			||||||
	block.Bytes = der
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	buf := new(bytes.Buffer)
 | 
					 | 
				
			||||||
	err = pem.Encode(buf, &block)
 | 
					 | 
				
			||||||
	if err != nil {
 | 
					 | 
				
			||||||
		return
 | 
					 | 
				
			||||||
	} else {
 | 
					 | 
				
			||||||
		out = buf.Bytes()
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	return
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// Import a PEM-encoded public key.
 | 
					 | 
				
			||||||
func ImportPublicPEM(in []byte) (pub *PublicKey, err error) {
 | 
					 | 
				
			||||||
	p, _ := pem.Decode(in)
 | 
					 | 
				
			||||||
	if p == nil || p.Type != "ELLIPTIC CURVE PUBLIC KEY" {
 | 
					 | 
				
			||||||
		return nil, ErrInvalidPublicKey
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	pub, err = UnmarshalPublic(p.Bytes)
 | 
					 | 
				
			||||||
	return
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// Import a PEM-encoded private key.
 | 
					 | 
				
			||||||
func ImportPrivatePEM(in []byte) (prv *PrivateKey, err error) {
 | 
					 | 
				
			||||||
	p, _ := pem.Decode(in)
 | 
					 | 
				
			||||||
	if p == nil || p.Type != "ELLIPTIC CURVE PRIVATE KEY" {
 | 
					 | 
				
			||||||
		return nil, ErrInvalidPrivateKey
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	prv, err = UnmarshalPrivate(p.Bytes)
 | 
					 | 
				
			||||||
	return
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
							
								
								
									
										326
									
								
								Godeps/_workspace/src/github.com/obscuren/ecies/ecies.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										326
									
								
								Godeps/_workspace/src/github.com/obscuren/ecies/ecies.go
									
									
									
										generated
									
									
										vendored
									
									
								
							@@ -1,326 +0,0 @@
 | 
				
			|||||||
package ecies
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
import (
 | 
					 | 
				
			||||||
	"crypto/cipher"
 | 
					 | 
				
			||||||
	"crypto/ecdsa"
 | 
					 | 
				
			||||||
	"crypto/elliptic"
 | 
					 | 
				
			||||||
	"crypto/hmac"
 | 
					 | 
				
			||||||
	"crypto/subtle"
 | 
					 | 
				
			||||||
	"fmt"
 | 
					 | 
				
			||||||
	"hash"
 | 
					 | 
				
			||||||
	"io"
 | 
					 | 
				
			||||||
	"math/big"
 | 
					 | 
				
			||||||
)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
var (
 | 
					 | 
				
			||||||
	ErrImport           = fmt.Errorf("ecies: failed to import key")
 | 
					 | 
				
			||||||
	ErrInvalidCurve     = fmt.Errorf("ecies: invalid elliptic curve")
 | 
					 | 
				
			||||||
	ErrInvalidParams    = fmt.Errorf("ecies: invalid ECIES parameters")
 | 
					 | 
				
			||||||
	ErrInvalidPublicKey = fmt.Errorf("ecies: invalid public key")
 | 
					 | 
				
			||||||
	ErrSharedKeyTooBig  = fmt.Errorf("ecies: shared key is too big")
 | 
					 | 
				
			||||||
)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// PublicKey is a representation of an elliptic curve public key.
 | 
					 | 
				
			||||||
type PublicKey struct {
 | 
					 | 
				
			||||||
	X *big.Int
 | 
					 | 
				
			||||||
	Y *big.Int
 | 
					 | 
				
			||||||
	elliptic.Curve
 | 
					 | 
				
			||||||
	Params *ECIESParams
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// Export an ECIES public key as an ECDSA public key.
 | 
					 | 
				
			||||||
func (pub *PublicKey) ExportECDSA() *ecdsa.PublicKey {
 | 
					 | 
				
			||||||
	return &ecdsa.PublicKey{pub.Curve, pub.X, pub.Y}
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// Import an ECDSA public key as an ECIES public key.
 | 
					 | 
				
			||||||
func ImportECDSAPublic(pub *ecdsa.PublicKey) *PublicKey {
 | 
					 | 
				
			||||||
	return &PublicKey{
 | 
					 | 
				
			||||||
		X:      pub.X,
 | 
					 | 
				
			||||||
		Y:      pub.Y,
 | 
					 | 
				
			||||||
		Curve:  pub.Curve,
 | 
					 | 
				
			||||||
		Params: ParamsFromCurve(pub.Curve),
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// PrivateKey is a representation of an elliptic curve private key.
 | 
					 | 
				
			||||||
type PrivateKey struct {
 | 
					 | 
				
			||||||
	PublicKey
 | 
					 | 
				
			||||||
	D *big.Int
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// Export an ECIES private key as an ECDSA private key.
 | 
					 | 
				
			||||||
func (prv *PrivateKey) ExportECDSA() *ecdsa.PrivateKey {
 | 
					 | 
				
			||||||
	pub := &prv.PublicKey
 | 
					 | 
				
			||||||
	pubECDSA := pub.ExportECDSA()
 | 
					 | 
				
			||||||
	return &ecdsa.PrivateKey{*pubECDSA, prv.D}
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// Import an ECDSA private key as an ECIES private key.
 | 
					 | 
				
			||||||
func ImportECDSA(prv *ecdsa.PrivateKey) *PrivateKey {
 | 
					 | 
				
			||||||
	pub := ImportECDSAPublic(&prv.PublicKey)
 | 
					 | 
				
			||||||
	return &PrivateKey{*pub, prv.D}
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// Generate an elliptic curve public / private keypair. If params is nil,
 | 
					 | 
				
			||||||
// the recommended default paramters for the key will be chosen.
 | 
					 | 
				
			||||||
func GenerateKey(rand io.Reader, curve elliptic.Curve, params *ECIESParams) (prv *PrivateKey, err error) {
 | 
					 | 
				
			||||||
	pb, x, y, err := elliptic.GenerateKey(curve, rand)
 | 
					 | 
				
			||||||
	if err != nil {
 | 
					 | 
				
			||||||
		return
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	prv = new(PrivateKey)
 | 
					 | 
				
			||||||
	prv.PublicKey.X = x
 | 
					 | 
				
			||||||
	prv.PublicKey.Y = y
 | 
					 | 
				
			||||||
	prv.PublicKey.Curve = curve
 | 
					 | 
				
			||||||
	prv.D = new(big.Int).SetBytes(pb)
 | 
					 | 
				
			||||||
	if params == nil {
 | 
					 | 
				
			||||||
		params = ParamsFromCurve(curve)
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	prv.PublicKey.Params = params
 | 
					 | 
				
			||||||
	return
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// MaxSharedKeyLength returns the maximum length of the shared key the
 | 
					 | 
				
			||||||
// public key can produce.
 | 
					 | 
				
			||||||
func MaxSharedKeyLength(pub *PublicKey) int {
 | 
					 | 
				
			||||||
	return (pub.Curve.Params().BitSize + 7) / 8
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// ECDH key agreement method used to establish secret keys for encryption.
 | 
					 | 
				
			||||||
func (prv *PrivateKey) GenerateShared(pub *PublicKey, skLen, macLen int) (sk []byte, err error) {
 | 
					 | 
				
			||||||
	if prv.PublicKey.Curve != pub.Curve {
 | 
					 | 
				
			||||||
		err = ErrInvalidCurve
 | 
					 | 
				
			||||||
		return
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	x, _ := pub.Curve.ScalarMult(pub.X, pub.Y, prv.D.Bytes())
 | 
					 | 
				
			||||||
	if x == nil || (x.BitLen()+7)/8 < (skLen+macLen) {
 | 
					 | 
				
			||||||
		err = ErrSharedKeyTooBig
 | 
					 | 
				
			||||||
		return
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	sk = x.Bytes()[:skLen+macLen]
 | 
					 | 
				
			||||||
	return
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
var (
 | 
					 | 
				
			||||||
	ErrKeyDataTooLong = fmt.Errorf("ecies: can't supply requested key data")
 | 
					 | 
				
			||||||
	ErrSharedTooLong  = fmt.Errorf("ecies: shared secret is too long")
 | 
					 | 
				
			||||||
	ErrInvalidMessage = fmt.Errorf("ecies: invalid message")
 | 
					 | 
				
			||||||
)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
var (
 | 
					 | 
				
			||||||
	big2To32   = new(big.Int).Exp(big.NewInt(2), big.NewInt(32), nil)
 | 
					 | 
				
			||||||
	big2To32M1 = new(big.Int).Sub(big2To32, big.NewInt(1))
 | 
					 | 
				
			||||||
)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func incCounter(ctr []byte) {
 | 
					 | 
				
			||||||
	if ctr[3]++; ctr[3] != 0 {
 | 
					 | 
				
			||||||
		return
 | 
					 | 
				
			||||||
	} else if ctr[2]++; ctr[2] != 0 {
 | 
					 | 
				
			||||||
		return
 | 
					 | 
				
			||||||
	} else if ctr[1]++; ctr[1] != 0 {
 | 
					 | 
				
			||||||
		return
 | 
					 | 
				
			||||||
	} else if ctr[0]++; ctr[0] != 0 {
 | 
					 | 
				
			||||||
		return
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	return
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// NIST SP 800-56 Concatenation Key Derivation Function (see section 5.8.1).
 | 
					 | 
				
			||||||
func concatKDF(hash hash.Hash, z, s1 []byte, kdLen int) (k []byte, err error) {
 | 
					 | 
				
			||||||
	if s1 == nil {
 | 
					 | 
				
			||||||
		s1 = make([]byte, 0)
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	reps := ((kdLen + 7) * 8) / (hash.BlockSize() * 8)
 | 
					 | 
				
			||||||
	if big.NewInt(int64(reps)).Cmp(big2To32M1) > 0 {
 | 
					 | 
				
			||||||
		fmt.Println(big2To32M1)
 | 
					 | 
				
			||||||
		return nil, ErrKeyDataTooLong
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	counter := []byte{0, 0, 0, 1}
 | 
					 | 
				
			||||||
	k = make([]byte, 0)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	for i := 0; i <= reps; i++ {
 | 
					 | 
				
			||||||
		hash.Write(counter)
 | 
					 | 
				
			||||||
		hash.Write(z)
 | 
					 | 
				
			||||||
		hash.Write(s1)
 | 
					 | 
				
			||||||
		k = append(k, hash.Sum(nil)...)
 | 
					 | 
				
			||||||
		hash.Reset()
 | 
					 | 
				
			||||||
		incCounter(counter)
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	k = k[:kdLen]
 | 
					 | 
				
			||||||
	return
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// messageTag computes the MAC of a message (called the tag) as per
 | 
					 | 
				
			||||||
// SEC 1, 3.5.
 | 
					 | 
				
			||||||
func messageTag(hash func() hash.Hash, km, msg, shared []byte) []byte {
 | 
					 | 
				
			||||||
	if shared == nil {
 | 
					 | 
				
			||||||
		shared = make([]byte, 0)
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	mac := hmac.New(hash, km)
 | 
					 | 
				
			||||||
	mac.Write(msg)
 | 
					 | 
				
			||||||
	tag := mac.Sum(nil)
 | 
					 | 
				
			||||||
	return tag
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// Generate an initialisation vector for CTR mode.
 | 
					 | 
				
			||||||
func generateIV(params *ECIESParams, rand io.Reader) (iv []byte, err error) {
 | 
					 | 
				
			||||||
	iv = make([]byte, params.BlockSize)
 | 
					 | 
				
			||||||
	_, err = io.ReadFull(rand, iv)
 | 
					 | 
				
			||||||
	return
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// symEncrypt carries out CTR encryption using the block cipher specified in the
 | 
					 | 
				
			||||||
// parameters.
 | 
					 | 
				
			||||||
func symEncrypt(rand io.Reader, params *ECIESParams, key, m []byte) (ct []byte, err error) {
 | 
					 | 
				
			||||||
	c, err := params.Cipher(key)
 | 
					 | 
				
			||||||
	if err != nil {
 | 
					 | 
				
			||||||
		return
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	iv, err := generateIV(params, rand)
 | 
					 | 
				
			||||||
	if err != nil {
 | 
					 | 
				
			||||||
		return
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	ctr := cipher.NewCTR(c, iv)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	ct = make([]byte, len(m)+params.BlockSize)
 | 
					 | 
				
			||||||
	copy(ct, iv)
 | 
					 | 
				
			||||||
	ctr.XORKeyStream(ct[params.BlockSize:], m)
 | 
					 | 
				
			||||||
	return
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// symDecrypt carries out CTR decryption using the block cipher specified in
 | 
					 | 
				
			||||||
// the parameters
 | 
					 | 
				
			||||||
func symDecrypt(rand io.Reader, params *ECIESParams, key, ct []byte) (m []byte, err error) {
 | 
					 | 
				
			||||||
	c, err := params.Cipher(key)
 | 
					 | 
				
			||||||
	if err != nil {
 | 
					 | 
				
			||||||
		return
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	ctr := cipher.NewCTR(c, ct[:params.BlockSize])
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	m = make([]byte, len(ct)-params.BlockSize)
 | 
					 | 
				
			||||||
	ctr.XORKeyStream(m, ct[params.BlockSize:])
 | 
					 | 
				
			||||||
	return
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// Encrypt encrypts a message using ECIES as specified in SEC 1, 5.1. If
 | 
					 | 
				
			||||||
// the shared information parameters aren't being used, they should be
 | 
					 | 
				
			||||||
// nil.
 | 
					 | 
				
			||||||
func Encrypt(rand io.Reader, pub *PublicKey, m, s1, s2 []byte) (ct []byte, err error) {
 | 
					 | 
				
			||||||
	params := pub.Params
 | 
					 | 
				
			||||||
	if params == nil {
 | 
					 | 
				
			||||||
		if params = ParamsFromCurve(pub.Curve); params == nil {
 | 
					 | 
				
			||||||
			err = ErrUnsupportedECIESParameters
 | 
					 | 
				
			||||||
			return
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	R, err := GenerateKey(rand, pub.Curve, params)
 | 
					 | 
				
			||||||
	if err != nil {
 | 
					 | 
				
			||||||
		return
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	hash := params.Hash()
 | 
					 | 
				
			||||||
	z, err := R.GenerateShared(pub, params.KeyLen, params.KeyLen)
 | 
					 | 
				
			||||||
	if err != nil {
 | 
					 | 
				
			||||||
		return
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	K, err := concatKDF(hash, z, s1, params.KeyLen+params.KeyLen)
 | 
					 | 
				
			||||||
	if err != nil {
 | 
					 | 
				
			||||||
		return
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	Ke := K[:params.KeyLen]
 | 
					 | 
				
			||||||
	Km := K[params.KeyLen:]
 | 
					 | 
				
			||||||
	hash.Write(Km)
 | 
					 | 
				
			||||||
	Km = hash.Sum(nil)
 | 
					 | 
				
			||||||
	hash.Reset()
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	em, err := symEncrypt(rand, params, Ke, m)
 | 
					 | 
				
			||||||
	if err != nil || len(em) <= params.BlockSize {
 | 
					 | 
				
			||||||
		return
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	d := messageTag(params.Hash, Km, em, s2)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	Rb := elliptic.Marshal(pub.Curve, R.PublicKey.X, R.PublicKey.Y)
 | 
					 | 
				
			||||||
	ct = make([]byte, len(Rb)+len(em)+len(d))
 | 
					 | 
				
			||||||
	copy(ct, Rb)
 | 
					 | 
				
			||||||
	copy(ct[len(Rb):], em)
 | 
					 | 
				
			||||||
	copy(ct[len(Rb)+len(em):], d)
 | 
					 | 
				
			||||||
	return
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// Decrypt decrypts an ECIES ciphertext.
 | 
					 | 
				
			||||||
func (prv *PrivateKey) Decrypt(rand io.Reader, c, s1, s2 []byte) (m []byte, err error) {
 | 
					 | 
				
			||||||
	if c == nil || len(c) == 0 {
 | 
					 | 
				
			||||||
		err = ErrInvalidMessage
 | 
					 | 
				
			||||||
		return
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	params := prv.PublicKey.Params
 | 
					 | 
				
			||||||
	if params == nil {
 | 
					 | 
				
			||||||
		if params = ParamsFromCurve(prv.PublicKey.Curve); params == nil {
 | 
					 | 
				
			||||||
			err = ErrUnsupportedECIESParameters
 | 
					 | 
				
			||||||
			return
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	hash := params.Hash()
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	var (
 | 
					 | 
				
			||||||
		rLen   int
 | 
					 | 
				
			||||||
		hLen   int = hash.Size()
 | 
					 | 
				
			||||||
		mStart int
 | 
					 | 
				
			||||||
		mEnd   int
 | 
					 | 
				
			||||||
	)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	switch c[0] {
 | 
					 | 
				
			||||||
	case 2, 3, 4:
 | 
					 | 
				
			||||||
		rLen = ((prv.PublicKey.Curve.Params().BitSize + 7) / 4)
 | 
					 | 
				
			||||||
		if len(c) < (rLen + hLen + 1) {
 | 
					 | 
				
			||||||
			err = ErrInvalidMessage
 | 
					 | 
				
			||||||
			return
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	default:
 | 
					 | 
				
			||||||
		err = ErrInvalidPublicKey
 | 
					 | 
				
			||||||
		return
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	mStart = rLen
 | 
					 | 
				
			||||||
	mEnd = len(c) - hLen
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	R := new(PublicKey)
 | 
					 | 
				
			||||||
	R.Curve = prv.PublicKey.Curve
 | 
					 | 
				
			||||||
	R.X, R.Y = elliptic.Unmarshal(R.Curve, c[:rLen])
 | 
					 | 
				
			||||||
	if R.X == nil {
 | 
					 | 
				
			||||||
		err = ErrInvalidPublicKey
 | 
					 | 
				
			||||||
		return
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	z, err := prv.GenerateShared(R, params.KeyLen, params.KeyLen)
 | 
					 | 
				
			||||||
	if err != nil {
 | 
					 | 
				
			||||||
		return
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	K, err := concatKDF(hash, z, s1, params.KeyLen+params.KeyLen)
 | 
					 | 
				
			||||||
	if err != nil {
 | 
					 | 
				
			||||||
		return
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	Ke := K[:params.KeyLen]
 | 
					 | 
				
			||||||
	Km := K[params.KeyLen:]
 | 
					 | 
				
			||||||
	hash.Write(Km)
 | 
					 | 
				
			||||||
	Km = hash.Sum(nil)
 | 
					 | 
				
			||||||
	hash.Reset()
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	d := messageTag(params.Hash, Km, c[mStart:mEnd], s2)
 | 
					 | 
				
			||||||
	if subtle.ConstantTimeCompare(c[mEnd:], d) != 1 {
 | 
					 | 
				
			||||||
		err = ErrInvalidMessage
 | 
					 | 
				
			||||||
		return
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	m, err = symDecrypt(rand, params, Ke, c[mStart:mEnd])
 | 
					 | 
				
			||||||
	return
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
							
								
								
									
										489
									
								
								Godeps/_workspace/src/github.com/obscuren/ecies/ecies_test.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										489
									
								
								Godeps/_workspace/src/github.com/obscuren/ecies/ecies_test.go
									
									
									
										generated
									
									
										vendored
									
									
								
							@@ -1,489 +0,0 @@
 | 
				
			|||||||
package ecies
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
import (
 | 
					 | 
				
			||||||
	"bytes"
 | 
					 | 
				
			||||||
	"crypto/elliptic"
 | 
					 | 
				
			||||||
	"crypto/rand"
 | 
					 | 
				
			||||||
	"crypto/sha256"
 | 
					 | 
				
			||||||
	"flag"
 | 
					 | 
				
			||||||
	"fmt"
 | 
					 | 
				
			||||||
	"io/ioutil"
 | 
					 | 
				
			||||||
	"testing"
 | 
					 | 
				
			||||||
)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
var dumpEnc bool
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func init() {
 | 
					 | 
				
			||||||
	flDump := flag.Bool("dump", false, "write encrypted test message to file")
 | 
					 | 
				
			||||||
	flag.Parse()
 | 
					 | 
				
			||||||
	dumpEnc = *flDump
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// Ensure the KDF generates appropriately sized keys.
 | 
					 | 
				
			||||||
func TestKDF(t *testing.T) {
 | 
					 | 
				
			||||||
	msg := []byte("Hello, world")
 | 
					 | 
				
			||||||
	h := sha256.New()
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	k, err := concatKDF(h, msg, nil, 64)
 | 
					 | 
				
			||||||
	if err != nil {
 | 
					 | 
				
			||||||
		fmt.Println(err.Error())
 | 
					 | 
				
			||||||
		t.FailNow()
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	if len(k) != 64 {
 | 
					 | 
				
			||||||
		fmt.Printf("KDF: generated key is the wrong size (%d instead of 64\n",
 | 
					 | 
				
			||||||
			len(k))
 | 
					 | 
				
			||||||
		t.FailNow()
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
var skLen int
 | 
					 | 
				
			||||||
var ErrBadSharedKeys = fmt.Errorf("ecies: shared keys don't match")
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// cmpParams compares a set of ECIES parameters. We assume, as per the
 | 
					 | 
				
			||||||
// docs, that AES is the only supported symmetric encryption algorithm.
 | 
					 | 
				
			||||||
func cmpParams(p1, p2 *ECIESParams) bool {
 | 
					 | 
				
			||||||
	if p1.hashAlgo != p2.hashAlgo {
 | 
					 | 
				
			||||||
		return false
 | 
					 | 
				
			||||||
	} else if p1.KeyLen != p2.KeyLen {
 | 
					 | 
				
			||||||
		return false
 | 
					 | 
				
			||||||
	} else if p1.BlockSize != p2.BlockSize {
 | 
					 | 
				
			||||||
		return false
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	return true
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// cmpPublic returns true if the two public keys represent the same pojnt.
 | 
					 | 
				
			||||||
func cmpPublic(pub1, pub2 PublicKey) bool {
 | 
					 | 
				
			||||||
	if pub1.X == nil || pub1.Y == nil {
 | 
					 | 
				
			||||||
		fmt.Println(ErrInvalidPublicKey.Error())
 | 
					 | 
				
			||||||
		return false
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	if pub2.X == nil || pub2.Y == nil {
 | 
					 | 
				
			||||||
		fmt.Println(ErrInvalidPublicKey.Error())
 | 
					 | 
				
			||||||
		return false
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	pub1Out := elliptic.Marshal(pub1.Curve, pub1.X, pub1.Y)
 | 
					 | 
				
			||||||
	pub2Out := elliptic.Marshal(pub2.Curve, pub2.X, pub2.Y)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	return bytes.Equal(pub1Out, pub2Out)
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// cmpPrivate returns true if the two private keys are the same.
 | 
					 | 
				
			||||||
func cmpPrivate(prv1, prv2 *PrivateKey) bool {
 | 
					 | 
				
			||||||
	if prv1 == nil || prv1.D == nil {
 | 
					 | 
				
			||||||
		return false
 | 
					 | 
				
			||||||
	} else if prv2 == nil || prv2.D == nil {
 | 
					 | 
				
			||||||
		return false
 | 
					 | 
				
			||||||
	} else if prv1.D.Cmp(prv2.D) != 0 {
 | 
					 | 
				
			||||||
		return false
 | 
					 | 
				
			||||||
	} else {
 | 
					 | 
				
			||||||
		return cmpPublic(prv1.PublicKey, prv2.PublicKey)
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// Validate the ECDH component.
 | 
					 | 
				
			||||||
func TestSharedKey(t *testing.T) {
 | 
					 | 
				
			||||||
	prv1, err := GenerateKey(rand.Reader, DefaultCurve, nil)
 | 
					 | 
				
			||||||
	if err != nil {
 | 
					 | 
				
			||||||
		fmt.Println(err.Error())
 | 
					 | 
				
			||||||
		t.FailNow()
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	skLen = MaxSharedKeyLength(&prv1.PublicKey) / 2
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	prv2, err := GenerateKey(rand.Reader, DefaultCurve, nil)
 | 
					 | 
				
			||||||
	if err != nil {
 | 
					 | 
				
			||||||
		fmt.Println(err.Error())
 | 
					 | 
				
			||||||
		t.FailNow()
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	sk1, err := prv1.GenerateShared(&prv2.PublicKey, skLen, skLen)
 | 
					 | 
				
			||||||
	if err != nil {
 | 
					 | 
				
			||||||
		fmt.Println(err.Error())
 | 
					 | 
				
			||||||
		t.FailNow()
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	sk2, err := prv2.GenerateShared(&prv1.PublicKey, skLen, skLen)
 | 
					 | 
				
			||||||
	if err != nil {
 | 
					 | 
				
			||||||
		fmt.Println(err.Error())
 | 
					 | 
				
			||||||
		t.FailNow()
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	if !bytes.Equal(sk1, sk2) {
 | 
					 | 
				
			||||||
		fmt.Println(ErrBadSharedKeys.Error())
 | 
					 | 
				
			||||||
		t.FailNow()
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// Verify that the key generation code fails when too much key data is
 | 
					 | 
				
			||||||
// requested.
 | 
					 | 
				
			||||||
func TestTooBigSharedKey(t *testing.T) {
 | 
					 | 
				
			||||||
	prv1, err := GenerateKey(rand.Reader, DefaultCurve, nil)
 | 
					 | 
				
			||||||
	if err != nil {
 | 
					 | 
				
			||||||
		fmt.Println(err.Error())
 | 
					 | 
				
			||||||
		t.FailNow()
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	prv2, err := GenerateKey(rand.Reader, DefaultCurve, nil)
 | 
					 | 
				
			||||||
	if err != nil {
 | 
					 | 
				
			||||||
		fmt.Println(err.Error())
 | 
					 | 
				
			||||||
		t.FailNow()
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	_, err = prv1.GenerateShared(&prv2.PublicKey, skLen*2, skLen*2)
 | 
					 | 
				
			||||||
	if err != ErrSharedKeyTooBig {
 | 
					 | 
				
			||||||
		fmt.Println("ecdh: shared key should be too large for curve")
 | 
					 | 
				
			||||||
		t.FailNow()
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	_, err = prv2.GenerateShared(&prv1.PublicKey, skLen*2, skLen*2)
 | 
					 | 
				
			||||||
	if err != ErrSharedKeyTooBig {
 | 
					 | 
				
			||||||
		fmt.Println("ecdh: shared key should be too large for curve")
 | 
					 | 
				
			||||||
		t.FailNow()
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// Ensure a public key can be successfully marshalled and unmarshalled, and
 | 
					 | 
				
			||||||
// that the decoded key is the same as the original.
 | 
					 | 
				
			||||||
func TestMarshalPublic(t *testing.T) {
 | 
					 | 
				
			||||||
	prv, err := GenerateKey(rand.Reader, DefaultCurve, nil)
 | 
					 | 
				
			||||||
	if err != nil {
 | 
					 | 
				
			||||||
		fmt.Println(err.Error())
 | 
					 | 
				
			||||||
		t.FailNow()
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	out, err := MarshalPublic(&prv.PublicKey)
 | 
					 | 
				
			||||||
	if err != nil {
 | 
					 | 
				
			||||||
		fmt.Println(err.Error())
 | 
					 | 
				
			||||||
		t.FailNow()
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	pub, err := UnmarshalPublic(out)
 | 
					 | 
				
			||||||
	if err != nil {
 | 
					 | 
				
			||||||
		fmt.Println(err.Error())
 | 
					 | 
				
			||||||
		t.FailNow()
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	if !cmpPublic(prv.PublicKey, *pub) {
 | 
					 | 
				
			||||||
		fmt.Println("ecies: failed to unmarshal public key")
 | 
					 | 
				
			||||||
		t.FailNow()
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// Ensure that a private key can be encoded into DER format, and that
 | 
					 | 
				
			||||||
// the resulting key is properly parsed back into a public key.
 | 
					 | 
				
			||||||
func TestMarshalPrivate(t *testing.T) {
 | 
					 | 
				
			||||||
	prv, err := GenerateKey(rand.Reader, DefaultCurve, nil)
 | 
					 | 
				
			||||||
	if err != nil {
 | 
					 | 
				
			||||||
		fmt.Println(err.Error())
 | 
					 | 
				
			||||||
		t.FailNow()
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	out, err := MarshalPrivate(prv)
 | 
					 | 
				
			||||||
	if err != nil {
 | 
					 | 
				
			||||||
		fmt.Println(err.Error())
 | 
					 | 
				
			||||||
		t.FailNow()
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	if dumpEnc {
 | 
					 | 
				
			||||||
		ioutil.WriteFile("test.out", out, 0644)
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	prv2, err := UnmarshalPrivate(out)
 | 
					 | 
				
			||||||
	if err != nil {
 | 
					 | 
				
			||||||
		fmt.Println(err.Error())
 | 
					 | 
				
			||||||
		t.FailNow()
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	if !cmpPrivate(prv, prv2) {
 | 
					 | 
				
			||||||
		fmt.Println("ecdh: private key import failed")
 | 
					 | 
				
			||||||
		t.FailNow()
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// Ensure that a private key can be successfully encoded to PEM format, and
 | 
					 | 
				
			||||||
// the resulting key is properly parsed back in.
 | 
					 | 
				
			||||||
func TestPrivatePEM(t *testing.T) {
 | 
					 | 
				
			||||||
	prv, err := GenerateKey(rand.Reader, DefaultCurve, nil)
 | 
					 | 
				
			||||||
	if err != nil {
 | 
					 | 
				
			||||||
		fmt.Println(err.Error())
 | 
					 | 
				
			||||||
		t.FailNow()
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	out, err := ExportPrivatePEM(prv)
 | 
					 | 
				
			||||||
	if err != nil {
 | 
					 | 
				
			||||||
		fmt.Println(err.Error())
 | 
					 | 
				
			||||||
		t.FailNow()
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	if dumpEnc {
 | 
					 | 
				
			||||||
		ioutil.WriteFile("test.key", out, 0644)
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	prv2, err := ImportPrivatePEM(out)
 | 
					 | 
				
			||||||
	if err != nil {
 | 
					 | 
				
			||||||
		fmt.Println(err.Error())
 | 
					 | 
				
			||||||
		t.FailNow()
 | 
					 | 
				
			||||||
	} else if !cmpPrivate(prv, prv2) {
 | 
					 | 
				
			||||||
		fmt.Println("ecdh: import from PEM failed")
 | 
					 | 
				
			||||||
		t.FailNow()
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// Ensure that a public key can be successfully encoded to PEM format, and
 | 
					 | 
				
			||||||
// the resulting key is properly parsed back in.
 | 
					 | 
				
			||||||
func TestPublicPEM(t *testing.T) {
 | 
					 | 
				
			||||||
	prv, err := GenerateKey(rand.Reader, DefaultCurve, nil)
 | 
					 | 
				
			||||||
	if err != nil {
 | 
					 | 
				
			||||||
		fmt.Println(err.Error())
 | 
					 | 
				
			||||||
		t.FailNow()
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	out, err := ExportPublicPEM(&prv.PublicKey)
 | 
					 | 
				
			||||||
	if err != nil {
 | 
					 | 
				
			||||||
		fmt.Println(err.Error())
 | 
					 | 
				
			||||||
		t.FailNow()
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	if dumpEnc {
 | 
					 | 
				
			||||||
		ioutil.WriteFile("test.pem", out, 0644)
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	pub2, err := ImportPublicPEM(out)
 | 
					 | 
				
			||||||
	if err != nil {
 | 
					 | 
				
			||||||
		fmt.Println(err.Error())
 | 
					 | 
				
			||||||
		t.FailNow()
 | 
					 | 
				
			||||||
	} else if !cmpPublic(prv.PublicKey, *pub2) {
 | 
					 | 
				
			||||||
		fmt.Println("ecdh: import from PEM failed")
 | 
					 | 
				
			||||||
		t.FailNow()
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// Benchmark the generation of P256 keys.
 | 
					 | 
				
			||||||
func BenchmarkGenerateKeyP256(b *testing.B) {
 | 
					 | 
				
			||||||
	for i := 0; i < b.N; i++ {
 | 
					 | 
				
			||||||
		if _, err := GenerateKey(rand.Reader, elliptic.P256(), nil); err != nil {
 | 
					 | 
				
			||||||
			fmt.Println(err.Error())
 | 
					 | 
				
			||||||
			b.FailNow()
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// Benchmark the generation of P256 shared keys.
 | 
					 | 
				
			||||||
func BenchmarkGenSharedKeyP256(b *testing.B) {
 | 
					 | 
				
			||||||
	prv, err := GenerateKey(rand.Reader, elliptic.P256(), nil)
 | 
					 | 
				
			||||||
	if err != nil {
 | 
					 | 
				
			||||||
		fmt.Println(err.Error())
 | 
					 | 
				
			||||||
		b.FailNow()
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	for i := 0; i < b.N; i++ {
 | 
					 | 
				
			||||||
		_, err := prv.GenerateShared(&prv.PublicKey, skLen, skLen)
 | 
					 | 
				
			||||||
		if err != nil {
 | 
					 | 
				
			||||||
			fmt.Println(err.Error())
 | 
					 | 
				
			||||||
			b.FailNow()
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// Verify that an encrypted message can be successfully decrypted.
 | 
					 | 
				
			||||||
func TestEncryptDecrypt(t *testing.T) {
 | 
					 | 
				
			||||||
	prv1, err := GenerateKey(rand.Reader, DefaultCurve, nil)
 | 
					 | 
				
			||||||
	if err != nil {
 | 
					 | 
				
			||||||
		fmt.Println(err.Error())
 | 
					 | 
				
			||||||
		t.FailNow()
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	prv2, err := GenerateKey(rand.Reader, DefaultCurve, nil)
 | 
					 | 
				
			||||||
	if err != nil {
 | 
					 | 
				
			||||||
		fmt.Println(err.Error())
 | 
					 | 
				
			||||||
		t.FailNow()
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	message := []byte("Hello, world.")
 | 
					 | 
				
			||||||
	ct, err := Encrypt(rand.Reader, &prv2.PublicKey, message, nil, nil)
 | 
					 | 
				
			||||||
	if err != nil {
 | 
					 | 
				
			||||||
		fmt.Println(err.Error())
 | 
					 | 
				
			||||||
		t.FailNow()
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	pt, err := prv2.Decrypt(rand.Reader, ct, nil, nil)
 | 
					 | 
				
			||||||
	if err != nil {
 | 
					 | 
				
			||||||
		fmt.Println(err.Error())
 | 
					 | 
				
			||||||
		t.FailNow()
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	if !bytes.Equal(pt, message) {
 | 
					 | 
				
			||||||
		fmt.Println("ecies: plaintext doesn't match message")
 | 
					 | 
				
			||||||
		t.FailNow()
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	_, err = prv1.Decrypt(rand.Reader, ct, nil, nil)
 | 
					 | 
				
			||||||
	if err == nil {
 | 
					 | 
				
			||||||
		fmt.Println("ecies: encryption should not have succeeded")
 | 
					 | 
				
			||||||
		t.FailNow()
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// TestMarshalEncryption validates the encode/decode produces a valid
 | 
					 | 
				
			||||||
// ECIES encryption key.
 | 
					 | 
				
			||||||
func TestMarshalEncryption(t *testing.T) {
 | 
					 | 
				
			||||||
	prv1, err := GenerateKey(rand.Reader, DefaultCurve, nil)
 | 
					 | 
				
			||||||
	if err != nil {
 | 
					 | 
				
			||||||
		fmt.Println(err.Error())
 | 
					 | 
				
			||||||
		t.FailNow()
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	out, err := MarshalPrivate(prv1)
 | 
					 | 
				
			||||||
	if err != nil {
 | 
					 | 
				
			||||||
		fmt.Println(err.Error())
 | 
					 | 
				
			||||||
		t.FailNow()
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	prv2, err := UnmarshalPrivate(out)
 | 
					 | 
				
			||||||
	if err != nil {
 | 
					 | 
				
			||||||
		fmt.Println(err.Error())
 | 
					 | 
				
			||||||
		t.FailNow()
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	message := []byte("Hello, world.")
 | 
					 | 
				
			||||||
	ct, err := Encrypt(rand.Reader, &prv2.PublicKey, message, nil, nil)
 | 
					 | 
				
			||||||
	if err != nil {
 | 
					 | 
				
			||||||
		fmt.Println(err.Error())
 | 
					 | 
				
			||||||
		t.FailNow()
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	pt, err := prv2.Decrypt(rand.Reader, ct, nil, nil)
 | 
					 | 
				
			||||||
	if err != nil {
 | 
					 | 
				
			||||||
		fmt.Println(err.Error())
 | 
					 | 
				
			||||||
		t.FailNow()
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	if !bytes.Equal(pt, message) {
 | 
					 | 
				
			||||||
		fmt.Println("ecies: plaintext doesn't match message")
 | 
					 | 
				
			||||||
		t.FailNow()
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	_, err = prv1.Decrypt(rand.Reader, ct, nil, nil)
 | 
					 | 
				
			||||||
	if err != nil {
 | 
					 | 
				
			||||||
		fmt.Println(err.Error())
 | 
					 | 
				
			||||||
		t.FailNow()
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
type testCase struct {
 | 
					 | 
				
			||||||
	Curve    elliptic.Curve
 | 
					 | 
				
			||||||
	Name     string
 | 
					 | 
				
			||||||
	Expected bool
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
var testCases = []testCase{
 | 
					 | 
				
			||||||
	testCase{
 | 
					 | 
				
			||||||
		Curve:    elliptic.P224(),
 | 
					 | 
				
			||||||
		Name:     "P224",
 | 
					 | 
				
			||||||
		Expected: false,
 | 
					 | 
				
			||||||
	},
 | 
					 | 
				
			||||||
	testCase{
 | 
					 | 
				
			||||||
		Curve:    elliptic.P256(),
 | 
					 | 
				
			||||||
		Name:     "P256",
 | 
					 | 
				
			||||||
		Expected: true,
 | 
					 | 
				
			||||||
	},
 | 
					 | 
				
			||||||
	testCase{
 | 
					 | 
				
			||||||
		Curve:    elliptic.P384(),
 | 
					 | 
				
			||||||
		Name:     "P384",
 | 
					 | 
				
			||||||
		Expected: true,
 | 
					 | 
				
			||||||
	},
 | 
					 | 
				
			||||||
	testCase{
 | 
					 | 
				
			||||||
		Curve:    elliptic.P521(),
 | 
					 | 
				
			||||||
		Name:     "P521",
 | 
					 | 
				
			||||||
		Expected: true,
 | 
					 | 
				
			||||||
	},
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// Test parameter selection for each curve, and that P224 fails automatic
 | 
					 | 
				
			||||||
// parameter selection (see README for a discussion of P224). Ensures that
 | 
					 | 
				
			||||||
// selecting a set of parameters automatically for the given curve works.
 | 
					 | 
				
			||||||
func TestParamSelection(t *testing.T) {
 | 
					 | 
				
			||||||
	for _, c := range testCases {
 | 
					 | 
				
			||||||
		testParamSelection(t, c)
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func testParamSelection(t *testing.T, c testCase) {
 | 
					 | 
				
			||||||
	params := ParamsFromCurve(c.Curve)
 | 
					 | 
				
			||||||
	if params == nil && c.Expected {
 | 
					 | 
				
			||||||
		fmt.Printf("%s (%s)\n", ErrInvalidParams.Error(), c.Name)
 | 
					 | 
				
			||||||
		t.FailNow()
 | 
					 | 
				
			||||||
	} else if params != nil && !c.Expected {
 | 
					 | 
				
			||||||
		fmt.Printf("ecies: parameters should be invalid (%s)\n",
 | 
					 | 
				
			||||||
			c.Name)
 | 
					 | 
				
			||||||
		t.FailNow()
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	prv1, err := GenerateKey(rand.Reader, DefaultCurve, nil)
 | 
					 | 
				
			||||||
	if err != nil {
 | 
					 | 
				
			||||||
		fmt.Printf("%s (%s)\n", err.Error(), c.Name)
 | 
					 | 
				
			||||||
		t.FailNow()
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	prv2, err := GenerateKey(rand.Reader, DefaultCurve, nil)
 | 
					 | 
				
			||||||
	if err != nil {
 | 
					 | 
				
			||||||
		fmt.Printf("%s (%s)\n", err.Error(), c.Name)
 | 
					 | 
				
			||||||
		t.FailNow()
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	message := []byte("Hello, world.")
 | 
					 | 
				
			||||||
	ct, err := Encrypt(rand.Reader, &prv2.PublicKey, message, nil, nil)
 | 
					 | 
				
			||||||
	if err != nil {
 | 
					 | 
				
			||||||
		fmt.Printf("%s (%s)\n", err.Error(), c.Name)
 | 
					 | 
				
			||||||
		t.FailNow()
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	pt, err := prv2.Decrypt(rand.Reader, ct, nil, nil)
 | 
					 | 
				
			||||||
	if err != nil {
 | 
					 | 
				
			||||||
		fmt.Printf("%s (%s)\n", err.Error(), c.Name)
 | 
					 | 
				
			||||||
		t.FailNow()
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	if !bytes.Equal(pt, message) {
 | 
					 | 
				
			||||||
		fmt.Printf("ecies: plaintext doesn't match message (%s)\n",
 | 
					 | 
				
			||||||
			c.Name)
 | 
					 | 
				
			||||||
		t.FailNow()
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	_, err = prv1.Decrypt(rand.Reader, ct, nil, nil)
 | 
					 | 
				
			||||||
	if err == nil {
 | 
					 | 
				
			||||||
		fmt.Printf("ecies: encryption should not have succeeded (%s)\n",
 | 
					 | 
				
			||||||
			c.Name)
 | 
					 | 
				
			||||||
		t.FailNow()
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// Ensure that the basic public key validation in the decryption operation
 | 
					 | 
				
			||||||
// works.
 | 
					 | 
				
			||||||
func TestBasicKeyValidation(t *testing.T) {
 | 
					 | 
				
			||||||
	badBytes := []byte{0, 1, 5, 6, 7, 8, 9}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	prv, err := GenerateKey(rand.Reader, DefaultCurve, nil)
 | 
					 | 
				
			||||||
	if err != nil {
 | 
					 | 
				
			||||||
		fmt.Println(err.Error())
 | 
					 | 
				
			||||||
		t.FailNow()
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	message := []byte("Hello, world.")
 | 
					 | 
				
			||||||
	ct, err := Encrypt(rand.Reader, &prv.PublicKey, message, nil, nil)
 | 
					 | 
				
			||||||
	if err != nil {
 | 
					 | 
				
			||||||
		fmt.Println(err.Error())
 | 
					 | 
				
			||||||
		t.FailNow()
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	for _, b := range badBytes {
 | 
					 | 
				
			||||||
		ct[0] = b
 | 
					 | 
				
			||||||
		_, err := prv.Decrypt(rand.Reader, ct, nil, nil)
 | 
					 | 
				
			||||||
		if err != ErrInvalidPublicKey {
 | 
					 | 
				
			||||||
			fmt.Println("ecies: validated an invalid key")
 | 
					 | 
				
			||||||
			t.FailNow()
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
							
								
								
									
										187
									
								
								Godeps/_workspace/src/github.com/obscuren/ecies/params.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										187
									
								
								Godeps/_workspace/src/github.com/obscuren/ecies/params.go
									
									
									
										generated
									
									
										vendored
									
									
								
							@@ -1,187 +0,0 @@
 | 
				
			|||||||
package ecies
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// This file contains parameters for ECIES encryption, specifying the
 | 
					 | 
				
			||||||
// symmetric encryption and HMAC parameters.
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
import (
 | 
					 | 
				
			||||||
	"crypto"
 | 
					 | 
				
			||||||
	"crypto/aes"
 | 
					 | 
				
			||||||
	"crypto/cipher"
 | 
					 | 
				
			||||||
	"crypto/elliptic"
 | 
					 | 
				
			||||||
	"crypto/sha256"
 | 
					 | 
				
			||||||
	"crypto/sha512"
 | 
					 | 
				
			||||||
	"fmt"
 | 
					 | 
				
			||||||
	"hash"
 | 
					 | 
				
			||||||
)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// The default curve for this package is the NIST P256 curve, which
 | 
					 | 
				
			||||||
// provides security equivalent to AES-128.
 | 
					 | 
				
			||||||
var DefaultCurve = elliptic.P256()
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
var (
 | 
					 | 
				
			||||||
	ErrUnsupportedECDHAlgorithm   = fmt.Errorf("ecies: unsupported ECDH algorithm")
 | 
					 | 
				
			||||||
	ErrUnsupportedECIESParameters = fmt.Errorf("ecies: unsupported ECIES parameters")
 | 
					 | 
				
			||||||
)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
type ECIESParams struct {
 | 
					 | 
				
			||||||
	Hash      func() hash.Hash // hash function
 | 
					 | 
				
			||||||
	hashAlgo  crypto.Hash
 | 
					 | 
				
			||||||
	Cipher    func([]byte) (cipher.Block, error) // symmetric cipher
 | 
					 | 
				
			||||||
	BlockSize int                                // block size of symmetric cipher
 | 
					 | 
				
			||||||
	KeyLen    int                                // length of symmetric key
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// Standard ECIES parameters:
 | 
					 | 
				
			||||||
// * ECIES using AES128 and HMAC-SHA-256-16
 | 
					 | 
				
			||||||
// * ECIES using AES256 and HMAC-SHA-256-32
 | 
					 | 
				
			||||||
// * ECIES using AES256 and HMAC-SHA-384-48
 | 
					 | 
				
			||||||
// * ECIES using AES256 and HMAC-SHA-512-64
 | 
					 | 
				
			||||||
var (
 | 
					 | 
				
			||||||
	ECIES_AES128_SHA256 *ECIESParams
 | 
					 | 
				
			||||||
	ECIES_AES256_SHA256 *ECIESParams
 | 
					 | 
				
			||||||
	ECIES_AES256_SHA384 *ECIESParams
 | 
					 | 
				
			||||||
	ECIES_AES256_SHA512 *ECIESParams
 | 
					 | 
				
			||||||
)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func init() {
 | 
					 | 
				
			||||||
	ECIES_AES128_SHA256 = &ECIESParams{
 | 
					 | 
				
			||||||
		Hash:      sha256.New,
 | 
					 | 
				
			||||||
		hashAlgo:  crypto.SHA256,
 | 
					 | 
				
			||||||
		Cipher:    aes.NewCipher,
 | 
					 | 
				
			||||||
		BlockSize: aes.BlockSize,
 | 
					 | 
				
			||||||
		KeyLen:    16,
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	ECIES_AES256_SHA256 = &ECIESParams{
 | 
					 | 
				
			||||||
		Hash:      sha256.New,
 | 
					 | 
				
			||||||
		hashAlgo:  crypto.SHA256,
 | 
					 | 
				
			||||||
		Cipher:    aes.NewCipher,
 | 
					 | 
				
			||||||
		BlockSize: aes.BlockSize,
 | 
					 | 
				
			||||||
		KeyLen:    32,
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	ECIES_AES256_SHA384 = &ECIESParams{
 | 
					 | 
				
			||||||
		Hash:      sha512.New384,
 | 
					 | 
				
			||||||
		hashAlgo:  crypto.SHA384,
 | 
					 | 
				
			||||||
		Cipher:    aes.NewCipher,
 | 
					 | 
				
			||||||
		BlockSize: aes.BlockSize,
 | 
					 | 
				
			||||||
		KeyLen:    32,
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	ECIES_AES256_SHA512 = &ECIESParams{
 | 
					 | 
				
			||||||
		Hash:      sha512.New,
 | 
					 | 
				
			||||||
		hashAlgo:  crypto.SHA512,
 | 
					 | 
				
			||||||
		Cipher:    aes.NewCipher,
 | 
					 | 
				
			||||||
		BlockSize: aes.BlockSize,
 | 
					 | 
				
			||||||
		KeyLen:    32,
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
var paramsFromCurve = map[elliptic.Curve]*ECIESParams{
 | 
					 | 
				
			||||||
	elliptic.P256(): ECIES_AES128_SHA256,
 | 
					 | 
				
			||||||
	elliptic.P384(): ECIES_AES256_SHA384,
 | 
					 | 
				
			||||||
	elliptic.P521(): ECIES_AES256_SHA512,
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func AddParamsForCurve(curve elliptic.Curve, params *ECIESParams) {
 | 
					 | 
				
			||||||
	paramsFromCurve[curve] = params
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// ParamsFromCurve selects parameters optimal for the selected elliptic curve.
 | 
					 | 
				
			||||||
// Only the curves P256, P384, and P512 are supported.
 | 
					 | 
				
			||||||
func ParamsFromCurve(curve elliptic.Curve) (params *ECIESParams) {
 | 
					 | 
				
			||||||
	return paramsFromCurve[curve]
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	/*
 | 
					 | 
				
			||||||
		switch curve {
 | 
					 | 
				
			||||||
		case elliptic.P256():
 | 
					 | 
				
			||||||
			return ECIES_AES128_SHA256
 | 
					 | 
				
			||||||
		case elliptic.P384():
 | 
					 | 
				
			||||||
			return ECIES_AES256_SHA384
 | 
					 | 
				
			||||||
		case elliptic.P521():
 | 
					 | 
				
			||||||
			return ECIES_AES256_SHA512
 | 
					 | 
				
			||||||
		default:
 | 
					 | 
				
			||||||
			return nil
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	*/
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// ASN.1 encode the ECIES parameters relevant to the encryption operations.
 | 
					 | 
				
			||||||
func paramsToASNECIES(params *ECIESParams) (asnParams asnECIESParameters) {
 | 
					 | 
				
			||||||
	if nil == params {
 | 
					 | 
				
			||||||
		return
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	asnParams.KDF = asnNISTConcatenationKDF
 | 
					 | 
				
			||||||
	asnParams.MAC = hmacFull
 | 
					 | 
				
			||||||
	switch params.KeyLen {
 | 
					 | 
				
			||||||
	case 16:
 | 
					 | 
				
			||||||
		asnParams.Sym = aes128CTRinECIES
 | 
					 | 
				
			||||||
	case 24:
 | 
					 | 
				
			||||||
		asnParams.Sym = aes192CTRinECIES
 | 
					 | 
				
			||||||
	case 32:
 | 
					 | 
				
			||||||
		asnParams.Sym = aes256CTRinECIES
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	return
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// ASN.1 encode the ECIES parameters relevant to ECDH.
 | 
					 | 
				
			||||||
func paramsToASNECDH(params *ECIESParams) (algo asnECDHAlgorithm) {
 | 
					 | 
				
			||||||
	switch params.hashAlgo {
 | 
					 | 
				
			||||||
	case crypto.SHA224:
 | 
					 | 
				
			||||||
		algo = dhSinglePass_stdDH_sha224kdf
 | 
					 | 
				
			||||||
	case crypto.SHA256:
 | 
					 | 
				
			||||||
		algo = dhSinglePass_stdDH_sha256kdf
 | 
					 | 
				
			||||||
	case crypto.SHA384:
 | 
					 | 
				
			||||||
		algo = dhSinglePass_stdDH_sha384kdf
 | 
					 | 
				
			||||||
	case crypto.SHA512:
 | 
					 | 
				
			||||||
		algo = dhSinglePass_stdDH_sha512kdf
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	return
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// ASN.1 decode the ECIES parameters relevant to the encryption stage.
 | 
					 | 
				
			||||||
func asnECIEStoParams(asnParams asnECIESParameters, params *ECIESParams) {
 | 
					 | 
				
			||||||
	if !asnParams.KDF.Cmp(asnNISTConcatenationKDF) {
 | 
					 | 
				
			||||||
		params = nil
 | 
					 | 
				
			||||||
		return
 | 
					 | 
				
			||||||
	} else if !asnParams.MAC.Cmp(hmacFull) {
 | 
					 | 
				
			||||||
		params = nil
 | 
					 | 
				
			||||||
		return
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	switch {
 | 
					 | 
				
			||||||
	case asnParams.Sym.Cmp(aes128CTRinECIES):
 | 
					 | 
				
			||||||
		params.KeyLen = 16
 | 
					 | 
				
			||||||
		params.BlockSize = 16
 | 
					 | 
				
			||||||
		params.Cipher = aes.NewCipher
 | 
					 | 
				
			||||||
	case asnParams.Sym.Cmp(aes192CTRinECIES):
 | 
					 | 
				
			||||||
		params.KeyLen = 24
 | 
					 | 
				
			||||||
		params.BlockSize = 16
 | 
					 | 
				
			||||||
		params.Cipher = aes.NewCipher
 | 
					 | 
				
			||||||
	case asnParams.Sym.Cmp(aes256CTRinECIES):
 | 
					 | 
				
			||||||
		params.KeyLen = 32
 | 
					 | 
				
			||||||
		params.BlockSize = 16
 | 
					 | 
				
			||||||
		params.Cipher = aes.NewCipher
 | 
					 | 
				
			||||||
	default:
 | 
					 | 
				
			||||||
		params = nil
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// ASN.1 decode the ECIES parameters relevant to ECDH.
 | 
					 | 
				
			||||||
func asnECDHtoParams(asnParams asnECDHAlgorithm, params *ECIESParams) {
 | 
					 | 
				
			||||||
	if asnParams.Cmp(dhSinglePass_stdDH_sha224kdf) {
 | 
					 | 
				
			||||||
		params.hashAlgo = crypto.SHA224
 | 
					 | 
				
			||||||
		params.Hash = sha256.New224
 | 
					 | 
				
			||||||
	} else if asnParams.Cmp(dhSinglePass_stdDH_sha256kdf) {
 | 
					 | 
				
			||||||
		params.hashAlgo = crypto.SHA256
 | 
					 | 
				
			||||||
		params.Hash = sha256.New
 | 
					 | 
				
			||||||
	} else if asnParams.Cmp(dhSinglePass_stdDH_sha384kdf) {
 | 
					 | 
				
			||||||
		params.hashAlgo = crypto.SHA384
 | 
					 | 
				
			||||||
		params.Hash = sha512.New384
 | 
					 | 
				
			||||||
	} else if asnParams.Cmp(dhSinglePass_stdDH_sha512kdf) {
 | 
					 | 
				
			||||||
		params.hashAlgo = crypto.SHA512
 | 
					 | 
				
			||||||
		params.Hash = sha512.New
 | 
					 | 
				
			||||||
	} else {
 | 
					 | 
				
			||||||
		params = nil
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
@@ -64,6 +64,20 @@ func Dial(url_, protocol, origin string) (ws *Conn, err error) {
 | 
				
			|||||||
	return DialConfig(config)
 | 
						return DialConfig(config)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					var portMap = map[string]string{
 | 
				
			||||||
 | 
						"ws":  "80",
 | 
				
			||||||
 | 
						"wss": "443",
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func parseAuthority(location *url.URL) string {
 | 
				
			||||||
 | 
						if _, ok := portMap[location.Scheme]; ok {
 | 
				
			||||||
 | 
							if _, _, err := net.SplitHostPort(location.Host); err != nil {
 | 
				
			||||||
 | 
								return net.JoinHostPort(location.Host, portMap[location.Scheme])
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return location.Host
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// DialConfig opens a new client connection to a WebSocket with a config.
 | 
					// DialConfig opens a new client connection to a WebSocket with a config.
 | 
				
			||||||
func DialConfig(config *Config) (ws *Conn, err error) {
 | 
					func DialConfig(config *Config) (ws *Conn, err error) {
 | 
				
			||||||
	var client net.Conn
 | 
						var client net.Conn
 | 
				
			||||||
@@ -75,10 +89,10 @@ func DialConfig(config *Config) (ws *Conn, err error) {
 | 
				
			|||||||
	}
 | 
						}
 | 
				
			||||||
	switch config.Location.Scheme {
 | 
						switch config.Location.Scheme {
 | 
				
			||||||
	case "ws":
 | 
						case "ws":
 | 
				
			||||||
		client, err = net.Dial("tcp", config.Location.Host)
 | 
							client, err = net.Dial("tcp", parseAuthority(config.Location))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	case "wss":
 | 
						case "wss":
 | 
				
			||||||
		client, err = tls.Dial("tcp", config.Location.Host, config.TlsConfig)
 | 
							client, err = tls.Dial("tcp", parseAuthority(config.Location), config.TlsConfig)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	default:
 | 
						default:
 | 
				
			||||||
		err = ErrBadScheme
 | 
							err = ErrBadScheme
 | 
				
			||||||
@@ -8,7 +8,7 @@ import (
 | 
				
			|||||||
	"fmt"
 | 
						"fmt"
 | 
				
			||||||
	"log"
 | 
						"log"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	"code.google.com/p/go.net/websocket"
 | 
						"golang.org/x/net/websocket"
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// This example demonstrates a trivial client.
 | 
					// This example demonstrates a trivial client.
 | 
				
			||||||
@@ -8,7 +8,7 @@ import (
 | 
				
			|||||||
	"io"
 | 
						"io"
 | 
				
			||||||
	"net/http"
 | 
						"net/http"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	"code.google.com/p/go.net/websocket"
 | 
						"golang.org/x/net/websocket"
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// Echo the data received on the WebSocket.
 | 
					// Echo the data received on the WebSocket.
 | 
				
			||||||
@@ -339,3 +339,76 @@ func TestSmallBuffer(t *testing.T) {
 | 
				
			|||||||
	}
 | 
						}
 | 
				
			||||||
	conn.Close()
 | 
						conn.Close()
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					var parseAuthorityTests = []struct {
 | 
				
			||||||
 | 
						in  *url.URL
 | 
				
			||||||
 | 
						out string
 | 
				
			||||||
 | 
					}{
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							&url.URL{
 | 
				
			||||||
 | 
								Scheme: "ws",
 | 
				
			||||||
 | 
								Host:   "www.google.com",
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
							"www.google.com:80",
 | 
				
			||||||
 | 
						},
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							&url.URL{
 | 
				
			||||||
 | 
								Scheme: "wss",
 | 
				
			||||||
 | 
								Host:   "www.google.com",
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
							"www.google.com:443",
 | 
				
			||||||
 | 
						},
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							&url.URL{
 | 
				
			||||||
 | 
								Scheme: "ws",
 | 
				
			||||||
 | 
								Host:   "www.google.com:80",
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
							"www.google.com:80",
 | 
				
			||||||
 | 
						},
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							&url.URL{
 | 
				
			||||||
 | 
								Scheme: "wss",
 | 
				
			||||||
 | 
								Host:   "www.google.com:443",
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
							"www.google.com:443",
 | 
				
			||||||
 | 
						},
 | 
				
			||||||
 | 
						// some invalid ones for parseAuthority. parseAuthority doesn't
 | 
				
			||||||
 | 
						// concern itself with the scheme unless it actually knows about it
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							&url.URL{
 | 
				
			||||||
 | 
								Scheme: "http",
 | 
				
			||||||
 | 
								Host:   "www.google.com",
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
							"www.google.com",
 | 
				
			||||||
 | 
						},
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							&url.URL{
 | 
				
			||||||
 | 
								Scheme: "http",
 | 
				
			||||||
 | 
								Host:   "www.google.com:80",
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
							"www.google.com:80",
 | 
				
			||||||
 | 
						},
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							&url.URL{
 | 
				
			||||||
 | 
								Scheme: "asdf",
 | 
				
			||||||
 | 
								Host:   "127.0.0.1",
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
							"127.0.0.1",
 | 
				
			||||||
 | 
						},
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							&url.URL{
 | 
				
			||||||
 | 
								Scheme: "asdf",
 | 
				
			||||||
 | 
								Host:   "www.google.com",
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
							"www.google.com",
 | 
				
			||||||
 | 
						},
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func TestParseAuthority(t *testing.T) {
 | 
				
			||||||
 | 
						for _, tt := range parseAuthorityTests {
 | 
				
			||||||
 | 
							out := parseAuthority(tt.in)
 | 
				
			||||||
 | 
							if out != tt.out {
 | 
				
			||||||
 | 
								t.Errorf("got %v; want %v", out, tt.out)
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@@ -2,10 +2,10 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
Ethereum Go Client © 2014 Jeffrey Wilcke.
 | 
					Ethereum Go Client © 2014 Jeffrey Wilcke.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
          | Linux   | OSX | Windows
 | 
					          | Linux   | OSX | Windows | Tests
 | 
				
			||||||
----------|---------|-----|--------
 | 
					----------|---------|-----|---------|------
 | 
				
			||||||
develop   | [](http://build.ethdev.com/builders/Linux%20Go%20develop%20branch/builds/-1) | [](http://build.ethdev.com/builders/OSX%20Go%20develop%20branch/builds/-1) | N/A
 | 
					develop   | [](https://build.ethdev.com/builders/Linux%20Go%20develop%20branch/builds/-1) | [](https://build.ethdev.com/builders/OSX%20Go%20develop%20branch/builds/-1) | N/A | [](https://travis-ci.org/ethereum/go-ethereum)
 | 
				
			||||||
master    | [](http://build.ethdev.com/builders/Linux%20Go%20master%20branch/builds/-1) | [](http://build.ethdev.com/builders/OSX%20Go%20master%20branch/builds/-1) | N/A
 | 
					master    | [](https://build.ethdev.com/builders/Linux%20Go%20master%20branch/builds/-1) | [](https://build.ethdev.com/builders/OSX%20Go%20master%20branch/builds/-1) | N/A | [](https://travis-ci.org/ethereum/go-ethereum)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
[](https://waffle.io/ethereum/go-ethereum)
 | 
					[](https://waffle.io/ethereum/go-ethereum)
 | 
				
			||||||
[](https://waffle.io/ethereum/go-ethereum)
 | 
					[](https://waffle.io/ethereum/go-ethereum)
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,8 +1,10 @@
 | 
				
			|||||||
package accounts
 | 
					package accounts
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import (
 | 
					import (
 | 
				
			||||||
	"github.com/ethereum/go-ethereum/crypto"
 | 
					 | 
				
			||||||
	"testing"
 | 
						"testing"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						"github.com/ethereum/go-ethereum/crypto"
 | 
				
			||||||
 | 
						"github.com/ethereum/go-ethereum/crypto/randentropy"
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func TestAccountManager(t *testing.T) {
 | 
					func TestAccountManager(t *testing.T) {
 | 
				
			||||||
@@ -10,7 +12,7 @@ func TestAccountManager(t *testing.T) {
 | 
				
			|||||||
	am := NewAccountManager(ks)
 | 
						am := NewAccountManager(ks)
 | 
				
			||||||
	pass := "" // not used but required by API
 | 
						pass := "" // not used but required by API
 | 
				
			||||||
	a1, err := am.NewAccount(pass)
 | 
						a1, err := am.NewAccount(pass)
 | 
				
			||||||
	toSign := crypto.GetEntropyCSPRNG(32)
 | 
						toSign := randentropy.GetEntropyCSPRNG(32)
 | 
				
			||||||
	_, err = am.Sign(a1, pass, toSign)
 | 
						_, err = am.Sign(a1, pass, toSign)
 | 
				
			||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
		t.Fatal(err)
 | 
							t.Fatal(err)
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -132,7 +132,7 @@ func Init() {
 | 
				
			|||||||
		natstr      = flag.String("nat", "any", "port mapping mechanism (any|none|upnp|pmp|extip:<IP>)")
 | 
							natstr      = flag.String("nat", "any", "port mapping mechanism (any|none|upnp|pmp|extip:<IP>)")
 | 
				
			||||||
	)
 | 
						)
 | 
				
			||||||
	flag.BoolVar(&Dial, "dial", true, "dial out connections (default on)")
 | 
						flag.BoolVar(&Dial, "dial", true, "dial out connections (default on)")
 | 
				
			||||||
	flag.BoolVar(&SHH, "shh", true, "run whisper protocol (default on)")
 | 
						//flag.BoolVar(&SHH, "shh", true, "run whisper protocol (default on)")
 | 
				
			||||||
	flag.StringVar(&OutboundPort, "port", "30303", "listening port")
 | 
						flag.StringVar(&OutboundPort, "port", "30303", "listening port")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	flag.StringVar(&BootNodes, "bootnodes", "", "space-separated node URLs for discovery bootstrap")
 | 
						flag.StringVar(&BootNodes, "bootnodes", "", "space-separated node URLs for discovery bootstrap")
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -37,7 +37,7 @@ import (
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
const (
 | 
					const (
 | 
				
			||||||
	ClientIdentifier = "Ethereum(G)"
 | 
						ClientIdentifier = "Ethereum(G)"
 | 
				
			||||||
	Version          = "0.8.3"
 | 
						Version          = "0.8.5"
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
var clilogger = logger.NewLogger("CLI")
 | 
					var clilogger = logger.NewLogger("CLI")
 | 
				
			||||||
@@ -67,11 +67,12 @@ func main() {
 | 
				
			|||||||
		DataDir:   Datadir,
 | 
							DataDir:   Datadir,
 | 
				
			||||||
		LogFile:   LogFile,
 | 
							LogFile:   LogFile,
 | 
				
			||||||
		LogLevel:  LogLevel,
 | 
							LogLevel:  LogLevel,
 | 
				
			||||||
 | 
							LogFormat: LogFormat,
 | 
				
			||||||
		MaxPeers:  MaxPeer,
 | 
							MaxPeers:  MaxPeer,
 | 
				
			||||||
		Port:      OutboundPort,
 | 
							Port:      OutboundPort,
 | 
				
			||||||
		NAT:       NAT,
 | 
							NAT:       NAT,
 | 
				
			||||||
		KeyRing:   KeyRing,
 | 
							KeyRing:   KeyRing,
 | 
				
			||||||
		Shh:       SHH,
 | 
							Shh:       true,
 | 
				
			||||||
		Dial:      Dial,
 | 
							Dial:      Dial,
 | 
				
			||||||
		BootNodes: BootNodes,
 | 
							BootNodes: BootNodes,
 | 
				
			||||||
		NodeKey:   NodeKey,
 | 
							NodeKey:   NodeKey,
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -51,8 +51,8 @@ func StateObjectFromAccount(db ethutil.Database, addr string, account Account) *
 | 
				
			|||||||
	if ethutil.IsHex(account.Code) {
 | 
						if ethutil.IsHex(account.Code) {
 | 
				
			||||||
		account.Code = account.Code[2:]
 | 
							account.Code = account.Code[2:]
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	obj.Code = ethutil.Hex2Bytes(account.Code)
 | 
						obj.SetCode(ethutil.Hex2Bytes(account.Code))
 | 
				
			||||||
	obj.Nonce = ethutil.Big(account.Nonce).Uint64()
 | 
						obj.SetNonce(ethutil.Big(account.Nonce).Uint64())
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return obj
 | 
						return obj
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										22
									
								
								cmd/mist/assets/examples/bomb.html
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										22
									
								
								cmd/mist/assets/examples/bomb.html
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,22 @@
 | 
				
			|||||||
 | 
					<html>
 | 
				
			||||||
 | 
					<head>
 | 
				
			||||||
 | 
					<script src="../ext/bignumber.min.js"></script>
 | 
				
			||||||
 | 
					<script src="../ext/ethereum.js/dist/ethereum.js"></script>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					<script>
 | 
				
			||||||
 | 
					var web3 = require('web3');
 | 
				
			||||||
 | 
					web3.setProvider(new web3.providers.HttpSyncProvider('http://localhost:8545'));
 | 
				
			||||||
 | 
					var eth = web3.eth;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					function bomb() {
 | 
				
			||||||
 | 
					    for (var i = 0; i < 200; i++) {
 | 
				
			||||||
 | 
					        eth.transact({})
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					</script>
 | 
				
			||||||
 | 
					</head>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					<body>
 | 
				
			||||||
 | 
					<button onclick="bomb();">BOOM!</button>
 | 
				
			||||||
 | 
					</body>
 | 
				
			||||||
 | 
					</html>
 | 
				
			||||||
@@ -14,8 +14,9 @@
 | 
				
			|||||||
</div>
 | 
					</div>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
<div>
 | 
					<div>
 | 
				
			||||||
	<span class="amount">Amount:</span>
 | 
						<span>Address:</span>
 | 
				
			||||||
	<input type="text" id="address" style="width:200px">
 | 
						<input type="text" id="address" style="width:200px">
 | 
				
			||||||
 | 
						<span>Amount:</span>
 | 
				
			||||||
	<input type="text" id="amount" style="width:200px">
 | 
						<input type="text" id="amount" style="width:200px">
 | 
				
			||||||
	<button onclick="transact()">Send</button>
 | 
						<button onclick="transact()">Send</button>
 | 
				
			||||||
</div>
 | 
					</div>
 | 
				
			||||||
@@ -58,7 +59,7 @@
 | 
				
			|||||||
		}],
 | 
							}],
 | 
				
			||||||
		"outputs": []
 | 
							"outputs": []
 | 
				
			||||||
	}, {
 | 
						}, {
 | 
				
			||||||
		"name":"received",
 | 
							"name":"Changed",
 | 
				
			||||||
		"type":"event",
 | 
							"type":"event",
 | 
				
			||||||
		"inputs": [
 | 
							"inputs": [
 | 
				
			||||||
			{"name":"from","type":"address","indexed":true},
 | 
								{"name":"from","type":"address","indexed":true},
 | 
				
			||||||
@@ -69,23 +70,14 @@
 | 
				
			|||||||
	var address = localStorage.getItem("address");
 | 
						var address = localStorage.getItem("address");
 | 
				
			||||||
	// deploy if not exist
 | 
						// deploy if not exist
 | 
				
			||||||
	if (address == null) {
 | 
						if (address == null) {
 | 
				
			||||||
		var code = "0x60056013565b61012b806100346000396000f35b6103e8600033600160a060020a0316600052602052604060002081905550560060e060020a6000350480637bb98a681461002b578063d0679d3414610039578063e3d670d71461004d57005b610033610126565b60006000f35b610047600435602435610062565b60006000f35b610058600435610104565b8060005260206000f35b80600033600160a060020a0316600052602052604060002054101561008657610100565b80600033600160a060020a0316600052602052604060002090815403908190555080600083600160a060020a0316600052602052604060002090815401908190555033600160a060020a0316600052806020527ff11e547d796cc64acdf758e7cee90439494fd886a19159454aa61e473fdbafef60406000a15b5050565b6000600082600160a060020a03166000526020526040600020549050919050565b5b60008156";
 | 
							var code = "0x60056013565b61014f8061003a6000396000f35b620f42406000600033600160a060020a0316815260200190815260200160002081905550560060e060020a600035048063d0679d3414610020578063e3d670d71461003457005b61002e600435602435610049565b60006000f35b61003f600435610129565b8060005260206000f35b806000600033600160a060020a03168152602001908152602001600020541061007157610076565b610125565b806000600033600160a060020a03168152602001908152602001600020908154039081905550806000600084600160a060020a031681526020019081526020016000209081540190819055508033600160a060020a03167fb52dda022b6c1a1f40905a85f257f689aa5d69d850e49cf939d688fbe5af594660006000a38082600160a060020a03167fb52dda022b6c1a1f40905a85f257f689aa5d69d850e49cf939d688fbe5af594660006000a35b5050565b60006000600083600160a060020a0316815260200190815260200160002054905091905056";
 | 
				
			||||||
		address = web3.eth.transact({data: code});
 | 
							address = web3.eth.transact({data: code});
 | 
				
			||||||
        	localStorage.setItem("address", address);
 | 
					        	localStorage.setItem("address", address);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	document.querySelector("#contract_addr").innerHTML = address.toUpperCase();
 | 
						document.querySelector("#contract_addr").innerHTML = address;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	var contract = web3.eth.contract(address, desc);
 | 
						var contract = web3.eth.contract(address, desc);
 | 
				
			||||||
	contract.received({from: eth.coinbase}).changed(function() {
 | 
						contract.Changed({from: eth.coinbase}).changed(function() {
 | 
				
			||||||
		refresh();
 | 
					 | 
				
			||||||
	});
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	var ev = contract.SingleTransact({})
 | 
					 | 
				
			||||||
	ev.watch(function(log) {
 | 
					 | 
				
			||||||
	someElement.innerHTML += "tnaheousnthaoeu";
 | 
					 | 
				
			||||||
	});
 | 
					 | 
				
			||||||
	
 | 
					 | 
				
			||||||
	eth.watch('chain').changed(function() {
 | 
					 | 
				
			||||||
		refresh();
 | 
							refresh();
 | 
				
			||||||
	});
 | 
						});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -98,7 +90,7 @@
 | 
				
			|||||||
		var storage = eth.storageAt(address);
 | 
							var storage = eth.storageAt(address);
 | 
				
			||||||
		table.innerHTML = "";
 | 
							table.innerHTML = "";
 | 
				
			||||||
		for( var item in storage ) {
 | 
							for( var item in storage ) {
 | 
				
			||||||
			table.innerHTML += "<tr><td>"+item.toUpperCase()+"</td><td>"+web3.toDecimal(storage[item])+"</td></tr>";
 | 
								table.innerHTML += "<tr><td>"+item+"</td><td>"+web3.toDecimal(storage[item])+"</td></tr>";
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -111,6 +103,7 @@
 | 
				
			|||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		var value = parseInt( document.querySelector("#amount").value );
 | 
							var value = parseInt( document.querySelector("#amount").value );
 | 
				
			||||||
 | 
							console.log("transact: ", to, " => ", value)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		contract.send( to, value );
 | 
							contract.send( to, value );
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
@@ -126,7 +119,7 @@ contract JevCoin {
 | 
				
			|||||||
        balances[msg.sender] = 1000000;
 | 
					        balances[msg.sender] = 1000000;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 
 | 
					 
 | 
				
			||||||
    event changed(address indexed from, address indexed to);
 | 
					    event Changed(address indexed from, uint indexed amount);
 | 
				
			||||||
    function send(address to, uint value)
 | 
					    function send(address to, uint value)
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        if( balances[msg.sender] < value ) return;
 | 
					        if( balances[msg.sender] < value ) return;
 | 
				
			||||||
@@ -134,7 +127,8 @@ contract JevCoin {
 | 
				
			|||||||
        balances[msg.sender] -= value;
 | 
					        balances[msg.sender] -= value;
 | 
				
			||||||
        balances[to] += value;
 | 
					        balances[to] += value;
 | 
				
			||||||
 
 | 
					 
 | 
				
			||||||
        changed(msg.sender, to);
 | 
					        Changed(msg.sender, value);
 | 
				
			||||||
 | 
					        Changed(to, value);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 
 | 
					 
 | 
				
			||||||
    function balance(address who) constant returns(uint t)
 | 
					    function balance(address who) constant returns(uint t)
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -71,6 +71,10 @@
 | 
				
			|||||||
    document.querySelector("#gas_price").innerHTML = eth.gasPrice;
 | 
					    document.querySelector("#gas_price").innerHTML = eth.gasPrice;
 | 
				
			||||||
    document.querySelector("#mining").innerHTML = eth.mining;
 | 
					    document.querySelector("#mining").innerHTML = eth.mining;
 | 
				
			||||||
    document.querySelector("#listening").innerHTML = eth.listening;
 | 
					    document.querySelector("#listening").innerHTML = eth.listening;
 | 
				
			||||||
 | 
					    eth.watch('chain').changed(function() {
 | 
				
			||||||
 | 
							    document.querySelector("#number").innerHTML = eth.number;
 | 
				
			||||||
 | 
							     });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
</script>
 | 
					</script>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
</html>
 | 
					</html>
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1417,6 +1417,8 @@ var ethMethods = function () {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    var methods = [
 | 
					    var methods = [
 | 
				
			||||||
    { name: 'balanceAt', call: 'eth_balanceAt' },
 | 
					    { name: 'balanceAt', call: 'eth_balanceAt' },
 | 
				
			||||||
 | 
					    { name: 'register', call: 'eth_register' },
 | 
				
			||||||
 | 
					    { name: 'unregister', call: 'eth_unregister' },
 | 
				
			||||||
    { name: 'stateAt', call: 'eth_stateAt' },
 | 
					    { name: 'stateAt', call: 'eth_stateAt' },
 | 
				
			||||||
    { name: 'storageAt', call: 'eth_storageAt' },
 | 
					    { name: 'storageAt', call: 'eth_storageAt' },
 | 
				
			||||||
    { name: 'countAt', call: 'eth_countAt'},
 | 
					    { name: 'countAt', call: 'eth_countAt'},
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -256,6 +256,7 @@ ApplicationWindow {
 | 
				
			|||||||
                }
 | 
					                }
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    property var blockModel: ListModel {
 | 
					    property var blockModel: ListModel {
 | 
				
			||||||
@@ -895,7 +896,7 @@ ApplicationWindow {
 | 
				
			|||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        function setWalletValue(value) {
 | 
					        function setWalletValue(value) {
 | 
				
			||||||
            walletValueLabel.text = value
 | 
					            //walletValueLabel.text = value
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        function loadPlugin(name) {
 | 
					        function loadPlugin(name) {
 | 
				
			||||||
@@ -947,7 +948,8 @@ ApplicationWindow {
 | 
				
			|||||||
                     model: peerModel
 | 
					                     model: peerModel
 | 
				
			||||||
                     TableViewColumn{width: 180; role: "addr" ; title: "Remote Address" }
 | 
					                     TableViewColumn{width: 180; role: "addr" ; title: "Remote Address" }
 | 
				
			||||||
                     TableViewColumn{width: 280; role: "nodeID" ; title: "Node ID" }
 | 
					                     TableViewColumn{width: 280; role: "nodeID" ; title: "Node ID" }
 | 
				
			||||||
                     TableViewColumn{width: 180; role: "caps" ; title: "Capabilities" }
 | 
					                     TableViewColumn{width: 100; role: "name" ; title: "Name" }
 | 
				
			||||||
 | 
					                     TableViewColumn{width: 40; role: "caps" ; title: "Capabilities" }
 | 
				
			||||||
                 }
 | 
					                 }
 | 
				
			||||||
             }
 | 
					             }
 | 
				
			||||||
         }
 | 
					         }
 | 
				
			||||||
@@ -978,7 +980,7 @@ ApplicationWindow {
 | 
				
			|||||||
                 anchors.top: parent.top
 | 
					                 anchors.top: parent.top
 | 
				
			||||||
                 anchors.topMargin: 30
 | 
					                 anchors.topMargin: 30
 | 
				
			||||||
                 font.pointSize: 12
 | 
					                 font.pointSize: 12
 | 
				
			||||||
                 text: "<h2>Mist (0.7.10)</h2><br><h3>Development</h3>Jeffrey Wilcke<br>Viktor Trón<br>Felix Lange<br>Taylor Gerring<br>Daniel Nagy<br><h3>UX</h3>Alex van de Sande<br>"
 | 
					                 text: "<h2>Mist (0.8.5)</h2><br><h3>Development</h3>Jeffrey Wilcke<br>Viktor Trón<br>Felix Lange<br>Taylor Gerring<br>Daniel Nagy<br>Gustav Simonsson<br><h3>UX/UI</h3>Alex van de Sande<br>Fabian Vogelsteller"
 | 
				
			||||||
             }
 | 
					             }
 | 
				
			||||||
         }
 | 
					         }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -41,4 +41,13 @@ Rectangle {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
		pendingTxModel.insert(0, {hash: tx.hash, to: tx.address, from: tx.sender, value: tx.value, contract: isContract})
 | 
							pendingTxModel.insert(0, {hash: tx.hash, to: tx.address, from: tx.sender, value: tx.value, contract: isContract})
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						function removeTx(tx) {
 | 
				
			||||||
 | 
							for (var i = 0; i < pendingTxModel.count; i++) {
 | 
				
			||||||
 | 
								if (tx.hash === pendingTxModel.get(i).hash) {
 | 
				
			||||||
 | 
									pendingTxModel.remove(i);
 | 
				
			||||||
 | 
									break;
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -63,6 +63,7 @@ var (
 | 
				
			|||||||
	DebugFile       string
 | 
						DebugFile       string
 | 
				
			||||||
	LogLevel        int
 | 
						LogLevel        int
 | 
				
			||||||
	VmType          int
 | 
						VmType          int
 | 
				
			||||||
 | 
						MinerThreads    int
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// flags specific to gui client
 | 
					// flags specific to gui client
 | 
				
			||||||
@@ -137,6 +138,8 @@ func Init() {
 | 
				
			|||||||
	flag.StringVar(&BootNodes, "bootnodes", "", "space-separated node URLs for discovery bootstrap")
 | 
						flag.StringVar(&BootNodes, "bootnodes", "", "space-separated node URLs for discovery bootstrap")
 | 
				
			||||||
	flag.IntVar(&MaxPeer, "maxpeer", 30, "maximum desired peers")
 | 
						flag.IntVar(&MaxPeer, "maxpeer", 30, "maximum desired peers")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						flag.IntVar(&MinerThreads, "minerthreads", runtime.NumCPU(), "number of miner threads")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	flag.Parse()
 | 
						flag.Parse()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	var err error
 | 
						var err error
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -131,6 +131,7 @@ func (gui *Gui) Start(assetPath string) {
 | 
				
			|||||||
	context.SetVar("gui", gui)
 | 
						context.SetVar("gui", gui)
 | 
				
			||||||
	context.SetVar("eth", gui.uiLib)
 | 
						context.SetVar("eth", gui.uiLib)
 | 
				
			||||||
	context.SetVar("shh", gui.whisper)
 | 
						context.SetVar("shh", gui.whisper)
 | 
				
			||||||
 | 
						//clipboard.SetQMLClipboard(context)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	win, err := gui.showWallet(context)
 | 
						win, err := gui.showWallet(context)
 | 
				
			||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
@@ -386,16 +387,11 @@ func (gui *Gui) update() {
 | 
				
			|||||||
	generalUpdateTicker := time.NewTicker(500 * time.Millisecond)
 | 
						generalUpdateTicker := time.NewTicker(500 * time.Millisecond)
 | 
				
			||||||
	statsUpdateTicker := time.NewTicker(5 * time.Second)
 | 
						statsUpdateTicker := time.NewTicker(5 * time.Second)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	state := gui.eth.ChainManager().TransState()
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	gui.win.Root().Call("setWalletValue", fmt.Sprintf("%v", ethutil.CurrencyToString(state.GetAccount(gui.address()).Balance())))
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	lastBlockLabel := gui.getObjectByName("lastBlockLabel")
 | 
						lastBlockLabel := gui.getObjectByName("lastBlockLabel")
 | 
				
			||||||
	miningLabel := gui.getObjectByName("miningLabel")
 | 
						miningLabel := gui.getObjectByName("miningLabel")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	events := gui.eth.EventMux().Subscribe(
 | 
						events := gui.eth.EventMux().Subscribe(
 | 
				
			||||||
		//eth.PeerListEvent{},
 | 
							core.ChainEvent{},
 | 
				
			||||||
		core.NewBlockEvent{},
 | 
					 | 
				
			||||||
		core.TxPreEvent{},
 | 
							core.TxPreEvent{},
 | 
				
			||||||
		core.TxPostEvent{},
 | 
							core.TxPostEvent{},
 | 
				
			||||||
	)
 | 
						)
 | 
				
			||||||
@@ -408,41 +404,13 @@ func (gui *Gui) update() {
 | 
				
			|||||||
				return
 | 
									return
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
			switch ev := ev.(type) {
 | 
								switch ev := ev.(type) {
 | 
				
			||||||
			case core.NewBlockEvent:
 | 
								case core.ChainEvent:
 | 
				
			||||||
				gui.processBlock(ev.Block, false)
 | 
									gui.processBlock(ev.Block, false)
 | 
				
			||||||
				//gui.setWalletValue(gui.eth.ChainManager().State().GetBalance(gui.address()), nil)
 | 
					 | 
				
			||||||
				balance := ethutil.CurrencyToString(gui.eth.ChainManager().State().GetBalance(gui.address()))
 | 
					 | 
				
			||||||
				gui.getObjectByName("balanceLabel").Set("text", fmt.Sprintf("%v", balance))
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
			case core.TxPreEvent:
 | 
								case core.TxPreEvent:
 | 
				
			||||||
				tx := ev.Tx
 | 
									gui.insertTransaction("pre", ev.Tx)
 | 
				
			||||||
 | 
					 | 
				
			||||||
				tstate := gui.eth.ChainManager().TransState()
 | 
					 | 
				
			||||||
				cstate := gui.eth.ChainManager().State()
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
				taccount := tstate.GetAccount(gui.address())
 | 
					 | 
				
			||||||
				caccount := cstate.GetAccount(gui.address())
 | 
					 | 
				
			||||||
				unconfirmedFunds := new(big.Int).Sub(taccount.Balance(), caccount.Balance())
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
				gui.setWalletValue(taccount.Balance(), unconfirmedFunds)
 | 
					 | 
				
			||||||
				gui.insertTransaction("pre", tx)
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
			case core.TxPostEvent:
 | 
								case core.TxPostEvent:
 | 
				
			||||||
				tx := ev.Tx
 | 
									gui.getObjectByName("pendingTxView").Call("removeTx", xeth.NewTx(ev.Tx))
 | 
				
			||||||
				object := state.GetAccount(gui.address())
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
				if bytes.Compare(tx.From(), gui.address()) == 0 {
 | 
					 | 
				
			||||||
					object.SubAmount(tx.Value())
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
					gui.txDb.Put(tx.Hash(), tx.RlpEncode())
 | 
					 | 
				
			||||||
				} else if bytes.Compare(tx.To(), gui.address()) == 0 {
 | 
					 | 
				
			||||||
					object.AddAmount(tx.Value())
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
					gui.txDb.Put(tx.Hash(), tx.RlpEncode())
 | 
					 | 
				
			||||||
				}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
				gui.setWalletValue(object.Balance(), nil)
 | 
					 | 
				
			||||||
				state.UpdateStateObject(object)
 | 
					 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		case <-peerUpdateTicker.C:
 | 
							case <-peerUpdateTicker.C:
 | 
				
			||||||
@@ -453,19 +421,6 @@ func (gui *Gui) update() {
 | 
				
			|||||||
			lastBlockLabel.Set("text", statusText)
 | 
								lastBlockLabel.Set("text", statusText)
 | 
				
			||||||
			miningLabel.Set("text", "Mining @ "+strconv.FormatInt(gui.uiLib.Miner().HashRate(), 10)+"/Khash")
 | 
								miningLabel.Set("text", "Mining @ "+strconv.FormatInt(gui.uiLib.Miner().HashRate(), 10)+"/Khash")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			/*
 | 
					 | 
				
			||||||
				blockLength := gui.eth.BlockPool().BlocksProcessed
 | 
					 | 
				
			||||||
				chainLength := gui.eth.BlockPool().ChainLength
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
				var (
 | 
					 | 
				
			||||||
					pct      float64 = 1.0 / float64(chainLength) * float64(blockLength)
 | 
					 | 
				
			||||||
					dlWidget         = gui.win.Root().ObjectByName("downloadIndicator")
 | 
					 | 
				
			||||||
					dlLabel          = gui.win.Root().ObjectByName("downloadLabel")
 | 
					 | 
				
			||||||
				)
 | 
					 | 
				
			||||||
				dlWidget.Set("value", pct)
 | 
					 | 
				
			||||||
				dlLabel.Set("text", fmt.Sprintf("%d / %d", blockLength, chainLength))
 | 
					 | 
				
			||||||
			*/
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		case <-statsUpdateTicker.C:
 | 
							case <-statsUpdateTicker.C:
 | 
				
			||||||
			gui.setStatsPane()
 | 
								gui.setStatsPane()
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
@@ -498,7 +453,7 @@ NumGC:      %d
 | 
				
			|||||||
	))
 | 
						))
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
type qmlpeer struct{ Addr, NodeID, Caps string }
 | 
					type qmlpeer struct{ Addr, NodeID, Name, Caps string }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
type peersByID []*qmlpeer
 | 
					type peersByID []*qmlpeer
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -513,6 +468,7 @@ func (gui *Gui) setPeerInfo() {
 | 
				
			|||||||
		qpeers[i] = &qmlpeer{
 | 
							qpeers[i] = &qmlpeer{
 | 
				
			||||||
			NodeID: p.ID().String(),
 | 
								NodeID: p.ID().String(),
 | 
				
			||||||
			Addr:   p.RemoteAddr().String(),
 | 
								Addr:   p.RemoteAddr().String(),
 | 
				
			||||||
 | 
								Name:   p.Name(),
 | 
				
			||||||
			Caps:   fmt.Sprint(p.Caps()),
 | 
								Caps:   fmt.Sprint(p.Caps()),
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -36,7 +36,7 @@ import (
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
const (
 | 
					const (
 | 
				
			||||||
	ClientIdentifier = "Mist"
 | 
						ClientIdentifier = "Mist"
 | 
				
			||||||
	Version          = "0.8.3"
 | 
						Version          = "0.8.5"
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
var ethereum *eth.Ethereum
 | 
					var ethereum *eth.Ethereum
 | 
				
			||||||
@@ -52,18 +52,20 @@ func run() error {
 | 
				
			|||||||
	config := utils.InitConfig(VmType, ConfigFile, Datadir, "ETH")
 | 
						config := utils.InitConfig(VmType, ConfigFile, Datadir, "ETH")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	ethereum, err := eth.New(ð.Config{
 | 
						ethereum, err := eth.New(ð.Config{
 | 
				
			||||||
		Name:      p2p.MakeName(ClientIdentifier, Version),
 | 
							Name:         p2p.MakeName(ClientIdentifier, Version),
 | 
				
			||||||
		KeyStore:  KeyStore,
 | 
							KeyStore:     KeyStore,
 | 
				
			||||||
		DataDir:   Datadir,
 | 
							DataDir:      Datadir,
 | 
				
			||||||
		LogFile:   LogFile,
 | 
							LogFile:      LogFile,
 | 
				
			||||||
		LogLevel:  LogLevel,
 | 
							LogLevel:     LogLevel,
 | 
				
			||||||
		MaxPeers:  MaxPeer,
 | 
							MaxPeers:     MaxPeer,
 | 
				
			||||||
		Port:      OutboundPort,
 | 
							Port:         OutboundPort,
 | 
				
			||||||
		NAT:       NAT,
 | 
							NAT:          NAT,
 | 
				
			||||||
		BootNodes: BootNodes,
 | 
							Shh:          true,
 | 
				
			||||||
		NodeKey:   NodeKey,
 | 
							BootNodes:    BootNodes,
 | 
				
			||||||
		KeyRing:   KeyRing,
 | 
							NodeKey:      NodeKey,
 | 
				
			||||||
		Dial:      true,
 | 
							KeyRing:      KeyRing,
 | 
				
			||||||
 | 
							Dial:         true,
 | 
				
			||||||
 | 
							MinerThreads: MinerThreads,
 | 
				
			||||||
	})
 | 
						})
 | 
				
			||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
		mainlogger.Fatalln(err)
 | 
							mainlogger.Fatalln(err)
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -146,8 +146,8 @@ func (ui *UiLib) AssetPath(p string) string {
 | 
				
			|||||||
func (self *UiLib) StartDbWithContractAndData(contractHash, data string) {
 | 
					func (self *UiLib) StartDbWithContractAndData(contractHash, data string) {
 | 
				
			||||||
	dbWindow := NewDebuggerWindow(self)
 | 
						dbWindow := NewDebuggerWindow(self)
 | 
				
			||||||
	object := self.eth.ChainManager().State().GetStateObject(ethutil.Hex2Bytes(contractHash))
 | 
						object := self.eth.ChainManager().State().GetStateObject(ethutil.Hex2Bytes(contractHash))
 | 
				
			||||||
	if len(object.Code) > 0 {
 | 
						if len(object.Code()) > 0 {
 | 
				
			||||||
		dbWindow.SetCode(ethutil.Bytes2Hex(object.Code))
 | 
							dbWindow.SetCode(ethutil.Bytes2Hex(object.Code()))
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	dbWindow.SetData(data)
 | 
						dbWindow.SetData(data)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -225,7 +225,7 @@ func StartMining(ethereum *eth.Ethereum) bool {
 | 
				
			|||||||
		go func() {
 | 
							go func() {
 | 
				
			||||||
			clilogger.Infoln("Start mining")
 | 
								clilogger.Infoln("Start mining")
 | 
				
			||||||
			if gminer == nil {
 | 
								if gminer == nil {
 | 
				
			||||||
				gminer = miner.New(addr, ethereum)
 | 
									gminer = miner.New(addr, ethereum, 4)
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
			gminer.Start()
 | 
								gminer.Start()
 | 
				
			||||||
		}()
 | 
							}()
 | 
				
			||||||
@@ -272,7 +272,7 @@ func BlockDo(ethereum *eth.Ethereum, hash []byte) error {
 | 
				
			|||||||
	parent := ethereum.ChainManager().GetBlock(block.ParentHash())
 | 
						parent := ethereum.ChainManager().GetBlock(block.ParentHash())
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	statedb := state.New(parent.Root(), ethereum.Db())
 | 
						statedb := state.New(parent.Root(), ethereum.Db())
 | 
				
			||||||
	_, err := ethereum.BlockProcessor().TransitionState(statedb, parent, block)
 | 
						_, err := ethereum.BlockProcessor().TransitionState(statedb, parent, block, true)
 | 
				
			||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
		return err
 | 
							return err
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -60,12 +60,12 @@ func NewBlockProcessor(db ethutil.Database, txpool *TxPool, chainManager *ChainM
 | 
				
			|||||||
	return sm
 | 
						return sm
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (sm *BlockProcessor) TransitionState(statedb *state.StateDB, parent, block *types.Block) (receipts types.Receipts, err error) {
 | 
					func (sm *BlockProcessor) TransitionState(statedb *state.StateDB, parent, block *types.Block, transientProcess bool) (receipts types.Receipts, err error) {
 | 
				
			||||||
	coinbase := statedb.GetOrNewStateObject(block.Header().Coinbase)
 | 
						coinbase := statedb.GetOrNewStateObject(block.Header().Coinbase)
 | 
				
			||||||
	coinbase.SetGasPool(CalcGasLimit(parent, block))
 | 
						coinbase.SetGasPool(CalcGasLimit(parent, block))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// Process the transactions on to parent state
 | 
						// Process the transactions on to parent state
 | 
				
			||||||
	receipts, _, _, _, err = sm.ApplyTransactions(coinbase, statedb, block, block.Transactions(), false)
 | 
						receipts, _, _, _, err = sm.ApplyTransactions(coinbase, statedb, block, block.Transactions(), transientProcess)
 | 
				
			||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
		return nil, err
 | 
							return nil, err
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
@@ -73,38 +73,40 @@ func (sm *BlockProcessor) TransitionState(statedb *state.StateDB, parent, block
 | 
				
			|||||||
	return receipts, nil
 | 
						return receipts, nil
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (self *BlockProcessor) ApplyTransaction(coinbase *state.StateObject, state *state.StateDB, block *types.Block, tx *types.Transaction, usedGas *big.Int, transientProcess bool) (*types.Receipt, *big.Int, error) {
 | 
					func (self *BlockProcessor) ApplyTransaction(coinbase *state.StateObject, statedb *state.StateDB, block *types.Block, tx *types.Transaction, usedGas *big.Int, transientProcess bool) (*types.Receipt, *big.Int, error) {
 | 
				
			||||||
	// If we are mining this block and validating we want to set the logs back to 0
 | 
						// If we are mining this block and validating we want to set the logs back to 0
 | 
				
			||||||
	state.EmptyLogs()
 | 
						statedb.EmptyLogs()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	txGas := new(big.Int).Set(tx.Gas())
 | 
						txGas := new(big.Int).Set(tx.Gas())
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	cb := state.GetStateObject(coinbase.Address())
 | 
						cb := statedb.GetStateObject(coinbase.Address())
 | 
				
			||||||
	st := NewStateTransition(NewEnv(state, self.bc, tx, block), tx, cb)
 | 
						st := NewStateTransition(NewEnv(statedb, self.bc, tx, block), tx, cb)
 | 
				
			||||||
	_, err := st.TransitionState()
 | 
						_, err := st.TransitionState()
 | 
				
			||||||
 | 
						if err != nil && (IsNonceErr(err) || state.IsGasLimitErr(err)) {
 | 
				
			||||||
 | 
							return nil, nil, err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	txGas.Sub(txGas, st.gas)
 | 
						txGas.Sub(txGas, st.gas)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// Update the state with pending changes
 | 
						// Update the state with pending changes
 | 
				
			||||||
	state.Update(txGas)
 | 
						statedb.Update(txGas)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	cumulative := new(big.Int).Set(usedGas.Add(usedGas, txGas))
 | 
						cumulative := new(big.Int).Set(usedGas.Add(usedGas, txGas))
 | 
				
			||||||
	receipt := types.NewReceipt(state.Root(), cumulative)
 | 
						receipt := types.NewReceipt(statedb.Root(), cumulative)
 | 
				
			||||||
	receipt.SetLogs(state.Logs())
 | 
						receipt.SetLogs(statedb.Logs())
 | 
				
			||||||
	receipt.Bloom = types.CreateBloom(types.Receipts{receipt})
 | 
						receipt.Bloom = types.CreateBloom(types.Receipts{receipt})
 | 
				
			||||||
	chainlogger.Debugln(receipt)
 | 
						chainlogger.Debugln(receipt)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// Notify all subscribers
 | 
						// Notify all subscribers
 | 
				
			||||||
	if !transientProcess {
 | 
						if !transientProcess {
 | 
				
			||||||
		go self.eventMux.Post(TxPostEvent{tx})
 | 
							go self.eventMux.Post(TxPostEvent{tx})
 | 
				
			||||||
 | 
							go self.eventMux.Post(statedb.Logs())
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	go self.eventMux.Post(state.Logs())
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	return receipt, txGas, err
 | 
						return receipt, txGas, err
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (self *BlockProcessor) ApplyTransactions(coinbase *state.StateObject, state *state.StateDB, block *types.Block, txs types.Transactions, transientProcess bool) (types.Receipts, types.Transactions, types.Transactions, types.Transactions, error) {
 | 
					func (self *BlockProcessor) ApplyTransactions(coinbase *state.StateObject, statedb *state.StateDB, block *types.Block, txs types.Transactions, transientProcess bool) (types.Receipts, types.Transactions, types.Transactions, types.Transactions, error) {
 | 
				
			||||||
	var (
 | 
						var (
 | 
				
			||||||
		receipts           types.Receipts
 | 
							receipts           types.Receipts
 | 
				
			||||||
		handled, unhandled types.Transactions
 | 
							handled, unhandled types.Transactions
 | 
				
			||||||
@@ -115,12 +117,12 @@ func (self *BlockProcessor) ApplyTransactions(coinbase *state.StateObject, state
 | 
				
			|||||||
	)
 | 
						)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	for _, tx := range txs {
 | 
						for _, tx := range txs {
 | 
				
			||||||
		receipt, txGas, err := self.ApplyTransaction(coinbase, state, block, tx, totalUsedGas, transientProcess)
 | 
							receipt, txGas, err := self.ApplyTransaction(coinbase, statedb, block, tx, totalUsedGas, transientProcess)
 | 
				
			||||||
		if err != nil {
 | 
							if err != nil {
 | 
				
			||||||
			switch {
 | 
								switch {
 | 
				
			||||||
			case IsNonceErr(err):
 | 
								case IsNonceErr(err):
 | 
				
			||||||
				return nil, nil, nil, nil, err
 | 
									return nil, nil, nil, nil, err
 | 
				
			||||||
			case IsGasLimitErr(err):
 | 
								case state.IsGasLimitErr(err):
 | 
				
			||||||
				return nil, nil, nil, nil, err
 | 
									return nil, nil, nil, nil, err
 | 
				
			||||||
			default:
 | 
								default:
 | 
				
			||||||
				statelogger.Infoln(err)
 | 
									statelogger.Infoln(err)
 | 
				
			||||||
@@ -176,7 +178,7 @@ func (sm *BlockProcessor) processWithParent(block, parent *types.Block) (td *big
 | 
				
			|||||||
		return
 | 
							return
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	receipts, err := sm.TransitionState(state, parent, block)
 | 
						receipts, err := sm.TransitionState(state, parent, block, false)
 | 
				
			||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
		return
 | 
							return
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
@@ -250,7 +252,11 @@ func (sm *BlockProcessor) ValidateBlock(block, parent *types.Block) error {
 | 
				
			|||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if block.Time() > time.Now().Unix() {
 | 
						if block.Time() > time.Now().Unix() {
 | 
				
			||||||
		return fmt.Errorf("block time is in the future")
 | 
							return BlockFutureErr
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if new(big.Int).Sub(block.Number(), parent.Number()).Cmp(big.NewInt(1)) != 0 {
 | 
				
			||||||
 | 
							return BlockNumberErr
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// Verify the nonce of the block. Return an error if it's not valid
 | 
						// Verify the nonce of the block. Return an error if it's not valid
 | 
				
			||||||
@@ -289,16 +295,13 @@ func (sm *BlockProcessor) AccumulateRewards(statedb *state.StateDB, block, paren
 | 
				
			|||||||
		r := new(big.Int)
 | 
							r := new(big.Int)
 | 
				
			||||||
		r.Mul(BlockReward, big.NewInt(15)).Div(r, big.NewInt(16))
 | 
							r.Mul(BlockReward, big.NewInt(15)).Div(r, big.NewInt(16))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		uncleAccount := statedb.GetAccount(uncle.Coinbase)
 | 
							statedb.AddBalance(uncle.Coinbase, r)
 | 
				
			||||||
		uncleAccount.AddAmount(r)
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
		reward.Add(reward, new(big.Int).Div(BlockReward, big.NewInt(32)))
 | 
							reward.Add(reward, new(big.Int).Div(BlockReward, big.NewInt(32)))
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// Get the account associated with the coinbase
 | 
						// Get the account associated with the coinbase
 | 
				
			||||||
	account := statedb.GetAccount(block.Header().Coinbase)
 | 
						statedb.AddBalance(block.Header().Coinbase, reward)
 | 
				
			||||||
	// Reward amount of ether to the coinbase address
 | 
					 | 
				
			||||||
	account.AddAmount(reward)
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return nil
 | 
						return nil
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
@@ -312,13 +315,10 @@ func (sm *BlockProcessor) GetLogs(block *types.Block) (logs state.Logs, err erro
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
	var (
 | 
						var (
 | 
				
			||||||
		parent = sm.bc.GetBlock(block.Header().ParentHash)
 | 
							parent = sm.bc.GetBlock(block.Header().ParentHash)
 | 
				
			||||||
		//state  = state.New(parent.Trie().Copy())
 | 
							state  = state.New(parent.Root(), sm.db)
 | 
				
			||||||
		state = state.New(parent.Root(), sm.db)
 | 
					 | 
				
			||||||
	)
 | 
						)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	defer state.Reset()
 | 
						sm.TransitionState(state, parent, block, true)
 | 
				
			||||||
 | 
					 | 
				
			||||||
	sm.TransitionState(state, parent, block)
 | 
					 | 
				
			||||||
	sm.AccumulateRewards(state, block, parent)
 | 
						sm.AccumulateRewards(state, block, parent)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return state.Logs(), nil
 | 
						return state.Logs(), nil
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										34
									
								
								core/block_processor_test.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										34
									
								
								core/block_processor_test.go
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,34 @@
 | 
				
			|||||||
 | 
					package core
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import (
 | 
				
			||||||
 | 
						"math/big"
 | 
				
			||||||
 | 
						"testing"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						"github.com/ethereum/go-ethereum/ethdb"
 | 
				
			||||||
 | 
						"github.com/ethereum/go-ethereum/event"
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func proc() (*BlockProcessor, *ChainManager) {
 | 
				
			||||||
 | 
						db, _ := ethdb.NewMemDatabase()
 | 
				
			||||||
 | 
						var mux event.TypeMux
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						chainMan := NewChainManager(db, &mux)
 | 
				
			||||||
 | 
						return NewBlockProcessor(db, nil, chainMan, &mux), chainMan
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func TestNumber(t *testing.T) {
 | 
				
			||||||
 | 
						bp, chain := proc()
 | 
				
			||||||
 | 
						block1 := chain.NewBlock(nil)
 | 
				
			||||||
 | 
						block1.Header().Number = big.NewInt(3)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						err := bp.ValidateBlock(block1, chain.Genesis())
 | 
				
			||||||
 | 
						if err != BlockNumberErr {
 | 
				
			||||||
 | 
							t.Errorf("expected block number error")
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						block1 = chain.NewBlock(nil)
 | 
				
			||||||
 | 
						err = bp.ValidateBlock(block1, chain.Genesis())
 | 
				
			||||||
 | 
						if err == BlockNumberErr {
 | 
				
			||||||
 | 
							t.Errorf("didn't expect block number error")
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@@ -79,6 +79,7 @@ type ChainManager struct {
 | 
				
			|||||||
	genesisBlock *types.Block
 | 
						genesisBlock *types.Block
 | 
				
			||||||
	// Last known total difficulty
 | 
						// Last known total difficulty
 | 
				
			||||||
	mu            sync.RWMutex
 | 
						mu            sync.RWMutex
 | 
				
			||||||
 | 
						tsmu          sync.RWMutex
 | 
				
			||||||
	td            *big.Int
 | 
						td            *big.Int
 | 
				
			||||||
	currentBlock  *types.Block
 | 
						currentBlock  *types.Block
 | 
				
			||||||
	lastBlockHash []byte
 | 
						lastBlockHash []byte
 | 
				
			||||||
@@ -86,6 +87,14 @@ type ChainManager struct {
 | 
				
			|||||||
	transState *state.StateDB
 | 
						transState *state.StateDB
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func NewChainManager(db ethutil.Database, mux *event.TypeMux) *ChainManager {
 | 
				
			||||||
 | 
						bc := &ChainManager{db: db, genesisBlock: GenesisBlock(db), eventMux: mux}
 | 
				
			||||||
 | 
						bc.setLastBlock()
 | 
				
			||||||
 | 
						bc.transState = bc.State().Copy()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return bc
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (self *ChainManager) Td() *big.Int {
 | 
					func (self *ChainManager) Td() *big.Int {
 | 
				
			||||||
	self.mu.RLock()
 | 
						self.mu.RLock()
 | 
				
			||||||
	defer self.mu.RUnlock()
 | 
						defer self.mu.RUnlock()
 | 
				
			||||||
@@ -107,14 +116,6 @@ func (self *ChainManager) CurrentBlock() *types.Block {
 | 
				
			|||||||
	return self.currentBlock
 | 
						return self.currentBlock
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func NewChainManager(db ethutil.Database, mux *event.TypeMux) *ChainManager {
 | 
					 | 
				
			||||||
	bc := &ChainManager{db: db, genesisBlock: GenesisBlock(db), eventMux: mux}
 | 
					 | 
				
			||||||
	bc.setLastBlock()
 | 
					 | 
				
			||||||
	bc.transState = bc.State().Copy()
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	return bc
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func (self *ChainManager) Status() (td *big.Int, currentBlock []byte, genesisBlock []byte) {
 | 
					func (self *ChainManager) Status() (td *big.Int, currentBlock []byte, genesisBlock []byte) {
 | 
				
			||||||
	self.mu.RLock()
 | 
						self.mu.RLock()
 | 
				
			||||||
	defer self.mu.RUnlock()
 | 
						defer self.mu.RUnlock()
 | 
				
			||||||
@@ -131,9 +132,16 @@ func (self *ChainManager) State() *state.StateDB {
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (self *ChainManager) TransState() *state.StateDB {
 | 
					func (self *ChainManager) TransState() *state.StateDB {
 | 
				
			||||||
 | 
						self.tsmu.RLock()
 | 
				
			||||||
 | 
						defer self.tsmu.RUnlock()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return self.transState
 | 
						return self.transState
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (self *ChainManager) setTransState(statedb *state.StateDB) {
 | 
				
			||||||
 | 
						self.transState = statedb
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (bc *ChainManager) setLastBlock() {
 | 
					func (bc *ChainManager) setLastBlock() {
 | 
				
			||||||
	data, _ := bc.db.Get([]byte("LastBlock"))
 | 
						data, _ := bc.db.Get([]byte("LastBlock"))
 | 
				
			||||||
	if len(data) != 0 {
 | 
						if len(data) != 0 {
 | 
				
			||||||
@@ -260,6 +268,7 @@ func (self *ChainManager) GetBlockHashesFromHash(hash []byte, max uint64) (chain
 | 
				
			|||||||
			break
 | 
								break
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
						fmt.Printf("get hash %x (%d)\n", hash, len(chain))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return
 | 
						return
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
@@ -350,6 +359,9 @@ func (bc *ChainManager) Stop() {
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (self *ChainManager) InsertChain(chain types.Blocks) error {
 | 
					func (self *ChainManager) InsertChain(chain types.Blocks) error {
 | 
				
			||||||
 | 
						self.tsmu.Lock()
 | 
				
			||||||
 | 
						defer self.tsmu.Unlock()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	for _, block := range chain {
 | 
						for _, block := range chain {
 | 
				
			||||||
		td, err := self.processor.Process(block)
 | 
							td, err := self.processor.Process(block)
 | 
				
			||||||
		if err != nil {
 | 
							if err != nil {
 | 
				
			||||||
@@ -365,6 +377,7 @@ func (self *ChainManager) InsertChain(chain types.Blocks) error {
 | 
				
			|||||||
		}
 | 
							}
 | 
				
			||||||
		block.Td = td
 | 
							block.Td = td
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							var chain, split bool
 | 
				
			||||||
		self.mu.Lock()
 | 
							self.mu.Lock()
 | 
				
			||||||
		{
 | 
							{
 | 
				
			||||||
			self.write(block)
 | 
								self.write(block)
 | 
				
			||||||
@@ -372,18 +385,25 @@ func (self *ChainManager) InsertChain(chain types.Blocks) error {
 | 
				
			|||||||
			if td.Cmp(self.td) > 0 {
 | 
								if td.Cmp(self.td) > 0 {
 | 
				
			||||||
				if block.Header().Number.Cmp(new(big.Int).Add(cblock.Header().Number, ethutil.Big1)) < 0 {
 | 
									if block.Header().Number.Cmp(new(big.Int).Add(cblock.Header().Number, ethutil.Big1)) < 0 {
 | 
				
			||||||
					chainlogger.Infof("Split detected. New head #%v (%x) TD=%v, was #%v (%x) TD=%v\n", block.Header().Number, block.Hash()[:4], td, cblock.Header().Number, cblock.Hash()[:4], self.td)
 | 
										chainlogger.Infof("Split detected. New head #%v (%x) TD=%v, was #%v (%x) TD=%v\n", block.Header().Number, block.Hash()[:4], td, cblock.Header().Number, cblock.Hash()[:4], self.td)
 | 
				
			||||||
 | 
										split = true
 | 
				
			||||||
				}
 | 
									}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
				self.setTotalDifficulty(td)
 | 
									self.setTotalDifficulty(td)
 | 
				
			||||||
				self.insert(block)
 | 
									self.insert(block)
 | 
				
			||||||
				self.transState = state.New(cblock.Root(), self.db)
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
				self.eventMux.Post(ChainEvent{block, td})
 | 
									chain = true
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		self.mu.Unlock()
 | 
							self.mu.Unlock()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		self.eventMux.Post(NewBlockEvent{block})
 | 
							if chain {
 | 
				
			||||||
 | 
								self.eventMux.Post(ChainEvent{block, td})
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							if split {
 | 
				
			||||||
 | 
								self.setTransState(state.New(block.Root(), self.db))
 | 
				
			||||||
 | 
								self.eventMux.Post(ChainSplitEvent{block})
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return nil
 | 
						return nil
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,10 +1,16 @@
 | 
				
			|||||||
package core
 | 
					package core
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import (
 | 
					import (
 | 
				
			||||||
 | 
						"errors"
 | 
				
			||||||
	"fmt"
 | 
						"fmt"
 | 
				
			||||||
	"math/big"
 | 
						"math/big"
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					var (
 | 
				
			||||||
 | 
						BlockNumberErr = errors.New("block number invalid")
 | 
				
			||||||
 | 
						BlockFutureErr = errors.New("block time is in the future")
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// Parent error. In case a parent is unknown this error will be thrown
 | 
					// Parent error. In case a parent is unknown this error will be thrown
 | 
				
			||||||
// by the block manager
 | 
					// by the block manager
 | 
				
			||||||
type ParentErr struct {
 | 
					type ParentErr struct {
 | 
				
			||||||
@@ -62,23 +68,6 @@ func IsValidationErr(err error) bool {
 | 
				
			|||||||
	return ok
 | 
						return ok
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
type GasLimitErr struct {
 | 
					 | 
				
			||||||
	Message string
 | 
					 | 
				
			||||||
	Is, Max *big.Int
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func IsGasLimitErr(err error) bool {
 | 
					 | 
				
			||||||
	_, ok := err.(*GasLimitErr)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	return ok
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
func (err *GasLimitErr) Error() string {
 | 
					 | 
				
			||||||
	return err.Message
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
func GasLimitError(is, max *big.Int) *GasLimitErr {
 | 
					 | 
				
			||||||
	return &GasLimitErr{Message: fmt.Sprintf("GasLimit error. Max %s, transaction would take it to %s", max, is), Is: is, Max: max}
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
type NonceErr struct {
 | 
					type NonceErr struct {
 | 
				
			||||||
	Message string
 | 
						Message string
 | 
				
			||||||
	Is, Exp uint64
 | 
						Is, Exp uint64
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -13,3 +13,6 @@ type NewBlockEvent struct{ Block *types.Block }
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
// NewMinedBlockEvent is posted when a block has been imported.
 | 
					// NewMinedBlockEvent is posted when a block has been imported.
 | 
				
			||||||
type NewMinedBlockEvent struct{ Block *types.Block }
 | 
					type NewMinedBlockEvent struct{ Block *types.Block }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// ChainSplit is posted when a new head is detected
 | 
				
			||||||
 | 
					type ChainSplitEvent struct{ Block *types.Block }
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -16,7 +16,7 @@ type FilterOptions struct {
 | 
				
			|||||||
	Earliest int64
 | 
						Earliest int64
 | 
				
			||||||
	Latest   int64
 | 
						Latest   int64
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	Address []byte
 | 
						Address [][]byte
 | 
				
			||||||
	Topics  [][]byte
 | 
						Topics  [][]byte
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	Skip int
 | 
						Skip int
 | 
				
			||||||
@@ -29,7 +29,7 @@ type Filter struct {
 | 
				
			|||||||
	earliest int64
 | 
						earliest int64
 | 
				
			||||||
	latest   int64
 | 
						latest   int64
 | 
				
			||||||
	skip     int
 | 
						skip     int
 | 
				
			||||||
	address  []byte
 | 
						address  [][]byte
 | 
				
			||||||
	max      int
 | 
						max      int
 | 
				
			||||||
	topics   [][]byte
 | 
						topics   [][]byte
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -65,7 +65,7 @@ func (self *Filter) SetLatestBlock(latest int64) {
 | 
				
			|||||||
	self.latest = latest
 | 
						self.latest = latest
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (self *Filter) SetAddress(addr []byte) {
 | 
					func (self *Filter) SetAddress(addr [][]byte) {
 | 
				
			||||||
	self.address = addr
 | 
						self.address = addr
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -111,14 +111,14 @@ func (self *Filter) Find() state.Logs {
 | 
				
			|||||||
		// current parameters
 | 
							// current parameters
 | 
				
			||||||
		if self.bloomFilter(block) {
 | 
							if self.bloomFilter(block) {
 | 
				
			||||||
			// Get the logs of the block
 | 
								// Get the logs of the block
 | 
				
			||||||
			logs, err := self.eth.BlockProcessor().GetLogs(block)
 | 
								unfiltered, err := self.eth.BlockProcessor().GetLogs(block)
 | 
				
			||||||
			if err != nil {
 | 
								if err != nil {
 | 
				
			||||||
				chainlogger.Warnln("err: filter get logs ", err)
 | 
									chainlogger.Warnln("err: filter get logs ", err)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
				break
 | 
									break
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			logs = append(logs, self.FilterLogs(logs)...)
 | 
								logs = append(logs, self.FilterLogs(unfiltered)...)
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		block = self.eth.ChainManager().GetBlock(block.ParentHash())
 | 
							block = self.eth.ChainManager().GetBlock(block.ParentHash())
 | 
				
			||||||
@@ -145,7 +145,7 @@ func (self *Filter) FilterLogs(logs state.Logs) state.Logs {
 | 
				
			|||||||
	// Filter the logs for interesting stuff
 | 
						// Filter the logs for interesting stuff
 | 
				
			||||||
Logs:
 | 
					Logs:
 | 
				
			||||||
	for _, log := range logs {
 | 
						for _, log := range logs {
 | 
				
			||||||
		if !bytes.Equal(self.address, log.Address()) {
 | 
							if !includes(self.address, log.Address()) {
 | 
				
			||||||
			continue
 | 
								continue
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -163,8 +163,18 @@ Logs:
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (self *Filter) bloomFilter(block *types.Block) bool {
 | 
					func (self *Filter) bloomFilter(block *types.Block) bool {
 | 
				
			||||||
	if len(self.address) > 0 && !types.BloomLookup(block.Bloom(), self.address) {
 | 
						if len(self.address) > 0 {
 | 
				
			||||||
		return false
 | 
							var included bool
 | 
				
			||||||
 | 
							for _, addr := range self.address {
 | 
				
			||||||
 | 
								if types.BloomLookup(block.Bloom(), addr) {
 | 
				
			||||||
 | 
									included = true
 | 
				
			||||||
 | 
									break
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							if !included {
 | 
				
			||||||
 | 
								return false
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	for _, topic := range self.topics {
 | 
						for _, topic := range self.topics {
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,7 +1,10 @@
 | 
				
			|||||||
package core
 | 
					package core
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import (
 | 
					import (
 | 
				
			||||||
 | 
						"encoding/json"
 | 
				
			||||||
 | 
						"fmt"
 | 
				
			||||||
	"math/big"
 | 
						"math/big"
 | 
				
			||||||
 | 
						"os"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	"github.com/ethereum/go-ethereum/core/types"
 | 
						"github.com/ethereum/go-ethereum/core/types"
 | 
				
			||||||
	"github.com/ethereum/go-ethereum/crypto"
 | 
						"github.com/ethereum/go-ethereum/crypto"
 | 
				
			||||||
@@ -31,24 +34,39 @@ func GenesisBlock(db ethutil.Database) *types.Block {
 | 
				
			|||||||
	genesis.SetTransactions(types.Transactions{})
 | 
						genesis.SetTransactions(types.Transactions{})
 | 
				
			||||||
	genesis.SetReceipts(types.Receipts{})
 | 
						genesis.SetReceipts(types.Receipts{})
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						var accounts map[string]struct{ Balance string }
 | 
				
			||||||
 | 
						err := json.Unmarshal(genesisData, &accounts)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							fmt.Println("enable to decode genesis json data:", err)
 | 
				
			||||||
 | 
							os.Exit(1)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	statedb := state.New(genesis.Root(), db)
 | 
						statedb := state.New(genesis.Root(), db)
 | 
				
			||||||
	for _, addr := range []string{
 | 
						for addr, account := range accounts {
 | 
				
			||||||
		"dbdbdb2cbd23b783741e8d7fcf51e459b497e4a6",
 | 
					 | 
				
			||||||
		"e4157b34ea9615cfbde6b4fda419828124b70c78",
 | 
					 | 
				
			||||||
		"b9c015918bdaba24b4ff057a92a3873d6eb201be",
 | 
					 | 
				
			||||||
		"6c386a4b26f73c802f34673f7248bb118f97424a",
 | 
					 | 
				
			||||||
		"cd2a3d9f938e13cd947ec05abc7fe734df8dd826",
 | 
					 | 
				
			||||||
		"2ef47100e0787b915105fd5e3f4ff6752079d5cb",
 | 
					 | 
				
			||||||
		"e6716f9544a56c530d868e4bfbacb172315bdead",
 | 
					 | 
				
			||||||
		"1a26338f0d905e295fccb71fa9ea849ffa12aaf4",
 | 
					 | 
				
			||||||
	} {
 | 
					 | 
				
			||||||
		codedAddr := ethutil.Hex2Bytes(addr)
 | 
							codedAddr := ethutil.Hex2Bytes(addr)
 | 
				
			||||||
		account := statedb.GetAccount(codedAddr)
 | 
							accountState := statedb.GetAccount(codedAddr)
 | 
				
			||||||
		account.SetBalance(ethutil.Big("1606938044258990275541962092341162602522202993782792835301376")) //ethutil.BigPow(2, 200)
 | 
							accountState.SetBalance(ethutil.Big(account.Balance))
 | 
				
			||||||
		statedb.UpdateStateObject(account)
 | 
							statedb.UpdateStateObject(accountState)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	statedb.Sync()
 | 
						statedb.Sync()
 | 
				
			||||||
	genesis.Header().Root = statedb.Root()
 | 
						genesis.Header().Root = statedb.Root()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						fmt.Printf("+++ genesis +++\nRoot: %x\nHash: %x\n", genesis.Header().Root, genesis.Hash())
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return genesis
 | 
						return genesis
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					var genesisData = []byte(`{
 | 
				
			||||||
 | 
						"dbdbdb2cbd23b783741e8d7fcf51e459b497e4a6": {"balance": "1606938044258990275541962092341162602522202993782792835301376"},
 | 
				
			||||||
 | 
						"e4157b34ea9615cfbde6b4fda419828124b70c78": {"balance": "1606938044258990275541962092341162602522202993782792835301376"},
 | 
				
			||||||
 | 
						"b9c015918bdaba24b4ff057a92a3873d6eb201be": {"balance": "1606938044258990275541962092341162602522202993782792835301376"},
 | 
				
			||||||
 | 
						"6c386a4b26f73c802f34673f7248bb118f97424a": {"balance": "1606938044258990275541962092341162602522202993782792835301376"},
 | 
				
			||||||
 | 
						"cd2a3d9f938e13cd947ec05abc7fe734df8dd826": {"balance": "1606938044258990275541962092341162602522202993782792835301376"},
 | 
				
			||||||
 | 
						"2ef47100e0787b915105fd5e3f4ff6752079d5cb": {"balance": "1606938044258990275541962092341162602522202993782792835301376"},
 | 
				
			||||||
 | 
						"e6716f9544a56c530d868e4bfbacb172315bdead": {"balance": "1606938044258990275541962092341162602522202993782792835301376"},
 | 
				
			||||||
 | 
						"1a26338f0d905e295fccb71fa9ea849ffa12aaf4": {"balance": "1606938044258990275541962092341162602522202993782792835301376"},
 | 
				
			||||||
 | 
						"b0afc46d9ce366d06ab4952ca27db1d9557ae9fd": {"balance": "154162184000000000000000"},
 | 
				
			||||||
 | 
						"f6b1e9dc460d4d62cc22ec5f987d726929c0f9f0": {"balance": "102774789000000000000000"},
 | 
				
			||||||
 | 
						"cc45122d8b7fa0b1eaa6b29e0fb561422a9239d0": {"balance": "51387394000000000000000"},
 | 
				
			||||||
 | 
						"b7576e9d314df41ec5506494293afb1bd5d3f65d": {"balance": "69423399000000000000000"}
 | 
				
			||||||
 | 
					}`)
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -138,8 +138,8 @@ func (self *StateTransition) preCheck() (err error) {
 | 
				
			|||||||
	)
 | 
						)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// Make sure this transaction's nonce is correct
 | 
						// Make sure this transaction's nonce is correct
 | 
				
			||||||
	if sender.Nonce != msg.Nonce() {
 | 
						if sender.Nonce() != msg.Nonce() {
 | 
				
			||||||
		return NonceError(msg.Nonce(), sender.Nonce)
 | 
							return NonceError(msg.Nonce(), sender.Nonce())
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// Pre-pay gas / Buy gas of the coinbase account
 | 
						// Pre-pay gas / Buy gas of the coinbase account
 | 
				
			||||||
@@ -166,7 +166,8 @@ func (self *StateTransition) TransitionState() (ret []byte, err error) {
 | 
				
			|||||||
	defer self.RefundGas()
 | 
						defer self.RefundGas()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// Increment the nonce for the next transaction
 | 
						// Increment the nonce for the next transaction
 | 
				
			||||||
	sender.Nonce += 1
 | 
						self.state.SetNonce(sender.Address(), sender.Nonce()+1)
 | 
				
			||||||
 | 
						//sender.Nonce += 1
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// Transaction gas
 | 
						// Transaction gas
 | 
				
			||||||
	if err = self.UseGas(vm.GasTx); err != nil {
 | 
						if err = self.UseGas(vm.GasTx); err != nil {
 | 
				
			||||||
@@ -241,7 +242,7 @@ func MakeContract(msg Message, state *state.StateDB) *state.StateObject {
 | 
				
			|||||||
	addr := AddressFromMessage(msg)
 | 
						addr := AddressFromMessage(msg)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	contract := state.GetOrNewStateObject(addr)
 | 
						contract := state.GetOrNewStateObject(addr)
 | 
				
			||||||
	contract.InitCode = msg.Data()
 | 
						contract.SetInitCode(msg.Data())
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return contract
 | 
						return contract
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -3,6 +3,7 @@ package core
 | 
				
			|||||||
import (
 | 
					import (
 | 
				
			||||||
	"errors"
 | 
						"errors"
 | 
				
			||||||
	"fmt"
 | 
						"fmt"
 | 
				
			||||||
 | 
						"sync"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	"github.com/ethereum/go-ethereum/core/types"
 | 
						"github.com/ethereum/go-ethereum/core/types"
 | 
				
			||||||
	"github.com/ethereum/go-ethereum/ethutil"
 | 
						"github.com/ethereum/go-ethereum/ethutil"
 | 
				
			||||||
@@ -35,6 +36,7 @@ type TxProcessor interface {
 | 
				
			|||||||
// guarantee a non blocking pool we use a queue channel which can be
 | 
					// guarantee a non blocking pool we use a queue channel which can be
 | 
				
			||||||
// independently read without needing access to the actual pool.
 | 
					// independently read without needing access to the actual pool.
 | 
				
			||||||
type TxPool struct {
 | 
					type TxPool struct {
 | 
				
			||||||
 | 
						mu sync.RWMutex
 | 
				
			||||||
	// Queueing channel for reading and writing incoming
 | 
						// Queueing channel for reading and writing incoming
 | 
				
			||||||
	// transactions to
 | 
						// transactions to
 | 
				
			||||||
	queueChan chan *types.Transaction
 | 
						queueChan chan *types.Transaction
 | 
				
			||||||
@@ -97,7 +99,7 @@ func (self *TxPool) addTx(tx *types.Transaction) {
 | 
				
			|||||||
	self.txs[string(tx.Hash())] = tx
 | 
						self.txs[string(tx.Hash())] = tx
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (self *TxPool) Add(tx *types.Transaction) error {
 | 
					func (self *TxPool) add(tx *types.Transaction) error {
 | 
				
			||||||
	if self.txs[string(tx.Hash())] != nil {
 | 
						if self.txs[string(tx.Hash())] != nil {
 | 
				
			||||||
		return fmt.Errorf("Known transaction (%x)", tx.Hash()[0:4])
 | 
							return fmt.Errorf("Known transaction (%x)", tx.Hash()[0:4])
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
@@ -128,17 +130,28 @@ func (self *TxPool) Size() int {
 | 
				
			|||||||
	return len(self.txs)
 | 
						return len(self.txs)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (self *TxPool) Add(tx *types.Transaction) error {
 | 
				
			||||||
 | 
						self.mu.Lock()
 | 
				
			||||||
 | 
						defer self.mu.Unlock()
 | 
				
			||||||
 | 
						return self.add(tx)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
func (self *TxPool) AddTransactions(txs []*types.Transaction) {
 | 
					func (self *TxPool) AddTransactions(txs []*types.Transaction) {
 | 
				
			||||||
 | 
						self.mu.Lock()
 | 
				
			||||||
 | 
						defer self.mu.Unlock()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	for _, tx := range txs {
 | 
						for _, tx := range txs {
 | 
				
			||||||
		if err := self.Add(tx); err != nil {
 | 
							if err := self.add(tx); err != nil {
 | 
				
			||||||
			txplogger.Infoln(err)
 | 
								txplogger.Debugln(err)
 | 
				
			||||||
		} else {
 | 
							} else {
 | 
				
			||||||
			txplogger.Infof("tx %x\n", tx.Hash()[0:4])
 | 
								txplogger.Debugf("tx %x\n", tx.Hash()[0:4])
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (self *TxPool) GetTransactions() (txs types.Transactions) {
 | 
					func (self *TxPool) GetTransactions() (txs types.Transactions) {
 | 
				
			||||||
 | 
						self.mu.RLock()
 | 
				
			||||||
 | 
						defer self.mu.RUnlock()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	txs = make(types.Transactions, self.Size())
 | 
						txs = make(types.Transactions, self.Size())
 | 
				
			||||||
	i := 0
 | 
						i := 0
 | 
				
			||||||
	for _, tx := range self.txs {
 | 
						for _, tx := range self.txs {
 | 
				
			||||||
@@ -150,30 +163,32 @@ func (self *TxPool) GetTransactions() (txs types.Transactions) {
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (pool *TxPool) RemoveInvalid(query StateQuery) {
 | 
					func (pool *TxPool) RemoveInvalid(query StateQuery) {
 | 
				
			||||||
 | 
						pool.mu.Lock()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	var removedTxs types.Transactions
 | 
						var removedTxs types.Transactions
 | 
				
			||||||
	for _, tx := range pool.txs {
 | 
						for _, tx := range pool.txs {
 | 
				
			||||||
		sender := query.GetAccount(tx.From())
 | 
							sender := query.GetAccount(tx.From())
 | 
				
			||||||
		err := pool.ValidateTransaction(tx)
 | 
							err := pool.ValidateTransaction(tx)
 | 
				
			||||||
		fmt.Println(err, sender.Nonce, tx.Nonce())
 | 
							if err != nil || sender.Nonce() >= tx.Nonce() {
 | 
				
			||||||
		if err != nil || sender.Nonce >= tx.Nonce() {
 | 
					 | 
				
			||||||
			removedTxs = append(removedTxs, tx)
 | 
								removedTxs = append(removedTxs, tx)
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
						pool.mu.Unlock()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	pool.RemoveSet(removedTxs)
 | 
						pool.RemoveSet(removedTxs)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (self *TxPool) RemoveSet(txs types.Transactions) {
 | 
					func (self *TxPool) RemoveSet(txs types.Transactions) {
 | 
				
			||||||
 | 
						self.mu.Lock()
 | 
				
			||||||
 | 
						defer self.mu.Unlock()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	for _, tx := range txs {
 | 
						for _, tx := range txs {
 | 
				
			||||||
		delete(self.txs, string(tx.Hash()))
 | 
							delete(self.txs, string(tx.Hash()))
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (pool *TxPool) Flush() []*types.Transaction {
 | 
					func (pool *TxPool) Flush() {
 | 
				
			||||||
	txList := pool.GetTransactions()
 | 
					 | 
				
			||||||
	pool.txs = make(map[string]*types.Transaction)
 | 
						pool.txs = make(map[string]*types.Transaction)
 | 
				
			||||||
 | 
					 | 
				
			||||||
	return txList
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (pool *TxPool) Start() {
 | 
					func (pool *TxPool) Start() {
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -185,6 +185,18 @@ func (self *Block) GasUsed() *big.Int         { return self.header.GasUsed }
 | 
				
			|||||||
func (self *Block) Root() []byte              { return self.header.Root }
 | 
					func (self *Block) Root() []byte              { return self.header.Root }
 | 
				
			||||||
func (self *Block) SetRoot(root []byte)       { self.header.Root = root }
 | 
					func (self *Block) SetRoot(root []byte)       { self.header.Root = root }
 | 
				
			||||||
func (self *Block) Size() ethutil.StorageSize { return ethutil.StorageSize(len(ethutil.Encode(self))) }
 | 
					func (self *Block) Size() ethutil.StorageSize { return ethutil.StorageSize(len(ethutil.Encode(self))) }
 | 
				
			||||||
 | 
					func (self *Block) GetTransaction(i int) *Transaction {
 | 
				
			||||||
 | 
						if len(self.transactions) > i {
 | 
				
			||||||
 | 
							return self.transactions[i]
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return nil
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					func (self *Block) GetUncle(i int) *Header {
 | 
				
			||||||
 | 
						if len(self.uncles) > i {
 | 
				
			||||||
 | 
							return self.uncles[i]
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return nil
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// Implement pow.Block
 | 
					// Implement pow.Block
 | 
				
			||||||
func (self *Block) Difficulty() *big.Int { return self.header.Difficulty }
 | 
					func (self *Block) Difficulty() *big.Int { return self.header.Difficulty }
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -16,12 +16,12 @@ import (
 | 
				
			|||||||
	"errors"
 | 
						"errors"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	"code.google.com/p/go-uuid/uuid"
 | 
						"code.google.com/p/go-uuid/uuid"
 | 
				
			||||||
	"code.google.com/p/go.crypto/pbkdf2"
 | 
					 | 
				
			||||||
	"code.google.com/p/go.crypto/ripemd160"
 | 
					 | 
				
			||||||
	"github.com/ethereum/go-ethereum/crypto/ecies"
 | 
						"github.com/ethereum/go-ethereum/crypto/ecies"
 | 
				
			||||||
	"github.com/ethereum/go-ethereum/crypto/secp256k1"
 | 
						"github.com/ethereum/go-ethereum/crypto/secp256k1"
 | 
				
			||||||
	"github.com/ethereum/go-ethereum/crypto/sha3"
 | 
						"github.com/ethereum/go-ethereum/crypto/sha3"
 | 
				
			||||||
	"github.com/ethereum/go-ethereum/ethutil"
 | 
						"github.com/ethereum/go-ethereum/ethutil"
 | 
				
			||||||
 | 
						"golang.org/x/crypto/pbkdf2"
 | 
				
			||||||
 | 
						"golang.org/x/crypto/ripemd160"
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func init() {
 | 
					func init() {
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -20,6 +20,7 @@
 | 
				
			|||||||
 * @date 2015
 | 
					 * @date 2015
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/*
 | 
					/*
 | 
				
			||||||
 | 
					
 | 
				
			||||||
This key store behaves as KeyStorePlain with the difference that
 | 
					This key store behaves as KeyStorePlain with the difference that
 | 
				
			||||||
@@ -64,17 +65,18 @@ package crypto
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
import (
 | 
					import (
 | 
				
			||||||
	"bytes"
 | 
						"bytes"
 | 
				
			||||||
	"code.google.com/p/go-uuid/uuid"
 | 
					 | 
				
			||||||
	"code.google.com/p/go.crypto/scrypt"
 | 
					 | 
				
			||||||
	"crypto/aes"
 | 
						"crypto/aes"
 | 
				
			||||||
	"crypto/cipher"
 | 
						"crypto/cipher"
 | 
				
			||||||
	"encoding/hex"
 | 
						"encoding/hex"
 | 
				
			||||||
	"encoding/json"
 | 
						"encoding/json"
 | 
				
			||||||
	"errors"
 | 
						"errors"
 | 
				
			||||||
	"github.com/ethereum/go-ethereum/crypto/randentropy"
 | 
					 | 
				
			||||||
	"io"
 | 
						"io"
 | 
				
			||||||
	"os"
 | 
						"os"
 | 
				
			||||||
	"path"
 | 
						"path"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						"code.google.com/p/go-uuid/uuid"
 | 
				
			||||||
 | 
						"github.com/ethereum/go-ethereum/crypto/randentropy"
 | 
				
			||||||
 | 
						"golang.org/x/crypto/scrypt"
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const (
 | 
					const (
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -3,6 +3,8 @@ package eth
 | 
				
			|||||||
import (
 | 
					import (
 | 
				
			||||||
	"crypto/ecdsa"
 | 
						"crypto/ecdsa"
 | 
				
			||||||
	"fmt"
 | 
						"fmt"
 | 
				
			||||||
 | 
						"io/ioutil"
 | 
				
			||||||
 | 
						"path"
 | 
				
			||||||
	"strings"
 | 
						"strings"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	"github.com/ethereum/go-ethereum/core"
 | 
						"github.com/ethereum/go-ethereum/core"
 | 
				
			||||||
@@ -25,7 +27,10 @@ var (
 | 
				
			|||||||
	jsonlogger = ethlogger.NewJsonLogger()
 | 
						jsonlogger = ethlogger.NewJsonLogger()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	defaultBootNodes = []*discover.Node{
 | 
						defaultBootNodes = []*discover.Node{
 | 
				
			||||||
 | 
							// ETH/DEV cmd/bootnode
 | 
				
			||||||
		discover.MustParseNode("enode://6cdd090303f394a1cac34ecc9f7cda18127eafa2a3a06de39f6d920b0e583e062a7362097c7c65ee490a758b442acd5c80c6fce4b148c6a391e946b45131365b@54.169.166.226:30303"),
 | 
							discover.MustParseNode("enode://6cdd090303f394a1cac34ecc9f7cda18127eafa2a3a06de39f6d920b0e583e062a7362097c7c65ee490a758b442acd5c80c6fce4b148c6a391e946b45131365b@54.169.166.226:30303"),
 | 
				
			||||||
 | 
							// ETH/DEV cpp-ethereum (poc-8.ethdev.com)
 | 
				
			||||||
 | 
							discover.MustParseNode("enode://4a44599974518ea5b0f14c31c4463692ac0329cb84851f3435e6d1b18ee4eae4aa495f846a0fa1219bd58035671881d44423876e57db2abd57254d0197da0ebe@5.1.83.226:30303"),
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -53,6 +58,8 @@ type Config struct {
 | 
				
			|||||||
	Shh  bool
 | 
						Shh  bool
 | 
				
			||||||
	Dial bool
 | 
						Dial bool
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						MinerThreads int
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	KeyManager *crypto.KeyManager
 | 
						KeyManager *crypto.KeyManager
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -75,6 +82,27 @@ func (cfg *Config) parseBootNodes() []*discover.Node {
 | 
				
			|||||||
	return ns
 | 
						return ns
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (cfg *Config) nodeKey() (*ecdsa.PrivateKey, error) {
 | 
				
			||||||
 | 
						// use explicit key from command line args if set
 | 
				
			||||||
 | 
						if cfg.NodeKey != nil {
 | 
				
			||||||
 | 
							return cfg.NodeKey, nil
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						// use persistent key if present
 | 
				
			||||||
 | 
						keyfile := path.Join(cfg.DataDir, "nodekey")
 | 
				
			||||||
 | 
						key, err := crypto.LoadECDSA(keyfile)
 | 
				
			||||||
 | 
						if err == nil {
 | 
				
			||||||
 | 
							return key, nil
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						// no persistent key, generate and store a new one
 | 
				
			||||||
 | 
						if key, err = crypto.GenerateKey(); err != nil {
 | 
				
			||||||
 | 
							return nil, fmt.Errorf("could not generate server key: %v", err)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if err := ioutil.WriteFile(keyfile, crypto.FromECDSA(key), 0600); err != nil {
 | 
				
			||||||
 | 
							logger.Errorln("could not persist nodekey: ", err)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return key, nil
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
type Ethereum struct {
 | 
					type Ethereum struct {
 | 
				
			||||||
	// Channel for shutting down the ethereum
 | 
						// Channel for shutting down the ethereum
 | 
				
			||||||
	shutdownChan chan bool
 | 
						shutdownChan chan bool
 | 
				
			||||||
@@ -153,20 +181,22 @@ func New(config *Config) (*Ethereum, error) {
 | 
				
			|||||||
	eth.blockProcessor = core.NewBlockProcessor(db, eth.txPool, eth.chainManager, eth.EventMux())
 | 
						eth.blockProcessor = core.NewBlockProcessor(db, eth.txPool, eth.chainManager, eth.EventMux())
 | 
				
			||||||
	eth.chainManager.SetProcessor(eth.blockProcessor)
 | 
						eth.chainManager.SetProcessor(eth.blockProcessor)
 | 
				
			||||||
	eth.whisper = whisper.New()
 | 
						eth.whisper = whisper.New()
 | 
				
			||||||
	eth.miner = miner.New(keyManager.Address(), eth)
 | 
						eth.miner = miner.New(keyManager.Address(), eth, config.MinerThreads)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	hasBlock := eth.chainManager.HasBlock
 | 
						hasBlock := eth.chainManager.HasBlock
 | 
				
			||||||
	insertChain := eth.chainManager.InsertChain
 | 
						insertChain := eth.chainManager.InsertChain
 | 
				
			||||||
	eth.blockPool = NewBlockPool(hasBlock, insertChain, ezp.Verify)
 | 
						eth.blockPool = NewBlockPool(hasBlock, insertChain, ezp.Verify)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	ethProto := EthProtocol(eth.txPool, eth.chainManager, eth.blockPool)
 | 
						netprv, err := config.nodeKey()
 | 
				
			||||||
	protocols := []p2p.Protocol{ethProto, eth.whisper.Protocol()}
 | 
						if err != nil {
 | 
				
			||||||
	netprv := config.NodeKey
 | 
							return nil, err
 | 
				
			||||||
	if netprv == nil {
 | 
					 | 
				
			||||||
		if netprv, err = crypto.GenerateKey(); err != nil {
 | 
					 | 
				
			||||||
			return nil, fmt.Errorf("could not generate server key: %v", err)
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
						ethProto := EthProtocol(eth.txPool, eth.chainManager, eth.blockPool)
 | 
				
			||||||
 | 
						protocols := []p2p.Protocol{ethProto}
 | 
				
			||||||
 | 
						if config.Shh {
 | 
				
			||||||
 | 
							protocols = append(protocols, eth.whisper.Protocol())
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	eth.net = &p2p.Server{
 | 
						eth.net = &p2p.Server{
 | 
				
			||||||
		PrivateKey:     netprv,
 | 
							PrivateKey:     netprv,
 | 
				
			||||||
		Name:           config.Name,
 | 
							Name:           config.Name,
 | 
				
			||||||
@@ -205,9 +235,7 @@ func (s *Ethereum) Coinbase() []byte                     { return nil } // TODO
 | 
				
			|||||||
func (s *Ethereum) Start() error {
 | 
					func (s *Ethereum) Start() error {
 | 
				
			||||||
	jsonlogger.LogJson(ðlogger.LogStarting{
 | 
						jsonlogger.LogJson(ðlogger.LogStarting{
 | 
				
			||||||
		ClientString:    s.net.Name,
 | 
							ClientString:    s.net.Name,
 | 
				
			||||||
		Coinbase:        ethutil.Bytes2Hex(s.KeyManager().Address()),
 | 
					 | 
				
			||||||
		ProtocolVersion: ProtocolVersion,
 | 
							ProtocolVersion: ProtocolVersion,
 | 
				
			||||||
		LogEvent:        ethlogger.LogEvent{Guid: ethutil.Bytes2Hex(crypto.FromECDSAPub(&s.net.PrivateKey.PublicKey))},
 | 
					 | 
				
			||||||
	})
 | 
						})
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	err := s.net.Start()
 | 
						err := s.net.Start()
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -13,7 +13,7 @@ import (
 | 
				
			|||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const (
 | 
					const (
 | 
				
			||||||
	ProtocolVersion    = 52
 | 
						ProtocolVersion    = 54
 | 
				
			||||||
	NetworkId          = 0
 | 
						NetworkId          = 0
 | 
				
			||||||
	ProtocolLength     = uint64(8)
 | 
						ProtocolLength     = uint64(8)
 | 
				
			||||||
	ProtocolMaxMsgSize = 10 * 1024 * 1024
 | 
						ProtocolMaxMsgSize = 10 * 1024 * 1024
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -4,6 +4,7 @@ import (
 | 
				
			|||||||
	"fmt"
 | 
						"fmt"
 | 
				
			||||||
	"math/big"
 | 
						"math/big"
 | 
				
			||||||
	"runtime"
 | 
						"runtime"
 | 
				
			||||||
 | 
						"time"
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func IsWindows() bool {
 | 
					func IsWindows() bool {
 | 
				
			||||||
@@ -86,3 +87,9 @@ var (
 | 
				
			|||||||
	Big256   = big.NewInt(0xff)
 | 
						Big256   = big.NewInt(0xff)
 | 
				
			||||||
	Big257   = big.NewInt(257)
 | 
						Big257   = big.NewInt(257)
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func Bench(pre string, cb func()) {
 | 
				
			||||||
 | 
						start := time.Now()
 | 
				
			||||||
 | 
						cb()
 | 
				
			||||||
 | 
						fmt.Println(pre, ": took:", time.Since(start))
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										181
									
								
								ethutil/number/int.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										181
									
								
								ethutil/number/int.go
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,181 @@
 | 
				
			|||||||
 | 
					package number
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import (
 | 
				
			||||||
 | 
						"math/big"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						"github.com/ethereum/go-ethereum/ethutil"
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					var tt256 = new(big.Int).Lsh(big.NewInt(1), 256)
 | 
				
			||||||
 | 
					var tt256m1 = new(big.Int).Sub(new(big.Int).Lsh(big.NewInt(1), 256), big.NewInt(1))
 | 
				
			||||||
 | 
					var tt255 = new(big.Int).Lsh(big.NewInt(1), 255)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func limitUnsigned256(x *Number) *Number {
 | 
				
			||||||
 | 
						x.num.And(x.num, tt256m1)
 | 
				
			||||||
 | 
						return x
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func limitSigned256(x *Number) *Number {
 | 
				
			||||||
 | 
						if x.num.Cmp(tt255) < 0 {
 | 
				
			||||||
 | 
							return x
 | 
				
			||||||
 | 
						} else {
 | 
				
			||||||
 | 
							x.num.Sub(x.num, tt256)
 | 
				
			||||||
 | 
							return x
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Number function
 | 
				
			||||||
 | 
					type Initialiser func(n int64) *Number
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// A Number represents a generic integer with a bounding function limiter. Limit is called after each operations
 | 
				
			||||||
 | 
					// to give "fake" bounded integers. New types of Number can be created through NewInitialiser returning a lambda
 | 
				
			||||||
 | 
					// with the new Initialiser.
 | 
				
			||||||
 | 
					type Number struct {
 | 
				
			||||||
 | 
						num   *big.Int
 | 
				
			||||||
 | 
						limit func(n *Number) *Number
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Returns a new initialiser for a new *Number without having to expose certain fields
 | 
				
			||||||
 | 
					func NewInitialiser(limiter func(*Number) *Number) Initialiser {
 | 
				
			||||||
 | 
						return func(n int64) *Number {
 | 
				
			||||||
 | 
							return &Number{big.NewInt(n), limiter}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Return a Number with a UNSIGNED limiter up to 256 bits
 | 
				
			||||||
 | 
					func Uint256(n int64) *Number {
 | 
				
			||||||
 | 
						return &Number{big.NewInt(n), limitUnsigned256}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Return a Number with a SIGNED limiter up to 256 bits
 | 
				
			||||||
 | 
					func Int256(n int64) *Number {
 | 
				
			||||||
 | 
						return &Number{big.NewInt(n), limitSigned256}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Returns a Number with a SIGNED unlimited size
 | 
				
			||||||
 | 
					func Big(n int64) *Number {
 | 
				
			||||||
 | 
						return &Number{big.NewInt(n), func(x *Number) *Number { return x }}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Sets i to sum of x+y
 | 
				
			||||||
 | 
					func (i *Number) Add(x, y *Number) *Number {
 | 
				
			||||||
 | 
						i.num.Add(x.num, y.num)
 | 
				
			||||||
 | 
						return i.limit(i)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Sets i to difference of x-y
 | 
				
			||||||
 | 
					func (i *Number) Sub(x, y *Number) *Number {
 | 
				
			||||||
 | 
						i.num.Sub(x.num, y.num)
 | 
				
			||||||
 | 
						return i.limit(i)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Sets i to product of x*y
 | 
				
			||||||
 | 
					func (i *Number) Mul(x, y *Number) *Number {
 | 
				
			||||||
 | 
						i.num.Mul(x.num, y.num)
 | 
				
			||||||
 | 
						return i.limit(i)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Sets i to the quotient prodject of x/y
 | 
				
			||||||
 | 
					func (i *Number) Div(x, y *Number) *Number {
 | 
				
			||||||
 | 
						i.num.Div(x.num, y.num)
 | 
				
			||||||
 | 
						return i.limit(i)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Sets i to x % y
 | 
				
			||||||
 | 
					func (i *Number) Mod(x, y *Number) *Number {
 | 
				
			||||||
 | 
						i.num.Mod(x.num, y.num)
 | 
				
			||||||
 | 
						return i.limit(i)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Sets i to x << s
 | 
				
			||||||
 | 
					func (i *Number) Lsh(x *Number, s uint) *Number {
 | 
				
			||||||
 | 
						i.num.Lsh(x.num, s)
 | 
				
			||||||
 | 
						return i.limit(i)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Sets i to x^y
 | 
				
			||||||
 | 
					func (i *Number) Pow(x, y *Number) *Number {
 | 
				
			||||||
 | 
						i.num.Exp(x.num, y.num, big.NewInt(0))
 | 
				
			||||||
 | 
						return i.limit(i)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Setters
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Set x to i
 | 
				
			||||||
 | 
					func (i *Number) Set(x *Number) *Number {
 | 
				
			||||||
 | 
						i.num.Set(x.num)
 | 
				
			||||||
 | 
						return i.limit(i)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Set x bytes to i
 | 
				
			||||||
 | 
					func (i *Number) SetBytes(x []byte) *Number {
 | 
				
			||||||
 | 
						i.num.SetBytes(x)
 | 
				
			||||||
 | 
						return i.limit(i)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Cmp compares x and y and returns:
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					//     -1 if x <  y
 | 
				
			||||||
 | 
					//     0 if x == y
 | 
				
			||||||
 | 
					//     +1 if x >  y
 | 
				
			||||||
 | 
					func (i *Number) Cmp(x *Number) int {
 | 
				
			||||||
 | 
						return i.num.Cmp(x.num)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Getters
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Returns the string representation of i
 | 
				
			||||||
 | 
					func (i *Number) String() string {
 | 
				
			||||||
 | 
						return i.num.String()
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Returns the byte representation of i
 | 
				
			||||||
 | 
					func (i *Number) Bytes() []byte {
 | 
				
			||||||
 | 
						return i.num.Bytes()
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Uint64 returns the Uint64 representation of x. If x cannot be represented in an int64, the result is undefined.
 | 
				
			||||||
 | 
					func (i *Number) Uint64() uint64 {
 | 
				
			||||||
 | 
						return i.num.Uint64()
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Int64 returns the int64 representation of x. If x cannot be represented in an int64, the result is undefined.
 | 
				
			||||||
 | 
					func (i *Number) Int64() int64 {
 | 
				
			||||||
 | 
						return i.num.Int64()
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Returns the signed version of i
 | 
				
			||||||
 | 
					func (i *Number) Int256() *Number {
 | 
				
			||||||
 | 
						return Int(0).Set(i)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Returns the unsigned version of i
 | 
				
			||||||
 | 
					func (i *Number) Uint256() *Number {
 | 
				
			||||||
 | 
						return Uint(0).Set(i)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Returns the index of the first bit that's set to 1
 | 
				
			||||||
 | 
					func (i *Number) FirstBitSet() int {
 | 
				
			||||||
 | 
						for j := 0; j < i.num.BitLen(); j++ {
 | 
				
			||||||
 | 
							if i.num.Bit(j) > 0 {
 | 
				
			||||||
 | 
								return j
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return i.num.BitLen()
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Variables
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					var (
 | 
				
			||||||
 | 
						Zero       = Uint(0)
 | 
				
			||||||
 | 
						One        = Uint(1)
 | 
				
			||||||
 | 
						Two        = Uint(2)
 | 
				
			||||||
 | 
						MaxUint256 = Uint(0).SetBytes(ethutil.Hex2Bytes("ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						MinOne = Int(-1)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// "typedefs"
 | 
				
			||||||
 | 
						Uint = Uint256
 | 
				
			||||||
 | 
						Int  = Int256
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
							
								
								
									
										92
									
								
								ethutil/number/uint_test.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										92
									
								
								ethutil/number/uint_test.go
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,92 @@
 | 
				
			|||||||
 | 
					package number
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import (
 | 
				
			||||||
 | 
						"math/big"
 | 
				
			||||||
 | 
						"testing"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						"github.com/ethereum/go-ethereum/ethutil"
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func TestSet(t *testing.T) {
 | 
				
			||||||
 | 
						a := Uint(0)
 | 
				
			||||||
 | 
						b := Uint(10)
 | 
				
			||||||
 | 
						a.Set(b)
 | 
				
			||||||
 | 
						if a.num.Cmp(b.num) != 0 {
 | 
				
			||||||
 | 
							t.Error("didn't compare", a, b)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						c := Uint(0).SetBytes(ethutil.Hex2Bytes("0a"))
 | 
				
			||||||
 | 
						if c.num.Cmp(big.NewInt(10)) != 0 {
 | 
				
			||||||
 | 
							t.Error("c set bytes failed.")
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func TestInitialiser(t *testing.T) {
 | 
				
			||||||
 | 
						check := false
 | 
				
			||||||
 | 
						init := NewInitialiser(func(x *Number) *Number {
 | 
				
			||||||
 | 
							check = true
 | 
				
			||||||
 | 
							return x
 | 
				
			||||||
 | 
						})
 | 
				
			||||||
 | 
						a := init(0).Add(init(1), init(2))
 | 
				
			||||||
 | 
						if a.Cmp(init(3)) != 0 {
 | 
				
			||||||
 | 
							t.Error("expected 3. got", a)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if !check {
 | 
				
			||||||
 | 
							t.Error("expected limiter to be called")
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func TestGet(t *testing.T) {
 | 
				
			||||||
 | 
						a := Uint(10)
 | 
				
			||||||
 | 
						if a.Uint64() != 10 {
 | 
				
			||||||
 | 
							t.Error("expected to get 10. got", a.Uint64())
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						a = Uint(10)
 | 
				
			||||||
 | 
						if a.Int64() != 10 {
 | 
				
			||||||
 | 
							t.Error("expected to get 10. got", a.Int64())
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func TestCmp(t *testing.T) {
 | 
				
			||||||
 | 
						a := Uint(10)
 | 
				
			||||||
 | 
						b := Uint(10)
 | 
				
			||||||
 | 
						c := Uint(11)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if a.Cmp(b) != 0 {
 | 
				
			||||||
 | 
							t.Error("a b == 0 failed", a, b)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if a.Cmp(c) >= 0 {
 | 
				
			||||||
 | 
							t.Error("a c < 0 failed", a, c)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if c.Cmp(b) <= 0 {
 | 
				
			||||||
 | 
							t.Error("c b > 0 failed", c, b)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func TestMaxArith(t *testing.T) {
 | 
				
			||||||
 | 
						a := Uint(0).Add(MaxUint256, One)
 | 
				
			||||||
 | 
						if a.Cmp(Zero) != 0 {
 | 
				
			||||||
 | 
							t.Error("expected max256 + 1 = 0 got", a)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						a = Uint(0).Sub(Uint(0), One)
 | 
				
			||||||
 | 
						if a.Cmp(MaxUint256) != 0 {
 | 
				
			||||||
 | 
							t.Error("expected 0 - 1 = max256 got", a)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						a = Int(0).Sub(Int(0), One)
 | 
				
			||||||
 | 
						if a.Cmp(MinOne) != 0 {
 | 
				
			||||||
 | 
							t.Error("expected 0 - 1 = -1 got", a)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func TestConversion(t *testing.T) {
 | 
				
			||||||
 | 
						a := Int(-1)
 | 
				
			||||||
 | 
						b := a.Uint256()
 | 
				
			||||||
 | 
						if b.Cmp(MaxUint256) != 0 {
 | 
				
			||||||
 | 
							t.Error("expected -1 => unsigned to return max. got", b)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@@ -3,6 +3,7 @@ package filter
 | 
				
			|||||||
// TODO make use of the generic filtering system
 | 
					// TODO make use of the generic filtering system
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import (
 | 
					import (
 | 
				
			||||||
 | 
						"fmt"
 | 
				
			||||||
	"sync"
 | 
						"sync"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	"github.com/ethereum/go-ethereum/core"
 | 
						"github.com/ethereum/go-ethereum/core"
 | 
				
			||||||
@@ -37,17 +38,18 @@ func (self *FilterManager) Stop() {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
func (self *FilterManager) InstallFilter(filter *core.Filter) (id int) {
 | 
					func (self *FilterManager) InstallFilter(filter *core.Filter) (id int) {
 | 
				
			||||||
	self.filterMu.Lock()
 | 
						self.filterMu.Lock()
 | 
				
			||||||
 | 
						defer self.filterMu.Unlock()
 | 
				
			||||||
	id = self.filterId
 | 
						id = self.filterId
 | 
				
			||||||
	self.filters[id] = filter
 | 
						self.filters[id] = filter
 | 
				
			||||||
	self.filterId++
 | 
						self.filterId++
 | 
				
			||||||
	self.filterMu.Unlock()
 | 
					
 | 
				
			||||||
	return id
 | 
						return id
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (self *FilterManager) UninstallFilter(id int) {
 | 
					func (self *FilterManager) UninstallFilter(id int) {
 | 
				
			||||||
	self.filterMu.Lock()
 | 
						self.filterMu.Lock()
 | 
				
			||||||
 | 
						defer self.filterMu.Unlock()
 | 
				
			||||||
	delete(self.filters, id)
 | 
						delete(self.filters, id)
 | 
				
			||||||
	self.filterMu.Unlock()
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// GetFilter retrieves a filter installed using InstallFilter.
 | 
					// GetFilter retrieves a filter installed using InstallFilter.
 | 
				
			||||||
@@ -60,7 +62,10 @@ func (self *FilterManager) GetFilter(id int) *core.Filter {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
func (self *FilterManager) filterLoop() {
 | 
					func (self *FilterManager) filterLoop() {
 | 
				
			||||||
	// Subscribe to events
 | 
						// Subscribe to events
 | 
				
			||||||
	events := self.eventMux.Subscribe(core.PendingBlockEvent{}, core.NewBlockEvent{}, state.Logs(nil))
 | 
						events := self.eventMux.Subscribe(
 | 
				
			||||||
 | 
							core.PendingBlockEvent{},
 | 
				
			||||||
 | 
							//core.ChainEvent{},
 | 
				
			||||||
 | 
							state.Logs(nil))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
out:
 | 
					out:
 | 
				
			||||||
	for {
 | 
						for {
 | 
				
			||||||
@@ -69,7 +74,8 @@ out:
 | 
				
			|||||||
			break out
 | 
								break out
 | 
				
			||||||
		case event := <-events.Chan():
 | 
							case event := <-events.Chan():
 | 
				
			||||||
			switch event := event.(type) {
 | 
								switch event := event.(type) {
 | 
				
			||||||
			case core.NewBlockEvent:
 | 
								case core.ChainEvent:
 | 
				
			||||||
 | 
									fmt.Println("filter start")
 | 
				
			||||||
				self.filterMu.RLock()
 | 
									self.filterMu.RLock()
 | 
				
			||||||
				for _, filter := range self.filters {
 | 
									for _, filter := range self.filters {
 | 
				
			||||||
					if filter.BlockCallback != nil {
 | 
										if filter.BlockCallback != nil {
 | 
				
			||||||
@@ -77,6 +83,7 @@ out:
 | 
				
			|||||||
					}
 | 
										}
 | 
				
			||||||
				}
 | 
									}
 | 
				
			||||||
				self.filterMu.RUnlock()
 | 
									self.filterMu.RUnlock()
 | 
				
			||||||
 | 
									fmt.Println("filter stop")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			case core.PendingBlockEvent:
 | 
								case core.PendingBlockEvent:
 | 
				
			||||||
				self.filterMu.RLock()
 | 
									self.filterMu.RLock()
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,11 +1,16 @@
 | 
				
			|||||||
#!/bin/bash
 | 
					#!/bin/bash
 | 
				
			||||||
# The script does automatic checking on a Go package and its sub-packages, including:
 | 
					 | 
				
			||||||
# 6. test coverage (http://blog.golang.org/cover)
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
set -e
 | 
					set -e
 | 
				
			||||||
 | 
					
 | 
				
			||||||
# Run test coverage on each subdirectories and merge the coverage profile.
 | 
					# Add godep workspace to GOPATH. We do it manually instead of using
 | 
				
			||||||
 | 
					# 'godep go test' or 'godep restore' so godep doesn't need to be installed.
 | 
				
			||||||
 | 
					GOPATH="$PWD/Godeps/_workspace:$GOPATH"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Install packages before testing. Not doing this would cause
 | 
				
			||||||
 | 
					# 'go test' to recompile all package dependencies before testing each package.
 | 
				
			||||||
 | 
					go install ./...
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Run test coverage on each subdirectories and merge the coverage profile.
 | 
				
			||||||
echo "mode: count" > profile.cov
 | 
					echo "mode: count" > profile.cov
 | 
				
			||||||
 | 
					
 | 
				
			||||||
# Standard go tooling behavior is to ignore dirs with leading underscors
 | 
					# Standard go tooling behavior is to ignore dirs with leading underscors
 | 
				
			||||||
@@ -13,7 +18,7 @@ for dir in $(find . -maxdepth 10 -not -path './.git*' -not -path '*/_*' -type d)
 | 
				
			|||||||
do
 | 
					do
 | 
				
			||||||
if ls $dir/*.go &> /dev/null; then
 | 
					if ls $dir/*.go &> /dev/null; then
 | 
				
			||||||
    # echo $dir
 | 
					    # echo $dir
 | 
				
			||||||
    if [[ $dir != "./tests/vm" ]]
 | 
					    if [[ $dir != "./tests/vm" && $dir != "." ]]
 | 
				
			||||||
    then
 | 
					    then
 | 
				
			||||||
        go test -covermode=count -coverprofile=$dir/profile.tmp $dir
 | 
					        go test -covermode=count -coverprofile=$dir/profile.tmp $dir
 | 
				
			||||||
    fi
 | 
					    fi
 | 
				
			||||||
@@ -24,6 +29,3 @@ if ls $dir/*.go &> /dev/null; then
 | 
				
			|||||||
    fi
 | 
					    fi
 | 
				
			||||||
fi
 | 
					fi
 | 
				
			||||||
done
 | 
					done
 | 
				
			||||||
 | 
					 | 
				
			||||||
go tool cover -func profile.cov
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										569
									
								
								logger/types.go
									
									
									
									
									
								
							
							
						
						
									
										569
									
								
								logger/types.go
									
									
									
									
									
								
							@@ -7,7 +7,6 @@ import (
 | 
				
			|||||||
type utctime8601 struct{}
 | 
					type utctime8601 struct{}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (utctime8601) MarshalJSON() ([]byte, error) {
 | 
					func (utctime8601) MarshalJSON() ([]byte, error) {
 | 
				
			||||||
	// FIX This should be re-formated for proper ISO 8601
 | 
					 | 
				
			||||||
	return []byte(`"` + time.Now().UTC().Format(time.RFC3339Nano)[:26] + `Z"`), nil
 | 
						return []byte(`"` + time.Now().UTC().Format(time.RFC3339Nano)[:26] + `Z"`), nil
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -16,14 +15,13 @@ type JsonLog interface {
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
type LogEvent struct {
 | 
					type LogEvent struct {
 | 
				
			||||||
	Guid string      `json:"guid"`
 | 
						// Guid string      `json:"guid"`
 | 
				
			||||||
	Ts   utctime8601 `json:"ts"`
 | 
						Ts utctime8601 `json:"ts"`
 | 
				
			||||||
	// Level string      `json:"level"`
 | 
						// Level string      `json:"level"`
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
type LogStarting struct {
 | 
					type LogStarting struct {
 | 
				
			||||||
	ClientString    string `json:"version_string"`
 | 
						ClientString    string `json:"client_impl"`
 | 
				
			||||||
	Coinbase        string `json:"coinbase"`
 | 
					 | 
				
			||||||
	ProtocolVersion int    `json:"eth_version"`
 | 
						ProtocolVersion int    `json:"eth_version"`
 | 
				
			||||||
	LogEvent
 | 
						LogEvent
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
@@ -32,20 +30,11 @@ func (l *LogStarting) EventName() string {
 | 
				
			|||||||
	return "starting"
 | 
						return "starting"
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
type P2PConnecting struct {
 | 
					 | 
				
			||||||
	RemoteId       string `json:"remote_id"`
 | 
					 | 
				
			||||||
	RemoteEndpoint string `json:"remote_endpoint"`
 | 
					 | 
				
			||||||
	NumConnections int    `json:"num_connections"`
 | 
					 | 
				
			||||||
	LogEvent
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func (l *P2PConnecting) EventName() string {
 | 
					 | 
				
			||||||
	return "p2p.connecting"
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
type P2PConnected struct {
 | 
					type P2PConnected struct {
 | 
				
			||||||
	NumConnections int    `json:"num_connections"`
 | 
						RemoteId            string `json:"remote_id"`
 | 
				
			||||||
	RemoteId       string `json:"remote_id"`
 | 
						RemoteAddress       string `json:"remote_addr"`
 | 
				
			||||||
 | 
						RemoteVersionString string `json:"remote_version_string"`
 | 
				
			||||||
 | 
						NumConnections      int    `json:"num_connections"`
 | 
				
			||||||
	LogEvent
 | 
						LogEvent
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -53,17 +42,6 @@ func (l *P2PConnected) EventName() string {
 | 
				
			|||||||
	return "p2p.connected"
 | 
						return "p2p.connected"
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
type P2PHandshaked struct {
 | 
					 | 
				
			||||||
	RemoteCapabilities []string `json:"remote_capabilities"`
 | 
					 | 
				
			||||||
	RemoteId           string   `json:"remote_id"`
 | 
					 | 
				
			||||||
	NumConnections     int      `json:"num_connections"`
 | 
					 | 
				
			||||||
	LogEvent
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func (l *P2PHandshaked) EventName() string {
 | 
					 | 
				
			||||||
	return "p2p.handshaked"
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
type P2PDisconnected struct {
 | 
					type P2PDisconnected struct {
 | 
				
			||||||
	NumConnections int    `json:"num_connections"`
 | 
						NumConnections int    `json:"num_connections"`
 | 
				
			||||||
	RemoteId       string `json:"remote_id"`
 | 
						RemoteId       string `json:"remote_id"`
 | 
				
			||||||
@@ -74,247 +52,46 @@ func (l *P2PDisconnected) EventName() string {
 | 
				
			|||||||
	return "p2p.disconnected"
 | 
						return "p2p.disconnected"
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
type P2PDisconnecting struct {
 | 
					type EthMinerNewBlock struct {
 | 
				
			||||||
	Reason         string `json:"reason"`
 | 
						BlockHash     string `json:"block_hash"`
 | 
				
			||||||
	RemoteId       string `json:"remote_id"`
 | 
						BlockNumber   int    `json:"block_number"`
 | 
				
			||||||
	NumConnections int    `json:"num_connections"`
 | 
						ChainHeadHash string `json:"chain_head_hash"`
 | 
				
			||||||
 | 
						BlockPrevHash string `json:"block_prev_hash"`
 | 
				
			||||||
	LogEvent
 | 
						LogEvent
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (l *P2PDisconnecting) EventName() string {
 | 
					func (l *EthMinerNewBlock) EventName() string {
 | 
				
			||||||
	return "p2p.disconnecting"
 | 
						return "eth.miner.new_block"
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
type P2PDisconnectingBadHandshake struct {
 | 
					type EthChainReceivedNewBlock struct {
 | 
				
			||||||
	Reason         string `json:"reason"`
 | 
						BlockHash     string `json:"block_hash"`
 | 
				
			||||||
	RemoteId       string `json:"remote_id"`
 | 
						BlockNumber   int    `json:"block_number"`
 | 
				
			||||||
	NumConnections int    `json:"num_connections"`
 | 
						ChainHeadHash string `json:"chain_head_hash"`
 | 
				
			||||||
 | 
						BlockPrevHash string `json:"block_prev_hash"`
 | 
				
			||||||
 | 
						RemoteId      int    `json:"remote_id"`
 | 
				
			||||||
	LogEvent
 | 
						LogEvent
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (l *P2PDisconnectingBadHandshake) EventName() string {
 | 
					func (l *EthChainReceivedNewBlock) EventName() string {
 | 
				
			||||||
	return "p2p.disconnecting.bad_handshake"
 | 
						return "eth.chain.received.new_block"
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
type P2PDisconnectingBadProtocol struct {
 | 
					type EthChainNewHead struct {
 | 
				
			||||||
	Reason         string `json:"reason"`
 | 
						BlockHash     string `json:"block_hash"`
 | 
				
			||||||
	RemoteId       string `json:"remote_id"`
 | 
						BlockNumber   int    `json:"block_number"`
 | 
				
			||||||
	NumConnections int    `json:"num_connections"`
 | 
						ChainHeadHash string `json:"chain_head_hash"`
 | 
				
			||||||
 | 
						BlockPrevHash string `json:"block_prev_hash"`
 | 
				
			||||||
	LogEvent
 | 
						LogEvent
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (l *P2PDisconnectingBadProtocol) EventName() string {
 | 
					func (l *EthChainNewHead) EventName() string {
 | 
				
			||||||
	return "p2p.disconnecting.bad_protocol"
 | 
						return "eth.chain.new_head"
 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
type P2PDisconnectingReputation struct {
 | 
					 | 
				
			||||||
	Reason         string `json:"reason"`
 | 
					 | 
				
			||||||
	RemoteId       string `json:"remote_id"`
 | 
					 | 
				
			||||||
	NumConnections int    `json:"num_connections"`
 | 
					 | 
				
			||||||
	LogEvent
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func (l *P2PDisconnectingReputation) EventName() string {
 | 
					 | 
				
			||||||
	return "p2p.disconnecting.reputation"
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
type P2PDisconnectingDHT struct {
 | 
					 | 
				
			||||||
	Reason         string `json:"reason"`
 | 
					 | 
				
			||||||
	RemoteId       string `json:"remote_id"`
 | 
					 | 
				
			||||||
	NumConnections int    `json:"num_connections"`
 | 
					 | 
				
			||||||
	LogEvent
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func (l *P2PDisconnectingDHT) EventName() string {
 | 
					 | 
				
			||||||
	return "p2p.disconnecting.dht"
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
type P2PEthDisconnectingBadBlock struct {
 | 
					 | 
				
			||||||
	Reason         string `json:"reason"`
 | 
					 | 
				
			||||||
	RemoteId       string `json:"remote_id"`
 | 
					 | 
				
			||||||
	NumConnections int    `json:"num_connections"`
 | 
					 | 
				
			||||||
	LogEvent
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func (l *P2PEthDisconnectingBadBlock) EventName() string {
 | 
					 | 
				
			||||||
	return "p2p.eth.disconnecting.bad_block"
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
type P2PEthDisconnectingBadTx struct {
 | 
					 | 
				
			||||||
	Reason         string `json:"reason"`
 | 
					 | 
				
			||||||
	RemoteId       string `json:"remote_id"`
 | 
					 | 
				
			||||||
	NumConnections int    `json:"num_connections"`
 | 
					 | 
				
			||||||
	LogEvent
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func (l *P2PEthDisconnectingBadTx) EventName() string {
 | 
					 | 
				
			||||||
	return "p2p.eth.disconnecting.bad_tx"
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
type EthNewBlockMined struct {
 | 
					 | 
				
			||||||
	BlockNumber     int    `json:"block_number"`
 | 
					 | 
				
			||||||
	HeadHash        string `json:"head_hash"`
 | 
					 | 
				
			||||||
	BlockHash       string `json:"block_hash"`
 | 
					 | 
				
			||||||
	BlockHexRlp     string `json:"block_hexrlp"`
 | 
					 | 
				
			||||||
	BlockDifficulty int    `json:"block_difficulty"`
 | 
					 | 
				
			||||||
	BlockPrevHash   string `json:"block_prev_hash"`
 | 
					 | 
				
			||||||
	LogEvent
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func (l *EthNewBlockMined) EventName() string {
 | 
					 | 
				
			||||||
	return "eth.newblock.mined"
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
type EthNewBlockBroadcasted struct {
 | 
					 | 
				
			||||||
	BlockNumber     int    `json:"block_number"`
 | 
					 | 
				
			||||||
	HeadHash        string `json:"head_hash"`
 | 
					 | 
				
			||||||
	BlockHash       string `json:"block_hash"`
 | 
					 | 
				
			||||||
	BlockDifficulty int    `json:"block_difficulty"`
 | 
					 | 
				
			||||||
	BlockPrevHash   string `json:"block_prev_hash"`
 | 
					 | 
				
			||||||
	LogEvent
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func (l *EthNewBlockBroadcasted) EventName() string {
 | 
					 | 
				
			||||||
	return "eth.newblock.broadcasted"
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
type EthNewBlockReceived struct {
 | 
					 | 
				
			||||||
	BlockNumber     int    `json:"block_number"`
 | 
					 | 
				
			||||||
	HeadHash        string `json:"head_hash"`
 | 
					 | 
				
			||||||
	BlockHash       string `json:"block_hash"`
 | 
					 | 
				
			||||||
	BlockDifficulty int    `json:"block_difficulty"`
 | 
					 | 
				
			||||||
	BlockPrevHash   string `json:"block_prev_hash"`
 | 
					 | 
				
			||||||
	LogEvent
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func (l *EthNewBlockReceived) EventName() string {
 | 
					 | 
				
			||||||
	return "eth.newblock.received"
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
type EthNewBlockIsKnown struct {
 | 
					 | 
				
			||||||
	BlockNumber     int    `json:"block_number"`
 | 
					 | 
				
			||||||
	HeadHash        string `json:"head_hash"`
 | 
					 | 
				
			||||||
	BlockHash       string `json:"block_hash"`
 | 
					 | 
				
			||||||
	BlockDifficulty int    `json:"block_difficulty"`
 | 
					 | 
				
			||||||
	BlockPrevHash   string `json:"block_prev_hash"`
 | 
					 | 
				
			||||||
	LogEvent
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func (l *EthNewBlockIsKnown) EventName() string {
 | 
					 | 
				
			||||||
	return "eth.newblock.is_known"
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
type EthNewBlockIsNew struct {
 | 
					 | 
				
			||||||
	BlockNumber     int    `json:"block_number"`
 | 
					 | 
				
			||||||
	HeadHash        string `json:"head_hash"`
 | 
					 | 
				
			||||||
	BlockHash       string `json:"block_hash"`
 | 
					 | 
				
			||||||
	BlockDifficulty int    `json:"block_difficulty"`
 | 
					 | 
				
			||||||
	BlockPrevHash   string `json:"block_prev_hash"`
 | 
					 | 
				
			||||||
	LogEvent
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func (l *EthNewBlockIsNew) EventName() string {
 | 
					 | 
				
			||||||
	return "eth.newblock.is_new"
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
type EthNewBlockMissingParent struct {
 | 
					 | 
				
			||||||
	BlockNumber     int    `json:"block_number"`
 | 
					 | 
				
			||||||
	HeadHash        string `json:"head_hash"`
 | 
					 | 
				
			||||||
	BlockHash       string `json:"block_hash"`
 | 
					 | 
				
			||||||
	BlockDifficulty int    `json:"block_difficulty"`
 | 
					 | 
				
			||||||
	BlockPrevHash   string `json:"block_prev_hash"`
 | 
					 | 
				
			||||||
	LogEvent
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func (l *EthNewBlockMissingParent) EventName() string {
 | 
					 | 
				
			||||||
	return "eth.newblock.missing_parent"
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
type EthNewBlockIsInvalid struct {
 | 
					 | 
				
			||||||
	BlockNumber     int    `json:"block_number"`
 | 
					 | 
				
			||||||
	HeadHash        string `json:"head_hash"`
 | 
					 | 
				
			||||||
	BlockHash       string `json:"block_hash"`
 | 
					 | 
				
			||||||
	BlockDifficulty int    `json:"block_difficulty"`
 | 
					 | 
				
			||||||
	BlockPrevHash   string `json:"block_prev_hash"`
 | 
					 | 
				
			||||||
	LogEvent
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func (l *EthNewBlockIsInvalid) EventName() string {
 | 
					 | 
				
			||||||
	return "eth.newblock.is_invalid"
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
type EthNewBlockChainIsOlder struct {
 | 
					 | 
				
			||||||
	BlockNumber     int    `json:"block_number"`
 | 
					 | 
				
			||||||
	HeadHash        string `json:"head_hash"`
 | 
					 | 
				
			||||||
	BlockHash       string `json:"block_hash"`
 | 
					 | 
				
			||||||
	BlockDifficulty int    `json:"block_difficulty"`
 | 
					 | 
				
			||||||
	BlockPrevHash   string `json:"block_prev_hash"`
 | 
					 | 
				
			||||||
	LogEvent
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func (l *EthNewBlockChainIsOlder) EventName() string {
 | 
					 | 
				
			||||||
	return "eth.newblock.chain.is_older"
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
type EthNewBlockChainIsCanonical struct {
 | 
					 | 
				
			||||||
	BlockNumber     int    `json:"block_number"`
 | 
					 | 
				
			||||||
	HeadHash        string `json:"head_hash"`
 | 
					 | 
				
			||||||
	BlockHash       string `json:"block_hash"`
 | 
					 | 
				
			||||||
	BlockDifficulty int    `json:"block_difficulty"`
 | 
					 | 
				
			||||||
	BlockPrevHash   string `json:"block_prev_hash"`
 | 
					 | 
				
			||||||
	LogEvent
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func (l *EthNewBlockChainIsCanonical) EventName() string {
 | 
					 | 
				
			||||||
	return "eth.newblock.chain.is_cannonical"
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
type EthNewBlockChainNotCanonical struct {
 | 
					 | 
				
			||||||
	BlockNumber     int    `json:"block_number"`
 | 
					 | 
				
			||||||
	HeadHash        string `json:"head_hash"`
 | 
					 | 
				
			||||||
	BlockHash       string `json:"block_hash"`
 | 
					 | 
				
			||||||
	BlockDifficulty int    `json:"block_difficulty"`
 | 
					 | 
				
			||||||
	BlockPrevHash   string `json:"block_prev_hash"`
 | 
					 | 
				
			||||||
	LogEvent
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func (l *EthNewBlockChainNotCanonical) EventName() string {
 | 
					 | 
				
			||||||
	return "eth.newblock.chain.not_cannonical"
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
type EthNewBlockChainSwitched struct {
 | 
					 | 
				
			||||||
	BlockNumber     int    `json:"block_number"`
 | 
					 | 
				
			||||||
	HeadHash        string `json:"head_hash"`
 | 
					 | 
				
			||||||
	OldHeadHash     string `json:"old_head_hash"`
 | 
					 | 
				
			||||||
	BlockHash       string `json:"block_hash"`
 | 
					 | 
				
			||||||
	BlockDifficulty int    `json:"block_difficulty"`
 | 
					 | 
				
			||||||
	BlockPrevHash   string `json:"block_prev_hash"`
 | 
					 | 
				
			||||||
	LogEvent
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func (l *EthNewBlockChainSwitched) EventName() string {
 | 
					 | 
				
			||||||
	return "eth.newblock.chain.switched"
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
type EthTxCreated struct {
 | 
					 | 
				
			||||||
	TxHash    string `json:"tx_hash"`
 | 
					 | 
				
			||||||
	TxSender  string `json:"tx_sender"`
 | 
					 | 
				
			||||||
	TxAddress string `json:"tx_address"`
 | 
					 | 
				
			||||||
	TxHexRLP  string `json:"tx_hexrlp"`
 | 
					 | 
				
			||||||
	TxNonce   int    `json:"tx_nonce"`
 | 
					 | 
				
			||||||
	LogEvent
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func (l *EthTxCreated) EventName() string {
 | 
					 | 
				
			||||||
	return "eth.tx.created"
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
type EthTxReceived struct {
 | 
					type EthTxReceived struct {
 | 
				
			||||||
	TxHash    string `json:"tx_hash"`
 | 
						TxHash   string `json:"tx_hash"`
 | 
				
			||||||
	TxAddress string `json:"tx_address"`
 | 
						RemoteId string `json:"remote_id"`
 | 
				
			||||||
	TxHexRLP  string `json:"tx_hexrlp"`
 | 
					 | 
				
			||||||
	RemoteId  string `json:"remote_id"`
 | 
					 | 
				
			||||||
	TxNonce   int    `json:"tx_nonce"`
 | 
					 | 
				
			||||||
	LogEvent
 | 
						LogEvent
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -322,39 +99,261 @@ func (l *EthTxReceived) EventName() string {
 | 
				
			|||||||
	return "eth.tx.received"
 | 
						return "eth.tx.received"
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
type EthTxBroadcasted struct {
 | 
					//
 | 
				
			||||||
	TxHash    string `json:"tx_hash"`
 | 
					//
 | 
				
			||||||
	TxSender  string `json:"tx_sender"`
 | 
					// The types below are legacy and need to be converted to new format or deleted
 | 
				
			||||||
	TxAddress string `json:"tx_address"`
 | 
					//
 | 
				
			||||||
	TxNonce   int    `json:"tx_nonce"`
 | 
					//
 | 
				
			||||||
	LogEvent
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (l *EthTxBroadcasted) EventName() string {
 | 
					// type P2PConnecting struct {
 | 
				
			||||||
	return "eth.tx.broadcasted"
 | 
					// 	RemoteId       string `json:"remote_id"`
 | 
				
			||||||
}
 | 
					// 	RemoteEndpoint string `json:"remote_endpoint"`
 | 
				
			||||||
 | 
					// 	NumConnections int    `json:"num_connections"`
 | 
				
			||||||
 | 
					// 	LogEvent
 | 
				
			||||||
 | 
					// }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
type EthTxValidated struct {
 | 
					// func (l *P2PConnecting) EventName() string {
 | 
				
			||||||
	TxHash    string `json:"tx_hash"`
 | 
					// 	return "p2p.connecting"
 | 
				
			||||||
	TxSender  string `json:"tx_sender"`
 | 
					// }
 | 
				
			||||||
	TxAddress string `json:"tx_address"`
 | 
					 | 
				
			||||||
	TxNonce   int    `json:"tx_nonce"`
 | 
					 | 
				
			||||||
	LogEvent
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (l *EthTxValidated) EventName() string {
 | 
					// type P2PHandshaked struct {
 | 
				
			||||||
	return "eth.tx.validated"
 | 
					// 	RemoteCapabilities []string `json:"remote_capabilities"`
 | 
				
			||||||
}
 | 
					// 	RemoteId           string   `json:"remote_id"`
 | 
				
			||||||
 | 
					// 	NumConnections     int      `json:"num_connections"`
 | 
				
			||||||
 | 
					// 	LogEvent
 | 
				
			||||||
 | 
					// }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
type EthTxIsInvalid struct {
 | 
					// func (l *P2PHandshaked) EventName() string {
 | 
				
			||||||
	TxHash    string `json:"tx_hash"`
 | 
					// 	return "p2p.handshaked"
 | 
				
			||||||
	TxSender  string `json:"tx_sender"`
 | 
					// }
 | 
				
			||||||
	TxAddress string `json:"tx_address"`
 | 
					 | 
				
			||||||
	Reason    string `json:"reason"`
 | 
					 | 
				
			||||||
	TxNonce   int    `json:"tx_nonce"`
 | 
					 | 
				
			||||||
	LogEvent
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (l *EthTxIsInvalid) EventName() string {
 | 
					// type P2PDisconnecting struct {
 | 
				
			||||||
	return "eth.tx.is_invalid"
 | 
					// 	Reason         string `json:"reason"`
 | 
				
			||||||
}
 | 
					// 	RemoteId       string `json:"remote_id"`
 | 
				
			||||||
 | 
					// 	NumConnections int    `json:"num_connections"`
 | 
				
			||||||
 | 
					// 	LogEvent
 | 
				
			||||||
 | 
					// }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// func (l *P2PDisconnecting) EventName() string {
 | 
				
			||||||
 | 
					// 	return "p2p.disconnecting"
 | 
				
			||||||
 | 
					// }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// type P2PDisconnectingBadHandshake struct {
 | 
				
			||||||
 | 
					// 	Reason         string `json:"reason"`
 | 
				
			||||||
 | 
					// 	RemoteId       string `json:"remote_id"`
 | 
				
			||||||
 | 
					// 	NumConnections int    `json:"num_connections"`
 | 
				
			||||||
 | 
					// 	LogEvent
 | 
				
			||||||
 | 
					// }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// func (l *P2PDisconnectingBadHandshake) EventName() string {
 | 
				
			||||||
 | 
					// 	return "p2p.disconnecting.bad_handshake"
 | 
				
			||||||
 | 
					// }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// type P2PDisconnectingBadProtocol struct {
 | 
				
			||||||
 | 
					// 	Reason         string `json:"reason"`
 | 
				
			||||||
 | 
					// 	RemoteId       string `json:"remote_id"`
 | 
				
			||||||
 | 
					// 	NumConnections int    `json:"num_connections"`
 | 
				
			||||||
 | 
					// 	LogEvent
 | 
				
			||||||
 | 
					// }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// func (l *P2PDisconnectingBadProtocol) EventName() string {
 | 
				
			||||||
 | 
					// 	return "p2p.disconnecting.bad_protocol"
 | 
				
			||||||
 | 
					// }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// type P2PDisconnectingReputation struct {
 | 
				
			||||||
 | 
					// 	Reason         string `json:"reason"`
 | 
				
			||||||
 | 
					// 	RemoteId       string `json:"remote_id"`
 | 
				
			||||||
 | 
					// 	NumConnections int    `json:"num_connections"`
 | 
				
			||||||
 | 
					// 	LogEvent
 | 
				
			||||||
 | 
					// }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// func (l *P2PDisconnectingReputation) EventName() string {
 | 
				
			||||||
 | 
					// 	return "p2p.disconnecting.reputation"
 | 
				
			||||||
 | 
					// }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// type P2PDisconnectingDHT struct {
 | 
				
			||||||
 | 
					// 	Reason         string `json:"reason"`
 | 
				
			||||||
 | 
					// 	RemoteId       string `json:"remote_id"`
 | 
				
			||||||
 | 
					// 	NumConnections int    `json:"num_connections"`
 | 
				
			||||||
 | 
					// 	LogEvent
 | 
				
			||||||
 | 
					// }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// func (l *P2PDisconnectingDHT) EventName() string {
 | 
				
			||||||
 | 
					// 	return "p2p.disconnecting.dht"
 | 
				
			||||||
 | 
					// }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// type P2PEthDisconnectingBadBlock struct {
 | 
				
			||||||
 | 
					// 	Reason         string `json:"reason"`
 | 
				
			||||||
 | 
					// 	RemoteId       string `json:"remote_id"`
 | 
				
			||||||
 | 
					// 	NumConnections int    `json:"num_connections"`
 | 
				
			||||||
 | 
					// 	LogEvent
 | 
				
			||||||
 | 
					// }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// func (l *P2PEthDisconnectingBadBlock) EventName() string {
 | 
				
			||||||
 | 
					// 	return "p2p.eth.disconnecting.bad_block"
 | 
				
			||||||
 | 
					// }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// type P2PEthDisconnectingBadTx struct {
 | 
				
			||||||
 | 
					// 	Reason         string `json:"reason"`
 | 
				
			||||||
 | 
					// 	RemoteId       string `json:"remote_id"`
 | 
				
			||||||
 | 
					// 	NumConnections int    `json:"num_connections"`
 | 
				
			||||||
 | 
					// 	LogEvent
 | 
				
			||||||
 | 
					// }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// func (l *P2PEthDisconnectingBadTx) EventName() string {
 | 
				
			||||||
 | 
					// 	return "p2p.eth.disconnecting.bad_tx"
 | 
				
			||||||
 | 
					// }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// type EthNewBlockBroadcasted struct {
 | 
				
			||||||
 | 
					// 	BlockNumber     int    `json:"block_number"`
 | 
				
			||||||
 | 
					// 	HeadHash        string `json:"head_hash"`
 | 
				
			||||||
 | 
					// 	BlockHash       string `json:"block_hash"`
 | 
				
			||||||
 | 
					// 	BlockDifficulty int    `json:"block_difficulty"`
 | 
				
			||||||
 | 
					// 	BlockPrevHash   string `json:"block_prev_hash"`
 | 
				
			||||||
 | 
					// 	LogEvent
 | 
				
			||||||
 | 
					// }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// func (l *EthNewBlockBroadcasted) EventName() string {
 | 
				
			||||||
 | 
					// 	return "eth.newblock.broadcasted"
 | 
				
			||||||
 | 
					// }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// type EthNewBlockIsKnown struct {
 | 
				
			||||||
 | 
					// 	BlockNumber     int    `json:"block_number"`
 | 
				
			||||||
 | 
					// 	HeadHash        string `json:"head_hash"`
 | 
				
			||||||
 | 
					// 	BlockHash       string `json:"block_hash"`
 | 
				
			||||||
 | 
					// 	BlockDifficulty int    `json:"block_difficulty"`
 | 
				
			||||||
 | 
					// 	BlockPrevHash   string `json:"block_prev_hash"`
 | 
				
			||||||
 | 
					// 	LogEvent
 | 
				
			||||||
 | 
					// }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// func (l *EthNewBlockIsKnown) EventName() string {
 | 
				
			||||||
 | 
					// 	return "eth.newblock.is_known"
 | 
				
			||||||
 | 
					// }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// type EthNewBlockIsNew struct {
 | 
				
			||||||
 | 
					// 	BlockNumber     int    `json:"block_number"`
 | 
				
			||||||
 | 
					// 	HeadHash        string `json:"head_hash"`
 | 
				
			||||||
 | 
					// 	BlockHash       string `json:"block_hash"`
 | 
				
			||||||
 | 
					// 	BlockDifficulty int    `json:"block_difficulty"`
 | 
				
			||||||
 | 
					// 	BlockPrevHash   string `json:"block_prev_hash"`
 | 
				
			||||||
 | 
					// 	LogEvent
 | 
				
			||||||
 | 
					// }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// func (l *EthNewBlockIsNew) EventName() string {
 | 
				
			||||||
 | 
					// 	return "eth.newblock.is_new"
 | 
				
			||||||
 | 
					// }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// type EthNewBlockMissingParent struct {
 | 
				
			||||||
 | 
					// 	BlockNumber     int    `json:"block_number"`
 | 
				
			||||||
 | 
					// 	HeadHash        string `json:"head_hash"`
 | 
				
			||||||
 | 
					// 	BlockHash       string `json:"block_hash"`
 | 
				
			||||||
 | 
					// 	BlockDifficulty int    `json:"block_difficulty"`
 | 
				
			||||||
 | 
					// 	BlockPrevHash   string `json:"block_prev_hash"`
 | 
				
			||||||
 | 
					// 	LogEvent
 | 
				
			||||||
 | 
					// }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// func (l *EthNewBlockMissingParent) EventName() string {
 | 
				
			||||||
 | 
					// 	return "eth.newblock.missing_parent"
 | 
				
			||||||
 | 
					// }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// type EthNewBlockIsInvalid struct {
 | 
				
			||||||
 | 
					// 	BlockNumber     int    `json:"block_number"`
 | 
				
			||||||
 | 
					// 	HeadHash        string `json:"head_hash"`
 | 
				
			||||||
 | 
					// 	BlockHash       string `json:"block_hash"`
 | 
				
			||||||
 | 
					// 	BlockDifficulty int    `json:"block_difficulty"`
 | 
				
			||||||
 | 
					// 	BlockPrevHash   string `json:"block_prev_hash"`
 | 
				
			||||||
 | 
					// 	LogEvent
 | 
				
			||||||
 | 
					// }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// func (l *EthNewBlockIsInvalid) EventName() string {
 | 
				
			||||||
 | 
					// 	return "eth.newblock.is_invalid"
 | 
				
			||||||
 | 
					// }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// type EthNewBlockChainIsOlder struct {
 | 
				
			||||||
 | 
					// 	BlockNumber     int    `json:"block_number"`
 | 
				
			||||||
 | 
					// 	HeadHash        string `json:"head_hash"`
 | 
				
			||||||
 | 
					// 	BlockHash       string `json:"block_hash"`
 | 
				
			||||||
 | 
					// 	BlockDifficulty int    `json:"block_difficulty"`
 | 
				
			||||||
 | 
					// 	BlockPrevHash   string `json:"block_prev_hash"`
 | 
				
			||||||
 | 
					// 	LogEvent
 | 
				
			||||||
 | 
					// }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// func (l *EthNewBlockChainIsOlder) EventName() string {
 | 
				
			||||||
 | 
					// 	return "eth.newblock.chain.is_older"
 | 
				
			||||||
 | 
					// }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// type EthNewBlockChainIsCanonical struct {
 | 
				
			||||||
 | 
					// 	BlockNumber     int    `json:"block_number"`
 | 
				
			||||||
 | 
					// 	HeadHash        string `json:"head_hash"`
 | 
				
			||||||
 | 
					// 	BlockHash       string `json:"block_hash"`
 | 
				
			||||||
 | 
					// 	BlockDifficulty int    `json:"block_difficulty"`
 | 
				
			||||||
 | 
					// 	BlockPrevHash   string `json:"block_prev_hash"`
 | 
				
			||||||
 | 
					// 	LogEvent
 | 
				
			||||||
 | 
					// }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// func (l *EthNewBlockChainIsCanonical) EventName() string {
 | 
				
			||||||
 | 
					// 	return "eth.newblock.chain.is_cannonical"
 | 
				
			||||||
 | 
					// }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// type EthNewBlockChainNotCanonical struct {
 | 
				
			||||||
 | 
					// 	BlockNumber     int    `json:"block_number"`
 | 
				
			||||||
 | 
					// 	HeadHash        string `json:"head_hash"`
 | 
				
			||||||
 | 
					// 	BlockHash       string `json:"block_hash"`
 | 
				
			||||||
 | 
					// 	BlockDifficulty int    `json:"block_difficulty"`
 | 
				
			||||||
 | 
					// 	BlockPrevHash   string `json:"block_prev_hash"`
 | 
				
			||||||
 | 
					// 	LogEvent
 | 
				
			||||||
 | 
					// }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// func (l *EthNewBlockChainNotCanonical) EventName() string {
 | 
				
			||||||
 | 
					// 	return "eth.newblock.chain.not_cannonical"
 | 
				
			||||||
 | 
					// }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// type EthTxCreated struct {
 | 
				
			||||||
 | 
					// 	TxHash    string `json:"tx_hash"`
 | 
				
			||||||
 | 
					// 	TxSender  string `json:"tx_sender"`
 | 
				
			||||||
 | 
					// 	TxAddress string `json:"tx_address"`
 | 
				
			||||||
 | 
					// 	TxHexRLP  string `json:"tx_hexrlp"`
 | 
				
			||||||
 | 
					// 	TxNonce   int    `json:"tx_nonce"`
 | 
				
			||||||
 | 
					// 	LogEvent
 | 
				
			||||||
 | 
					// }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// func (l *EthTxCreated) EventName() string {
 | 
				
			||||||
 | 
					// 	return "eth.tx.created"
 | 
				
			||||||
 | 
					// }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// type EthTxBroadcasted struct {
 | 
				
			||||||
 | 
					// 	TxHash    string `json:"tx_hash"`
 | 
				
			||||||
 | 
					// 	TxSender  string `json:"tx_sender"`
 | 
				
			||||||
 | 
					// 	TxAddress string `json:"tx_address"`
 | 
				
			||||||
 | 
					// 	TxNonce   int    `json:"tx_nonce"`
 | 
				
			||||||
 | 
					// 	LogEvent
 | 
				
			||||||
 | 
					// }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// func (l *EthTxBroadcasted) EventName() string {
 | 
				
			||||||
 | 
					// 	return "eth.tx.broadcasted"
 | 
				
			||||||
 | 
					// }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// type EthTxValidated struct {
 | 
				
			||||||
 | 
					// 	TxHash    string `json:"tx_hash"`
 | 
				
			||||||
 | 
					// 	TxSender  string `json:"tx_sender"`
 | 
				
			||||||
 | 
					// 	TxAddress string `json:"tx_address"`
 | 
				
			||||||
 | 
					// 	TxNonce   int    `json:"tx_nonce"`
 | 
				
			||||||
 | 
					// 	LogEvent
 | 
				
			||||||
 | 
					// }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// func (l *EthTxValidated) EventName() string {
 | 
				
			||||||
 | 
					// 	return "eth.tx.validated"
 | 
				
			||||||
 | 
					// }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// type EthTxIsInvalid struct {
 | 
				
			||||||
 | 
					// 	TxHash    string `json:"tx_hash"`
 | 
				
			||||||
 | 
					// 	TxSender  string `json:"tx_sender"`
 | 
				
			||||||
 | 
					// 	TxAddress string `json:"tx_address"`
 | 
				
			||||||
 | 
					// 	Reason    string `json:"reason"`
 | 
				
			||||||
 | 
					// 	TxNonce   int    `json:"tx_nonce"`
 | 
				
			||||||
 | 
					// 	LogEvent
 | 
				
			||||||
 | 
					// }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// func (l *EthTxIsInvalid) EventName() string {
 | 
				
			||||||
 | 
					// 	return "eth.tx.is_invalid"
 | 
				
			||||||
 | 
					// }
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -20,13 +20,13 @@ type Miner struct {
 | 
				
			|||||||
	mining   bool
 | 
						mining   bool
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func New(coinbase []byte, eth core.Backend) *Miner {
 | 
					func New(coinbase []byte, eth core.Backend, minerThreads int) *Miner {
 | 
				
			||||||
	miner := &Miner{
 | 
						miner := &Miner{
 | 
				
			||||||
		Coinbase: coinbase,
 | 
							Coinbase: coinbase,
 | 
				
			||||||
		worker:   newWorker(coinbase, eth),
 | 
							worker:   newWorker(coinbase, eth),
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	for i := 0; i < 4; i++ {
 | 
						for i := 0; i < minerThreads; i++ {
 | 
				
			||||||
		miner.worker.register(NewCpuMiner(i, ezp.New()))
 | 
							miner.worker.register(NewCpuMiner(i, ezp.New()))
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -109,14 +109,18 @@ func (self *worker) register(agent Agent) {
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (self *worker) update() {
 | 
					func (self *worker) update() {
 | 
				
			||||||
	events := self.mux.Subscribe(core.ChainEvent{}, core.TxPreEvent{})
 | 
						events := self.mux.Subscribe(core.ChainEvent{}, core.NewMinedBlockEvent{})
 | 
				
			||||||
 | 
					
 | 
				
			||||||
out:
 | 
					out:
 | 
				
			||||||
	for {
 | 
						for {
 | 
				
			||||||
		select {
 | 
							select {
 | 
				
			||||||
		case event := <-events.Chan():
 | 
							case event := <-events.Chan():
 | 
				
			||||||
			switch event.(type) {
 | 
								switch ev := event.(type) {
 | 
				
			||||||
			case core.ChainEvent, core.TxPreEvent:
 | 
								case core.ChainEvent:
 | 
				
			||||||
 | 
									if self.current.block != ev.Block {
 | 
				
			||||||
 | 
										self.commitNewWork()
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
								case core.NewMinedBlockEvent:
 | 
				
			||||||
				self.commitNewWork()
 | 
									self.commitNewWork()
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
		case <-self.quit:
 | 
							case <-self.quit:
 | 
				
			||||||
@@ -172,17 +176,19 @@ func (self *worker) commitNewWork() {
 | 
				
			|||||||
	transactions := self.eth.TxPool().GetTransactions()
 | 
						transactions := self.eth.TxPool().GetTransactions()
 | 
				
			||||||
	sort.Sort(types.TxByNonce{transactions})
 | 
						sort.Sort(types.TxByNonce{transactions})
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						minerlogger.Infof("committing new work with %d txs\n", len(transactions))
 | 
				
			||||||
	// Keep track of transactions which return errors so they can be removed
 | 
						// Keep track of transactions which return errors so they can be removed
 | 
				
			||||||
	var remove types.Transactions
 | 
						var remove types.Transactions
 | 
				
			||||||
 | 
					gasLimit:
 | 
				
			||||||
	for _, tx := range transactions {
 | 
						for _, tx := range transactions {
 | 
				
			||||||
		err := self.commitTransaction(tx)
 | 
							err := self.commitTransaction(tx)
 | 
				
			||||||
		switch {
 | 
							switch {
 | 
				
			||||||
		case core.IsNonceErr(err):
 | 
							case core.IsNonceErr(err):
 | 
				
			||||||
			// Remove invalid transactions
 | 
								// Remove invalid transactions
 | 
				
			||||||
			remove = append(remove, tx)
 | 
								remove = append(remove, tx)
 | 
				
			||||||
		case core.IsGasLimitErr(err):
 | 
							case state.IsGasLimitErr(err):
 | 
				
			||||||
			// Break on gas limit
 | 
								// Break on gas limit
 | 
				
			||||||
			break
 | 
								break gasLimit
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		if err != nil {
 | 
							if err != nil {
 | 
				
			||||||
@@ -227,11 +233,9 @@ func (self *worker) commitUncle(uncle *types.Header) error {
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (self *worker) commitTransaction(tx *types.Transaction) error {
 | 
					func (self *worker) commitTransaction(tx *types.Transaction) error {
 | 
				
			||||||
	snapshot := self.current.state.Copy()
 | 
						//fmt.Printf("proc %x %v\n", tx.Hash()[:3], tx.Nonce())
 | 
				
			||||||
	receipt, _, err := self.proc.ApplyTransaction(self.current.coinbase, self.current.state, self.current.block, tx, self.current.totalUsedGas, true)
 | 
						receipt, _, err := self.proc.ApplyTransaction(self.current.coinbase, self.current.state, self.current.block, tx, self.current.totalUsedGas, true)
 | 
				
			||||||
	if err != nil && (core.IsNonceErr(err) || core.IsGasLimitErr(err)) {
 | 
						if err != nil && (core.IsNonceErr(err) || state.IsGasLimitErr(err)) {
 | 
				
			||||||
		self.current.state.Set(snapshot)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		return err
 | 
							return err
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -253,7 +253,8 @@ func (t *udp) loop() {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
		case reply := <-t.replies:
 | 
							case reply := <-t.replies:
 | 
				
			||||||
			// run matching callbacks, remove if they return false.
 | 
								// run matching callbacks, remove if they return false.
 | 
				
			||||||
			for i, p := range pending {
 | 
								for i := 0; i < len(pending); i++ {
 | 
				
			||||||
 | 
									p := pending[i]
 | 
				
			||||||
				if reply.from == p.from && reply.ptype == p.ptype && p.callback(reply.data) {
 | 
									if reply.from == p.from && reply.ptype == p.ptype && p.callback(reply.data) {
 | 
				
			||||||
					p.errc <- nil
 | 
										p.errc <- nil
 | 
				
			||||||
					copy(pending[i:], pending[i+1:])
 | 
										copy(pending[i:], pending[i+1:])
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,21 +1,20 @@
 | 
				
			|||||||
package p2p
 | 
					package p2p
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import (
 | 
					import (
 | 
				
			||||||
	// "binary"
 | 
					 | 
				
			||||||
	"crypto/ecdsa"
 | 
						"crypto/ecdsa"
 | 
				
			||||||
	"crypto/rand"
 | 
						"crypto/rand"
 | 
				
			||||||
 | 
						"errors"
 | 
				
			||||||
	"fmt"
 | 
						"fmt"
 | 
				
			||||||
	"io"
 | 
						"io"
 | 
				
			||||||
 | 
						"net"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	"github.com/ethereum/go-ethereum/crypto"
 | 
						"github.com/ethereum/go-ethereum/crypto"
 | 
				
			||||||
	"github.com/ethereum/go-ethereum/crypto/ecies"
 | 
						"github.com/ethereum/go-ethereum/crypto/ecies"
 | 
				
			||||||
	"github.com/ethereum/go-ethereum/crypto/secp256k1"
 | 
						"github.com/ethereum/go-ethereum/crypto/secp256k1"
 | 
				
			||||||
	ethlogger "github.com/ethereum/go-ethereum/logger"
 | 
					 | 
				
			||||||
	"github.com/ethereum/go-ethereum/p2p/discover"
 | 
						"github.com/ethereum/go-ethereum/p2p/discover"
 | 
				
			||||||
 | 
						"github.com/ethereum/go-ethereum/rlp"
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
var clogger = ethlogger.NewLogger("CRYPTOID")
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
const (
 | 
					const (
 | 
				
			||||||
	sskLen = 16 // ecies.MaxSharedKeyLength(pubKey) / 2
 | 
						sskLen = 16 // ecies.MaxSharedKeyLength(pubKey) / 2
 | 
				
			||||||
	sigLen = 65 // elliptic S256
 | 
						sigLen = 65 // elliptic S256
 | 
				
			||||||
@@ -30,26 +29,76 @@ const (
 | 
				
			|||||||
	rHSLen     = authRespLen + eciesBytes // size of the final ECIES payload sent as receiver's handshake
 | 
						rHSLen     = authRespLen + eciesBytes // size of the final ECIES payload sent as receiver's handshake
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
type hexkey []byte
 | 
					type conn struct {
 | 
				
			||||||
 | 
						*frameRW
 | 
				
			||||||
func (self hexkey) String() string {
 | 
						*protoHandshake
 | 
				
			||||||
	return fmt.Sprintf("(%d) %x", len(self), []byte(self))
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func encHandshake(conn io.ReadWriter, prv *ecdsa.PrivateKey, dial *discover.Node) (
 | 
					func newConn(fd net.Conn, hs *protoHandshake) *conn {
 | 
				
			||||||
	remoteID discover.NodeID,
 | 
						return &conn{newFrameRW(fd, msgWriteTimeout), hs}
 | 
				
			||||||
	sessionToken []byte,
 | 
					}
 | 
				
			||||||
	err error,
 | 
					
 | 
				
			||||||
) {
 | 
					// encHandshake represents information about the remote end
 | 
				
			||||||
 | 
					// of a connection that is negotiated during the encryption handshake.
 | 
				
			||||||
 | 
					type encHandshake struct {
 | 
				
			||||||
 | 
						ID         discover.NodeID
 | 
				
			||||||
 | 
						IngressMAC []byte
 | 
				
			||||||
 | 
						EgressMAC  []byte
 | 
				
			||||||
 | 
						Token      []byte
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// protoHandshake is the RLP structure of the protocol handshake.
 | 
				
			||||||
 | 
					type protoHandshake struct {
 | 
				
			||||||
 | 
						Version    uint64
 | 
				
			||||||
 | 
						Name       string
 | 
				
			||||||
 | 
						Caps       []Cap
 | 
				
			||||||
 | 
						ListenPort uint64
 | 
				
			||||||
 | 
						ID         discover.NodeID
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// setupConn starts a protocol session on the given connection.
 | 
				
			||||||
 | 
					// It runs the encryption handshake and the protocol handshake.
 | 
				
			||||||
 | 
					// If dial is non-nil, the connection the local node is the initiator.
 | 
				
			||||||
 | 
					func setupConn(fd net.Conn, prv *ecdsa.PrivateKey, our *protoHandshake, dial *discover.Node) (*conn, error) {
 | 
				
			||||||
	if dial == nil {
 | 
						if dial == nil {
 | 
				
			||||||
		var remotePubkey []byte
 | 
							return setupInboundConn(fd, prv, our)
 | 
				
			||||||
		sessionToken, remotePubkey, err = inboundEncHandshake(conn, prv, nil)
 | 
					 | 
				
			||||||
		copy(remoteID[:], remotePubkey)
 | 
					 | 
				
			||||||
	} else {
 | 
						} else {
 | 
				
			||||||
		remoteID = dial.ID
 | 
							return setupOutboundConn(fd, prv, our, dial)
 | 
				
			||||||
		sessionToken, err = outboundEncHandshake(conn, prv, remoteID[:], nil)
 | 
					 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	return remoteID, sessionToken, err
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func setupInboundConn(fd net.Conn, prv *ecdsa.PrivateKey, our *protoHandshake) (*conn, error) {
 | 
				
			||||||
 | 
						// var remotePubkey []byte
 | 
				
			||||||
 | 
						// sessionToken, remotePubkey, err = inboundEncHandshake(fd, prv, nil)
 | 
				
			||||||
 | 
						// copy(remoteID[:], remotePubkey)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						rw := newFrameRW(fd, msgWriteTimeout)
 | 
				
			||||||
 | 
						rhs, err := readProtocolHandshake(rw, our)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							return nil, err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if err := writeProtocolHandshake(rw, our); err != nil {
 | 
				
			||||||
 | 
							return nil, fmt.Errorf("protocol write error: %v", err)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return &conn{rw, rhs}, nil
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func setupOutboundConn(fd net.Conn, prv *ecdsa.PrivateKey, our *protoHandshake, dial *discover.Node) (*conn, error) {
 | 
				
			||||||
 | 
						// remoteID = dial.ID
 | 
				
			||||||
 | 
						// sessionToken, err = outboundEncHandshake(fd, prv, remoteID[:], nil)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						rw := newFrameRW(fd, msgWriteTimeout)
 | 
				
			||||||
 | 
						if err := writeProtocolHandshake(rw, our); err != nil {
 | 
				
			||||||
 | 
							return nil, fmt.Errorf("protocol write error: %v", err)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						rhs, err := readProtocolHandshake(rw, our)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							return nil, fmt.Errorf("protocol handshake read error: %v", err)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if rhs.ID != dial.ID {
 | 
				
			||||||
 | 
							return nil, errors.New("dialed node id mismatch")
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return &conn{rw, rhs}, nil
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// outboundEncHandshake negotiates a session token on conn.
 | 
					// outboundEncHandshake negotiates a session token on conn.
 | 
				
			||||||
@@ -66,18 +115,9 @@ func outboundEncHandshake(conn io.ReadWriter, prvKey *ecdsa.PrivateKey, remotePu
 | 
				
			|||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
		return nil, err
 | 
							return nil, err
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	if sessionToken != nil {
 | 
					 | 
				
			||||||
		clogger.Debugf("session-token: %v", hexkey(sessionToken))
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	clogger.Debugf("initiator-nonce: %v", hexkey(initNonce))
 | 
					 | 
				
			||||||
	clogger.Debugf("initiator-random-private-key: %v", hexkey(crypto.FromECDSA(randomPrivKey)))
 | 
					 | 
				
			||||||
	randomPublicKeyS, _ := exportPublicKey(&randomPrivKey.PublicKey)
 | 
					 | 
				
			||||||
	clogger.Debugf("initiator-random-public-key: %v", hexkey(randomPublicKeyS))
 | 
					 | 
				
			||||||
	if _, err = conn.Write(auth); err != nil {
 | 
						if _, err = conn.Write(auth); err != nil {
 | 
				
			||||||
		return nil, err
 | 
							return nil, err
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	clogger.Debugf("initiator handshake: %v", hexkey(auth))
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	response := make([]byte, rHSLen)
 | 
						response := make([]byte, rHSLen)
 | 
				
			||||||
	if _, err = io.ReadFull(conn, response); err != nil {
 | 
						if _, err = io.ReadFull(conn, response); err != nil {
 | 
				
			||||||
@@ -88,9 +128,6 @@ func outboundEncHandshake(conn io.ReadWriter, prvKey *ecdsa.PrivateKey, remotePu
 | 
				
			|||||||
		return nil, err
 | 
							return nil, err
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	clogger.Debugf("receiver-nonce: %v", hexkey(recNonce))
 | 
					 | 
				
			||||||
	remoteRandomPubKeyS, _ := exportPublicKey(remoteRandomPubKey)
 | 
					 | 
				
			||||||
	clogger.Debugf("receiver-random-public-key: %v", hexkey(remoteRandomPubKeyS))
 | 
					 | 
				
			||||||
	return newSession(initNonce, recNonce, randomPrivKey, remoteRandomPubKey)
 | 
						return newSession(initNonce, recNonce, randomPrivKey, remoteRandomPubKey)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -221,12 +258,9 @@ func inboundEncHandshake(conn io.ReadWriter, prvKey *ecdsa.PrivateKey, sessionTo
 | 
				
			|||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
		return nil, nil, err
 | 
							return nil, nil, err
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	clogger.Debugf("receiver-nonce: %v", hexkey(recNonce))
 | 
					 | 
				
			||||||
	clogger.Debugf("receiver-random-priv-key: %v", hexkey(crypto.FromECDSA(randomPrivKey)))
 | 
					 | 
				
			||||||
	if _, err = conn.Write(response); err != nil {
 | 
						if _, err = conn.Write(response); err != nil {
 | 
				
			||||||
		return nil, nil, err
 | 
							return nil, nil, err
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	clogger.Debugf("receiver handshake:\n%v", hexkey(response))
 | 
					 | 
				
			||||||
	token, err = newSession(initNonce, recNonce, randomPrivKey, remoteRandomPubKey)
 | 
						token, err = newSession(initNonce, recNonce, randomPrivKey, remoteRandomPubKey)
 | 
				
			||||||
	return token, remotePubKey, err
 | 
						return token, remotePubKey, err
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
@@ -361,3 +395,40 @@ func xor(one, other []byte) (xor []byte) {
 | 
				
			|||||||
	}
 | 
						}
 | 
				
			||||||
	return xor
 | 
						return xor
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func writeProtocolHandshake(w MsgWriter, our *protoHandshake) error {
 | 
				
			||||||
 | 
						return EncodeMsg(w, handshakeMsg, our.Version, our.Name, our.Caps, our.ListenPort, our.ID[:])
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func readProtocolHandshake(r MsgReader, our *protoHandshake) (*protoHandshake, error) {
 | 
				
			||||||
 | 
						// read and handle remote handshake
 | 
				
			||||||
 | 
						msg, err := r.ReadMsg()
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							return nil, err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if msg.Code == discMsg {
 | 
				
			||||||
 | 
							// disconnect before protocol handshake is valid according to the
 | 
				
			||||||
 | 
							// spec and we send it ourself if Server.addPeer fails.
 | 
				
			||||||
 | 
							var reason DiscReason
 | 
				
			||||||
 | 
							rlp.Decode(msg.Payload, &reason)
 | 
				
			||||||
 | 
							return nil, discRequestedError(reason)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if msg.Code != handshakeMsg {
 | 
				
			||||||
 | 
							return nil, fmt.Errorf("expected handshake, got %x", msg.Code)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if msg.Size > baseProtocolMaxMsgSize {
 | 
				
			||||||
 | 
							return nil, fmt.Errorf("message too big (%d > %d)", msg.Size, baseProtocolMaxMsgSize)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						var hs protoHandshake
 | 
				
			||||||
 | 
						if err := msg.Decode(&hs); err != nil {
 | 
				
			||||||
 | 
							return nil, err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						// validate handshake info
 | 
				
			||||||
 | 
						if hs.Version != our.Version {
 | 
				
			||||||
 | 
							return nil, newPeerError(errP2PVersionMismatch, "required version %d, received %d\n", baseProtocolVersion, hs.Version)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if (hs.ID == discover.NodeID{}) {
 | 
				
			||||||
 | 
							return nil, newPeerError(errPubkeyInvalid, "missing")
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return &hs, nil
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@@ -5,10 +5,12 @@ import (
 | 
				
			|||||||
	"crypto/ecdsa"
 | 
						"crypto/ecdsa"
 | 
				
			||||||
	"crypto/rand"
 | 
						"crypto/rand"
 | 
				
			||||||
	"net"
 | 
						"net"
 | 
				
			||||||
 | 
						"reflect"
 | 
				
			||||||
	"testing"
 | 
						"testing"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	"github.com/ethereum/go-ethereum/crypto"
 | 
						"github.com/ethereum/go-ethereum/crypto"
 | 
				
			||||||
	"github.com/obscuren/ecies"
 | 
						"github.com/ethereum/go-ethereum/crypto/ecies"
 | 
				
			||||||
 | 
						"github.com/ethereum/go-ethereum/p2p/discover"
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func TestPublicKeyEncoding(t *testing.T) {
 | 
					func TestPublicKeyEncoding(t *testing.T) {
 | 
				
			||||||
@@ -91,14 +93,14 @@ func testCryptoHandshake(prv0, prv1 *ecdsa.PrivateKey, sessionToken []byte, t *t
 | 
				
			|||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
		t.Errorf("%v", err)
 | 
							t.Errorf("%v", err)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	t.Logf("-> %v", hexkey(auth))
 | 
						// t.Logf("-> %v", hexkey(auth))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// receiver reads auth and responds with response
 | 
						// receiver reads auth and responds with response
 | 
				
			||||||
	response, remoteRecNonce, remoteInitNonce, _, remoteRandomPrivKey, remoteInitRandomPubKey, err := authResp(auth, sessionToken, prv1)
 | 
						response, remoteRecNonce, remoteInitNonce, _, remoteRandomPrivKey, remoteInitRandomPubKey, err := authResp(auth, sessionToken, prv1)
 | 
				
			||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
		t.Errorf("%v", err)
 | 
							t.Errorf("%v", err)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	t.Logf("<- %v\n", hexkey(response))
 | 
						// t.Logf("<- %v\n", hexkey(response))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// initiator reads receiver's response and the key exchange completes
 | 
						// initiator reads receiver's response and the key exchange completes
 | 
				
			||||||
	recNonce, remoteRandomPubKey, _, err := completeHandshake(response, prv0)
 | 
						recNonce, remoteRandomPubKey, _, err := completeHandshake(response, prv0)
 | 
				
			||||||
@@ -132,7 +134,7 @@ func testCryptoHandshake(prv0, prv1 *ecdsa.PrivateKey, sessionToken []byte, t *t
 | 
				
			|||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func TestHandshake(t *testing.T) {
 | 
					func TestEncHandshake(t *testing.T) {
 | 
				
			||||||
	defer testlog(t).detach()
 | 
						defer testlog(t).detach()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	prv0, _ := crypto.GenerateKey()
 | 
						prv0, _ := crypto.GenerateKey()
 | 
				
			||||||
@@ -165,3 +167,58 @@ func TestHandshake(t *testing.T) {
 | 
				
			|||||||
		t.Error("session token mismatch")
 | 
							t.Error("session token mismatch")
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func TestSetupConn(t *testing.T) {
 | 
				
			||||||
 | 
						prv0, _ := crypto.GenerateKey()
 | 
				
			||||||
 | 
						prv1, _ := crypto.GenerateKey()
 | 
				
			||||||
 | 
						node0 := &discover.Node{
 | 
				
			||||||
 | 
							ID:      discover.PubkeyID(&prv0.PublicKey),
 | 
				
			||||||
 | 
							IP:      net.IP{1, 2, 3, 4},
 | 
				
			||||||
 | 
							TCPPort: 33,
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						node1 := &discover.Node{
 | 
				
			||||||
 | 
							ID:      discover.PubkeyID(&prv1.PublicKey),
 | 
				
			||||||
 | 
							IP:      net.IP{5, 6, 7, 8},
 | 
				
			||||||
 | 
							TCPPort: 44,
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						hs0 := &protoHandshake{
 | 
				
			||||||
 | 
							Version: baseProtocolVersion,
 | 
				
			||||||
 | 
							ID:      node0.ID,
 | 
				
			||||||
 | 
							Caps:    []Cap{{"a", 0}, {"b", 2}},
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						hs1 := &protoHandshake{
 | 
				
			||||||
 | 
							Version: baseProtocolVersion,
 | 
				
			||||||
 | 
							ID:      node1.ID,
 | 
				
			||||||
 | 
							Caps:    []Cap{{"c", 1}, {"d", 3}},
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						fd0, fd1 := net.Pipe()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						done := make(chan struct{})
 | 
				
			||||||
 | 
						go func() {
 | 
				
			||||||
 | 
							defer close(done)
 | 
				
			||||||
 | 
							conn0, err := setupConn(fd0, prv0, hs0, node1)
 | 
				
			||||||
 | 
							if err != nil {
 | 
				
			||||||
 | 
								t.Errorf("outbound side error: %v", err)
 | 
				
			||||||
 | 
								return
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							if conn0.ID != node1.ID {
 | 
				
			||||||
 | 
								t.Errorf("outbound conn id mismatch: got %v, want %v", conn0.ID, node1.ID)
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							if !reflect.DeepEqual(conn0.Caps, hs1.Caps) {
 | 
				
			||||||
 | 
								t.Errorf("outbound caps mismatch: got %v, want %v", conn0.Caps, hs1.Caps)
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						conn1, err := setupConn(fd1, prv1, hs1, nil)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							t.Fatalf("inbound side error: %v", err)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if conn1.ID != node0.ID {
 | 
				
			||||||
 | 
							t.Errorf("inbound conn id mismatch: got %v, want %v", conn1.ID, node0.ID)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if !reflect.DeepEqual(conn1.Caps, hs0.Caps) {
 | 
				
			||||||
 | 
							t.Errorf("inbound caps mismatch: got %v, want %v", conn1.Caps, hs0.Caps)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						<-done
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@@ -197,7 +197,7 @@ func (rw *frameRW) ReadMsg() (msg Msg, err error) {
 | 
				
			|||||||
		return msg, err
 | 
							return msg, err
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	if !bytes.HasPrefix(start, magicToken) {
 | 
						if !bytes.HasPrefix(start, magicToken) {
 | 
				
			||||||
		return msg, fmt.Errorf("bad magic token %x", start[:4], magicToken)
 | 
							return msg, fmt.Errorf("bad magic token %x", start[:4])
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	size := binary.BigEndian.Uint32(start[4:])
 | 
						size := binary.BigEndian.Uint32(start[4:])
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -7,9 +7,9 @@ import (
 | 
				
			|||||||
	"strings"
 | 
						"strings"
 | 
				
			||||||
	"time"
 | 
						"time"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	"github.com/fjl/goupnp"
 | 
						"github.com/huin/goupnp"
 | 
				
			||||||
	"github.com/fjl/goupnp/dcps/internetgateway1"
 | 
						"github.com/huin/goupnp/dcps/internetgateway1"
 | 
				
			||||||
	"github.com/fjl/goupnp/dcps/internetgateway2"
 | 
						"github.com/huin/goupnp/dcps/internetgateway2"
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
type upnp struct {
 | 
					type upnp struct {
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										264
									
								
								p2p/peer.go
									
									
									
									
									
								
							
							
						
						
									
										264
									
								
								p2p/peer.go
									
									
									
									
									
								
							@@ -21,6 +21,7 @@ const (
 | 
				
			|||||||
	baseProtocolMaxMsgSize = 10 * 1024 * 1024
 | 
						baseProtocolMaxMsgSize = 10 * 1024 * 1024
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	disconnectGracePeriod = 2 * time.Second
 | 
						disconnectGracePeriod = 2 * time.Second
 | 
				
			||||||
 | 
						pingInterval          = 15 * time.Second
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const (
 | 
					const (
 | 
				
			||||||
@@ -33,37 +34,14 @@ const (
 | 
				
			|||||||
	peersMsg     = 0x05
 | 
						peersMsg     = 0x05
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// handshake is the RLP structure of the protocol handshake.
 | 
					 | 
				
			||||||
type handshake struct {
 | 
					 | 
				
			||||||
	Version    uint64
 | 
					 | 
				
			||||||
	Name       string
 | 
					 | 
				
			||||||
	Caps       []Cap
 | 
					 | 
				
			||||||
	ListenPort uint64
 | 
					 | 
				
			||||||
	NodeID     discover.NodeID
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// Peer represents a connected remote node.
 | 
					// Peer represents a connected remote node.
 | 
				
			||||||
type Peer struct {
 | 
					type Peer struct {
 | 
				
			||||||
	// Peers have all the log methods.
 | 
						// Peers have all the log methods.
 | 
				
			||||||
	// Use them to display messages related to the peer.
 | 
						// Use them to display messages related to the peer.
 | 
				
			||||||
	*logger.Logger
 | 
						*logger.Logger
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	infoMu sync.Mutex
 | 
						rw      *conn
 | 
				
			||||||
	name   string
 | 
						running map[string]*protoRW
 | 
				
			||||||
	caps   []Cap
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	ourID, remoteID *discover.NodeID
 | 
					 | 
				
			||||||
	ourName         string
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	rw *frameRW
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// These fields maintain the running protocols.
 | 
					 | 
				
			||||||
	protocols []Protocol
 | 
					 | 
				
			||||||
	runlock   sync.RWMutex // protects running
 | 
					 | 
				
			||||||
	running   map[string]*proto
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// disables protocol handshake, for testing
 | 
					 | 
				
			||||||
	noHandshake bool
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	protoWG  sync.WaitGroup
 | 
						protoWG  sync.WaitGroup
 | 
				
			||||||
	protoErr chan error
 | 
						protoErr chan error
 | 
				
			||||||
@@ -73,36 +51,27 @@ type Peer struct {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
// NewPeer returns a peer for testing purposes.
 | 
					// NewPeer returns a peer for testing purposes.
 | 
				
			||||||
func NewPeer(id discover.NodeID, name string, caps []Cap) *Peer {
 | 
					func NewPeer(id discover.NodeID, name string, caps []Cap) *Peer {
 | 
				
			||||||
	conn, _ := net.Pipe()
 | 
						pipe, _ := net.Pipe()
 | 
				
			||||||
	peer := newPeer(conn, nil, "", nil, &id)
 | 
						conn := newConn(pipe, &protoHandshake{ID: id, Name: name, Caps: caps})
 | 
				
			||||||
	peer.setHandshakeInfo(name, caps)
 | 
						peer := newPeer(conn, nil)
 | 
				
			||||||
	close(peer.closed) // ensures Disconnect doesn't block
 | 
						close(peer.closed) // ensures Disconnect doesn't block
 | 
				
			||||||
	return peer
 | 
						return peer
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// ID returns the node's public key.
 | 
					// ID returns the node's public key.
 | 
				
			||||||
func (p *Peer) ID() discover.NodeID {
 | 
					func (p *Peer) ID() discover.NodeID {
 | 
				
			||||||
	return *p.remoteID
 | 
						return p.rw.ID
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// Name returns the node name that the remote node advertised.
 | 
					// Name returns the node name that the remote node advertised.
 | 
				
			||||||
func (p *Peer) Name() string {
 | 
					func (p *Peer) Name() string {
 | 
				
			||||||
	// this needs a lock because the information is part of the
 | 
						return p.rw.Name
 | 
				
			||||||
	// protocol handshake.
 | 
					 | 
				
			||||||
	p.infoMu.Lock()
 | 
					 | 
				
			||||||
	name := p.name
 | 
					 | 
				
			||||||
	p.infoMu.Unlock()
 | 
					 | 
				
			||||||
	return name
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// Caps returns the capabilities (supported subprotocols) of the remote peer.
 | 
					// Caps returns the capabilities (supported subprotocols) of the remote peer.
 | 
				
			||||||
func (p *Peer) Caps() []Cap {
 | 
					func (p *Peer) Caps() []Cap {
 | 
				
			||||||
	// this needs a lock because the information is part of the
 | 
						// TODO: maybe return copy
 | 
				
			||||||
	// protocol handshake.
 | 
						return p.rw.Caps
 | 
				
			||||||
	p.infoMu.Lock()
 | 
					 | 
				
			||||||
	caps := p.caps
 | 
					 | 
				
			||||||
	p.infoMu.Unlock()
 | 
					 | 
				
			||||||
	return caps
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// RemoteAddr returns the remote address of the network connection.
 | 
					// RemoteAddr returns the remote address of the network connection.
 | 
				
			||||||
@@ -126,30 +95,20 @@ func (p *Peer) Disconnect(reason DiscReason) {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
// String implements fmt.Stringer.
 | 
					// String implements fmt.Stringer.
 | 
				
			||||||
func (p *Peer) String() string {
 | 
					func (p *Peer) String() string {
 | 
				
			||||||
	return fmt.Sprintf("Peer %.8x %v", p.remoteID[:], p.RemoteAddr())
 | 
						return fmt.Sprintf("Peer %.8x %v", p.rw.ID[:], p.RemoteAddr())
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func newPeer(conn net.Conn, protocols []Protocol, ourName string, ourID, remoteID *discover.NodeID) *Peer {
 | 
					func newPeer(conn *conn, protocols []Protocol) *Peer {
 | 
				
			||||||
	logtag := fmt.Sprintf("Peer %.8x %v", remoteID[:], conn.RemoteAddr())
 | 
						logtag := fmt.Sprintf("Peer %.8x %v", conn.ID[:], conn.RemoteAddr())
 | 
				
			||||||
	return &Peer{
 | 
						p := &Peer{
 | 
				
			||||||
		Logger:    logger.NewLogger(logtag),
 | 
							Logger:   logger.NewLogger(logtag),
 | 
				
			||||||
		rw:        newFrameRW(conn, msgWriteTimeout),
 | 
							rw:       conn,
 | 
				
			||||||
		ourID:     ourID,
 | 
							running:  matchProtocols(protocols, conn.Caps, conn),
 | 
				
			||||||
		ourName:   ourName,
 | 
							disc:     make(chan DiscReason),
 | 
				
			||||||
		remoteID:  remoteID,
 | 
							protoErr: make(chan error),
 | 
				
			||||||
		protocols: protocols,
 | 
							closed:   make(chan struct{}),
 | 
				
			||||||
		running:   make(map[string]*proto),
 | 
					 | 
				
			||||||
		disc:      make(chan DiscReason),
 | 
					 | 
				
			||||||
		protoErr:  make(chan error),
 | 
					 | 
				
			||||||
		closed:    make(chan struct{}),
 | 
					 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
						return p
 | 
				
			||||||
 | 
					 | 
				
			||||||
func (p *Peer) setHandshakeInfo(name string, caps []Cap) {
 | 
					 | 
				
			||||||
	p.infoMu.Lock()
 | 
					 | 
				
			||||||
	p.name = name
 | 
					 | 
				
			||||||
	p.caps = caps
 | 
					 | 
				
			||||||
	p.infoMu.Unlock()
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (p *Peer) run() DiscReason {
 | 
					func (p *Peer) run() DiscReason {
 | 
				
			||||||
@@ -157,29 +116,36 @@ func (p *Peer) run() DiscReason {
 | 
				
			|||||||
	defer p.closeProtocols()
 | 
						defer p.closeProtocols()
 | 
				
			||||||
	defer close(p.closed)
 | 
						defer close(p.closed)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						p.startProtocols()
 | 
				
			||||||
	go func() { readErr <- p.readLoop() }()
 | 
						go func() { readErr <- p.readLoop() }()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if !p.noHandshake {
 | 
						ping := time.NewTicker(pingInterval)
 | 
				
			||||||
		if err := writeProtocolHandshake(p.rw, p.ourName, *p.ourID, p.protocols); err != nil {
 | 
						defer ping.Stop()
 | 
				
			||||||
			p.DebugDetailf("Protocol handshake error: %v\n", err)
 | 
					 | 
				
			||||||
			p.rw.Close()
 | 
					 | 
				
			||||||
			return DiscProtocolError
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// Wait for an error or disconnect.
 | 
						// Wait for an error or disconnect.
 | 
				
			||||||
	var reason DiscReason
 | 
						var reason DiscReason
 | 
				
			||||||
	select {
 | 
					loop:
 | 
				
			||||||
	case err := <-readErr:
 | 
						for {
 | 
				
			||||||
		// We rely on protocols to abort if there is a write error. It
 | 
							select {
 | 
				
			||||||
		// might be more robust to handle them here as well.
 | 
							case <-ping.C:
 | 
				
			||||||
		p.DebugDetailf("Read error: %v\n", err)
 | 
								go func() {
 | 
				
			||||||
		p.rw.Close()
 | 
									if err := EncodeMsg(p.rw, pingMsg, nil); err != nil {
 | 
				
			||||||
		return DiscNetworkError
 | 
										p.protoErr <- err
 | 
				
			||||||
 | 
										return
 | 
				
			||||||
	case err := <-p.protoErr:
 | 
									}
 | 
				
			||||||
		reason = discReasonForError(err)
 | 
								}()
 | 
				
			||||||
	case reason = <-p.disc:
 | 
							case err := <-readErr:
 | 
				
			||||||
 | 
								// We rely on protocols to abort if there is a write error. It
 | 
				
			||||||
 | 
								// might be more robust to handle them here as well.
 | 
				
			||||||
 | 
								p.DebugDetailf("Read error: %v\n", err)
 | 
				
			||||||
 | 
								p.rw.Close()
 | 
				
			||||||
 | 
								return DiscNetworkError
 | 
				
			||||||
 | 
							case err := <-p.protoErr:
 | 
				
			||||||
 | 
								reason = discReasonForError(err)
 | 
				
			||||||
 | 
								break loop
 | 
				
			||||||
 | 
							case reason = <-p.disc:
 | 
				
			||||||
 | 
								break loop
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	p.politeDisconnect(reason)
 | 
						p.politeDisconnect(reason)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -206,11 +172,6 @@ func (p *Peer) politeDisconnect(reason DiscReason) {
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (p *Peer) readLoop() error {
 | 
					func (p *Peer) readLoop() error {
 | 
				
			||||||
	if !p.noHandshake {
 | 
					 | 
				
			||||||
		if err := readProtocolHandshake(p, p.rw); err != nil {
 | 
					 | 
				
			||||||
			return err
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	for {
 | 
						for {
 | 
				
			||||||
		msg, err := p.rw.ReadMsg()
 | 
							msg, err := p.rw.ReadMsg()
 | 
				
			||||||
		if err != nil {
 | 
							if err != nil {
 | 
				
			||||||
@@ -249,105 +210,51 @@ func (p *Peer) handle(msg Msg) error {
 | 
				
			|||||||
	return nil
 | 
						return nil
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func readProtocolHandshake(p *Peer, rw MsgReadWriter) error {
 | 
					// matchProtocols creates structures for matching named subprotocols.
 | 
				
			||||||
	// read and handle remote handshake
 | 
					func matchProtocols(protocols []Protocol, caps []Cap, rw MsgReadWriter) map[string]*protoRW {
 | 
				
			||||||
	msg, err := rw.ReadMsg()
 | 
					 | 
				
			||||||
	if err != nil {
 | 
					 | 
				
			||||||
		return err
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	if msg.Code == discMsg {
 | 
					 | 
				
			||||||
		// disconnect before protocol handshake is valid according to the
 | 
					 | 
				
			||||||
		// spec and we send it ourself if Server.addPeer fails.
 | 
					 | 
				
			||||||
		var reason DiscReason
 | 
					 | 
				
			||||||
		rlp.Decode(msg.Payload, &reason)
 | 
					 | 
				
			||||||
		return discRequestedError(reason)
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	if msg.Code != handshakeMsg {
 | 
					 | 
				
			||||||
		return newPeerError(errProtocolBreach, "expected handshake, got %x", msg.Code)
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	if msg.Size > baseProtocolMaxMsgSize {
 | 
					 | 
				
			||||||
		return newPeerError(errInvalidMsg, "message too big")
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	var hs handshake
 | 
					 | 
				
			||||||
	if err := msg.Decode(&hs); err != nil {
 | 
					 | 
				
			||||||
		return err
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	// validate handshake info
 | 
					 | 
				
			||||||
	if hs.Version != baseProtocolVersion {
 | 
					 | 
				
			||||||
		return newPeerError(errP2PVersionMismatch, "required version %d, received %d\n",
 | 
					 | 
				
			||||||
			baseProtocolVersion, hs.Version)
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	if hs.NodeID == *p.remoteID {
 | 
					 | 
				
			||||||
		return newPeerError(errPubkeyForbidden, "node ID mismatch")
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	// TODO: remove Caps with empty name
 | 
					 | 
				
			||||||
	p.setHandshakeInfo(hs.Name, hs.Caps)
 | 
					 | 
				
			||||||
	p.startSubprotocols(hs.Caps)
 | 
					 | 
				
			||||||
	return nil
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func writeProtocolHandshake(w MsgWriter, name string, id discover.NodeID, ps []Protocol) error {
 | 
					 | 
				
			||||||
	var caps []interface{}
 | 
					 | 
				
			||||||
	for _, proto := range ps {
 | 
					 | 
				
			||||||
		caps = append(caps, proto.cap())
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	return EncodeMsg(w, handshakeMsg, baseProtocolVersion, name, caps, 0, id)
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// startProtocols starts matching named subprotocols.
 | 
					 | 
				
			||||||
func (p *Peer) startSubprotocols(caps []Cap) {
 | 
					 | 
				
			||||||
	sort.Sort(capsByName(caps))
 | 
						sort.Sort(capsByName(caps))
 | 
				
			||||||
	p.runlock.Lock()
 | 
					 | 
				
			||||||
	defer p.runlock.Unlock()
 | 
					 | 
				
			||||||
	offset := baseProtocolLength
 | 
						offset := baseProtocolLength
 | 
				
			||||||
 | 
						result := make(map[string]*protoRW)
 | 
				
			||||||
outer:
 | 
					outer:
 | 
				
			||||||
	for _, cap := range caps {
 | 
						for _, cap := range caps {
 | 
				
			||||||
		for _, proto := range p.protocols {
 | 
							for _, proto := range protocols {
 | 
				
			||||||
			if proto.Name == cap.Name &&
 | 
								if proto.Name == cap.Name && proto.Version == cap.Version && result[cap.Name] == nil {
 | 
				
			||||||
				proto.Version == cap.Version &&
 | 
									result[cap.Name] = &protoRW{Protocol: proto, offset: offset, in: make(chan Msg), w: rw}
 | 
				
			||||||
				p.running[cap.Name] == nil {
 | 
					 | 
				
			||||||
				p.running[cap.Name] = p.startProto(offset, proto)
 | 
					 | 
				
			||||||
				offset += proto.Length
 | 
									offset += proto.Length
 | 
				
			||||||
				continue outer
 | 
									continue outer
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
						return result
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (p *Peer) startProto(offset uint64, impl Protocol) *proto {
 | 
					func (p *Peer) startProtocols() {
 | 
				
			||||||
	p.DebugDetailf("Starting protocol %s/%d\n", impl.Name, impl.Version)
 | 
						for _, proto := range p.running {
 | 
				
			||||||
	rw := &proto{
 | 
							proto := proto
 | 
				
			||||||
		name:    impl.Name,
 | 
							p.DebugDetailf("Starting protocol %s/%d\n", proto.Name, proto.Version)
 | 
				
			||||||
		in:      make(chan Msg),
 | 
							p.protoWG.Add(1)
 | 
				
			||||||
		offset:  offset,
 | 
							go func() {
 | 
				
			||||||
		maxcode: impl.Length,
 | 
								err := proto.Run(p, proto)
 | 
				
			||||||
		w:       p.rw,
 | 
								if err == nil {
 | 
				
			||||||
 | 
									p.DebugDetailf("Protocol %s/%d returned\n", proto.Name, proto.Version)
 | 
				
			||||||
 | 
									err = errors.New("protocol returned")
 | 
				
			||||||
 | 
								} else {
 | 
				
			||||||
 | 
									p.DebugDetailf("Protocol %s/%d error: %v\n", proto.Name, proto.Version, err)
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								select {
 | 
				
			||||||
 | 
								case p.protoErr <- err:
 | 
				
			||||||
 | 
								case <-p.closed:
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								p.protoWG.Done()
 | 
				
			||||||
 | 
							}()
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	p.protoWG.Add(1)
 | 
					 | 
				
			||||||
	go func() {
 | 
					 | 
				
			||||||
		err := impl.Run(p, rw)
 | 
					 | 
				
			||||||
		if err == nil {
 | 
					 | 
				
			||||||
			p.DebugDetailf("Protocol %s/%d returned\n", impl.Name, impl.Version)
 | 
					 | 
				
			||||||
			err = errors.New("protocol returned")
 | 
					 | 
				
			||||||
		} else {
 | 
					 | 
				
			||||||
			p.DebugDetailf("Protocol %s/%d error: %v\n", impl.Name, impl.Version, err)
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		select {
 | 
					 | 
				
			||||||
		case p.protoErr <- err:
 | 
					 | 
				
			||||||
		case <-p.closed:
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		p.protoWG.Done()
 | 
					 | 
				
			||||||
	}()
 | 
					 | 
				
			||||||
	return rw
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// getProto finds the protocol responsible for handling
 | 
					// getProto finds the protocol responsible for handling
 | 
				
			||||||
// the given message code.
 | 
					// the given message code.
 | 
				
			||||||
func (p *Peer) getProto(code uint64) (*proto, error) {
 | 
					func (p *Peer) getProto(code uint64) (*protoRW, error) {
 | 
				
			||||||
	p.runlock.RLock()
 | 
					 | 
				
			||||||
	defer p.runlock.RUnlock()
 | 
					 | 
				
			||||||
	for _, proto := range p.running {
 | 
						for _, proto := range p.running {
 | 
				
			||||||
		if code >= proto.offset && code < proto.offset+proto.maxcode {
 | 
							if code >= proto.offset && code < proto.offset+proto.Length {
 | 
				
			||||||
			return proto, nil
 | 
								return proto, nil
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
@@ -355,46 +262,43 @@ func (p *Peer) getProto(code uint64) (*proto, error) {
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (p *Peer) closeProtocols() {
 | 
					func (p *Peer) closeProtocols() {
 | 
				
			||||||
	p.runlock.RLock()
 | 
					 | 
				
			||||||
	for _, p := range p.running {
 | 
						for _, p := range p.running {
 | 
				
			||||||
		close(p.in)
 | 
							close(p.in)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	p.runlock.RUnlock()
 | 
					 | 
				
			||||||
	p.protoWG.Wait()
 | 
						p.protoWG.Wait()
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// writeProtoMsg sends the given message on behalf of the given named protocol.
 | 
					// writeProtoMsg sends the given message on behalf of the given named protocol.
 | 
				
			||||||
// this exists because of Server.Broadcast.
 | 
					// this exists because of Server.Broadcast.
 | 
				
			||||||
func (p *Peer) writeProtoMsg(protoName string, msg Msg) error {
 | 
					func (p *Peer) writeProtoMsg(protoName string, msg Msg) error {
 | 
				
			||||||
	p.runlock.RLock()
 | 
					 | 
				
			||||||
	proto, ok := p.running[protoName]
 | 
						proto, ok := p.running[protoName]
 | 
				
			||||||
	p.runlock.RUnlock()
 | 
					 | 
				
			||||||
	if !ok {
 | 
						if !ok {
 | 
				
			||||||
		return fmt.Errorf("protocol %s not handled by peer", protoName)
 | 
							return fmt.Errorf("protocol %s not handled by peer", protoName)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	if msg.Code >= proto.maxcode {
 | 
						if msg.Code >= proto.Length {
 | 
				
			||||||
		return newPeerError(errInvalidMsgCode, "code %x is out of range for protocol %q", msg.Code, protoName)
 | 
							return newPeerError(errInvalidMsgCode, "code %x is out of range for protocol %q", msg.Code, protoName)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	msg.Code += proto.offset
 | 
						msg.Code += proto.offset
 | 
				
			||||||
	return p.rw.WriteMsg(msg)
 | 
						return p.rw.WriteMsg(msg)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
type proto struct {
 | 
					type protoRW struct {
 | 
				
			||||||
	name            string
 | 
						Protocol
 | 
				
			||||||
	in              chan Msg
 | 
					
 | 
				
			||||||
	maxcode, offset uint64
 | 
						in     chan Msg
 | 
				
			||||||
	w               MsgWriter
 | 
						offset uint64
 | 
				
			||||||
 | 
						w      MsgWriter
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (rw *proto) WriteMsg(msg Msg) error {
 | 
					func (rw *protoRW) WriteMsg(msg Msg) error {
 | 
				
			||||||
	if msg.Code >= rw.maxcode {
 | 
						if msg.Code >= rw.Length {
 | 
				
			||||||
		return newPeerError(errInvalidMsgCode, "not handled")
 | 
							return newPeerError(errInvalidMsgCode, "not handled")
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	msg.Code += rw.offset
 | 
						msg.Code += rw.offset
 | 
				
			||||||
	return rw.w.WriteMsg(msg)
 | 
						return rw.w.WriteMsg(msg)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (rw *proto) ReadMsg() (Msg, error) {
 | 
					func (rw *protoRW) ReadMsg() (Msg, error) {
 | 
				
			||||||
	msg, ok := <-rw.in
 | 
						msg, ok := <-rw.in
 | 
				
			||||||
	if !ok {
 | 
						if !ok {
 | 
				
			||||||
		return msg, io.EOF
 | 
							return msg, io.EOF
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										105
									
								
								p2p/peer_test.go
									
									
									
									
									
								
							
							
						
						
									
										105
									
								
								p2p/peer_test.go
									
									
									
									
									
								
							@@ -6,11 +6,9 @@ import (
 | 
				
			|||||||
	"io/ioutil"
 | 
						"io/ioutil"
 | 
				
			||||||
	"net"
 | 
						"net"
 | 
				
			||||||
	"reflect"
 | 
						"reflect"
 | 
				
			||||||
	"sort"
 | 
					 | 
				
			||||||
	"testing"
 | 
						"testing"
 | 
				
			||||||
	"time"
 | 
						"time"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	"github.com/ethereum/go-ethereum/p2p/discover"
 | 
					 | 
				
			||||||
	"github.com/ethereum/go-ethereum/rlp"
 | 
						"github.com/ethereum/go-ethereum/rlp"
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -23,6 +21,7 @@ var discard = Protocol{
 | 
				
			|||||||
			if err != nil {
 | 
								if err != nil {
 | 
				
			||||||
				return err
 | 
									return err
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
 | 
								fmt.Printf("discarding %d\n", msg.Code)
 | 
				
			||||||
			if err = msg.Discard(); err != nil {
 | 
								if err = msg.Discard(); err != nil {
 | 
				
			||||||
				return err
 | 
									return err
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
@@ -30,13 +29,20 @@ var discard = Protocol{
 | 
				
			|||||||
	},
 | 
						},
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func testPeer(noHandshake bool, protos []Protocol) (*frameRW, *Peer, <-chan DiscReason) {
 | 
					func testPeer(protos []Protocol) (*conn, *Peer, <-chan DiscReason) {
 | 
				
			||||||
	conn1, conn2 := net.Pipe()
 | 
						fd1, fd2 := net.Pipe()
 | 
				
			||||||
	peer := newPeer(conn1, protos, "name", &discover.NodeID{}, &discover.NodeID{})
 | 
						hs1 := &protoHandshake{ID: randomID(), Version: baseProtocolVersion}
 | 
				
			||||||
	peer.noHandshake = noHandshake
 | 
						hs2 := &protoHandshake{ID: randomID(), Version: baseProtocolVersion}
 | 
				
			||||||
 | 
						for _, p := range protos {
 | 
				
			||||||
 | 
							hs1.Caps = append(hs1.Caps, p.cap())
 | 
				
			||||||
 | 
							hs2.Caps = append(hs2.Caps, p.cap())
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						peer := newPeer(newConn(fd1, hs1), protos)
 | 
				
			||||||
	errc := make(chan DiscReason, 1)
 | 
						errc := make(chan DiscReason, 1)
 | 
				
			||||||
	go func() { errc <- peer.run() }()
 | 
						go func() { errc <- peer.run() }()
 | 
				
			||||||
	return newFrameRW(conn2, msgWriteTimeout), peer, errc
 | 
					
 | 
				
			||||||
 | 
						return newConn(fd2, hs2), peer, errc
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func TestPeerProtoReadMsg(t *testing.T) {
 | 
					func TestPeerProtoReadMsg(t *testing.T) {
 | 
				
			||||||
@@ -61,9 +67,8 @@ func TestPeerProtoReadMsg(t *testing.T) {
 | 
				
			|||||||
		},
 | 
							},
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	rw, peer, errc := testPeer(true, []Protocol{proto})
 | 
						rw, _, errc := testPeer([]Protocol{proto})
 | 
				
			||||||
	defer rw.Close()
 | 
						defer rw.Close()
 | 
				
			||||||
	peer.startSubprotocols([]Cap{proto.cap()})
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	EncodeMsg(rw, baseProtocolLength+2, 1)
 | 
						EncodeMsg(rw, baseProtocolLength+2, 1)
 | 
				
			||||||
	EncodeMsg(rw, baseProtocolLength+3, 2)
 | 
						EncodeMsg(rw, baseProtocolLength+3, 2)
 | 
				
			||||||
@@ -100,9 +105,8 @@ func TestPeerProtoReadLargeMsg(t *testing.T) {
 | 
				
			|||||||
		},
 | 
							},
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	rw, peer, errc := testPeer(true, []Protocol{proto})
 | 
						rw, _, errc := testPeer([]Protocol{proto})
 | 
				
			||||||
	defer rw.Close()
 | 
						defer rw.Close()
 | 
				
			||||||
	peer.startSubprotocols([]Cap{proto.cap()})
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	EncodeMsg(rw, 18, make([]byte, msgsize))
 | 
						EncodeMsg(rw, 18, make([]byte, msgsize))
 | 
				
			||||||
	select {
 | 
						select {
 | 
				
			||||||
@@ -130,9 +134,8 @@ func TestPeerProtoEncodeMsg(t *testing.T) {
 | 
				
			|||||||
			return nil
 | 
								return nil
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	rw, peer, _ := testPeer(true, []Protocol{proto})
 | 
						rw, _, _ := testPeer([]Protocol{proto})
 | 
				
			||||||
	defer rw.Close()
 | 
						defer rw.Close()
 | 
				
			||||||
	peer.startSubprotocols([]Cap{proto.cap()})
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if err := expectMsg(rw, 17, []string{"foo", "bar"}); err != nil {
 | 
						if err := expectMsg(rw, 17, []string{"foo", "bar"}); err != nil {
 | 
				
			||||||
		t.Error(err)
 | 
							t.Error(err)
 | 
				
			||||||
@@ -142,9 +145,8 @@ func TestPeerProtoEncodeMsg(t *testing.T) {
 | 
				
			|||||||
func TestPeerWriteForBroadcast(t *testing.T) {
 | 
					func TestPeerWriteForBroadcast(t *testing.T) {
 | 
				
			||||||
	defer testlog(t).detach()
 | 
						defer testlog(t).detach()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	rw, peer, peerErr := testPeer(true, []Protocol{discard})
 | 
						rw, peer, peerErr := testPeer([]Protocol{discard})
 | 
				
			||||||
	defer rw.Close()
 | 
						defer rw.Close()
 | 
				
			||||||
	peer.startSubprotocols([]Cap{discard.cap()})
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// test write errors
 | 
						// test write errors
 | 
				
			||||||
	if err := peer.writeProtoMsg("b", NewMsg(3)); err == nil {
 | 
						if err := peer.writeProtoMsg("b", NewMsg(3)); err == nil {
 | 
				
			||||||
@@ -160,7 +162,7 @@ func TestPeerWriteForBroadcast(t *testing.T) {
 | 
				
			|||||||
	read := make(chan struct{})
 | 
						read := make(chan struct{})
 | 
				
			||||||
	go func() {
 | 
						go func() {
 | 
				
			||||||
		if err := expectMsg(rw, 16, nil); err != nil {
 | 
							if err := expectMsg(rw, 16, nil); err != nil {
 | 
				
			||||||
			t.Error()
 | 
								t.Error(err)
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		close(read)
 | 
							close(read)
 | 
				
			||||||
	}()
 | 
						}()
 | 
				
			||||||
@@ -179,7 +181,7 @@ func TestPeerWriteForBroadcast(t *testing.T) {
 | 
				
			|||||||
func TestPeerPing(t *testing.T) {
 | 
					func TestPeerPing(t *testing.T) {
 | 
				
			||||||
	defer testlog(t).detach()
 | 
						defer testlog(t).detach()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	rw, _, _ := testPeer(true, nil)
 | 
						rw, _, _ := testPeer(nil)
 | 
				
			||||||
	defer rw.Close()
 | 
						defer rw.Close()
 | 
				
			||||||
	if err := EncodeMsg(rw, pingMsg); err != nil {
 | 
						if err := EncodeMsg(rw, pingMsg); err != nil {
 | 
				
			||||||
		t.Fatal(err)
 | 
							t.Fatal(err)
 | 
				
			||||||
@@ -192,7 +194,7 @@ func TestPeerPing(t *testing.T) {
 | 
				
			|||||||
func TestPeerDisconnect(t *testing.T) {
 | 
					func TestPeerDisconnect(t *testing.T) {
 | 
				
			||||||
	defer testlog(t).detach()
 | 
						defer testlog(t).detach()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	rw, _, disc := testPeer(true, nil)
 | 
						rw, _, disc := testPeer(nil)
 | 
				
			||||||
	defer rw.Close()
 | 
						defer rw.Close()
 | 
				
			||||||
	if err := EncodeMsg(rw, discMsg, DiscQuitting); err != nil {
 | 
						if err := EncodeMsg(rw, discMsg, DiscQuitting); err != nil {
 | 
				
			||||||
		t.Fatal(err)
 | 
							t.Fatal(err)
 | 
				
			||||||
@@ -206,73 +208,6 @@ func TestPeerDisconnect(t *testing.T) {
 | 
				
			|||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func TestPeerHandshake(t *testing.T) {
 | 
					 | 
				
			||||||
	defer testlog(t).detach()
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// remote has two matching protocols: a and c
 | 
					 | 
				
			||||||
	remote := NewPeer(randomID(), "", []Cap{{"a", 1}, {"b", 999}, {"c", 3}})
 | 
					 | 
				
			||||||
	remoteID := randomID()
 | 
					 | 
				
			||||||
	remote.ourID = &remoteID
 | 
					 | 
				
			||||||
	remote.ourName = "remote peer"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	start := make(chan string)
 | 
					 | 
				
			||||||
	stop := make(chan struct{})
 | 
					 | 
				
			||||||
	run := func(p *Peer, rw MsgReadWriter) error {
 | 
					 | 
				
			||||||
		name := rw.(*proto).name
 | 
					 | 
				
			||||||
		if name != "a" && name != "c" {
 | 
					 | 
				
			||||||
			t.Errorf("protocol %q should not be started", name)
 | 
					 | 
				
			||||||
		} else {
 | 
					 | 
				
			||||||
			start <- name
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		<-stop
 | 
					 | 
				
			||||||
		return nil
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	protocols := []Protocol{
 | 
					 | 
				
			||||||
		{Name: "a", Version: 1, Length: 1, Run: run},
 | 
					 | 
				
			||||||
		{Name: "b", Version: 2, Length: 1, Run: run},
 | 
					 | 
				
			||||||
		{Name: "c", Version: 3, Length: 1, Run: run},
 | 
					 | 
				
			||||||
		{Name: "d", Version: 4, Length: 1, Run: run},
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	rw, p, disc := testPeer(false, protocols)
 | 
					 | 
				
			||||||
	p.remoteID = remote.ourID
 | 
					 | 
				
			||||||
	defer rw.Close()
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// run the handshake
 | 
					 | 
				
			||||||
	remoteProtocols := []Protocol{protocols[0], protocols[2]}
 | 
					 | 
				
			||||||
	if err := writeProtocolHandshake(rw, "remote peer", remoteID, remoteProtocols); err != nil {
 | 
					 | 
				
			||||||
		t.Fatalf("handshake write error: %v", err)
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	if err := readProtocolHandshake(remote, rw); err != nil {
 | 
					 | 
				
			||||||
		t.Fatalf("handshake read error: %v", err)
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// check that all protocols have been started
 | 
					 | 
				
			||||||
	var started []string
 | 
					 | 
				
			||||||
	for i := 0; i < 2; i++ {
 | 
					 | 
				
			||||||
		select {
 | 
					 | 
				
			||||||
		case name := <-start:
 | 
					 | 
				
			||||||
			started = append(started, name)
 | 
					 | 
				
			||||||
		case <-time.After(100 * time.Millisecond):
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	sort.Strings(started)
 | 
					 | 
				
			||||||
	if !reflect.DeepEqual(started, []string{"a", "c"}) {
 | 
					 | 
				
			||||||
		t.Errorf("wrong protocols started: %v", started)
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// check that metadata has been set
 | 
					 | 
				
			||||||
	if p.ID() != remoteID {
 | 
					 | 
				
			||||||
		t.Errorf("peer has wrong node ID: got %v, want %v", p.ID(), remoteID)
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	if p.Name() != remote.ourName {
 | 
					 | 
				
			||||||
		t.Errorf("peer has wrong node name: got %q, want %q", p.Name(), remote.ourName)
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	close(stop)
 | 
					 | 
				
			||||||
	expectMsg(rw, discMsg, nil)
 | 
					 | 
				
			||||||
	t.Logf("disc reason: %v", <-disc)
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func TestNewPeer(t *testing.T) {
 | 
					func TestNewPeer(t *testing.T) {
 | 
				
			||||||
	name := "nodename"
 | 
						name := "nodename"
 | 
				
			||||||
	caps := []Cap{{"foo", 2}, {"bar", 3}}
 | 
						caps := []Cap{{"foo", 2}, {"bar", 3}}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -5,7 +5,6 @@ import (
 | 
				
			|||||||
	"crypto/ecdsa"
 | 
						"crypto/ecdsa"
 | 
				
			||||||
	"errors"
 | 
						"errors"
 | 
				
			||||||
	"fmt"
 | 
						"fmt"
 | 
				
			||||||
	"io"
 | 
					 | 
				
			||||||
	"net"
 | 
						"net"
 | 
				
			||||||
	"runtime"
 | 
						"runtime"
 | 
				
			||||||
	"sync"
 | 
						"sync"
 | 
				
			||||||
@@ -23,6 +22,7 @@ const (
 | 
				
			|||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
var srvlog = logger.NewLogger("P2P Server")
 | 
					var srvlog = logger.NewLogger("P2P Server")
 | 
				
			||||||
 | 
					var srvjslog = logger.NewJsonLogger()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// MakeName creates a node name that follows the ethereum convention
 | 
					// MakeName creates a node name that follows the ethereum convention
 | 
				
			||||||
// for such names. It adds the operation system name and Go runtime version
 | 
					// for such names. It adds the operation system name and Go runtime version
 | 
				
			||||||
@@ -83,9 +83,11 @@ type Server struct {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
	// Hooks for testing. These are useful because we can inhibit
 | 
						// Hooks for testing. These are useful because we can inhibit
 | 
				
			||||||
	// the whole protocol stack.
 | 
						// the whole protocol stack.
 | 
				
			||||||
	handshakeFunc
 | 
						setupFunc
 | 
				
			||||||
	newPeerHook
 | 
						newPeerHook
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						ourHandshake *protoHandshake
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	lock     sync.RWMutex
 | 
						lock     sync.RWMutex
 | 
				
			||||||
	running  bool
 | 
						running  bool
 | 
				
			||||||
	listener net.Listener
 | 
						listener net.Listener
 | 
				
			||||||
@@ -99,7 +101,7 @@ type Server struct {
 | 
				
			|||||||
	peerConnect chan *discover.Node
 | 
						peerConnect chan *discover.Node
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
type handshakeFunc func(io.ReadWriter, *ecdsa.PrivateKey, *discover.Node) (discover.NodeID, []byte, error)
 | 
					type setupFunc func(net.Conn, *ecdsa.PrivateKey, *protoHandshake, *discover.Node) (*conn, error)
 | 
				
			||||||
type newPeerHook func(*Peer)
 | 
					type newPeerHook func(*Peer)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// Peers returns all connected peers.
 | 
					// Peers returns all connected peers.
 | 
				
			||||||
@@ -159,7 +161,7 @@ func (srv *Server) Start() (err error) {
 | 
				
			|||||||
	}
 | 
						}
 | 
				
			||||||
	srvlog.Infoln("Starting Server")
 | 
						srvlog.Infoln("Starting Server")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// initialize all the fields
 | 
						// static fields
 | 
				
			||||||
	if srv.PrivateKey == nil {
 | 
						if srv.PrivateKey == nil {
 | 
				
			||||||
		return fmt.Errorf("Server.PrivateKey must be set to a non-nil key")
 | 
							return fmt.Errorf("Server.PrivateKey must be set to a non-nil key")
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
@@ -169,25 +171,32 @@ func (srv *Server) Start() (err error) {
 | 
				
			|||||||
	srv.quit = make(chan struct{})
 | 
						srv.quit = make(chan struct{})
 | 
				
			||||||
	srv.peers = make(map[discover.NodeID]*Peer)
 | 
						srv.peers = make(map[discover.NodeID]*Peer)
 | 
				
			||||||
	srv.peerConnect = make(chan *discover.Node)
 | 
						srv.peerConnect = make(chan *discover.Node)
 | 
				
			||||||
 | 
						if srv.setupFunc == nil {
 | 
				
			||||||
	if srv.handshakeFunc == nil {
 | 
							srv.setupFunc = setupConn
 | 
				
			||||||
		srv.handshakeFunc = encHandshake
 | 
					 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	if srv.Blacklist == nil {
 | 
						if srv.Blacklist == nil {
 | 
				
			||||||
		srv.Blacklist = NewBlacklist()
 | 
							srv.Blacklist = NewBlacklist()
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// node table
 | 
				
			||||||
 | 
						ntab, err := discover.ListenUDP(srv.PrivateKey, srv.ListenAddr, srv.NAT)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							return err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						srv.ntab = ntab
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// handshake
 | 
				
			||||||
 | 
						srv.ourHandshake = &protoHandshake{Version: baseProtocolVersion, Name: srv.Name, ID: ntab.Self()}
 | 
				
			||||||
 | 
						for _, p := range srv.Protocols {
 | 
				
			||||||
 | 
							srv.ourHandshake.Caps = append(srv.ourHandshake.Caps, p.cap())
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// listen/dial
 | 
				
			||||||
	if srv.ListenAddr != "" {
 | 
						if srv.ListenAddr != "" {
 | 
				
			||||||
		if err := srv.startListening(); err != nil {
 | 
							if err := srv.startListening(); err != nil {
 | 
				
			||||||
			return err
 | 
								return err
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					 | 
				
			||||||
	// dial stuff
 | 
					 | 
				
			||||||
	dt, err := discover.ListenUDP(srv.PrivateKey, srv.ListenAddr, srv.NAT)
 | 
					 | 
				
			||||||
	if err != nil {
 | 
					 | 
				
			||||||
		return err
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	srv.ntab = dt
 | 
					 | 
				
			||||||
	if srv.Dialer == nil {
 | 
						if srv.Dialer == nil {
 | 
				
			||||||
		srv.Dialer = &net.Dialer{Timeout: defaultDialTimeout}
 | 
							srv.Dialer = &net.Dialer{Timeout: defaultDialTimeout}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
@@ -347,30 +356,41 @@ func (srv *Server) findPeers() {
 | 
				
			|||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (srv *Server) startPeer(conn net.Conn, dest *discover.Node) {
 | 
					func (srv *Server) startPeer(fd net.Conn, dest *discover.Node) {
 | 
				
			||||||
	// TODO: handle/store session token
 | 
						// TODO: handle/store session token
 | 
				
			||||||
	conn.SetDeadline(time.Now().Add(handshakeTimeout))
 | 
						fd.SetDeadline(time.Now().Add(handshakeTimeout))
 | 
				
			||||||
	remoteID, _, err := srv.handshakeFunc(conn, srv.PrivateKey, dest)
 | 
						conn, err := srv.setupFunc(fd, srv.PrivateKey, srv.ourHandshake, dest)
 | 
				
			||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
		conn.Close()
 | 
							fd.Close()
 | 
				
			||||||
		srvlog.Debugf("Encryption Handshake with %v failed: %v", conn.RemoteAddr(), err)
 | 
							srvlog.Debugf("Handshake with %v failed: %v", fd.RemoteAddr(), err)
 | 
				
			||||||
		return
 | 
							return
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	ourID := srv.ntab.Self()
 | 
						p := newPeer(conn, srv.Protocols)
 | 
				
			||||||
	p := newPeer(conn, srv.Protocols, srv.Name, &ourID, &remoteID)
 | 
						if ok, reason := srv.addPeer(conn.ID, p); !ok {
 | 
				
			||||||
	if ok, reason := srv.addPeer(remoteID, p); !ok {
 | 
					 | 
				
			||||||
		srvlog.DebugDetailf("Not adding %v (%v)\n", p, reason)
 | 
							srvlog.DebugDetailf("Not adding %v (%v)\n", p, reason)
 | 
				
			||||||
		p.politeDisconnect(reason)
 | 
							p.politeDisconnect(reason)
 | 
				
			||||||
		return
 | 
							return
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	srvlog.Debugf("Added %v\n", p)
 | 
						srvlog.Debugf("Added %v\n", p)
 | 
				
			||||||
 | 
						srvjslog.LogJson(&logger.P2PConnected{
 | 
				
			||||||
 | 
							RemoteId:            fmt.Sprintf("%x", conn.ID[:]),
 | 
				
			||||||
 | 
							RemoteAddress:       conn.RemoteAddr().String(),
 | 
				
			||||||
 | 
							RemoteVersionString: conn.Name,
 | 
				
			||||||
 | 
							NumConnections:      srv.PeerCount(),
 | 
				
			||||||
 | 
						})
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if srv.newPeerHook != nil {
 | 
						if srv.newPeerHook != nil {
 | 
				
			||||||
		srv.newPeerHook(p)
 | 
							srv.newPeerHook(p)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	discreason := p.run()
 | 
						discreason := p.run()
 | 
				
			||||||
	srv.removePeer(p)
 | 
						srv.removePeer(p)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	srvlog.Debugf("Removed %v (%v)\n", p, discreason)
 | 
						srvlog.Debugf("Removed %v (%v)\n", p, discreason)
 | 
				
			||||||
 | 
						srvjslog.LogJson(&logger.P2PDisconnected{
 | 
				
			||||||
 | 
							RemoteId:       fmt.Sprintf("%x", conn.ID[:]),
 | 
				
			||||||
 | 
							NumConnections: srv.PeerCount(),
 | 
				
			||||||
 | 
						})
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (srv *Server) addPeer(id discover.NodeID, p *Peer) (bool, DiscReason) {
 | 
					func (srv *Server) addPeer(id discover.NodeID, p *Peer) (bool, DiscReason) {
 | 
				
			||||||
@@ -394,7 +414,7 @@ func (srv *Server) addPeer(id discover.NodeID, p *Peer) (bool, DiscReason) {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
func (srv *Server) removePeer(p *Peer) {
 | 
					func (srv *Server) removePeer(p *Peer) {
 | 
				
			||||||
	srv.lock.Lock()
 | 
						srv.lock.Lock()
 | 
				
			||||||
	delete(srv.peers, *p.remoteID)
 | 
						delete(srv.peers, p.ID())
 | 
				
			||||||
	srv.lock.Unlock()
 | 
						srv.lock.Unlock()
 | 
				
			||||||
	srv.peerWG.Done()
 | 
						srv.peerWG.Done()
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -21,8 +21,12 @@ func startTestServer(t *testing.T, pf newPeerHook) *Server {
 | 
				
			|||||||
		ListenAddr:  "127.0.0.1:0",
 | 
							ListenAddr:  "127.0.0.1:0",
 | 
				
			||||||
		PrivateKey:  newkey(),
 | 
							PrivateKey:  newkey(),
 | 
				
			||||||
		newPeerHook: pf,
 | 
							newPeerHook: pf,
 | 
				
			||||||
		handshakeFunc: func(io.ReadWriter, *ecdsa.PrivateKey, *discover.Node) (id discover.NodeID, st []byte, err error) {
 | 
							setupFunc: func(fd net.Conn, prv *ecdsa.PrivateKey, our *protoHandshake, dial *discover.Node) (*conn, error) {
 | 
				
			||||||
			return randomID(), nil, err
 | 
								id := randomID()
 | 
				
			||||||
 | 
								return &conn{
 | 
				
			||||||
 | 
									frameRW:        newFrameRW(fd, msgWriteTimeout),
 | 
				
			||||||
 | 
									protoHandshake: &protoHandshake{ID: id, Version: baseProtocolVersion},
 | 
				
			||||||
 | 
								}, nil
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	if err := server.Start(); err != nil {
 | 
						if err := server.Start(); err != nil {
 | 
				
			||||||
@@ -116,9 +120,7 @@ func TestServerBroadcast(t *testing.T) {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
	var connected sync.WaitGroup
 | 
						var connected sync.WaitGroup
 | 
				
			||||||
	srv := startTestServer(t, func(p *Peer) {
 | 
						srv := startTestServer(t, func(p *Peer) {
 | 
				
			||||||
		p.protocols = []Protocol{discard}
 | 
							p.running = matchProtocols([]Protocol{discard}, []Cap{discard.cap()}, p.rw)
 | 
				
			||||||
		p.startSubprotocols([]Cap{discard.cap()})
 | 
					 | 
				
			||||||
		p.noHandshake = true
 | 
					 | 
				
			||||||
		connected.Done()
 | 
							connected.Done()
 | 
				
			||||||
	})
 | 
						})
 | 
				
			||||||
	defer srv.Stop()
 | 
						defer srv.Stop()
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										49
									
								
								rpc/args.go
									
									
									
									
									
								
							
							
						
						
									
										49
									
								
								rpc/args.go
									
									
									
									
									
								
							@@ -1,6 +1,7 @@
 | 
				
			|||||||
package rpc
 | 
					package rpc
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import "encoding/json"
 | 
					import "encoding/json"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import "github.com/ethereum/go-ethereum/core"
 | 
					import "github.com/ethereum/go-ethereum/core"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
type GetBlockArgs struct {
 | 
					type GetBlockArgs struct {
 | 
				
			||||||
@@ -37,6 +38,35 @@ type NewTxArgs struct {
 | 
				
			|||||||
	Data     string `json:"data"`
 | 
						Data     string `json:"data"`
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (obj *NewTxArgs) UnmarshalJSON(b []byte) (err error) {
 | 
				
			||||||
 | 
						// Data can be either specified as "data" or "code" :-/
 | 
				
			||||||
 | 
						var ext struct {
 | 
				
			||||||
 | 
							From     string
 | 
				
			||||||
 | 
							To       string
 | 
				
			||||||
 | 
							Value    string
 | 
				
			||||||
 | 
							Gas      string
 | 
				
			||||||
 | 
							GasPrice string
 | 
				
			||||||
 | 
							Data     string
 | 
				
			||||||
 | 
							Code     string
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if err = json.Unmarshal(b, &ext); err == nil {
 | 
				
			||||||
 | 
							if len(ext.Data) == 0 {
 | 
				
			||||||
 | 
								ext.Data = ext.Code
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							obj.From = ext.From
 | 
				
			||||||
 | 
							obj.To = ext.To
 | 
				
			||||||
 | 
							obj.Value = ext.Value
 | 
				
			||||||
 | 
							obj.Gas = ext.Gas
 | 
				
			||||||
 | 
							obj.GasPrice = ext.GasPrice
 | 
				
			||||||
 | 
							obj.Data = ext.Data
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							return
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return NewErrorResponse(ErrorDecodeArgs)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
type PushTxArgs struct {
 | 
					type PushTxArgs struct {
 | 
				
			||||||
	Tx string `json:"tx"`
 | 
						Tx string `json:"tx"`
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
@@ -203,7 +233,7 @@ func (obj *Sha3Args) UnmarshalJSON(b []byte) (err error) {
 | 
				
			|||||||
type FilterOptions struct {
 | 
					type FilterOptions struct {
 | 
				
			||||||
	Earliest int64
 | 
						Earliest int64
 | 
				
			||||||
	Latest   int64
 | 
						Latest   int64
 | 
				
			||||||
	Address  string
 | 
						Address  interface{}
 | 
				
			||||||
	Topic    []string
 | 
						Topic    []string
 | 
				
			||||||
	Skip     int
 | 
						Skip     int
 | 
				
			||||||
	Max      int
 | 
						Max      int
 | 
				
			||||||
@@ -211,9 +241,22 @@ type FilterOptions struct {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
func toFilterOptions(options *FilterOptions) core.FilterOptions {
 | 
					func toFilterOptions(options *FilterOptions) core.FilterOptions {
 | 
				
			||||||
	var opts core.FilterOptions
 | 
						var opts core.FilterOptions
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Convert optional address slice/string to byte slice
 | 
				
			||||||
 | 
						if str, ok := options.Address.(string); ok {
 | 
				
			||||||
 | 
							opts.Address = [][]byte{fromHex(str)}
 | 
				
			||||||
 | 
						} else if slice, ok := options.Address.([]interface{}); ok {
 | 
				
			||||||
 | 
							bslice := make([][]byte, len(slice))
 | 
				
			||||||
 | 
							for i, addr := range slice {
 | 
				
			||||||
 | 
								if saddr, ok := addr.(string); ok {
 | 
				
			||||||
 | 
									bslice[i] = fromHex(saddr)
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							opts.Address = bslice
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	opts.Earliest = options.Earliest
 | 
						opts.Earliest = options.Earliest
 | 
				
			||||||
	opts.Latest = options.Latest
 | 
						opts.Latest = options.Latest
 | 
				
			||||||
	opts.Address = fromHex(options.Address)
 | 
					 | 
				
			||||||
	opts.Topics = make([][]byte, len(options.Topic))
 | 
						opts.Topics = make([][]byte, len(options.Topic))
 | 
				
			||||||
	for i, topic := range options.Topic {
 | 
						for i, topic := range options.Topic {
 | 
				
			||||||
		opts.Topics[i] = fromHex(topic)
 | 
							opts.Topics[i] = fromHex(topic)
 | 
				
			||||||
@@ -246,7 +289,7 @@ type WhisperMessageArgs struct {
 | 
				
			|||||||
	Payload  string
 | 
						Payload  string
 | 
				
			||||||
	To       string
 | 
						To       string
 | 
				
			||||||
	From     string
 | 
						From     string
 | 
				
			||||||
	Topics   []string
 | 
						Topic    []string
 | 
				
			||||||
	Priority uint32
 | 
						Priority uint32
 | 
				
			||||||
	Ttl      uint32
 | 
						Ttl      uint32
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -201,6 +201,36 @@ func (req *RpcRequest) ToGetCodeAtArgs() (*GetCodeAtArgs, error) {
 | 
				
			|||||||
	return args, nil
 | 
						return args, nil
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (req *RpcRequest) ToBoolArgs() (bool, error) {
 | 
				
			||||||
 | 
						if len(req.Params) < 1 {
 | 
				
			||||||
 | 
							return false, NewErrorResponse(ErrorArguments)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						var args bool
 | 
				
			||||||
 | 
						err := json.Unmarshal(req.Params[0], &args)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							return false, NewErrorResponse(ErrorDecodeArgs)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						rpclogger.DebugDetailf("%T %v", args, args)
 | 
				
			||||||
 | 
						return args, nil
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (req *RpcRequest) ToCompileArgs() (string, error) {
 | 
				
			||||||
 | 
						if len(req.Params) < 1 {
 | 
				
			||||||
 | 
							return "", NewErrorResponse(ErrorArguments)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						var args string
 | 
				
			||||||
 | 
						err := json.Unmarshal(req.Params[0], &args)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							return "", NewErrorResponse(ErrorDecodeArgs)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						rpclogger.DebugDetailf("%T %v", args, args)
 | 
				
			||||||
 | 
						return args, nil
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (req *RpcRequest) ToFilterArgs() (*FilterOptions, error) {
 | 
					func (req *RpcRequest) ToFilterArgs() (*FilterOptions, error) {
 | 
				
			||||||
	if len(req.Params) < 1 {
 | 
						if len(req.Params) < 1 {
 | 
				
			||||||
		return nil, NewErrorResponse(ErrorArguments)
 | 
							return nil, NewErrorResponse(ErrorArguments)
 | 
				
			||||||
@@ -231,6 +261,21 @@ func (req *RpcRequest) ToFilterStringArgs() (string, error) {
 | 
				
			|||||||
	return args, nil
 | 
						return args, nil
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (req *RpcRequest) ToUninstallFilterArgs() (int, error) {
 | 
				
			||||||
 | 
						if len(req.Params) < 1 {
 | 
				
			||||||
 | 
							return 0, NewErrorResponse(ErrorArguments)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						var args int
 | 
				
			||||||
 | 
						err := json.Unmarshal(req.Params[0], &args)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							return 0, NewErrorResponse(ErrorDecodeArgs)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						rpclogger.DebugDetailf("%T %v", args, args)
 | 
				
			||||||
 | 
						return args, nil
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (req *RpcRequest) ToFilterChangedArgs() (int, error) {
 | 
					func (req *RpcRequest) ToFilterChangedArgs() (int, error) {
 | 
				
			||||||
	if len(req.Params) < 1 {
 | 
						if len(req.Params) < 1 {
 | 
				
			||||||
		return 0, NewErrorResponse(ErrorArguments)
 | 
							return 0, NewErrorResponse(ErrorArguments)
 | 
				
			||||||
@@ -301,7 +346,7 @@ func (req *RpcRequest) ToWhisperFilterArgs() (*xeth.Options, error) {
 | 
				
			|||||||
	return &args, nil
 | 
						return &args, nil
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (req *RpcRequest) ToWhisperIdArgs() (int, error) {
 | 
					func (req *RpcRequest) ToIdArgs() (int, error) {
 | 
				
			||||||
	if len(req.Params) < 1 {
 | 
						if len(req.Params) < 1 {
 | 
				
			||||||
		return 0, NewErrorResponse(ErrorArguments)
 | 
							return 0, NewErrorResponse(ErrorArguments)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
@@ -342,3 +387,31 @@ func (req *RpcRequest) ToWhisperHasIdentityArgs() (string, error) {
 | 
				
			|||||||
	rpclogger.DebugDetailf("%T %v", args, args)
 | 
						rpclogger.DebugDetailf("%T %v", args, args)
 | 
				
			||||||
	return args, nil
 | 
						return args, nil
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (req *RpcRequest) ToRegisterArgs() (string, error) {
 | 
				
			||||||
 | 
						if len(req.Params) < 1 {
 | 
				
			||||||
 | 
							return "", NewErrorResponse(ErrorArguments)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						var args string
 | 
				
			||||||
 | 
						err := json.Unmarshal(req.Params[0], &args)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							return "", err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						rpclogger.DebugDetailf("%T %v", args, args)
 | 
				
			||||||
 | 
						return args, nil
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (req *RpcRequest) ToWatchTxArgs() (string, error) {
 | 
				
			||||||
 | 
						if len(req.Params) < 1 {
 | 
				
			||||||
 | 
							return "", NewErrorResponse(ErrorArguments)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						var args string
 | 
				
			||||||
 | 
						err := json.Unmarshal(req.Params[0], &args)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							return "", err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						rpclogger.DebugDetailf("%T %v", args, args)
 | 
				
			||||||
 | 
						return args, nil
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										234
									
								
								rpc/packages.go
									
									
									
									
									
								
							
							
						
						
									
										234
									
								
								rpc/packages.go
									
									
									
									
									
								
							@@ -1,21 +1,4 @@
 | 
				
			|||||||
/*
 | 
					/*
 | 
				
			||||||
	This file is part of go-ethereum
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	go-ethereum is free software: you can redistribute it and/or modify
 | 
					 | 
				
			||||||
	it under the terms of the GNU General Public License as published by
 | 
					 | 
				
			||||||
	the Free Software Foundation, either version 3 of the License, or
 | 
					 | 
				
			||||||
	(at your option) any later version.
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	go-ethereum 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 General Public License for more details.
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	You should have received a copy of the GNU General Public License
 | 
					 | 
				
			||||||
	along with go-ethereum.  If not, see <http://www.gnu.org/licenses/>.
 | 
					 | 
				
			||||||
*/
 | 
					 | 
				
			||||||
/*
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
For each request type, define the following:
 | 
					For each request type, define the following:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
1. RpcRequest "To" method [message.go], which does basic validation and conversion to "Args" type via json.Decoder()
 | 
					1. RpcRequest "To" method [message.go], which does basic validation and conversion to "Args" type via json.Decoder()
 | 
				
			||||||
@@ -30,6 +13,7 @@ import (
 | 
				
			|||||||
	"math/big"
 | 
						"math/big"
 | 
				
			||||||
	"strings"
 | 
						"strings"
 | 
				
			||||||
	"sync"
 | 
						"sync"
 | 
				
			||||||
 | 
						"time"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	"github.com/ethereum/go-ethereum/core"
 | 
						"github.com/ethereum/go-ethereum/core"
 | 
				
			||||||
	"github.com/ethereum/go-ethereum/core/types"
 | 
						"github.com/ethereum/go-ethereum/core/types"
 | 
				
			||||||
@@ -48,13 +32,17 @@ const (
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
type EthereumApi struct {
 | 
					type EthereumApi struct {
 | 
				
			||||||
	xeth          *xeth.XEth
 | 
						xeth          *xeth.XEth
 | 
				
			||||||
 | 
						quit          chan struct{}
 | 
				
			||||||
	filterManager *filter.FilterManager
 | 
						filterManager *filter.FilterManager
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	logMut sync.RWMutex
 | 
						logMut sync.RWMutex
 | 
				
			||||||
	logs   map[int]state.Logs
 | 
						logs   map[int]*logFilter
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	messagesMut sync.RWMutex
 | 
						messagesMut sync.RWMutex
 | 
				
			||||||
	messages    map[int][]xeth.WhisperMessage
 | 
						messages    map[int]*whisperFilter
 | 
				
			||||||
 | 
						// Register keeps a list of accounts and transaction data
 | 
				
			||||||
 | 
						regmut   sync.Mutex
 | 
				
			||||||
 | 
						register map[string][]*NewTxArgs
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	db ethutil.Database
 | 
						db ethutil.Database
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
@@ -63,16 +51,48 @@ func NewEthereumApi(eth *xeth.XEth) *EthereumApi {
 | 
				
			|||||||
	db, _ := ethdb.NewLDBDatabase("dapps")
 | 
						db, _ := ethdb.NewLDBDatabase("dapps")
 | 
				
			||||||
	api := &EthereumApi{
 | 
						api := &EthereumApi{
 | 
				
			||||||
		xeth:          eth,
 | 
							xeth:          eth,
 | 
				
			||||||
 | 
							quit:          make(chan struct{}),
 | 
				
			||||||
		filterManager: filter.NewFilterManager(eth.Backend().EventMux()),
 | 
							filterManager: filter.NewFilterManager(eth.Backend().EventMux()),
 | 
				
			||||||
		logs:          make(map[int]state.Logs),
 | 
							logs:          make(map[int]*logFilter),
 | 
				
			||||||
		messages:      make(map[int][]xeth.WhisperMessage),
 | 
							messages:      make(map[int]*whisperFilter),
 | 
				
			||||||
		db:            db,
 | 
							db:            db,
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	go api.filterManager.Start()
 | 
						go api.filterManager.Start()
 | 
				
			||||||
 | 
						go api.start()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return api
 | 
						return api
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (self *EthereumApi) Register(args string, reply *interface{}) error {
 | 
				
			||||||
 | 
						self.regmut.Lock()
 | 
				
			||||||
 | 
						defer self.regmut.Unlock()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if _, ok := self.register[args]; ok {
 | 
				
			||||||
 | 
							self.register[args] = nil // register with empty
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return nil
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (self *EthereumApi) Unregister(args string, reply *interface{}) error {
 | 
				
			||||||
 | 
						self.regmut.Lock()
 | 
				
			||||||
 | 
						defer self.regmut.Unlock()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						delete(self.register, args)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return nil
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (self *EthereumApi) WatchTx(args string, reply *interface{}) error {
 | 
				
			||||||
 | 
						self.regmut.Lock()
 | 
				
			||||||
 | 
						defer self.regmut.Unlock()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						txs := self.register[args]
 | 
				
			||||||
 | 
						self.register[args] = nil
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						*reply = txs
 | 
				
			||||||
 | 
						return nil
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (self *EthereumApi) NewFilter(args *FilterOptions, reply *interface{}) error {
 | 
					func (self *EthereumApi) NewFilter(args *FilterOptions, reply *interface{}) error {
 | 
				
			||||||
	var id int
 | 
						var id int
 | 
				
			||||||
	filter := core.NewFilter(self.xeth.Backend())
 | 
						filter := core.NewFilter(self.xeth.Backend())
 | 
				
			||||||
@@ -81,20 +101,36 @@ func (self *EthereumApi) NewFilter(args *FilterOptions, reply *interface{}) erro
 | 
				
			|||||||
		self.logMut.Lock()
 | 
							self.logMut.Lock()
 | 
				
			||||||
		defer self.logMut.Unlock()
 | 
							defer self.logMut.Unlock()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		self.logs[id] = append(self.logs[id], logs...)
 | 
							self.logs[id].add(logs...)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	id = self.filterManager.InstallFilter(filter)
 | 
						id = self.filterManager.InstallFilter(filter)
 | 
				
			||||||
 | 
						self.logs[id] = &logFilter{timeout: time.Now()}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	*reply = id
 | 
						*reply = id
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return nil
 | 
						return nil
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (self *EthereumApi) UninstallFilter(id int, reply *interface{}) error {
 | 
				
			||||||
 | 
						delete(self.logs, id)
 | 
				
			||||||
 | 
						self.filterManager.UninstallFilter(id)
 | 
				
			||||||
 | 
						*reply = true
 | 
				
			||||||
 | 
						return nil
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (self *EthereumApi) NewFilterString(args string, reply *interface{}) error {
 | 
					func (self *EthereumApi) NewFilterString(args string, reply *interface{}) error {
 | 
				
			||||||
	var id int
 | 
						var id int
 | 
				
			||||||
	filter := core.NewFilter(self.xeth.Backend())
 | 
						filter := core.NewFilter(self.xeth.Backend())
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	callback := func(block *types.Block) {
 | 
						callback := func(block *types.Block) {
 | 
				
			||||||
		self.logs[id] = append(self.logs[id], &state.StateLog{})
 | 
							self.logMut.Lock()
 | 
				
			||||||
 | 
							defer self.logMut.Unlock()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							if self.logs[id] == nil {
 | 
				
			||||||
 | 
								self.logs[id] = &logFilter{timeout: time.Now()}
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							self.logs[id].add(&state.StateLog{})
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	if args == "pending" {
 | 
						if args == "pending" {
 | 
				
			||||||
		filter.PendingCallback = callback
 | 
							filter.PendingCallback = callback
 | 
				
			||||||
@@ -112,15 +148,29 @@ func (self *EthereumApi) FilterChanged(id int, reply *interface{}) error {
 | 
				
			|||||||
	self.logMut.Lock()
 | 
						self.logMut.Lock()
 | 
				
			||||||
	defer self.logMut.Unlock()
 | 
						defer self.logMut.Unlock()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	*reply = toLogs(self.logs[id])
 | 
						if self.logs[id] != nil {
 | 
				
			||||||
 | 
							*reply = toLogs(self.logs[id].get())
 | 
				
			||||||
	self.logs[id] = nil // empty the logs
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return nil
 | 
						return nil
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (self *EthereumApi) Logs(id int, reply *interface{}) error {
 | 
					func (self *EthereumApi) Logs(id int, reply *interface{}) error {
 | 
				
			||||||
 | 
						self.logMut.Lock()
 | 
				
			||||||
 | 
						defer self.logMut.Unlock()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	filter := self.filterManager.GetFilter(id)
 | 
						filter := self.filterManager.GetFilter(id)
 | 
				
			||||||
 | 
						if filter != nil {
 | 
				
			||||||
 | 
							*reply = toLogs(filter.Find())
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return nil
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (self *EthereumApi) AllLogs(args *FilterOptions, reply *interface{}) error {
 | 
				
			||||||
 | 
						filter := core.NewFilter(self.xeth.Backend())
 | 
				
			||||||
 | 
						filter.SetOptions(toFilterOptions(args))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	*reply = toLogs(filter.Find())
 | 
						*reply = toLogs(filter.Find())
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return nil
 | 
						return nil
 | 
				
			||||||
@@ -149,8 +199,14 @@ func (p *EthereumApi) Transact(args *NewTxArgs, reply *interface{}) error {
 | 
				
			|||||||
		args.GasPrice = defaultGasPrice
 | 
							args.GasPrice = defaultGasPrice
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	result, _ := p.xeth.Transact( /* TODO specify account */ args.To, args.Value, args.Gas, args.GasPrice, args.Data)
 | 
						// TODO if no_private_key then
 | 
				
			||||||
	*reply = result
 | 
						if _, exists := p.register[args.From]; exists {
 | 
				
			||||||
 | 
							p.register[args.From] = append(p.register[args.From], args)
 | 
				
			||||||
 | 
						} else {
 | 
				
			||||||
 | 
							result, _ := p.xeth.Transact( /* TODO specify account */ args.To, args.Value, args.Gas, args.GasPrice, args.Data)
 | 
				
			||||||
 | 
							*reply = result
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return nil
 | 
						return nil
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -231,6 +287,11 @@ func (p *EthereumApi) GetIsMining(reply *interface{}) error {
 | 
				
			|||||||
	return nil
 | 
						return nil
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (p *EthereumApi) SetMining(shouldmine bool, reply *interface{}) error {
 | 
				
			||||||
 | 
						*reply = p.xeth.SetMining(shouldmine)
 | 
				
			||||||
 | 
						return nil
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (p *EthereumApi) BlockNumber(reply *interface{}) error {
 | 
					func (p *EthereumApi) BlockNumber(reply *interface{}) error {
 | 
				
			||||||
	*reply = p.xeth.Backend().ChainManager().CurrentBlock().Number()
 | 
						*reply = p.xeth.Backend().ChainManager().CurrentBlock().Number()
 | 
				
			||||||
	return nil
 | 
						return nil
 | 
				
			||||||
@@ -264,6 +325,21 @@ func (p *EthereumApi) GetCodeAt(args *GetCodeAtArgs, reply *interface{}) error {
 | 
				
			|||||||
	return nil
 | 
						return nil
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (p *EthereumApi) GetCompilers(reply *interface{}) error {
 | 
				
			||||||
 | 
						c := []string{"serpent"}
 | 
				
			||||||
 | 
						*reply = c
 | 
				
			||||||
 | 
						return nil
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (p *EthereumApi) CompileSerpent(script string, reply *interface{}) error {
 | 
				
			||||||
 | 
						res, err := ethutil.Compile(script, false)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							return err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						*reply = res
 | 
				
			||||||
 | 
						return nil
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (p *EthereumApi) Sha3(args *Sha3Args, reply *interface{}) error {
 | 
					func (p *EthereumApi) Sha3(args *Sha3Args, reply *interface{}) error {
 | 
				
			||||||
	*reply = toHex(crypto.Sha3(fromHex(args.Data)))
 | 
						*reply = toHex(crypto.Sha3(fromHex(args.Data)))
 | 
				
			||||||
	return nil
 | 
						return nil
 | 
				
			||||||
@@ -301,7 +377,10 @@ func (p *EthereumApi) NewWhisperFilter(args *xeth.Options, reply *interface{}) e
 | 
				
			|||||||
	args.Fn = func(msg xeth.WhisperMessage) {
 | 
						args.Fn = func(msg xeth.WhisperMessage) {
 | 
				
			||||||
		p.messagesMut.Lock()
 | 
							p.messagesMut.Lock()
 | 
				
			||||||
		defer p.messagesMut.Unlock()
 | 
							defer p.messagesMut.Unlock()
 | 
				
			||||||
		p.messages[id] = append(p.messages[id], msg)
 | 
							if p.messages[id] == nil {
 | 
				
			||||||
 | 
								p.messages[id] = &whisperFilter{timeout: time.Now()}
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							p.messages[id].add(msg) // = append(p.messages[id], msg)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	id = p.xeth.Whisper().Watch(args)
 | 
						id = p.xeth.Whisper().Watch(args)
 | 
				
			||||||
	*reply = id
 | 
						*reply = id
 | 
				
			||||||
@@ -312,15 +391,15 @@ func (self *EthereumApi) MessagesChanged(id int, reply *interface{}) error {
 | 
				
			|||||||
	self.messagesMut.Lock()
 | 
						self.messagesMut.Lock()
 | 
				
			||||||
	defer self.messagesMut.Unlock()
 | 
						defer self.messagesMut.Unlock()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	*reply = self.messages[id]
 | 
						if self.messages[id] != nil {
 | 
				
			||||||
 | 
							*reply = self.messages[id].get()
 | 
				
			||||||
	self.messages[id] = nil // empty the messages
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return nil
 | 
						return nil
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (p *EthereumApi) WhisperPost(args *WhisperMessageArgs, reply *interface{}) error {
 | 
					func (p *EthereumApi) WhisperPost(args *WhisperMessageArgs, reply *interface{}) error {
 | 
				
			||||||
	err := p.xeth.Whisper().Post(args.Payload, args.To, args.From, args.Topics, args.Priority, args.Ttl)
 | 
						err := p.xeth.Whisper().Post(args.Payload, args.To, args.From, args.Topic, args.Priority, args.Ttl)
 | 
				
			||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
		return err
 | 
							return err
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
@@ -349,6 +428,12 @@ func (p *EthereumApi) GetRequestReply(req *RpcRequest, reply *interface{}) error
 | 
				
			|||||||
		return p.GetIsListening(reply)
 | 
							return p.GetIsListening(reply)
 | 
				
			||||||
	case "eth_mining":
 | 
						case "eth_mining":
 | 
				
			||||||
		return p.GetIsMining(reply)
 | 
							return p.GetIsMining(reply)
 | 
				
			||||||
 | 
						case "eth_setMining":
 | 
				
			||||||
 | 
							args, err := req.ToBoolArgs()
 | 
				
			||||||
 | 
							if err != nil {
 | 
				
			||||||
 | 
								return err
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							return p.SetMining(args, reply)
 | 
				
			||||||
	case "eth_peerCount":
 | 
						case "eth_peerCount":
 | 
				
			||||||
		return p.GetPeerCount(reply)
 | 
							return p.GetPeerCount(reply)
 | 
				
			||||||
	case "eth_number":
 | 
						case "eth_number":
 | 
				
			||||||
@@ -415,15 +500,59 @@ func (p *EthereumApi) GetRequestReply(req *RpcRequest, reply *interface{}) error
 | 
				
			|||||||
			return err
 | 
								return err
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		return p.NewFilterString(args, reply)
 | 
							return p.NewFilterString(args, reply)
 | 
				
			||||||
 | 
						case "eth_uninstallFilter":
 | 
				
			||||||
 | 
							args, err := req.ToUninstallFilterArgs()
 | 
				
			||||||
 | 
							if err != nil {
 | 
				
			||||||
 | 
								return err
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							return p.UninstallFilter(args, reply)
 | 
				
			||||||
	case "eth_changed":
 | 
						case "eth_changed":
 | 
				
			||||||
		args, err := req.ToFilterChangedArgs()
 | 
							args, err := req.ToIdArgs()
 | 
				
			||||||
		if err != nil {
 | 
							if err != nil {
 | 
				
			||||||
			return err
 | 
								return err
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		return p.FilterChanged(args, reply)
 | 
							return p.FilterChanged(args, reply)
 | 
				
			||||||
 | 
						case "eth_filterLogs":
 | 
				
			||||||
 | 
							args, err := req.ToIdArgs()
 | 
				
			||||||
 | 
							if err != nil {
 | 
				
			||||||
 | 
								return err
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							return p.Logs(args, reply)
 | 
				
			||||||
 | 
						case "eth_logs":
 | 
				
			||||||
 | 
							args, err := req.ToFilterArgs()
 | 
				
			||||||
 | 
							if err != nil {
 | 
				
			||||||
 | 
								return err
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							return p.AllLogs(args, reply)
 | 
				
			||||||
	case "eth_gasPrice":
 | 
						case "eth_gasPrice":
 | 
				
			||||||
		*reply = defaultGasPrice
 | 
							*reply = defaultGasPrice
 | 
				
			||||||
		return nil
 | 
							return nil
 | 
				
			||||||
 | 
						case "eth_register":
 | 
				
			||||||
 | 
							args, err := req.ToRegisterArgs()
 | 
				
			||||||
 | 
							if err != nil {
 | 
				
			||||||
 | 
								return err
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							return p.Register(args, reply)
 | 
				
			||||||
 | 
						case "eth_unregister":
 | 
				
			||||||
 | 
							args, err := req.ToRegisterArgs()
 | 
				
			||||||
 | 
							if err != nil {
 | 
				
			||||||
 | 
								return err
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							return p.Unregister(args, reply)
 | 
				
			||||||
 | 
						case "eth_watchTx":
 | 
				
			||||||
 | 
							args, err := req.ToWatchTxArgs()
 | 
				
			||||||
 | 
							if err != nil {
 | 
				
			||||||
 | 
								return err
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							return p.WatchTx(args, reply)
 | 
				
			||||||
 | 
						case "eth_compilers":
 | 
				
			||||||
 | 
							return p.GetCompilers(reply)
 | 
				
			||||||
 | 
						case "eth_serpent":
 | 
				
			||||||
 | 
							args, err := req.ToCompileArgs()
 | 
				
			||||||
 | 
							if err != nil {
 | 
				
			||||||
 | 
								return err
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							return p.CompileSerpent(args, reply)
 | 
				
			||||||
	case "web3_sha3":
 | 
						case "web3_sha3":
 | 
				
			||||||
		args, err := req.ToSha3Args()
 | 
							args, err := req.ToSha3Args()
 | 
				
			||||||
		if err != nil {
 | 
							if err != nil {
 | 
				
			||||||
@@ -451,7 +580,7 @@ func (p *EthereumApi) GetRequestReply(req *RpcRequest, reply *interface{}) error
 | 
				
			|||||||
		}
 | 
							}
 | 
				
			||||||
		return p.NewWhisperFilter(args, reply)
 | 
							return p.NewWhisperFilter(args, reply)
 | 
				
			||||||
	case "shh_changed":
 | 
						case "shh_changed":
 | 
				
			||||||
		args, err := req.ToWhisperIdArgs()
 | 
							args, err := req.ToIdArgs()
 | 
				
			||||||
		if err != nil {
 | 
							if err != nil {
 | 
				
			||||||
			return err
 | 
								return err
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
@@ -469,7 +598,7 @@ func (p *EthereumApi) GetRequestReply(req *RpcRequest, reply *interface{}) error
 | 
				
			|||||||
		}
 | 
							}
 | 
				
			||||||
		return p.HasWhisperIdentity(args, reply)
 | 
							return p.HasWhisperIdentity(args, reply)
 | 
				
			||||||
	case "shh_getMessages":
 | 
						case "shh_getMessages":
 | 
				
			||||||
		args, err := req.ToWhisperIdArgs()
 | 
							args, err := req.ToIdArgs()
 | 
				
			||||||
		if err != nil {
 | 
							if err != nil {
 | 
				
			||||||
			return err
 | 
								return err
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
@@ -481,3 +610,36 @@ func (p *EthereumApi) GetRequestReply(req *RpcRequest, reply *interface{}) error
 | 
				
			|||||||
	rpclogger.DebugDetailf("Reply: %T %s", reply, reply)
 | 
						rpclogger.DebugDetailf("Reply: %T %s", reply, reply)
 | 
				
			||||||
	return nil
 | 
						return nil
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					var filterTickerTime = 15 * time.Second
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (self *EthereumApi) start() {
 | 
				
			||||||
 | 
						timer := time.NewTicker(filterTickerTime)
 | 
				
			||||||
 | 
					done:
 | 
				
			||||||
 | 
						for {
 | 
				
			||||||
 | 
							select {
 | 
				
			||||||
 | 
							case <-timer.C:
 | 
				
			||||||
 | 
								self.logMut.Lock()
 | 
				
			||||||
 | 
								self.messagesMut.Lock()
 | 
				
			||||||
 | 
								for id, filter := range self.logs {
 | 
				
			||||||
 | 
									if time.Since(filter.timeout) > 20*time.Second {
 | 
				
			||||||
 | 
										delete(self.logs, id)
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								for id, filter := range self.messages {
 | 
				
			||||||
 | 
									if time.Since(filter.timeout) > 20*time.Second {
 | 
				
			||||||
 | 
										delete(self.messages, id)
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								self.logMut.Unlock()
 | 
				
			||||||
 | 
								self.messagesMut.Unlock()
 | 
				
			||||||
 | 
							case <-self.quit:
 | 
				
			||||||
 | 
								break done
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (self *EthereumApi) stop() {
 | 
				
			||||||
 | 
						close(self.quit)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										37
									
								
								rpc/packages_test.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										37
									
								
								rpc/packages_test.go
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,37 @@
 | 
				
			|||||||
 | 
					package rpc
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import (
 | 
				
			||||||
 | 
						"sync"
 | 
				
			||||||
 | 
						"testing"
 | 
				
			||||||
 | 
						"time"
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func TestFilterClose(t *testing.T) {
 | 
				
			||||||
 | 
						api := &EthereumApi{
 | 
				
			||||||
 | 
							logs:     make(map[int]*logFilter),
 | 
				
			||||||
 | 
							messages: make(map[int]*whisperFilter),
 | 
				
			||||||
 | 
							quit:     make(chan struct{}),
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						filterTickerTime = 1
 | 
				
			||||||
 | 
						api.logs[0] = &logFilter{}
 | 
				
			||||||
 | 
						api.messages[0] = &whisperFilter{}
 | 
				
			||||||
 | 
						var wg sync.WaitGroup
 | 
				
			||||||
 | 
						wg.Add(1)
 | 
				
			||||||
 | 
						go api.start()
 | 
				
			||||||
 | 
						go func() {
 | 
				
			||||||
 | 
							select {
 | 
				
			||||||
 | 
							case <-time.After(500 * time.Millisecond):
 | 
				
			||||||
 | 
								api.stop()
 | 
				
			||||||
 | 
								wg.Done()
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}()
 | 
				
			||||||
 | 
						wg.Wait()
 | 
				
			||||||
 | 
						if len(api.logs) != 0 {
 | 
				
			||||||
 | 
							t.Error("expected logs to be empty")
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if len(api.messages) != 0 {
 | 
				
			||||||
 | 
							t.Error("expected messages to be empty")
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										41
									
								
								rpc/util.go
									
									
									
									
									
								
							
							
						
						
									
										41
									
								
								rpc/util.go
									
									
									
									
									
								
							@@ -20,10 +20,12 @@ import (
 | 
				
			|||||||
	"encoding/json"
 | 
						"encoding/json"
 | 
				
			||||||
	"io"
 | 
						"io"
 | 
				
			||||||
	"net/http"
 | 
						"net/http"
 | 
				
			||||||
 | 
						"time"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	"github.com/ethereum/go-ethereum/ethutil"
 | 
						"github.com/ethereum/go-ethereum/ethutil"
 | 
				
			||||||
	"github.com/ethereum/go-ethereum/logger"
 | 
						"github.com/ethereum/go-ethereum/logger"
 | 
				
			||||||
	"github.com/ethereum/go-ethereum/state"
 | 
						"github.com/ethereum/go-ethereum/state"
 | 
				
			||||||
 | 
						"github.com/ethereum/go-ethereum/xeth"
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
var rpclogger = logger.NewLogger("RPC")
 | 
					var rpclogger = logger.NewLogger("RPC")
 | 
				
			||||||
@@ -80,8 +82,9 @@ type RpcServer interface {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
type Log struct {
 | 
					type Log struct {
 | 
				
			||||||
	Address string   `json:"address"`
 | 
						Address string   `json:"address"`
 | 
				
			||||||
	Topics  []string `json:"topics"`
 | 
						Topic   []string `json:"topics"`
 | 
				
			||||||
	Data    string   `json:"data"`
 | 
						Data    string   `json:"data"`
 | 
				
			||||||
 | 
						Number  uint64   `json:"number"`
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func toLogs(logs state.Logs) (ls []Log) {
 | 
					func toLogs(logs state.Logs) (ls []Log) {
 | 
				
			||||||
@@ -89,14 +92,46 @@ func toLogs(logs state.Logs) (ls []Log) {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
	for i, log := range logs {
 | 
						for i, log := range logs {
 | 
				
			||||||
		var l Log
 | 
							var l Log
 | 
				
			||||||
		l.Topics = make([]string, len(log.Topics()))
 | 
							l.Topic = make([]string, len(log.Topics()))
 | 
				
			||||||
		l.Address = toHex(log.Address())
 | 
							l.Address = toHex(log.Address())
 | 
				
			||||||
		l.Data = toHex(log.Data())
 | 
							l.Data = toHex(log.Data())
 | 
				
			||||||
 | 
							l.Number = log.Number()
 | 
				
			||||||
		for j, topic := range log.Topics() {
 | 
							for j, topic := range log.Topics() {
 | 
				
			||||||
			l.Topics[j] = toHex(topic)
 | 
								l.Topic[j] = toHex(topic)
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		ls[i] = l
 | 
							ls[i] = l
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return
 | 
						return
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					type whisperFilter struct {
 | 
				
			||||||
 | 
						messages []xeth.WhisperMessage
 | 
				
			||||||
 | 
						timeout  time.Time
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (w *whisperFilter) add(msgs ...xeth.WhisperMessage) {
 | 
				
			||||||
 | 
						w.messages = append(w.messages, msgs...)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					func (w *whisperFilter) get() []xeth.WhisperMessage {
 | 
				
			||||||
 | 
						w.timeout = time.Now()
 | 
				
			||||||
 | 
						tmp := w.messages
 | 
				
			||||||
 | 
						w.messages = nil
 | 
				
			||||||
 | 
						return tmp
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					type logFilter struct {
 | 
				
			||||||
 | 
						logs    state.Logs
 | 
				
			||||||
 | 
						timeout time.Time
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (l *logFilter) add(logs ...state.Log) {
 | 
				
			||||||
 | 
						l.logs = append(l.logs, logs...)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (l *logFilter) get() state.Logs {
 | 
				
			||||||
 | 
						l.timeout = time.Now()
 | 
				
			||||||
 | 
						tmp := l.logs
 | 
				
			||||||
 | 
						l.logs = nil
 | 
				
			||||||
 | 
						return tmp
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -21,10 +21,10 @@ import (
 | 
				
			|||||||
	"net"
 | 
						"net"
 | 
				
			||||||
	"net/http"
 | 
						"net/http"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	"code.google.com/p/go.net/websocket"
 | 
					 | 
				
			||||||
	"github.com/ethereum/go-ethereum/logger"
 | 
						"github.com/ethereum/go-ethereum/logger"
 | 
				
			||||||
	"github.com/ethereum/go-ethereum/rpc"
 | 
						"github.com/ethereum/go-ethereum/rpc"
 | 
				
			||||||
	"github.com/ethereum/go-ethereum/xeth"
 | 
						"github.com/ethereum/go-ethereum/xeth"
 | 
				
			||||||
 | 
						"golang.org/x/net/websocket"
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
var wslogger = logger.NewLogger("RPC-WS")
 | 
					var wslogger = logger.NewLogger("RPC-WS")
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -30,7 +30,7 @@ func (self *StateDB) Dump() []byte {
 | 
				
			|||||||
	for it.Next() {
 | 
						for it.Next() {
 | 
				
			||||||
		stateObject := NewStateObjectFromBytes(it.Key, it.Value, self.db)
 | 
							stateObject := NewStateObjectFromBytes(it.Key, it.Value, self.db)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		account := Account{Balance: stateObject.balance.String(), Nonce: stateObject.Nonce, Root: ethutil.Bytes2Hex(stateObject.Root()), CodeHash: ethutil.Bytes2Hex(stateObject.codeHash)}
 | 
							account := Account{Balance: stateObject.balance.String(), Nonce: stateObject.nonce, Root: ethutil.Bytes2Hex(stateObject.Root()), CodeHash: ethutil.Bytes2Hex(stateObject.codeHash)}
 | 
				
			||||||
		account.Storage = make(map[string]string)
 | 
							account.Storage = make(map[string]string)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		storageIt := stateObject.State.trie.Iterator()
 | 
							storageIt := stateObject.State.trie.Iterator()
 | 
				
			||||||
@@ -50,7 +50,7 @@ func (self *StateDB) Dump() []byte {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
// Debug stuff
 | 
					// Debug stuff
 | 
				
			||||||
func (self *StateObject) CreateOutputForDiff() {
 | 
					func (self *StateObject) CreateOutputForDiff() {
 | 
				
			||||||
	fmt.Printf("%x %x %x %x\n", self.Address(), self.State.Root(), self.balance.Bytes(), self.Nonce)
 | 
						fmt.Printf("%x %x %x %x\n", self.Address(), self.State.Root(), self.balance.Bytes(), self.nonce)
 | 
				
			||||||
	it := self.State.trie.Iterator()
 | 
						it := self.State.trie.Iterator()
 | 
				
			||||||
	for it.Next() {
 | 
						for it.Next() {
 | 
				
			||||||
		fmt.Printf("%x %x\n", it.Key, it.Value)
 | 
							fmt.Printf("%x %x\n", it.Key, it.Value)
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										11
									
								
								state/log.go
									
									
									
									
									
								
							
							
						
						
									
										11
									
								
								state/log.go
									
									
									
									
									
								
							@@ -12,16 +12,19 @@ type Log interface {
 | 
				
			|||||||
	Address() []byte
 | 
						Address() []byte
 | 
				
			||||||
	Topics() [][]byte
 | 
						Topics() [][]byte
 | 
				
			||||||
	Data() []byte
 | 
						Data() []byte
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						Number() uint64
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
type StateLog struct {
 | 
					type StateLog struct {
 | 
				
			||||||
	address []byte
 | 
						address []byte
 | 
				
			||||||
	topics  [][]byte
 | 
						topics  [][]byte
 | 
				
			||||||
	data    []byte
 | 
						data    []byte
 | 
				
			||||||
 | 
						number  uint64
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func NewLog(address []byte, topics [][]byte, data []byte) *StateLog {
 | 
					func NewLog(address []byte, topics [][]byte, data []byte, number uint64) *StateLog {
 | 
				
			||||||
	return &StateLog{address, topics, data}
 | 
						return &StateLog{address, topics, data, number}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (self *StateLog) Address() []byte {
 | 
					func (self *StateLog) Address() []byte {
 | 
				
			||||||
@@ -36,6 +39,10 @@ func (self *StateLog) Data() []byte {
 | 
				
			|||||||
	return self.data
 | 
						return self.data
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (self *StateLog) Number() uint64 {
 | 
				
			||||||
 | 
						return self.number
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func NewLogFromValue(decoder *ethutil.Value) *StateLog {
 | 
					func NewLogFromValue(decoder *ethutil.Value) *StateLog {
 | 
				
			||||||
	log := &StateLog{
 | 
						log := &StateLog{
 | 
				
			||||||
		address: decoder.Get(0).Bytes(),
 | 
							address: decoder.Get(0).Bytes(),
 | 
				
			||||||
 
 | 
				
			|||||||
Some files were not shown because too many files have changed in this diff Show More
		Reference in New Issue
	
	Block a user