aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--build/ci.go5
-rw-r--r--core/tx_pool.go19
-rw-r--r--core/tx_pool_test.go54
-rw-r--r--crypto/ecies/asn1.go584
-rw-r--r--crypto/ecies/ecies.go10
-rw-r--r--crypto/ecies/ecies_test.go186
-rw-r--r--crypto/ecies/params.go93
-rw-r--r--crypto/sha3/sha3.go5
-rw-r--r--crypto/sha3/sha3_test.go11
-rw-r--r--eth/api.go20
-rw-r--r--eth/downloader/downloader_test.go19
-rw-r--r--eth/filters/api.go1
-rw-r--r--eth/filters/filter.go3
-rw-r--r--eth/filters/filter_system.go1
-rw-r--r--eth/filters/filter_system_test.go7
-rw-r--r--eth/sync.go6
-rw-r--r--ethdb/database_test.go161
-rw-r--r--internal/build/util.go16
-rw-r--r--internal/ethapi/api.go29
-rw-r--r--internal/jsre/pretty.go8
-rw-r--r--light/lightchain.go1
-rw-r--r--light/lightchain_test.go13
-rw-r--r--light/txpool.go6
-rw-r--r--rpc/server.go29
-rw-r--r--rpc/subscription.go1
-rw-r--r--rpc/subscription_test.go16
-rw-r--r--rpc/types.go13
-rw-r--r--rpc/utils.go27
28 files changed, 274 insertions, 1070 deletions
diff --git a/build/ci.go b/build/ci.go
index e631d70ef..6fe03db71 100644
--- a/build/ci.go
+++ b/build/ci.go
@@ -250,10 +250,7 @@ func goTool(subcmd string, args ...string) *exec.Cmd {
}
func goToolArch(arch string, subcmd string, args ...string) *exec.Cmd {
- gocmd := filepath.Join(runtime.GOROOT(), "bin", "go")
- cmd := exec.Command(gocmd, subcmd)
- cmd.Args = append(cmd.Args, args...)
-
+ cmd := build.GoTool(subcmd, args...)
if subcmd == "build" || subcmd == "install" || subcmd == "test" {
// Go CGO has a Windows linker error prior to 1.8 (https://github.com/golang/go/issues/8756).
// Work around issue by allowing multiple definitions for <1.8 builds.
diff --git a/core/tx_pool.go b/core/tx_pool.go
index 16f774265..b0c251f92 100644
--- a/core/tx_pool.go
+++ b/core/tx_pool.go
@@ -207,7 +207,7 @@ func NewTxPool(config TxPoolConfig, chainconfig *params.ChainConfig, eventMux *e
}
pool.locals = newAccountSet(pool.signer)
pool.priced = newTxPricedList(&pool.all)
- pool.resetState()
+ pool.reset()
// If local transactions and journaling is enabled, load from disk
if !config.NoLocals && config.Journal != "" {
@@ -261,7 +261,7 @@ func (pool *TxPool) loop() {
pool.homestead = true
}
}
- pool.resetState()
+ pool.reset()
pool.mu.Unlock()
case RemovedTransactionEvent:
@@ -300,15 +300,28 @@ func (pool *TxPool) loop() {
// Handle local transaction journal rotation
case <-journal.C:
if pool.journal != nil {
+ pool.mu.Lock()
if err := pool.journal.rotate(pool.local()); err != nil {
log.Warn("Failed to rotate local tx journal", "err", err)
}
+ pool.mu.Unlock()
}
}
}
}
-func (pool *TxPool) resetState() {
+// lockedReset is a wrapper around reset to allow calling it in a thread safe
+// manner. This method is only ever used in the tester!
+func (pool *TxPool) lockedReset() {
+ pool.mu.Lock()
+ defer pool.mu.Unlock()
+
+ pool.reset()
+}
+
+// reset retrieves the current state of the blockchain and ensures the content
+// of the transaction pool is valid with regard to the chain state.
+func (pool *TxPool) reset() {
currentState, err := pool.currentState()
if err != nil {
log.Error("Failed reset txpool state", "err", err)
diff --git a/core/tx_pool_test.go b/core/tx_pool_test.go
index 020d6bedd..fcb330051 100644
--- a/core/tx_pool_test.go
+++ b/core/tx_pool_test.go
@@ -153,7 +153,7 @@ func TestStateChangeDuringPoolReset(t *testing.T) {
// trigger state change in the background
trigger = true
- pool.resetState()
+ pool.lockedReset()
pendingTx, err := pool.Pending()
if err != nil {
@@ -213,7 +213,7 @@ func TestTransactionQueue(t *testing.T) {
from, _ := deriveSender(tx)
currentState, _ := pool.currentState()
currentState.AddBalance(from, big.NewInt(1000))
- pool.resetState()
+ pool.lockedReset()
pool.enqueueTx(tx.Hash(), tx)
pool.promoteExecutables(currentState, []common.Address{from})
@@ -243,7 +243,7 @@ func TestTransactionQueue(t *testing.T) {
from, _ = deriveSender(tx1)
currentState, _ = pool.currentState()
currentState.AddBalance(from, big.NewInt(1000))
- pool.resetState()
+ pool.lockedReset()
pool.enqueueTx(tx1.Hash(), tx1)
pool.enqueueTx(tx2.Hash(), tx2)
@@ -314,7 +314,7 @@ func TestTransactionChainFork(t *testing.T) {
pool.currentState = func() (*state.StateDB, error) { return statedb, nil }
currentState, _ := pool.currentState()
currentState.AddBalance(addr, big.NewInt(100000000000000))
- pool.resetState()
+ pool.lockedReset()
}
resetState()
@@ -342,7 +342,7 @@ func TestTransactionDoubleNonce(t *testing.T) {
pool.currentState = func() (*state.StateDB, error) { return statedb, nil }
currentState, _ := pool.currentState()
currentState.AddBalance(addr, big.NewInt(100000000000000))
- pool.resetState()
+ pool.lockedReset()
}
resetState()
@@ -412,14 +412,14 @@ func TestNonceRecovery(t *testing.T) {
currentState, _ := pool.currentState()
currentState.SetNonce(addr, n)
currentState.AddBalance(addr, big.NewInt(100000000000000))
- pool.resetState()
+ pool.lockedReset()
tx := transaction(n, big.NewInt(100000), key)
if err := pool.AddRemote(tx); err != nil {
t.Error(err)
}
// simulate some weird re-order of transactions and missing nonce(s)
currentState.SetNonce(addr, n-1)
- pool.resetState()
+ pool.lockedReset()
if fn := pool.pendingState.GetNonce(addr); fn != n+1 {
t.Errorf("expected nonce to be %d, got %d", n+1, fn)
}
@@ -433,7 +433,7 @@ func TestRemovedTxEvent(t *testing.T) {
from, _ := deriveSender(tx)
currentState, _ := pool.currentState()
currentState.AddBalance(from, big.NewInt(1000000000000))
- pool.resetState()
+ pool.lockedReset()
pool.eventMux.Post(RemovedTransactionEvent{types.Transactions{tx}})
pool.eventMux.Post(ChainHeadEvent{nil})
if pool.pending[from].Len() != 1 {
@@ -482,7 +482,7 @@ func TestTransactionDropping(t *testing.T) {
if len(pool.all) != 6 {
t.Errorf("total transaction mismatch: have %d, want %d", len(pool.all), 6)
}
- pool.resetState()
+ pool.lockedReset()
if pool.pending[account].Len() != 3 {
t.Errorf("pending transaction mismatch: have %d, want %d", pool.pending[account].Len(), 3)
}
@@ -494,7 +494,7 @@ func TestTransactionDropping(t *testing.T) {
}
// Reduce the balance of the account, and check that invalidated transactions are dropped
state.AddBalance(account, big.NewInt(-650))
- pool.resetState()
+ pool.lockedReset()
if _, ok := pool.pending[account].txs.items[tx0.Nonce()]; !ok {
t.Errorf("funded pending transaction missing: %v", tx0)
@@ -519,7 +519,7 @@ func TestTransactionDropping(t *testing.T) {
}
// Reduce the block gas limit, check that invalidated transactions are dropped
pool.gasLimit = func() *big.Int { return big.NewInt(100) }
- pool.resetState()
+ pool.lockedReset()
if _, ok := pool.pending[account].txs.items[tx0.Nonce()]; !ok {
t.Errorf("funded pending transaction missing: %v", tx0)
@@ -573,7 +573,7 @@ func TestTransactionPostponing(t *testing.T) {
if len(pool.all) != len(txns) {
t.Errorf("total transaction mismatch: have %d, want %d", len(pool.all), len(txns))
}
- pool.resetState()
+ pool.lockedReset()
if pool.pending[account].Len() != len(txns) {
t.Errorf("pending transaction mismatch: have %d, want %d", pool.pending[account].Len(), len(txns))
}
@@ -585,7 +585,7 @@ func TestTransactionPostponing(t *testing.T) {
}
// Reduce the balance of the account, and check that transactions are reorganised
state.AddBalance(account, big.NewInt(-750))
- pool.resetState()
+ pool.lockedReset()
if _, ok := pool.pending[account].txs.items[txns[0].Nonce()]; !ok {
t.Errorf("tx %d: valid and funded transaction missing from pending pool: %v", 0, txns[0])
@@ -626,7 +626,7 @@ func TestTransactionQueueAccountLimiting(t *testing.T) {
state, _ := pool.currentState()
state.AddBalance(account, big.NewInt(1000000))
- pool.resetState()
+ pool.lockedReset()
// Keep queuing up transactions and make sure all above a limit are dropped
for i := uint64(1); i <= testTxPoolConfig.AccountQueue+5; i++ {
@@ -780,7 +780,7 @@ func testTransactionQueueTimeLimiting(t *testing.T, nolocals bool) {
if err := pool.AddRemote(pricedTransaction(1, big.NewInt(100000), big.NewInt(1), remote)); err != nil {
t.Fatalf("failed to add remote transaction: %v", err)
}
- pending, queued := pool.stats()
+ pending, queued := pool.Stats()
if pending != 0 {
t.Fatalf("pending transactions mismatched: have %d, want %d", pending, 0)
}
@@ -793,7 +793,7 @@ func testTransactionQueueTimeLimiting(t *testing.T, nolocals bool) {
// Wait a bit for eviction to run and clean up any leftovers, and ensure only the local remains
time.Sleep(2 * config.Lifetime)
- pending, queued = pool.stats()
+ pending, queued = pool.Stats()
if pending != 0 {
t.Fatalf("pending transactions mismatched: have %d, want %d", pending, 0)
}
@@ -823,7 +823,7 @@ func TestTransactionPendingLimiting(t *testing.T) {
state, _ := pool.currentState()
state.AddBalance(account, big.NewInt(1000000))
- pool.resetState()
+ pool.lockedReset()
// Keep queuing up transactions and make sure all above a limit are dropped
for i := uint64(0); i < testTxPoolConfig.AccountQueue+5; i++ {
@@ -1057,7 +1057,7 @@ func TestTransactionPoolRepricing(t *testing.T) {
pool.AddRemotes(txs)
pool.AddLocal(ltx)
- pending, queued := pool.stats()
+ pending, queued := pool.Stats()
if pending != 4 {
t.Fatalf("pending transactions mismatched: have %d, want %d", pending, 4)
}
@@ -1070,7 +1070,7 @@ func TestTransactionPoolRepricing(t *testing.T) {
// Reprice the pool and check that underpriced transactions get dropped
pool.SetGasPrice(big.NewInt(2))
- pending, queued = pool.stats()
+ pending, queued = pool.Stats()
if pending != 2 {
t.Fatalf("pending transactions mismatched: have %d, want %d", pending, 2)
}
@@ -1095,7 +1095,7 @@ func TestTransactionPoolRepricing(t *testing.T) {
if err := pool.AddLocal(tx); err != nil {
t.Fatalf("failed to add underpriced local transaction: %v", err)
}
- if pending, _ = pool.stats(); pending != 3 {
+ if pending, _ = pool.Stats(); pending != 3 {
t.Fatalf("pending transactions mismatched: have %d, want %d", pending, 3)
}
if err := validateTxPoolInternals(pool); err != nil {
@@ -1142,7 +1142,7 @@ func TestTransactionPoolUnderpricing(t *testing.T) {
pool.AddRemotes(txs)
pool.AddLocal(ltx)
- pending, queued := pool.stats()
+ pending, queued := pool.Stats()
if pending != 3 {
t.Fatalf("pending transactions mismatched: have %d, want %d", pending, 3)
}
@@ -1166,7 +1166,7 @@ func TestTransactionPoolUnderpricing(t *testing.T) {
if err := pool.AddRemote(pricedTransaction(3, big.NewInt(100000), big.NewInt(5), keys[1])); err != nil {
t.Fatalf("failed to add well priced transaction: %v", err)
}
- pending, queued = pool.stats()
+ pending, queued = pool.Stats()
if pending != 2 {
t.Fatalf("pending transactions mismatched: have %d, want %d", pending, 2)
}
@@ -1181,7 +1181,7 @@ func TestTransactionPoolUnderpricing(t *testing.T) {
if err := pool.AddLocal(tx); err != nil {
t.Fatalf("failed to add underpriced local transaction: %v", err)
}
- pending, queued = pool.stats()
+ pending, queued = pool.Stats()
if pending != 2 {
t.Fatalf("pending transactions mismatched: have %d, want %d", pending, 2)
}
@@ -1307,7 +1307,7 @@ func testTransactionJournaling(t *testing.T, nolocals bool) {
if err := pool.AddRemote(pricedTransaction(0, big.NewInt(100000), big.NewInt(1), remote)); err != nil {
t.Fatalf("failed to add remote transaction: %v", err)
}
- pending, queued := pool.stats()
+ pending, queued := pool.Stats()
if pending != 4 {
t.Fatalf("pending transactions mismatched: have %d, want %d", pending, 4)
}
@@ -1322,7 +1322,7 @@ func testTransactionJournaling(t *testing.T, nolocals bool) {
statedb.SetNonce(crypto.PubkeyToAddress(local.PublicKey), 1)
pool = NewTxPool(config, params.TestChainConfig, new(event.TypeMux), func() (*state.StateDB, error) { return statedb, nil }, func() *big.Int { return big.NewInt(1000000) })
- pending, queued = pool.stats()
+ pending, queued = pool.Stats()
if queued != 0 {
t.Fatalf("queued transactions mismatched: have %d, want %d", queued, 0)
}
@@ -1340,13 +1340,13 @@ func testTransactionJournaling(t *testing.T, nolocals bool) {
}
// Bump the nonce temporarily and ensure the newly invalidated transaction is removed
statedb.SetNonce(crypto.PubkeyToAddress(local.PublicKey), 2)
- pool.resetState()
+ pool.lockedReset()
time.Sleep(2 * config.Rejournal)
pool.Stop()
statedb.SetNonce(crypto.PubkeyToAddress(local.PublicKey), 1)
pool = NewTxPool(config, params.TestChainConfig, new(event.TypeMux), func() (*state.StateDB, error) { return statedb, nil }, func() *big.Int { return big.NewInt(1000000) })
- pending, queued = pool.stats()
+ pending, queued = pool.Stats()
if pending != 0 {
t.Fatalf("pending transactions mismatched: have %d, want %d", pending, 0)
}
diff --git a/crypto/ecies/asn1.go b/crypto/ecies/asn1.go
deleted file mode 100644
index d3e77d849..000000000
--- a/crypto/ecies/asn1.go
+++ /dev/null
@@ -1,584 +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.
-
-package ecies
-
-import (
- "bytes"
- "crypto"
- "crypto/elliptic"
- "crypto/sha1"
- "crypto/sha256"
- "crypto/sha512"
- "encoding/asn1"
- "encoding/pem"
- "fmt"
- "hash"
- "math/big"
-
- ethcrypto "github.com/ethereum/go-ethereum/crypto"
-)
-
-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 (
- secgNamedCurveS256 = secgNamedCurve{1, 3, 132, 0, 10}
- secgNamedCurveP256 = secgNamedCurve{1, 2, 840, 10045, 3, 1, 7}
- secgNamedCurveP384 = secgNamedCurve{1, 3, 132, 0, 34}
- secgNamedCurveP521 = secgNamedCurve{1, 3, 132, 0, 35}
- 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.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(secgNamedCurveS256):
- return ethcrypto.S256()
- 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.P256():
- return secgNamedCurveP256, true
- case elliptic.P384():
- return secgNamedCurveP384, true
- case elliptic.P521():
- return secgNamedCurveP521, true
- case ethcrypto.S256():
- return secgNamedCurveS256, 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.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/crypto/ecies/ecies.go b/crypto/ecies/ecies.go
index 2a16f20a2..1d5f96ed2 100644
--- a/crypto/ecies/ecies.go
+++ b/crypto/ecies/ecies.go
@@ -151,14 +151,16 @@ var (
func incCounter(ctr []byte) {
if ctr[3]++; ctr[3] != 0 {
return
- } else if ctr[2]++; ctr[2] != 0 {
+ }
+ if ctr[2]++; ctr[2] != 0 {
return
- } else if ctr[1]++; ctr[1] != 0 {
+ }
+ if ctr[1]++; ctr[1] != 0 {
return
- } else if ctr[0]++; ctr[0] != 0 {
+ }
+ if ctr[0]++; ctr[0] != 0 {
return
}
- return
}
// NIST SP 800-56 Concatenation Key Derivation Function (see section 5.8.1).
diff --git a/crypto/ecies/ecies_test.go b/crypto/ecies/ecies_test.go
index 7c454aa73..9cd5c79f7 100644
--- a/crypto/ecies/ecies_test.go
+++ b/crypto/ecies/ecies_test.go
@@ -37,7 +37,6 @@ import (
"encoding/hex"
"flag"
"fmt"
- "io/ioutil"
"math/big"
"testing"
@@ -63,8 +62,7 @@ func TestKDF(t *testing.T) {
t.FailNow()
}
if len(k) != 64 {
- fmt.Printf("KDF: generated key is the wrong size (%d instead of 64\n",
- len(k))
+ fmt.Printf("KDF: generated key is the wrong size (%d instead of 64\n", len(k))
t.FailNow()
}
}
@@ -74,14 +72,9 @@ 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
+ return p1.hashAlgo == p2.hashAlgo &&
+ p1.KeyLen == p2.KeyLen &&
+ p1.BlockSize == p2.BlockSize
}
// cmpPublic returns true if the two public keys represent the same pojnt.
@@ -212,118 +205,6 @@ func TestTooBigSharedKey(t *testing.T) {
}
}
-// 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 {
- t.Fatalf("GenerateKey error: %s", err)
- }
-
- out, err := MarshalPublic(&prv.PublicKey)
- if err != nil {
- t.Fatalf("MarshalPublic error: %s", err)
- }
-
- pub, err := UnmarshalPublic(out)
- if err != nil {
- t.Fatalf("UnmarshalPublic error: %s", err)
- }
-
- if !cmpPublic(prv.PublicKey, *pub) {
- t.Fatal("ecies: failed to unmarshal public key")
- }
-}
-
-// 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++ {
@@ -437,74 +318,27 @@ func TestDecryptShared2(t *testing.T) {
}
}
-// 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
+ Expected *ECIESParams
}
var testCases = []testCase{
{
Curve: elliptic.P256(),
Name: "P256",
- Expected: true,
+ Expected: ECIES_AES128_SHA256,
},
{
Curve: elliptic.P384(),
Name: "P384",
- Expected: true,
+ Expected: ECIES_AES256_SHA384,
},
{
Curve: elliptic.P521(),
Name: "P521",
- Expected: true,
+ Expected: ECIES_AES256_SHA512,
},
}
@@ -519,10 +353,10 @@ func TestParamSelection(t *testing.T) {
func testParamSelection(t *testing.T, c testCase) {
params := ParamsFromCurve(c.Curve)
- if params == nil && c.Expected {
+ if params == nil && c.Expected != nil {
fmt.Printf("%s (%s)\n", ErrInvalidParams.Error(), c.Name)
t.FailNow()
- } else if params != nil && !c.Expected {
+ } else if params != nil && !cmpParams(params, c.Expected) {
fmt.Printf("ecies: parameters should be invalid (%s)\n",
c.Name)
t.FailNow()
diff --git a/crypto/ecies/params.go b/crypto/ecies/params.go
index 826d90c84..6312daf5a 100644
--- a/crypto/ecies/params.go
+++ b/crypto/ecies/params.go
@@ -114,97 +114,4 @@ func AddParamsForCurve(curve elliptic.Curve, params *ECIESParams) {
// 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/crypto/sha3/sha3.go b/crypto/sha3/sha3.go
index c86167c0b..b12a35c87 100644
--- a/crypto/sha3/sha3.go
+++ b/crypto/sha3/sha3.go
@@ -42,9 +42,8 @@ type state struct {
storage [maxRate]byte
// Specific to SHA-3 and SHAKE.
- fixedOutput bool // whether this is a fixed-output-length instance
- outputLen int // the default output size in bytes
- state spongeDirection // whether the sponge is absorbing or squeezing
+ outputLen int // the default output size in bytes
+ state spongeDirection // whether the sponge is absorbing or squeezing
}
// BlockSize returns the rate of sponge underlying this hash function.
diff --git a/crypto/sha3/sha3_test.go b/crypto/sha3/sha3_test.go
index c433761a8..0e33676ce 100644
--- a/crypto/sha3/sha3_test.go
+++ b/crypto/sha3/sha3_test.go
@@ -53,15 +53,6 @@ var testShakes = map[string]func() ShakeHash{
"SHAKE256": NewShake256,
}
-// decodeHex converts a hex-encoded string into a raw byte string.
-func decodeHex(s string) []byte {
- b, err := hex.DecodeString(s)
- if err != nil {
- panic(err)
- }
- return b
-}
-
// structs used to marshal JSON test-cases.
type KeccakKats struct {
Kats map[string][]struct {
@@ -125,7 +116,7 @@ func TestKeccakKats(t *testing.T) {
// TestUnalignedWrite tests that writing data in an arbitrary pattern with
// small input buffers.
-func testUnalignedWrite(t *testing.T) {
+func TestUnalignedWrite(t *testing.T) {
testUnalignedAndGeneric(t, func(impl string) {
buf := sequentialBytes(0x10000)
for alg, df := range testDigests {
diff --git a/eth/api.go b/eth/api.go
index 0d90759b6..f5214fc37 100644
--- a/eth/api.go
+++ b/eth/api.go
@@ -465,26 +465,6 @@ func (api *PrivateDebugAPI) traceBlock(block *types.Block, logConfig *vm.LogConf
return true, structLogger.StructLogs(), nil
}
-// callmsg is the message type used for call transitions.
-type callmsg struct {
- addr common.Address
- to *common.Address
- gas, gasPrice *big.Int
- value *big.Int
- data []byte
-}
-
-// accessor boilerplate to implement core.Message
-func (m callmsg) From() (common.Address, error) { return m.addr, nil }
-func (m callmsg) FromFrontier() (common.Address, error) { return m.addr, nil }
-func (m callmsg) Nonce() uint64 { return 0 }
-func (m callmsg) CheckNonce() bool { return false }
-func (m callmsg) To() *common.Address { return m.to }
-func (m callmsg) GasPrice() *big.Int { return m.gasPrice }
-func (m callmsg) Gas() *big.Int { return m.gas }
-func (m callmsg) Value() *big.Int { return m.value }
-func (m callmsg) Data() []byte { return m.data }
-
// formatError formats a Go error into either an empty string or the data content
// of the error itself.
func formatError(err error) string {
diff --git a/eth/downloader/downloader_test.go b/eth/downloader/downloader_test.go
index b354682a1..36e8c800f 100644
--- a/eth/downloader/downloader_test.go
+++ b/eth/downloader/downloader_test.go
@@ -403,8 +403,7 @@ func (dl *downloadTester) newSlowPeer(id string, version int, hashes []common.Ha
dl.lock.Lock()
defer dl.lock.Unlock()
- var err error
- err = dl.downloader.RegisterPeer(id, version, &downloadTesterPeer{dl, id, delay})
+ var err = dl.downloader.RegisterPeer(id, version, &downloadTesterPeer{dl, id, delay})
if err == nil {
// Assign the owned hashes, headers and blocks to the peer (deep copy)
dl.peerHashes[id] = make([]common.Hash, len(hashes))
@@ -1381,7 +1380,7 @@ func testSyncProgress(t *testing.T, protocol int, mode SyncMode) {
go func() {
defer pending.Done()
if err := tester.sync("peer-half", nil, mode); err != nil {
- t.Fatalf("failed to synchronise blocks: %v", err)
+ panic(fmt.Sprintf("failed to synchronise blocks: %v", err))
}
}()
<-starting
@@ -1398,7 +1397,7 @@ func testSyncProgress(t *testing.T, protocol int, mode SyncMode) {
go func() {
defer pending.Done()
if err := tester.sync("peer-full", nil, mode); err != nil {
- t.Fatalf("failed to synchronise blocks: %v", err)
+ panic(fmt.Sprintf("failed to synchronise blocks: %v", err))
}
}()
<-starting
@@ -1454,7 +1453,7 @@ func testForkedSyncProgress(t *testing.T, protocol int, mode SyncMode) {
go func() {
defer pending.Done()
if err := tester.sync("fork A", nil, mode); err != nil {
- t.Fatalf("failed to synchronise blocks: %v", err)
+ panic(fmt.Sprintf("failed to synchronise blocks: %v", err))
}
}()
<-starting
@@ -1474,7 +1473,7 @@ func testForkedSyncProgress(t *testing.T, protocol int, mode SyncMode) {
go func() {
defer pending.Done()
if err := tester.sync("fork B", nil, mode); err != nil {
- t.Fatalf("failed to synchronise blocks: %v", err)
+ panic(fmt.Sprintf("failed to synchronise blocks: %v", err))
}
}()
<-starting
@@ -1535,7 +1534,7 @@ func testFailedSyncProgress(t *testing.T, protocol int, mode SyncMode) {
go func() {
defer pending.Done()
if err := tester.sync("faulty", nil, mode); err == nil {
- t.Fatalf("succeeded faulty synchronisation")
+ panic("succeeded faulty synchronisation")
}
}()
<-starting
@@ -1552,7 +1551,7 @@ func testFailedSyncProgress(t *testing.T, protocol int, mode SyncMode) {
go func() {
defer pending.Done()
if err := tester.sync("valid", nil, mode); err != nil {
- t.Fatalf("failed to synchronise blocks: %v", err)
+ panic(fmt.Sprintf("failed to synchronise blocks: %v", err))
}
}()
<-starting
@@ -1613,7 +1612,7 @@ func testFakedSyncProgress(t *testing.T, protocol int, mode SyncMode) {
go func() {
defer pending.Done()
if err := tester.sync("attack", nil, mode); err == nil {
- t.Fatalf("succeeded attacker synchronisation")
+ panic("succeeded attacker synchronisation")
}
}()
<-starting
@@ -1630,7 +1629,7 @@ func testFakedSyncProgress(t *testing.T, protocol int, mode SyncMode) {
go func() {
defer pending.Done()
if err := tester.sync("valid", nil, mode); err != nil {
- t.Fatalf("failed to synchronise blocks: %v", err)
+ panic(fmt.Sprintf("failed to synchronise blocks: %v", err))
}
}()
<-starting
diff --git a/eth/filters/api.go b/eth/filters/api.go
index 61647a5d0..fff58a268 100644
--- a/eth/filters/api.go
+++ b/eth/filters/api.go
@@ -54,7 +54,6 @@ type PublicFilterAPI struct {
backend Backend
useMipMap bool
mux *event.TypeMux
- quit chan struct{}
chainDb ethdb.Database
events *EventSystem
filtersMu sync.Mutex
diff --git a/eth/filters/filter.go b/eth/filters/filter.go
index 0a0b81224..f27b76929 100644
--- a/eth/filters/filter.go
+++ b/eth/filters/filter.go
@@ -20,7 +20,6 @@ import (
"context"
"math"
"math/big"
- "time"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core"
@@ -42,8 +41,6 @@ type Filter struct {
backend Backend
useMipMap bool
- created time.Time
-
db ethdb.Database
begin, end int64
addresses []common.Address
diff --git a/eth/filters/filter_system.go b/eth/filters/filter_system.go
index 7abace1e6..ab0b7473e 100644
--- a/eth/filters/filter_system.go
+++ b/eth/filters/filter_system.go
@@ -74,7 +74,6 @@ type subscription struct {
// subscription which match the subscription criteria.
type EventSystem struct {
mux *event.TypeMux
- sub *event.TypeMuxSubscription
backend Backend
lightMode bool
lastHead *types.Header
diff --git a/eth/filters/filter_system_test.go b/eth/filters/filter_system_test.go
index 822580b56..23e6d66e1 100644
--- a/eth/filters/filter_system_test.go
+++ b/eth/filters/filter_system_test.go
@@ -18,6 +18,7 @@ package filters
import (
"context"
+ "fmt"
"math/big"
"reflect"
"testing"
@@ -439,15 +440,15 @@ func TestPendingLogsSubscription(t *testing.T) {
}
if len(fetched) != len(tt.expected) {
- t.Fatalf("invalid number of logs for case %d, want %d log(s), got %d", i, len(tt.expected), len(fetched))
+ panic(fmt.Sprintf("invalid number of logs for case %d, want %d log(s), got %d", i, len(tt.expected), len(fetched)))
}
for l := range fetched {
if fetched[l].Removed {
- t.Errorf("expected log not to be removed for log %d in case %d", l, i)
+ panic(fmt.Sprintf("expected log not to be removed for log %d in case %d", l, i))
}
if !reflect.DeepEqual(fetched[l], tt.expected[l]) {
- t.Errorf("invalid log on index %d for case %d", l, i)
+ panic(fmt.Sprintf("invalid log on index %d for case %d", l, i))
}
}
}()
diff --git a/eth/sync.go b/eth/sync.go
index 8784b225d..7442f912c 100644
--- a/eth/sync.go
+++ b/eth/sync.go
@@ -138,7 +138,9 @@ func (pm *ProtocolManager) syncer() {
defer pm.downloader.Terminate()
// Wait for different events to fire synchronisation operations
- forceSync := time.Tick(forceSyncCycle)
+ forceSync := time.NewTicker(forceSyncCycle)
+ defer forceSync.Stop()
+
for {
select {
case <-pm.newPeerCh:
@@ -148,7 +150,7 @@ func (pm *ProtocolManager) syncer() {
}
go pm.synchronise(pm.peers.BestPeer())
- case <-forceSync:
+ case <-forceSync.C:
// Force a sync even if not enough peers are present
go pm.synchronise(pm.peers.BestPeer())
diff --git a/ethdb/database_test.go b/ethdb/database_test.go
index 0e69a1218..4740cdaed 100644
--- a/ethdb/database_test.go
+++ b/ethdb/database_test.go
@@ -14,21 +14,164 @@
// You should have received a copy of the GNU Lesser General Public License
// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
-package ethdb
+package ethdb_test
import (
+ "bytes"
+ "fmt"
+ "io/ioutil"
"os"
- "path/filepath"
+ "strconv"
+ "sync"
+ "testing"
- "github.com/ethereum/go-ethereum/common"
+ "github.com/ethereum/go-ethereum/ethdb"
)
-func newDb() *LDBDatabase {
- file := filepath.Join("/", "tmp", "ldbtesttmpfile")
- if common.FileExist(file) {
- os.RemoveAll(file)
+func newTestLDB() (*ethdb.LDBDatabase, func()) {
+ dirname, err := ioutil.TempDir(os.TempDir(), "ethdb_test_")
+ if err != nil {
+ panic("failed to create test file: " + err.Error())
+ }
+ db, err := ethdb.NewLDBDatabase(dirname, 0, 0)
+ if err != nil {
+ panic("failed to create test database: " + err.Error())
+ }
+
+ return db, func() {
+ db.Close()
+ os.RemoveAll(dirname)
+ }
+}
+
+var test_values = []string{"", "a", "1251", "\x00123\x00"}
+
+func TestLDB_PutGet(t *testing.T) {
+ db, remove := newTestLDB()
+ defer remove()
+ testPutGet(db, t)
+}
+
+func TestMemoryDB_PutGet(t *testing.T) {
+ db, _ := ethdb.NewMemDatabase()
+ testPutGet(db, t)
+}
+
+func testPutGet(db ethdb.Database, t *testing.T) {
+ t.Parallel()
+
+ for _, v := range test_values {
+ err := db.Put([]byte(v), []byte(v))
+ if err != nil {
+ t.Fatalf("put failed: %v", err)
+ }
+ }
+
+ for _, v := range test_values {
+ data, err := db.Get([]byte(v))
+ if err != nil {
+ t.Fatalf("get failed: %v", err)
+ }
+ if !bytes.Equal(data, []byte(v)) {
+ t.Fatalf("get returned wrong result, got %q expected %q", string(data), v)
+ }
+ }
+
+ for _, v := range test_values {
+ err := db.Put([]byte(v), []byte("?"))
+ if err != nil {
+ t.Fatalf("put override failed: %v", err)
+ }
+ }
+
+ for _, v := range test_values {
+ data, err := db.Get([]byte(v))
+ if err != nil {
+ t.Fatalf("get failed: %v", err)
+ }
+ if !bytes.Equal(data, []byte("?")) {
+ t.Fatalf("get returned wrong result, got %q expected ?", string(data))
+ }
}
- db, _ := NewLDBDatabase(file, 0, 0)
- return db
+ for _, v := range test_values {
+ err := db.Delete([]byte(v))
+ if err != nil {
+ t.Fatalf("delete %q failed: %v", v, err)
+ }
+ }
+
+ for _, v := range test_values {
+ _, err := db.Get([]byte(v))
+ if err == nil {
+ t.Fatalf("got deleted value %q", v)
+ }
+ }
+}
+
+func TestLDB_ParallelPutGet(t *testing.T) {
+ db, remove := newTestLDB()
+ defer remove()
+ testParallelPutGet(db, t)
+}
+
+func TestMemoryDB_ParallelPutGet(t *testing.T) {
+ db, _ := ethdb.NewMemDatabase()
+ testParallelPutGet(db, t)
+}
+
+func testParallelPutGet(db ethdb.Database, t *testing.T) {
+ const n = 8
+ var pending sync.WaitGroup
+
+ pending.Add(n)
+ for i := 0; i < n; i++ {
+ go func(key string) {
+ defer pending.Done()
+ err := db.Put([]byte(key), []byte("v"+key))
+ if err != nil {
+ panic("put failed: " + err.Error())
+ }
+ }(strconv.Itoa(i))
+ }
+ pending.Wait()
+
+ pending.Add(n)
+ for i := 0; i < n; i++ {
+ go func(key string) {
+ defer pending.Done()
+ data, err := db.Get([]byte(key))
+ if err != nil {
+ panic("get failed: " + err.Error())
+ }
+ if !bytes.Equal(data, []byte("v"+key)) {
+ panic(fmt.Sprintf("get failed, got %q expected %q", []byte(data), []byte("v"+key)))
+ }
+ }(strconv.Itoa(i))
+ }
+ pending.Wait()
+
+ pending.Add(n)
+ for i := 0; i < n; i++ {
+ go func(key string) {
+ defer pending.Done()
+ err := db.Delete([]byte(key))
+ if err != nil {
+ panic("delete failed: " + err.Error())
+ }
+ }(strconv.Itoa(i))
+ }
+ pending.Wait()
+
+ pending.Add(n)
+ for i := 0; i < n; i++ {
+ go func(key string) {
+ defer pending.Done()
+ _, err := db.Get([]byte(key))
+ if err == nil {
+ panic("get succeeded")
+ }
+ }(strconv.Itoa(i))
+ }
+ pending.Wait()
}
diff --git a/internal/build/util.go b/internal/build/util.go
index 44f6760b9..ade9cbe93 100644
--- a/internal/build/util.go
+++ b/internal/build/util.go
@@ -138,6 +138,19 @@ func CopyFile(dst, src string, mode os.FileMode) {
}
}
+// GoTool returns the command that runs a go tool. This uses go from GOROOT instead of PATH
+// so that go commands executed by build use the same version of Go as the 'host' that runs
+// build code. e.g.
+//
+// /usr/lib/go-1.8/bin/go run build/ci.go ...
+//
+// runs using go 1.8 and invokes go 1.8 tools from the same GOROOT. This is also important
+// because runtime.Version checks on the host should match the tools that are run.
+func GoTool(tool string, args ...string) *exec.Cmd {
+ args = append([]string{tool}, args...)
+ return exec.Command(filepath.Join(runtime.GOROOT(), "bin", "go"), args...)
+}
+
// ExpandPackagesNoVendor expands a cmd/go import path pattern, skipping
// vendored packages.
func ExpandPackagesNoVendor(patterns []string) []string {
@@ -148,8 +161,7 @@ func ExpandPackagesNoVendor(patterns []string) []string {
}
}
if expand {
- args := append([]string{"list"}, patterns...)
- cmd := exec.Command(filepath.Join(runtime.GOROOT(), "bin", "go"), args...)
+ cmd := GoTool("list", patterns...)
out, err := cmd.CombinedOutput()
if err != nil {
log.Fatalf("package listing failed: %v\n%s", err, string(out))
diff --git a/internal/ethapi/api.go b/internal/ethapi/api.go
index 1b23ac559..7874b7101 100644
--- a/internal/ethapi/api.go
+++ b/internal/ethapi/api.go
@@ -46,7 +46,6 @@ import (
const (
defaultGas = 90000
defaultGasPrice = 50 * params.Shannon
- emptyHex = "0x"
)
// PublicEthereumAPI provides an API to access Ethereum related information.
@@ -548,26 +547,6 @@ func (s *PublicBlockChainAPI) GetStorageAt(ctx context.Context, address common.A
return res[:], state.Error()
}
-// callmsg is the message type used for call transitions.
-type callmsg struct {
- addr common.Address
- to *common.Address
- gas, gasPrice *big.Int
- value *big.Int
- data []byte
-}
-
-// accessor boilerplate to implement core.Message
-func (m callmsg) From() (common.Address, error) { return m.addr, nil }
-func (m callmsg) FromFrontier() (common.Address, error) { return m.addr, nil }
-func (m callmsg) Nonce() uint64 { return 0 }
-func (m callmsg) CheckNonce() bool { return false }
-func (m callmsg) To() *common.Address { return m.to }
-func (m callmsg) GasPrice() *big.Int { return m.gasPrice }
-func (m callmsg) Gas() *big.Int { return m.gas }
-func (m callmsg) Value() *big.Int { return m.value }
-func (m callmsg) Data() []byte { return m.data }
-
// CallArgs represents the arguments for a call.
type CallArgs struct {
From common.Address `json:"from"`
@@ -626,10 +605,8 @@ func (s *PublicBlockChainAPI) doCall(ctx context.Context, args CallArgs, blockNr
// Wait for the context to be done and cancel the evm. Even if the
// EVM has finished, cancelling may be done (repeatedly)
go func() {
- select {
- case <-ctx.Done():
- evm.Cancel()
- }
+ <-ctx.Done()
+ evm.Cancel()
}()
// Setup the gas pool (also for unmetered requests)
@@ -1306,7 +1283,7 @@ func (api *PublicDebugAPI) PrintBlock(ctx context.Context, number uint64) (strin
if block == nil {
return "", fmt.Errorf("block #%d not found", number)
}
- return fmt.Sprintf("%s", block), nil
+ return block.String(), nil
}
// SeedHash retrieves the seed hash of a block.
diff --git a/internal/jsre/pretty.go b/internal/jsre/pretty.go
index e096eec23..16fa91b67 100644
--- a/internal/jsre/pretty.go
+++ b/internal/jsre/pretty.go
@@ -65,14 +65,6 @@ func prettyError(vm *otto.Otto, err error, w io.Writer) {
fmt.Fprint(w, ErrorColor("%s", failure))
}
-// jsErrorString adds a backtrace to errors generated by otto.
-func jsErrorString(err error) string {
- if ottoErr, ok := err.(*otto.Error); ok {
- return ottoErr.String()
- }
- return err.Error()
-}
-
func (re *JSRE) prettyPrintJS(call otto.FunctionCall) otto.Value {
for _, v := range call.ArgumentList {
prettyPrint(call.Otto, v, re.output)
diff --git a/light/lightchain.go b/light/lightchain.go
index 8bbf529cc..a51043975 100644
--- a/light/lightchain.go
+++ b/light/lightchain.go
@@ -52,7 +52,6 @@ type LightChain struct {
mu sync.RWMutex
chainmu sync.RWMutex
- procmu sync.RWMutex
bodyCache *lru.Cache // Cache for the most recent block bodies
bodyRLPCache *lru.Cache // Cache for the most recent block bodies in RLP encoded format
diff --git a/light/lightchain_test.go b/light/lightchain_test.go
index 21b621046..0ad640525 100644
--- a/light/lightchain_test.go
+++ b/light/lightchain_test.go
@@ -18,7 +18,6 @@ package light
import (
"context"
- "fmt"
"math/big"
"testing"
@@ -98,10 +97,7 @@ func testFork(t *testing.T, LightChain *LightChain, i, n int, comparator func(td
t.Errorf("chain content mismatch at %d: have hash %v, want hash %v", i, hash2, hash1)
}
// Extend the newly created chain
- var (
- headerChainB []*types.Header
- )
- headerChainB = makeHeaderChain(LightChain2.CurrentHeader(), n, db, forkSeed)
+ headerChainB := makeHeaderChain(LightChain2.CurrentHeader(), n, db, forkSeed)
if _, err := LightChain2.InsertHeaderChain(headerChainB, 1); err != nil {
t.Fatalf("failed to insert forking chain: %v", err)
}
@@ -117,13 +113,6 @@ func testFork(t *testing.T, LightChain *LightChain, i, n int, comparator func(td
comparator(tdPre, tdPost)
}
-func printChain(bc *LightChain) {
- for i := bc.CurrentHeader().Number.Uint64(); i > 0; i-- {
- b := bc.GetHeaderByNumber(uint64(i))
- fmt.Printf("\t%x %v\n", b.Hash(), b.Difficulty)
- }
-}
-
// testHeaderChainImport tries to process a chain of header, writing them into
// the database if successful.
func testHeaderChainImport(chain []*types.Header, lightchain *LightChain) error {
diff --git a/light/txpool.go b/light/txpool.go
index 1d52aa622..7cbb991e8 100644
--- a/light/txpool.go
+++ b/light/txpool.go
@@ -124,12 +124,6 @@ func (pool *TxPool) GetNonce(ctx context.Context, addr common.Address) (uint64,
return nonce, nil
}
-type txBlockData struct {
- BlockHash common.Hash
- BlockIndex uint64
- Index uint64
-}
-
// txStateChanges stores the recent changes between pending/mined states of
// transactions. True means mined, false means rolled back, no entry means no change
type txStateChanges map[common.Hash]bool
diff --git a/rpc/server.go b/rpc/server.go
index 62b84af34..30c288349 100644
--- a/rpc/server.go
+++ b/rpc/server.go
@@ -29,11 +29,7 @@ import (
"gopkg.in/fatih/set.v0"
)
-const (
- notificationBufferSize = 10000 // max buffered notifications before codec is closed
-
- MetadataApi = "rpc"
-)
+const MetadataApi = "rpc"
// CodecOption specifies which type of messages this codec supports
type CodecOption int
@@ -49,10 +45,9 @@ const (
// NewServer will create a new server instance with no registered handlers.
func NewServer() *Server {
server := &Server{
- services: make(serviceRegistry),
- subscriptions: make(subscriptionRegistry),
- codecs: set.New(),
- run: 1,
+ services: make(serviceRegistry),
+ codecs: set.New(),
+ run: 1,
}
// register a default service which will provide meta information about the RPC service such as the services and
@@ -124,16 +119,6 @@ func (s *Server) RegisterName(name string, rcvr interface{}) error {
return nil
}
-// hasOption returns true if option is included in options, otherwise false
-func hasOption(option CodecOption, options []CodecOption) bool {
- for _, o := range options {
- if option == o {
- return true
- }
- }
- return false
-}
-
// serveRequest will reads requests from the codec, calls the RPC callback and
// writes the response to the given codec.
//
@@ -148,13 +133,11 @@ func (s *Server) serveRequest(codec ServerCodec, singleShot bool, options CodecO
const size = 64 << 10
buf := make([]byte, size)
buf = buf[:runtime.Stack(buf, false)]
- log.Error(fmt.Sprint(string(buf)))
+ log.Error(string(buf))
}
s.codecsMu.Lock()
s.codecs.Remove(codec)
s.codecsMu.Unlock()
-
- return
}()
ctx, cancel := context.WithCancel(context.Background())
@@ -246,7 +229,7 @@ func (s *Server) ServeSingleRequest(codec ServerCodec, options CodecOption) {
// close all codecs which will cancel pending requests/subscriptions.
func (s *Server) Stop() {
if atomic.CompareAndSwapInt32(&s.run, 1, 0) {
- log.Debug(fmt.Sprint("RPC Server shutdown initiatied"))
+ log.Debug("RPC Server shutdown initiatied")
s.codecsMu.Lock()
defer s.codecsMu.Unlock()
s.codecs.Each(func(c interface{}) bool {
diff --git a/rpc/subscription.go b/rpc/subscription.go
index 720e4dd06..6ce7befa1 100644
--- a/rpc/subscription.go
+++ b/rpc/subscription.go
@@ -53,7 +53,6 @@ type notifierKey struct{}
type Notifier struct {
codec ServerCodec
subMu sync.RWMutex // guards active and inactive maps
- stopped bool
active map[ID]*Subscription
inactive map[ID]*Subscription
}
diff --git a/rpc/subscription_test.go b/rpc/subscription_test.go
index 0ed15ddfe..39f759692 100644
--- a/rpc/subscription_test.go
+++ b/rpc/subscription_test.go
@@ -165,7 +165,7 @@ func TestNotifications(t *testing.T) {
}
func waitForMessages(t *testing.T, in *json.Decoder, successes chan<- jsonSuccessResponse,
- failures chan<- jsonErrResponse, notifications chan<- jsonNotification) {
+ failures chan<- jsonErrResponse, notifications chan<- jsonNotification, errors chan<- error) {
// read and parse server messages
for {
@@ -177,12 +177,14 @@ func waitForMessages(t *testing.T, in *json.Decoder, successes chan<- jsonSucces
var responses []map[string]interface{}
if rmsg[0] == '[' {
if err := json.Unmarshal(rmsg, &responses); err != nil {
- t.Fatalf("Received invalid message: %s", rmsg)
+ errors <- fmt.Errorf("Received invalid message: %s", rmsg)
+ return
}
} else {
var msg map[string]interface{}
if err := json.Unmarshal(rmsg, &msg); err != nil {
- t.Fatalf("Received invalid message: %s", rmsg)
+ errors <- fmt.Errorf("Received invalid message: %s", rmsg)
+ return
}
responses = append(responses, msg)
}
@@ -216,7 +218,7 @@ func waitForMessages(t *testing.T, in *json.Decoder, successes chan<- jsonSucces
}
continue
}
- t.Fatalf("Received invalid message: %s", msg)
+ errors <- fmt.Errorf("Received invalid message: %s", msg)
}
}
}
@@ -235,6 +237,8 @@ func TestSubscriptionMultipleNamespaces(t *testing.T) {
successes = make(chan jsonSuccessResponse)
failures = make(chan jsonErrResponse)
notifications = make(chan jsonNotification)
+
+ errors = make(chan error, 10)
)
// setup and start server
@@ -248,7 +252,7 @@ func TestSubscriptionMultipleNamespaces(t *testing.T) {
defer server.Stop()
// wait for message and write them to the given channels
- go waitForMessages(t, in, successes, failures, notifications)
+ go waitForMessages(t, in, successes, failures, notifications, errors)
// create subscriptions one by one
n := 3
@@ -297,6 +301,8 @@ func TestSubscriptionMultipleNamespaces(t *testing.T) {
}
select {
+ case err := <-errors:
+ t.Fatal(err)
case suc := <-successes: // subscription created
subids[namespaces[int(suc.Id.(float64))]] = suc.Result.(string)
case failure := <-failures:
diff --git a/rpc/types.go b/rpc/types.go
index a7b8c9788..f2375604e 100644
--- a/rpc/types.go
+++ b/rpc/types.go
@@ -48,7 +48,6 @@ type callback struct {
// service represents a registered object
type service struct {
name string // name for service
- rcvr reflect.Value // receiver of methods for the service
typ reflect.Type // receiver type
callbacks callbacks // registered handlers
subscriptions subscriptions // available subscriptions/notifications
@@ -58,23 +57,19 @@ type service struct {
type serverRequest struct {
id interface{}
svcname string
- rcvr reflect.Value
callb *callback
args []reflect.Value
isUnsubscribe bool
err Error
}
-type serviceRegistry map[string]*service // collection of services
-type callbacks map[string]*callback // collection of RPC callbacks
-type subscriptions map[string]*callback // collection of subscription callbacks
-type subscriptionRegistry map[string]*callback // collection of subscription callbacks
+type serviceRegistry map[string]*service // collection of services
+type callbacks map[string]*callback // collection of RPC callbacks
+type subscriptions map[string]*callback // collection of subscription callbacks
// Server represents a RPC server
type Server struct {
- services serviceRegistry
- muSubcriptions sync.Mutex // protects subscriptions
- subscriptions subscriptionRegistry
+ services serviceRegistry
run int32
codecsMu sync.Mutex
diff --git a/rpc/utils.go b/rpc/utils.go
index 2506c4833..9315cab59 100644
--- a/rpc/utils.go
+++ b/rpc/utils.go
@@ -119,21 +119,6 @@ func isHexNum(t reflect.Type) bool {
return t == bigIntType
}
-var blockNumberType = reflect.TypeOf((*BlockNumber)(nil)).Elem()
-
-// Indication if the given block is a BlockNumber
-func isBlockNumber(t reflect.Type) bool {
- if t == nil {
- return false
- }
-
- for t.Kind() == reflect.Ptr {
- t = t.Elem()
- }
-
- return t == blockNumberType
-}
-
// suitableCallbacks iterates over the methods of the given type. It will determine if a method satisfies the criteria
// for a RPC callback or a subscription callback and adds it to the collection of callbacks or subscriptions. See server
// documentation for a summary of these criteria.
@@ -210,18 +195,12 @@ METHODS:
}
switch mtype.NumOut() {
- case 0, 1:
- break
- case 2:
- if h.errPos == -1 { // method must one return value and 1 error
+ case 0, 1, 2:
+ if mtype.NumOut() == 2 && h.errPos == -1 { // method must one return value and 1 error
continue METHODS
}
- break
- default:
- continue METHODS
+ callbacks[mname] = &h
}
-
- callbacks[mname] = &h
}
return callbacks, subscriptions