diff --git a/.travis.yml b/.travis.yml
index 9fcfe6338f..9563903e45 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -146,7 +146,7 @@ matrix:
git:
submodules: false # avoid cloning ethereum/tests
before_install:
- - curl https://storage.googleapis.com/golang/go1.10.2.linux-amd64.tar.gz | tar -xz
+ - curl https://storage.googleapis.com/golang/go1.10.3.linux-amd64.tar.gz | tar -xz
- export PATH=`pwd`/go/bin:$PATH
- export GOROOT=`pwd`/go
- export GOPATH=$HOME/go
diff --git a/VERSION b/VERSION
index 267637b120..7d2424c90b 100644
--- a/VERSION
+++ b/VERSION
@@ -1 +1 @@
-1.8.11
+1.8.12
diff --git a/appveyor.yml b/appveyor.yml
index f10000af86..05ff92cf36 100644
--- a/appveyor.yml
+++ b/appveyor.yml
@@ -23,8 +23,8 @@ environment:
install:
- git submodule update --init
- rmdir C:\go /s /q
- - appveyor DownloadFile https://storage.googleapis.com/golang/go1.10.2.windows-%GETH_ARCH%.zip
- - 7z x go1.10.2.windows-%GETH_ARCH%.zip -y -oC:\ > NUL
+ - appveyor DownloadFile https://storage.googleapis.com/golang/go1.10.3.windows-%GETH_ARCH%.zip
+ - 7z x go1.10.3.windows-%GETH_ARCH%.zip -y -oC:\ > NUL
- go version
- gcc --version
diff --git a/build/ci.go b/build/ci.go
index 9bd73fad24..f9ce68a5a0 100644
--- a/build/ci.go
+++ b/build/ci.go
@@ -330,6 +330,7 @@ func doLint(cmdline []string) {
configs := []string{
"--vendor",
"--tests",
+ "--deadline=2m",
"--disable-all",
"--enable=goimports",
"--enable=varcheck",
diff --git a/cmd/utils/flags.go b/cmd/utils/flags.go
index 6c3e9cb5b2..329c6c671a 100644
--- a/cmd/utils/flags.go
+++ b/cmd/utils/flags.go
@@ -1084,6 +1084,9 @@ func SetEthConfig(ctx *cli.Context, stack *node.Node, cfg *eth.Config) {
}
cfg.Genesis = core.DefaultRinkebyGenesisBlock()
case ctx.GlobalBool(DeveloperFlag.Name):
+ if !ctx.GlobalIsSet(NetworkIdFlag.Name) {
+ cfg.NetworkId = 1337
+ }
// Create new developer account or reuse existing one
var (
developer accounts.Account
diff --git a/common/hexutil/hexutil.go b/common/hexutil/hexutil.go
index 02c488a3f1..46223a2815 100644
--- a/common/hexutil/hexutil.go
+++ b/common/hexutil/hexutil.go
@@ -39,6 +39,7 @@ import (
const uintBits = 32 << (uint64(^uint(0)) >> 63)
+// Errors
var (
ErrEmptyString = &decError{"empty hex string"}
ErrSyntax = &decError{"invalid hex string"}
diff --git a/common/math/big.go b/common/math/big.go
index dbf2770a94..9d2e7946d1 100644
--- a/common/math/big.go
+++ b/common/math/big.go
@@ -22,12 +22,13 @@ import (
"math/big"
)
+// Various big integer limit values.
var (
tt255 = BigPow(2, 255)
tt256 = BigPow(2, 256)
tt256m1 = new(big.Int).Sub(tt256, big.NewInt(1))
- MaxBig256 = new(big.Int).Set(tt256m1)
tt63 = BigPow(2, 63)
+ MaxBig256 = new(big.Int).Set(tt256m1)
MaxBig63 = new(big.Int).Sub(tt63, big.NewInt(1))
)
diff --git a/common/math/integer.go b/common/math/integer.go
index 7eff4d3b00..93b1d036dd 100644
--- a/common/math/integer.go
+++ b/common/math/integer.go
@@ -21,8 +21,8 @@ import (
"strconv"
)
+// Integer limit values.
const (
- // Integer limit values.
MaxInt8 = 1<<7 - 1
MinInt8 = -1 << 7
MaxInt16 = 1<<15 - 1
diff --git a/common/mclock/mclock.go b/common/mclock/mclock.go
index 92005252eb..02608d17b0 100644
--- a/common/mclock/mclock.go
+++ b/common/mclock/mclock.go
@@ -14,7 +14,7 @@
// You should have received a copy of the GNU Lesser General Public License
// along with the go-ethereum library. If not, see .
-// package mclock is a wrapper for a monotonic clock source
+// Package mclock is a wrapper for a monotonic clock source
package mclock
import (
@@ -23,8 +23,10 @@ import (
"github.com/aristanetworks/goarista/monotime"
)
-type AbsTime time.Duration // absolute monotonic time
+// AbsTime represents absolute monotonic time.
+type AbsTime time.Duration
+// Now returns the current absolute monotonic time.
func Now() AbsTime {
return AbsTime(monotime.Now())
}
diff --git a/common/number/int.go b/common/number/int.go
index a84fab9392..a3d3d5fc31 100644
--- a/common/number/int.go
+++ b/common/number/int.go
@@ -22,9 +22,11 @@ import (
"github.com/EthereumCommonwealth/go-callisto/common"
)
-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)
+var (
+ tt256 = new(big.Int).Lsh(big.NewInt(1), 256)
+ tt256m1 = new(big.Int).Sub(new(big.Int).Lsh(big.NewInt(1), 256), big.NewInt(1))
+ tt255 = new(big.Int).Lsh(big.NewInt(1), 255)
+)
func limitUnsigned256(x *Number) *Number {
x.num.And(x.num, tt256m1)
@@ -181,7 +183,6 @@ func (i *Number) FirstBitSet() int {
}
// Variables
-
var (
Zero = Uint(0)
One = Uint(1)
diff --git a/common/types.go b/common/types.go
index dfc0fc0b97..448cbbd261 100644
--- a/common/types.go
+++ b/common/types.go
@@ -29,6 +29,7 @@ import (
"github.com/EthereumCommonwealth/go-callisto/crypto/sha3"
)
+// Lengths of hashes and addresses in bytes.
const (
HashLength = 32
AddressLength = 20
diff --git a/console/console.go b/console/console.go
index 9f01e27053..68515584c7 100644
--- a/console/console.go
+++ b/console/console.go
@@ -60,7 +60,7 @@ type Config struct {
Preload []string // Absolute paths to JavaScript files to preload
}
-// Console is a JavaScript interpreted runtime environment. It is a fully fleged
+// Console is a JavaScript interpreted runtime environment. It is a fully fledged
// JavaScript console attached to a running node via an external or in-process RPC
// client.
type Console struct {
diff --git a/contracts/ens/ens.go b/contracts/ens/ens.go
index b8b18482d8..f3ef26d23e 100644
--- a/contracts/ens/ens.go
+++ b/contracts/ens/ens.go
@@ -95,7 +95,7 @@ func ensParentNode(name string) (common.Hash, common.Hash) {
}
}
-func ensNode(name string) common.Hash {
+func EnsNode(name string) common.Hash {
parentNode, parentLabel := ensParentNode(name)
return crypto.Keccak256Hash(parentNode[:], parentLabel[:])
}
@@ -136,7 +136,7 @@ func (self *ENS) getRegistrar(node [32]byte) (*contract.FIFSRegistrarSession, er
// Resolve is a non-transactional call that returns the content hash associated with a name.
func (self *ENS) Resolve(name string) (common.Hash, error) {
- node := ensNode(name)
+ node := EnsNode(name)
resolver, err := self.getResolver(node)
if err != nil {
@@ -165,7 +165,7 @@ func (self *ENS) Register(name string) (*types.Transaction, error) {
// SetContentHash sets the content hash associated with a name. Only works if the caller
// owns the name, and the associated resolver implements a `setContent` function.
func (self *ENS) SetContentHash(name string, hash common.Hash) (*types.Transaction, error) {
- node := ensNode(name)
+ node := EnsNode(name)
resolver, err := self.getResolver(node)
if err != nil {
diff --git a/contracts/ens/ens_test.go b/contracts/ens/ens_test.go
index 9aabfdeba1..2cd1b444c7 100644
--- a/contracts/ens/ens_test.go
+++ b/contracts/ens/ens_test.go
@@ -55,7 +55,7 @@ func TestENS(t *testing.T) {
if err != nil {
t.Fatalf("can't deploy resolver: %v", err)
}
- if _, err := ens.SetResolver(ensNode(name), resolverAddr); err != nil {
+ if _, err := ens.SetResolver(EnsNode(name), resolverAddr); err != nil {
t.Fatalf("can't set resolver: %v", err)
}
contractBackend.Commit()
diff --git a/core/asm/lexer.go b/core/asm/lexer.go
index 4d62159e55..91caeb27bc 100644
--- a/core/asm/lexer.go
+++ b/core/asm/lexer.go
@@ -242,7 +242,7 @@ func lexLabel(l *lexer) stateFn {
}
// lexInsideString lexes the inside of a string until
-// until the state function finds the closing quote.
+// the state function finds the closing quote.
// It returns the lex text state function.
func lexInsideString(l *lexer) stateFn {
if l.acceptRunUntil('"') {
diff --git a/core/tx_pool.go b/core/tx_pool.go
index 1cc796376a..deb0dcd732 100644
--- a/core/tx_pool.go
+++ b/core/tx_pool.go
@@ -1107,7 +1107,7 @@ func (pool *TxPool) demoteUnexecutables() {
log.Trace("Demoting pending transaction", "hash", hash)
pool.enqueueTx(hash, tx)
}
- // If there's a gap in front, warn (should never happen) and postpone all transactions
+ // If there's a gap in front, alert (should never happen) and postpone all transactions
if list.Len() > 0 && list.txs.Get(nonce) == nil {
for _, tx := range list.Cap(0) {
hash := tx.Hash()
diff --git a/core/vm/instructions.go b/core/vm/instructions.go
index c5055a23a7..dd5ff9f89c 100644
--- a/core/vm/instructions.go
+++ b/core/vm/instructions.go
@@ -556,7 +556,7 @@ func opMload(pc *uint64, evm *EVM, contract *Contract, memory *Memory, stack *St
func opMstore(pc *uint64, evm *EVM, contract *Contract, memory *Memory, stack *Stack) ([]byte, error) {
// pop value of the stack
mStart, val := stack.pop(), stack.pop()
- memory.Set(mStart.Uint64(), 32, math.PaddedBigBytes(val, 32))
+ memory.Set32(mStart.Uint64(), val)
evm.interpreter.intPool.put(mStart, val)
return nil, nil
@@ -570,9 +570,9 @@ func opMstore8(pc *uint64, evm *EVM, contract *Contract, memory *Memory, stack *
}
func opSload(pc *uint64, evm *EVM, contract *Contract, memory *Memory, stack *Stack) ([]byte, error) {
- loc := common.BigToHash(stack.pop())
- val := evm.StateDB.GetState(contract.Address(), loc).Big()
- stack.push(val)
+ loc := stack.peek()
+ val := evm.StateDB.GetState(contract.Address(), common.BigToHash(loc))
+ loc.SetBytes(val.Bytes())
return nil, nil
}
diff --git a/core/vm/instructions_test.go b/core/vm/instructions_test.go
index ca2ae19742..c6c07a6c1e 100644
--- a/core/vm/instructions_test.go
+++ b/core/vm/instructions_test.go
@@ -425,3 +425,42 @@ func BenchmarkOpIsZero(b *testing.B) {
x := "FBCDEF090807060504030201ffffffffFBCDEF090807060504030201ffffffff"
opBenchmark(b, opIszero, x)
}
+
+func TestOpMstore(t *testing.T) {
+ var (
+ env = NewEVM(Context{}, nil, params.TestChainConfig, Config{})
+ stack = newstack()
+ mem = NewMemory()
+ )
+ mem.Resize(64)
+ pc := uint64(0)
+ v := "abcdef00000000000000abba000000000deaf000000c0de00100000000133700"
+ stack.pushN(new(big.Int).SetBytes(common.Hex2Bytes(v)), big.NewInt(0))
+ opMstore(&pc, env, nil, mem, stack)
+ if got := common.Bytes2Hex(mem.Get(0, 32)); got != v {
+ t.Fatalf("Mstore fail, got %v, expected %v", got, v)
+ }
+ stack.pushN(big.NewInt(0x1), big.NewInt(0))
+ opMstore(&pc, env, nil, mem, stack)
+ if common.Bytes2Hex(mem.Get(0, 32)) != "0000000000000000000000000000000000000000000000000000000000000001" {
+ t.Fatalf("Mstore failed to overwrite previous value")
+ }
+}
+
+func BenchmarkOpMstore(bench *testing.B) {
+ var (
+ env = NewEVM(Context{}, nil, params.TestChainConfig, Config{})
+ stack = newstack()
+ mem = NewMemory()
+ )
+ mem.Resize(64)
+ pc := uint64(0)
+ memStart := big.NewInt(0)
+ value := big.NewInt(0x1337)
+
+ bench.ResetTimer()
+ for i := 0; i < bench.N; i++ {
+ stack.pushN(value, memStart)
+ opMstore(&pc, env, nil, mem, stack)
+ }
+}
diff --git a/core/vm/memory.go b/core/vm/memory.go
index d5cc7870bc..490eb978fe 100644
--- a/core/vm/memory.go
+++ b/core/vm/memory.go
@@ -16,7 +16,12 @@
package vm
-import "fmt"
+import (
+ "fmt"
+ "math/big"
+
+ "github.com/EthereumCommonwealth/go-callisto/common/math"
+)
// Memory implements a simple memory model for the ethereum virtual machine.
type Memory struct {
@@ -30,19 +35,32 @@ func NewMemory() *Memory {
// Set sets offset + size to value
func (m *Memory) Set(offset, size uint64, value []byte) {
- // length of store may never be less than offset + size.
- // The store should be resized PRIOR to setting the memory
- if size > uint64(len(m.store)) {
- panic("INVALID memory: store empty")
- }
-
// It's possible the offset is greater than 0 and size equals 0. This is because
// the calcMemSize (common.go) could potentially return 0 when size is zero (NO-OP)
if size > 0 {
+ // length of store may never be less than offset + size.
+ // The store should be resized PRIOR to setting the memory
+ if offset+size > uint64(len(m.store)) {
+ panic("invalid memory: store empty")
+ }
copy(m.store[offset:offset+size], value)
}
}
+// Set32 sets the 32 bytes starting at offset to the value of val, left-padded with zeroes to
+// 32 bytes.
+func (m *Memory) Set32(offset uint64, val *big.Int) {
+ // length of store may never be less than offset + size.
+ // The store should be resized PRIOR to setting the memory
+ if offset+32 > uint64(len(m.store)) {
+ panic("invalid memory: store empty")
+ }
+ // Zero the memory area
+ copy(m.store[offset:offset+32], []byte{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0})
+ // Fill in relevant bits
+ math.ReadBits(val, m.store[offset:offset+32])
+}
+
// Resize resizes the memory to size
func (m *Memory) Resize(size uint64) {
if uint64(m.Len()) < size {
diff --git a/eth/api.go b/eth/api.go
index 4bfa0ab113..9ed3e0ad20 100644
--- a/eth/api.go
+++ b/eth/api.go
@@ -359,7 +359,7 @@ type BadBlockArgs struct {
RLP string `json:"rlp"`
}
-// GetBadBLocks returns a list of the last 'bad blocks' that the client has seen on the network
+// GetBadBlocks returns a list of the last 'bad blocks' that the client has seen on the network
// and returns them as a JSON list of block-hashes
func (api *PrivateDebugAPI) GetBadBlocks(ctx context.Context) ([]*BadBlockArgs, error) {
blocks := api.eth.BlockChain().BadBlocks()
@@ -431,7 +431,7 @@ func storageRangeAt(st state.Trie, start []byte, maxResult int) (StorageRangeRes
return result, nil
}
-// GetModifiedAccountsByumber returns all accounts that have changed between the
+// GetModifiedAccountsByNumber returns all accounts that have changed between the
// two blocks specified. A change is defined as a difference in nonce, balance,
// code hash, or storage hash.
//
diff --git a/eth/api_backend.go b/eth/api_backend.go
index 59b2c05e77..6ec9cd4667 100644
--- a/eth/api_backend.go
+++ b/eth/api_backend.go
@@ -43,6 +43,7 @@ type EthAPIBackend struct {
gpo *gasprice.Oracle
}
+// ChainConfig returns the active chain configuration.
func (b *EthAPIBackend) ChainConfig() *params.ChainConfig {
return b.eth.chainConfig
}
diff --git a/eth/backend.go b/eth/backend.go
index 43267303be..37369dba44 100644
--- a/eth/backend.go
+++ b/eth/backend.go
@@ -88,7 +88,7 @@ type Ethereum struct {
gasPrice *big.Int
etherbase common.Address
- networkId uint64
+ networkID uint64
netRPCService *ethapi.PublicNetAPI
lock sync.RWMutex // Protects the variadic fields (e.g. gas price and etherbase)
@@ -126,7 +126,7 @@ func New(ctx *node.ServiceContext, config *Config) (*Ethereum, error) {
accountManager: ctx.AccountManager,
engine: CreateConsensusEngine(ctx, &config.Ethash, chainConfig, chainDb),
shutdownChan: make(chan bool),
- networkId: config.NetworkId,
+ networkID: config.NetworkId,
gasPrice: config.GasPrice,
etherbase: config.Etherbase,
bloomRequests: make(chan chan *bloombits.Retrieval),
@@ -369,7 +369,7 @@ func (s *Ethereum) Engine() consensus.Engine { return s.engine }
func (s *Ethereum) ChainDb() ethdb.Database { return s.chainDb }
func (s *Ethereum) IsListening() bool { return true } // Always listening
func (s *Ethereum) EthVersion() int { return int(s.protocolManager.SubProtocols[0].Version) }
-func (s *Ethereum) NetVersion() uint64 { return s.networkId }
+func (s *Ethereum) NetVersion() uint64 { return s.networkID }
func (s *Ethereum) Downloader() *downloader.Downloader { return s.protocolManager.downloader }
// Protocols implements node.Service, returning all the currently configured
diff --git a/eth/downloader/downloader.go b/eth/downloader/downloader.go
index 7eb86632e2..c42da41a43 100644
--- a/eth/downloader/downloader.go
+++ b/eth/downloader/downloader.go
@@ -900,7 +900,7 @@ func (d *Downloader) fillHeaderSkeleton(from uint64, skeleton []*types.Header) (
var (
deliver = func(packet dataPack) (int, error) {
pack := packet.(*headerPack)
- return d.queue.DeliverHeaders(pack.peerId, pack.headers, d.headerProcCh)
+ return d.queue.DeliverHeaders(pack.peerID, pack.headers, d.headerProcCh)
}
expire = func() map[string]int { return d.queue.ExpireHeaders(d.requestTTL()) }
throttle = func() bool { return false }
@@ -930,7 +930,7 @@ func (d *Downloader) fetchBodies(from uint64) error {
var (
deliver = func(packet dataPack) (int, error) {
pack := packet.(*bodyPack)
- return d.queue.DeliverBodies(pack.peerId, pack.transactions, pack.uncles)
+ return d.queue.DeliverBodies(pack.peerID, pack.transactions, pack.uncles)
}
expire = func() map[string]int { return d.queue.ExpireBodies(d.requestTTL()) }
fetch = func(p *peerConnection, req *fetchRequest) error { return p.FetchBodies(req) }
@@ -954,7 +954,7 @@ func (d *Downloader) fetchReceipts(from uint64) error {
var (
deliver = func(packet dataPack) (int, error) {
pack := packet.(*receiptPack)
- return d.queue.DeliverReceipts(pack.peerId, pack.receipts)
+ return d.queue.DeliverReceipts(pack.peerID, pack.receipts)
}
expire = func() map[string]int { return d.queue.ExpireReceipts(d.requestTTL()) }
fetch = func(p *peerConnection, req *fetchRequest) error { return p.FetchReceipts(req) }
diff --git a/eth/downloader/queue.go b/eth/downloader/queue.go
index b0abde25e4..adf02a3c13 100644
--- a/eth/downloader/queue.go
+++ b/eth/downloader/queue.go
@@ -596,21 +596,21 @@ func (q *queue) cancel(request *fetchRequest, taskQueue *prque.Prque, pendPool m
// Revoke cancels all pending requests belonging to a given peer. This method is
// meant to be called during a peer drop to quickly reassign owned data fetches
// to remaining nodes.
-func (q *queue) Revoke(peerId string) {
+func (q *queue) Revoke(peerID string) {
q.lock.Lock()
defer q.lock.Unlock()
- if request, ok := q.blockPendPool[peerId]; ok {
+ if request, ok := q.blockPendPool[peerID]; ok {
for _, header := range request.Headers {
q.blockTaskQueue.Push(header, -float32(header.Number.Uint64()))
}
- delete(q.blockPendPool, peerId)
+ delete(q.blockPendPool, peerID)
}
- if request, ok := q.receiptPendPool[peerId]; ok {
+ if request, ok := q.receiptPendPool[peerID]; ok {
for _, header := range request.Headers {
q.receiptTaskQueue.Push(header, -float32(header.Number.Uint64()))
}
- delete(q.receiptPendPool, peerId)
+ delete(q.receiptPendPool, peerID)
}
}
diff --git a/eth/downloader/types.go b/eth/downloader/types.go
index b4edb4b9fa..2a4ffc3015 100644
--- a/eth/downloader/types.go
+++ b/eth/downloader/types.go
@@ -34,22 +34,22 @@ type dataPack interface {
// headerPack is a batch of block headers returned by a peer.
type headerPack struct {
- peerId string
+ peerID string
headers []*types.Header
}
-func (p *headerPack) PeerId() string { return p.peerId }
+func (p *headerPack) PeerId() string { return p.peerID }
func (p *headerPack) Items() int { return len(p.headers) }
func (p *headerPack) Stats() string { return fmt.Sprintf("%d", len(p.headers)) }
// bodyPack is a batch of block bodies returned by a peer.
type bodyPack struct {
- peerId string
+ peerID string
transactions [][]*types.Transaction
uncles [][]*types.Header
}
-func (p *bodyPack) PeerId() string { return p.peerId }
+func (p *bodyPack) PeerId() string { return p.peerID }
func (p *bodyPack) Items() int {
if len(p.transactions) <= len(p.uncles) {
return len(p.transactions)
@@ -60,20 +60,20 @@ func (p *bodyPack) Stats() string { return fmt.Sprintf("%d:%d", len(p.transactio
// receiptPack is a batch of receipts returned by a peer.
type receiptPack struct {
- peerId string
+ peerID string
receipts [][]*types.Receipt
}
-func (p *receiptPack) PeerId() string { return p.peerId }
+func (p *receiptPack) PeerId() string { return p.peerID }
func (p *receiptPack) Items() int { return len(p.receipts) }
func (p *receiptPack) Stats() string { return fmt.Sprintf("%d", len(p.receipts)) }
// statePack is a batch of states returned by a peer.
type statePack struct {
- peerId string
+ peerID string
states [][]byte
}
-func (p *statePack) PeerId() string { return p.peerId }
+func (p *statePack) PeerId() string { return p.peerID }
func (p *statePack) Items() int { return len(p.states) }
func (p *statePack) Stats() string { return fmt.Sprintf("%d", len(p.states)) }
diff --git a/eth/fetcher/fetcher.go b/eth/fetcher/fetcher.go
index da2aff511a..cbdf5c1a7a 100644
--- a/eth/fetcher/fetcher.go
+++ b/eth/fetcher/fetcher.go
@@ -88,7 +88,7 @@ type headerFilterTask struct {
time time.Time // Arrival time of the headers
}
-// headerFilterTask represents a batch of block bodies (transactions and uncles)
+// bodyFilterTask represents a batch of block bodies (transactions and uncles)
// needing fetcher filtering.
type bodyFilterTask struct {
peer string // The source peer of block bodies
diff --git a/eth/filters/filter.go b/eth/filters/filter.go
index 6f3689b119..ea6d43f88f 100644
--- a/eth/filters/filter.go
+++ b/eth/filters/filter.go
@@ -258,9 +258,9 @@ Logs:
if len(topics) > len(log.Topics) {
continue Logs
}
- for i, topics := range topics {
- match := len(topics) == 0 // empty rule set == wildcard
- for _, topic := range topics {
+ for i, sub := range topics {
+ match := len(sub) == 0 // empty rule set == wildcard
+ for _, topic := range sub {
if log.Topics[i] == topic {
match = true
break
diff --git a/eth/handler.go b/eth/handler.go
index 58f20af893..4d8009d25d 100644
--- a/eth/handler.go
+++ b/eth/handler.go
@@ -64,7 +64,7 @@ func errResp(code errCode, format string, v ...interface{}) error {
}
type ProtocolManager struct {
- networkId uint64
+ networkID uint64
fastSync uint32 // Flag whether fast sync is enabled (gets disabled if we already have blocks)
acceptTxs uint32 // Flag whether we're considered synchronised (enables transaction processing)
@@ -98,10 +98,10 @@ type ProtocolManager struct {
// NewProtocolManager returns a new Ethereum sub protocol manager. The Ethereum sub protocol manages peers capable
// with the Ethereum network.
-func NewProtocolManager(config *params.ChainConfig, mode downloader.SyncMode, networkId uint64, mux *event.TypeMux, txpool txPool, engine consensus.Engine, blockchain *core.BlockChain, chaindb ethdb.Database) (*ProtocolManager, error) {
+func NewProtocolManager(config *params.ChainConfig, mode downloader.SyncMode, networkID uint64, mux *event.TypeMux, txpool txPool, engine consensus.Engine, blockchain *core.BlockChain, chaindb ethdb.Database) (*ProtocolManager, error) {
// Create the protocol manager with the base fields
manager := &ProtocolManager{
- networkId: networkId,
+ networkID: networkID,
eventMux: mux,
txpool: txpool,
blockchain: blockchain,
@@ -263,7 +263,7 @@ func (pm *ProtocolManager) handle(p *peer) error {
number = head.Number.Uint64()
td = pm.blockchain.GetTd(hash, number)
)
- if err := p.Handshake(pm.networkId, td, hash, genesis.Hash()); err != nil {
+ if err := p.Handshake(pm.networkID, td, hash, genesis.Hash()); err != nil {
p.Log().Debug("Ethereum handshake failed", "err", err)
return err
}
@@ -779,7 +779,7 @@ type NodeInfo struct {
func (pm *ProtocolManager) NodeInfo() *NodeInfo {
currentBlock := pm.blockchain.CurrentBlock()
return &NodeInfo{
- Network: pm.networkId,
+ Network: pm.networkID,
Difficulty: pm.blockchain.GetTd(currentBlock.Hash(), currentBlock.NumberU64()),
Genesis: pm.blockchain.Genesis().Hash(),
Config: pm.blockchain.Config(),
diff --git a/internal/web3ext/web3ext.go b/internal/web3ext/web3ext.go
index 9d6ce8c6c8..89ebceec7c 100644
--- a/internal/web3ext/web3ext.go
+++ b/internal/web3ext/web3ext.go
@@ -313,8 +313,8 @@ web3._extend({
params: 2
}),
new web3._extend.Method({
- name: 'setMutexProfileRate',
- call: 'debug_setMutexProfileRate',
+ name: 'setMutexProfileFraction',
+ call: 'debug_setMutexProfileFraction',
params: 1
}),
new web3._extend.Method({
diff --git a/log/format.go b/log/format.go
index 36afc948ea..d3149dc78b 100644
--- a/log/format.go
+++ b/log/format.go
@@ -15,7 +15,7 @@ import (
const (
timeFormat = "2006-01-02T15:04:05-0700"
- termTimeFormat = "01-02|15:04:05"
+ termTimeFormat = "01-02|15:04:05.999999"
floatFormat = 'f'
termMsgJust = 40
)
diff --git a/log/logger.go b/log/logger.go
index a2fe6dc580..438aa548fa 100644
--- a/log/logger.go
+++ b/log/logger.go
@@ -12,6 +12,7 @@ const timeKey = "t"
const lvlKey = "lvl"
const msgKey = "msg"
const errorKey = "LOG15_ERROR"
+const skipLevel = 2
type Lvl int
@@ -127,13 +128,13 @@ type logger struct {
h *swapHandler
}
-func (l *logger) write(msg string, lvl Lvl, ctx []interface{}) {
+func (l *logger) write(msg string, lvl Lvl, ctx []interface{}, skip int) {
l.h.Log(&Record{
Time: time.Now(),
Lvl: lvl,
Msg: msg,
Ctx: newContext(l.ctx, ctx),
- Call: stack.Caller(2),
+ Call: stack.Caller(skip),
KeyNames: RecordKeyNames{
Time: timeKey,
Msg: msgKey,
@@ -157,27 +158,27 @@ func newContext(prefix []interface{}, suffix []interface{}) []interface{} {
}
func (l *logger) Trace(msg string, ctx ...interface{}) {
- l.write(msg, LvlTrace, ctx)
+ l.write(msg, LvlTrace, ctx, skipLevel)
}
func (l *logger) Debug(msg string, ctx ...interface{}) {
- l.write(msg, LvlDebug, ctx)
+ l.write(msg, LvlDebug, ctx, skipLevel)
}
func (l *logger) Info(msg string, ctx ...interface{}) {
- l.write(msg, LvlInfo, ctx)
+ l.write(msg, LvlInfo, ctx, skipLevel)
}
func (l *logger) Warn(msg string, ctx ...interface{}) {
- l.write(msg, LvlWarn, ctx)
+ l.write(msg, LvlWarn, ctx, skipLevel)
}
func (l *logger) Error(msg string, ctx ...interface{}) {
- l.write(msg, LvlError, ctx)
+ l.write(msg, LvlError, ctx, skipLevel)
}
func (l *logger) Crit(msg string, ctx ...interface{}) {
- l.write(msg, LvlCrit, ctx)
+ l.write(msg, LvlCrit, ctx, skipLevel)
os.Exit(1)
}
diff --git a/log/root.go b/log/root.go
index 71b8cef6d4..9fb4c5ae0b 100644
--- a/log/root.go
+++ b/log/root.go
@@ -31,31 +31,40 @@ func Root() Logger {
// Trace is a convenient alias for Root().Trace
func Trace(msg string, ctx ...interface{}) {
- root.write(msg, LvlTrace, ctx)
+ root.write(msg, LvlTrace, ctx, skipLevel)
}
// Debug is a convenient alias for Root().Debug
func Debug(msg string, ctx ...interface{}) {
- root.write(msg, LvlDebug, ctx)
+ root.write(msg, LvlDebug, ctx, skipLevel)
}
// Info is a convenient alias for Root().Info
func Info(msg string, ctx ...interface{}) {
- root.write(msg, LvlInfo, ctx)
+ root.write(msg, LvlInfo, ctx, skipLevel)
}
// Warn is a convenient alias for Root().Warn
func Warn(msg string, ctx ...interface{}) {
- root.write(msg, LvlWarn, ctx)
+ root.write(msg, LvlWarn, ctx, skipLevel)
}
// Error is a convenient alias for Root().Error
func Error(msg string, ctx ...interface{}) {
- root.write(msg, LvlError, ctx)
+ root.write(msg, LvlError, ctx, skipLevel)
}
// Crit is a convenient alias for Root().Crit
func Crit(msg string, ctx ...interface{}) {
- root.write(msg, LvlCrit, ctx)
+ root.write(msg, LvlCrit, ctx, skipLevel)
os.Exit(1)
}
+
+// Output is a convenient alias for write, allowing for the modification of
+// the calldepth (number of stack frames to skip).
+// calldepth influences the reported line number of the log message.
+// A calldepth of zero reports the immediate caller of Output.
+// Non-zero calldepth skips as many stack frames.
+func Output(msg string, lvl Lvl, calldepth int, ctx ...interface{}) {
+ root.write(msg, lvl, ctx, calldepth+skipLevel)
+}
diff --git a/metrics/timer_test.go b/metrics/timer_test.go
index c1f0ff9388..8638a2270b 100644
--- a/metrics/timer_test.go
+++ b/metrics/timer_test.go
@@ -47,8 +47,8 @@ func TestTimerStop(t *testing.T) {
func TestTimerFunc(t *testing.T) {
tm := NewTimer()
tm.Time(func() { time.Sleep(50e6) })
- if max := tm.Max(); 35e6 > max || max > 95e6 {
- t.Errorf("tm.Max(): 35e6 > %v || %v > 95e6\n", max, max)
+ if max := tm.Max(); 35e6 > max || max > 145e6 {
+ t.Errorf("tm.Max(): 35e6 > %v || %v > 145e6\n", max, max)
}
}
diff --git a/p2p/discover/table.go b/p2p/discover/table.go
index 655d7cc290..f32bea5b29 100644
--- a/p2p/discover/table.go
+++ b/p2p/discover/table.go
@@ -480,16 +480,16 @@ func (tab *Table) doRevalidate(done chan<- struct{}) {
b := tab.buckets[bi]
if err == nil {
// The node responded, move it to the front.
- log.Debug("Revalidated node", "b", bi, "id", last.ID)
+ log.Trace("Revalidated node", "b", bi, "id", last.ID)
b.bump(last)
return
}
// No reply received, pick a replacement or delete the node if there aren't
// any replacements.
if r := tab.replace(b, last); r != nil {
- log.Debug("Replaced dead node", "b", bi, "id", last.ID, "ip", last.IP, "r", r.ID, "rip", r.IP)
+ log.Trace("Replaced dead node", "b", bi, "id", last.ID, "ip", last.IP, "r", r.ID, "rip", r.IP)
} else {
- log.Debug("Removed dead node", "b", bi, "id", last.ID, "ip", last.IP)
+ log.Trace("Removed dead node", "b", bi, "id", last.ID, "ip", last.IP)
}
}
diff --git a/p2p/protocols/protocol.go b/p2p/protocols/protocol.go
index 79932a0c35..439bb1e3bc 100644
--- a/p2p/protocols/protocol.go
+++ b/p2p/protocols/protocol.go
@@ -33,7 +33,9 @@ import (
"fmt"
"reflect"
"sync"
+ "time"
+ "github.com/EthereumCommonwealth/go-callisto/metrics"
"github.com/EthereumCommonwealth/go-callisto/p2p"
)
@@ -217,6 +219,8 @@ func (p *Peer) Drop(err error) {
// this low level call will be wrapped by libraries providing routed or broadcast sends
// but often just used to forward and push messages to directly connected peers
func (p *Peer) Send(msg interface{}) error {
+ defer metrics.GetOrRegisterResettingTimer("peer.send_t", nil).UpdateSince(time.Now())
+ metrics.GetOrRegisterCounter("peer.send", nil).Inc(1)
code, found := p.spec.GetCode(msg)
if !found {
return errorf(ErrInvalidMsgType, "%v", code)
diff --git a/p2p/protocols/protocol_test.go b/p2p/protocols/protocol_test.go
index 9912b32e79..5e6b959ca8 100644
--- a/p2p/protocols/protocol_test.go
+++ b/p2p/protocols/protocol_test.go
@@ -373,15 +373,14 @@ WAIT:
}
}
-
-func TestMultiplePeersDropSelf(t *testing.T) {
+func XTestMultiplePeersDropSelf(t *testing.T) {
runMultiplePeers(t, 0,
fmt.Errorf("subprotocol error"),
fmt.Errorf("Message handler error: (msg code 3): dropped"),
)
}
-func TestMultiplePeersDropOther(t *testing.T) {
+func XTestMultiplePeersDropOther(t *testing.T) {
runMultiplePeers(t, 1,
fmt.Errorf("Message handler error: (msg code 3): dropped"),
fmt.Errorf("subprotocol error"),
diff --git a/p2p/rlpx_test.go b/p2p/rlpx_test.go
index a87ebcc92b..7759bedecc 100644
--- a/p2p/rlpx_test.go
+++ b/p2p/rlpx_test.go
@@ -30,12 +30,13 @@ import (
"testing"
"time"
- "github.com/davecgh/go-spew/spew"
"github.com/EthereumCommonwealth/go-callisto/crypto"
"github.com/EthereumCommonwealth/go-callisto/crypto/ecies"
"github.com/EthereumCommonwealth/go-callisto/crypto/sha3"
"github.com/EthereumCommonwealth/go-callisto/p2p/discover"
+ "github.com/EthereumCommonwealth/go-callisto/p2p/simulations/pipes"
"github.com/EthereumCommonwealth/go-callisto/rlp"
+ "github.com/davecgh/go-spew/spew"
)
func TestSharedSecret(t *testing.T) {
@@ -159,7 +160,7 @@ func TestProtocolHandshake(t *testing.T) {
wg sync.WaitGroup
)
- fd0, fd1, err := tcpPipe()
+ fd0, fd1, err := pipes.TCPPipe()
if err != nil {
t.Fatal(err)
}
@@ -601,31 +602,3 @@ func TestHandshakeForwardCompatibility(t *testing.T) {
t.Errorf("ingress-mac('foo') mismatch:\ngot %x\nwant %x", fooIngressHash, wantFooIngressHash)
}
}
-
-// tcpPipe creates an in process full duplex pipe based on a localhost TCP socket
-func tcpPipe() (net.Conn, net.Conn, error) {
- l, err := net.Listen("tcp", "127.0.0.1:0")
- if err != nil {
- return nil, nil, err
- }
- defer l.Close()
-
- var aconn net.Conn
- aerr := make(chan error, 1)
- go func() {
- var err error
- aconn, err = l.Accept()
- aerr <- err
- }()
-
- dconn, err := net.Dial("tcp", l.Addr().String())
- if err != nil {
- <-aerr
- return nil, nil, err
- }
- if err := <-aerr; err != nil {
- dconn.Close()
- return nil, nil, err
- }
- return aconn, dconn, nil
-}
diff --git a/p2p/server.go b/p2p/server.go
index 5897938aaa..98edf5230e 100644
--- a/p2p/server.go
+++ b/p2p/server.go
@@ -594,13 +594,13 @@ running:
// This channel is used by AddPeer to add to the
// ephemeral static peer list. Add it to the dialer,
// it will keep the node connected.
- srv.log.Debug("Adding static node", "node", n)
+ srv.log.Trace("Adding static node", "node", n)
dialstate.addStatic(n)
case n := <-srv.removestatic:
// This channel is used by RemovePeer to send a
// disconnect request to a peer and begin the
// stop keeping the node connected
- srv.log.Debug("Removing static node", "node", n)
+ srv.log.Trace("Removing static node", "node", n)
dialstate.removeStatic(n)
if p, ok := peers[n.ID]; ok {
p.Disconnect(DiscRequested)
diff --git a/p2p/simulations/adapters/docker.go b/p2p/simulations/adapters/docker.go
index 815848f04d..570997ad50 100644
--- a/p2p/simulations/adapters/docker.go
+++ b/p2p/simulations/adapters/docker.go
@@ -27,12 +27,15 @@ import (
"runtime"
"strings"
- "github.com/EthereumCommonwealth/go-callisto/log"
"github.com/EthereumCommonwealth/go-callisto/node"
"github.com/EthereumCommonwealth/go-callisto/p2p/discover"
"github.com/docker/docker/pkg/reexec"
)
+var (
+ ErrLinuxOnly = errors.New("DockerAdapter can only be used on Linux as it uses the current binary (which must be a Linux binary)")
+)
+
// DockerAdapter is a NodeAdapter which runs simulation nodes inside Docker
// containers.
//
@@ -52,7 +55,7 @@ func NewDockerAdapter() (*DockerAdapter, error) {
// It is reasonable to require this because the caller can just
// compile the current binary in a Docker container.
if runtime.GOOS != "linux" {
- return nil, errors.New("DockerAdapter can only be used on Linux as it uses the current binary (which must be a Linux binary)")
+ return nil, ErrLinuxOnly
}
if err := buildDockerImage(); err != nil {
@@ -95,7 +98,10 @@ func (d *DockerAdapter) NewNode(config *NodeConfig) (Node, error) {
conf.Stack.P2P.NoDiscovery = true
conf.Stack.P2P.NAT = nil
conf.Stack.NoUSB = true
- conf.Stack.Logger = log.New("node.id", config.ID.String())
+
+ // listen on all interfaces on a given port, which we set when we
+ // initialise NodeConfig (usually a random port)
+ conf.Stack.P2P.ListenAddr = fmt.Sprintf(":%d", config.Port)
node := &DockerNode{
ExecNode: ExecNode{
diff --git a/p2p/simulations/adapters/exec.go b/p2p/simulations/adapters/exec.go
index 0eae4e1a98..9198a35db5 100644
--- a/p2p/simulations/adapters/exec.go
+++ b/p2p/simulations/adapters/exec.go
@@ -17,6 +17,7 @@
package adapters
import (
+ "bufio"
"context"
"crypto/ecdsa"
"encoding/json"
@@ -103,9 +104,9 @@ func (e *ExecAdapter) NewNode(config *NodeConfig) (Node, error) {
conf.Stack.P2P.NAT = nil
conf.Stack.NoUSB = true
- // listen on a random localhost port (we'll get the actual port after
- // starting the node through the RPC admin.nodeInfo method)
- conf.Stack.P2P.ListenAddr = "127.0.0.1:0"
+ // listen on a localhost port, which we set when we
+ // initialise NodeConfig (usually a random port)
+ conf.Stack.P2P.ListenAddr = fmt.Sprintf(":%d", config.Port)
node := &ExecNode{
ID: config.ID,
@@ -190,9 +191,23 @@ func (n *ExecNode) Start(snapshots map[string][]byte) (err error) {
n.Cmd = cmd
// read the WebSocket address from the stderr logs
- wsAddr, err := findWSAddr(stderrR, 10*time.Second)
- if err != nil {
- return fmt.Errorf("error getting WebSocket address: %s", err)
+ var wsAddr string
+ wsAddrC := make(chan string)
+ go func() {
+ s := bufio.NewScanner(stderrR)
+ for s.Scan() {
+ if strings.Contains(s.Text(), "WebSocket endpoint opened") {
+ wsAddrC <- wsAddrPattern.FindString(s.Text())
+ }
+ }
+ }()
+ select {
+ case wsAddr = <-wsAddrC:
+ if wsAddr == "" {
+ return errors.New("failed to read WebSocket address from stderr")
+ }
+ case <-time.After(10 * time.Second):
+ return errors.New("timed out waiting for WebSocket address on stderr")
}
// create the RPC client and load the node info
@@ -318,6 +333,21 @@ type execNodeConfig struct {
PeerAddrs map[string]string `json:"peer_addrs,omitempty"`
}
+// ExternalIP gets an external IP address so that Enode URL is usable
+func ExternalIP() net.IP {
+ addrs, err := net.InterfaceAddrs()
+ if err != nil {
+ log.Crit("error getting IP address", "err", err)
+ }
+ for _, addr := range addrs {
+ if ip, ok := addr.(*net.IPNet); ok && !ip.IP.IsLoopback() && !ip.IP.IsLinkLocalUnicast() {
+ return ip.IP
+ }
+ }
+ log.Warn("unable to determine explicit IP address, falling back to loopback")
+ return net.IP{127, 0, 0, 1}
+}
+
// execP2PNode starts a devp2p node when the current binary is executed with
// argv[0] being "p2p-node", reading the service / ID from argv[1] / argv[2]
// and the node config from the _P2P_NODE_CONFIG environment variable
@@ -341,25 +371,11 @@ func execP2PNode() {
conf.Stack.P2P.PrivateKey = conf.Node.PrivateKey
conf.Stack.Logger = log.New("node.id", conf.Node.ID.String())
- // use explicit IP address in ListenAddr so that Enode URL is usable
- externalIP := func() string {
- addrs, err := net.InterfaceAddrs()
- if err != nil {
- log.Crit("error getting IP address", "err", err)
- }
- for _, addr := range addrs {
- if ip, ok := addr.(*net.IPNet); ok && !ip.IP.IsLoopback() {
- return ip.IP.String()
- }
- }
- log.Crit("unable to determine explicit IP address")
- return ""
- }
if strings.HasPrefix(conf.Stack.P2P.ListenAddr, ":") {
- conf.Stack.P2P.ListenAddr = externalIP() + conf.Stack.P2P.ListenAddr
+ conf.Stack.P2P.ListenAddr = ExternalIP().String() + conf.Stack.P2P.ListenAddr
}
if conf.Stack.WSHost == "0.0.0.0" {
- conf.Stack.WSHost = externalIP()
+ conf.Stack.WSHost = ExternalIP().String()
}
// initialize the devp2p stack
diff --git a/p2p/simulations/adapters/inproc.go b/p2p/simulations/adapters/inproc.go
index 81271d449f..5d4e0ce449 100644
--- a/p2p/simulations/adapters/inproc.go
+++ b/p2p/simulations/adapters/inproc.go
@@ -28,12 +28,14 @@ import (
"github.com/EthereumCommonwealth/go-callisto/node"
"github.com/EthereumCommonwealth/go-callisto/p2p"
"github.com/EthereumCommonwealth/go-callisto/p2p/discover"
+ "github.com/EthereumCommonwealth/go-callisto/p2p/simulations/pipes"
"github.com/EthereumCommonwealth/go-callisto/rpc"
)
// SimAdapter is a NodeAdapter which creates in-memory simulation nodes and
-// connects them using in-memory net.Pipe connections
+// connects them using net.Pipe
type SimAdapter struct {
+ pipe func() (net.Conn, net.Conn, error)
mtx sync.RWMutex
nodes map[discover.NodeID]*SimNode
services map[string]ServiceFunc
@@ -42,8 +44,18 @@ type SimAdapter struct {
// NewSimAdapter creates a SimAdapter which is capable of running in-memory
// simulation nodes running any of the given services (the services to run on a
// particular node are passed to the NewNode function in the NodeConfig)
+// the adapter uses a net.Pipe for in-memory simulated network connections
func NewSimAdapter(services map[string]ServiceFunc) *SimAdapter {
return &SimAdapter{
+ pipe: pipes.NetPipe,
+ nodes: make(map[discover.NodeID]*SimNode),
+ services: services,
+ }
+}
+
+func NewTCPAdapter(services map[string]ServiceFunc) *SimAdapter {
+ return &SimAdapter{
+ pipe: pipes.TCPPipe,
nodes: make(map[discover.NodeID]*SimNode),
services: services,
}
@@ -81,7 +93,7 @@ func (s *SimAdapter) NewNode(config *NodeConfig) (Node, error) {
MaxPeers: math.MaxInt32,
NoDiscovery: true,
Dialer: s,
- EnableMsgEvents: true,
+ EnableMsgEvents: config.EnableMsgEvents,
},
NoUSB: true,
Logger: log.New("node.id", id.String()),
@@ -102,7 +114,7 @@ func (s *SimAdapter) NewNode(config *NodeConfig) (Node, error) {
}
// Dial implements the p2p.NodeDialer interface by connecting to the node using
-// an in-memory net.Pipe connection
+// an in-memory net.Pipe
func (s *SimAdapter) Dial(dest *discover.Node) (conn net.Conn, err error) {
node, ok := s.GetNode(dest.ID)
if !ok {
@@ -112,7 +124,14 @@ func (s *SimAdapter) Dial(dest *discover.Node) (conn net.Conn, err error) {
if srv == nil {
return nil, fmt.Errorf("node not running: %s", dest.ID)
}
- pipe1, pipe2 := net.Pipe()
+ // SimAdapter.pipe is net.Pipe (NewSimAdapter)
+ pipe1, pipe2, err := s.pipe()
+ if err != nil {
+ return nil, err
+ }
+ // this is simulated 'listening'
+ // asynchronously call the dialed destintion node's p2p server
+ // to set up connection on the 'listening' side
go srv.SetupConn(pipe1, 0, nil)
return pipe2, nil
}
@@ -140,8 +159,8 @@ func (s *SimAdapter) GetNode(id discover.NodeID) (*SimNode, bool) {
}
// SimNode is an in-memory simulation node which connects to other nodes using
-// an in-memory net.Pipe connection (see SimAdapter.Dial), running devp2p
-// protocols directly over that pipe
+// net.Pipe (see SimAdapter.Dial), running devp2p protocols directly over that
+// pipe
type SimNode struct {
lock sync.RWMutex
ID discover.NodeID
@@ -241,7 +260,7 @@ func (sn *SimNode) Start(snapshots map[string][]byte) error {
for _, name := range sn.config.Services {
if err := sn.node.Register(newService(name)); err != nil {
regErr = err
- return
+ break
}
}
})
@@ -314,3 +333,18 @@ func (sn *SimNode) NodeInfo() *p2p.NodeInfo {
}
return server.NodeInfo()
}
+
+func setSocketBuffer(conn net.Conn, socketReadBuffer int, socketWriteBuffer int) error {
+ switch v := conn.(type) {
+ case *net.UnixConn:
+ err := v.SetReadBuffer(socketReadBuffer)
+ if err != nil {
+ return err
+ }
+ err = v.SetWriteBuffer(socketWriteBuffer)
+ if err != nil {
+ return err
+ }
+ }
+ return nil
+}
diff --git a/p2p/simulations/adapters/inproc_test.go b/p2p/simulations/adapters/inproc_test.go
new file mode 100644
index 0000000000..497561486e
--- /dev/null
+++ b/p2p/simulations/adapters/inproc_test.go
@@ -0,0 +1,259 @@
+// Copyright 2017 The go-ethereum Authors
+// This file is part of the go-ethereum library.
+//
+// The go-ethereum library is free software: you can redistribute it and/or modify
+// it under the terms of the GNU Lesser General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// The go-ethereum library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public License
+// along with the go-ethereum library. If not, see .
+
+package adapters
+
+import (
+ "bytes"
+ "encoding/binary"
+ "fmt"
+ "testing"
+ "time"
+
+ "github.com/EthereumCommonwealth/go-callisto/p2p/simulations/pipes"
+)
+
+func TestTCPPipe(t *testing.T) {
+ c1, c2, err := pipes.TCPPipe()
+ if err != nil {
+ t.Fatal(err)
+ }
+
+ done := make(chan struct{})
+
+ go func() {
+ msgs := 50
+ size := 1024
+ for i := 0; i < msgs; i++ {
+ msg := make([]byte, size)
+ _ = binary.PutUvarint(msg, uint64(i))
+
+ _, err := c1.Write(msg)
+ if err != nil {
+ t.Fatal(err)
+ }
+ }
+
+ for i := 0; i < msgs; i++ {
+ msg := make([]byte, size)
+ _ = binary.PutUvarint(msg, uint64(i))
+
+ out := make([]byte, size)
+ _, err := c2.Read(out)
+ if err != nil {
+ t.Fatal(err)
+ }
+
+ if !bytes.Equal(msg, out) {
+ t.Fatalf("expected %#v, got %#v", msg, out)
+ }
+ }
+ done <- struct{}{}
+ }()
+
+ select {
+ case <-done:
+ case <-time.After(5 * time.Second):
+ t.Fatal("test timeout")
+ }
+}
+
+func TestTCPPipeBidirections(t *testing.T) {
+ c1, c2, err := pipes.TCPPipe()
+ if err != nil {
+ t.Fatal(err)
+ }
+
+ done := make(chan struct{})
+
+ go func() {
+ msgs := 50
+ size := 7
+ for i := 0; i < msgs; i++ {
+ msg := []byte(fmt.Sprintf("ping %02d", i))
+
+ _, err := c1.Write(msg)
+ if err != nil {
+ t.Fatal(err)
+ }
+ }
+
+ for i := 0; i < msgs; i++ {
+ expected := []byte(fmt.Sprintf("ping %02d", i))
+
+ out := make([]byte, size)
+ _, err := c2.Read(out)
+ if err != nil {
+ t.Fatal(err)
+ }
+
+ if !bytes.Equal(expected, out) {
+ t.Fatalf("expected %#v, got %#v", out, expected)
+ } else {
+ msg := []byte(fmt.Sprintf("pong %02d", i))
+ _, err := c2.Write(msg)
+ if err != nil {
+ t.Fatal(err)
+ }
+ }
+ }
+
+ for i := 0; i < msgs; i++ {
+ expected := []byte(fmt.Sprintf("pong %02d", i))
+
+ out := make([]byte, size)
+ _, err := c1.Read(out)
+ if err != nil {
+ t.Fatal(err)
+ }
+
+ if !bytes.Equal(expected, out) {
+ t.Fatalf("expected %#v, got %#v", out, expected)
+ }
+ }
+ done <- struct{}{}
+ }()
+
+ select {
+ case <-done:
+ case <-time.After(5 * time.Second):
+ t.Fatal("test timeout")
+ }
+}
+
+func TestNetPipe(t *testing.T) {
+ c1, c2, err := pipes.NetPipe()
+ if err != nil {
+ t.Fatal(err)
+ }
+
+ done := make(chan struct{})
+
+ go func() {
+ msgs := 50
+ size := 1024
+ // netPipe is blocking, so writes are emitted asynchronously
+ go func() {
+ for i := 0; i < msgs; i++ {
+ msg := make([]byte, size)
+ _ = binary.PutUvarint(msg, uint64(i))
+
+ _, err := c1.Write(msg)
+ if err != nil {
+ t.Fatal(err)
+ }
+ }
+ }()
+
+ for i := 0; i < msgs; i++ {
+ msg := make([]byte, size)
+ _ = binary.PutUvarint(msg, uint64(i))
+
+ out := make([]byte, size)
+ _, err := c2.Read(out)
+ if err != nil {
+ t.Fatal(err)
+ }
+
+ if !bytes.Equal(msg, out) {
+ t.Fatalf("expected %#v, got %#v", msg, out)
+ }
+ }
+
+ done <- struct{}{}
+ }()
+
+ select {
+ case <-done:
+ case <-time.After(5 * time.Second):
+ t.Fatal("test timeout")
+ }
+}
+
+func TestNetPipeBidirections(t *testing.T) {
+ c1, c2, err := pipes.NetPipe()
+ if err != nil {
+ t.Fatal(err)
+ }
+
+ done := make(chan struct{})
+
+ go func() {
+ msgs := 1000
+ size := 8
+ pingTemplate := "ping %03d"
+ pongTemplate := "pong %03d"
+
+ // netPipe is blocking, so writes are emitted asynchronously
+ go func() {
+ for i := 0; i < msgs; i++ {
+ msg := []byte(fmt.Sprintf(pingTemplate, i))
+
+ _, err := c1.Write(msg)
+ if err != nil {
+ t.Fatal(err)
+ }
+ }
+ }()
+
+ // netPipe is blocking, so reads for pong are emitted asynchronously
+ go func() {
+ for i := 0; i < msgs; i++ {
+ expected := []byte(fmt.Sprintf(pongTemplate, i))
+
+ out := make([]byte, size)
+ _, err := c1.Read(out)
+ if err != nil {
+ t.Fatal(err)
+ }
+
+ if !bytes.Equal(expected, out) {
+ t.Fatalf("expected %#v, got %#v", expected, out)
+ }
+ }
+
+ done <- struct{}{}
+ }()
+
+ // expect to read pings, and respond with pongs to the alternate connection
+ for i := 0; i < msgs; i++ {
+ expected := []byte(fmt.Sprintf(pingTemplate, i))
+
+ out := make([]byte, size)
+ _, err := c2.Read(out)
+ if err != nil {
+ t.Fatal(err)
+ }
+
+ if !bytes.Equal(expected, out) {
+ t.Fatalf("expected %#v, got %#v", expected, out)
+ } else {
+ msg := []byte(fmt.Sprintf(pongTemplate, i))
+
+ _, err := c2.Write(msg)
+ if err != nil {
+ t.Fatal(err)
+ }
+ }
+ }
+ }()
+
+ select {
+ case <-done:
+ case <-time.After(5 * time.Second):
+ t.Fatal("test timeout")
+ }
+}
diff --git a/p2p/simulations/adapters/types.go b/p2p/simulations/adapters/types.go
index 52b46fb9b0..cc0f72fd6e 100644
--- a/p2p/simulations/adapters/types.go
+++ b/p2p/simulations/adapters/types.go
@@ -23,6 +23,7 @@ import (
"fmt"
"net"
"os"
+ "strconv"
"github.com/docker/docker/pkg/reexec"
"github.com/EthereumCommonwealth/go-callisto/crypto"
@@ -97,24 +98,30 @@ type NodeConfig struct {
// function to sanction or prevent suggesting a peer
Reachable func(id discover.NodeID) bool
+
+ Port uint16
}
// nodeConfigJSON is used to encode and decode NodeConfig as JSON by encoding
// all fields as strings
type nodeConfigJSON struct {
- ID string `json:"id"`
- PrivateKey string `json:"private_key"`
- Name string `json:"name"`
- Services []string `json:"services"`
+ ID string `json:"id"`
+ PrivateKey string `json:"private_key"`
+ Name string `json:"name"`
+ Services []string `json:"services"`
+ EnableMsgEvents bool `json:"enable_msg_events"`
+ Port uint16 `json:"port"`
}
// MarshalJSON implements the json.Marshaler interface by encoding the config
// fields as strings
func (n *NodeConfig) MarshalJSON() ([]byte, error) {
confJSON := nodeConfigJSON{
- ID: n.ID.String(),
- Name: n.Name,
- Services: n.Services,
+ ID: n.ID.String(),
+ Name: n.Name,
+ Services: n.Services,
+ Port: n.Port,
+ EnableMsgEvents: n.EnableMsgEvents,
}
if n.PrivateKey != nil {
confJSON.PrivateKey = hex.EncodeToString(crypto.FromECDSA(n.PrivateKey))
@@ -152,6 +159,8 @@ func (n *NodeConfig) UnmarshalJSON(data []byte) error {
n.Name = confJSON.Name
n.Services = confJSON.Services
+ n.Port = confJSON.Port
+ n.EnableMsgEvents = confJSON.EnableMsgEvents
return nil
}
@@ -163,13 +172,36 @@ func RandomNodeConfig() *NodeConfig {
if err != nil {
panic("unable to generate key")
}
- var id discover.NodeID
- pubkey := crypto.FromECDSAPub(&key.PublicKey)
- copy(id[:], pubkey[1:])
- return &NodeConfig{
- ID: id,
- PrivateKey: key,
+
+ id := discover.PubkeyID(&key.PublicKey)
+ port, err := assignTCPPort()
+ if err != nil {
+ panic("unable to assign tcp port")
}
+ return &NodeConfig{
+ ID: id,
+ Name: fmt.Sprintf("node_%s", id.String()),
+ PrivateKey: key,
+ Port: port,
+ EnableMsgEvents: true,
+ }
+}
+
+func assignTCPPort() (uint16, error) {
+ l, err := net.Listen("tcp", "127.0.0.1:0")
+ if err != nil {
+ return 0, err
+ }
+ l.Close()
+ _, port, err := net.SplitHostPort(l.Addr().String())
+ if err != nil {
+ return 0, err
+ }
+ p, err := strconv.ParseInt(port, 10, 32)
+ if err != nil {
+ return 0, err
+ }
+ return uint16(p), nil
}
// ServiceContext is a collection of options and methods which can be utilised
diff --git a/p2p/simulations/http.go b/p2p/simulations/http.go
index ea66b1d5eb..1fbd6a4adf 100644
--- a/p2p/simulations/http.go
+++ b/p2p/simulations/http.go
@@ -561,7 +561,8 @@ func (s *Server) LoadSnapshot(w http.ResponseWriter, req *http.Request) {
// CreateNode creates a node in the network using the given configuration
func (s *Server) CreateNode(w http.ResponseWriter, req *http.Request) {
- config := adapters.RandomNodeConfig()
+ config := &adapters.NodeConfig{}
+
err := json.NewDecoder(req.Body).Decode(config)
if err != nil && err != io.EOF {
http.Error(w, err.Error(), http.StatusBadRequest)
diff --git a/p2p/simulations/http_test.go b/p2p/simulations/http_test.go
index ae71e3663b..71647f4ece 100644
--- a/p2p/simulations/http_test.go
+++ b/p2p/simulations/http_test.go
@@ -348,7 +348,8 @@ func startTestNetwork(t *testing.T, client *Client) []string {
nodeCount := 2
nodeIDs := make([]string, nodeCount)
for i := 0; i < nodeCount; i++ {
- node, err := client.CreateNode(nil)
+ config := adapters.RandomNodeConfig()
+ node, err := client.CreateNode(config)
if err != nil {
t.Fatalf("error creating node: %s", err)
}
@@ -527,7 +528,9 @@ func TestHTTPNodeRPC(t *testing.T) {
// start a node in the network
client := NewClient(s.URL)
- node, err := client.CreateNode(nil)
+
+ config := adapters.RandomNodeConfig()
+ node, err := client.CreateNode(config)
if err != nil {
t.Fatalf("error creating node: %s", err)
}
@@ -589,7 +592,8 @@ func TestHTTPSnapshot(t *testing.T) {
nodeCount := 2
nodes := make([]*p2p.NodeInfo, nodeCount)
for i := 0; i < nodeCount; i++ {
- node, err := client.CreateNode(nil)
+ config := adapters.RandomNodeConfig()
+ node, err := client.CreateNode(config)
if err != nil {
t.Fatalf("error creating node: %s", err)
}
diff --git a/p2p/simulations/mocker.go b/p2p/simulations/mocker.go
index 96583dc74b..bc131cddd3 100644
--- a/p2p/simulations/mocker.go
+++ b/p2p/simulations/mocker.go
@@ -26,6 +26,7 @@ import (
"github.com/EthereumCommonwealth/go-callisto/log"
"github.com/EthereumCommonwealth/go-callisto/p2p/discover"
+ "github.com/EthereumCommonwealth/go-callisto/p2p/simulations/adapters"
)
//a map of mocker names to its function
@@ -102,7 +103,13 @@ func startStop(net *Network, quit chan struct{}, nodeCount int) {
func probabilistic(net *Network, quit chan struct{}, nodeCount int) {
nodes, err := connectNodesInRing(net, nodeCount)
if err != nil {
- panic("Could not startup node network for mocker")
+ select {
+ case <-quit:
+ //error may be due to abortion of mocking; so the quit channel is closed
+ return
+ default:
+ panic("Could not startup node network for mocker")
+ }
}
for {
select {
@@ -143,7 +150,7 @@ func probabilistic(net *Network, quit chan struct{}, nodeCount int) {
log.Debug(fmt.Sprintf("node %v shutting down", nodes[i]))
err := net.Stop(nodes[i])
if err != nil {
- log.Error(fmt.Sprintf("Error stopping node %s", nodes[i]))
+ log.Error("Error stopping node", "node", nodes[i])
wg.Done()
continue
}
@@ -151,7 +158,7 @@ func probabilistic(net *Network, quit chan struct{}, nodeCount int) {
time.Sleep(randWait)
err := net.Start(id)
if err != nil {
- log.Error(fmt.Sprintf("Error starting node %s", id))
+ log.Error("Error starting node", "node", id)
}
wg.Done()
}(nodes[i])
@@ -165,9 +172,10 @@ func probabilistic(net *Network, quit chan struct{}, nodeCount int) {
func connectNodesInRing(net *Network, nodeCount int) ([]discover.NodeID, error) {
ids := make([]discover.NodeID, nodeCount)
for i := 0; i < nodeCount; i++ {
- node, err := net.NewNode()
+ conf := adapters.RandomNodeConfig()
+ node, err := net.NewNodeWithConfig(conf)
if err != nil {
- log.Error("Error creating a node! %s", err)
+ log.Error("Error creating a node!", "err", err)
return nil, err
}
ids[i] = node.ID()
@@ -175,7 +183,7 @@ func connectNodesInRing(net *Network, nodeCount int) ([]discover.NodeID, error)
for _, id := range ids {
if err := net.Start(id); err != nil {
- log.Error("Error starting a node! %s", err)
+ log.Error("Error starting a node!", "err", err)
return nil, err
}
log.Debug(fmt.Sprintf("node %v starting up", id))
@@ -183,7 +191,7 @@ func connectNodesInRing(net *Network, nodeCount int) ([]discover.NodeID, error)
for i, id := range ids {
peerID := ids[(i+1)%len(ids)]
if err := net.Connect(id, peerID); err != nil {
- log.Error("Error connecting a node to a peer! %s", err)
+ log.Error("Error connecting a node to a peer!", "err", err)
return nil, err
}
}
diff --git a/p2p/simulations/network.go b/p2p/simulations/network.go
index 4c44207385..a50cfd35e3 100644
--- a/p2p/simulations/network.go
+++ b/p2p/simulations/network.go
@@ -382,6 +382,15 @@ func (net *Network) GetNodeByName(name string) *Node {
return net.getNodeByName(name)
}
+// GetNodes returns the existing nodes
+func (net *Network) GetNodes() (nodes []*Node) {
+ net.lock.Lock()
+ defer net.lock.Unlock()
+
+ nodes = append(nodes, net.Nodes...)
+ return nodes
+}
+
func (net *Network) getNode(id discover.NodeID) *Node {
i, found := net.nodeMap[id]
if !found {
@@ -399,15 +408,6 @@ func (net *Network) getNodeByName(name string) *Node {
return nil
}
-// GetNodes returns the existing nodes
-func (net *Network) GetNodes() (nodes []*Node) {
- net.lock.Lock()
- defer net.lock.Unlock()
-
- nodes = append(nodes, net.Nodes...)
- return nodes
-}
-
// GetConn returns the connection which exists between "one" and "other"
// regardless of which node initiated the connection
func (net *Network) GetConn(oneID, otherID discover.NodeID) *Conn {
diff --git a/p2p/simulations/network_test.go b/p2p/simulations/network_test.go
index 6cf313ed4d..b471aef86c 100644
--- a/p2p/simulations/network_test.go
+++ b/p2p/simulations/network_test.go
@@ -41,7 +41,8 @@ func TestNetworkSimulation(t *testing.T) {
nodeCount := 20
ids := make([]discover.NodeID, nodeCount)
for i := 0; i < nodeCount; i++ {
- node, err := network.NewNode()
+ conf := adapters.RandomNodeConfig()
+ node, err := network.NewNodeWithConfig(conf)
if err != nil {
t.Fatalf("error creating node: %s", err)
}
diff --git a/p2p/simulations/pipes/pipes.go b/p2p/simulations/pipes/pipes.go
new file mode 100644
index 0000000000..8532c1bcf0
--- /dev/null
+++ b/p2p/simulations/pipes/pipes.go
@@ -0,0 +1,55 @@
+// Copyright 2017 The go-ethereum Authors
+// This file is part of the go-ethereum library.
+//
+// The go-ethereum library is free software: you can redistribute it and/or modify
+// it under the terms of the GNU Lesser General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// The go-ethereum library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public License
+// along with the go-ethereum library. If not, see .
+
+package pipes
+
+import (
+ "net"
+)
+
+// NetPipe wraps net.Pipe in a signature returning an error
+func NetPipe() (net.Conn, net.Conn, error) {
+ p1, p2 := net.Pipe()
+ return p1, p2, nil
+}
+
+// TCPPipe creates an in process full duplex pipe based on a localhost TCP socket
+func TCPPipe() (net.Conn, net.Conn, error) {
+ l, err := net.Listen("tcp", "127.0.0.1:0")
+ if err != nil {
+ return nil, nil, err
+ }
+ defer l.Close()
+
+ var aconn net.Conn
+ aerr := make(chan error, 1)
+ go func() {
+ var err error
+ aconn, err = l.Accept()
+ aerr <- err
+ }()
+
+ dconn, err := net.Dial("tcp", l.Addr().String())
+ if err != nil {
+ <-aerr
+ return nil, nil, err
+ }
+ if err := <-aerr; err != nil {
+ dconn.Close()
+ return nil, nil, err
+ }
+ return aconn, dconn, nil
+}
diff --git a/params/version.go b/params/version.go
index 471c935075..c35f04e954 100644
--- a/params/version.go
+++ b/params/version.go
@@ -21,10 +21,10 @@ import (
)
const (
- VersionMajor = 1 // Major version component of the current release
- VersionMinor = 8 // Minor version component of the current release
- VersionPatch = 11 // Patch version component of the current release
- VersionMeta = "CLO stable" // Version metadata to append to the version string
+ VersionMajor = 1 // Major version component of the current release
+ VersionMinor = 8 // Minor version component of the current release
+ VersionPatch = 12 // Patch version component of the current release
+ VersionMeta = "CLO Unstable" // Version metadata to append to the version string
)
// Version holds the textual version string.
diff --git a/rpc/client.go b/rpc/client.go
index d9dcaae47f..ede6c91785 100644
--- a/rpc/client.go
+++ b/rpc/client.go
@@ -61,7 +61,7 @@ const (
// The approach taken here is to maintain a per-subscription linked list buffer
// shrinks on demand. If the buffer reaches the size below, the subscription is
// dropped.
- maxClientSubscriptionBuffer = 8000
+ maxClientSubscriptionBuffer = 20000
)
// BatchElem is an element in a batch request.
diff --git a/whisper/whisperv5/peer_test.go b/whisper/whisperv5/peer_test.go
index 75ab525900..9769f85b43 100644
--- a/whisper/whisperv5/peer_test.go
+++ b/whisper/whisperv5/peer_test.go
@@ -19,7 +19,6 @@ package whisperv5
import (
"bytes"
"crypto/ecdsa"
- "fmt"
"net"
"sync"
"testing"
@@ -108,8 +107,6 @@ func TestSimulation(t *testing.T) {
func initialize(t *testing.T) {
var err error
- ip := net.IPv4(127, 0, 0, 1)
- port0 := 30303
for i := 0; i < NumNodes; i++ {
var node TestNode
@@ -128,29 +125,15 @@ func initialize(t *testing.T) {
if err != nil {
t.Fatalf("failed convert the key: %s.", keys[i])
}
- port := port0 + i
- addr := fmt.Sprintf(":%d", port) // e.g. ":30303"
name := common.MakeName("whisper-go", "2.0")
- var peers []*discover.Node
- if i > 0 {
- peerNodeId := nodes[i-1].id
- peerPort := uint16(port - 1)
- peerNode := discover.PubkeyID(&peerNodeId.PublicKey)
- peer := discover.NewNode(peerNode, ip, peerPort, peerPort)
- peers = append(peers, peer)
- }
-
node.server = &p2p.Server{
Config: p2p.Config{
- PrivateKey: node.id,
- MaxPeers: NumNodes/2 + 1,
- Name: name,
- Protocols: node.shh.Protocols(),
- ListenAddr: addr,
- NAT: nat.Any(),
- BootstrapNodes: peers,
- StaticNodes: peers,
- TrustedNodes: peers,
+ PrivateKey: node.id,
+ MaxPeers: NumNodes/2 + 1,
+ Name: name,
+ Protocols: node.shh.Protocols(),
+ ListenAddr: "127.0.0.1:0",
+ NAT: nat.Any(),
},
}
@@ -159,6 +142,15 @@ func initialize(t *testing.T) {
t.Fatalf("failed to start server %d.", i)
}
+ for j := 0; j < i; j++ {
+ peerNodeId := nodes[j].id
+ address, _ := net.ResolveTCPAddr("tcp", nodes[j].server.ListenAddr)
+ peerPort := uint16(address.Port)
+ peerNode := discover.PubkeyID(&peerNodeId.PublicKey)
+ peer := discover.NewNode(peerNode, address.IP, peerPort, peerPort)
+ node.server.AddPeer(peer)
+ }
+
nodes[i] = &node
}
}
diff --git a/whisper/whisperv6/peer_test.go b/whisper/whisperv6/peer_test.go
index ebf89216fa..d6f1d4f5ca 100644
--- a/whisper/whisperv6/peer_test.go
+++ b/whisper/whisperv6/peer_test.go
@@ -21,12 +21,13 @@ import (
"crypto/ecdsa"
"fmt"
mrand "math/rand"
- "net"
"sync"
"sync/atomic"
"testing"
"time"
+ "net"
+
"github.com/EthereumCommonwealth/go-callisto/common"
"github.com/EthereumCommonwealth/go-callisto/common/hexutil"
"github.com/EthereumCommonwealth/go-callisto/crypto"
@@ -173,8 +174,6 @@ func initialize(t *testing.T) {
initBloom(t)
var err error
- ip := net.IPv4(127, 0, 0, 1)
- port0 := 30303
for i := 0; i < NumNodes; i++ {
var node TestNode
@@ -199,40 +198,36 @@ func initialize(t *testing.T) {
if err != nil {
t.Fatalf("failed convert the key: %s.", keys[i])
}
- port := port0 + i
- addr := fmt.Sprintf(":%d", port) // e.g. ":30303"
name := common.MakeName("whisper-go", "2.0")
- var peers []*discover.Node
- if i > 0 {
- peerNodeID := nodes[i-1].id
- peerPort := uint16(port - 1)
- peerNode := discover.PubkeyID(&peerNodeID.PublicKey)
- peer := discover.NewNode(peerNode, ip, peerPort, peerPort)
- peers = append(peers, peer)
- }
node.server = &p2p.Server{
Config: p2p.Config{
- PrivateKey: node.id,
- MaxPeers: NumNodes/2 + 1,
- Name: name,
- Protocols: node.shh.Protocols(),
- ListenAddr: addr,
- NAT: nat.Any(),
- BootstrapNodes: peers,
- StaticNodes: peers,
- TrustedNodes: peers,
+ PrivateKey: node.id,
+ MaxPeers: NumNodes/2 + 1,
+ Name: name,
+ Protocols: node.shh.Protocols(),
+ ListenAddr: "127.0.0.1:0",
+ NAT: nat.Any(),
},
}
+ go startServer(t, node.server)
+
nodes[i] = &node
}
- for i := 0; i < NumNodes; i++ {
- go startServer(t, nodes[i].server)
- }
-
waitForServersToStart(t)
+
+ for i := 0; i < NumNodes; i++ {
+ for j := 0; j < i; j++ {
+ peerNodeId := nodes[j].id
+ address, _ := net.ResolveTCPAddr("tcp", nodes[j].server.ListenAddr)
+ peerPort := uint16(address.Port)
+ peerNode := discover.PubkeyID(&peerNodeId.PublicKey)
+ peer := discover.NewNode(peerNode, address.IP, peerPort, peerPort)
+ nodes[i].server.AddPeer(peer)
+ }
+ }
}
func startServer(t *testing.T, s *p2p.Server) {