aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAlexandre Van de Sande <alex.vandesande@ethdev.com>2015-02-23 20:05:15 +0800
committerAlexandre Van de Sande <alex.vandesande@ethdev.com>2015-02-23 20:05:15 +0800
commitdea65840186fe861017524c9cb59ae07ac97ed06 (patch)
tree5cb5e339b9ce77a2a3c92cf8a10c4294fcf7965c
parentbb3338df6363d8267a24190584f0908463241a6c (diff)
parentdd086791acf477da7641c168f82de70ed0b2dca6 (diff)
downloadgo-tangerine-dea65840186fe861017524c9cb59ae07ac97ed06.tar
go-tangerine-dea65840186fe861017524c9cb59ae07ac97ed06.tar.gz
go-tangerine-dea65840186fe861017524c9cb59ae07ac97ed06.tar.bz2
go-tangerine-dea65840186fe861017524c9cb59ae07ac97ed06.tar.lz
go-tangerine-dea65840186fe861017524c9cb59ae07ac97ed06.tar.xz
go-tangerine-dea65840186fe861017524c9cb59ae07ac97ed06.tar.zst
go-tangerine-dea65840186fe861017524c9cb59ae07ac97ed06.zip
Merge branch 'develop' into ui
-rw-r--r--.travis.yml13
-rw-r--r--Godeps/Godeps.json46
-rw-r--r--Godeps/_workspace/src/code.google.com/p/go.crypto/pbkdf2/pbkdf2.go77
-rw-r--r--Godeps/_workspace/src/code.google.com/p/go.crypto/pbkdf2/pbkdf2_test.go157
-rw-r--r--Godeps/_workspace/src/github.com/huin/goupnp/LICENSE (renamed from Godeps/_workspace/src/github.com/fjl/goupnp/LICENSE)0
-rw-r--r--Godeps/_workspace/src/github.com/huin/goupnp/README.md (renamed from Godeps/_workspace/src/github.com/fjl/goupnp/README.md)2
-rw-r--r--Godeps/_workspace/src/github.com/huin/goupnp/cmd/example_httpu_serving/example_httpu_serving.go (renamed from Godeps/_workspace/src/github.com/fjl/goupnp/cmd/example_httpu_serving/example_httpu_serving.go)2
-rw-r--r--Godeps/_workspace/src/github.com/huin/goupnp/cmd/example_internetgateway1/example_internetgateway1.go (renamed from Godeps/_workspace/src/github.com/fjl/goupnp/cmd/example_internetgateway1/example_internetgateway1.go)2
-rw-r--r--Godeps/_workspace/src/github.com/huin/goupnp/dcps/internetgateway1/internetgateway1.go (renamed from Godeps/_workspace/src/github.com/fjl/goupnp/dcps/internetgateway1/internetgateway1.go)4
-rw-r--r--Godeps/_workspace/src/github.com/huin/goupnp/dcps/internetgateway2/internetgateway2.go (renamed from Godeps/_workspace/src/github.com/fjl/goupnp/dcps/internetgateway2/internetgateway2.go)4
-rw-r--r--Godeps/_workspace/src/github.com/huin/goupnp/device.go (renamed from Godeps/_workspace/src/github.com/fjl/goupnp/device.go)4
-rw-r--r--Godeps/_workspace/src/github.com/huin/goupnp/example/example.go (renamed from Godeps/_workspace/src/github.com/fjl/goupnp/example/example.go)2
-rw-r--r--Godeps/_workspace/src/github.com/huin/goupnp/example/example_test.go (renamed from Godeps/_workspace/src/github.com/fjl/goupnp/example/example_test.go)4
-rw-r--r--Godeps/_workspace/src/github.com/huin/goupnp/gotasks/specgen_task.go (renamed from Godeps/_workspace/src/github.com/fjl/goupnp/gotasks/specgen_task.go)10
-rw-r--r--Godeps/_workspace/src/github.com/huin/goupnp/goupnp.go (renamed from Godeps/_workspace/src/github.com/fjl/goupnp/goupnp.go)10
-rw-r--r--Godeps/_workspace/src/github.com/huin/goupnp/httpu/httpu.go (renamed from Godeps/_workspace/src/github.com/fjl/goupnp/httpu/httpu.go)0
-rw-r--r--Godeps/_workspace/src/github.com/huin/goupnp/httpu/serve.go (renamed from Godeps/_workspace/src/github.com/fjl/goupnp/httpu/serve.go)0
-rw-r--r--Godeps/_workspace/src/github.com/huin/goupnp/scpd/scpd.go (renamed from Godeps/_workspace/src/github.com/fjl/goupnp/scpd/scpd.go)0
-rw-r--r--Godeps/_workspace/src/github.com/huin/goupnp/service_client.go (renamed from Godeps/_workspace/src/github.com/fjl/goupnp/service_client.go)3
-rw-r--r--Godeps/_workspace/src/github.com/huin/goupnp/soap/soap.go (renamed from Godeps/_workspace/src/github.com/fjl/goupnp/soap/soap.go)0
-rw-r--r--Godeps/_workspace/src/github.com/huin/goupnp/soap/soap_test.go (renamed from Godeps/_workspace/src/github.com/fjl/goupnp/soap/soap_test.go)0
-rw-r--r--Godeps/_workspace/src/github.com/huin/goupnp/soap/types.go (renamed from Godeps/_workspace/src/github.com/fjl/goupnp/soap/types.go)0
-rw-r--r--Godeps/_workspace/src/github.com/huin/goupnp/soap/types_test.go (renamed from Godeps/_workspace/src/github.com/fjl/goupnp/soap/types_test.go)0
-rw-r--r--Godeps/_workspace/src/github.com/huin/goupnp/ssdp/registry.go (renamed from Godeps/_workspace/src/github.com/fjl/goupnp/ssdp/registry.go)2
-rw-r--r--Godeps/_workspace/src/github.com/huin/goupnp/ssdp/ssdp.go (renamed from Godeps/_workspace/src/github.com/fjl/goupnp/ssdp/ssdp.go)2
-rw-r--r--Godeps/_workspace/src/github.com/obscuren/ecies/.gitignore24
-rw-r--r--Godeps/_workspace/src/github.com/obscuren/ecies/LICENSE28
-rw-r--r--Godeps/_workspace/src/github.com/obscuren/ecies/README94
-rw-r--r--Godeps/_workspace/src/github.com/obscuren/ecies/asn1.go556
-rw-r--r--Godeps/_workspace/src/github.com/obscuren/ecies/ecies.go326
-rw-r--r--Godeps/_workspace/src/github.com/obscuren/ecies/ecies_test.go489
-rw-r--r--Godeps/_workspace/src/github.com/obscuren/ecies/params.go187
-rw-r--r--Godeps/_workspace/src/golang.org/x/crypto/ripemd160/ripemd160.go (renamed from Godeps/_workspace/src/code.google.com/p/go.crypto/ripemd160/ripemd160.go)0
-rw-r--r--Godeps/_workspace/src/golang.org/x/crypto/ripemd160/ripemd160_test.go (renamed from Godeps/_workspace/src/code.google.com/p/go.crypto/ripemd160/ripemd160_test.go)0
-rw-r--r--Godeps/_workspace/src/golang.org/x/crypto/ripemd160/ripemd160block.go (renamed from Godeps/_workspace/src/code.google.com/p/go.crypto/ripemd160/ripemd160block.go)0
-rw-r--r--Godeps/_workspace/src/golang.org/x/crypto/scrypt/scrypt.go (renamed from Godeps/_workspace/src/code.google.com/p/go.crypto/scrypt/scrypt.go)0
-rw-r--r--Godeps/_workspace/src/golang.org/x/crypto/scrypt/scrypt_test.go (renamed from Godeps/_workspace/src/code.google.com/p/go.crypto/scrypt/scrypt_test.go)0
-rw-r--r--Godeps/_workspace/src/golang.org/x/net/websocket/client.go (renamed from Godeps/_workspace/src/code.google.com/p/go.net/websocket/client.go)18
-rw-r--r--Godeps/_workspace/src/golang.org/x/net/websocket/exampledial_test.go (renamed from Godeps/_workspace/src/code.google.com/p/go.net/websocket/exampledial_test.go)2
-rw-r--r--Godeps/_workspace/src/golang.org/x/net/websocket/examplehandler_test.go (renamed from Godeps/_workspace/src/code.google.com/p/go.net/websocket/examplehandler_test.go)2
-rw-r--r--Godeps/_workspace/src/golang.org/x/net/websocket/hybi.go (renamed from Godeps/_workspace/src/code.google.com/p/go.net/websocket/hybi.go)0
-rw-r--r--Godeps/_workspace/src/golang.org/x/net/websocket/hybi_test.go (renamed from Godeps/_workspace/src/code.google.com/p/go.net/websocket/hybi_test.go)0
-rw-r--r--Godeps/_workspace/src/golang.org/x/net/websocket/server.go (renamed from Godeps/_workspace/src/code.google.com/p/go.net/websocket/server.go)0
-rw-r--r--Godeps/_workspace/src/golang.org/x/net/websocket/websocket.go (renamed from Godeps/_workspace/src/code.google.com/p/go.net/websocket/websocket.go)0
-rw-r--r--Godeps/_workspace/src/golang.org/x/net/websocket/websocket_test.go (renamed from Godeps/_workspace/src/code.google.com/p/go.net/websocket/websocket_test.go)73
-rw-r--r--README.md8
-rw-r--r--accounts/accounts_test.go6
-rw-r--r--cmd/ethereum/flags.go2
-rw-r--r--cmd/ethereum/main.go5
-rw-r--r--cmd/ethtest/main.go4
-rw-r--r--cmd/mist/assets/examples/bomb.html22
-rw-r--r--cmd/mist/assets/examples/coin.html28
-rw-r--r--cmd/mist/assets/examples/info.html4
-rw-r--r--cmd/mist/assets/ext/ethereum.js/dist/ethereum.js2
-rw-r--r--cmd/mist/assets/qml/main.qml8
-rw-r--r--cmd/mist/assets/qml/views/pending_tx.qml9
-rw-r--r--cmd/mist/flags.go3
-rw-r--r--cmd/mist/gui.go58
-rw-r--r--cmd/mist/main.go28
-rw-r--r--cmd/mist/ui_lib.go4
-rw-r--r--cmd/utils/cmd.go4
-rw-r--r--core/block_processor.go52
-rw-r--r--core/block_processor_test.go34
-rw-r--r--core/chain_manager.go42
-rw-r--r--core/error.go23
-rw-r--r--core/events.go3
-rw-r--r--core/filter.go26
-rw-r--r--core/genesis.go44
-rw-r--r--core/state_transition.go9
-rw-r--r--core/transaction_pool.go35
-rw-r--r--core/types/block.go12
-rw-r--r--crypto/crypto.go4
-rw-r--r--crypto/key_store_passphrase.go8
-rw-r--r--eth/backend.go46
-rw-r--r--eth/protocol.go2
-rw-r--r--ethutil/common.go7
-rw-r--r--ethutil/number/int.go181
-rw-r--r--ethutil/number/uint_test.go92
-rw-r--r--event/filter/eth_filter.go15
-rwxr-xr-xgocoverage.sh16
-rw-r--r--logger/types.go579
-rw-r--r--miner/miner.go4
-rw-r--r--miner/worker.go22
-rw-r--r--p2p/discover/udp.go3
-rw-r--r--p2p/handshake.go (renamed from p2p/crypto.go)137
-rw-r--r--p2p/handshake_test.go (renamed from p2p/crypto_test.go)65
-rw-r--r--p2p/message.go2
-rw-r--r--p2p/nat/natupnp.go6
-rw-r--r--p2p/peer.go264
-rw-r--r--p2p/peer_test.go105
-rw-r--r--p2p/server.go66
-rw-r--r--p2p/server_test.go12
-rw-r--r--rpc/args.go49
-rw-r--r--rpc/message.go75
-rw-r--r--rpc/packages.go234
-rw-r--r--rpc/packages_test.go37
-rw-r--r--rpc/util.go41
-rw-r--r--rpc/ws/server.go2
-rw-r--r--state/dump.go4
-rw-r--r--state/log.go11
-rw-r--r--state/state_object.go101
-rw-r--r--state/state_test.go43
-rw-r--r--state/statedb.go45
-rw-r--r--tests/vm/gh_test.go4
-rw-r--r--tests/vm/nowarn.go3
-rw-r--r--ui/filter.go4
-rw-r--r--update-license.go1
-rw-r--r--vm/environment.go5
-rw-r--r--vm/vm.go13
-rw-r--r--xeth/types.go2
-rw-r--r--xeth/xeth.go37
111 files changed, 1988 insertions, 2977 deletions
diff --git a/.travis.yml b/.travis.yml
index 2dfb7e283..5499cf257 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -6,18 +6,15 @@ before_install:
- sudo apt-get update -qq
- sudo apt-get install -yqq libgmp3-dev libreadline6-dev qt54quickcontrols qt54webengine
install:
- - go get code.google.com/p/go.tools/cmd/goimports
- - go get github.com/golang/lint/golint
+ # - go get code.google.com/p/go.tools/cmd/goimports
+ # - go get github.com/golang/lint/golint
# - 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
- go get github.com/mattn/goveralls
- - go get gopkg.in/check.v1
- - go get github.com/tools/godep
before_script:
- - godep restore
- - gofmt -l -w .
- - goimports -l -w .
- - golint .
+ # - gofmt -l -w .
+ # - goimports -l -w .
+ # - golint .
# - go vet ./...
# - go test -race ./...
script:
diff --git a/Godeps/Godeps.json b/Godeps/Godeps.json
index 831140690..9b7306530 100644
--- a/Godeps/Godeps.json
+++ b/Godeps/Godeps.json
@@ -1,6 +1,6 @@
{
"ImportPath": "github.com/ethereum/go-ethereum",
- "GoVersion": "go1.4",
+ "GoVersion": "go1.4.1",
"Packages": [
"./..."
],
@@ -16,26 +16,6 @@
"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",
"Comment": "null-15",
"Rev": "12e4b4183793ac4b061921e7980845e750679fd0"
@@ -45,21 +25,17 @@
"Rev": "5767a0dbd759d313df3f404dadb7f98d7ab51443"
},
{
- "ImportPath": "github.com/fjl/goupnp",
- "Rev": "fa95df6feb61e136b499d01711fcd410ccaf20c1"
- },
- {
"ImportPath": "github.com/howeyc/fsnotify",
"Comment": "v0.9.0-11-g6b1ef89",
"Rev": "6b1ef893dc11e0447abda6da20a5203481878dda"
},
{
- "ImportPath": "github.com/jackpal/go-nat-pmp",
- "Rev": "a45aa3d54aef73b504e15eb71bea0e5565b5e6e1"
+ "ImportPath": "github.com/huin/goupnp",
+ "Rev": "4191d8a85005844ea202fde52799681971b12dfe"
},
{
- "ImportPath": "github.com/obscuren/ecies",
- "Rev": "d899334bba7bf4a157cab19d8ad836dcb1de0c34"
+ "ImportPath": "github.com/jackpal/go-nat-pmp",
+ "Rev": "a45aa3d54aef73b504e15eb71bea0e5565b5e6e1"
},
{
"ImportPath": "github.com/obscuren/otto",
@@ -110,6 +86,18 @@
"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",
"Rev": "64131543e7896d5bcc6bd5a76287eb75ea96c673"
},
diff --git a/Godeps/_workspace/src/code.google.com/p/go.crypto/pbkdf2/pbkdf2.go b/Godeps/_workspace/src/code.google.com/p/go.crypto/pbkdf2/pbkdf2.go
deleted file mode 100644
index c02b4d5a7..000000000
--- a/Godeps/_workspace/src/code.google.com/p/go.crypto/pbkdf2/pbkdf2.go
+++ /dev/null
@@ -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]
-}
diff --git a/Godeps/_workspace/src/code.google.com/p/go.crypto/pbkdf2/pbkdf2_test.go b/Godeps/_workspace/src/code.google.com/p/go.crypto/pbkdf2/pbkdf2_test.go
deleted file mode 100644
index 137924061..000000000
--- a/Godeps/_workspace/src/code.google.com/p/go.crypto/pbkdf2/pbkdf2_test.go
+++ /dev/null
@@ -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)
-}
diff --git a/Godeps/_workspace/src/github.com/fjl/goupnp/LICENSE b/Godeps/_workspace/src/github.com/huin/goupnp/LICENSE
index 252e3d639..252e3d639 100644
--- a/Godeps/_workspace/src/github.com/fjl/goupnp/LICENSE
+++ b/Godeps/_workspace/src/github.com/huin/goupnp/LICENSE
diff --git a/Godeps/_workspace/src/github.com/fjl/goupnp/README.md b/Godeps/_workspace/src/github.com/huin/goupnp/README.md
index d464c8288..ea2c155a1 100644
--- a/Godeps/_workspace/src/github.com/fjl/goupnp/README.md
+++ b/Godeps/_workspace/src/github.com/huin/goupnp/README.md
@@ -3,7 +3,7 @@ goupnp is a UPnP client library for Go
Installation
------------
-Run `go get -u github.com/fjl/goupnp`.
+Run `go get -u github.com/huin/goupnp`.
Regenerating dcps generated source code:
----------------------------------------
diff --git a/Godeps/_workspace/src/github.com/fjl/goupnp/cmd/example_httpu_serving/example_httpu_serving.go b/Godeps/_workspace/src/github.com/huin/goupnp/cmd/example_httpu_serving/example_httpu_serving.go
index d56d39572..d9d9daa93 100644
--- a/Godeps/_workspace/src/github.com/fjl/goupnp/cmd/example_httpu_serving/example_httpu_serving.go
+++ b/Godeps/_workspace/src/github.com/huin/goupnp/cmd/example_httpu_serving/example_httpu_serving.go
@@ -4,7 +4,7 @@ import (
"log"
"net/http"
- "github.com/fjl/goupnp/httpu"
+ "github.com/huin/goupnp/httpu"
)
func main() {
diff --git a/Godeps/_workspace/src/github.com/fjl/goupnp/cmd/example_internetgateway1/example_internetgateway1.go b/Godeps/_workspace/src/github.com/huin/goupnp/cmd/example_internetgateway1/example_internetgateway1.go
index fda612500..29e8adc8b 100644
--- a/Godeps/_workspace/src/github.com/fjl/goupnp/cmd/example_internetgateway1/example_internetgateway1.go
+++ b/Godeps/_workspace/src/github.com/huin/goupnp/cmd/example_internetgateway1/example_internetgateway1.go
@@ -4,7 +4,7 @@ import (
"fmt"
"log"
- "github.com/fjl/goupnp/dcps/internetgateway1"
+ "github.com/huin/goupnp/dcps/internetgateway1"
)
func main() {
diff --git a/Godeps/_workspace/src/github.com/fjl/goupnp/dcps/internetgateway1/internetgateway1.go b/Godeps/_workspace/src/github.com/huin/goupnp/dcps/internetgateway1/internetgateway1.go
index 49659722c..be71855a9 100644
--- a/Godeps/_workspace/src/github.com/fjl/goupnp/dcps/internetgateway1/internetgateway1.go
+++ b/Godeps/_workspace/src/github.com/huin/goupnp/dcps/internetgateway1/internetgateway1.go
@@ -11,8 +11,8 @@ package internetgateway1
import (
"time"
- "github.com/fjl/goupnp"
- "github.com/fjl/goupnp/soap"
+ "github.com/huin/goupnp"
+ "github.com/huin/goupnp/soap"
)
// Hack to avoid Go complaining if time isn't used.
diff --git a/Godeps/_workspace/src/github.com/fjl/goupnp/dcps/internetgateway2/internetgateway2.go b/Godeps/_workspace/src/github.com/huin/goupnp/dcps/internetgateway2/internetgateway2.go
index cf34c61f0..a5892288e 100644
--- a/Godeps/_workspace/src/github.com/fjl/goupnp/dcps/internetgateway2/internetgateway2.go
+++ b/Godeps/_workspace/src/github.com/huin/goupnp/dcps/internetgateway2/internetgateway2.go
@@ -11,8 +11,8 @@ package internetgateway2
import (
"time"
- "github.com/fjl/goupnp"
- "github.com/fjl/goupnp/soap"
+ "github.com/huin/goupnp"
+ "github.com/huin/goupnp/soap"
)
// Hack to avoid Go complaining if time isn't used.
diff --git a/Godeps/_workspace/src/github.com/fjl/goupnp/device.go b/Godeps/_workspace/src/github.com/huin/goupnp/device.go
index 2b8e9bb07..e5b658b21 100644
--- a/Godeps/_workspace/src/github.com/fjl/goupnp/device.go
+++ b/Godeps/_workspace/src/github.com/huin/goupnp/device.go
@@ -8,8 +8,8 @@ import (
"fmt"
"net/url"
- "github.com/fjl/goupnp/scpd"
- "github.com/fjl/goupnp/soap"
+ "github.com/huin/goupnp/scpd"
+ "github.com/huin/goupnp/soap"
)
const (
diff --git a/Godeps/_workspace/src/github.com/fjl/goupnp/example/example.go b/Godeps/_workspace/src/github.com/huin/goupnp/example/example.go
index aae4c28f4..df7420226 100644
--- a/Godeps/_workspace/src/github.com/fjl/goupnp/example/example.go
+++ b/Godeps/_workspace/src/github.com/huin/goupnp/example/example.go
@@ -2,5 +2,5 @@
//
// To run examples and see the output for your local network, run the following
// command (specifically including the -v flag):
-// go test -v github.com/fjl/goupnp/example
+// go test -v github.com/huin/goupnp/example
package example
diff --git a/Godeps/_workspace/src/github.com/fjl/goupnp/example/example_test.go b/Godeps/_workspace/src/github.com/huin/goupnp/example/example_test.go
index d926a06b0..1f3667df7 100644
--- a/Godeps/_workspace/src/github.com/fjl/goupnp/example/example_test.go
+++ b/Godeps/_workspace/src/github.com/huin/goupnp/example/example_test.go
@@ -4,8 +4,8 @@ import (
"fmt"
"os"
- "github.com/fjl/goupnp"
- "github.com/fjl/goupnp/dcps/internetgateway1"
+ "github.com/huin/goupnp"
+ "github.com/huin/goupnp/dcps/internetgateway1"
)
// Use discovered WANPPPConnection1 services to find external IP addresses.
diff --git a/Godeps/_workspace/src/github.com/fjl/goupnp/gotasks/specgen_task.go b/Godeps/_workspace/src/github.com/huin/goupnp/gotasks/specgen_task.go
index 006e8fef3..0ac1d4ff3 100644
--- a/Godeps/_workspace/src/github.com/fjl/goupnp/gotasks/specgen_task.go
+++ b/Godeps/_workspace/src/github.com/huin/goupnp/gotasks/specgen_task.go
@@ -17,8 +17,8 @@ import (
"strings"
"text/template"
- "github.com/fjl/goupnp"
- "github.com/fjl/goupnp/scpd"
+ "github.com/huin/goupnp"
+ "github.com/huin/goupnp/scpd"
"github.com/huin/goutil/codegen"
"github.com/jingweno/gotask/tasking"
)
@@ -38,7 +38,7 @@ var (
// -s, --spec_filename=<upnpresources.zip>
// Path to the specification file, available from http://upnp.org/resources/upnpresources.zip
// -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
// 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) {
@@ -445,8 +445,8 @@ package {{$name}}
import (
"time"
- "github.com/fjl/goupnp"
- "github.com/fjl/goupnp/soap"
+ "github.com/huin/goupnp"
+ "github.com/huin/goupnp/soap"
)
// Hack to avoid Go complaining if time isn't used.
diff --git a/Godeps/_workspace/src/github.com/fjl/goupnp/goupnp.go b/Godeps/_workspace/src/github.com/huin/goupnp/goupnp.go
index c962fbc57..120b92444 100644
--- a/Godeps/_workspace/src/github.com/fjl/goupnp/goupnp.go
+++ b/Godeps/_workspace/src/github.com/huin/goupnp/goupnp.go
@@ -1,11 +1,11 @@
// goupnp is an implementation of a client for various UPnP services.
//
// For most uses, it is recommended to use the code-generated packages under
-// github.com/fjl/goupnp/dcps. Example use is shown at
-// http://godoc.org/github.com/fjl/goupnp/example
+// github.com/huin/goupnp/dcps. Example use is shown at
+// http://godoc.org/github.com/huin/goupnp/example
//
// 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
// UPnP example XML specifications. Not all methods will work on these clients,
@@ -20,8 +20,8 @@ import (
"net/http"
"net/url"
- "github.com/fjl/goupnp/httpu"
- "github.com/fjl/goupnp/ssdp"
+ "github.com/huin/goupnp/httpu"
+ "github.com/huin/goupnp/ssdp"
)
// ContextError is an error that wraps an error with some context information.
diff --git a/Godeps/_workspace/src/github.com/fjl/goupnp/httpu/httpu.go b/Godeps/_workspace/src/github.com/huin/goupnp/httpu/httpu.go
index 862c3def4..862c3def4 100644
--- a/Godeps/_workspace/src/github.com/fjl/goupnp/httpu/httpu.go
+++ b/Godeps/_workspace/src/github.com/huin/goupnp/httpu/httpu.go
diff --git a/Godeps/_workspace/src/github.com/fjl/goupnp/httpu/serve.go b/Godeps/_workspace/src/github.com/huin/goupnp/httpu/serve.go
index 9f67af85b..9f67af85b 100644
--- a/Godeps/_workspace/src/github.com/fjl/goupnp/httpu/serve.go
+++ b/Godeps/_workspace/src/github.com/huin/goupnp/httpu/serve.go
diff --git a/Godeps/_workspace/src/github.com/fjl/goupnp/scpd/scpd.go b/Godeps/_workspace/src/github.com/huin/goupnp/scpd/scpd.go
index c9d2e69e8..c9d2e69e8 100644
--- a/Godeps/_workspace/src/github.com/fjl/goupnp/scpd/scpd.go
+++ b/Godeps/_workspace/src/github.com/huin/goupnp/scpd/scpd.go
diff --git a/Godeps/_workspace/src/github.com/fjl/goupnp/service_client.go b/Godeps/_workspace/src/github.com/huin/goupnp/service_client.go
index 258b7593b..c0d16ce2a 100644
--- a/Godeps/_workspace/src/github.com/fjl/goupnp/service_client.go
+++ b/Godeps/_workspace/src/github.com/huin/goupnp/service_client.go
@@ -2,8 +2,7 @@ package goupnp
import (
"fmt"
-
- "github.com/fjl/goupnp/soap"
+ "github.com/huin/goupnp/soap"
)
// ServiceClient is a SOAP client, root device and the service for the SOAP
diff --git a/Godeps/_workspace/src/github.com/fjl/goupnp/soap/soap.go b/Godeps/_workspace/src/github.com/huin/goupnp/soap/soap.go
index 815610734..815610734 100644
--- a/Godeps/_workspace/src/github.com/fjl/goupnp/soap/soap.go
+++ b/Godeps/_workspace/src/github.com/huin/goupnp/soap/soap.go
diff --git a/Godeps/_workspace/src/github.com/fjl/goupnp/soap/soap_test.go b/Godeps/_workspace/src/github.com/huin/goupnp/soap/soap_test.go
index 75dbbdbf1..75dbbdbf1 100644
--- a/Godeps/_workspace/src/github.com/fjl/goupnp/soap/soap_test.go
+++ b/Godeps/_workspace/src/github.com/huin/goupnp/soap/soap_test.go
diff --git a/Godeps/_workspace/src/github.com/fjl/goupnp/soap/types.go b/Godeps/_workspace/src/github.com/huin/goupnp/soap/types.go
index cd16510e3..cd16510e3 100644
--- a/Godeps/_workspace/src/github.com/fjl/goupnp/soap/types.go
+++ b/Godeps/_workspace/src/github.com/huin/goupnp/soap/types.go
diff --git a/Godeps/_workspace/src/github.com/fjl/goupnp/soap/types_test.go b/Godeps/_workspace/src/github.com/huin/goupnp/soap/types_test.go
index da6816190..da6816190 100644
--- a/Godeps/_workspace/src/github.com/fjl/goupnp/soap/types_test.go
+++ b/Godeps/_workspace/src/github.com/huin/goupnp/soap/types_test.go
diff --git a/Godeps/_workspace/src/github.com/fjl/goupnp/ssdp/registry.go b/Godeps/_workspace/src/github.com/huin/goupnp/ssdp/registry.go
index 9e2611b7f..38d10203f 100644
--- a/Godeps/_workspace/src/github.com/fjl/goupnp/ssdp/registry.go
+++ b/Godeps/_workspace/src/github.com/huin/goupnp/ssdp/registry.go
@@ -10,7 +10,7 @@ import (
"sync"
"time"
- "github.com/fjl/goupnp/httpu"
+ "github.com/huin/goupnp/httpu"
)
const (
diff --git a/Godeps/_workspace/src/github.com/fjl/goupnp/ssdp/ssdp.go b/Godeps/_workspace/src/github.com/huin/goupnp/ssdp/ssdp.go
index 6a186afa5..8178f5d94 100644
--- a/Godeps/_workspace/src/github.com/fjl/goupnp/ssdp/ssdp.go
+++ b/Godeps/_workspace/src/github.com/huin/goupnp/ssdp/ssdp.go
@@ -8,7 +8,7 @@ import (
"strconv"
"time"
- "github.com/fjl/goupnp/httpu"
+ "github.com/huin/goupnp/httpu"
)
const (
diff --git a/Godeps/_workspace/src/github.com/obscuren/ecies/.gitignore b/Godeps/_workspace/src/github.com/obscuren/ecies/.gitignore
deleted file mode 100644
index 802b6744a..000000000
--- a/Godeps/_workspace/src/github.com/obscuren/ecies/.gitignore
+++ /dev/null
@@ -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
-
-*~
diff --git a/Godeps/_workspace/src/github.com/obscuren/ecies/LICENSE b/Godeps/_workspace/src/github.com/obscuren/ecies/LICENSE
deleted file mode 100644
index e1ed19a27..000000000
--- a/Godeps/_workspace/src/github.com/obscuren/ecies/LICENSE
+++ /dev/null
@@ -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.
diff --git a/Godeps/_workspace/src/github.com/obscuren/ecies/README b/Godeps/_workspace/src/github.com/obscuren/ecies/README
deleted file mode 100644
index 2650c7b9f..000000000
--- a/Godeps/_workspace/src/github.com/obscuren/ecies/README
+++ /dev/null
@@ -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
-
diff --git a/Godeps/_workspace/src/github.com/obscuren/ecies/asn1.go b/Godeps/_workspace/src/github.com/obscuren/ecies/asn1.go
deleted file mode 100644
index 3ef194ea0..000000000
--- a/Godeps/_workspace/src/github.com/obscuren/ecies/asn1.go
+++ /dev/null
@@ -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
-}
diff --git a/Godeps/_workspace/src/github.com/obscuren/ecies/ecies.go b/Godeps/_workspace/src/github.com/obscuren/ecies/ecies.go
deleted file mode 100644
index 0e2403d47..000000000
--- a/Godeps/_workspace/src/github.com/obscuren/ecies/ecies.go
+++ /dev/null
@@ -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
-}
diff --git a/Godeps/_workspace/src/github.com/obscuren/ecies/ecies_test.go b/Godeps/_workspace/src/github.com/obscuren/ecies/ecies_test.go
deleted file mode 100644
index 943e4488e..000000000
--- a/Godeps/_workspace/src/github.com/obscuren/ecies/ecies_test.go
+++ /dev/null
@@ -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()
- }
- }
-}
diff --git a/Godeps/_workspace/src/github.com/obscuren/ecies/params.go b/Godeps/_workspace/src/github.com/obscuren/ecies/params.go
deleted file mode 100644
index b968c7c17..000000000
--- a/Godeps/_workspace/src/github.com/obscuren/ecies/params.go
+++ /dev/null
@@ -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
- }
-}
diff --git a/Godeps/_workspace/src/code.google.com/p/go.crypto/ripemd160/ripemd160.go b/Godeps/_workspace/src/golang.org/x/crypto/ripemd160/ripemd160.go
index da690f0b9..da690f0b9 100644
--- a/Godeps/_workspace/src/code.google.com/p/go.crypto/ripemd160/ripemd160.go
+++ b/Godeps/_workspace/src/golang.org/x/crypto/ripemd160/ripemd160.go
diff --git a/Godeps/_workspace/src/code.google.com/p/go.crypto/ripemd160/ripemd160_test.go b/Godeps/_workspace/src/golang.org/x/crypto/ripemd160/ripemd160_test.go
index 5df1b2593..5df1b2593 100644
--- a/Godeps/_workspace/src/code.google.com/p/go.crypto/ripemd160/ripemd160_test.go
+++ b/Godeps/_workspace/src/golang.org/x/crypto/ripemd160/ripemd160_test.go
diff --git a/Godeps/_workspace/src/code.google.com/p/go.crypto/ripemd160/ripemd160block.go b/Godeps/_workspace/src/golang.org/x/crypto/ripemd160/ripemd160block.go
index 7bc8e6c48..7bc8e6c48 100644
--- a/Godeps/_workspace/src/code.google.com/p/go.crypto/ripemd160/ripemd160block.go
+++ b/Godeps/_workspace/src/golang.org/x/crypto/ripemd160/ripemd160block.go
diff --git a/Godeps/_workspace/src/code.google.com/p/go.crypto/scrypt/scrypt.go b/Godeps/_workspace/src/golang.org/x/crypto/scrypt/scrypt.go
index 30737b0a6..30737b0a6 100644
--- a/Godeps/_workspace/src/code.google.com/p/go.crypto/scrypt/scrypt.go
+++ b/Godeps/_workspace/src/golang.org/x/crypto/scrypt/scrypt.go
diff --git a/Godeps/_workspace/src/code.google.com/p/go.crypto/scrypt/scrypt_test.go b/Godeps/_workspace/src/golang.org/x/crypto/scrypt/scrypt_test.go
index e096c3a31..e096c3a31 100644
--- a/Godeps/_workspace/src/code.google.com/p/go.crypto/scrypt/scrypt_test.go
+++ b/Godeps/_workspace/src/golang.org/x/crypto/scrypt/scrypt_test.go
diff --git a/Godeps/_workspace/src/code.google.com/p/go.net/websocket/client.go b/Godeps/_workspace/src/golang.org/x/net/websocket/client.go
index a861bb92c..ef11a51e4 100644
--- a/Godeps/_workspace/src/code.google.com/p/go.net/websocket/client.go
+++ b/Godeps/_workspace/src/golang.org/x/net/websocket/client.go
@@ -64,6 +64,20 @@ func Dial(url_, protocol, origin string) (ws *Conn, err error) {
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.
func DialConfig(config *Config) (ws *Conn, err error) {
var client net.Conn
@@ -75,10 +89,10 @@ func DialConfig(config *Config) (ws *Conn, err error) {
}
switch config.Location.Scheme {
case "ws":
- client, err = net.Dial("tcp", config.Location.Host)
+ client, err = net.Dial("tcp", parseAuthority(config.Location))
case "wss":
- client, err = tls.Dial("tcp", config.Location.Host, config.TlsConfig)
+ client, err = tls.Dial("tcp", parseAuthority(config.Location), config.TlsConfig)
default:
err = ErrBadScheme
diff --git a/Godeps/_workspace/src/code.google.com/p/go.net/websocket/exampledial_test.go b/Godeps/_workspace/src/golang.org/x/net/websocket/exampledial_test.go
index 777a66895..72bb9d48e 100644
--- a/Godeps/_workspace/src/code.google.com/p/go.net/websocket/exampledial_test.go
+++ b/Godeps/_workspace/src/golang.org/x/net/websocket/exampledial_test.go
@@ -8,7 +8,7 @@ import (
"fmt"
"log"
- "code.google.com/p/go.net/websocket"
+ "golang.org/x/net/websocket"
)
// This example demonstrates a trivial client.
diff --git a/Godeps/_workspace/src/code.google.com/p/go.net/websocket/examplehandler_test.go b/Godeps/_workspace/src/golang.org/x/net/websocket/examplehandler_test.go
index 47b0bb9b5..f22a98fcd 100644
--- a/Godeps/_workspace/src/code.google.com/p/go.net/websocket/examplehandler_test.go
+++ b/Godeps/_workspace/src/golang.org/x/net/websocket/examplehandler_test.go
@@ -8,7 +8,7 @@ import (
"io"
"net/http"
- "code.google.com/p/go.net/websocket"
+ "golang.org/x/net/websocket"
)
// Echo the data received on the WebSocket.
diff --git a/Godeps/_workspace/src/code.google.com/p/go.net/websocket/hybi.go b/Godeps/_workspace/src/golang.org/x/net/websocket/hybi.go
index f8c0b2e29..f8c0b2e29 100644
--- a/Godeps/_workspace/src/code.google.com/p/go.net/websocket/hybi.go
+++ b/Godeps/_workspace/src/golang.org/x/net/websocket/hybi.go
diff --git a/Godeps/_workspace/src/code.google.com/p/go.net/websocket/hybi_test.go b/Godeps/_workspace/src/golang.org/x/net/websocket/hybi_test.go
index d6a19108a..d6a19108a 100644
--- a/Godeps/_workspace/src/code.google.com/p/go.net/websocket/hybi_test.go
+++ b/Godeps/_workspace/src/golang.org/x/net/websocket/hybi_test.go
diff --git a/Godeps/_workspace/src/code.google.com/p/go.net/websocket/server.go b/Godeps/_workspace/src/golang.org/x/net/websocket/server.go
index 70322133c..70322133c 100644
--- a/Godeps/_workspace/src/code.google.com/p/go.net/websocket/server.go
+++ b/Godeps/_workspace/src/golang.org/x/net/websocket/server.go
diff --git a/Godeps/_workspace/src/code.google.com/p/go.net/websocket/websocket.go b/Godeps/_workspace/src/golang.org/x/net/websocket/websocket.go
index 0f4917bf7..0f4917bf7 100644
--- a/Godeps/_workspace/src/code.google.com/p/go.net/websocket/websocket.go
+++ b/Godeps/_workspace/src/golang.org/x/net/websocket/websocket.go
diff --git a/Godeps/_workspace/src/code.google.com/p/go.net/websocket/websocket_test.go b/Godeps/_workspace/src/golang.org/x/net/websocket/websocket_test.go
index 48f14b696..a376abacf 100644
--- a/Godeps/_workspace/src/code.google.com/p/go.net/websocket/websocket_test.go
+++ b/Godeps/_workspace/src/golang.org/x/net/websocket/websocket_test.go
@@ -339,3 +339,76 @@ func TestSmallBuffer(t *testing.T) {
}
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)
+ }
+ }
+}
diff --git a/README.md b/README.md
index 6dd2182de..18392816a 100644
--- a/README.md
+++ b/README.md
@@ -2,10 +2,10 @@
Ethereum Go Client © 2014 Jeffrey Wilcke.
- | Linux | OSX | Windows
-----------|---------|-----|--------
-develop | [![Build+Status](http://build.ethdev.com/buildstatusimage?builder=Linux%20Go%20develop%20branch)](http://build.ethdev.com/builders/Linux%20Go%20develop%20branch/builds/-1) | [![Build+Status](http://build.ethdev.com/buildstatusimage?builder=Linux%20Go%20develop%20branch)](http://build.ethdev.com/builders/OSX%20Go%20develop%20branch/builds/-1) | N/A
-master | [![Build+Status](http://build.ethdev.com/buildstatusimage?builder=Linux%20Go%20master%20branch)](http://build.ethdev.com/builders/Linux%20Go%20master%20branch/builds/-1) | [![Build+Status](http://build.ethdev.com/buildstatusimage?builder=OSX%20Go%20master%20branch)](http://build.ethdev.com/builders/OSX%20Go%20master%20branch/builds/-1) | N/A
+ | Linux | OSX | Windows | Tests
+----------|---------|-----|---------|------
+develop | [![Build+Status](https://build.ethdev.com/buildstatusimage?builder=Linux%20Go%20develop%20branch)](https://build.ethdev.com/builders/Linux%20Go%20develop%20branch/builds/-1) | [![Build+Status](https://build.ethdev.com/buildstatusimage?builder=Linux%20Go%20develop%20branch)](https://build.ethdev.com/builders/OSX%20Go%20develop%20branch/builds/-1) | N/A | [![Buildr+Status](https://travis-ci.org/ethereum/go-ethereum.svg?branch=develop)](https://travis-ci.org/ethereum/go-ethereum)
+master | [![Build+Status](https://build.ethdev.com/buildstatusimage?builder=Linux%20Go%20master%20branch)](https://build.ethdev.com/builders/Linux%20Go%20master%20branch/builds/-1) | [![Build+Status](https://build.ethdev.com/buildstatusimage?builder=OSX%20Go%20master%20branch)](https://build.ethdev.com/builders/OSX%20Go%20master%20branch/builds/-1) | N/A | [![Buildr+Status](https://travis-ci.org/ethereum/go-ethereum.svg?branch=master)](https://travis-ci.org/ethereum/go-ethereum)
[![Bugs](https://badge.waffle.io/ethereum/go-ethereum.png?label=bug&title=Bugs)](https://waffle.io/ethereum/go-ethereum)
[![Stories in Ready](https://badge.waffle.io/ethereum/go-ethereum.png?label=ready&title=Ready)](https://waffle.io/ethereum/go-ethereum)
diff --git a/accounts/accounts_test.go b/accounts/accounts_test.go
index da9406ebe..30e8c6285 100644
--- a/accounts/accounts_test.go
+++ b/accounts/accounts_test.go
@@ -1,8 +1,10 @@
package accounts
import (
- "github.com/ethereum/go-ethereum/crypto"
"testing"
+
+ "github.com/ethereum/go-ethereum/crypto"
+ "github.com/ethereum/go-ethereum/crypto/randentropy"
)
func TestAccountManager(t *testing.T) {
@@ -10,7 +12,7 @@ func TestAccountManager(t *testing.T) {
am := NewAccountManager(ks)
pass := "" // not used but required by API
a1, err := am.NewAccount(pass)
- toSign := crypto.GetEntropyCSPRNG(32)
+ toSign := randentropy.GetEntropyCSPRNG(32)
_, err = am.Sign(a1, pass, toSign)
if err != nil {
t.Fatal(err)
diff --git a/cmd/ethereum/flags.go b/cmd/ethereum/flags.go
index 1e6869a69..577bee442 100644
--- a/cmd/ethereum/flags.go
+++ b/cmd/ethereum/flags.go
@@ -132,7 +132,7 @@ func Init() {
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(&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(&BootNodes, "bootnodes", "", "space-separated node URLs for discovery bootstrap")
diff --git a/cmd/ethereum/main.go b/cmd/ethereum/main.go
index 0dba462be..9c840de58 100644
--- a/cmd/ethereum/main.go
+++ b/cmd/ethereum/main.go
@@ -37,7 +37,7 @@ import (
const (
ClientIdentifier = "Ethereum(G)"
- Version = "0.8.3"
+ Version = "0.8.5"
)
var clilogger = logger.NewLogger("CLI")
@@ -67,11 +67,12 @@ func main() {
DataDir: Datadir,
LogFile: LogFile,
LogLevel: LogLevel,
+ LogFormat: LogFormat,
MaxPeers: MaxPeer,
Port: OutboundPort,
NAT: NAT,
KeyRing: KeyRing,
- Shh: SHH,
+ Shh: true,
Dial: Dial,
BootNodes: BootNodes,
NodeKey: NodeKey,
diff --git a/cmd/ethtest/main.go b/cmd/ethtest/main.go
index e1c4806ad..40874616c 100644
--- a/cmd/ethtest/main.go
+++ b/cmd/ethtest/main.go
@@ -51,8 +51,8 @@ func StateObjectFromAccount(db ethutil.Database, addr string, account Account) *
if ethutil.IsHex(account.Code) {
account.Code = account.Code[2:]
}
- obj.Code = ethutil.Hex2Bytes(account.Code)
- obj.Nonce = ethutil.Big(account.Nonce).Uint64()
+ obj.SetCode(ethutil.Hex2Bytes(account.Code))
+ obj.SetNonce(ethutil.Big(account.Nonce).Uint64())
return obj
}
diff --git a/cmd/mist/assets/examples/bomb.html b/cmd/mist/assets/examples/bomb.html
new file mode 100644
index 000000000..62540f9bb
--- /dev/null
+++ b/cmd/mist/assets/examples/bomb.html
@@ -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>
diff --git a/cmd/mist/assets/examples/coin.html b/cmd/mist/assets/examples/coin.html
index ca7a9c0dd..18a6811d7 100644
--- a/cmd/mist/assets/examples/coin.html
+++ b/cmd/mist/assets/examples/coin.html
@@ -14,8 +14,9 @@
</div>
<div>
- <span class="amount">Amount:</span>
+ <span>Address:</span>
<input type="text" id="address" style="width:200px">
+ <span>Amount:</span>
<input type="text" id="amount" style="width:200px">
<button onclick="transact()">Send</button>
</div>
@@ -58,7 +59,7 @@
}],
"outputs": []
}, {
- "name":"received",
+ "name":"Changed",
"type":"event",
"inputs": [
{"name":"from","type":"address","indexed":true},
@@ -69,23 +70,14 @@
var address = localStorage.getItem("address");
// deploy if not exist
if (address == null) {
- var code = "0x60056013565b61012b806100346000396000f35b6103e8600033600160a060020a0316600052602052604060002081905550560060e060020a6000350480637bb98a681461002b578063d0679d3414610039578063e3d670d71461004d57005b610033610126565b60006000f35b610047600435602435610062565b60006000f35b610058600435610104565b8060005260206000f35b80600033600160a060020a0316600052602052604060002054101561008657610100565b80600033600160a060020a0316600052602052604060002090815403908190555080600083600160a060020a0316600052602052604060002090815401908190555033600160a060020a0316600052806020527ff11e547d796cc64acdf758e7cee90439494fd886a19159454aa61e473fdbafef60406000a15b5050565b6000600082600160a060020a03166000526020526040600020549050919050565b5b60008156";
+ var code = "0x60056013565b61014f8061003a6000396000f35b620f42406000600033600160a060020a0316815260200190815260200160002081905550560060e060020a600035048063d0679d3414610020578063e3d670d71461003457005b61002e600435602435610049565b60006000f35b61003f600435610129565b8060005260206000f35b806000600033600160a060020a03168152602001908152602001600020541061007157610076565b610125565b806000600033600160a060020a03168152602001908152602001600020908154039081905550806000600084600160a060020a031681526020019081526020016000209081540190819055508033600160a060020a03167fb52dda022b6c1a1f40905a85f257f689aa5d69d850e49cf939d688fbe5af594660006000a38082600160a060020a03167fb52dda022b6c1a1f40905a85f257f689aa5d69d850e49cf939d688fbe5af594660006000a35b5050565b60006000600083600160a060020a0316815260200190815260200160002054905091905056";
address = web3.eth.transact({data: code});
localStorage.setItem("address", address);
}
- document.querySelector("#contract_addr").innerHTML = address.toUpperCase();
+ document.querySelector("#contract_addr").innerHTML = address;
var contract = web3.eth.contract(address, desc);
- contract.received({from: eth.coinbase}).changed(function() {
- refresh();
- });
-
- var ev = contract.SingleTransact({})
- ev.watch(function(log) {
- someElement.innerHTML += "tnaheousnthaoeu";
- });
-
- eth.watch('chain').changed(function() {
+ contract.Changed({from: eth.coinbase}).changed(function() {
refresh();
});
@@ -98,7 +90,7 @@
var storage = eth.storageAt(address);
table.innerHTML = "";
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 );
+ console.log("transact: ", to, " => ", value)
contract.send( to, value );
}
@@ -126,7 +119,7 @@ contract JevCoin {
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)
{
if( balances[msg.sender] < value ) return;
@@ -134,7 +127,8 @@ contract JevCoin {
balances[msg.sender] -= value;
balances[to] += value;
- changed(msg.sender, to);
+ Changed(msg.sender, value);
+ Changed(to, value);
}
function balance(address who) constant returns(uint t)
diff --git a/cmd/mist/assets/examples/info.html b/cmd/mist/assets/examples/info.html
index d8816b19f..2a405c280 100644
--- a/cmd/mist/assets/examples/info.html
+++ b/cmd/mist/assets/examples/info.html
@@ -71,6 +71,10 @@
document.querySelector("#gas_price").innerHTML = eth.gasPrice;
document.querySelector("#mining").innerHTML = eth.mining;
document.querySelector("#listening").innerHTML = eth.listening;
+ eth.watch('chain').changed(function() {
+ document.querySelector("#number").innerHTML = eth.number;
+ });
+
</script>
</html>
diff --git a/cmd/mist/assets/ext/ethereum.js/dist/ethereum.js b/cmd/mist/assets/ext/ethereum.js/dist/ethereum.js
index d0e9d3cb7..83b598b3f 100644
--- a/cmd/mist/assets/ext/ethereum.js/dist/ethereum.js
+++ b/cmd/mist/assets/ext/ethereum.js/dist/ethereum.js
@@ -1417,6 +1417,8 @@ var ethMethods = function () {
var methods = [
{ name: 'balanceAt', call: 'eth_balanceAt' },
+ { name: 'register', call: 'eth_register' },
+ { name: 'unregister', call: 'eth_unregister' },
{ name: 'stateAt', call: 'eth_stateAt' },
{ name: 'storageAt', call: 'eth_storageAt' },
{ name: 'countAt', call: 'eth_countAt'},
diff --git a/cmd/mist/assets/qml/main.qml b/cmd/mist/assets/qml/main.qml
index 3c5772d84..1f7fcbec6 100644
--- a/cmd/mist/assets/qml/main.qml
+++ b/cmd/mist/assets/qml/main.qml
@@ -256,6 +256,7 @@ ApplicationWindow {
}
}
}
+
}
property var blockModel: ListModel {
@@ -895,7 +896,7 @@ ApplicationWindow {
}
function setWalletValue(value) {
- walletValueLabel.text = value
+ //walletValueLabel.text = value
}
function loadPlugin(name) {
@@ -947,7 +948,8 @@ ApplicationWindow {
model: peerModel
TableViewColumn{width: 180; role: "addr" ; title: "Remote Address" }
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.topMargin: 30
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"
}
}
diff --git a/cmd/mist/assets/qml/views/pending_tx.qml b/cmd/mist/assets/qml/views/pending_tx.qml
index 4442a69db..3dcedeff2 100644
--- a/cmd/mist/assets/qml/views/pending_tx.qml
+++ b/cmd/mist/assets/qml/views/pending_tx.qml
@@ -41,4 +41,13 @@ Rectangle {
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;
+ }
+ }
+ }
}
diff --git a/cmd/mist/flags.go b/cmd/mist/flags.go
index eb280f71b..d9487de9e 100644
--- a/cmd/mist/flags.go
+++ b/cmd/mist/flags.go
@@ -63,6 +63,7 @@ var (
DebugFile string
LogLevel int
VmType int
+ MinerThreads int
)
// flags specific to gui client
@@ -137,6 +138,8 @@ func Init() {
flag.StringVar(&BootNodes, "bootnodes", "", "space-separated node URLs for discovery bootstrap")
flag.IntVar(&MaxPeer, "maxpeer", 30, "maximum desired peers")
+ flag.IntVar(&MinerThreads, "minerthreads", runtime.NumCPU(), "number of miner threads")
+
flag.Parse()
var err error
diff --git a/cmd/mist/gui.go b/cmd/mist/gui.go
index 9ce6ba650..4af0cff43 100644
--- a/cmd/mist/gui.go
+++ b/cmd/mist/gui.go
@@ -131,6 +131,7 @@ func (gui *Gui) Start(assetPath string) {
context.SetVar("gui", gui)
context.SetVar("eth", gui.uiLib)
context.SetVar("shh", gui.whisper)
+ //clipboard.SetQMLClipboard(context)
win, err := gui.showWallet(context)
if err != nil {
@@ -386,16 +387,11 @@ func (gui *Gui) update() {
generalUpdateTicker := time.NewTicker(500 * time.Millisecond)
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")
miningLabel := gui.getObjectByName("miningLabel")
events := gui.eth.EventMux().Subscribe(
- //eth.PeerListEvent{},
- core.NewBlockEvent{},
+ core.ChainEvent{},
core.TxPreEvent{},
core.TxPostEvent{},
)
@@ -408,41 +404,13 @@ func (gui *Gui) update() {
return
}
switch ev := ev.(type) {
- case core.NewBlockEvent:
+ case core.ChainEvent:
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:
- tx := 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)
+ gui.insertTransaction("pre", ev.Tx)
case core.TxPostEvent:
- tx := 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)
+ gui.getObjectByName("pendingTxView").Call("removeTx", xeth.NewTx(ev.Tx))
}
case <-peerUpdateTicker.C:
@@ -453,19 +421,6 @@ func (gui *Gui) update() {
lastBlockLabel.Set("text", statusText)
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:
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
@@ -513,6 +468,7 @@ func (gui *Gui) setPeerInfo() {
qpeers[i] = &qmlpeer{
NodeID: p.ID().String(),
Addr: p.RemoteAddr().String(),
+ Name: p.Name(),
Caps: fmt.Sprint(p.Caps()),
}
}
diff --git a/cmd/mist/main.go b/cmd/mist/main.go
index 32222fbef..ad6eb5bec 100644
--- a/cmd/mist/main.go
+++ b/cmd/mist/main.go
@@ -36,7 +36,7 @@ import (
const (
ClientIdentifier = "Mist"
- Version = "0.8.3"
+ Version = "0.8.5"
)
var ethereum *eth.Ethereum
@@ -52,18 +52,20 @@ func run() error {
config := utils.InitConfig(VmType, ConfigFile, Datadir, "ETH")
ethereum, err := eth.New(&eth.Config{
- Name: p2p.MakeName(ClientIdentifier, Version),
- KeyStore: KeyStore,
- DataDir: Datadir,
- LogFile: LogFile,
- LogLevel: LogLevel,
- MaxPeers: MaxPeer,
- Port: OutboundPort,
- NAT: NAT,
- BootNodes: BootNodes,
- NodeKey: NodeKey,
- KeyRing: KeyRing,
- Dial: true,
+ Name: p2p.MakeName(ClientIdentifier, Version),
+ KeyStore: KeyStore,
+ DataDir: Datadir,
+ LogFile: LogFile,
+ LogLevel: LogLevel,
+ MaxPeers: MaxPeer,
+ Port: OutboundPort,
+ NAT: NAT,
+ Shh: true,
+ BootNodes: BootNodes,
+ NodeKey: NodeKey,
+ KeyRing: KeyRing,
+ Dial: true,
+ MinerThreads: MinerThreads,
})
if err != nil {
mainlogger.Fatalln(err)
diff --git a/cmd/mist/ui_lib.go b/cmd/mist/ui_lib.go
index 1a4d21012..4fa6e8e55 100644
--- a/cmd/mist/ui_lib.go
+++ b/cmd/mist/ui_lib.go
@@ -146,8 +146,8 @@ func (ui *UiLib) AssetPath(p string) string {
func (self *UiLib) StartDbWithContractAndData(contractHash, data string) {
dbWindow := NewDebuggerWindow(self)
object := self.eth.ChainManager().State().GetStateObject(ethutil.Hex2Bytes(contractHash))
- if len(object.Code) > 0 {
- dbWindow.SetCode(ethutil.Bytes2Hex(object.Code))
+ if len(object.Code()) > 0 {
+ dbWindow.SetCode(ethutil.Bytes2Hex(object.Code()))
}
dbWindow.SetData(data)
diff --git a/cmd/utils/cmd.go b/cmd/utils/cmd.go
index ecb847fc3..bc8fafafb 100644
--- a/cmd/utils/cmd.go
+++ b/cmd/utils/cmd.go
@@ -225,7 +225,7 @@ func StartMining(ethereum *eth.Ethereum) bool {
go func() {
clilogger.Infoln("Start mining")
if gminer == nil {
- gminer = miner.New(addr, ethereum)
+ gminer = miner.New(addr, ethereum, 4)
}
gminer.Start()
}()
@@ -272,7 +272,7 @@ func BlockDo(ethereum *eth.Ethereum, hash []byte) error {
parent := ethereum.ChainManager().GetBlock(block.ParentHash())
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 {
return err
}
diff --git a/core/block_processor.go b/core/block_processor.go
index 893c586dd..fd591a29d 100644
--- a/core/block_processor.go
+++ b/core/block_processor.go
@@ -60,12 +60,12 @@ func NewBlockProcessor(db ethutil.Database, txpool *TxPool, chainManager *ChainM
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.SetGasPool(CalcGasLimit(parent, block))
// 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 {
return nil, err
}
@@ -73,38 +73,40 @@ func (sm *BlockProcessor) TransitionState(statedb *state.StateDB, parent, block
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
- state.EmptyLogs()
+ statedb.EmptyLogs()
txGas := new(big.Int).Set(tx.Gas())
- cb := state.GetStateObject(coinbase.Address())
- st := NewStateTransition(NewEnv(state, self.bc, tx, block), tx, cb)
+ cb := statedb.GetStateObject(coinbase.Address())
+ st := NewStateTransition(NewEnv(statedb, self.bc, tx, block), tx, cb)
_, err := st.TransitionState()
+ if err != nil && (IsNonceErr(err) || state.IsGasLimitErr(err)) {
+ return nil, nil, err
+ }
txGas.Sub(txGas, st.gas)
// Update the state with pending changes
- state.Update(txGas)
+ statedb.Update(txGas)
cumulative := new(big.Int).Set(usedGas.Add(usedGas, txGas))
- receipt := types.NewReceipt(state.Root(), cumulative)
- receipt.SetLogs(state.Logs())
+ receipt := types.NewReceipt(statedb.Root(), cumulative)
+ receipt.SetLogs(statedb.Logs())
receipt.Bloom = types.CreateBloom(types.Receipts{receipt})
chainlogger.Debugln(receipt)
// Notify all subscribers
if !transientProcess {
go self.eventMux.Post(TxPostEvent{tx})
+ go self.eventMux.Post(statedb.Logs())
}
- go self.eventMux.Post(state.Logs())
-
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 (
receipts types.Receipts
handled, unhandled types.Transactions
@@ -115,12 +117,12 @@ func (self *BlockProcessor) ApplyTransactions(coinbase *state.StateObject, state
)
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 {
switch {
case IsNonceErr(err):
return nil, nil, nil, nil, err
- case IsGasLimitErr(err):
+ case state.IsGasLimitErr(err):
return nil, nil, nil, nil, err
default:
statelogger.Infoln(err)
@@ -176,7 +178,7 @@ func (sm *BlockProcessor) processWithParent(block, parent *types.Block) (td *big
return
}
- receipts, err := sm.TransitionState(state, parent, block)
+ receipts, err := sm.TransitionState(state, parent, block, false)
if err != nil {
return
}
@@ -250,7 +252,11 @@ func (sm *BlockProcessor) ValidateBlock(block, parent *types.Block) error {
}
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
@@ -289,16 +295,13 @@ func (sm *BlockProcessor) AccumulateRewards(statedb *state.StateDB, block, paren
r := new(big.Int)
r.Mul(BlockReward, big.NewInt(15)).Div(r, big.NewInt(16))
- uncleAccount := statedb.GetAccount(uncle.Coinbase)
- uncleAccount.AddAmount(r)
+ statedb.AddBalance(uncle.Coinbase, r)
reward.Add(reward, new(big.Int).Div(BlockReward, big.NewInt(32)))
}
// Get the account associated with the coinbase
- account := statedb.GetAccount(block.Header().Coinbase)
- // Reward amount of ether to the coinbase address
- account.AddAmount(reward)
+ statedb.AddBalance(block.Header().Coinbase, reward)
return nil
}
@@ -312,13 +315,10 @@ func (sm *BlockProcessor) GetLogs(block *types.Block) (logs state.Logs, err erro
var (
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)
+ sm.TransitionState(state, parent, block, true)
sm.AccumulateRewards(state, block, parent)
return state.Logs(), nil
diff --git a/core/block_processor_test.go b/core/block_processor_test.go
new file mode 100644
index 000000000..35aeaa714
--- /dev/null
+++ b/core/block_processor_test.go
@@ -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")
+ }
+}
diff --git a/core/chain_manager.go b/core/chain_manager.go
index c28e901c6..9ef091c3c 100644
--- a/core/chain_manager.go
+++ b/core/chain_manager.go
@@ -79,6 +79,7 @@ type ChainManager struct {
genesisBlock *types.Block
// Last known total difficulty
mu sync.RWMutex
+ tsmu sync.RWMutex
td *big.Int
currentBlock *types.Block
lastBlockHash []byte
@@ -86,6 +87,14 @@ type ChainManager struct {
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 {
self.mu.RLock()
defer self.mu.RUnlock()
@@ -107,14 +116,6 @@ func (self *ChainManager) CurrentBlock() *types.Block {
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) {
self.mu.RLock()
defer self.mu.RUnlock()
@@ -131,9 +132,16 @@ func (self *ChainManager) State() *state.StateDB {
}
func (self *ChainManager) TransState() *state.StateDB {
+ self.tsmu.RLock()
+ defer self.tsmu.RUnlock()
+
return self.transState
}
+func (self *ChainManager) setTransState(statedb *state.StateDB) {
+ self.transState = statedb
+}
+
func (bc *ChainManager) setLastBlock() {
data, _ := bc.db.Get([]byte("LastBlock"))
if len(data) != 0 {
@@ -260,6 +268,7 @@ func (self *ChainManager) GetBlockHashesFromHash(hash []byte, max uint64) (chain
break
}
}
+ fmt.Printf("get hash %x (%d)\n", hash, len(chain))
return
}
@@ -350,6 +359,9 @@ func (bc *ChainManager) Stop() {
}
func (self *ChainManager) InsertChain(chain types.Blocks) error {
+ self.tsmu.Lock()
+ defer self.tsmu.Unlock()
+
for _, block := range chain {
td, err := self.processor.Process(block)
if err != nil {
@@ -365,6 +377,7 @@ func (self *ChainManager) InsertChain(chain types.Blocks) error {
}
block.Td = td
+ var chain, split bool
self.mu.Lock()
{
self.write(block)
@@ -372,18 +385,25 @@ func (self *ChainManager) InsertChain(chain types.Blocks) error {
if td.Cmp(self.td) > 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)
+ split = true
}
self.setTotalDifficulty(td)
self.insert(block)
- self.transState = state.New(cblock.Root(), self.db)
- self.eventMux.Post(ChainEvent{block, td})
+ chain = true
}
}
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
diff --git a/core/error.go b/core/error.go
index 11d8c1653..e86bacb2d 100644
--- a/core/error.go
+++ b/core/error.go
@@ -1,10 +1,16 @@
package core
import (
+ "errors"
"fmt"
"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
// by the block manager
type ParentErr struct {
@@ -62,23 +68,6 @@ func IsValidationErr(err error) bool {
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 {
Message string
Is, Exp uint64
diff --git a/core/events.go b/core/events.go
index fe106da49..4cbbc609c 100644
--- a/core/events.go
+++ b/core/events.go
@@ -13,3 +13,6 @@ type NewBlockEvent struct{ Block *types.Block }
// NewMinedBlockEvent is posted when a block has been imported.
type NewMinedBlockEvent struct{ Block *types.Block }
+
+// ChainSplit is posted when a new head is detected
+type ChainSplitEvent struct{ Block *types.Block }
diff --git a/core/filter.go b/core/filter.go
index 234fa3316..cdf7b282d 100644
--- a/core/filter.go
+++ b/core/filter.go
@@ -16,7 +16,7 @@ type FilterOptions struct {
Earliest int64
Latest int64
- Address []byte
+ Address [][]byte
Topics [][]byte
Skip int
@@ -29,7 +29,7 @@ type Filter struct {
earliest int64
latest int64
skip int
- address []byte
+ address [][]byte
max int
topics [][]byte
@@ -65,7 +65,7 @@ func (self *Filter) SetLatestBlock(latest int64) {
self.latest = latest
}
-func (self *Filter) SetAddress(addr []byte) {
+func (self *Filter) SetAddress(addr [][]byte) {
self.address = addr
}
@@ -111,14 +111,14 @@ func (self *Filter) Find() state.Logs {
// current parameters
if self.bloomFilter(block) {
// Get the logs of the block
- logs, err := self.eth.BlockProcessor().GetLogs(block)
+ unfiltered, err := self.eth.BlockProcessor().GetLogs(block)
if err != nil {
chainlogger.Warnln("err: filter get logs ", err)
break
}
- logs = append(logs, self.FilterLogs(logs)...)
+ logs = append(logs, self.FilterLogs(unfiltered)...)
}
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
Logs:
for _, log := range logs {
- if !bytes.Equal(self.address, log.Address()) {
+ if !includes(self.address, log.Address()) {
continue
}
@@ -163,8 +163,18 @@ Logs:
}
func (self *Filter) bloomFilter(block *types.Block) bool {
- if len(self.address) > 0 && !types.BloomLookup(block.Bloom(), self.address) {
- return false
+ if len(self.address) > 0 {
+ 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 {
diff --git a/core/genesis.go b/core/genesis.go
index c870ce61e..75b4fc100 100644
--- a/core/genesis.go
+++ b/core/genesis.go
@@ -1,7 +1,10 @@
package core
import (
+ "encoding/json"
+ "fmt"
"math/big"
+ "os"
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/crypto"
@@ -31,24 +34,39 @@ func GenesisBlock(db ethutil.Database) *types.Block {
genesis.SetTransactions(types.Transactions{})
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)
- for _, addr := range []string{
- "dbdbdb2cbd23b783741e8d7fcf51e459b497e4a6",
- "e4157b34ea9615cfbde6b4fda419828124b70c78",
- "b9c015918bdaba24b4ff057a92a3873d6eb201be",
- "6c386a4b26f73c802f34673f7248bb118f97424a",
- "cd2a3d9f938e13cd947ec05abc7fe734df8dd826",
- "2ef47100e0787b915105fd5e3f4ff6752079d5cb",
- "e6716f9544a56c530d868e4bfbacb172315bdead",
- "1a26338f0d905e295fccb71fa9ea849ffa12aaf4",
- } {
+ for addr, account := range accounts {
codedAddr := ethutil.Hex2Bytes(addr)
- account := statedb.GetAccount(codedAddr)
- account.SetBalance(ethutil.Big("1606938044258990275541962092341162602522202993782792835301376")) //ethutil.BigPow(2, 200)
- statedb.UpdateStateObject(account)
+ accountState := statedb.GetAccount(codedAddr)
+ accountState.SetBalance(ethutil.Big(account.Balance))
+ statedb.UpdateStateObject(accountState)
}
statedb.Sync()
genesis.Header().Root = statedb.Root()
+ fmt.Printf("+++ genesis +++\nRoot: %x\nHash: %x\n", genesis.Header().Root, genesis.Hash())
+
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"}
+}`)
diff --git a/core/state_transition.go b/core/state_transition.go
index 33dd45f02..36ffa23d9 100644
--- a/core/state_transition.go
+++ b/core/state_transition.go
@@ -138,8 +138,8 @@ func (self *StateTransition) preCheck() (err error) {
)
// Make sure this transaction's nonce is correct
- if sender.Nonce != msg.Nonce() {
- return NonceError(msg.Nonce(), sender.Nonce)
+ if sender.Nonce() != msg.Nonce() {
+ return NonceError(msg.Nonce(), sender.Nonce())
}
// Pre-pay gas / Buy gas of the coinbase account
@@ -166,7 +166,8 @@ func (self *StateTransition) TransitionState() (ret []byte, err error) {
defer self.RefundGas()
// Increment the nonce for the next transaction
- sender.Nonce += 1
+ self.state.SetNonce(sender.Address(), sender.Nonce()+1)
+ //sender.Nonce += 1
// Transaction gas
if err = self.UseGas(vm.GasTx); err != nil {
@@ -241,7 +242,7 @@ func MakeContract(msg Message, state *state.StateDB) *state.StateObject {
addr := AddressFromMessage(msg)
contract := state.GetOrNewStateObject(addr)
- contract.InitCode = msg.Data()
+ contract.SetInitCode(msg.Data())
return contract
}
diff --git a/core/transaction_pool.go b/core/transaction_pool.go
index 7a901fcae..050cff3d8 100644
--- a/core/transaction_pool.go
+++ b/core/transaction_pool.go
@@ -3,6 +3,7 @@ package core
import (
"errors"
"fmt"
+ "sync"
"github.com/ethereum/go-ethereum/core/types"
"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
// independently read without needing access to the actual pool.
type TxPool struct {
+ mu sync.RWMutex
// Queueing channel for reading and writing incoming
// transactions to
queueChan chan *types.Transaction
@@ -97,7 +99,7 @@ func (self *TxPool) addTx(tx *types.Transaction) {
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 {
return fmt.Errorf("Known transaction (%x)", tx.Hash()[0:4])
}
@@ -128,17 +130,28 @@ func (self *TxPool) Size() int {
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) {
+ self.mu.Lock()
+ defer self.mu.Unlock()
+
for _, tx := range txs {
- if err := self.Add(tx); err != nil {
- txplogger.Infoln(err)
+ if err := self.add(tx); err != nil {
+ txplogger.Debugln(err)
} 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) {
+ self.mu.RLock()
+ defer self.mu.RUnlock()
+
txs = make(types.Transactions, self.Size())
i := 0
for _, tx := range self.txs {
@@ -150,30 +163,32 @@ func (self *TxPool) GetTransactions() (txs types.Transactions) {
}
func (pool *TxPool) RemoveInvalid(query StateQuery) {
+ pool.mu.Lock()
+
var removedTxs types.Transactions
for _, tx := range pool.txs {
sender := query.GetAccount(tx.From())
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)
}
}
+ pool.mu.Unlock()
pool.RemoveSet(removedTxs)
}
func (self *TxPool) RemoveSet(txs types.Transactions) {
+ self.mu.Lock()
+ defer self.mu.Unlock()
+
for _, tx := range txs {
delete(self.txs, string(tx.Hash()))
}
}
-func (pool *TxPool) Flush() []*types.Transaction {
- txList := pool.GetTransactions()
+func (pool *TxPool) Flush() {
pool.txs = make(map[string]*types.Transaction)
-
- return txList
}
func (pool *TxPool) Start() {
diff --git a/core/types/block.go b/core/types/block.go
index fa28f5cc7..d57de1311 100644
--- a/core/types/block.go
+++ b/core/types/block.go
@@ -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) SetRoot(root []byte) { self.header.Root = root }
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
func (self *Block) Difficulty() *big.Int { return self.header.Difficulty }
diff --git a/crypto/crypto.go b/crypto/crypto.go
index e59250eb2..90e2c8939 100644
--- a/crypto/crypto.go
+++ b/crypto/crypto.go
@@ -16,12 +16,12 @@ import (
"errors"
"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/secp256k1"
"github.com/ethereum/go-ethereum/crypto/sha3"
"github.com/ethereum/go-ethereum/ethutil"
+ "golang.org/x/crypto/pbkdf2"
+ "golang.org/x/crypto/ripemd160"
)
func init() {
diff --git a/crypto/key_store_passphrase.go b/crypto/key_store_passphrase.go
index 74408f874..7d21b6604 100644
--- a/crypto/key_store_passphrase.go
+++ b/crypto/key_store_passphrase.go
@@ -20,6 +20,7 @@
* @date 2015
*
*/
+
/*
This key store behaves as KeyStorePlain with the difference that
@@ -64,17 +65,18 @@ package crypto
import (
"bytes"
- "code.google.com/p/go-uuid/uuid"
- "code.google.com/p/go.crypto/scrypt"
"crypto/aes"
"crypto/cipher"
"encoding/hex"
"encoding/json"
"errors"
- "github.com/ethereum/go-ethereum/crypto/randentropy"
"io"
"os"
"path"
+
+ "code.google.com/p/go-uuid/uuid"
+ "github.com/ethereum/go-ethereum/crypto/randentropy"
+ "golang.org/x/crypto/scrypt"
)
const (
diff --git a/eth/backend.go b/eth/backend.go
index 690c7136d..0e5d24429 100644
--- a/eth/backend.go
+++ b/eth/backend.go
@@ -3,6 +3,8 @@ package eth
import (
"crypto/ecdsa"
"fmt"
+ "io/ioutil"
+ "path"
"strings"
"github.com/ethereum/go-ethereum/core"
@@ -25,7 +27,10 @@ var (
jsonlogger = ethlogger.NewJsonLogger()
defaultBootNodes = []*discover.Node{
+ // ETH/DEV cmd/bootnode
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
Dial bool
+ MinerThreads int
+
KeyManager *crypto.KeyManager
}
@@ -75,6 +82,27 @@ func (cfg *Config) parseBootNodes() []*discover.Node {
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 {
// Channel for shutting down the ethereum
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.chainManager.SetProcessor(eth.blockProcessor)
eth.whisper = whisper.New()
- eth.miner = miner.New(keyManager.Address(), eth)
+ eth.miner = miner.New(keyManager.Address(), eth, config.MinerThreads)
hasBlock := eth.chainManager.HasBlock
insertChain := eth.chainManager.InsertChain
eth.blockPool = NewBlockPool(hasBlock, insertChain, ezp.Verify)
+ netprv, err := config.nodeKey()
+ if err != nil {
+ return nil, err
+ }
ethProto := EthProtocol(eth.txPool, eth.chainManager, eth.blockPool)
- protocols := []p2p.Protocol{ethProto, eth.whisper.Protocol()}
- netprv := config.NodeKey
- if netprv == nil {
- if netprv, err = crypto.GenerateKey(); err != nil {
- return nil, fmt.Errorf("could not generate server key: %v", err)
- }
+ protocols := []p2p.Protocol{ethProto}
+ if config.Shh {
+ protocols = append(protocols, eth.whisper.Protocol())
}
+
eth.net = &p2p.Server{
PrivateKey: netprv,
Name: config.Name,
@@ -205,9 +235,7 @@ func (s *Ethereum) Coinbase() []byte { return nil } // TODO
func (s *Ethereum) Start() error {
jsonlogger.LogJson(&ethlogger.LogStarting{
ClientString: s.net.Name,
- Coinbase: ethutil.Bytes2Hex(s.KeyManager().Address()),
ProtocolVersion: ProtocolVersion,
- LogEvent: ethlogger.LogEvent{Guid: ethutil.Bytes2Hex(crypto.FromECDSAPub(&s.net.PrivateKey.PublicKey))},
})
err := s.net.Start()
diff --git a/eth/protocol.go b/eth/protocol.go
index fb694c877..8221c1b29 100644
--- a/eth/protocol.go
+++ b/eth/protocol.go
@@ -13,7 +13,7 @@ import (
)
const (
- ProtocolVersion = 52
+ ProtocolVersion = 54
NetworkId = 0
ProtocolLength = uint64(8)
ProtocolMaxMsgSize = 10 * 1024 * 1024
diff --git a/ethutil/common.go b/ethutil/common.go
index 271c56fd5..2ef2440c7 100644
--- a/ethutil/common.go
+++ b/ethutil/common.go
@@ -4,6 +4,7 @@ import (
"fmt"
"math/big"
"runtime"
+ "time"
)
func IsWindows() bool {
@@ -86,3 +87,9 @@ var (
Big256 = big.NewInt(0xff)
Big257 = big.NewInt(257)
)
+
+func Bench(pre string, cb func()) {
+ start := time.Now()
+ cb()
+ fmt.Println(pre, ": took:", time.Since(start))
+}
diff --git a/ethutil/number/int.go b/ethutil/number/int.go
new file mode 100644
index 000000000..9a41fe3e5
--- /dev/null
+++ b/ethutil/number/int.go
@@ -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
+)
diff --git a/ethutil/number/uint_test.go b/ethutil/number/uint_test.go
new file mode 100644
index 000000000..c42989465
--- /dev/null
+++ b/ethutil/number/uint_test.go
@@ -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)
+ }
+}
diff --git a/event/filter/eth_filter.go b/event/filter/eth_filter.go
index 295fcfbbf..73d2cd935 100644
--- a/event/filter/eth_filter.go
+++ b/event/filter/eth_filter.go
@@ -3,6 +3,7 @@ package filter
// TODO make use of the generic filtering system
import (
+ "fmt"
"sync"
"github.com/ethereum/go-ethereum/core"
@@ -37,17 +38,18 @@ func (self *FilterManager) Stop() {
func (self *FilterManager) InstallFilter(filter *core.Filter) (id int) {
self.filterMu.Lock()
+ defer self.filterMu.Unlock()
id = self.filterId
self.filters[id] = filter
self.filterId++
- self.filterMu.Unlock()
+
return id
}
func (self *FilterManager) UninstallFilter(id int) {
self.filterMu.Lock()
+ defer self.filterMu.Unlock()
delete(self.filters, id)
- self.filterMu.Unlock()
}
// GetFilter retrieves a filter installed using InstallFilter.
@@ -60,7 +62,10 @@ func (self *FilterManager) GetFilter(id int) *core.Filter {
func (self *FilterManager) filterLoop() {
// 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:
for {
@@ -69,7 +74,8 @@ out:
break out
case event := <-events.Chan():
switch event := event.(type) {
- case core.NewBlockEvent:
+ case core.ChainEvent:
+ fmt.Println("filter start")
self.filterMu.RLock()
for _, filter := range self.filters {
if filter.BlockCallback != nil {
@@ -77,6 +83,7 @@ out:
}
}
self.filterMu.RUnlock()
+ fmt.Println("filter stop")
case core.PendingBlockEvent:
self.filterMu.RLock()
diff --git a/gocoverage.sh b/gocoverage.sh
index 4245e3901..5479d8d3b 100755
--- a/gocoverage.sh
+++ b/gocoverage.sh
@@ -1,11 +1,16 @@
#!/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
-# 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
# 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
if ls $dir/*.go &> /dev/null; then
# echo $dir
- if [[ $dir != "./tests/vm" ]]
+ if [[ $dir != "./tests/vm" && $dir != "." ]]
then
go test -covermode=count -coverprofile=$dir/profile.tmp $dir
fi
@@ -24,6 +29,3 @@ if ls $dir/*.go &> /dev/null; then
fi
fi
done
-
-go tool cover -func profile.cov
-
diff --git a/logger/types.go b/logger/types.go
index f8dcb4e78..7ab4a2b8c 100644
--- a/logger/types.go
+++ b/logger/types.go
@@ -7,7 +7,6 @@ import (
type utctime8601 struct{}
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
}
@@ -16,14 +15,13 @@ type JsonLog interface {
}
type LogEvent struct {
- Guid string `json:"guid"`
- Ts utctime8601 `json:"ts"`
+ // Guid string `json:"guid"`
+ Ts utctime8601 `json:"ts"`
// Level string `json:"level"`
}
type LogStarting struct {
- ClientString string `json:"version_string"`
- Coinbase string `json:"coinbase"`
+ ClientString string `json:"client_impl"`
ProtocolVersion int `json:"eth_version"`
LogEvent
}
@@ -32,20 +30,11 @@ func (l *LogStarting) EventName() string {
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 {
- 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
}
@@ -53,17 +42,6 @@ func (l *P2PConnected) EventName() string {
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 {
NumConnections int `json:"num_connections"`
RemoteId string `json:"remote_id"`
@@ -74,247 +52,46 @@ func (l *P2PDisconnected) EventName() string {
return "p2p.disconnected"
}
-type P2PDisconnecting struct {
- 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 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"`
+type EthMinerNewBlock struct {
+ BlockHash string `json:"block_hash"`
+ BlockNumber int `json:"block_number"`
+ ChainHeadHash string `json:"chain_head_hash"`
+ BlockPrevHash string `json:"block_prev_hash"`
LogEvent
}
-func (l *EthNewBlockReceived) EventName() string {
- return "eth.newblock.received"
+func (l *EthMinerNewBlock) EventName() string {
+ return "eth.miner.new_block"
}
-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"`
+type EthChainReceivedNewBlock struct {
+ BlockHash string `json:"block_hash"`
+ BlockNumber int `json:"block_number"`
+ ChainHeadHash string `json:"chain_head_hash"`
+ BlockPrevHash string `json:"block_prev_hash"`
+ RemoteId int `json:"remote_id"`
LogEvent
}
-func (l *EthNewBlockIsKnown) EventName() string {
- return "eth.newblock.is_known"
+func (l *EthChainReceivedNewBlock) EventName() string {
+ return "eth.chain.received.new_block"
}
-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"`
+type EthChainNewHead struct {
+ BlockHash string `json:"block_hash"`
+ BlockNumber int `json:"block_number"`
+ ChainHeadHash string `json:"chain_head_hash"`
+ 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"
+func (l *EthChainNewHead) EventName() string {
+ return "eth.chain.new_head"
}
type EthTxReceived struct {
- TxHash string `json:"tx_hash"`
- TxAddress string `json:"tx_address"`
- TxHexRLP string `json:"tx_hexrlp"`
- RemoteId string `json:"remote_id"`
- TxNonce int `json:"tx_nonce"`
+ TxHash string `json:"tx_hash"`
+ RemoteId string `json:"remote_id"`
LogEvent
}
@@ -322,39 +99,261 @@ func (l *EthTxReceived) EventName() string {
return "eth.tx.received"
}
-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"
-}
+//
+//
+// The types below are legacy and need to be converted to new format or deleted
+//
+//
+
+// 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 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 P2PDisconnecting struct {
+// 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"
+// }
diff --git a/miner/miner.go b/miner/miner.go
index 27afcf684..0cc2361c8 100644
--- a/miner/miner.go
+++ b/miner/miner.go
@@ -20,13 +20,13 @@ type Miner struct {
mining bool
}
-func New(coinbase []byte, eth core.Backend) *Miner {
+func New(coinbase []byte, eth core.Backend, minerThreads int) *Miner {
miner := &Miner{
Coinbase: coinbase,
worker: newWorker(coinbase, eth),
}
- for i := 0; i < 4; i++ {
+ for i := 0; i < minerThreads; i++ {
miner.worker.register(NewCpuMiner(i, ezp.New()))
}
diff --git a/miner/worker.go b/miner/worker.go
index 47b462e53..1f3a52ab5 100644
--- a/miner/worker.go
+++ b/miner/worker.go
@@ -109,14 +109,18 @@ func (self *worker) register(agent Agent) {
}
func (self *worker) update() {
- events := self.mux.Subscribe(core.ChainEvent{}, core.TxPreEvent{})
+ events := self.mux.Subscribe(core.ChainEvent{}, core.NewMinedBlockEvent{})
out:
for {
select {
case event := <-events.Chan():
- switch event.(type) {
- case core.ChainEvent, core.TxPreEvent:
+ switch ev := event.(type) {
+ case core.ChainEvent:
+ if self.current.block != ev.Block {
+ self.commitNewWork()
+ }
+ case core.NewMinedBlockEvent:
self.commitNewWork()
}
case <-self.quit:
@@ -172,17 +176,19 @@ func (self *worker) commitNewWork() {
transactions := self.eth.TxPool().GetTransactions()
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
var remove types.Transactions
+gasLimit:
for _, tx := range transactions {
err := self.commitTransaction(tx)
switch {
case core.IsNonceErr(err):
// Remove invalid transactions
remove = append(remove, tx)
- case core.IsGasLimitErr(err):
+ case state.IsGasLimitErr(err):
// Break on gas limit
- break
+ break gasLimit
}
if err != nil {
@@ -227,11 +233,9 @@ func (self *worker) commitUncle(uncle *types.Header) 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)
- if err != nil && (core.IsNonceErr(err) || core.IsGasLimitErr(err)) {
- self.current.state.Set(snapshot)
-
+ if err != nil && (core.IsNonceErr(err) || state.IsGasLimitErr(err)) {
return err
}
diff --git a/p2p/discover/udp.go b/p2p/discover/udp.go
index b2a895442..69e9f3c2e 100644
--- a/p2p/discover/udp.go
+++ b/p2p/discover/udp.go
@@ -253,7 +253,8 @@ func (t *udp) loop() {
case reply := <-t.replies:
// 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) {
p.errc <- nil
copy(pending[i:], pending[i+1:])
diff --git a/p2p/crypto.go b/p2p/handshake.go
index 7e4b43712..614711eaf 100644
--- a/p2p/crypto.go
+++ b/p2p/handshake.go
@@ -1,21 +1,20 @@
package p2p
import (
- // "binary"
"crypto/ecdsa"
"crypto/rand"
+ "errors"
"fmt"
"io"
+ "net"
"github.com/ethereum/go-ethereum/crypto"
"github.com/ethereum/go-ethereum/crypto/ecies"
"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/rlp"
)
-var clogger = ethlogger.NewLogger("CRYPTOID")
-
const (
sskLen = 16 // ecies.MaxSharedKeyLength(pubKey) / 2
sigLen = 65 // elliptic S256
@@ -30,26 +29,76 @@ const (
rHSLen = authRespLen + eciesBytes // size of the final ECIES payload sent as receiver's handshake
)
-type hexkey []byte
+type conn struct {
+ *frameRW
+ *protoHandshake
+}
-func (self hexkey) String() string {
- return fmt.Sprintf("(%d) %x", len(self), []byte(self))
+func newConn(fd net.Conn, hs *protoHandshake) *conn {
+ return &conn{newFrameRW(fd, msgWriteTimeout), hs}
}
-func encHandshake(conn io.ReadWriter, prv *ecdsa.PrivateKey, dial *discover.Node) (
- remoteID discover.NodeID,
- 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 {
- var remotePubkey []byte
- sessionToken, remotePubkey, err = inboundEncHandshake(conn, prv, nil)
- copy(remoteID[:], remotePubkey)
+ return setupInboundConn(fd, prv, our)
} else {
- remoteID = dial.ID
- sessionToken, err = outboundEncHandshake(conn, prv, remoteID[:], nil)
+ return setupOutboundConn(fd, prv, our, dial)
+ }
+}
+
+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)
}
- return remoteID, sessionToken, 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.
@@ -66,18 +115,9 @@ func outboundEncHandshake(conn io.ReadWriter, prvKey *ecdsa.PrivateKey, remotePu
if err != nil {
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 {
return nil, err
}
- clogger.Debugf("initiator handshake: %v", hexkey(auth))
response := make([]byte, rHSLen)
if _, err = io.ReadFull(conn, response); err != nil {
@@ -88,9 +128,6 @@ func outboundEncHandshake(conn io.ReadWriter, prvKey *ecdsa.PrivateKey, remotePu
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)
}
@@ -221,12 +258,9 @@ func inboundEncHandshake(conn io.ReadWriter, prvKey *ecdsa.PrivateKey, sessionTo
if err != nil {
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 {
return nil, nil, err
}
- clogger.Debugf("receiver handshake:\n%v", hexkey(response))
token, err = newSession(initNonce, recNonce, randomPrivKey, remoteRandomPubKey)
return token, remotePubKey, err
}
@@ -361,3 +395,40 @@ func xor(one, other []byte) (xor []byte) {
}
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
+}
diff --git a/p2p/crypto_test.go b/p2p/handshake_test.go
index 0a9d49f96..06c6a6932 100644
--- a/p2p/crypto_test.go
+++ b/p2p/handshake_test.go
@@ -5,10 +5,12 @@ import (
"crypto/ecdsa"
"crypto/rand"
"net"
+ "reflect"
"testing"
"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) {
@@ -91,14 +93,14 @@ func testCryptoHandshake(prv0, prv1 *ecdsa.PrivateKey, sessionToken []byte, t *t
if err != nil {
t.Errorf("%v", err)
}
- t.Logf("-> %v", hexkey(auth))
+ // t.Logf("-> %v", hexkey(auth))
// receiver reads auth and responds with response
response, remoteRecNonce, remoteInitNonce, _, remoteRandomPrivKey, remoteInitRandomPubKey, err := authResp(auth, sessionToken, prv1)
if err != nil {
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
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()
prv0, _ := crypto.GenerateKey()
@@ -165,3 +167,58 @@ func TestHandshake(t *testing.T) {
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
+}
diff --git a/p2p/message.go b/p2p/message.go
index 07916f7b3..7adad4b09 100644
--- a/p2p/message.go
+++ b/p2p/message.go
@@ -197,7 +197,7 @@ func (rw *frameRW) ReadMsg() (msg Msg, err error) {
return msg, err
}
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:])
diff --git a/p2p/nat/natupnp.go b/p2p/nat/natupnp.go
index 25cbc0d71..ef7765e8d 100644
--- a/p2p/nat/natupnp.go
+++ b/p2p/nat/natupnp.go
@@ -7,9 +7,9 @@ import (
"strings"
"time"
- "github.com/fjl/goupnp"
- "github.com/fjl/goupnp/dcps/internetgateway1"
- "github.com/fjl/goupnp/dcps/internetgateway2"
+ "github.com/huin/goupnp"
+ "github.com/huin/goupnp/dcps/internetgateway1"
+ "github.com/huin/goupnp/dcps/internetgateway2"
)
type upnp struct {
diff --git a/p2p/peer.go b/p2p/peer.go
index fd5bec7d5..fb027c834 100644
--- a/p2p/peer.go
+++ b/p2p/peer.go
@@ -21,6 +21,7 @@ const (
baseProtocolMaxMsgSize = 10 * 1024 * 1024
disconnectGracePeriod = 2 * time.Second
+ pingInterval = 15 * time.Second
)
const (
@@ -33,37 +34,14 @@ const (
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.
type Peer struct {
// Peers have all the log methods.
// Use them to display messages related to the peer.
*logger.Logger
- infoMu sync.Mutex
- name string
- 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
+ rw *conn
+ running map[string]*protoRW
protoWG sync.WaitGroup
protoErr chan error
@@ -73,36 +51,27 @@ type Peer struct {
// NewPeer returns a peer for testing purposes.
func NewPeer(id discover.NodeID, name string, caps []Cap) *Peer {
- conn, _ := net.Pipe()
- peer := newPeer(conn, nil, "", nil, &id)
- peer.setHandshakeInfo(name, caps)
+ pipe, _ := net.Pipe()
+ conn := newConn(pipe, &protoHandshake{ID: id, Name: name, Caps: caps})
+ peer := newPeer(conn, nil)
close(peer.closed) // ensures Disconnect doesn't block
return peer
}
// ID returns the node's public key.
func (p *Peer) ID() discover.NodeID {
- return *p.remoteID
+ return p.rw.ID
}
// Name returns the node name that the remote node advertised.
func (p *Peer) Name() string {
- // this needs a lock because the information is part of the
- // protocol handshake.
- p.infoMu.Lock()
- name := p.name
- p.infoMu.Unlock()
- return name
+ return p.rw.Name
}
// Caps returns the capabilities (supported subprotocols) of the remote peer.
func (p *Peer) Caps() []Cap {
- // this needs a lock because the information is part of the
- // protocol handshake.
- p.infoMu.Lock()
- caps := p.caps
- p.infoMu.Unlock()
- return caps
+ // TODO: maybe return copy
+ return p.rw.Caps
}
// RemoteAddr returns the remote address of the network connection.
@@ -126,30 +95,20 @@ func (p *Peer) Disconnect(reason DiscReason) {
// String implements fmt.Stringer.
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 {
- logtag := fmt.Sprintf("Peer %.8x %v", remoteID[:], conn.RemoteAddr())
- return &Peer{
- Logger: logger.NewLogger(logtag),
- rw: newFrameRW(conn, msgWriteTimeout),
- ourID: ourID,
- ourName: ourName,
- remoteID: remoteID,
- protocols: protocols,
- running: make(map[string]*proto),
- disc: make(chan DiscReason),
- protoErr: make(chan error),
- closed: make(chan struct{}),
+func newPeer(conn *conn, protocols []Protocol) *Peer {
+ logtag := fmt.Sprintf("Peer %.8x %v", conn.ID[:], conn.RemoteAddr())
+ p := &Peer{
+ Logger: logger.NewLogger(logtag),
+ rw: conn,
+ running: matchProtocols(protocols, conn.Caps, conn),
+ disc: make(chan DiscReason),
+ protoErr: make(chan error),
+ closed: make(chan struct{}),
}
-}
-
-func (p *Peer) setHandshakeInfo(name string, caps []Cap) {
- p.infoMu.Lock()
- p.name = name
- p.caps = caps
- p.infoMu.Unlock()
+ return p
}
func (p *Peer) run() DiscReason {
@@ -157,29 +116,36 @@ func (p *Peer) run() DiscReason {
defer p.closeProtocols()
defer close(p.closed)
+ p.startProtocols()
go func() { readErr <- p.readLoop() }()
- if !p.noHandshake {
- if err := writeProtocolHandshake(p.rw, p.ourName, *p.ourID, p.protocols); err != nil {
- p.DebugDetailf("Protocol handshake error: %v\n", err)
- p.rw.Close()
- return DiscProtocolError
- }
- }
+ ping := time.NewTicker(pingInterval)
+ defer ping.Stop()
// Wait for an error or disconnect.
var reason DiscReason
- select {
- 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)
- case reason = <-p.disc:
+loop:
+ for {
+ select {
+ case <-ping.C:
+ go func() {
+ if err := EncodeMsg(p.rw, pingMsg, nil); err != nil {
+ p.protoErr <- err
+ return
+ }
+ }()
+ 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)
@@ -206,11 +172,6 @@ func (p *Peer) politeDisconnect(reason DiscReason) {
}
func (p *Peer) readLoop() error {
- if !p.noHandshake {
- if err := readProtocolHandshake(p, p.rw); err != nil {
- return err
- }
- }
for {
msg, err := p.rw.ReadMsg()
if err != nil {
@@ -249,105 +210,51 @@ func (p *Peer) handle(msg Msg) error {
return nil
}
-func readProtocolHandshake(p *Peer, rw MsgReadWriter) error {
- // read and handle remote handshake
- 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) {
+// matchProtocols creates structures for matching named subprotocols.
+func matchProtocols(protocols []Protocol, caps []Cap, rw MsgReadWriter) map[string]*protoRW {
sort.Sort(capsByName(caps))
- p.runlock.Lock()
- defer p.runlock.Unlock()
offset := baseProtocolLength
+ result := make(map[string]*protoRW)
outer:
for _, cap := range caps {
- for _, proto := range p.protocols {
- if proto.Name == cap.Name &&
- proto.Version == cap.Version &&
- p.running[cap.Name] == nil {
- p.running[cap.Name] = p.startProto(offset, proto)
+ for _, proto := range protocols {
+ if proto.Name == cap.Name && proto.Version == cap.Version && result[cap.Name] == nil {
+ result[cap.Name] = &protoRW{Protocol: proto, offset: offset, in: make(chan Msg), w: rw}
offset += proto.Length
continue outer
}
}
}
+ return result
}
-func (p *Peer) startProto(offset uint64, impl Protocol) *proto {
- p.DebugDetailf("Starting protocol %s/%d\n", impl.Name, impl.Version)
- rw := &proto{
- name: impl.Name,
- in: make(chan Msg),
- offset: offset,
- maxcode: impl.Length,
- w: p.rw,
+func (p *Peer) startProtocols() {
+ for _, proto := range p.running {
+ proto := proto
+ p.DebugDetailf("Starting protocol %s/%d\n", proto.Name, proto.Version)
+ p.protoWG.Add(1)
+ go func() {
+ err := proto.Run(p, proto)
+ 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
// the given message code.
-func (p *Peer) getProto(code uint64) (*proto, error) {
- p.runlock.RLock()
- defer p.runlock.RUnlock()
+func (p *Peer) getProto(code uint64) (*protoRW, error) {
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
}
}
@@ -355,46 +262,43 @@ func (p *Peer) getProto(code uint64) (*proto, error) {
}
func (p *Peer) closeProtocols() {
- p.runlock.RLock()
for _, p := range p.running {
close(p.in)
}
- p.runlock.RUnlock()
p.protoWG.Wait()
}
// writeProtoMsg sends the given message on behalf of the given named protocol.
// this exists because of Server.Broadcast.
func (p *Peer) writeProtoMsg(protoName string, msg Msg) error {
- p.runlock.RLock()
proto, ok := p.running[protoName]
- p.runlock.RUnlock()
if !ok {
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)
}
msg.Code += proto.offset
return p.rw.WriteMsg(msg)
}
-type proto struct {
- name string
- in chan Msg
- maxcode, offset uint64
- w MsgWriter
+type protoRW struct {
+ Protocol
+
+ in chan Msg
+ offset uint64
+ w MsgWriter
}
-func (rw *proto) WriteMsg(msg Msg) error {
- if msg.Code >= rw.maxcode {
+func (rw *protoRW) WriteMsg(msg Msg) error {
+ if msg.Code >= rw.Length {
return newPeerError(errInvalidMsgCode, "not handled")
}
msg.Code += rw.offset
return rw.w.WriteMsg(msg)
}
-func (rw *proto) ReadMsg() (Msg, error) {
+func (rw *protoRW) ReadMsg() (Msg, error) {
msg, ok := <-rw.in
if !ok {
return msg, io.EOF
diff --git a/p2p/peer_test.go b/p2p/peer_test.go
index 68c9910a2..a1260adbd 100644
--- a/p2p/peer_test.go
+++ b/p2p/peer_test.go
@@ -6,11 +6,9 @@ import (
"io/ioutil"
"net"
"reflect"
- "sort"
"testing"
"time"
- "github.com/ethereum/go-ethereum/p2p/discover"
"github.com/ethereum/go-ethereum/rlp"
)
@@ -23,6 +21,7 @@ var discard = Protocol{
if err != nil {
return err
}
+ fmt.Printf("discarding %d\n", msg.Code)
if err = msg.Discard(); err != nil {
return err
}
@@ -30,13 +29,20 @@ var discard = Protocol{
},
}
-func testPeer(noHandshake bool, protos []Protocol) (*frameRW, *Peer, <-chan DiscReason) {
- conn1, conn2 := net.Pipe()
- peer := newPeer(conn1, protos, "name", &discover.NodeID{}, &discover.NodeID{})
- peer.noHandshake = noHandshake
+func testPeer(protos []Protocol) (*conn, *Peer, <-chan DiscReason) {
+ fd1, fd2 := net.Pipe()
+ hs1 := &protoHandshake{ID: randomID(), Version: baseProtocolVersion}
+ 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)
go func() { errc <- peer.run() }()
- return newFrameRW(conn2, msgWriteTimeout), peer, errc
+
+ return newConn(fd2, hs2), peer, errc
}
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()
- peer.startSubprotocols([]Cap{proto.cap()})
EncodeMsg(rw, baseProtocolLength+2, 1)
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()
- peer.startSubprotocols([]Cap{proto.cap()})
EncodeMsg(rw, 18, make([]byte, msgsize))
select {
@@ -130,9 +134,8 @@ func TestPeerProtoEncodeMsg(t *testing.T) {
return nil
},
}
- rw, peer, _ := testPeer(true, []Protocol{proto})
+ rw, _, _ := testPeer([]Protocol{proto})
defer rw.Close()
- peer.startSubprotocols([]Cap{proto.cap()})
if err := expectMsg(rw, 17, []string{"foo", "bar"}); err != nil {
t.Error(err)
@@ -142,9 +145,8 @@ func TestPeerProtoEncodeMsg(t *testing.T) {
func TestPeerWriteForBroadcast(t *testing.T) {
defer testlog(t).detach()
- rw, peer, peerErr := testPeer(true, []Protocol{discard})
+ rw, peer, peerErr := testPeer([]Protocol{discard})
defer rw.Close()
- peer.startSubprotocols([]Cap{discard.cap()})
// test write errors
if err := peer.writeProtoMsg("b", NewMsg(3)); err == nil {
@@ -160,7 +162,7 @@ func TestPeerWriteForBroadcast(t *testing.T) {
read := make(chan struct{})
go func() {
if err := expectMsg(rw, 16, nil); err != nil {
- t.Error()
+ t.Error(err)
}
close(read)
}()
@@ -179,7 +181,7 @@ func TestPeerWriteForBroadcast(t *testing.T) {
func TestPeerPing(t *testing.T) {
defer testlog(t).detach()
- rw, _, _ := testPeer(true, nil)
+ rw, _, _ := testPeer(nil)
defer rw.Close()
if err := EncodeMsg(rw, pingMsg); err != nil {
t.Fatal(err)
@@ -192,7 +194,7 @@ func TestPeerPing(t *testing.T) {
func TestPeerDisconnect(t *testing.T) {
defer testlog(t).detach()
- rw, _, disc := testPeer(true, nil)
+ rw, _, disc := testPeer(nil)
defer rw.Close()
if err := EncodeMsg(rw, discMsg, DiscQuitting); err != nil {
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) {
name := "nodename"
caps := []Cap{{"foo", 2}, {"bar", 3}}
diff --git a/p2p/server.go b/p2p/server.go
index 35b584a27..3ea2538d1 100644
--- a/p2p/server.go
+++ b/p2p/server.go
@@ -5,7 +5,6 @@ import (
"crypto/ecdsa"
"errors"
"fmt"
- "io"
"net"
"runtime"
"sync"
@@ -23,6 +22,7 @@ const (
)
var srvlog = logger.NewLogger("P2P Server")
+var srvjslog = logger.NewJsonLogger()
// MakeName creates a node name that follows the ethereum convention
// 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
// the whole protocol stack.
- handshakeFunc
+ setupFunc
newPeerHook
+ ourHandshake *protoHandshake
+
lock sync.RWMutex
running bool
listener net.Listener
@@ -99,7 +101,7 @@ type Server struct {
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)
// Peers returns all connected peers.
@@ -159,7 +161,7 @@ func (srv *Server) Start() (err error) {
}
srvlog.Infoln("Starting Server")
- // initialize all the fields
+ // static fields
if srv.PrivateKey == nil {
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.peers = make(map[discover.NodeID]*Peer)
srv.peerConnect = make(chan *discover.Node)
-
- if srv.handshakeFunc == nil {
- srv.handshakeFunc = encHandshake
+ if srv.setupFunc == nil {
+ srv.setupFunc = setupConn
}
if srv.Blacklist == nil {
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 err := srv.startListening(); err != nil {
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 {
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
- conn.SetDeadline(time.Now().Add(handshakeTimeout))
- remoteID, _, err := srv.handshakeFunc(conn, srv.PrivateKey, dest)
+ fd.SetDeadline(time.Now().Add(handshakeTimeout))
+ conn, err := srv.setupFunc(fd, srv.PrivateKey, srv.ourHandshake, dest)
if err != nil {
- conn.Close()
- srvlog.Debugf("Encryption Handshake with %v failed: %v", conn.RemoteAddr(), err)
+ fd.Close()
+ srvlog.Debugf("Handshake with %v failed: %v", fd.RemoteAddr(), err)
return
}
- ourID := srv.ntab.Self()
- p := newPeer(conn, srv.Protocols, srv.Name, &ourID, &remoteID)
- if ok, reason := srv.addPeer(remoteID, p); !ok {
+ p := newPeer(conn, srv.Protocols)
+ if ok, reason := srv.addPeer(conn.ID, p); !ok {
srvlog.DebugDetailf("Not adding %v (%v)\n", p, reason)
p.politeDisconnect(reason)
return
}
+
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 {
srv.newPeerHook(p)
}
discreason := p.run()
srv.removePeer(p)
+
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) {
@@ -394,7 +414,7 @@ func (srv *Server) addPeer(id discover.NodeID, p *Peer) (bool, DiscReason) {
func (srv *Server) removePeer(p *Peer) {
srv.lock.Lock()
- delete(srv.peers, *p.remoteID)
+ delete(srv.peers, p.ID())
srv.lock.Unlock()
srv.peerWG.Done()
}
diff --git a/p2p/server_test.go b/p2p/server_test.go
index aa2b3d243..c109fffb9 100644
--- a/p2p/server_test.go
+++ b/p2p/server_test.go
@@ -21,8 +21,12 @@ func startTestServer(t *testing.T, pf newPeerHook) *Server {
ListenAddr: "127.0.0.1:0",
PrivateKey: newkey(),
newPeerHook: pf,
- handshakeFunc: func(io.ReadWriter, *ecdsa.PrivateKey, *discover.Node) (id discover.NodeID, st []byte, err error) {
- return randomID(), nil, err
+ setupFunc: func(fd net.Conn, prv *ecdsa.PrivateKey, our *protoHandshake, dial *discover.Node) (*conn, error) {
+ id := randomID()
+ return &conn{
+ frameRW: newFrameRW(fd, msgWriteTimeout),
+ protoHandshake: &protoHandshake{ID: id, Version: baseProtocolVersion},
+ }, nil
},
}
if err := server.Start(); err != nil {
@@ -116,9 +120,7 @@ func TestServerBroadcast(t *testing.T) {
var connected sync.WaitGroup
srv := startTestServer(t, func(p *Peer) {
- p.protocols = []Protocol{discard}
- p.startSubprotocols([]Cap{discard.cap()})
- p.noHandshake = true
+ p.running = matchProtocols([]Protocol{discard}, []Cap{discard.cap()}, p.rw)
connected.Done()
})
defer srv.Stop()
diff --git a/rpc/args.go b/rpc/args.go
index 12e3103bc..f730819fd 100644
--- a/rpc/args.go
+++ b/rpc/args.go
@@ -1,6 +1,7 @@
package rpc
import "encoding/json"
+
import "github.com/ethereum/go-ethereum/core"
type GetBlockArgs struct {
@@ -37,6 +38,35 @@ type NewTxArgs struct {
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 {
Tx string `json:"tx"`
}
@@ -203,7 +233,7 @@ func (obj *Sha3Args) UnmarshalJSON(b []byte) (err error) {
type FilterOptions struct {
Earliest int64
Latest int64
- Address string
+ Address interface{}
Topic []string
Skip int
Max int
@@ -211,9 +241,22 @@ type FilterOptions struct {
func toFilterOptions(options *FilterOptions) 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.Latest = options.Latest
- opts.Address = fromHex(options.Address)
opts.Topics = make([][]byte, len(options.Topic))
for i, topic := range options.Topic {
opts.Topics[i] = fromHex(topic)
@@ -246,7 +289,7 @@ type WhisperMessageArgs struct {
Payload string
To string
From string
- Topics []string
+ Topic []string
Priority uint32
Ttl uint32
}
diff --git a/rpc/message.go b/rpc/message.go
index 7983e003d..825ede05b 100644
--- a/rpc/message.go
+++ b/rpc/message.go
@@ -201,6 +201,36 @@ func (req *RpcRequest) ToGetCodeAtArgs() (*GetCodeAtArgs, error) {
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) {
if len(req.Params) < 1 {
return nil, NewErrorResponse(ErrorArguments)
@@ -231,6 +261,21 @@ func (req *RpcRequest) ToFilterStringArgs() (string, error) {
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) {
if len(req.Params) < 1 {
return 0, NewErrorResponse(ErrorArguments)
@@ -301,7 +346,7 @@ func (req *RpcRequest) ToWhisperFilterArgs() (*xeth.Options, error) {
return &args, nil
}
-func (req *RpcRequest) ToWhisperIdArgs() (int, error) {
+func (req *RpcRequest) ToIdArgs() (int, error) {
if len(req.Params) < 1 {
return 0, NewErrorResponse(ErrorArguments)
}
@@ -342,3 +387,31 @@ func (req *RpcRequest) ToWhisperHasIdentityArgs() (string, error) {
rpclogger.DebugDetailf("%T %v", args, args)
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
+}
diff --git a/rpc/packages.go b/rpc/packages.go
index ef31ff1e1..b51bde7ce 100644
--- a/rpc/packages.go
+++ b/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:
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"
"strings"
"sync"
+ "time"
"github.com/ethereum/go-ethereum/core"
"github.com/ethereum/go-ethereum/core/types"
@@ -48,13 +32,17 @@ const (
type EthereumApi struct {
xeth *xeth.XEth
+ quit chan struct{}
filterManager *filter.FilterManager
logMut sync.RWMutex
- logs map[int]state.Logs
+ logs map[int]*logFilter
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
}
@@ -63,16 +51,48 @@ func NewEthereumApi(eth *xeth.XEth) *EthereumApi {
db, _ := ethdb.NewLDBDatabase("dapps")
api := &EthereumApi{
xeth: eth,
+ quit: make(chan struct{}),
filterManager: filter.NewFilterManager(eth.Backend().EventMux()),
- logs: make(map[int]state.Logs),
- messages: make(map[int][]xeth.WhisperMessage),
+ logs: make(map[int]*logFilter),
+ messages: make(map[int]*whisperFilter),
db: db,
}
go api.filterManager.Start()
+ go api.start()
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 {
var id int
filter := core.NewFilter(self.xeth.Backend())
@@ -81,20 +101,36 @@ func (self *EthereumApi) NewFilter(args *FilterOptions, reply *interface{}) erro
self.logMut.Lock()
defer self.logMut.Unlock()
- self.logs[id] = append(self.logs[id], logs...)
+ self.logs[id].add(logs...)
}
id = self.filterManager.InstallFilter(filter)
+ self.logs[id] = &logFilter{timeout: time.Now()}
+
*reply = id
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 {
var id int
filter := core.NewFilter(self.xeth.Backend())
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" {
filter.PendingCallback = callback
@@ -112,15 +148,29 @@ func (self *EthereumApi) FilterChanged(id int, reply *interface{}) error {
self.logMut.Lock()
defer self.logMut.Unlock()
- *reply = toLogs(self.logs[id])
-
- self.logs[id] = nil // empty the logs
+ if self.logs[id] != nil {
+ *reply = toLogs(self.logs[id].get())
+ }
return nil
}
func (self *EthereumApi) Logs(id int, reply *interface{}) error {
+ self.logMut.Lock()
+ defer self.logMut.Unlock()
+
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())
return nil
@@ -149,8 +199,14 @@ func (p *EthereumApi) Transact(args *NewTxArgs, reply *interface{}) error {
args.GasPrice = defaultGasPrice
}
- result, _ := p.xeth.Transact( /* TODO specify account */ args.To, args.Value, args.Gas, args.GasPrice, args.Data)
- *reply = result
+ // TODO if no_private_key then
+ 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
}
@@ -231,6 +287,11 @@ func (p *EthereumApi) GetIsMining(reply *interface{}) error {
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 {
*reply = p.xeth.Backend().ChainManager().CurrentBlock().Number()
return nil
@@ -264,6 +325,21 @@ func (p *EthereumApi) GetCodeAt(args *GetCodeAtArgs, reply *interface{}) error {
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 {
*reply = toHex(crypto.Sha3(fromHex(args.Data)))
return nil
@@ -301,7 +377,10 @@ func (p *EthereumApi) NewWhisperFilter(args *xeth.Options, reply *interface{}) e
args.Fn = func(msg xeth.WhisperMessage) {
p.messagesMut.Lock()
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)
*reply = id
@@ -312,15 +391,15 @@ func (self *EthereumApi) MessagesChanged(id int, reply *interface{}) error {
self.messagesMut.Lock()
defer self.messagesMut.Unlock()
- *reply = self.messages[id]
-
- self.messages[id] = nil // empty the messages
+ if self.messages[id] != nil {
+ *reply = self.messages[id].get()
+ }
return nil
}
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 {
return err
}
@@ -349,6 +428,12 @@ func (p *EthereumApi) GetRequestReply(req *RpcRequest, reply *interface{}) error
return p.GetIsListening(reply)
case "eth_mining":
return p.GetIsMining(reply)
+ case "eth_setMining":
+ args, err := req.ToBoolArgs()
+ if err != nil {
+ return err
+ }
+ return p.SetMining(args, reply)
case "eth_peerCount":
return p.GetPeerCount(reply)
case "eth_number":
@@ -415,15 +500,59 @@ func (p *EthereumApi) GetRequestReply(req *RpcRequest, reply *interface{}) error
return err
}
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":
- args, err := req.ToFilterChangedArgs()
+ args, err := req.ToIdArgs()
if err != nil {
return err
}
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":
*reply = defaultGasPrice
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":
args, err := req.ToSha3Args()
if err != nil {
@@ -451,7 +580,7 @@ func (p *EthereumApi) GetRequestReply(req *RpcRequest, reply *interface{}) error
}
return p.NewWhisperFilter(args, reply)
case "shh_changed":
- args, err := req.ToWhisperIdArgs()
+ args, err := req.ToIdArgs()
if err != nil {
return err
}
@@ -469,7 +598,7 @@ func (p *EthereumApi) GetRequestReply(req *RpcRequest, reply *interface{}) error
}
return p.HasWhisperIdentity(args, reply)
case "shh_getMessages":
- args, err := req.ToWhisperIdArgs()
+ args, err := req.ToIdArgs()
if err != nil {
return err
}
@@ -481,3 +610,36 @@ func (p *EthereumApi) GetRequestReply(req *RpcRequest, reply *interface{}) error
rpclogger.DebugDetailf("Reply: %T %s", reply, reply)
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)
+}
diff --git a/rpc/packages_test.go b/rpc/packages_test.go
new file mode 100644
index 000000000..037fd78b3
--- /dev/null
+++ b/rpc/packages_test.go
@@ -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")
+ }
+}
diff --git a/rpc/util.go b/rpc/util.go
index 679d83754..1939b3474 100644
--- a/rpc/util.go
+++ b/rpc/util.go
@@ -20,10 +20,12 @@ import (
"encoding/json"
"io"
"net/http"
+ "time"
"github.com/ethereum/go-ethereum/ethutil"
"github.com/ethereum/go-ethereum/logger"
"github.com/ethereum/go-ethereum/state"
+ "github.com/ethereum/go-ethereum/xeth"
)
var rpclogger = logger.NewLogger("RPC")
@@ -80,8 +82,9 @@ type RpcServer interface {
type Log struct {
Address string `json:"address"`
- Topics []string `json:"topics"`
+ Topic []string `json:"topics"`
Data string `json:"data"`
+ Number uint64 `json:"number"`
}
func toLogs(logs state.Logs) (ls []Log) {
@@ -89,14 +92,46 @@ func toLogs(logs state.Logs) (ls []Log) {
for i, log := range logs {
var l Log
- l.Topics = make([]string, len(log.Topics()))
+ l.Topic = make([]string, len(log.Topics()))
l.Address = toHex(log.Address())
l.Data = toHex(log.Data())
+ l.Number = log.Number()
for j, topic := range log.Topics() {
- l.Topics[j] = toHex(topic)
+ l.Topic[j] = toHex(topic)
}
ls[i] = l
}
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
+}
diff --git a/rpc/ws/server.go b/rpc/ws/server.go
index 100713c10..b8cc2fa6b 100644
--- a/rpc/ws/server.go
+++ b/rpc/ws/server.go
@@ -21,10 +21,10 @@ import (
"net"
"net/http"
- "code.google.com/p/go.net/websocket"
"github.com/ethereum/go-ethereum/logger"
"github.com/ethereum/go-ethereum/rpc"
"github.com/ethereum/go-ethereum/xeth"
+ "golang.org/x/net/websocket"
)
var wslogger = logger.NewLogger("RPC-WS")
diff --git a/state/dump.go b/state/dump.go
index ac646480c..81895f1a3 100644
--- a/state/dump.go
+++ b/state/dump.go
@@ -30,7 +30,7 @@ func (self *StateDB) Dump() []byte {
for it.Next() {
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)
storageIt := stateObject.State.trie.Iterator()
@@ -50,7 +50,7 @@ func (self *StateDB) Dump() []byte {
// Debug stuff
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()
for it.Next() {
fmt.Printf("%x %x\n", it.Key, it.Value)
diff --git a/state/log.go b/state/log.go
index 46360f4aa..d503bd1a0 100644
--- a/state/log.go
+++ b/state/log.go
@@ -12,16 +12,19 @@ type Log interface {
Address() []byte
Topics() [][]byte
Data() []byte
+
+ Number() uint64
}
type StateLog struct {
address []byte
topics [][]byte
data []byte
+ number uint64
}
-func NewLog(address []byte, topics [][]byte, data []byte) *StateLog {
- return &StateLog{address, topics, data}
+func NewLog(address []byte, topics [][]byte, data []byte, number uint64) *StateLog {
+ return &StateLog{address, topics, data, number}
}
func (self *StateLog) Address() []byte {
@@ -36,6 +39,10 @@ func (self *StateLog) Data() []byte {
return self.data
}
+func (self *StateLog) Number() uint64 {
+ return self.number
+}
+
func NewLogFromValue(decoder *ethutil.Value) *StateLog {
log := &StateLog{
address: decoder.Get(0).Bytes(),
diff --git a/state/state_object.go b/state/state_object.go
index 340939a5d..477b912a1 100644
--- a/state/state_object.go
+++ b/state/state_object.go
@@ -1,11 +1,13 @@
package state
import (
+ "bytes"
"fmt"
"math/big"
"github.com/ethereum/go-ethereum/crypto"
"github.com/ethereum/go-ethereum/ethutil"
+ "github.com/ethereum/go-ethereum/rlp"
"github.com/ethereum/go-ethereum/trie"
)
@@ -34,11 +36,11 @@ type StateObject struct {
// Shared attributes
balance *big.Int
codeHash []byte
- Nonce uint64
+ nonce uint64
// Contract related attributes
State *StateDB
- Code Code
- InitCode Code
+ code Code
+ initCode Code
storage Storage
@@ -51,6 +53,7 @@ type StateObject struct {
// When an object is marked for deletion it will be delete from the trie
// during the "update" phase of the state transition
remove bool
+ dirty bool
}
func (self *StateObject) Reset() {
@@ -62,7 +65,7 @@ func NewStateObject(addr []byte, db ethutil.Database) *StateObject {
// This to ensure that it has 20 bytes (and not 0 bytes), thus left or right pad doesn't matter.
address := ethutil.Address(addr)
- object := &StateObject{db: db, address: address, balance: new(big.Int), gasPool: new(big.Int)}
+ object := &StateObject{db: db, address: address, balance: new(big.Int), gasPool: new(big.Int), dirty: true}
object.State = New(nil, db) //New(trie.New(ethutil.Config.Db, ""))
object.storage = make(Storage)
object.gasPool = new(big.Int)
@@ -71,15 +74,36 @@ func NewStateObject(addr []byte, db ethutil.Database) *StateObject {
}
func NewStateObjectFromBytes(address, data []byte, db ethutil.Database) *StateObject {
+ // TODO clean me up
+ var extobject struct {
+ Nonce uint64
+ Balance *big.Int
+ Root []byte
+ CodeHash []byte
+ }
+ err := rlp.Decode(bytes.NewReader(data), &extobject)
+ if err != nil {
+ fmt.Println(err)
+ return nil
+ }
+
object := &StateObject{address: address, db: db}
- object.RlpDecode(data)
+ //object.RlpDecode(data)
+ object.nonce = extobject.Nonce
+ object.balance = extobject.Balance
+ object.codeHash = extobject.CodeHash
+ object.State = New(extobject.Root, db)
+ object.storage = make(map[string]*ethutil.Value)
+ object.gasPool = new(big.Int)
+ object.code, _ = db.Get(extobject.CodeHash)
return object
}
func (self *StateObject) MarkForDeletion() {
self.remove = true
- statelogger.DebugDetailf("%x: #%d %v (deletion)\n", self.Address(), self.Nonce, self.balance)
+ self.dirty = true
+ statelogger.DebugDetailf("%x: #%d %v (deletion)\n", self.Address(), self.nonce, self.balance)
}
func (c *StateObject) getAddr(addr []byte) *ethutil.Value {
@@ -95,6 +119,7 @@ func (self *StateObject) GetStorage(key *big.Int) *ethutil.Value {
}
func (self *StateObject) SetStorage(key *big.Int, value *ethutil.Value) {
self.SetState(key.Bytes(), value)
+ self.dirty = true
}
func (self *StateObject) Storage() map[string]*ethutil.Value {
@@ -119,6 +144,7 @@ func (self *StateObject) GetState(k []byte) *ethutil.Value {
func (self *StateObject) SetState(k []byte, value *ethutil.Value) {
key := ethutil.LeftPadBytes(k, 32)
self.storage[string(key)] = value.Copy()
+ self.dirty = true
}
func (self *StateObject) Sync() {
@@ -130,36 +156,36 @@ func (self *StateObject) Sync() {
self.setAddr([]byte(key), value)
}
+ self.storage = make(Storage)
}
func (c *StateObject) GetInstr(pc *big.Int) *ethutil.Value {
- if int64(len(c.Code)-1) < pc.Int64() {
+ if int64(len(c.code)-1) < pc.Int64() {
return ethutil.NewValue(0)
}
- return ethutil.NewValueFromBytes([]byte{c.Code[pc.Int64()]})
+ return ethutil.NewValueFromBytes([]byte{c.code[pc.Int64()]})
}
func (c *StateObject) AddBalance(amount *big.Int) {
c.SetBalance(new(big.Int).Add(c.balance, amount))
- statelogger.Debugf("%x: #%d %v (+ %v)\n", c.Address(), c.Nonce, c.balance, amount)
+ statelogger.Debugf("%x: #%d %v (+ %v)\n", c.Address(), c.nonce, c.balance, amount)
}
func (c *StateObject) AddAmount(amount *big.Int) { c.AddBalance(amount) }
func (c *StateObject) SubBalance(amount *big.Int) {
c.SetBalance(new(big.Int).Sub(c.balance, amount))
- statelogger.Debugf("%x: #%d %v (- %v)\n", c.Address(), c.Nonce, c.balance, amount)
+ statelogger.Debugf("%x: #%d %v (- %v)\n", c.Address(), c.nonce, c.balance, amount)
}
func (c *StateObject) SubAmount(amount *big.Int) { c.SubBalance(amount) }
func (c *StateObject) SetBalance(amount *big.Int) {
c.balance = amount
+ c.dirty = true
}
-func (self *StateObject) Balance() *big.Int { return self.balance }
-
//
// Gas setters and getters
//
@@ -174,6 +200,8 @@ func (c *StateObject) ConvertGas(gas, price *big.Int) error {
c.SubAmount(total)
+ c.dirty = true
+
return nil
}
@@ -188,11 +216,15 @@ func (self *StateObject) BuyGas(gas, price *big.Int) error {
return GasLimitError(self.gasPool, gas)
}
+ self.gasPool.Sub(self.gasPool, gas)
+
rGas := new(big.Int).Set(gas)
rGas.Mul(rGas, price)
self.AddAmount(rGas)
+ self.dirty = true
+
return nil
}
@@ -209,15 +241,16 @@ func (self *StateObject) Copy() *StateObject {
stateObject := NewStateObject(self.Address(), self.db)
stateObject.balance.Set(self.balance)
stateObject.codeHash = ethutil.CopyBytes(self.codeHash)
- stateObject.Nonce = self.Nonce
+ stateObject.nonce = self.nonce
if self.State != nil {
stateObject.State = self.State.Copy()
}
- stateObject.Code = ethutil.CopyBytes(self.Code)
- stateObject.InitCode = ethutil.CopyBytes(self.InitCode)
+ stateObject.code = ethutil.CopyBytes(self.code)
+ stateObject.initCode = ethutil.CopyBytes(self.initCode)
stateObject.storage = self.storage.Copy()
stateObject.gasPool.Set(self.gasPool)
stateObject.remove = self.remove
+ stateObject.dirty = self.dirty
return stateObject
}
@@ -230,8 +263,12 @@ func (self *StateObject) Set(stateObject *StateObject) {
// Attribute accessors
//
+func (self *StateObject) Balance() *big.Int {
+ return self.balance
+}
+
func (c *StateObject) N() *big.Int {
- return big.NewInt(int64(c.Nonce))
+ return big.NewInt(int64(c.nonce))
}
// Returns the address of the contract/account
@@ -241,7 +278,7 @@ func (c *StateObject) Address() []byte {
// Returns the initialization Code
func (c *StateObject) Init() Code {
- return c.InitCode
+ return c.initCode
}
func (self *StateObject) Trie() *trie.Trie {
@@ -252,8 +289,27 @@ func (self *StateObject) Root() []byte {
return self.Trie().Root()
}
+func (self *StateObject) Code() []byte {
+ return self.code
+}
+
func (self *StateObject) SetCode(code []byte) {
- self.Code = code
+ self.code = code
+ self.dirty = true
+}
+
+func (self *StateObject) SetInitCode(code []byte) {
+ self.initCode = code
+ self.dirty = true
+}
+
+func (self *StateObject) SetNonce(nonce uint64) {
+ self.nonce = nonce
+ self.dirty = true
+}
+
+func (self *StateObject) Nonce() uint64 {
+ return self.nonce
}
//
@@ -262,17 +318,16 @@ func (self *StateObject) SetCode(code []byte) {
// State object encoding methods
func (c *StateObject) RlpEncode() []byte {
- return ethutil.Encode([]interface{}{c.Nonce, c.balance, c.Root(), c.CodeHash()})
+ return ethutil.Encode([]interface{}{c.nonce, c.balance, c.Root(), c.CodeHash()})
}
func (c *StateObject) CodeHash() ethutil.Bytes {
- return crypto.Sha3(c.Code)
+ return crypto.Sha3(c.code)
}
func (c *StateObject) RlpDecode(data []byte) {
decoder := ethutil.NewValueFromBytes(data)
-
- c.Nonce = decoder.Get(0).Uint()
+ c.nonce = decoder.Get(0).Uint()
c.balance = decoder.Get(1).BigInt()
c.State = New(decoder.Get(2).Bytes(), c.db) //New(trie.New(ethutil.Config.Db, decoder.Get(2).Interface()))
c.storage = make(map[string]*ethutil.Value)
@@ -280,7 +335,7 @@ func (c *StateObject) RlpDecode(data []byte) {
c.codeHash = decoder.Get(3).Bytes()
- c.Code, _ = c.db.Get(c.codeHash)
+ c.code, _ = c.db.Get(c.codeHash)
}
// Storage change object. Used by the manifest for notifying changes to
diff --git a/state/state_test.go b/state/state_test.go
index 7c54cedc0..ee1cf9286 100644
--- a/state/state_test.go
+++ b/state/state_test.go
@@ -1,6 +1,8 @@
package state
import (
+ "math/big"
+
checker "gopkg.in/check.v1"
"github.com/ethereum/go-ethereum/ethdb"
@@ -16,11 +18,42 @@ var _ = checker.Suite(&StateSuite{})
// var ZeroHash256 = make([]byte, 32)
func (s *StateSuite) TestDump(c *checker.C) {
- key := []byte{0x01}
- value := []byte("foo")
- s.state.trie.Update(key, value)
- dump := s.state.Dump()
- c.Assert(dump, checker.NotNil)
+ // generate a few entries
+ obj1 := s.state.GetOrNewStateObject([]byte{0x01})
+ obj1.AddBalance(big.NewInt(22))
+ obj2 := s.state.GetOrNewStateObject([]byte{0x01, 0x02})
+ obj2.SetCode([]byte{3, 3, 3, 3, 3, 3, 3})
+ obj3 := s.state.GetOrNewStateObject([]byte{0x02})
+ obj3.SetBalance(big.NewInt(44))
+
+ // write some of them to the trie
+ s.state.UpdateStateObject(obj1)
+ s.state.UpdateStateObject(obj2)
+
+ // check that dump contains the state objects that are in trie
+ got := string(s.state.Dump())
+ want := `{
+ "root": "4e3a59299745ba6752247c8b91d0f716dac9ec235861c91f5ac1894a361d87ba",
+ "accounts": {
+ "0000000000000000000000000000000000000001": {
+ "balance": "22",
+ "nonce": 0,
+ "root": "56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "codeHash": "c5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "storage": {}
+ },
+ "0000000000000000000000000000000000000102": {
+ "balance": "0",
+ "nonce": 0,
+ "root": "56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "codeHash": "87874902497a5bb968da31a2998d8f22e949d1ef6214bcdedd8bae24cca4b9e3",
+ "storage": {}
+ }
+ }
+}`
+ if got != want {
+ c.Errorf("dump mismatch:\ngot: %s\nwant: %s\n", got, want)
+ }
}
func (s *StateSuite) SetUpTest(c *checker.C) {
diff --git a/state/statedb.go b/state/statedb.go
index c83d59ed7..7e2b24b94 100644
--- a/state/statedb.go
+++ b/state/statedb.go
@@ -72,43 +72,42 @@ func (self *StateDB) AddBalance(addr []byte, amount *big.Int) {
func (self *StateDB) GetNonce(addr []byte) uint64 {
stateObject := self.GetStateObject(addr)
if stateObject != nil {
- return stateObject.Nonce
+ return stateObject.nonce
}
return 0
}
-func (self *StateDB) SetNonce(addr []byte, nonce uint64) {
+func (self *StateDB) GetCode(addr []byte) []byte {
stateObject := self.GetStateObject(addr)
if stateObject != nil {
- stateObject.Nonce = nonce
+ return stateObject.code
}
+
+ return nil
}
-func (self *StateDB) GetCode(addr []byte) []byte {
- stateObject := self.GetStateObject(addr)
+func (self *StateDB) GetState(a, b []byte) []byte {
+ stateObject := self.GetStateObject(a)
if stateObject != nil {
- return stateObject.Code
+ return stateObject.GetState(b).Bytes()
}
return nil
}
-func (self *StateDB) SetCode(addr, code []byte) {
+func (self *StateDB) SetNonce(addr []byte, nonce uint64) {
stateObject := self.GetStateObject(addr)
if stateObject != nil {
- stateObject.SetCode(code)
+ stateObject.SetNonce(nonce)
}
}
-// TODO vars
-func (self *StateDB) GetState(a, b []byte) []byte {
- stateObject := self.GetStateObject(a)
+func (self *StateDB) SetCode(addr, code []byte) {
+ stateObject := self.GetStateObject(addr)
if stateObject != nil {
- return stateObject.GetState(b).Bytes()
+ stateObject.SetCode(code)
}
-
- return nil
}
func (self *StateDB) SetState(addr, key []byte, value interface{}) {
@@ -138,7 +137,7 @@ func (self *StateDB) UpdateStateObject(stateObject *StateObject) {
addr := stateObject.Address()
if len(stateObject.CodeHash()) > 0 {
- self.db.Put(stateObject.CodeHash(), stateObject.Code)
+ self.db.Put(stateObject.CodeHash(), stateObject.code)
}
self.trie.Update(addr, stateObject.RlpEncode())
@@ -282,16 +281,18 @@ func (self *StateDB) Refunds() map[string]*big.Int {
}
func (self *StateDB) Update(gasUsed *big.Int) {
-
self.refund = make(map[string]*big.Int)
for _, stateObject := range self.stateObjects {
- if stateObject.remove {
- self.DeleteStateObject(stateObject)
- } else {
- stateObject.Sync()
-
- self.UpdateStateObject(stateObject)
+ if stateObject.dirty {
+ if stateObject.remove {
+ self.DeleteStateObject(stateObject)
+ } else {
+ stateObject.Sync()
+
+ self.UpdateStateObject(stateObject)
+ }
+ stateObject.dirty = false
}
}
}
diff --git a/tests/vm/gh_test.go b/tests/vm/gh_test.go
index 17f945910..2151cf9a5 100644
--- a/tests/vm/gh_test.go
+++ b/tests/vm/gh_test.go
@@ -46,8 +46,8 @@ func StateObjectFromAccount(db ethutil.Database, addr string, account Account) *
if ethutil.IsHex(account.Code) {
account.Code = account.Code[2:]
}
- obj.Code = ethutil.Hex2Bytes(account.Code)
- obj.Nonce = ethutil.Big(account.Nonce).Uint64()
+ obj.SetCode(ethutil.Hex2Bytes(account.Code))
+ obj.SetNonce(ethutil.Big(account.Nonce).Uint64())
return obj
}
diff --git a/tests/vm/nowarn.go b/tests/vm/nowarn.go
new file mode 100644
index 000000000..2a45a6cc6
--- /dev/null
+++ b/tests/vm/nowarn.go
@@ -0,0 +1,3 @@
+// This silences the warning given by 'go install ./...'.
+
+package vm
diff --git a/ui/filter.go b/ui/filter.go
index da2ea0edb..0d1746915 100644
--- a/ui/filter.go
+++ b/ui/filter.go
@@ -29,8 +29,8 @@ func NewFilterFromMap(object map[string]interface{}, eth core.Backend) *core.Fil
}
if object["address"] != nil {
- val := ethutil.NewValue(object["address"])
- filter.SetAddress(fromHex(val.Str()))
+ //val := ethutil.NewValue(object["address"])
+ //filter.SetAddress(fromHex(val.Str()))
}
if object["max"] != nil {
diff --git a/update-license.go b/update-license.go
index d5e21fdd3..832a94712 100644
--- a/update-license.go
+++ b/update-license.go
@@ -1,4 +1,5 @@
// +build none
+
/*
This command generates GPL license headers on top of all source files.
You can run it once per month, before cutting a release or just
diff --git a/vm/environment.go b/vm/environment.go
index 8507e248f..5b4d6c8f0 100644
--- a/vm/environment.go
+++ b/vm/environment.go
@@ -54,6 +54,7 @@ type Log struct {
address []byte
topics [][]byte
data []byte
+ log uint64
}
func (self *Log) Address() []byte {
@@ -68,6 +69,10 @@ func (self *Log) Data() []byte {
return self.data
}
+func (self *Log) Number() uint64 {
+ return self.log
+}
+
func (self *Log) RlpData() interface{} {
return []interface{}{self.address, ethutil.ByteSliceToInterface(self.topics), self.data}
}
diff --git a/vm/vm.go b/vm/vm.go
index 29e1ade54..f9efeed96 100644
--- a/vm/vm.go
+++ b/vm/vm.go
@@ -266,7 +266,7 @@ func (self *Vm) Run(me, caller ContextRef, code []byte, value, gas, price *big.I
base.Sub(Pow256, stack.Pop()).Sub(base, ethutil.Big1)
// Not needed
- //base = U256(base)
+ base = U256(base)
stack.Push(base)
case LT:
@@ -532,7 +532,7 @@ func (self *Vm) Run(me, caller ContextRef, code []byte, value, gas, price *big.I
case NUMBER:
number := self.env.BlockNumber()
- stack.Push(number)
+ stack.Push(U256(number))
self.Printf(" => 0x%x", number.Bytes())
case DIFFICULTY:
@@ -578,7 +578,7 @@ func (self *Vm) Run(me, caller ContextRef, code []byte, value, gas, price *big.I
}
data := mem.Get(mStart.Int64(), mSize.Int64())
- log := &Log{context.Address(), topics, data}
+ log := &Log{context.Address(), topics, data, self.env.BlockNumber().Uint64()}
self.env.AddLog(log)
self.Printf(" => %v", log)
@@ -676,6 +676,7 @@ func (self *Vm) Run(me, caller ContextRef, code []byte, value, gas, price *big.I
gas := stack.Pop()
// Pop gas and value of the stack.
value, addr := stack.Popn()
+ value = U256(value)
// Pop input size and offset
inSize, inOffset := stack.Popn()
// Pop return size and offset
@@ -778,9 +779,9 @@ func (self *Vm) calculateGasAndSize(context *Context, caller ContextRef, op OpCo
// Stack Check, memory resize & gas phase
switch op {
// Stack checks only
- case ISZERO, CALLDATALOAD, POP, JUMP, NOT: // 1
+ case ISZERO, CALLDATALOAD, POP, JUMP, NOT, EXTCODESIZE, BLOCKHASH: // 1
stack.require(1)
- case JUMPI, ADD, SUB, DIV, SDIV, MOD, SMOD, LT, GT, SLT, SGT, EQ, AND, OR, XOR, BYTE, SIGNEXTEND: // 2
+ case JUMPI, ADD, SUB, DIV, MUL, SDIV, MOD, SMOD, LT, GT, SLT, SGT, EQ, AND, OR, XOR, BYTE, SIGNEXTEND: // 2
stack.require(2)
case ADDMOD, MULMOD: // 3
stack.require(3)
@@ -858,7 +859,7 @@ func (self *Vm) calculateGasAndSize(context *Context, caller ContextRef, op OpCo
newMemSize = calcMemSize(stack.Peek(), stack.data[stack.Len()-2])
additionalGas.Set(stack.data[stack.Len()-2])
case CALLDATACOPY:
- stack.require(2)
+ stack.require(3)
newMemSize = calcMemSize(stack.Peek(), stack.data[stack.Len()-3])
additionalGas.Set(stack.data[stack.Len()-3])
diff --git a/xeth/types.go b/xeth/types.go
index a903fccbb..5b2d16018 100644
--- a/xeth/types.go
+++ b/xeth/types.go
@@ -150,7 +150,7 @@ type Transaction struct {
func NewTx(tx *types.Transaction) *Transaction {
hash := toHex(tx.Hash())
receiver := toHex(tx.To())
- if receiver == "0000000000000000000000000000000000000000" {
+ if len(receiver) == 0 {
receiver = toHex(core.AddressFromMessage(tx))
}
sender := toHex(tx.From())
diff --git a/xeth/xeth.go b/xeth/xeth.go
index 27435b956..5907a8329 100644
--- a/xeth/xeth.go
+++ b/xeth/xeth.go
@@ -7,6 +7,7 @@ package xeth
import (
"bytes"
"encoding/json"
+ "fmt"
"github.com/ethereum/go-ethereum/core"
"github.com/ethereum/go-ethereum/core/types"
@@ -16,7 +17,6 @@ import (
"github.com/ethereum/go-ethereum/logger"
"github.com/ethereum/go-ethereum/miner"
"github.com/ethereum/go-ethereum/p2p"
- "github.com/ethereum/go-ethereum/state"
"github.com/ethereum/go-ethereum/whisper"
)
@@ -103,6 +103,17 @@ func (self *XEth) IsMining() bool {
return self.miner.Mining()
}
+func (self *XEth) SetMining(shouldmine bool) bool {
+ ismining := self.miner.Mining()
+ if shouldmine && !ismining {
+ self.miner.Start()
+ }
+ if ismining && !shouldmine {
+ self.miner.Stop()
+ }
+ return self.miner.Mining()
+}
+
func (self *XEth) IsListening() bool {
return self.eth.IsListening()
}
@@ -128,15 +139,15 @@ func (self *XEth) BalanceAt(addr string) string {
}
func (self *XEth) TxCountAt(address string) int {
- return int(self.State().SafeGet(address).Nonce)
+ return int(self.State().SafeGet(address).Nonce())
}
func (self *XEth) CodeAt(address string) string {
- return toHex(self.State().SafeGet(address).Code)
+ return toHex(self.State().SafeGet(address).Code())
}
func (self *XEth) IsContract(address string) bool {
- return len(self.State().SafeGet(address).Code) > 0
+ return len(self.State().SafeGet(address).Code()) > 0
}
func (self *XEth) SecretToAddress(key string) string {
@@ -220,7 +231,7 @@ func (self *XEth) Call(toStr, valueStr, gasStr, gasPriceStr, dataStr string) (st
var (
statedb = self.chainManager.TransState()
key = self.eth.KeyManager().KeyPair()
- from = state.NewStateObject(key.Address(), self.eth.Db())
+ from = statedb.GetOrNewStateObject(key.Address())
block = self.chainManager.CurrentBlock()
to = statedb.GetOrNewStateObject(fromHex(toStr))
data = fromHex(dataStr)
@@ -242,7 +253,6 @@ func (self *XEth) Call(toStr, valueStr, gasStr, gasPriceStr, dataStr string) (st
}
func (self *XEth) Transact(toStr, valueStr, gasStr, gasPriceStr, codeStr string) (string, error) {
-
var (
to []byte
value = ethutil.NewValue(valueStr)
@@ -266,29 +276,30 @@ func (self *XEth) Transact(toStr, valueStr, gasStr, gasPriceStr, codeStr string)
tx = types.NewTransactionMessage(to, value.BigInt(), gas.BigInt(), price.BigInt(), data)
}
- state := self.chainManager.TransState()
+ var err error
+ state := self.eth.ChainManager().TransState()
+ if balance := state.GetBalance(key.Address()); balance.Cmp(tx.Value()) < 0 {
+ return "", fmt.Errorf("insufficient balance. balance=%v tx=%v", balance, tx.Value())
+ }
nonce := state.GetNonce(key.Address())
tx.SetNonce(nonce)
tx.Sign(key.PrivateKey)
+ //fmt.Printf("create tx: %x %v\n", tx.Hash()[:4], tx.Nonce())
+
// Do some pre processing for our "pre" events and hooks
block := self.chainManager.NewBlock(key.Address())
coinbase := state.GetOrNewStateObject(key.Address())
coinbase.SetGasPool(block.GasLimit())
self.blockProcessor.ApplyTransactions(coinbase, state, block, types.Transactions{tx}, true)
- err := self.eth.TxPool().Add(tx)
+ err = self.eth.TxPool().Add(tx)
if err != nil {
return "", err
}
state.SetNonce(key.Address(), nonce+1)
- if contractCreation {
- addr := core.AddressFromMessage(tx)
- pipelogger.Infof("Contract addr %x\n", addr)
- }
-
if types.IsContractAddr(to) {
return toHex(core.AddressFromMessage(tx)), nil
}