p2p: fixes for traviscli using gofmt

This commit is contained in:
Kiel barry 2018-05-02 12:36:47 -07:00
commit 9fe645fac2
48 changed files with 503 additions and 268 deletions

View file

@ -31,7 +31,6 @@ matrix:
script:
- unset -f cd # workaround for https://github.com/travis-ci/travis-ci/issues/8703
- brew update
- brew install caskroom/cask/brew-cask
- brew cask install osxfuse
- go run build/ci.go install
- go run build/ci.go test -coverage $TEST_PACKAGES

View file

@ -1 +1 @@
1.8.7
1.8.8

View file

@ -33,15 +33,15 @@ type Event struct {
Inputs Arguments
}
func (event Event) String() string {
inputs := make([]string, len(event.Inputs))
for i, input := range event.Inputs {
func (e Event) String() string {
inputs := make([]string, len(e.Inputs))
for i, input := range e.Inputs {
inputs[i] = fmt.Sprintf("%v %v", input.Name, input.Type)
if input.Indexed {
inputs[i] = fmt.Sprintf("%v indexed %v", input.Name, input.Type)
}
}
return fmt.Sprintf("event %v(%v)", event.Name, strings.Join(inputs, ", "))
return fmt.Sprintf("e %v(%v)", e.Name, strings.Join(inputs, ", "))
}
// Id returns the canonical representation of the event's signature used by the

View file

@ -731,7 +731,7 @@ func doAndroidArchive(cmdline []string) {
// Build the Android archive and Maven resources
build.MustRun(goTool("get", "golang.org/x/mobile/cmd/gomobile", "golang.org/x/mobile/cmd/gobind"))
build.MustRun(gomobileTool("init", "--ndk", os.Getenv("ANDROID_NDK")))
build.MustRun(gomobileTool("bind", "--target", "android", "--javapkg", "org.ethereum", "-v", "github.com/ethereum/go-ethereum/mobile"))
build.MustRun(gomobileTool("bind", "-ldflags", "-s -w", "--target", "android", "--javapkg", "org.ethereum", "-v", "github.com/ethereum/go-ethereum/mobile"))
if *local {
// If we're building locally, copy bundle to build dir and skip Maven
@ -852,7 +852,7 @@ func doXCodeFramework(cmdline []string) {
// Build the iOS XCode framework
build.MustRun(goTool("get", "golang.org/x/mobile/cmd/gomobile", "golang.org/x/mobile/cmd/gobind"))
build.MustRun(gomobileTool("init"))
bind := gomobileTool("bind", "--target", "ios", "--tags", "ios", "-v", "github.com/ethereum/go-ethereum/mobile")
bind := gomobileTool("bind", "-ldflags", "-s -w", "--target", "ios", "--tags", "ios", "-v", "github.com/ethereum/go-ethereum/mobile")
if *local {
// If we're building locally, use the build folder and stop afterwards

View file

@ -12,6 +12,11 @@ synchronised with the chain or a particular Ethereum node that has no built-in (
Clef can run as a daemon on the same machine, or off a usb-stick like [usb armory](https://inversepath.com/usbarmory),
or a separate VM in a [QubesOS](https://www.qubes-os.org/) type os setup.
Check out
* the [tutorial](tutorial.md) for some concrete examples on how the signer works.
* the [setup docs](docs/setup.md) for some information on how to configure it to work on QubesOS or USBArmory.
## Command line flags
Clef accepts the following command line options:
@ -49,7 +54,6 @@ Example:
signer -keystore /my/keystore -chainid 4
```
Check out the [tutorial](tutorial.md) for some concrete examples on how the signer works.
## Security model
@ -862,3 +866,12 @@ A UI should conform to the following rules.
along with the UI.
### UI Implementations
There are a couple of implementation for a UI. We'll try to keep this list up to date.
| Name | Repo | UI type| No external resources| Blocky support| Verifies permissions | Hash information | No secondary storage | Statically linked| Can modify parameters|
| ---- | ---- | -------| ---- | ---- | ---- |---- | ---- | ---- | ---- |
| QtSigner| https://github.com/holiman/qtsigner/| Python3/QT-based| :+1:| :+1:| :+1:| :+1:| :+1:| :x: | :+1: (partially)|
| GtkSigner| https://github.com/holiman/gtksigner| Python3/GTK-based| :+1:| :x:| :x:| :+1:| :+1:| :x: | :x: |
| Frame | https://github.com/floating/frame/commits/go-signer| Electron-based| :x:| :x:| :x:| :x:| ?| :x: | :x: |

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 20 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 19 KiB

View file

@ -0,0 +1,23 @@
"""
This implements a dispatcher which listens to localhost:8550, and proxies
requests via qrexec to the service qubes.EthSign on a target domain
"""
import http.server
import socketserver,subprocess
PORT=8550
TARGET_DOMAIN= 'debian-work'
class Dispatcher(http.server.BaseHTTPRequestHandler):
def do_POST(self):
post_data = self.rfile.read(int(self.headers['Content-Length']))
p = subprocess.Popen(['/usr/bin/qrexec-client-vm',TARGET_DOMAIN,'qubes.Clefsign'],stdin=subprocess.PIPE, stdout=subprocess.PIPE)
output = p.communicate(post_data)[0]
self.wfile.write(output)
with socketserver.TCPServer(("",PORT), Dispatcher) as httpd:
print("Serving at port", PORT)
httpd.serve_forever()

View file

@ -0,0 +1,16 @@
#!/bin/bash
SIGNER_BIN="/home/user/tools/clef/clef"
SIGNER_CMD="/home/user/tools/gtksigner/gtkui.py -s $SIGNER_BIN"
# Start clef if not already started
if [ ! -S /home/user/.clef/clef.ipc ]; then
$SIGNER_CMD &
sleep 1
fi
# Should be started by now
if [ -S /home/user/.clef/clef.ipc ]; then
# Post incoming request to HTTP channel
curl -H "Content-Type: application/json" -X POST -d @- http://localhost:8550 2>/dev/null
fi

Binary file not shown.

After

Width:  |  Height:  |  Size: 25 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 42 KiB

198
cmd/clef/docs/setup.md Normal file
View file

@ -0,0 +1,198 @@
# Setting up Clef
This document describes how Clef can be used in a more secure manner than executing it from your everyday laptop,
in order to ensure that the keys remain safe in the event that your computer should get compromised.
## Qubes OS
### Background
The Qubes operating system is based around virtual machines (qubes), where a set of virtual machines are configured, typically for
different purposes such as:
- personal
- Your personal email, browsing etc
- work
- Work email etc
- vault
- a VM without network access, where gpg-keys and/or keepass credentials are stored.
A couple of dedicated virtual machines handle externalities:
- sys-net provides networking to all other (network-enabled) machines
- sys-firewall handles firewall rules
- sys-usb handles USB devices, and can map usb-devices to certain qubes.
The goal of this document is to describe how we can set up clef to provide secure transaction
signing from a `vault` vm, to another networked qube which runs Dapps.
### Setup
There are two ways that this can be achieved: integrated via Qubes or integrated via networking.
#### 1. Qubes Integrated
Qubes provdes a facility for inter-qubes communication via `qrexec`. A qube can request to make a cross-qube RPC request
to another qube. The OS then asks the user if the call is permitted.
![Example](qubes/qrexec-example.png)
A policy-file can be created to allow such interaction. On the `target` domain, a service is invoked which can read the
`stdin` from the `client` qube.
This is how [Split GPG](https://www.qubes-os.org/doc/split-gpg/) is implemented. We can set up Clef the same way:
##### Server
![Clef via qrexec](qubes/clef_qubes_qrexec.png)
On the `target` qubes, we need to define the rpc service.
[qubes.Clefsign](qubes/qubes.Clefsign):
```bash
#!/bin/bash
SIGNER_BIN="/home/user/tools/clef/clef"
SIGNER_CMD="/home/user/tools/gtksigner/gtkui.py -s $SIGNER_BIN"
# Start clef if not already started
if [ ! -S /home/user/.clef/clef.ipc ]; then
$SIGNER_CMD &
sleep 1
fi
# Should be started by now
if [ -S /home/user/.clef/clef.ipc ]; then
# Post incoming request to HTTP channel
curl -H "Content-Type: application/json" -X POST -d @- http://localhost:8550 2>/dev/null
fi
```
This RPC service is not complete (see notes about HTTP headers below), but works as a proof-of-concept.
It will forward the data received on `stdin` (forwarded by the OS) to Clef's HTTP channel.
It would have been possible to send data directly to the `/home/user/.clef/.clef.ipc`
socket via e.g `nc -U /home/user/.clef/clef.ipc`, but the reason for sending the request
data over `HTTP` instead of `IPC` is that we want the ability to forward `HTTP` headers.
To enable the service:
``` bash
sudo cp qubes.Clefsign /etc/qubes-rpc/
sudo chmod +x /etc/qubes-rpc/ qubes.Clefsign
```
This setup uses [gtksigner](https://github.com/holiman/gtksigner), which is a very minimal GTK-based UI that works well
with minimal requirements.
##### Client
On the `client` qube, we need to create a listener which will receive the request from the Dapp, and proxy it.
[qubes-client.py](qubes/client/qubes-client.py):
```python
"""
This implements a dispatcher which listens to localhost:8550, and proxies
requests via qrexec to the service qubes.EthSign on a target domain
"""
import http.server
import socketserver,subprocess
PORT=8550
TARGET_DOMAIN= 'debian-work'
class Dispatcher(http.server.BaseHTTPRequestHandler):
def do_POST(self):
post_data = self.rfile.read(int(self.headers['Content-Length']))
p = subprocess.Popen(['/usr/bin/qrexec-client-vm',TARGET_DOMAIN,'qubes.Clefsign'],stdin=subprocess.PIPE, stdout=subprocess.PIPE)
output = p.communicate(post_data)[0]
self.wfile.write(output)
with socketserver.TCPServer(("",PORT), Dispatcher) as httpd:
print("Serving at port", PORT)
httpd.serve_forever()
```
#### Testing
To test the flow, if we have set up `debian-work` as the `target`, we can do
```bash
$ cat newaccnt.json
{ "id": 0, "jsonrpc": "2.0","method": "account_new","params": []}
$ cat newaccnt.json| qrexec-client-vm debian-work qubes.Clefsign
```
This should pop up first a dialog to allow the IPC call:
![one](qubes/qubes_newaccount-1.png)
Followed by a GTK-dialog to approve the operation
![two](qubes/qubes_newaccount-2.png)
To test the full flow, we use the client wrapper. Start it on the `client` qube:
```
[user@work qubes]$ python3 qubes-client.py
```
Make the request over http (`client` qube):
```
[user@work clef]$ cat newaccnt.json | curl -X POST -d @- http://localhost:8550
```
And it should show the same popups again.
##### Pros and cons
The benefits of this setup are:
- This is the qubes-os intended model for inter-qube communication,
- and thus benefits from qubes-os dialogs and policies for user approval
However, it comes with a couple of drawbacks:
- The `qubes-gpg-client` must forward the http request via RPC to the `target` qube. When doing so, the proxy
will either drop important headers, or replace them.
- The `Host` header is most likely `localhost`
- The `Origin` header must be forwarded
- Information about the remote ip must be added as a `X-Forwarded-For`. However, Clef cannot always trust an `XFF` header,
since malicious clients may lie about `XFF` in order to fool the http server into believing it comes from another address.
- Even with a policy in place to allow rpc-calls between `caller` and `target`, there will be several popups:
- One qubes-specific where the user specifies the `target` vm
- One clef-specific to approve the transaction
#### 2. Network integrated
The second way to set up Clef on a qubes system is to allow networking, and have Clef listen to a port which is accessible
form other qubes.
![Clef via http](qubes/clef_qubes_http.png)
## USBArmory
The [USB armory](https://inversepath.com/usbarmory) is an open source hardware design with an 800 Mhz ARM processor. It is a pocket-size
computer. When inserted into a laptop, it identifies itself as a USB network interface, basically adding another network
to your computer. Over this new network interface, you can SSH into the device.
Running Clef off a USB armory means that you can use the armory as a very versatile offline computer, which only
ever connects to a local network between your computer and the device itself.
Needless to say, the while this model should be fairly secure against remote attacks, an attacker with physical access
to the USB Armory would trivially be able to extract the contents of the device filesystem.

View file

@ -21,12 +21,12 @@ import (
"encoding/json"
"fmt"
"io/ioutil"
"math/big"
"os"
goruntime "runtime"
"runtime/pprof"
"time"
goruntime "runtime"
"github.com/ethereum/go-ethereum/cmd/evm/internal/compiler"
"github.com/ethereum/go-ethereum/cmd/utils"
"github.com/ethereum/go-ethereum/common"
@ -86,6 +86,7 @@ func runCmd(ctx *cli.Context) error {
chainConfig *params.ChainConfig
sender = common.BytesToAddress([]byte("sender"))
receiver = common.BytesToAddress([]byte("receiver"))
blockNumber uint64
)
if ctx.GlobalBool(MachineFlag.Name) {
tracer = NewJSONLogger(logconfig, os.Stdout)
@ -101,6 +102,7 @@ func runCmd(ctx *cli.Context) error {
genesis := gen.ToBlock(db)
statedb, _ = state.New(genesis.Root(), state.NewDatabase(db))
chainConfig = gen.Config
blockNumber = gen.Number
} else {
db, _ := ethdb.NewMemDatabase()
statedb, _ = state.New(common.Hash{}, state.NewDatabase(db))
@ -161,6 +163,7 @@ func runCmd(ctx *cli.Context) error {
GasLimit: initialGas,
GasPrice: utils.GlobalBig(ctx, PriceFlag.Name),
Value: utils.GlobalBig(ctx, ValueFlag.Name),
BlockNumber: new(big.Int).SetUint64(blockNumber),
EVMConfig: vm.Config{
Tracer: tracer,
Debug: ctx.GlobalBool(DebugFlag.Name) || ctx.GlobalBool(MachineFlag.Name),

View file

@ -158,11 +158,11 @@ var (
}
FastSyncFlag = cli.BoolFlag{
Name: "fast",
Usage: "Enable fast syncing through state downloads",
Usage: "Enable fast syncing through state downloads (replaced by --syncmode)",
}
LightModeFlag = cli.BoolFlag{
Name: "light",
Usage: "Enable light client mode",
Usage: "Enable light client mode (replaced by --syncmode)",
}
defaultSyncMode = eth.DefaultConfig.SyncMode
SyncModeFlag = TextMarshalerFlag{

View file

@ -178,9 +178,7 @@ func (self *stateObject) GetState(db Database, key common.Hash) common.Hash {
}
value.SetBytes(content)
}
if (value != common.Hash{}) {
self.cachedStorage[key] = value
}
return value
}
@ -197,7 +195,6 @@ func (self *stateObject) SetState(db Database, key, value common.Hash) {
func (self *stateObject) setState(key, value common.Hash) {
self.cachedStorage[key] = value
self.dirtyStorage[key] = value
}
// updateTrie writes cached storage modifications into the object's storage trie.

View file

@ -572,27 +572,6 @@ func (self *StateDB) Prepare(thash, bhash common.Hash, ti int) {
self.txIndex = ti
}
// DeleteSuicides flags the suicided objects for deletion so that it
// won't be referenced again when called / queried up on.
//
// DeleteSuicides should not be used for consensus related updates
// under any circumstances.
func (s *StateDB) DeleteSuicides() {
// Reset refund so that any used-gas calculations can use this method.
s.clearJournalAndRefund()
for addr := range s.stateObjectsDirty {
stateObject := s.stateObjects[addr]
// If the object has been removed by a suicide
// flag the object as deleted.
if stateObject.suicided {
stateObject.deleted = true
}
delete(s.stateObjectsDirty, addr)
}
}
func (s *StateDB) clearJournalAndRefund() {
s.journal = newJournal()
s.validRevisions = s.validRevisions[:0]

View file

@ -618,7 +618,7 @@ func (pool *TxPool) add(tx *types.Transaction, local bool) (bool, error) {
// If the transaction pool is full, discard underpriced transactions
if uint64(len(pool.all)) >= pool.config.GlobalSlots+pool.config.GlobalQueue {
// If the new transaction is underpriced, don't accept it
if pool.priced.Underpriced(tx, pool.locals) {
if !local && pool.priced.Underpriced(tx, pool.locals) {
log.Trace("Discarding underpriced transaction", "hash", hash, "price", tx.GasPrice())
underpricedTxCounter.Inc(1)
return false, ErrUnderpriced

View file

@ -1346,7 +1346,7 @@ func TestTransactionPoolUnderpricing(t *testing.T) {
defer sub.Unsubscribe()
// Create a number of test accounts and fund them
keys := make([]*ecdsa.PrivateKey, 3)
keys := make([]*ecdsa.PrivateKey, 4)
for i := 0; i < len(keys); i++ {
keys[i], _ = crypto.GenerateKey()
pool.currentState.AddBalance(crypto.PubkeyToAddress(keys[i].PublicKey), big.NewInt(1000000))
@ -1406,18 +1406,22 @@ func TestTransactionPoolUnderpricing(t *testing.T) {
t.Fatalf("pool internal state corrupted: %v", err)
}
// Ensure that adding local transactions can push out even higher priced ones
tx := pricedTransaction(1, 100000, big.NewInt(0), keys[2])
if err := pool.AddLocal(tx); err != nil {
t.Fatalf("failed to add underpriced local transaction: %v", err)
ltx = pricedTransaction(1, 100000, big.NewInt(0), keys[2])
if err := pool.AddLocal(ltx); err != nil {
t.Fatalf("failed to append underpriced local transaction: %v", err)
}
ltx = pricedTransaction(0, 100000, big.NewInt(0), keys[3])
if err := pool.AddLocal(ltx); err != nil {
t.Fatalf("failed to add new underpriced local transaction: %v", err)
}
pending, queued = pool.Stats()
if pending != 2 {
t.Fatalf("pending transactions mismatched: have %d, want %d", pending, 2)
if pending != 3 {
t.Fatalf("pending transactions mismatched: have %d, want %d", pending, 3)
}
if queued != 2 {
t.Fatalf("queued transactions mismatched: have %d, want %d", queued, 2)
if queued != 1 {
t.Fatalf("queued transactions mismatched: have %d, want %d", queued, 1)
}
if err := validateEvents(events, 1); err != nil {
if err := validateEvents(events, 2); err != nil {
t.Fatalf("local event firing failed: %v", err)
}
if err := validateTxPoolInternals(pool); err != nil {

View file

@ -139,15 +139,15 @@ func (c *Contract) Value() *big.Int {
}
// SetCode sets the code to the contract
func (self *Contract) SetCode(hash common.Hash, code []byte) {
self.Code = code
self.CodeHash = hash
func (c *Contract) SetCode(hash common.Hash, code []byte) {
c.Code = code
c.CodeHash = hash
}
// SetCallCode sets the code of the contract and address of the backing data
// object
func (self *Contract) SetCallCode(addr *common.Address, hash common.Hash, code []byte) {
self.Code = code
self.CodeHash = hash
self.CodeAddr = addr
func (c *Contract) SetCallCode(addr *common.Address, hash common.Hash, code []byte) {
c.Code = code
c.CodeHash = hash
c.CodeAddr = addr
}

View file

@ -160,6 +160,11 @@ func (evm *EVM) Call(caller ContractRef, addr common.Address, input []byte, gas
precompiles = PrecompiledContractsByzantium
}
if precompiles[addr] == nil && evm.ChainConfig().IsEIP158(evm.BlockNumber) && value.Sign() == 0 {
// Calling a non existing account, don't do antything, but ping the tracer
if evm.vmConfig.Debug && evm.depth == 0 {
evm.vmConfig.Tracer.CaptureStart(caller.Address(), addr, false, input, gas, value)
evm.vmConfig.Tracer.CaptureEnd(ret, 0, 0, nil)
}
return nil, gas, nil
}
evm.StateDB.CreateAccount(addr)

View file

@ -31,9 +31,9 @@ import (
type Storage map[common.Hash]common.Hash
func (self Storage) Copy() Storage {
func (s Storage) Copy() Storage {
cpy := make(Storage)
for key, value := range self {
for key, value := range s {
cpy[key] = value
}

View file

@ -51,14 +51,14 @@ func (m *Memory) Resize(size uint64) {
}
// Get returns offset + size as a new slice
func (self *Memory) Get(offset, size int64) (cpy []byte) {
func (m *Memory) Get(offset, size int64) (cpy []byte) {
if size == 0 {
return nil
}
if len(self.store) > int(offset) {
if len(m.store) > int(offset) {
cpy = make([]byte, size)
copy(cpy, self.store[offset:offset+size])
copy(cpy, m.store[offset:offset+size])
return
}
@ -67,13 +67,13 @@ func (self *Memory) Get(offset, size int64) (cpy []byte) {
}
// GetPtr returns the offset + size
func (self *Memory) GetPtr(offset, size int64) []byte {
func (m *Memory) GetPtr(offset, size int64) []byte {
if size == 0 {
return nil
}
if len(self.store) > int(offset) {
return self.store[offset : offset+size]
if len(m.store) > int(offset) {
return m.store[offset : offset+size]
}
return nil

View file

@ -375,10 +375,10 @@ var opCodeToString = map[OpCode]string{
SWAP: "SWAP",
}
func (o OpCode) String() string {
str := opCodeToString[o]
func (op OpCode) String() string {
str := opCodeToString[op]
if len(str) == 0 {
return fmt.Sprintf("Missing opcode 0x%x", int(o))
return fmt.Sprintf("Missing opcode 0x%x", int(op))
}
return str

View file

@ -201,7 +201,7 @@ func (api *PrivateDebugAPI) traceChain(ctx context.Context, start, end *types.Bl
log.Warn("Tracing failed", "hash", tx.Hash(), "block", task.block.NumberU64(), "err", err)
break
}
task.statedb.DeleteSuicides()
task.statedb.Finalise(true)
task.results[i] = &txTraceResult{Result: res}
}
// Stream the result back to the user or abort on teardown
@ -640,7 +640,8 @@ func (api *PrivateDebugAPI) computeTxEnv(blockHash common.Hash, txIndex int, ree
if _, _, _, err := core.ApplyMessage(vmenv, msg, new(core.GasPool).AddGas(tx.Gas())); err != nil {
return nil, vm.Context{}, nil, fmt.Errorf("tx %x failed: %v", tx.Hash(), err)
}
statedb.DeleteSuicides()
// Ensure any modifications are committed to the state
statedb.Finalise(true)
}
return nil, vm.Context{}, nil, fmt.Errorf("tx index %d out of range for block %x", txIndex, blockHash)
}

View file

@ -102,8 +102,8 @@ func randomSource() *rand.Rand {
// call the functions of the otto vm directly to circumvent the queue. These
// functions should be used if and only if running a routine that was already
// called from JS through an RPC call.
func (self *JSRE) runEventLoop() {
defer close(self.closed)
func (re *JSRE) runEventLoop() {
defer close(re.closed)
vm := otto.New()
r := randomSource()
@ -202,14 +202,14 @@ loop:
break loop
}
}
case req := <-self.evalQueue:
case req := <-re.evalQueue:
// run the code, send the result back
req.fn(vm)
close(req.done)
if waitForCallbacks && (len(registry) == 0) {
break loop
}
case waitForCallbacks = <-self.stopEventLoop:
case waitForCallbacks = <-re.stopEventLoop:
if !waitForCallbacks || (len(registry) == 0) {
break loop
}
@ -223,31 +223,31 @@ loop:
}
// Do executes the given function on the JS event loop.
func (self *JSRE) Do(fn func(*otto.Otto)) {
func (re *JSRE) Do(fn func(*otto.Otto)) {
done := make(chan bool)
req := &evalReq{fn, done}
self.evalQueue <- req
re.evalQueue <- req
<-done
}
// stops the event loop before exit, optionally waits for all timers to expire
func (self *JSRE) Stop(waitForCallbacks bool) {
func (re *JSRE) Stop(waitForCallbacks bool) {
select {
case <-self.closed:
case self.stopEventLoop <- waitForCallbacks:
<-self.closed
case <-re.closed:
case re.stopEventLoop <- waitForCallbacks:
<-re.closed
}
}
// Exec(file) loads and runs the contents of a file
// if a relative path is given, the jsre's assetPath is used
func (self *JSRE) Exec(file string) error {
code, err := ioutil.ReadFile(common.AbsolutePath(self.assetPath, file))
func (re *JSRE) Exec(file string) error {
code, err := ioutil.ReadFile(common.AbsolutePath(re.assetPath, file))
if err != nil {
return err
}
var script *otto.Script
self.Do(func(vm *otto.Otto) {
re.Do(func(vm *otto.Otto) {
script, err = vm.Compile(file, code)
if err != nil {
return
@ -259,36 +259,36 @@ func (self *JSRE) Exec(file string) error {
// Bind assigns value v to a variable in the JS environment
// This method is deprecated, use Set.
func (self *JSRE) Bind(name string, v interface{}) error {
return self.Set(name, v)
func (re *JSRE) Bind(name string, v interface{}) error {
return re.Set(name, v)
}
// Run runs a piece of JS code.
func (self *JSRE) Run(code string) (v otto.Value, err error) {
self.Do(func(vm *otto.Otto) { v, err = vm.Run(code) })
func (re *JSRE) Run(code string) (v otto.Value, err error) {
re.Do(func(vm *otto.Otto) { v, err = vm.Run(code) })
return v, err
}
// Get returns the value of a variable in the JS environment.
func (self *JSRE) Get(ns string) (v otto.Value, err error) {
self.Do(func(vm *otto.Otto) { v, err = vm.Get(ns) })
func (re *JSRE) Get(ns string) (v otto.Value, err error) {
re.Do(func(vm *otto.Otto) { v, err = vm.Get(ns) })
return v, err
}
// Set assigns value v to a variable in the JS environment.
func (self *JSRE) Set(ns string, v interface{}) (err error) {
self.Do(func(vm *otto.Otto) { err = vm.Set(ns, v) })
func (re *JSRE) Set(ns string, v interface{}) (err error) {
re.Do(func(vm *otto.Otto) { err = vm.Set(ns, v) })
return err
}
// loadScript executes a JS script from inside the currently executing JS code.
func (self *JSRE) loadScript(call otto.FunctionCall) otto.Value {
func (re *JSRE) loadScript(call otto.FunctionCall) otto.Value {
file, err := call.Argument(0).ToString()
if err != nil {
// TODO: throw exception
return otto.FalseValue()
}
file = common.AbsolutePath(self.assetPath, file)
file = common.AbsolutePath(re.assetPath, file)
source, err := ioutil.ReadFile(file)
if err != nil {
// TODO: throw exception
@ -305,10 +305,10 @@ func (self *JSRE) loadScript(call otto.FunctionCall) otto.Value {
// Evaluate executes code and pretty prints the result to the specified output
// stream.
func (self *JSRE) Evaluate(code string, w io.Writer) error {
func (re *JSRE) Evaluate(code string, w io.Writer) error {
var fail error
self.Do(func(vm *otto.Otto) {
re.Do(func(vm *otto.Otto) {
val, err := vm.Run(code)
if err != nil {
prettyError(vm, err, w)
@ -321,8 +321,8 @@ func (self *JSRE) Evaluate(code string, w io.Writer) error {
}
// Compile compiles and then runs a piece of JS code.
func (self *JSRE) Compile(filename string, src interface{}) (err error) {
self.Do(func(vm *otto.Otto) { _, err = compileAndRun(vm, filename, src) })
func (re *JSRE) Compile(filename string, src interface{}) (err error) {
re.Do(func(vm *otto.Otto) { _, err = compileAndRun(vm, filename, src) })
return err
}

View file

@ -562,7 +562,7 @@ type preminedTestnet struct {
dists [hashBits + 1][]NodeID
}
func (net *preminedTestnet) findnode(toid NodeID, toaddr *net.UDPAddr, target NodeID) ([]*Node, error) {
func (tn *preminedTestnet) findnode(toid NodeID, toaddr *net.UDPAddr, target NodeID) ([]*Node, error) {
// current log distance is encoded in port number
// fmt.Println("findnode query at dist", toaddr.Port)
if toaddr.Port == 0 {
@ -570,7 +570,7 @@ func (net *preminedTestnet) findnode(toid NodeID, toaddr *net.UDPAddr, target No
}
next := uint16(toaddr.Port) - 1
var result []*Node
for i, id := range net.dists[toaddr.Port] {
for i, id := range tn.dists[toaddr.Port] {
result = append(result, NewNode(id, net.ParseIP("127.0.0.1"), next, uint16(i)))
}
return result, nil
@ -582,26 +582,26 @@ func (*preminedTestnet) ping(toid NodeID, toaddr *net.UDPAddr) error { return ni
// mine generates a testnet struct literal with nodes at
// various distances to the given target.
func (net *preminedTestnet) mine(target NodeID) {
net.target = target
net.targetSha = crypto.Keccak256Hash(net.target[:])
func (tn *preminedTestnet) mine(target NodeID) {
tn.target = target
tn.targetSha = crypto.Keccak256Hash(tn.target[:])
found := 0
for found < bucketSize*10 {
k := newkey()
id := PubkeyID(&k.PublicKey)
sha := crypto.Keccak256Hash(id[:])
ld := logdist(net.targetSha, sha)
if len(net.dists[ld]) < bucketSize {
net.dists[ld] = append(net.dists[ld], id)
ld := logdist(tn.targetSha, sha)
if len(tn.dists[ld]) < bucketSize {
tn.dists[ld] = append(tn.dists[ld], id)
fmt.Println("found ID with ld", ld)
found++
}
}
fmt.Println("&preminedTestnet{")
fmt.Printf(" target: %#v,\n", net.target)
fmt.Printf(" targetSha: %#v,\n", net.targetSha)
fmt.Printf(" dists: [%d][]NodeID{\n", len(net.dists))
for ld, ns := range net.dists {
fmt.Printf(" target: %#v,\n", tn.target)
fmt.Printf(" targetSha: %#v,\n", tn.targetSha)
fmt.Printf(" dists: [%d][]NodeID{\n", len(tn.dists))
for ld, ns := range tn.dists {
if len(ns) == 0 {
continue
}

View file

@ -265,11 +265,11 @@ type preminedTestnet struct {
net *Network
}
func (net *preminedTestnet) sendFindnode(to *Node, target NodeID) {
func (tn *preminedTestnet) sendFindnode(to *Node, target NodeID) {
panic("sendFindnode called")
}
func (net *preminedTestnet) sendFindnodeHash(to *Node, target common.Hash) {
func (tn *preminedTestnet) sendFindnodeHash(to *Node, target common.Hash) {
// current log distance is encoded in port number
// fmt.Println("findnode query at dist", toaddr.Port)
if to.UDP <= lowPort {
@ -277,21 +277,21 @@ func (net *preminedTestnet) sendFindnodeHash(to *Node, target common.Hash) {
}
next := to.UDP - 1
var result []rpcNode
for i, id := range net.dists[to.UDP-lowPort] {
for i, id := range tn.dists[to.UDP-lowPort] {
result = append(result, nodeToRPC(NewNode(id, net.ParseIP("10.0.2.99"), next, uint16(i)+1+lowPort)))
}
injectResponse(net.net, to, neighborsPacket, &neighbors{Nodes: result})
injectResponse(tn.net, to, neighborsPacket, &neighbors{Nodes: result})
}
func (net *preminedTestnet) sendPing(to *Node, addr *net.UDPAddr, topics []Topic) []byte {
injectResponse(net.net, to, pongPacket, &pong{ReplyTok: []byte{1}})
func (tn *preminedTestnet) sendPing(to *Node, addr *net.UDPAddr, topics []Topic) []byte {
injectResponse(tn.net, to, pongPacket, &pong{ReplyTok: []byte{1}})
return []byte{1}
}
func (net *preminedTestnet) send(to *Node, ptype nodeEvent, data interface{}) (hash []byte) {
func (tn *preminedTestnet) send(to *Node, ptype nodeEvent, data interface{}) (hash []byte) {
switch ptype {
case pingPacket:
injectResponse(net.net, to, pongPacket, &pong{ReplyTok: []byte{1}})
injectResponse(tn.net, to, pongPacket, &pong{ReplyTok: []byte{1}})
case pongPacket:
// ignored
case findnodeHashPacket:
@ -302,29 +302,29 @@ func (net *preminedTestnet) send(to *Node, ptype nodeEvent, data interface{}) (h
}
next := to.UDP - 1
var result []rpcNode
for i, id := range net.dists[to.UDP-lowPort] {
for i, id := range tn.dists[to.UDP-lowPort] {
result = append(result, nodeToRPC(NewNode(id, net.ParseIP("10.0.2.99"), next, uint16(i)+1+lowPort)))
}
injectResponse(net.net, to, neighborsPacket, &neighbors{Nodes: result})
injectResponse(tn.net, to, neighborsPacket, &neighbors{Nodes: result})
default:
panic("send(" + ptype.String() + ")")
}
return []byte{2}
}
func (net *preminedTestnet) sendNeighbours(to *Node, nodes []*Node) {
func (tn *preminedTestnet) sendNeighbours(to *Node, nodes []*Node) {
panic("sendNeighbours called")
}
func (net *preminedTestnet) sendTopicQuery(to *Node, topic Topic) {
func (tn *preminedTestnet) sendTopicQuery(to *Node, topic Topic) {
panic("sendTopicQuery called")
}
func (net *preminedTestnet) sendTopicNodes(to *Node, queryHash common.Hash, nodes []*Node) {
func (tn *preminedTestnet) sendTopicNodes(to *Node, queryHash common.Hash, nodes []*Node) {
panic("sendTopicNodes called")
}
func (net *preminedTestnet) sendTopicRegister(to *Node, topics []Topic, idx int, pong []byte) {
func (tn *preminedTestnet) sendTopicRegister(to *Node, topics []Topic, idx int, pong []byte) {
panic("sendTopicRegister called")
}
@ -336,26 +336,26 @@ func (*preminedTestnet) localAddr() *net.UDPAddr {
// mine generates a testnet struct literal with nodes at
// various distances to the given target.
func (net *preminedTestnet) mine(target NodeID) {
net.target = target
net.targetSha = crypto.Keccak256Hash(net.target[:])
func (tn *preminedTestnet) mine(target NodeID) {
tn.target = target
tn.targetSha = crypto.Keccak256Hash(tn.target[:])
found := 0
for found < bucketSize*10 {
k := newkey()
id := PubkeyID(&k.PublicKey)
sha := crypto.Keccak256Hash(id[:])
ld := logdist(net.targetSha, sha)
if len(net.dists[ld]) < bucketSize {
net.dists[ld] = append(net.dists[ld], id)
ld := logdist(tn.targetSha, sha)
if len(tn.dists[ld]) < bucketSize {
tn.dists[ld] = append(tn.dists[ld], id)
fmt.Println("found ID with ld", ld)
found++
}
}
fmt.Println("&preminedTesnetet{")
fmt.Printf(" target: %#v,\n", net.target)
fmt.Printf(" targetSha: %#v,\n", net.targetSha)
fmt.Printf(" dists: [%d][]NodeID{\n", len(net.dists))
for ld, ns := range net.dists {
fmt.Println("&preminedTestnet{")
fmt.Printf(" target: %#v,\n", tn.target)
fmt.Printf(" targetSha: %#v,\n", tn.targetSha)
fmt.Printf(" dists: [%d][]NodeID{\n", len(tn.dists))
for ld, ns := range tn.dists {
if len(ns) == 0 {
continue
}

View file

@ -266,7 +266,6 @@ func (sn *SimNode) Start(snapshots map[string][]byte) error {
return nil
}
// Stop closes the RPC client and stops the underlying devp2p node
func (sn *SimNode) Stop() error {
sn.lock.Lock()

View file

@ -23,7 +23,7 @@ import (
const (
VersionMajor = 1 // Major version component of the current release
VersionMinor = 8 // Minor version component of the current release
VersionPatch = 7 // Patch version component of the current release
VersionPatch = 8 // Patch version component of the current release
VersionMeta = "unstable" // Version metadata to append to the version string
)

View file

@ -104,7 +104,7 @@ func (t *BlockTest) Run() error {
return err
}
if gblock.Hash() != t.json.Genesis.Hash {
return fmt.Errorf("genesis block hash doesn't match test: computed=%x, test=%x\n", gblock.Hash().Bytes()[:6], t.json.Genesis.Hash[:6])
return fmt.Errorf("genesis block hash doesn't match test: computed=%x, test=%x", gblock.Hash().Bytes()[:6], t.json.Genesis.Hash[:6])
}
if gblock.Root() != t.json.Genesis.StateRoot {
return fmt.Errorf("genesis block state root does not match test: computed=%x, test=%x", gblock.Root().Bytes()[:6], t.json.Genesis.StateRoot[:6])

View file

@ -23,7 +23,7 @@ import (
"github.com/ethereum/go-ethereum/params"
)
// This table defines supported forks and their chain config.
// Forks table defines supported forks and their chain config.
var Forks = map[string]*params.ChainConfig{
"Frontier": {
ChainId: big.NewInt(1),

View file

@ -42,7 +42,7 @@ var (
difficultyTestDir = filepath.Join(baseDir, "BasicTests")
)
func readJson(reader io.Reader, value interface{}) error {
func readJSON(reader io.Reader, value interface{}) error {
data, err := ioutil.ReadAll(reader)
if err != nil {
return fmt.Errorf("error reading JSON file: %v", err)
@ -57,14 +57,14 @@ func readJson(reader io.Reader, value interface{}) error {
return nil
}
func readJsonFile(fn string, value interface{}) error {
func readJSONFile(fn string, value interface{}) error {
file, err := os.Open(fn)
if err != nil {
return err
}
defer file.Close()
err = readJson(file, value)
err = readJSON(file, value)
if err != nil {
return fmt.Errorf("%s in file %s", err.Error(), fn)
}
@ -169,9 +169,8 @@ func (tm *testMatcher) checkFailure(t *testing.T, name string, err error) error
if err != nil {
t.Logf("error: %v", err)
return nil
} else {
return fmt.Errorf("test succeeded unexpectedly")
}
return fmt.Errorf("test succeeded unexpectedly")
}
return err
}
@ -213,7 +212,7 @@ func (tm *testMatcher) runTestFile(t *testing.T, path, name string, runTest inte
// Load the file as map[string]<testType>.
m := makeMapFromTestFunc(runTest)
if err := readJsonFile(path, m.Addr().Interface()); err != nil {
if err := readJSONFile(path, m.Addr().Interface()); err != nil {
t.Fatal(err)
}

View file

@ -72,9 +72,8 @@ func (tt *TransactionTest) Run(config *params.ChainConfig) error {
if err := rlp.DecodeBytes(tt.json.RLP, tx); err != nil {
if tt.json.Transaction == nil {
return nil
} else {
return fmt.Errorf("RLP decoding failed: %v", err)
}
return fmt.Errorf("RLP decoding failed: %v", err)
}
// Check sender derivation.
signer := types.MakeSigner(config, new(big.Int).SetUint64(uint64(tt.json.BlockNumber)))

View file

@ -303,7 +303,7 @@ func (it *nodeIterator) push(state *nodeIteratorState, parentIndex *int, path []
it.path = path
it.stack = append(it.stack, state)
if parentIndex != nil {
*parentIndex += 1
*parentIndex++
}
}
@ -380,7 +380,7 @@ func (it *differenceIterator) Next(bool) bool {
if !it.b.Next(true) {
return false
}
it.count += 1
it.count++
if it.eof {
// a has reached eof, so we just return all elements from b
@ -395,7 +395,7 @@ func (it *differenceIterator) Next(bool) bool {
it.eof = true
return true
}
it.count += 1
it.count++
case 1:
// b is before a
return true
@ -405,12 +405,12 @@ func (it *differenceIterator) Next(bool) bool {
if !it.b.Next(hasHash) {
return false
}
it.count += 1
it.count++
if !it.a.Next(hasHash) {
it.eof = true
return true
}
it.count += 1
it.count++
}
}
}
@ -504,14 +504,14 @@ func (it *unionIterator) Next(descend bool) bool {
skipped := heap.Pop(it.items).(NodeIterator)
// Skip the whole subtree if the nodes have hashes; otherwise just skip this node
if skipped.Next(skipped.Hash() == common.Hash{}) {
it.count += 1
it.count++
// If there are more elements, push the iterator back on the heap
heap.Push(it.items, skipped)
}
}
if least.Next(descend) {
it.count += 1
it.count++
heap.Push(it.items, least)
}

View file

@ -123,17 +123,17 @@ func decodeNode(hash, buf []byte, cachegen uint16) (node, error) {
}
switch c, _ := rlp.CountValues(elems); c {
case 2:
n, err := decodeShort(hash, buf, elems, cachegen)
n, err := decodeShort(hash, elems, cachegen)
return n, wrapError(err, "short")
case 17:
n, err := decodeFull(hash, buf, elems, cachegen)
n, err := decodeFull(hash, elems, cachegen)
return n, wrapError(err, "full")
default:
return nil, fmt.Errorf("invalid number of list elements: %v", c)
}
}
func decodeShort(hash, buf, elems []byte, cachegen uint16) (node, error) {
func decodeShort(hash, elems []byte, cachegen uint16) (node, error) {
kbuf, rest, err := rlp.SplitString(elems)
if err != nil {
return nil, err
@ -155,7 +155,7 @@ func decodeShort(hash, buf, elems []byte, cachegen uint16) (node, error) {
return &shortNode{key, r, flag}, nil
}
func decodeFull(hash, buf, elems []byte, cachegen uint16) (*fullNode, error) {
func decodeFull(hash, elems []byte, cachegen uint16) (*fullNode, error) {
n := &fullNode{flags: nodeFlag{hash: hash, gen: cachegen}}
for i := 0; i < 16; i++ {
cld, rest, err := decodeRef(elems, cachegen)

View file

@ -12,7 +12,11 @@ import (
"sync"
)
const typeShift = 3
const typeShift = 4
// Verify at compile-time that typeShift is large enough to cover all FileType
// values by confirming that 0 == 0.
var _ [0]struct{} = [TypeAll >> typeShift]struct{}{}
type memStorageLock struct {
ms *memStorage
@ -143,7 +147,7 @@ func (ms *memStorage) Remove(fd FileDesc) error {
}
func (ms *memStorage) Rename(oldfd, newfd FileDesc) error {
if FileDescOk(oldfd) || FileDescOk(newfd) {
if !FileDescOk(oldfd) || !FileDescOk(newfd) {
return ErrInvalidFile
}
if oldfd == newfd {

View file

@ -20,7 +20,7 @@ func shorten(str string) string {
return str[:3] + ".." + str[len(str)-3:]
}
var bunits = [...]string{"", "Ki", "Mi", "Gi"}
var bunits = [...]string{"", "Ki", "Mi", "Gi", "Ti"}
func shortenb(bytes int) string {
i := 0

52
vendor/vendor.json vendored
View file

@ -418,76 +418,76 @@
"revisionTime": "2017-07-05T02:17:15Z"
},
{
"checksumSHA1": "3QsnhPTXGytTbW3uDvQLgSo9s9M=",
"checksumSHA1": "k13cCuMJO7+KhR8ZXx5oUqDKGQA=",
"path": "github.com/syndtr/goleveldb/leveldb",
"revision": "169b1b37be738edb2813dab48c97a549bcf99bb5",
"revisionTime": "2018-03-07T11:33:52Z"
"revision": "ae970a0732be3a1f5311da86118d37b9f4bd2a5a",
"revisionTime": "2018-05-02T07:23:49Z"
},
{
"checksumSHA1": "EKIow7XkgNdWvR/982ffIZxKG8Y=",
"path": "github.com/syndtr/goleveldb/leveldb/cache",
"revision": "169b1b37be738edb2813dab48c97a549bcf99bb5",
"revisionTime": "2018-03-07T11:33:52Z"
"revision": "ae970a0732be3a1f5311da86118d37b9f4bd2a5a",
"revisionTime": "2018-05-02T07:23:49Z"
},
{
"checksumSHA1": "5KPgnvCPlR0ysDAqo6jApzRQ3tw=",
"path": "github.com/syndtr/goleveldb/leveldb/comparer",
"revision": "169b1b37be738edb2813dab48c97a549bcf99bb5",
"revisionTime": "2018-03-07T11:33:52Z"
"revision": "ae970a0732be3a1f5311da86118d37b9f4bd2a5a",
"revisionTime": "2018-05-02T07:23:49Z"
},
{
"checksumSHA1": "1DRAxdlWzS4U0xKN/yQ/fdNN7f0=",
"path": "github.com/syndtr/goleveldb/leveldb/errors",
"revision": "169b1b37be738edb2813dab48c97a549bcf99bb5",
"revisionTime": "2018-03-07T11:33:52Z"
"revision": "ae970a0732be3a1f5311da86118d37b9f4bd2a5a",
"revisionTime": "2018-05-02T07:23:49Z"
},
{
"checksumSHA1": "eqKeD6DS7eNCtxVYZEHHRKkyZrw=",
"path": "github.com/syndtr/goleveldb/leveldb/filter",
"revision": "169b1b37be738edb2813dab48c97a549bcf99bb5",
"revisionTime": "2018-03-07T11:33:52Z"
"revision": "ae970a0732be3a1f5311da86118d37b9f4bd2a5a",
"revisionTime": "2018-05-02T07:23:49Z"
},
{
"checksumSHA1": "weSsccMav4BCerDpSLzh3mMxAYo=",
"path": "github.com/syndtr/goleveldb/leveldb/iterator",
"revision": "169b1b37be738edb2813dab48c97a549bcf99bb5",
"revisionTime": "2018-03-07T11:33:52Z"
"revision": "ae970a0732be3a1f5311da86118d37b9f4bd2a5a",
"revisionTime": "2018-05-02T07:23:49Z"
},
{
"checksumSHA1": "gJY7bRpELtO0PJpZXgPQ2BYFJ88=",
"path": "github.com/syndtr/goleveldb/leveldb/journal",
"revision": "169b1b37be738edb2813dab48c97a549bcf99bb5",
"revisionTime": "2018-03-07T11:33:52Z"
"revision": "ae970a0732be3a1f5311da86118d37b9f4bd2a5a",
"revisionTime": "2018-05-02T07:23:49Z"
},
{
"checksumSHA1": "MtYY1b2234y/MlS+djL8tXVAcQs=",
"path": "github.com/syndtr/goleveldb/leveldb/memdb",
"revision": "169b1b37be738edb2813dab48c97a549bcf99bb5",
"revisionTime": "2018-03-07T11:33:52Z"
"revision": "ae970a0732be3a1f5311da86118d37b9f4bd2a5a",
"revisionTime": "2018-05-02T07:23:49Z"
},
{
"checksumSHA1": "UmQeotV+m8/FduKEfLOhjdp18rs=",
"path": "github.com/syndtr/goleveldb/leveldb/opt",
"revision": "169b1b37be738edb2813dab48c97a549bcf99bb5",
"revisionTime": "2018-03-07T11:33:52Z"
"revision": "ae970a0732be3a1f5311da86118d37b9f4bd2a5a",
"revisionTime": "2018-05-02T07:23:49Z"
},
{
"checksumSHA1": "QCSae2ub87f8awH+PKMpd8ZYOtg=",
"checksumSHA1": "7H3fa12T7WoMAeXq1+qG5O7LD0w=",
"path": "github.com/syndtr/goleveldb/leveldb/storage",
"revision": "169b1b37be738edb2813dab48c97a549bcf99bb5",
"revisionTime": "2018-03-07T11:33:52Z"
"revision": "ae970a0732be3a1f5311da86118d37b9f4bd2a5a",
"revisionTime": "2018-05-02T07:23:49Z"
},
{
"checksumSHA1": "gWFPMz8OQeul0t54RM66yMTX49g=",
"path": "github.com/syndtr/goleveldb/leveldb/table",
"revision": "169b1b37be738edb2813dab48c97a549bcf99bb5",
"revisionTime": "2018-03-07T11:33:52Z"
"revision": "ae970a0732be3a1f5311da86118d37b9f4bd2a5a",
"revisionTime": "2018-05-02T07:23:49Z"
},
{
"checksumSHA1": "V/Dh7NV0/fy/5jX1KaAjmGcNbzI=",
"path": "github.com/syndtr/goleveldb/leveldb/util",
"revision": "169b1b37be738edb2813dab48c97a549bcf99bb5",
"revisionTime": "2018-03-07T11:33:52Z"
"revision": "ae970a0732be3a1f5311da86118d37b9f4bd2a5a",
"revisionTime": "2018-05-02T07:23:49Z"
},
{
"checksumSHA1": "TT1rac6kpQp2vz24m5yDGUNQ/QQ=",

View file

@ -67,7 +67,6 @@ func (sc *Client) SetMaxMessageSize(ctx context.Context, size uint32) error {
}
// SetMinimumPoW (experimental) sets the minimal PoW required by this node.
// This experimental function was introduced for the future dynamic adjustment of
// PoW requirement. If the node is overwhelmed with messages, it should raise the
// PoW requirement and notify the peers. The new value should be set relative to
@ -77,7 +76,7 @@ func (sc *Client) SetMinimumPoW(ctx context.Context, pow float64) error {
return sc.c.CallContext(ctx, &ignored, "shh_setMinPoW", pow)
}
// Marks specific peer trusted, which will allow it to send historic (expired) messages.
// MarkTrustedPeer marks specific peer trusted, which will allow it to send historic (expired) messages.
// Note This function is not adding new nodes, the node needs to exists as a peer.
func (sc *Client) MarkTrustedPeer(ctx context.Context, enode string) error {
var ignored bool

View file

@ -89,7 +89,7 @@ func (api *PublicWhisperAPI) SetMaxMessageSize(ctx context.Context, size uint32)
return true, api.w.SetMaxMessageSize(size)
}
// SetMinPow sets the minimum PoW for a message before it is accepted.
// SetMinPoW sets the minimum PoW for a message before it is accepted.
func (api *PublicWhisperAPI) SetMinPoW(ctx context.Context, pow float64) (bool, error) {
return true, api.w.SetMinimumPoW(pow)
}
@ -142,7 +142,7 @@ func (api *PublicWhisperAPI) GetPublicKey(ctx context.Context, id string) (hexut
return crypto.FromECDSAPub(&key.PublicKey), nil
}
// GetPublicKey returns the private key associated with the given key. The key is the hex
// GetPrivateKey returns the private key associated with the given key. The key is the hex
// encoded representation of a key in the form specified in section 4.3.6 of ANSI X9.62.
func (api *PublicWhisperAPI) GetPrivateKey(ctx context.Context, id string) (hexutil.Bytes, error) {
key, err := api.w.GetPrivateKey(id)

View file

@ -15,7 +15,7 @@
// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
/*
Package whisper implements the Whisper protocol (version 5).
Package whisperv5 implements the Whisper protocol (version 5).
Whisper combines aspects of both DHTs and datagram messaging systems (e.g. UDP).
As such it may be likened and compared to both, not dissimilar to the

View file

@ -33,7 +33,7 @@ import (
"github.com/ethereum/go-ethereum/log"
)
// Options specifies the exact way a message should be wrapped into an Envelope.
// MessageParams specifies the exact way a message should be wrapped into an Envelope.
type MessageParams struct {
TTL uint32
Src *ecdsa.PrivateKey
@ -86,7 +86,7 @@ func (msg *ReceivedMessage) isAsymmetricEncryption() bool {
return msg.Dst != nil
}
// NewMessage creates and initializes a non-signed, non-encrypted Whisper message.
// NewSentMessage creates and initializes a non-signed, non-encrypted Whisper message.
func NewSentMessage(params *MessageParams) (*sentMessage, error) {
msg := sentMessage{}
msg.Raw = make([]byte, 1, len(params.Payload)+len(params.Padding)+signatureLength+padSizeLimit)
@ -330,7 +330,7 @@ func (msg *ReceivedMessage) extractPadding(end int) (int, bool) {
return paddingSize, true
}
// Recover retrieves the public key of the message signer.
// SigToPubKey retrieves the public key of the message signer.
func (msg *ReceivedMessage) SigToPubKey() *ecdsa.PublicKey {
defer func() { recover() }() // in case of invalid signature

View file

@ -27,7 +27,7 @@ import (
set "gopkg.in/fatih/set.v0"
)
// peer represents a whisper protocol peer connection.
// Peer represents a whisper protocol peer connection.
type Peer struct {
host *Whisper
peer *p2p.Peer
@ -53,51 +53,51 @@ func newPeer(host *Whisper, remote *p2p.Peer, rw p2p.MsgReadWriter) *Peer {
// start initiates the peer updater, periodically broadcasting the whisper packets
// into the network.
func (p *Peer) start() {
go p.update()
log.Trace("start", "peer", p.ID())
func (peer *Peer) start() {
go peer.update()
log.Trace("start", "peer", peer.ID())
}
// stop terminates the peer updater, stopping message forwarding to it.
func (p *Peer) stop() {
close(p.quit)
log.Trace("stop", "peer", p.ID())
func (peer *Peer) stop() {
close(peer.quit)
log.Trace("stop", "peer", peer.ID())
}
// handshake sends the protocol initiation status message to the remote peer and
// verifies the remote status too.
func (p *Peer) handshake() error {
func (peer *Peer) handshake() error {
// Send the handshake status message asynchronously
errc := make(chan error, 1)
go func() {
errc <- p2p.Send(p.ws, statusCode, ProtocolVersion)
errc <- p2p.Send(peer.ws, statusCode, ProtocolVersion)
}()
// Fetch the remote status packet and verify protocol match
packet, err := p.ws.ReadMsg()
packet, err := peer.ws.ReadMsg()
if err != nil {
return err
}
if packet.Code != statusCode {
return fmt.Errorf("peer [%x] sent packet %x before status packet", p.ID(), packet.Code)
return fmt.Errorf("peer [%x] sent packet %x before status packet", peer.ID(), packet.Code)
}
s := rlp.NewStream(packet.Payload, uint64(packet.Size))
peerVersion, err := s.Uint()
if err != nil {
return fmt.Errorf("peer [%x] sent bad status message: %v", p.ID(), err)
return fmt.Errorf("peer [%x] sent bad status message: %v", peer.ID(), err)
}
if peerVersion != ProtocolVersion {
return fmt.Errorf("peer [%x]: protocol version mismatch %d != %d", p.ID(), peerVersion, ProtocolVersion)
return fmt.Errorf("peer [%x]: protocol version mismatch %d != %d", peer.ID(), peerVersion, ProtocolVersion)
}
// Wait until out own status is consumed too
if err := <-errc; err != nil {
return fmt.Errorf("peer [%x] failed to send status packet: %v", p.ID(), err)
return fmt.Errorf("peer [%x] failed to send status packet: %v", peer.ID(), err)
}
return nil
}
// update executes periodic operations on the peer, including message transmission
// and expiration.
func (p *Peer) update() {
func (peer *Peer) update() {
// Start the tickers for the updates
expire := time.NewTicker(expirationCycle)
transmit := time.NewTicker(transmissionCycle)
@ -106,15 +106,15 @@ func (p *Peer) update() {
for {
select {
case <-expire.C:
p.expire()
peer.expire()
case <-transmit.C:
if err := p.broadcast(); err != nil {
log.Trace("broadcast failed", "reason", err, "peer", p.ID())
if err := peer.broadcast(); err != nil {
log.Trace("broadcast failed", "reason", err, "peer", peer.ID())
return
}
case <-p.quit:
case <-peer.quit:
return
}
}
@ -148,16 +148,16 @@ func (peer *Peer) expire() {
// broadcast iterates over the collection of envelopes and transmits yet unknown
// ones over the network.
func (p *Peer) broadcast() error {
func (peer *Peer) broadcast() error {
var cnt int
envelopes := p.host.Envelopes()
envelopes := peer.host.Envelopes()
for _, envelope := range envelopes {
if !p.marked(envelope) {
err := p2p.Send(p.ws, messagesCode, envelope)
if !peer.marked(envelope) {
err := p2p.Send(peer.ws, messagesCode, envelope)
if err != nil {
return err
} else {
p.mark(envelope)
peer.mark(envelope)
cnt++
}
}
@ -168,7 +168,7 @@ func (p *Peer) broadcast() error {
return nil
}
func (p *Peer) ID() []byte {
id := p.peer.ID()
func (peer *Peer) ID() []byte {
id := peer.peer.ID()
return id[:]
}

View file

@ -32,7 +32,7 @@ import (
"github.com/ethereum/go-ethereum/p2p/nat"
)
var keys []string = []string{
var keys = []string{
"d49dcf37238dc8a7aac57dc61b9fee68f0a97f062968978b9fafa7d1033d03a9",
"73fd6143c48e80ed3c56ea159fe7494a0b6b393a392227b422f4c3e8f1b54f98",
"119dd32adb1daa7a4c7bf77f847fb28730785aa92947edf42fdd997b54de40dc",
@ -84,9 +84,9 @@ type TestNode struct {
var result TestData
var nodes [NumNodes]*TestNode
var sharedKey []byte = []byte("some arbitrary data here")
var sharedKey = []byte("some arbitrary data here")
var sharedTopic TopicType = TopicType{0xF, 0x1, 0x2, 0}
var expectedMessage []byte = []byte("per rectum ad astra")
var expectedMessage = []byte("per rectum ad astra")
// This test does the following:
// 1. creates a chain of whisper nodes,

View file

@ -23,7 +23,7 @@ import (
"github.com/ethereum/go-ethereum/common/hexutil"
)
// Topic represents a cryptographically secure, probabilistic partial
// TopicType represents a cryptographically secure, probabilistic partial
// classifications of a message, determined as the first (left) 4 bytes of the
// SHA3 hash of some arbitrary data given by the original author of the message.
type TopicType [TopicLength]byte

View file

@ -469,18 +469,18 @@ func (w *Whisper) Stop() error {
// HandlePeer is called by the underlying P2P layer when the whisper sub-protocol
// connection is negotiated.
func (wh *Whisper) HandlePeer(peer *p2p.Peer, rw p2p.MsgReadWriter) error {
func (w *Whisper) HandlePeer(peer *p2p.Peer, rw p2p.MsgReadWriter) error {
// Create the new peer and start tracking it
whisperPeer := newPeer(wh, peer, rw)
whisperPeer := newPeer(w, peer, rw)
wh.peerMu.Lock()
wh.peers[whisperPeer] = struct{}{}
wh.peerMu.Unlock()
w.peerMu.Lock()
w.peers[whisperPeer] = struct{}{}
w.peerMu.Unlock()
defer func() {
wh.peerMu.Lock()
delete(wh.peers, whisperPeer)
wh.peerMu.Unlock()
w.peerMu.Lock()
delete(w.peers, whisperPeer)
w.peerMu.Unlock()
}()
// Run the peer handshake and state updates
@ -490,11 +490,11 @@ func (wh *Whisper) HandlePeer(peer *p2p.Peer, rw p2p.MsgReadWriter) error {
whisperPeer.start()
defer whisperPeer.stop()
return wh.runMessageLoop(whisperPeer, rw)
return w.runMessageLoop(whisperPeer, rw)
}
// runMessageLoop reads and processes inbound messages directly to merge into client-global state.
func (wh *Whisper) runMessageLoop(p *Peer, rw p2p.MsgReadWriter) error {
func (w *Whisper) runMessageLoop(p *Peer, rw p2p.MsgReadWriter) error {
for {
// fetch the next packet
packet, err := rw.ReadMsg()
@ -502,7 +502,7 @@ func (wh *Whisper) runMessageLoop(p *Peer, rw p2p.MsgReadWriter) error {
log.Warn("message loop", "peer", p.peer.ID(), "err", err)
return err
}
if packet.Size > wh.MaxMessageSize() {
if packet.Size > w.MaxMessageSize() {
log.Warn("oversized message received", "peer", p.peer.ID())
return errors.New("oversized message received")
}
@ -518,7 +518,7 @@ func (wh *Whisper) runMessageLoop(p *Peer, rw p2p.MsgReadWriter) error {
log.Warn("failed to decode envelope, peer will be disconnected", "peer", p.peer.ID(), "err", err)
return errors.New("invalid envelope")
}
cached, err := wh.add(&envelope)
cached, err := w.add(&envelope)
if err != nil {
log.Warn("bad envelope received, peer will be disconnected", "peer", p.peer.ID(), "err", err)
return errors.New("invalid envelope")
@ -537,17 +537,17 @@ func (wh *Whisper) runMessageLoop(p *Peer, rw p2p.MsgReadWriter) error {
log.Warn("failed to decode direct message, peer will be disconnected", "peer", p.peer.ID(), "err", err)
return errors.New("invalid direct message")
}
wh.postEvent(&envelope, true)
w.postEvent(&envelope, true)
}
case p2pRequestCode:
// Must be processed if mail server is implemented. Otherwise ignore.
if wh.mailServer != nil {
if w.mailServer != nil {
var request Envelope
if err := packet.Decode(&request); err != nil {
log.Warn("failed to decode p2p request message, peer will be disconnected", "peer", p.peer.ID(), "err", err)
return errors.New("invalid p2p request")
}
wh.mailServer.DeliverMail(p, &request)
w.mailServer.DeliverMail(p, &request)
}
default:
// New message types might be implemented in the future versions of Whisper.
@ -561,29 +561,27 @@ func (wh *Whisper) runMessageLoop(p *Peer, rw p2p.MsgReadWriter) error {
// add inserts a new envelope into the message pool to be distributed within the
// whisper network. It also inserts the envelope into the expiration pool at the
// appropriate time-stamp. In case of error, connection should be dropped.
func (wh *Whisper) add(envelope *Envelope) (bool, error) {
func (w *Whisper) add(envelope *Envelope) (bool, error) {
now := uint32(time.Now().Unix())
sent := envelope.Expiry - envelope.TTL
if sent > now {
if sent-SynchAllowance > now {
return false, fmt.Errorf("envelope created in the future [%x]", envelope.Hash())
} else {
}
// recalculate PoW, adjusted for the time difference, plus one second for latency
envelope.calculatePoW(sent - now + 1)
}
}
if envelope.Expiry < now {
if envelope.Expiry+SynchAllowance*2 < now {
return false, fmt.Errorf("very old message")
} else {
}
log.Debug("expired envelope dropped", "hash", envelope.Hash().Hex())
return false, nil // drop envelope without error
}
}
if uint32(envelope.size()) > wh.MaxMessageSize() {
if uint32(envelope.size()) > w.MaxMessageSize() {
return false, fmt.Errorf("huge messages are not allowed [%x]", envelope.Hash())
}
@ -598,36 +596,36 @@ func (wh *Whisper) add(envelope *Envelope) (bool, error) {
return false, fmt.Errorf("wrong size of AESNonce: %d bytes [env: %x]", aesNonceSize, envelope.Hash())
}
if envelope.PoW() < wh.MinPow() {
if envelope.PoW() < w.MinPow() {
log.Debug("envelope with low PoW dropped", "PoW", envelope.PoW(), "hash", envelope.Hash().Hex())
return false, nil // drop envelope without error
}
hash := envelope.Hash()
wh.poolMu.Lock()
_, alreadyCached := wh.envelopes[hash]
w.poolMu.Lock()
_, alreadyCached := w.envelopes[hash]
if !alreadyCached {
wh.envelopes[hash] = envelope
if wh.expirations[envelope.Expiry] == nil {
wh.expirations[envelope.Expiry] = set.NewNonTS()
w.envelopes[hash] = envelope
if w.expirations[envelope.Expiry] == nil {
w.expirations[envelope.Expiry] = set.NewNonTS()
}
if !wh.expirations[envelope.Expiry].Has(hash) {
wh.expirations[envelope.Expiry].Add(hash)
if !w.expirations[envelope.Expiry].Has(hash) {
w.expirations[envelope.Expiry].Add(hash)
}
}
wh.poolMu.Unlock()
w.poolMu.Unlock()
if alreadyCached {
log.Trace("whisper envelope already cached", "hash", envelope.Hash().Hex())
} else {
log.Trace("cached whisper envelope", "hash", envelope.Hash().Hex())
wh.statsMu.Lock()
wh.stats.memoryUsed += envelope.size()
wh.statsMu.Unlock()
wh.postEvent(envelope, false) // notify the local node about the new message
if wh.mailServer != nil {
wh.mailServer.Archive(envelope)
w.statsMu.Lock()
w.stats.memoryUsed += envelope.size()
w.statsMu.Unlock()
w.postEvent(envelope, false) // notify the local node about the new message
if w.mailServer != nil {
w.mailServer.Archive(envelope)
}
}
return true, nil
@ -838,9 +836,8 @@ func deriveKeyMaterial(key []byte, version uint64) (derivedKey []byte, err error
// because it's a once in a session experience
derivedKey := pbkdf2.Key(key, nil, 65356, aesKeyLength, sha256.New)
return derivedKey, nil
} else {
return nil, unknownVersionError(version)
}
return nil, unknownVersionError(version)
}
// GenerateRandomID generates a random string, which is then returned to be used as a key id