aboutsummaryrefslogtreecommitdiffstats
path: root/cmd
diff options
context:
space:
mode:
Diffstat (limited to 'cmd')
-rw-r--r--cmd/bootnode/main.go93
-rw-r--r--cmd/ethereum/flags.go50
-rw-r--r--cmd/ethereum/main.go33
-rw-r--r--cmd/ethtest/main.go4
-rw-r--r--cmd/mist/assets/backButtonDisabled.pngbin0 -> 634 bytes
-rw-r--r--cmd/mist/assets/backButtonDisabled@2x.pngbin0 -> 1458 bytes
-rw-r--r--cmd/mist/assets/backButtonHover.pngbin0 -> 657 bytes
-rw-r--r--cmd/mist/assets/backButtonHover@2x.pngbin0 -> 1517 bytes
-rw-r--r--cmd/mist/assets/browser.pngbin5329 -> 756 bytes
-rw-r--r--cmd/mist/assets/browser@2x.pngbin0 -> 1603 bytes
-rw-r--r--cmd/mist/assets/examples/bomb.html22
-rw-r--r--cmd/mist/assets/examples/coin.html34
-rw-r--r--cmd/mist/assets/examples/coin.js65
-rw-r--r--cmd/mist/assets/examples/info.html8
-rw-r--r--cmd/mist/assets/ext/ethereum.js/dist/ethereum.js2
-rw-r--r--cmd/mist/assets/ext/mist.js37
-rw-r--r--cmd/mist/assets/miner.pngbin2100 -> 0 bytes
-rw-r--r--cmd/mist/assets/mining-icon.pngbin0 -> 1029 bytes
-rw-r--r--cmd/mist/assets/mining-icon@2x.pngbin0 -> 2312 bytes
-rw-r--r--cmd/mist/assets/qml/main.qml304
-rw-r--r--cmd/mist/assets/qml/views/browser.qml229
-rw-r--r--cmd/mist/assets/qml/views/catalog.qml141
-rw-r--r--cmd/mist/assets/qml/views/info.qml12
-rw-r--r--cmd/mist/assets/qml/views/miner.qml23
-rw-r--r--cmd/mist/assets/qml/views/pending_tx.qml9
-rw-r--r--cmd/mist/assets/qml/views/transaction.qml4
-rw-r--r--cmd/mist/assets/qml/views/wallet.qml12
-rw-r--r--cmd/mist/bindings.go9
-rw-r--r--cmd/mist/ext_app.go28
-rw-r--r--cmd/mist/flags.go47
-rw-r--r--cmd/mist/gui.go120
-rw-r--r--cmd/mist/html_container.go14
-rw-r--r--cmd/mist/main.go33
-rw-r--r--cmd/mist/qml_container.go6
-rw-r--r--cmd/mist/ui_lib.go50
-rw-r--r--cmd/peerserver/main.go58
-rw-r--r--cmd/utils/cmd.go12
37 files changed, 800 insertions, 659 deletions
diff --git a/cmd/bootnode/main.go b/cmd/bootnode/main.go
new file mode 100644
index 000000000..dda9f34d4
--- /dev/null
+++ b/cmd/bootnode/main.go
@@ -0,0 +1,93 @@
+/*
+ This file is part of go-ethereum
+
+ go-ethereum is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ go-ethereum is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with go-ethereum. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+// Command bootnode runs a bootstrap node for the Discovery Protocol.
+package main
+
+import (
+ "crypto/ecdsa"
+ "encoding/hex"
+ "flag"
+ "fmt"
+ "io/ioutil"
+ "log"
+ "os"
+
+ "github.com/ethereum/go-ethereum/crypto"
+ "github.com/ethereum/go-ethereum/logger"
+ "github.com/ethereum/go-ethereum/p2p/discover"
+ "github.com/ethereum/go-ethereum/p2p/nat"
+)
+
+func main() {
+ var (
+ listenAddr = flag.String("addr", ":30301", "listen address")
+ genKey = flag.String("genkey", "", "generate a node key and quit")
+ nodeKeyFile = flag.String("nodekey", "", "private key filename")
+ nodeKeyHex = flag.String("nodekeyhex", "", "private key as hex (for testing)")
+ natdesc = flag.String("nat", "none", "port mapping mechanism (any|none|upnp|pmp|extip:<IP>)")
+
+ nodeKey *ecdsa.PrivateKey
+ err error
+ )
+ flag.Parse()
+ logger.AddLogSystem(logger.NewStdLogSystem(os.Stdout, log.LstdFlags, logger.DebugLevel))
+
+ if *genKey != "" {
+ writeKey(*genKey)
+ os.Exit(0)
+ }
+
+ natm, err := nat.Parse(*natdesc)
+ if err != nil {
+ log.Fatalf("-nat: %v", err)
+ }
+ switch {
+ case *nodeKeyFile == "" && *nodeKeyHex == "":
+ log.Fatal("Use -nodekey or -nodekeyhex to specify a private key")
+ case *nodeKeyFile != "" && *nodeKeyHex != "":
+ log.Fatal("Options -nodekey and -nodekeyhex are mutually exclusive")
+ case *nodeKeyFile != "":
+ if nodeKey, err = crypto.LoadECDSA(*nodeKeyFile); err != nil {
+ log.Fatalf("-nodekey: %v", err)
+ }
+ case *nodeKeyHex != "":
+ if nodeKey, err = crypto.HexToECDSA(*nodeKeyHex); err != nil {
+ log.Fatalf("-nodekeyhex: %v", err)
+ }
+ }
+
+ if _, err := discover.ListenUDP(nodeKey, *listenAddr, natm); err != nil {
+ log.Fatal(err)
+ }
+ select {}
+}
+
+func writeKey(target string) {
+ key, err := crypto.GenerateKey()
+ if err != nil {
+ log.Fatal("could not generate key: %v", err)
+ }
+ b := crypto.FromECDSA(key)
+ if target == "-" {
+ fmt.Println(hex.EncodeToString(b))
+ } else {
+ if err := ioutil.WriteFile(target, b, 0600); err != nil {
+ log.Fatal("write error: ", err)
+ }
+ }
+}
diff --git a/cmd/ethereum/flags.go b/cmd/ethereum/flags.go
index af57c6a67..577bee442 100644
--- a/cmd/ethereum/flags.go
+++ b/cmd/ethereum/flags.go
@@ -21,6 +21,7 @@
package main
import (
+ "crypto/ecdsa"
"flag"
"fmt"
"log"
@@ -28,7 +29,9 @@ import (
"os/user"
"path"
+ "github.com/ethereum/go-ethereum/crypto"
"github.com/ethereum/go-ethereum/logger"
+ "github.com/ethereum/go-ethereum/p2p/nat"
"github.com/ethereum/go-ethereum/vm"
)
@@ -42,14 +45,14 @@ var (
StartWebSockets bool
RpcPort int
WsPort int
- NatType string
- PMPGateway string
OutboundPort string
ShowGenesis bool
AddPeer string
MaxPeer int
GenAddr bool
- SeedNode string
+ BootNodes string
+ NodeKey *ecdsa.PrivateKey
+ NAT nat.Interface
SecretFile string
ExportDir string
NonInteractive bool
@@ -58,6 +61,7 @@ var (
ConfigFile string
DebugFile string
LogLevel int
+ LogFormat string
Dump bool
DumpHash string
DumpNumber int
@@ -83,6 +87,7 @@ func defaultDataDir() string {
var defaultConfigFile = path.Join(defaultDataDir(), "conf.ini")
func Init() {
+ // TODO: move common flag processing to cmd/util
flag.Usage = func() {
fmt.Fprintf(os.Stderr, "%s [options] [filename]:\noptions precedence: default < config file < environment variables < command line\n", os.Args[0])
flag.PrintDefaults()
@@ -92,18 +97,12 @@ func Init() {
flag.StringVar(&Identifier, "id", "", "Custom client identifier")
flag.StringVar(&KeyRing, "keyring", "", "identifier for keyring to use")
flag.StringVar(&KeyStore, "keystore", "db", "system to store keyrings: db|file (db)")
- flag.StringVar(&OutboundPort, "port", "30303", "listening port")
- flag.StringVar(&NatType, "nat", "", "NAT support (UPNP|PMP) (none)")
- flag.StringVar(&PMPGateway, "pmp", "", "Gateway IP for PMP")
- flag.IntVar(&MaxPeer, "maxpeer", 30, "maximum desired peers")
+
flag.IntVar(&RpcPort, "rpcport", 8545, "port to start json-rpc server on")
flag.IntVar(&WsPort, "wsport", 40404, "port to start websocket rpc server on")
flag.BoolVar(&StartRpc, "rpc", false, "start rpc server")
flag.BoolVar(&StartWebSockets, "ws", false, "start websocket server")
flag.BoolVar(&NonInteractive, "y", false, "non-interactive mode (say yes to confirmations)")
- flag.StringVar(&SeedNode, "seednode", "poc-8.ethdev.com:30303", "ip:port of seed node to connect to. Set to blank for skip")
- flag.BoolVar(&SHH, "shh", true, "whisper protocol (on)")
- flag.BoolVar(&Dial, "dial", true, "dial out connections (on)")
flag.BoolVar(&GenAddr, "genaddr", false, "create a new priv/pub key")
flag.StringVar(&SecretFile, "import", "", "imports the file given (hex or mnemonic formats)")
flag.StringVar(&ExportDir, "export", "", "exports the session keyring to files in the directory given")
@@ -112,6 +111,7 @@ func Init() {
flag.StringVar(&ConfigFile, "conf", defaultConfigFile, "config file")
flag.StringVar(&DebugFile, "debug", "", "debug file (no debugging if not set)")
flag.IntVar(&LogLevel, "loglevel", int(logger.InfoLevel), "loglevel: 0-5: silent,error,warn,info,debug,debug detail)")
+ flag.StringVar(&LogFormat, "logformat", "std", "logformat: std,raw)")
flag.BoolVar(&DiffTool, "difftool", false, "creates output for diff'ing. Sets LogLevel=0")
flag.StringVar(&DiffType, "diff", "all", "sets the level of diff output [vm, all]. Has no effect if difftool=false")
flag.BoolVar(&ShowGenesis, "genesis", false, "Dump the genesis block")
@@ -125,8 +125,38 @@ func Init() {
flag.BoolVar(&StartJsConsole, "js", false, "launches javascript console")
flag.BoolVar(&PrintVersion, "version", false, "prints version number")
+ // Network stuff
+ var (
+ nodeKeyFile = flag.String("nodekey", "", "network private key file")
+ nodeKeyHex = flag.String("nodekeyhex", "", "network private key (for testing)")
+ natstr = flag.String("nat", "any", "port mapping mechanism (any|none|upnp|pmp|extip:<IP>)")
+ )
+ flag.BoolVar(&Dial, "dial", true, "dial out connections (default on)")
+ //flag.BoolVar(&SHH, "shh", true, "run whisper protocol (default on)")
+ flag.StringVar(&OutboundPort, "port", "30303", "listening port")
+
+ flag.StringVar(&BootNodes, "bootnodes", "", "space-separated node URLs for discovery bootstrap")
+ flag.IntVar(&MaxPeer, "maxpeer", 30, "maximum desired peers")
+
flag.Parse()
+ var err error
+ if NAT, err = nat.Parse(*natstr); err != nil {
+ log.Fatalf("-nat: %v", err)
+ }
+ switch {
+ case *nodeKeyFile != "" && *nodeKeyHex != "":
+ log.Fatal("Options -nodekey and -nodekeyhex are mutually exclusive")
+ case *nodeKeyFile != "":
+ if NodeKey, err = crypto.LoadECDSA(*nodeKeyFile); err != nil {
+ log.Fatalf("-nodekey: %v", err)
+ }
+ case *nodeKeyHex != "":
+ if NodeKey, err = crypto.HexToECDSA(*nodeKeyHex); err != nil {
+ log.Fatalf("-nodekeyhex: %v", err)
+ }
+ }
+
if VmType >= int(vm.MaxVmTy) {
log.Fatal("Invalid VM type ", VmType)
}
diff --git a/cmd/ethereum/main.go b/cmd/ethereum/main.go
index 4b16fb79f..9c840de58 100644
--- a/cmd/ethereum/main.go
+++ b/cmd/ethereum/main.go
@@ -31,12 +31,13 @@ import (
"github.com/ethereum/go-ethereum/eth"
"github.com/ethereum/go-ethereum/ethutil"
"github.com/ethereum/go-ethereum/logger"
+ "github.com/ethereum/go-ethereum/p2p"
"github.com/ethereum/go-ethereum/state"
)
const (
ClientIdentifier = "Ethereum(G)"
- Version = "0.8.2"
+ Version = "0.8.5"
)
var clilogger = logger.NewLogger("CLI")
@@ -61,20 +62,20 @@ func main() {
utils.InitConfig(VmType, ConfigFile, Datadir, "ETH")
ethereum, err := eth.New(&eth.Config{
- Name: ClientIdentifier,
- Version: Version,
- KeyStore: KeyStore,
- DataDir: Datadir,
- LogFile: LogFile,
- LogLevel: LogLevel,
- Identifier: Identifier,
- MaxPeers: MaxPeer,
- Port: OutboundPort,
- NATType: PMPGateway,
- PMPGateway: PMPGateway,
- KeyRing: KeyRing,
- Shh: SHH,
- Dial: Dial,
+ Name: p2p.MakeName(ClientIdentifier, Version),
+ KeyStore: KeyStore,
+ DataDir: Datadir,
+ LogFile: LogFile,
+ LogLevel: LogLevel,
+ LogFormat: LogFormat,
+ MaxPeers: MaxPeer,
+ Port: OutboundPort,
+ NAT: NAT,
+ KeyRing: KeyRing,
+ Shh: true,
+ Dial: Dial,
+ BootNodes: BootNodes,
+ NodeKey: NodeKey,
})
if err != nil {
@@ -134,7 +135,7 @@ func main() {
utils.StartWebSockets(ethereum, WsPort)
}
- utils.StartEthereum(ethereum, SeedNode)
+ utils.StartEthereum(ethereum)
if StartJsConsole {
InitJsConsole(ethereum)
diff --git a/cmd/ethtest/main.go b/cmd/ethtest/main.go
index e1c4806ad..40874616c 100644
--- a/cmd/ethtest/main.go
+++ b/cmd/ethtest/main.go
@@ -51,8 +51,8 @@ func StateObjectFromAccount(db ethutil.Database, addr string, account Account) *
if ethutil.IsHex(account.Code) {
account.Code = account.Code[2:]
}
- obj.Code = ethutil.Hex2Bytes(account.Code)
- obj.Nonce = ethutil.Big(account.Nonce).Uint64()
+ obj.SetCode(ethutil.Hex2Bytes(account.Code))
+ obj.SetNonce(ethutil.Big(account.Nonce).Uint64())
return obj
}
diff --git a/cmd/mist/assets/backButtonDisabled.png b/cmd/mist/assets/backButtonDisabled.png
new file mode 100644
index 000000000..428747870
--- /dev/null
+++ b/cmd/mist/assets/backButtonDisabled.png
Binary files differ
diff --git a/cmd/mist/assets/backButtonDisabled@2x.png b/cmd/mist/assets/backButtonDisabled@2x.png
new file mode 100644
index 000000000..0eaa6daa5
--- /dev/null
+++ b/cmd/mist/assets/backButtonDisabled@2x.png
Binary files differ
diff --git a/cmd/mist/assets/backButtonHover.png b/cmd/mist/assets/backButtonHover.png
new file mode 100644
index 000000000..8c5226f5a
--- /dev/null
+++ b/cmd/mist/assets/backButtonHover.png
Binary files differ
diff --git a/cmd/mist/assets/backButtonHover@2x.png b/cmd/mist/assets/backButtonHover@2x.png
new file mode 100644
index 000000000..406601ebc
--- /dev/null
+++ b/cmd/mist/assets/backButtonHover@2x.png
Binary files differ
diff --git a/cmd/mist/assets/browser.png b/cmd/mist/assets/browser.png
index 7b3b0870c..074c9ae3c 100644
--- a/cmd/mist/assets/browser.png
+++ b/cmd/mist/assets/browser.png
Binary files differ
diff --git a/cmd/mist/assets/browser@2x.png b/cmd/mist/assets/browser@2x.png
new file mode 100644
index 000000000..8ca417608
--- /dev/null
+++ b/cmd/mist/assets/browser@2x.png
Binary files differ
diff --git a/cmd/mist/assets/examples/bomb.html b/cmd/mist/assets/examples/bomb.html
new file mode 100644
index 000000000..62540f9bb
--- /dev/null
+++ b/cmd/mist/assets/examples/bomb.html
@@ -0,0 +1,22 @@
+<html>
+<head>
+<script src="../ext/bignumber.min.js"></script>
+<script src="../ext/ethereum.js/dist/ethereum.js"></script>
+
+<script>
+var web3 = require('web3');
+web3.setProvider(new web3.providers.HttpSyncProvider('http://localhost:8545'));
+var eth = web3.eth;
+
+function bomb() {
+ for (var i = 0; i < 200; i++) {
+ eth.transact({})
+ }
+}
+</script>
+</head>
+
+<body>
+<button onclick="bomb();">BOOM!</button>
+</body>
+</html>
diff --git a/cmd/mist/assets/examples/coin.html b/cmd/mist/assets/examples/coin.html
index 71b359834..18a6811d7 100644
--- a/cmd/mist/assets/examples/coin.html
+++ b/cmd/mist/assets/examples/coin.html
@@ -7,15 +7,16 @@
</head>
<body>
-<h1>JevCoin <code id="address"></code></h1>
+<h1>JevCoin <code id="contract_addr"></code></h1>
<div>
<strong>Balance</strong>
<span id="balance"></strong>
</div>
<div>
- <span class="amount">Amount:</span>
+ <span>Address:</span>
<input type="text" id="address" style="width:200px">
+ <span>Amount:</span>
<input type="text" id="amount" style="width:200px">
<button onclick="transact()">Send</button>
</div>
@@ -58,32 +59,25 @@
}],
"outputs": []
}, {
- "name":"changed",
+ "name":"Changed",
"type":"event",
"inputs": [
- {"name":"to","type":"address","indexed":true},
{"name":"from","type":"address","indexed":true},
+ {"name":"amount","type":"uint256","indexed":true},
],
}];
var address = localStorage.getItem("address");
// deploy if not exist
if (address == null) {
- var code = "0x60056013565b610132806100356000396000f35b620f4240600033600160a060020a0316600052602052604060002081905550560060e060020a6000350480637bb98a681461002b578063d0679d3414610039578063e3d670d71461004d57005b61003361012d565b60006000f35b610047600435602435610062565b60006000f35b61005860043561010b565b8060005260206000f35b80600033600160a060020a0316600052602052604060002054106100855761008a565b610107565b80600033600160a060020a0316600052602052604060002090815403908190555080600083600160a060020a0316600052602052604060002090815401908190555081600160a060020a031633600160a060020a03167f1863989b4bb7c5c3941722099764574df7a459f9f9c6b6cdca35ddc9731792b860006000a35b5050565b6000600082600160a060020a03166000526020526040600020549050919050565b5b60008156";
- address = web3.eth.transact({
- data: code,
- gasPrice: "1000000000000000",
- gas: "10000",
- });
+ var code = "0x60056013565b61014f8061003a6000396000f35b620f42406000600033600160a060020a0316815260200190815260200160002081905550560060e060020a600035048063d0679d3414610020578063e3d670d71461003457005b61002e600435602435610049565b60006000f35b61003f600435610129565b8060005260206000f35b806000600033600160a060020a03168152602001908152602001600020541061007157610076565b610125565b806000600033600160a060020a03168152602001908152602001600020908154039081905550806000600084600160a060020a031681526020019081526020016000209081540190819055508033600160a060020a03167fb52dda022b6c1a1f40905a85f257f689aa5d69d850e49cf939d688fbe5af594660006000a38082600160a060020a03167fb52dda022b6c1a1f40905a85f257f689aa5d69d850e49cf939d688fbe5af594660006000a35b5050565b60006000600083600160a060020a0316815260200190815260200160002054905091905056";
+ address = web3.eth.transact({data: code});
localStorage.setItem("address", address);
}
- document.querySelector("#address").innerHTML = address.toUpperCase();
+ document.querySelector("#contract_addr").innerHTML = address;
var contract = web3.eth.contract(address, desc);
- contract.changed({from: eth.accounts[0]}).changed(function() {
- refresh();
- });
- eth.watch('chain').changed(function() {
+ contract.Changed({from: eth.coinbase}).changed(function() {
refresh();
});
@@ -96,13 +90,12 @@
var storage = eth.storageAt(address);
table.innerHTML = "";
for( var item in storage ) {
- table.innerHTML += "<tr><td>"+item.toUpperCase()+"</td><td>"+web3.toDecimal(storage[item])+"</td></tr>";
+ table.innerHTML += "<tr><td>"+item+"</td><td>"+web3.toDecimal(storage[item])+"</td></tr>";
}
}
function transact() {
var to = document.querySelector("#address").value;
-
if( to.length == 0 ) {
to = "0x4205b06c2cfa0e30359edcab94543266cb6fa1d3";
} else {
@@ -110,13 +103,13 @@
}
var value = parseInt( document.querySelector("#amount").value );
+ console.log("transact: ", to, " => ", value)
contract.send( to, value );
}
refresh();
</script>
-
</html>
<!--
@@ -126,7 +119,7 @@ contract JevCoin {
balances[msg.sender] = 1000000;
}
- event changed(address indexed from, address indexed to);
+ event Changed(address indexed from, uint indexed amount);
function send(address to, uint value)
{
if( balances[msg.sender] < value ) return;
@@ -134,7 +127,8 @@ contract JevCoin {
balances[msg.sender] -= value;
balances[to] += value;
- changed(msg.sender, to);
+ Changed(msg.sender, value);
+ Changed(to, value);
}
function balance(address who) constant returns(uint t)
diff --git a/cmd/mist/assets/examples/coin.js b/cmd/mist/assets/examples/coin.js
new file mode 100644
index 000000000..77daac846
--- /dev/null
+++ b/cmd/mist/assets/examples/coin.js
@@ -0,0 +1,65 @@
+var walletABI = [
+ {
+ "name":"confirm",
+ "type":"function",
+ "constant":false,
+ "inputs":[
+ {"name":"_h","type":"hash256"}
+ ],
+ "outputs":[]
+ },{
+ "name":"execute",
+ "constant":false,
+ "type":"function",
+ "inputs":[
+ {"name":"_to","type":"address"},
+ {"name":"_value","type":"uint256"},
+ {"name":"_data","type":"bytes"}
+ ],
+ "outputs":[
+ {"name":"_r","type":"hash256"}
+ ]
+ },{
+ "name":"kill",
+ "type":"function",
+ "constant":false,
+ "inputs":[
+ {"name":"_to","type":"address"}
+ ],
+ "outputs":[]
+ },{
+ "name":"changeOwner",
+ "type":"function",
+ "constant":false,
+ "inputs":[
+ {"name":"_from","type":"address"},
+ {"name":"_to","type":"address"}
+ ],
+ "outputs":[]
+ },{
+ "name":"CashIn",
+ "type":"event",
+ "inputs":[
+ {"indexed":false,"name":"value","type":"uint256"}
+ ]
+ },{
+ "name":"SingleTransact",
+ "type":"event",
+ "inputs":[
+ {"indexed":true,"name":"out","type":"string32"},
+ {"indexed":false,"name":"owner","type":"address"},
+ {"indexed":false,"name":"value","type":"uint256"},
+ {"indexed":false,"name":"to","type":"address"}
+ ]
+ },{
+ "name":"MultiTransact",
+ "type":"event",
+ "inputs":[
+ {"indexed":true,"name":"out","type":"string32"},
+ {"indexed":false,"name":"owner","type":"address"},
+ {"indexed":false,"name":"operation","type":"hash256"},
+ {"indexed":false,"name":"value","type":"uint256"},
+ {"indexed":false,"name":"to","type":"address"}
+ ]
+ }
+];
diff --git a/cmd/mist/assets/examples/info.html b/cmd/mist/assets/examples/info.html
index daad8c706..2a405c280 100644
--- a/cmd/mist/assets/examples/info.html
+++ b/cmd/mist/assets/examples/info.html
@@ -1,8 +1,8 @@
<!doctype>
<html>
-
<head>
+<meta name="badge" content="10">
<script type="text/javascript" src="../ext/bignumber.min.js"></script>
<script type="text/javascript" src="../ext/ethereum.js/dist/ethereum.js"></script>
</head>
@@ -60,7 +60,7 @@
var web3 = require('web3');
var eth = web3.eth;
- web3.setProvider(new web3.providers.HttpSyncProvider('http://localhost:8080'));
+ web3.setProvider(new web3.providers.HttpSyncProvider('http://localhost:8545'));
document.querySelector("#number").innerHTML = eth.number;
document.querySelector("#coinbase").innerHTML = eth.coinbase
@@ -71,6 +71,10 @@
document.querySelector("#gas_price").innerHTML = eth.gasPrice;
document.querySelector("#mining").innerHTML = eth.mining;
document.querySelector("#listening").innerHTML = eth.listening;
+ eth.watch('chain').changed(function() {
+ document.querySelector("#number").innerHTML = eth.number;
+ });
+
</script>
</html>
diff --git a/cmd/mist/assets/ext/ethereum.js/dist/ethereum.js b/cmd/mist/assets/ext/ethereum.js/dist/ethereum.js
index d0e9d3cb7..83b598b3f 100644
--- a/cmd/mist/assets/ext/ethereum.js/dist/ethereum.js
+++ b/cmd/mist/assets/ext/ethereum.js/dist/ethereum.js
@@ -1417,6 +1417,8 @@ var ethMethods = function () {
var methods = [
{ name: 'balanceAt', call: 'eth_balanceAt' },
+ { name: 'register', call: 'eth_register' },
+ { name: 'unregister', call: 'eth_unregister' },
{ name: 'stateAt', call: 'eth_stateAt' },
{ name: 'storageAt', call: 'eth_storageAt' },
{ name: 'countAt', call: 'eth_countAt'},
diff --git a/cmd/mist/assets/ext/mist.js b/cmd/mist/assets/ext/mist.js
new file mode 100644
index 000000000..2fc38cdfa
--- /dev/null
+++ b/cmd/mist/assets/ext/mist.js
@@ -0,0 +1,37 @@
+// Copyright (c) 2015, ETHDEV. All rights reserved.
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public
+// License as published by the Free Software Foundation; either
+// version 2.1 of the License, or (at your option) any later version.
+//
+// This 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
+// General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this library; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+// MA 02110-1301 USA
+
+// this function is included locally, but you can also include separately via a header definition
+
+console.log("loaded?");
+
+document.onkeydown = function(evt) {
+ // This functions keeps track of keyboard inputs in order to allow copy, paste and other features
+
+ evt = evt || window.event;
+ if (evt.ctrlKey && evt.keyCode == 67) {
+ window.document.execCommand("copy");
+ } else if (evt.ctrlKey && evt.keyCode == 88) {
+ window.document.execCommand("cut");
+ } else if (evt.ctrlKey && evt.keyCode == 86) {
+ window.document.execCommand("paste");
+ } else if (evt.ctrlKey && evt.keyCode == 90) {
+ window.document.execCommand("undo");
+ } else if (evt.ctrlKey && evt.shiftKey && evt.keyCode == 90) {
+ window.document.execCommand("redo");
+ }
+}; \ No newline at end of file
diff --git a/cmd/mist/assets/miner.png b/cmd/mist/assets/miner.png
deleted file mode 100644
index 58e3f4dfe..000000000
--- a/cmd/mist/assets/miner.png
+++ /dev/null
Binary files differ
diff --git a/cmd/mist/assets/mining-icon.png b/cmd/mist/assets/mining-icon.png
new file mode 100644
index 000000000..db611e5c0
--- /dev/null
+++ b/cmd/mist/assets/mining-icon.png
Binary files differ
diff --git a/cmd/mist/assets/mining-icon@2x.png b/cmd/mist/assets/mining-icon@2x.png
new file mode 100644
index 000000000..16466d338
--- /dev/null
+++ b/cmd/mist/assets/mining-icon@2x.png
Binary files differ
diff --git a/cmd/mist/assets/qml/main.qml b/cmd/mist/assets/qml/main.qml
index e169f54ec..e80bd87e0 100644
--- a/cmd/mist/assets/qml/main.qml
+++ b/cmd/mist/assets/qml/main.qml
@@ -17,6 +17,7 @@ ApplicationWindow {
// Use this to make the window frameless. But then you'll need to do move and resize by hand
property var ethx : Eth.ethx
+ property var catalog;
width: 1200
height: 820
@@ -39,19 +40,22 @@ ApplicationWindow {
// Takes care of loading all default plugins
Component.onCompleted: {
- addPlugin("./views/catalog.qml", {noAdd: true, close: false, section: "begin"});
- var wallet = addPlugin("./views/wallet.qml", {noAdd: true, close: false, section: "ethereum", active: true});
+ catalog = addPlugin("./views/catalog.qml", {noAdd: true, close: false, section: "begin", active: true});
- addPlugin("./views/miner.qml", {noAdd: true, close: false, section: "ethereum", active: true});
+ var walletWeb = addPlugin("./views/browser.qml", {noAdd: true, close: false, section: "ethereum", active: false});
+ walletWeb.view.url = "http://ethereum-dapp-wallet.meteor.com/";
+ walletWeb.menuItem.title = "Wallet";
+
+ addPlugin("./views/miner.qml", {noAdd: true, close: false, section: "ethereum", active: false});
addPlugin("./views/transaction.qml", {noAdd: true, close: false, section: "legacy"});
addPlugin("./views/whisper.qml", {noAdd: true, close: false, section: "legacy"});
addPlugin("./views/chain.qml", {noAdd: true, close: false, section: "legacy"});
addPlugin("./views/pending_tx.qml", {noAdd: true, close: false, section: "legacy"});
addPlugin("./views/info.qml", {noAdd: true, close: false, section: "legacy"});
- mainSplit.setView(wallet.view, wallet.menuItem);
+ mainSplit.setView(catalog.view, catalog.menuItem);
- newBrowserTab("http://ethereum-dapp-whisper-client.meteor.com/chat/amsteam");
+ //newBrowserTab("http://ethereum-dapp-catalog.meteor.com");
// Command setup
gui.sendCommand(0)
@@ -59,13 +63,14 @@ ApplicationWindow {
function activeView(view, menuItem) {
mainSplit.setView(view, menuItem)
- if (view.hideUrl) {
+ /*if (view.hideUrl) {
urlPane.visible = false;
mainView.anchors.top = rootView.top
} else {
urlPane.visible = true;
mainView.anchors.top = divider.bottom
- }
+ }*/
+
}
function addViews(view, path, options) {
@@ -114,10 +119,34 @@ ApplicationWindow {
}
function newBrowserTab(url) {
- var window = addPlugin("./views/browser.qml", {noAdd: true, close: true, section: "apps", active: true});
- window.view.url = url;
- window.menuItem.title = "Mist";
- activeView(window.view, window.menuItem);
+
+ var urlMatches = url.toString().match(/^[a-z]*\:\/\/([^\/?#]+)(?:[\/?#]|$)/i);
+ var requestedDomain = urlMatches && urlMatches[1];
+
+ var domainAlreadyOpen = false;
+
+ for(var i = 0; i < mainSplit.views.length; i++) {
+ if (mainSplit.views[i].view.url) {
+ var matches = mainSplit.views[i].view.url.toString().match(/^[a-z]*\:\/\/(?:www\.)?([^\/?#]+)(?:[\/?#]|$)/i);
+ var existingDomain = matches && matches[1];
+ if (requestedDomain == existingDomain) {
+ domainAlreadyOpen = true;
+
+ if (mainSplit.views[i].view.url != url){
+ mainSplit.views[i].view.url = url;
+ }
+
+ activeView(mainSplit.views[i].view, mainSplit.views[i].menuItem);
+ }
+ }
+ }
+
+ if (!domainAlreadyOpen) {
+ var window = addPlugin("./views/browser.qml", {noAdd: true, close: true, section: "apps", active: true});
+ window.view.url = url;
+ window.menuItem.title = "Mist";
+ activeView(window.view, window.menuItem);
+ }
}
@@ -126,27 +155,10 @@ ApplicationWindow {
Menu {
title: "File"
MenuItem {
- text: "Import App"
- shortcut: "Ctrl+o"
- onTriggered: {
- generalFileDialog.show(true, importApp)
- }
- }
-
- MenuItem {
- text: "Add plugin"
- onTriggered: {
- generalFileDialog.show(true, function(path) {
- addPlugin(path, {close: true, section: "apps"})
- })
- }
- }
-
- MenuItem {
text: "New tab"
shortcut: "Ctrl+t"
onTriggered: {
- newBrowserTab("http://etherian.io");
+ activeView(catalog.view, catalog.menuItem);
}
}
@@ -239,90 +251,8 @@ ApplicationWindow {
}
}
- Menu {
- title: "GLOBAL SHORTCUTS"
- visible: false
- MenuItem {
- visible: false
- shortcut: "Ctrl+l"
- onTriggered: {
- url.focus = true
- }
- }
- }
- }
-
- statusBar: StatusBar {
- //height: 32
- visible: false
-
- id: statusBar
- Label {
- //y: 6
- id: walletValueLabel
-
- font.pixelSize: 10
- styleColor: "#797979"
- }
-
- Label {
- //y: 6
- objectName: "miningLabel"
- visible: true
- font.pixelSize: 10
- anchors.right: lastBlockLabel.left
- anchors.rightMargin: 5
- }
-
- Label {
- id: lastBlockLabel
- objectName: "lastBlockLabel"
- visible: true
- text: "---"
- font.pixelSize: 10
- anchors.right: peerGroup.left
- anchors.rightMargin: 5
- }
-
- ProgressBar {
- visible: false
- id: downloadIndicator
- value: 0
- objectName: "downloadIndicator"
- y: -4
- x: statusBar.width / 2 - this.width / 2
- width: 160
- }
-
- Label {
- visible: false
- objectName: "downloadLabel"
- //y: 7
- anchors.left: downloadIndicator.right
- anchors.leftMargin: 5
- font.pixelSize: 10
- text: "0 / 0"
- }
-
-
- RowLayout {
- id: peerGroup
- //y: 7
- anchors.right: parent.right
- MouseArea {
- onDoubleClicked: peerWindow.visible = true
- anchors.fill: parent
- }
-
- Label {
- id: peerLabel
- font.pixelSize: 10
- text: "0 / 0"
- }
- }
}
-
property var blockModel: ListModel {
id: blockModel
}
@@ -332,8 +262,9 @@ ApplicationWindow {
id: mainSplit
anchors.fill: parent
- resizing: false
+ //resizing: false // this is NOT where we remove that damning resizing handle..
handleDelegate: Item {
+ //This handle is a way to remove the line between the split views
Rectangle {
anchors.fill: parent
}
@@ -447,10 +378,14 @@ ApplicationWindow {
property var view;
property var path;
property var closable;
+ property var badgeContent;
property alias title: label.text
property alias icon: icon.source
property alias secondaryTitle: secondary.text
+ property alias badgeNumber: badgeNumberLabel.text
+ property alias badgeIcon: badgeIconLabel.text
+
function setSelection(on) {
sel.visible = on
@@ -464,7 +399,7 @@ ApplicationWindow {
label.visible = !on
buttonLabel.visible = on
}
-
+
width: 192
height: 55
color: "#00000000"
@@ -497,7 +432,7 @@ ApplicationWindow {
anchors.fill: parent
border.width: 0
radius: 5
- color: "#FFFFFFFF"
+ color: "#FAFAFA"
}
Rectangle {
anchors {
@@ -506,7 +441,7 @@ ApplicationWindow {
right: r.right
}
width: 10
- color: "#FFFFFFFF"
+ color: "#FAFAFA"
border.width:0
Rectangle {
@@ -517,7 +452,7 @@ ApplicationWindow {
top: parent.top
}
height: 1
- color: "#FFFFFF"
+ color: "#FAFAFA"
}
Rectangle {
@@ -528,7 +463,7 @@ ApplicationWindow {
bottom: parent.bottom
}
height: 1
- color: "#FFFFFF"
+ color: "#FAFAFA"
}
}
}
@@ -543,7 +478,6 @@ ApplicationWindow {
if (parent.closable == true) {
closeIcon.visible = sel.visible
}
-
}
onExited: {
closeIcon.visible = false
@@ -552,8 +486,8 @@ ApplicationWindow {
Image {
id: icon
- height: 24
- width: 24
+ height: 28
+ width: 28
anchors {
left: parent.left
verticalCenter: parent.verticalCenter
@@ -576,18 +510,24 @@ ApplicationWindow {
id: label
font.family: sourceSansPro.name
font.weight: Font.DemiBold
+ elide: Text.ElideRight
+ x:250
+ color: "#665F5F"
+ font.pixelSize: 14
anchors {
left: icon.right
+ right: parent.right
verticalCenter: parent.verticalCenter
leftMargin: 6
- // verticalCenterOffset: -10
+ rightMargin: 8
+ verticalCenterOffset: (secondaryTitle == "") ? 0 : -10;
}
- x:250
- color: "#665F5F"
- font.pixelSize: 14
- }
+
+
+ }
+
Text {
id: secondary
font.family: sourceSansPro.name
@@ -606,7 +546,7 @@ ApplicationWindow {
visible: false
width: 10
height: 10
- color: "#FFFFFF"
+ color: "#FAFAFA"
anchors {
fill: icon
}
@@ -625,9 +565,49 @@ ApplicationWindow {
centerIn: parent
}
color: "#665F5F"
- font.pixelSize: 18
+ font.pixelSize: 20
text: "\ue082"
}
+ }
+
+ Rectangle {
+ id: badge
+ visible: (badgeContent == "icon" || badgeContent == "number" )? true : false
+ width: 32
+ color: "#05000000"
+ anchors {
+ right: parent.right;
+ top: parent.top;
+ bottom: parent.bottom;
+ rightMargin: 4;
+ }
+
+ Text {
+ id: badgeIconLabel
+ visible: (badgeContent == "icon") ? true : false;
+ font.family: simpleLineIcons.name
+ anchors {
+ centerIn: parent
+ }
+ horizontalAlignment: Text.AlignCenter
+ color: "#AAA0A0"
+ font.pixelSize: 20
+ text: badgeIcon
+ }
+
+ Text {
+ id: badgeNumberLabel
+ visible: (badgeContent == "number") ? true : false;
+ anchors {
+ centerIn: parent
+ }
+ horizontalAlignment: Text.AlignCenter
+ font.family: sourceSansPro.name
+ font.weight: Font.Light
+ color: "#AAA0A0"
+ font.pixelSize: 18
+ text: badgeNumber
+ }
}
@@ -800,7 +780,7 @@ ApplicationWindow {
anchors.top: parent.top
color: "#00000000"
- Rectangle {
+ /*Rectangle {
id: urlPane
height: 40
color: "#00000000"
@@ -847,7 +827,7 @@ ApplicationWindow {
z: -1
height: 1
color: "#CCCCCC"
- }
+ }*/
Rectangle {
id: mainView
@@ -855,7 +835,7 @@ ApplicationWindow {
anchors.right: parent.right
anchors.left: parent.left
anchors.bottom: parent.bottom
- anchors.top: divider.bottom
+ anchors.top: parent.top
function createView(component) {
var view = component.createObject(mainView)
@@ -899,9 +879,8 @@ ApplicationWindow {
}
}
-
function setWalletValue(value) {
- walletValueLabel.text = value
+ //walletValueLabel.text = value
}
function loadPlugin(name) {
@@ -909,17 +888,11 @@ ApplicationWindow {
var view = mainView.addPlugin(name)
}
- function setPeers(text) {
- peerLabel.text = text
- }
-
- function addPeer(peer) {
- // We could just append the whole peer object but it cries if you try to alter them
- peerModel.append({ip: peer.ip, port: peer.port, lastResponse:timeAgo(peer.lastSend), latency: peer.latency, version: peer.version, caps: peer.caps})
- }
+ function clearPeers() { peerModel.clear() }
+ function addPeer(peer) { peerModel.append(peer) }
- function resetPeers(){
- peerModel.clear()
+ function setPeerCounters(text) {
+ //peerCounterLabel.text = text
}
function timeAgo(unixTs){
@@ -957,9 +930,10 @@ ApplicationWindow {
anchors.fill: parent
id: peerTable
model: peerModel
- TableViewColumn{width: 200; role: "ip" ; title: "IP" }
- TableViewColumn{width: 260; role: "version" ; title: "Version" }
- TableViewColumn{width: 180; role: "caps" ; title: "Capabilities" }
+ TableViewColumn{width: 180; role: "addr" ; title: "Remote Address" }
+ TableViewColumn{width: 280; role: "nodeID" ; title: "Node ID" }
+ TableViewColumn{width: 100; role: "name" ; title: "Name" }
+ TableViewColumn{width: 40; role: "caps" ; title: "Capabilities" }
}
}
}
@@ -990,7 +964,7 @@ ApplicationWindow {
anchors.top: parent.top
anchors.topMargin: 30
font.pointSize: 12
- text: "<h2>Mist (0.7.10)</h2><br><h3>Development</h3>Jeffrey Wilcke<br>Viktor Trón<br>Felix Lange<br>Taylor Gerring<br>Daniel Nagy<br><h3>UX</h3>Alex van de Sande<br>"
+ text: "<h2>Mist (0.8.5)</h2><br><h3>Development</h3>Jeffrey Wilcke<br>Viktor Trón<br>Felix Lange<br>Taylor Gerring<br>Daniel Nagy<br>Gustav Simonsson<br><h3>UX/UI</h3>Alex van de Sande<br>Fabian Vogelsteller"
}
}
@@ -1027,37 +1001,25 @@ ApplicationWindow {
Window {
id: addPeerWin
visible: false
- minimumWidth: 300
- maximumWidth: 300
+ minimumWidth: 400
+ maximumWidth: 400
maximumHeight: 50
minimumHeight: 50
title: "Connect to peer"
- ComboBox {
+ TextField {
id: addrField
anchors.verticalCenter: parent.verticalCenter
anchors.left: parent.left
anchors.right: addPeerButton.left
anchors.leftMargin: 10
anchors.rightMargin: 10
+ placeholderText: "enode://<hex node id>:<IP address>:<port>"
onAccepted: {
- eth.connectToPeer(addrField.currentText)
- addPeerWin.visible = false
- }
-
- editable: true
- model: ListModel { id: pastPeers }
-
- Component.onCompleted: {
- pastPeers.insert(0, {text: "poc-8.ethdev.com:30303"})
- /*
- var ips = eth.pastPeers()
- for(var i = 0; i < ips.length; i++) {
- pastPeers.append({text: ips.get(i)})
- }
-
- pastPeers.insert(0, {text: "poc-7.ethdev.com:30303"})
- */
+ if(addrField.text.length != 0) {
+ eth.connectToPeer(addrField.text)
+ addPeerWin.visible = false
+ }
}
}
@@ -1066,14 +1028,16 @@ ApplicationWindow {
anchors.right: parent.right
anchors.verticalCenter: parent.verticalCenter
anchors.rightMargin: 10
- text: "Add"
+ text: "Connect"
onClicked: {
- eth.connectToPeer(addrField.currentText)
- addPeerWin.visible = false
+ if(addrField.text.length != 0) {
+ eth.connectToPeer(addrField.text)
+ addPeerWin.visible = false
+ }
}
}
Component.onCompleted: {
addrField.focus = true
}
}
- } \ No newline at end of file
+ }
diff --git a/cmd/mist/assets/qml/views/browser.qml b/cmd/mist/assets/qml/views/browser.qml
index db89c6837..edecc8696 100644
--- a/cmd/mist/assets/qml/views/browser.qml
+++ b/cmd/mist/assets/qml/views/browser.qml
@@ -3,7 +3,7 @@ import QtQuick.Controls 1.0;
import QtQuick.Controls.Styles 1.0
import QtQuick.Layouts 1.0;
import QtWebEngine 1.0
-//import QtWebEngine.experimental 1.0
+import QtWebEngine.experimental 1.0
import QtQuick.Window 2.0;
Rectangle {
@@ -64,23 +64,15 @@ Rectangle {
}
function showFullUrlBar(on){
- if (on) {
- //appTitle.visible = false
- //appDomain.visible = false
-
- //uriNav.visible = true
- clickAnywhereOnApp.visible = true
-
- navBar.state = "fullUrlVisible"
- } else {
- //appTitle.visible = true
- //appDomain.visible = true
- //uriNav.visible = false
- clickAnywhereOnApp.visible = false
-
- navBar.state = "titleVisible"
-
- }
+ if (uriNav.focus == false ) {
+ if (on == false) {
+ clickAnywhereOnApp.visible = false
+ navBar.state = "titleVisible"
+ } else {
+ clickAnywhereOnApp.visible = true
+ navBar.state = "fullUrlVisible"
+ }
+ }
}
@@ -90,24 +82,40 @@ Rectangle {
Item {
objectName: "root"
id: root
- anchors.fill: parent
+ anchors {
+ fill: parent
+ }
+
state: "inspectorShown"
MouseArea {
id: clickAnywhereOnApp
z:15
- //hoverEnabled: true
- anchors.fill: parent
- /*hoverEnabled: true*/
+ // Using a secondary screen to catch on mouse exits for the area, because
+ // there are many hover actions conflicting
+
+ anchors {
+ top: parent.top
+ topMargin: 50
+ right: parent.right
+ bottom: parent.bottom
+ left: parent.left
+ }
+ hoverEnabled: true
- onClicked: {
+ onEntered: {
showFullUrlBar(false);
}
- /*Rectangle {
- anchors.fill: parent
- color: "#88888888"
- }*/
+ onClicked: {
+ uriNav.focus = false
+ showFullUrlBar(false);
+ }
+
+ // Rectangle {
+ // anchors.fill: parent
+ // color: "#88888888"
+ // }
}
RowLayout {
@@ -121,40 +129,44 @@ Rectangle {
Button {
id: back
-
- onClicked: {
- webview.goBack()
+ z: 30
+ onClicked: {
+ webview.goBack()
}
- anchors{
+ anchors {
left: parent.left
leftMargin: 6
}
style: ButtonStyle {
- background: Image {
- source: "../../backButton.png"
- width: 20
- height: 30
- }
+ background: Image {
+ source: (webview.canGoBack) ?
+ (control.hovered ? "../../backButtonHover.png" : "../../backButton.png") :
+ "../../backButtonDisabled.png"
+ width: 20
+ height: 30
+ }
}
}
Rectangle {
- id: appInfoPane
- height: 28
- color: "#FFFFFF"
- radius: 6
-
-
- MouseArea {
+ id: appInfoPane
+ height: 28
+ color: "#FFFFFF"
+ radius: 6
+ z:2
+ MouseArea {
anchors.fill: parent
z: 10
hoverEnabled: true
onEntered: {
- showFullUrlBar(true);
- }
+ showFullUrlBar(true);
+ }
+ /*onExited: {
+ showFullUrlBar(false);
+ }*/
}
@@ -171,14 +183,15 @@ Rectangle {
font.bold: true
font.capitalization: Font.AllUppercase
horizontalAlignment: Text.AlignRight
- verticalAlignment: Text.AlignVCenter
-
+ verticalAlignment: Text.AlignVCenter
+ elide: Text.ElideRight
+
anchors {
left: parent.left
right: parent.horizontalCenter
top: parent.top
bottom: parent.bottom
- rightMargin: 10
+ leftMargin: 32
}
color: "#928484"
}
@@ -189,13 +202,15 @@ Rectangle {
font.bold: false
horizontalAlignment: Text.AlignLeft
verticalAlignment: Text.AlignVCenter
+ elide: Text.ElideLeft
anchors {
left: parent.horizontalCenter
right: parent.right
top: parent.top
bottom: parent.bottom
- leftMargin: 10
+ leftMargin: 32
+
}
color: "#C0AFAF"
}
@@ -212,7 +227,7 @@ Rectangle {
}
horizontalAlignment: Text.AlignHCenter
-
+
style: TextFieldStyle {
textColor: "#928484"
background: Rectangle {
@@ -225,16 +240,16 @@ Rectangle {
z: 20
activeFocusOnPress: true
Keys.onReturnPressed: {
- webview.url = this.text;
+ // if there's no http, add it.
+ var url = this.text,
+ matches = url.match(/^([a-z]*\:\/\/)?([^\/.]+)(:?\/)(.*|$)/i),
+ requestedProtocol = (matches && matches[1] != "undefined")? "" : "http://";
+
+ webview.url = requestedProtocol + url;
}
- /* onFocusedChanged: {
- if (focused) {
- //uriNav.selectAll();
- }
- }*/
}
- z:2
+
}
Rectangle {
@@ -243,6 +258,7 @@ Rectangle {
height: 30
color: "#BDB6B6"
radius: 6
+ z:1
anchors {
left: back.right
@@ -251,19 +267,17 @@ Rectangle {
rightMargin:10
top: parent.top
topMargin: 23
- }
-
- z:1
+ }
}
Rectangle {
id: navBarBackground
anchors.fill: parent
+ z:-1
gradient: Gradient {
GradientStop { position: 0.0; color: "#F6F1F2" }
GradientStop { position: 1.0; color: "#DED5D5" }
}
- z:-1
}
states: [
@@ -326,6 +340,8 @@ Rectangle {
WebEngineView {
objectName: "webView"
id: webview
+ experimental.settings.javascriptCanAccessClipboard: true
+ //experimental.settings.localContentCanAccessRemoteUrls: true
anchors {
left: parent.left
right: parent.right
@@ -333,17 +349,79 @@ Rectangle {
top: navBar.bottom
}
z: 10
+
+ Timer {
+ interval: 2000; running: true; repeat: true
+ onTriggered: {
+ webview.runJavaScript("try{document.querySelector('meta[name=ethereum-dapp-info]').getAttribute('content')}catch(e){}", function(extraInfo) {
+ if (extraInfo) {
+ menuItem.secondaryTitle = extraInfo;
+ }
+ });
+ webview.runJavaScript("try{document.querySelector('meta[name=ethereum-dapp-badge]').getAttribute('content')}catch(e){}", function(badge) {
+ if (badge) {
+ if (Number(badge)>0 && Number(badge)<999) {
+ menuItem.badgeNumber = Number(badge);
+ menuItem.badgeContent = "number"
+ } else if (badge == "warning") {
+ menuItem.badgeIcon = "\ue00e"
+ menuItem.badgeContent = "icon"
+
+ } else if (badge == "ghost") {
+ menuItem.badgeIcon = "\ue01a"
+ menuItem.badgeContent = "icon"
+
+ } else if (badge == "question") {
+ menuItem.badgeIcon = "\ue05d"
+ menuItem.badgeContent = "icon"
+
+ } else if (badge == "info") {
+ menuItem.badgeIcon = "\ue08b"
+ menuItem.badgeContent = "icon"
+
+ } else if (badge == "check") {
+ menuItem.badgeIcon = "\ue080"
+ menuItem.badgeContent = "icon"
+
+ } else if (badge == "gear") {
+ menuItem.badgeIcon = "\ue09a"
+ menuItem.badgeContent = "icon"
+
+ } else {
+ menuItem.badgeContent = ""
+ }
+ } else {
+ menuItem.badgeContent = ""
+ }
+ });
+ }
+ }
onLoadingChanged: {
if (loadRequest.status == WebEngineView.LoadSucceededStatus) {
- webview.runJavaScript("document.title", function(pageTitle) {
+
+ webview.runJavaScript("document.title", function(pageTitle) {
menuItem.title = pageTitle;
});
- //var topBarStyle
- webView.runJavaScript("document.querySelector(\"meta[name='ethereum-dapp-url-bar-style']\").getAttribute(\"content\")", function(topBarStyle){
- if (topBarStyle=="transparent") {
+ webView.runJavaScript("try{document.querySelector(\"link[rel='icon']\").getAttribute(\"href\")}catch(e){}", function(sideIcon){
+ if(sideIcon){
+ menuItem.icon = webview.url + sideIcon;
+ };
+ });
+
+ webView.runJavaScript("try{document.querySelector(\"meta[name='ethereum-dapp-url-bar-style']\").getAttribute(\"content\")}catch(e){}", function(topBarStyle){
+ if (!topBarStyle) {
+ showFullUrlBar(true);
+ navBarBackground.visible = true;
+ back.visible = true;
+ appInfoPane.anchors.leftMargin = 0;
+ appInfoPaneShadow.anchors.leftMargin = 0;
+ webview.anchors.topMargin = 0;
+ return;
+ }
+ if (topBarStyle=="transparent") {
// Adjust for a transparent sidebar Dapp
navBarBackground.visible = false;
back.visible = false;
@@ -352,22 +430,31 @@ Rectangle {
webview.anchors.topMargin = -74;
webview.runJavaScript("document.querySelector('body').classList.add('ethereum-dapp-url-bar-style-transparent')")
+ } else {
+ navBarBackground.visible = true;
+ back.visible = true;
+ appInfoPane.anchors.leftMargin = 0;
+ appInfoPaneShadow.anchors.leftMargin = 0;
+ webview.anchors.topMargin = 0;
};
});
-
webview.runJavaScript(eth.readFile("bignumber.min.js"));
- webview.runJavaScript(eth.readFile("ethereum.js/dist/ethereum.js"));
-
+ webview.runJavaScript(eth.readFile("ethereum.js/dist/ethereum.js"));
+ webview.runJavaScript(eth.readFile("mist.js"));
+
var cleanTitle = webview.url.toString()
var matches = cleanTitle.match(/^[a-z]*\:\/\/([^\/?#]+)(?:[\/?#]|$)/i);
var domain = matches && matches[1];
- appDomain.text = domain //webview.url.replace("a", "z")
- appTitle.text = webview.title
- showFullUrlBar(false);
+ if (domain)
+ appDomain.text = domain //webview.url.replace("a", "z")
+ if (webview.title)
+ appTitle.text = webview.title
+
+ showFullUrlBar(false);
}
}
onJavaScriptConsoleMessage: {
diff --git a/cmd/mist/assets/qml/views/catalog.qml b/cmd/mist/assets/qml/views/catalog.qml
index 7f42c25dc..29e133074 100644
--- a/cmd/mist/assets/qml/views/catalog.qml
+++ b/cmd/mist/assets/qml/views/catalog.qml
@@ -3,7 +3,7 @@ import QtQuick.Controls 1.0;
import QtQuick.Controls.Styles 1.0
import QtQuick.Layouts 1.0;
import QtWebEngine 1.0
-//import QtWebEngine.experimental 1.0
+import QtWebEngine.experimental 1.0
import QtQuick.Window 2.0;
@@ -12,7 +12,7 @@ Rectangle {
anchors.fill: parent
color: "#00000000"
- property var title: ""
+ property var title: "Catalog"
property var iconSource: ""
property var menuItem
property var hideUrl: true
@@ -21,8 +21,6 @@ Rectangle {
property alias windowTitle: webview.title
property alias webView: webview
-
-
property var cleanPath: false
property var open: function(url) {
if(!window.cleanPath) {
@@ -66,124 +64,61 @@ Rectangle {
}
}
- Component.onCompleted: {
- }
-
Item {
objectName: "root"
id: root
anchors.fill: parent
state: "inspectorShown"
- RowLayout {
- id: navBar
- height: 184
- z: 20
+ WebEngineView {
+ objectName: "webView"
+ id: webview
+ anchors.fill: parent
- anchors {
- left: parent.left
- right: parent.right
- }
+ property var protocol: "http://"
+ //property var domain: "localhost:3000"
+ property var domain: "ethereum-dapp-catalog.meteor.com"
+ url: protocol + domain
- Rectangle {
- id: appInfoPane
- height: 28
- color: "#efefef"
- radius: 6
- z:25
-
- MouseArea {
- anchors.fill: parent
- z: 10
- hoverEnabled: true
- onEntered: {
- uriNav.visible = true
- appTitle.visible = false
- appDomain.visible = false
- }
- }
-
- anchors {
- left: parent.left
- right: parent.right
- leftMargin: 10
- rightMargin: 10
- top: parent.verticalCenter
- topMargin: 23
- }
+ experimental.settings.javascriptCanAccessClipboard: true
- TextField {
- id: uriNav
- anchors {
- left: parent.left
- right: parent.right
- leftMargin: 16
- top: parent.verticalCenter
- topMargin: -10
- }
-
- horizontalAlignment: Text.AlignHCenter
-
- style: TextFieldStyle {
- textColor: "#928484"
- background: Rectangle {
- border.width: 0
- color: "transparent"
- }
- }
- text: "Type the address of a new Dapp";
- y: parent.height / 2 - this.height / 2
- z: 30
- activeFocusOnPress: true
- Keys.onReturnPressed: {
- newBrowserTab(this.text);
- this.text = "Type the address of a new Dapp";
- }
-
- }
- }
-
- Rectangle {
- id: appInfoPaneShadow
- width: 10
- height: 30
- color: "#BDB6B6"
- radius: 6
- z: 15
-
- anchors {
- left: parent.left
- right: parent.right
- leftMargin:10
- rightMargin:10
- top: parent.verticalCenter
- topMargin: 23
- }
-
+ onJavaScriptConsoleMessage: {
+ console.log(sourceID + ":" + lineNumber + ":" + JSON.stringify(message));
}
- }
-
-
- WebEngineView {
- objectName: "webView"
- id: webview
- anchors.fill: parent
-
+ onNavigationRequested: {
+ // this checks if the domain of the requested link is the same as the catalog's
+ // If it is, it opens on the same window, if it's not it opens a new tab
+
+ var cleanTitle = request.url.toString()
+ var matches = cleanTitle.match(/^[a-z]*\:\/\/([^\/?#]+)(?:[\/?#]|$)/i);
+ var requestedDomain = matches && matches[1];
+
+
+ if(request.navigationType==0){
+
+ if (requestedDomain === this.domain){
+ request.action = WebEngineView.AcceptRequest;
+ } else {
+ request.action = WebEngineView.IgnoreRequest;
+ newBrowserTab(request.url);
+ }
+
+ }
+ }
onLoadingChanged: {
if (loadRequest.status == WebEngineView.LoadSucceededStatus) {
- webview.runJavaScript(eth.readFile("bignumber.min.js"));
- webview.runJavaScript(eth.readFile("ethereum.js/dist/ethereum.js"));
+ webview.runJavaScript(eth.readFile("mist.js"));
}
}
- onJavaScriptConsoleMessage: {
- console.log(sourceID + ":" + lineNumber + ":" + JSON.stringify(message));
- }
}
+
+
+
WebEngineView {
id: inspector
visible: false
@@ -191,7 +126,7 @@ Rectangle {
anchors {
left: root.left
right: root.right
- top: sizeGrip.bottom
+ top: root.top
bottom: root.bottom
}
diff --git a/cmd/mist/assets/qml/views/info.qml b/cmd/mist/assets/qml/views/info.qml
index 14ee0bce1..b2d2f521c 100644
--- a/cmd/mist/assets/qml/views/info.qml
+++ b/cmd/mist/assets/qml/views/info.qml
@@ -32,18 +32,6 @@ Rectangle {
width: 500
}
- Label {
- text: "Client ID"
- }
- TextField {
- text: gui.getCustomIdentifier()
- width: 500
- placeholderText: "Anonymous"
- onTextChanged: {
- gui.setCustomIdentifier(text)
- }
- }
-
TextArea {
objectName: "statsPane"
width: parent.width
diff --git a/cmd/mist/assets/qml/views/miner.qml b/cmd/mist/assets/qml/views/miner.qml
index 193ce37be..e239c7d7b 100644
--- a/cmd/mist/assets/qml/views/miner.qml
+++ b/cmd/mist/assets/qml/views/miner.qml
@@ -9,11 +9,32 @@ import Ethereum 1.0
Rectangle {
id: root
property var title: "Miner"
- property var iconSource: "../miner.png"
+ property var iconSource: "../mining-icon.png"
property var menuItem
color: "#00000000"
+ Label {
+ visible: false
+ id: lastBlockLabel
+ objectName: "lastBlockLabel"
+ text: "---"
+ onTextChanged: {
+ //menuItem.secondaryTitle = text
+ }
+ }
+
+ Label {
+ objectName: "miningLabel"
+ visible: false
+ font.pixelSize: 10
+ anchors.right: lastBlockLabel.left
+ anchors.rightMargin: 5
+ onTextChanged: {
+ menuItem.secondaryTitle = text
+ }
+ }
+
ColumnLayout {
spacing: 10
anchors.fill: parent
diff --git a/cmd/mist/assets/qml/views/pending_tx.qml b/cmd/mist/assets/qml/views/pending_tx.qml
index 4442a69db..3dcedeff2 100644
--- a/cmd/mist/assets/qml/views/pending_tx.qml
+++ b/cmd/mist/assets/qml/views/pending_tx.qml
@@ -41,4 +41,13 @@ Rectangle {
pendingTxModel.insert(0, {hash: tx.hash, to: tx.address, from: tx.sender, value: tx.value, contract: isContract})
}
+
+ function removeTx(tx) {
+ for (var i = 0; i < pendingTxModel.count; i++) {
+ if (tx.hash === pendingTxModel.get(i).hash) {
+ pendingTxModel.remove(i);
+ break;
+ }
+ }
+ }
}
diff --git a/cmd/mist/assets/qml/views/transaction.qml b/cmd/mist/assets/qml/views/transaction.qml
index 62c762956..df798a9c0 100644
--- a/cmd/mist/assets/qml/views/transaction.qml
+++ b/cmd/mist/assets/qml/views/transaction.qml
@@ -103,7 +103,7 @@ Rectangle {
ComboBox {
id: valueDenom
- currentIndex: 6
+ currentIndex: 5
model: denomModel
}
}
@@ -177,7 +177,7 @@ Rectangle {
mainContractColumn.state = "ERROR"
} else {
txResult.text = "Your transaction has been submitted:\n"
- txOutput.text = res[0].address
+ txOutput.text = res.toString()
mainContractColumn.state = "DONE"
console.log(res)
diff --git a/cmd/mist/assets/qml/views/wallet.qml b/cmd/mist/assets/qml/views/wallet.qml
index 545098284..2369390c3 100644
--- a/cmd/mist/assets/qml/views/wallet.qml
+++ b/cmd/mist/assets/qml/views/wallet.qml
@@ -9,12 +9,20 @@ import Ethereum 1.0
Rectangle {
id: root
property var title: "Wallet"
- property var iconSource: "../facet.png"
property var menuItem
objectName: "walletView"
anchors.fill: parent
+ Label {
+ objectName: "balanceLabel"
+ visible: false
+ onTextChanged: {
+ balance.text = text
+ menuItem.secondaryTitle = text
+ }
+ }
+
function onReady() {
setBalance()
}
@@ -95,7 +103,7 @@ Rectangle {
ComboBox {
id: valueDenom
- currentIndex: 6
+ currentIndex: 5
model: denomModel
}
diff --git a/cmd/mist/bindings.go b/cmd/mist/bindings.go
index 706c789b1..9623538a3 100644
--- a/cmd/mist/bindings.go
+++ b/cmd/mist/bindings.go
@@ -64,15 +64,6 @@ func (gui *Gui) Transact(recipient, value, gas, gasPrice, d string) (string, err
return gui.xeth.Transact(recipient, value, gas, gasPrice, data)
}
-func (gui *Gui) SetCustomIdentifier(customIdentifier string) {
- gui.clientIdentity.SetCustomIdentifier(customIdentifier)
- gui.config.Save("id", customIdentifier)
-}
-
-func (gui *Gui) GetCustomIdentifier() string {
- return gui.clientIdentity.GetCustomIdentifier()
-}
-
// functions that allow Gui to implement interface guilogger.LogSystem
func (gui *Gui) SetLogLevel(level logger.LogLevel) {
gui.logLevel = level
diff --git a/cmd/mist/ext_app.go b/cmd/mist/ext_app.go
index 20ec52e60..7ac51db0b 100644
--- a/cmd/mist/ext_app.go
+++ b/cmd/mist/ext_app.go
@@ -24,7 +24,6 @@ import (
"github.com/ethereum/go-ethereum/core"
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/event"
- "github.com/ethereum/go-ethereum/state"
"github.com/ethereum/go-ethereum/ui/qt"
"github.com/ethereum/go-ethereum/xeth"
"github.com/obscuren/qml"
@@ -39,13 +38,12 @@ type AppContainer interface {
NewBlock(*types.Block)
NewWatcher(chan bool)
- Messages(state.Messages, string)
Post(string, int)
}
type ExtApplication struct {
*xeth.XEth
- eth core.EthManager
+ eth core.Backend
events event.Subscription
watcherQuitChan chan bool
@@ -79,10 +77,6 @@ func (app *ExtApplication) run() {
return
}
- // Subscribe to events
- mux := app.lib.eth.EventMux()
- app.events = mux.Subscribe(core.NewBlockEvent{}, state.Messages(nil))
-
// Call the main loop
go app.mainLoop()
@@ -126,23 +120,3 @@ func (app *ExtApplication) mainLoop() {
func (self *ExtApplication) Watch(filterOptions map[string]interface{}, identifier string) {
self.filters[identifier] = qt.NewFilterFromMap(filterOptions, self.eth)
}
-
-func (self *ExtApplication) GetMessages(object map[string]interface{}) string {
- /* TODO remove me
- filter := qt.NewFilterFromMap(object, self.eth)
-
- messages := filter.Find()
- var msgs []javascript.JSMessage
- for _, m := range messages {
- msgs = append(msgs, javascript.NewJSMessage(m))
- }
-
- b, err := json.Marshal(msgs)
- if err != nil {
- return "{\"error\":" + err.Error() + "}"
- }
-
- return string(b)
- */
- return ""
-}
diff --git a/cmd/mist/flags.go b/cmd/mist/flags.go
index f042b39b0..d9487de9e 100644
--- a/cmd/mist/flags.go
+++ b/cmd/mist/flags.go
@@ -21,6 +21,7 @@
package main
import (
+ "crypto/ecdsa"
"flag"
"fmt"
"log"
@@ -31,7 +32,9 @@ import (
"runtime"
"bitbucket.org/kardianos/osext"
+ "github.com/ethereum/go-ethereum/crypto"
"github.com/ethereum/go-ethereum/logger"
+ "github.com/ethereum/go-ethereum/p2p/nat"
"github.com/ethereum/go-ethereum/vm"
)
@@ -39,19 +42,18 @@ var (
Identifier string
KeyRing string
KeyStore string
- PMPGateway string
StartRpc bool
StartWebSockets bool
RpcPort int
WsPort int
- UseUPnP bool
- NatType string
OutboundPort string
ShowGenesis bool
AddPeer string
MaxPeer int
GenAddr bool
- SeedNode string
+ BootNodes string
+ NodeKey *ecdsa.PrivateKey
+ NAT nat.Interface
SecretFile string
ExportDir string
NonInteractive bool
@@ -61,6 +63,7 @@ var (
DebugFile string
LogLevel int
VmType int
+ MinerThreads int
)
// flags specific to gui client
@@ -99,6 +102,7 @@ func defaultDataDir() string {
var defaultConfigFile = path.Join(defaultDataDir(), "conf.ini")
func Init() {
+ // TODO: move common flag processing to cmd/utils
flag.Usage = func() {
fmt.Fprintf(os.Stderr, "%s [options] [filename]:\noptions precedence: default < config file < environment variables < command line\n", os.Args[0])
flag.PrintDefaults()
@@ -108,30 +112,53 @@ func Init() {
flag.StringVar(&Identifier, "id", "", "Custom client identifier")
flag.StringVar(&KeyRing, "keyring", "", "identifier for keyring to use")
flag.StringVar(&KeyStore, "keystore", "db", "system to store keyrings: db|file (db)")
- flag.StringVar(&OutboundPort, "port", "30303", "listening port")
- flag.BoolVar(&UseUPnP, "upnp", true, "enable UPnP support")
- flag.IntVar(&MaxPeer, "maxpeer", 30, "maximum desired peers")
flag.IntVar(&RpcPort, "rpcport", 8545, "port to start json-rpc server on")
flag.IntVar(&WsPort, "wsport", 40404, "port to start websocket rpc server on")
flag.BoolVar(&StartRpc, "rpc", true, "start rpc server")
flag.BoolVar(&StartWebSockets, "ws", false, "start websocket server")
flag.BoolVar(&NonInteractive, "y", false, "non-interactive mode (say yes to confirmations)")
- flag.StringVar(&SeedNode, "seednode", "poc-8.ethdev.com:30303", "ip:port of seed node to connect to. Set to blank for skip")
flag.BoolVar(&GenAddr, "genaddr", false, "create a new priv/pub key")
- flag.StringVar(&NatType, "nat", "", "NAT support (UPNP|PMP) (none)")
flag.StringVar(&SecretFile, "import", "", "imports the file given (hex or mnemonic formats)")
flag.StringVar(&ExportDir, "export", "", "exports the session keyring to files in the directory given")
flag.StringVar(&LogFile, "logfile", "", "log file (defaults to standard output)")
flag.StringVar(&Datadir, "datadir", defaultDataDir(), "specifies the datadir to use")
- flag.StringVar(&PMPGateway, "pmp", "", "Gateway IP for PMP")
flag.StringVar(&ConfigFile, "conf", defaultConfigFile, "config file")
flag.StringVar(&DebugFile, "debug", "", "debug file (no debugging if not set)")
flag.IntVar(&LogLevel, "loglevel", int(logger.InfoLevel), "loglevel: 0-5: silent,error,warn,info,debug,debug detail)")
flag.StringVar(&AssetPath, "asset_path", defaultAssetPath(), "absolute path to GUI assets directory")
+ // Network stuff
+ var (
+ nodeKeyFile = flag.String("nodekey", "", "network private key file")
+ nodeKeyHex = flag.String("nodekeyhex", "", "network private key (for testing)")
+ natstr = flag.String("nat", "any", "port mapping mechanism (any|none|upnp|pmp|extip:<IP>)")
+ )
+ flag.StringVar(&OutboundPort, "port", "30303", "listening port")
+ flag.StringVar(&BootNodes, "bootnodes", "", "space-separated node URLs for discovery bootstrap")
+ flag.IntVar(&MaxPeer, "maxpeer", 30, "maximum desired peers")
+
+ flag.IntVar(&MinerThreads, "minerthreads", runtime.NumCPU(), "number of miner threads")
+
flag.Parse()
+ var err error
+ if NAT, err = nat.Parse(*natstr); err != nil {
+ log.Fatalf("-nat: %v", err)
+ }
+ switch {
+ case *nodeKeyFile != "" && *nodeKeyHex != "":
+ log.Fatal("Options -nodekey and -nodekeyhex are mutually exclusive")
+ case *nodeKeyFile != "":
+ if NodeKey, err = crypto.LoadECDSA(*nodeKeyFile); err != nil {
+ log.Fatalf("-nodekey: %v", err)
+ }
+ case *nodeKeyHex != "":
+ if NodeKey, err = crypto.HexToECDSA(*nodeKeyHex); err != nil {
+ log.Fatalf("-nodekeyhex: %v", err)
+ }
+ }
+
if VmType >= int(vm.MaxVmTy) {
log.Fatal("Invalid VM type ", VmType)
}
diff --git a/cmd/mist/gui.go b/cmd/mist/gui.go
index edc799abc..4af0cff43 100644
--- a/cmd/mist/gui.go
+++ b/cmd/mist/gui.go
@@ -31,6 +31,7 @@ import (
"os"
"path"
"runtime"
+ "sort"
"strconv"
"time"
@@ -40,8 +41,6 @@ import (
"github.com/ethereum/go-ethereum/ethdb"
"github.com/ethereum/go-ethereum/ethutil"
"github.com/ethereum/go-ethereum/logger"
- "github.com/ethereum/go-ethereum/miner"
- "github.com/ethereum/go-ethereum/p2p"
"github.com/ethereum/go-ethereum/ui/qt/qwhisper"
"github.com/ethereum/go-ethereum/xeth"
"github.com/obscuren/qml"
@@ -77,17 +76,14 @@ type Gui struct {
xeth *xeth.XEth
- Session string
- clientIdentity *p2p.SimpleClientIdentity
- config *ethutil.ConfigManager
+ Session string
+ config *ethutil.ConfigManager
plugins map[string]plugin
-
- miner *miner.Miner
}
// Create GUI, but doesn't start it
-func NewWindow(ethereum *eth.Ethereum, config *ethutil.ConfigManager, clientIdentity *p2p.SimpleClientIdentity, session string, logLevel int) *Gui {
+func NewWindow(ethereum *eth.Ethereum, config *ethutil.ConfigManager, session string, logLevel int) *Gui {
db, err := ethdb.NewLDBDatabase("tx_database")
if err != nil {
panic(err)
@@ -95,15 +91,14 @@ func NewWindow(ethereum *eth.Ethereum, config *ethutil.ConfigManager, clientIden
xeth := xeth.New(ethereum)
gui := &Gui{eth: ethereum,
- txDb: db,
- xeth: xeth,
- logLevel: logger.LogLevel(logLevel),
- Session: session,
- open: false,
- clientIdentity: clientIdentity,
- config: config,
- plugins: make(map[string]plugin),
- serviceEvents: make(chan ServEv, 1),
+ txDb: db,
+ xeth: xeth,
+ logLevel: logger.LogLevel(logLevel),
+ Session: session,
+ open: false,
+ config: config,
+ plugins: make(map[string]plugin),
+ serviceEvents: make(chan ServEv, 1),
}
data, _ := ethutil.ReadAllFile(path.Join(ethutil.Config.ExecPath, "plugins.json"))
json.Unmarshal([]byte(data), &gui.plugins)
@@ -136,6 +131,7 @@ func (gui *Gui) Start(assetPath string) {
context.SetVar("gui", gui)
context.SetVar("eth", gui.uiLib)
context.SetVar("shh", gui.whisper)
+ //clipboard.SetQMLClipboard(context)
win, err := gui.showWallet(context)
if err != nil {
@@ -391,16 +387,11 @@ func (gui *Gui) update() {
generalUpdateTicker := time.NewTicker(500 * time.Millisecond)
statsUpdateTicker := time.NewTicker(5 * time.Second)
- state := gui.eth.ChainManager().TransState()
-
- gui.win.Root().Call("setWalletValue", fmt.Sprintf("%v", ethutil.CurrencyToString(state.GetAccount(gui.address()).Balance())))
-
lastBlockLabel := gui.getObjectByName("lastBlockLabel")
miningLabel := gui.getObjectByName("miningLabel")
events := gui.eth.EventMux().Subscribe(
- //eth.PeerListEvent{},
- core.NewBlockEvent{},
+ core.ChainEvent{},
core.TxPreEvent{},
core.TxPostEvent{},
)
@@ -413,62 +404,22 @@ func (gui *Gui) update() {
return
}
switch ev := ev.(type) {
- case core.NewBlockEvent:
+ case core.ChainEvent:
gui.processBlock(ev.Block, false)
- if bytes.Compare(ev.Block.Coinbase(), gui.address()) == 0 {
- gui.setWalletValue(gui.eth.ChainManager().State().GetBalance(gui.address()), nil)
- }
-
case core.TxPreEvent:
- tx := ev.Tx
-
- tstate := gui.eth.ChainManager().TransState()
- cstate := gui.eth.ChainManager().State()
-
- taccount := tstate.GetAccount(gui.address())
- caccount := cstate.GetAccount(gui.address())
- unconfirmedFunds := new(big.Int).Sub(taccount.Balance(), caccount.Balance())
-
- gui.setWalletValue(taccount.Balance(), unconfirmedFunds)
- gui.insertTransaction("pre", tx)
+ gui.insertTransaction("pre", ev.Tx)
case core.TxPostEvent:
- tx := ev.Tx
- object := state.GetAccount(gui.address())
-
- if bytes.Compare(tx.From(), gui.address()) == 0 {
- object.SubAmount(tx.Value())
-
- gui.txDb.Put(tx.Hash(), tx.RlpEncode())
- } else if bytes.Compare(tx.To(), gui.address()) == 0 {
- object.AddAmount(tx.Value())
-
- gui.txDb.Put(tx.Hash(), tx.RlpEncode())
- }
-
- gui.setWalletValue(object.Balance(), nil)
- state.UpdateStateObject(object)
+ gui.getObjectByName("pendingTxView").Call("removeTx", xeth.NewTx(ev.Tx))
}
case <-peerUpdateTicker.C:
gui.setPeerInfo()
+
case <-generalUpdateTicker.C:
statusText := "#" + gui.eth.ChainManager().CurrentBlock().Number().String()
lastBlockLabel.Set("text", statusText)
- miningLabel.Set("text", "Mining @ "+strconv.FormatInt(gui.uiLib.miner.GetPow().GetHashrate(), 10)+"Khash")
-
- /*
- blockLength := gui.eth.BlockPool().BlocksProcessed
- chainLength := gui.eth.BlockPool().ChainLength
-
- var (
- pct float64 = 1.0 / float64(chainLength) * float64(blockLength)
- dlWidget = gui.win.Root().ObjectByName("downloadIndicator")
- dlLabel = gui.win.Root().ObjectByName("downloadLabel")
- )
- dlWidget.Set("value", pct)
- dlLabel.Set("text", fmt.Sprintf("%d / %d", blockLength, chainLength))
- */
+ miningLabel.Set("text", "Mining @ "+strconv.FormatInt(gui.uiLib.Miner().HashRate(), 10)+"/Khash")
case <-statsUpdateTicker.C:
gui.setStatsPane()
@@ -502,12 +453,35 @@ NumGC: %d
))
}
+type qmlpeer struct{ Addr, NodeID, Name, Caps string }
+
+type peersByID []*qmlpeer
+
+func (s peersByID) Len() int { return len(s) }
+func (s peersByID) Less(i, j int) bool { return s[i].NodeID < s[j].NodeID }
+func (s peersByID) Swap(i, j int) { s[i], s[j] = s[j], s[i] }
+
func (gui *Gui) setPeerInfo() {
- gui.win.Root().Call("setPeers", fmt.Sprintf("%d / %d", gui.eth.PeerCount(), gui.eth.MaxPeers))
- gui.win.Root().Call("resetPeers")
- //for _, peer := range gui.xeth.Peers() {
- //gui.win.Root().Call("addPeer", peer)
- //}
+ peers := gui.eth.Peers()
+ qpeers := make(peersByID, len(peers))
+ for i, p := range peers {
+ qpeers[i] = &qmlpeer{
+ NodeID: p.ID().String(),
+ Addr: p.RemoteAddr().String(),
+ Name: p.Name(),
+ Caps: fmt.Sprint(p.Caps()),
+ }
+ }
+ // we need to sort the peers because they jump around randomly
+ // otherwise. order returned by eth.Peers is random because they
+ // are taken from a map.
+ sort.Sort(qpeers)
+
+ gui.win.Root().Call("setPeerCounters", fmt.Sprintf("%d / %d", len(peers), gui.eth.MaxPeers()))
+ gui.win.Root().Call("clearPeers")
+ for _, p := range qpeers {
+ gui.win.Root().Call("addPeer", p)
+ }
}
func (gui *Gui) privateKey() string {
diff --git a/cmd/mist/html_container.go b/cmd/mist/html_container.go
index 0909a6abd..e4ea57b9b 100644
--- a/cmd/mist/html_container.go
+++ b/cmd/mist/html_container.go
@@ -31,7 +31,6 @@ import (
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/ethutil"
- "github.com/ethereum/go-ethereum/state"
"github.com/ethereum/go-ethereum/xeth"
"github.com/howeyc/fsnotify"
"github.com/obscuren/qml"
@@ -144,19 +143,6 @@ func (app *HtmlApplication) NewBlock(block *types.Block) {
app.webView.Call("onNewBlockCb", b)
}
-func (self *HtmlApplication) Messages(messages state.Messages, id string) {
- /* TODO remove me
- var msgs []javascript.JSMessage
- for _, m := range messages {
- msgs = append(msgs, javascript.NewJSMessage(m))
- }
-
- b, _ := json.Marshal(msgs)
-
- self.webView.Call("onWatchedCb", string(b), id)
- */
-}
-
func (app *HtmlApplication) Destroy() {
app.engine.Destroy()
}
diff --git a/cmd/mist/main.go b/cmd/mist/main.go
index 66872a241..ad6eb5bec 100644
--- a/cmd/mist/main.go
+++ b/cmd/mist/main.go
@@ -36,7 +36,7 @@ import (
const (
ClientIdentifier = "Mist"
- Version = "0.8.2"
+ Version = "0.8.5"
)
var ethereum *eth.Ethereum
@@ -52,19 +52,20 @@ func run() error {
config := utils.InitConfig(VmType, ConfigFile, Datadir, "ETH")
ethereum, err := eth.New(&eth.Config{
- Name: ClientIdentifier,
- Version: Version,
- KeyStore: KeyStore,
- DataDir: Datadir,
- LogFile: LogFile,
- LogLevel: LogLevel,
- Identifier: Identifier,
- MaxPeers: MaxPeer,
- Port: OutboundPort,
- NATType: PMPGateway,
- PMPGateway: PMPGateway,
- KeyRing: KeyRing,
- Dial: true,
+ Name: p2p.MakeName(ClientIdentifier, Version),
+ KeyStore: KeyStore,
+ DataDir: Datadir,
+ LogFile: LogFile,
+ LogLevel: LogLevel,
+ MaxPeers: MaxPeer,
+ Port: OutboundPort,
+ NAT: NAT,
+ Shh: true,
+ BootNodes: BootNodes,
+ NodeKey: NodeKey,
+ KeyRing: KeyRing,
+ Dial: true,
+ MinerThreads: MinerThreads,
})
if err != nil {
mainlogger.Fatalln(err)
@@ -79,12 +80,12 @@ func run() error {
utils.StartWebSockets(ethereum, WsPort)
}
- gui := NewWindow(ethereum, config, ethereum.ClientIdentity().(*p2p.SimpleClientIdentity), KeyRing, LogLevel)
+ gui := NewWindow(ethereum, config, KeyRing, LogLevel)
utils.RegisterInterrupt(func(os.Signal) {
gui.Stop()
})
- go utils.StartEthereum(ethereum, SeedNode)
+ go utils.StartEthereum(ethereum)
fmt.Println("ETH stack took", time.Since(tstart))
diff --git a/cmd/mist/qml_container.go b/cmd/mist/qml_container.go
index 9d76d8fe4..16a055bc0 100644
--- a/cmd/mist/qml_container.go
+++ b/cmd/mist/qml_container.go
@@ -22,12 +22,10 @@
package main
import (
- "fmt"
"runtime"
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/ethutil"
- "github.com/ethereum/go-ethereum/state"
"github.com/ethereum/go-ethereum/xeth"
"github.com/obscuren/qml"
)
@@ -74,10 +72,6 @@ func (app *QmlApplication) NewBlock(block *types.Block) {
app.win.Call("onNewBlockCb", pblock)
}
-func (self *QmlApplication) Messages(msgs state.Messages, id string) {
- fmt.Println("IMPLEMENT QML APPLICATION MESSAGES METHOD")
-}
-
// Getters
func (app *QmlApplication) Engine() *qml.Engine {
return app.engine
diff --git a/cmd/mist/ui_lib.go b/cmd/mist/ui_lib.go
index 7c5802076..4fa6e8e55 100644
--- a/cmd/mist/ui_lib.go
+++ b/cmd/mist/ui_lib.go
@@ -30,7 +30,6 @@ import (
"github.com/ethereum/go-ethereum/ethutil"
"github.com/ethereum/go-ethereum/event/filter"
"github.com/ethereum/go-ethereum/javascript"
- "github.com/ethereum/go-ethereum/miner"
"github.com/ethereum/go-ethereum/xeth"
"github.com/obscuren/qml"
)
@@ -56,13 +55,10 @@ type UiLib struct {
filterCallbacks map[int][]int
filterManager *filter.FilterManager
-
- miner *miner.Miner
}
func NewUiLib(engine *qml.Engine, eth *eth.Ethereum, assetPath string) *UiLib {
lib := &UiLib{XEth: xeth.New(eth), engine: engine, eth: eth, assetPath: assetPath, jsEngine: javascript.NewJSRE(eth), filterCallbacks: make(map[int][]int)} //, filters: make(map[int]*xeth.JSFilter)}
- lib.miner = miner.New(eth.KeyManager().Address(), eth)
lib.filterManager = filter.NewFilterManager(eth.EventMux())
go lib.filterManager.Start()
@@ -73,11 +69,6 @@ func (self *UiLib) Notef(args []interface{}) {
guilogger.Infoln(args...)
}
-func (self *UiLib) PastPeers() *ethutil.List {
- return ethutil.NewList([]string{})
- //return ethutil.NewList(eth.PastPeers())
-}
-
func (self *UiLib) ImportTx(rlpTx string) {
tx := types.NewTransactionFromBytes(ethutil.Hex2Bytes(rlpTx))
err := self.eth.TxPool().Add(tx)
@@ -136,15 +127,15 @@ func (ui *UiLib) Muted(content string) {
func (ui *UiLib) Connect(button qml.Object) {
if !ui.connected {
- ui.eth.Start(SeedNode)
+ ui.eth.Start()
ui.connected = true
button.Set("enabled", false)
}
}
-func (ui *UiLib) ConnectToPeer(addr string) {
- if err := ui.eth.SuggestPeer(addr); err != nil {
- guilogger.Infoln(err)
+func (ui *UiLib) ConnectToPeer(nodeURL string) {
+ if err := ui.eth.SuggestPeer(nodeURL); err != nil {
+ guilogger.Infoln("SuggestPeer error: " + err.Error())
}
}
@@ -155,8 +146,8 @@ func (ui *UiLib) AssetPath(p string) string {
func (self *UiLib) StartDbWithContractAndData(contractHash, data string) {
dbWindow := NewDebuggerWindow(self)
object := self.eth.ChainManager().State().GetStateObject(ethutil.Hex2Bytes(contractHash))
- if len(object.Code) > 0 {
- dbWindow.SetCode(ethutil.Bytes2Hex(object.Code))
+ if len(object.Code()) > 0 {
+ dbWindow.SetCode(ethutil.Bytes2Hex(object.Code()))
}
dbWindow.SetData(data)
@@ -209,34 +200,37 @@ func (self *UiLib) Call(params map[string]interface{}) (string, error) {
}
func (self *UiLib) AddLocalTransaction(to, data, gas, gasPrice, value string) int {
- return self.miner.AddLocalTx(&miner.LocalTx{
- To: ethutil.Hex2Bytes(to),
- Data: ethutil.Hex2Bytes(data),
- Gas: gas,
- GasPrice: gasPrice,
- Value: value,
- }) - 1
+ return 0
+ /*
+ return self.miner.AddLocalTx(&miner.LocalTx{
+ To: ethutil.Hex2Bytes(to),
+ Data: ethutil.Hex2Bytes(data),
+ Gas: gas,
+ GasPrice: gasPrice,
+ Value: value,
+ }) - 1
+ */
}
func (self *UiLib) RemoveLocalTransaction(id int) {
- self.miner.RemoveLocalTx(id)
+ //self.miner.RemoveLocalTx(id)
}
func (self *UiLib) SetGasPrice(price string) {
- self.miner.MinAcceptedGasPrice = ethutil.Big(price)
+ self.Miner().MinAcceptedGasPrice = ethutil.Big(price)
}
func (self *UiLib) SetExtra(extra string) {
- self.miner.Extra = extra
+ self.Miner().Extra = extra
}
func (self *UiLib) ToggleMining() bool {
- if !self.miner.Mining() {
- self.miner.Start()
+ if !self.Miner().Mining() {
+ self.Miner().Start()
return true
} else {
- self.miner.Stop()
+ self.Miner().Stop()
return false
}
diff --git a/cmd/peerserver/main.go b/cmd/peerserver/main.go
deleted file mode 100644
index 341c4dbb9..000000000
--- a/cmd/peerserver/main.go
+++ /dev/null
@@ -1,58 +0,0 @@
-/*
- This file is part of go-ethereum
-
- go-ethereum is free software: you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation, either version 3 of the License, or
- (at your option) any later version.
-
- go-ethereum is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with go-ethereum. If not, see <http://www.gnu.org/licenses/>.
-*/
-package main
-
-import (
- "crypto/elliptic"
- "flag"
- "log"
- "os"
-
- "github.com/ethereum/go-ethereum/crypto"
- "github.com/ethereum/go-ethereum/logger"
- "github.com/ethereum/go-ethereum/p2p"
-)
-
-var (
- natType = flag.String("nat", "", "NAT traversal implementation")
- pmpGateway = flag.String("gateway", "", "gateway address for NAT-PMP")
- listenAddr = flag.String("addr", ":30301", "listen address")
-)
-
-func main() {
- flag.Parse()
- nat, err := p2p.ParseNAT(*natType, *pmpGateway)
- if err != nil {
- log.Fatal("invalid nat:", err)
- }
-
- logger.AddLogSystem(logger.NewStdLogSystem(os.Stdout, log.LstdFlags, logger.InfoLevel))
- key, _ := crypto.GenerateKey()
- marshaled := elliptic.Marshal(crypto.S256(), key.PublicKey.X, key.PublicKey.Y)
-
- srv := p2p.Server{
- MaxPeers: 100,
- Identity: p2p.NewSimpleClientIdentity("Ethereum(G)", "0.1", "Peer Server Two", marshaled),
- ListenAddr: *listenAddr,
- NAT: nat,
- NoDial: true,
- }
- if err := srv.Start(); err != nil {
- log.Fatal("could not start server:", err)
- }
- select {}
-}
diff --git a/cmd/utils/cmd.go b/cmd/utils/cmd.go
index 70df289c3..bc8fafafb 100644
--- a/cmd/utils/cmd.go
+++ b/cmd/utils/cmd.go
@@ -121,13 +121,11 @@ func exit(err error) {
os.Exit(status)
}
-func StartEthereum(ethereum *eth.Ethereum, SeedNode string) {
- clilogger.Infof("Starting %s", ethereum.ClientIdentity())
- err := ethereum.Start(SeedNode)
- if err != nil {
+func StartEthereum(ethereum *eth.Ethereum) {
+ clilogger.Infoln("Starting ", ethereum.Name())
+ if err := ethereum.Start(); err != nil {
exit(err)
}
-
RegisterInterrupt(func(sig os.Signal) {
ethereum.Stop()
logger.Flush()
@@ -227,7 +225,7 @@ func StartMining(ethereum *eth.Ethereum) bool {
go func() {
clilogger.Infoln("Start mining")
if gminer == nil {
- gminer = miner.New(addr, ethereum)
+ gminer = miner.New(addr, ethereum, 4)
}
gminer.Start()
}()
@@ -274,7 +272,7 @@ func BlockDo(ethereum *eth.Ethereum, hash []byte) error {
parent := ethereum.ChainManager().GetBlock(block.ParentHash())
statedb := state.New(parent.Root(), ethereum.Db())
- _, err := ethereum.BlockProcessor().TransitionState(statedb, parent, block)
+ _, err := ethereum.BlockProcessor().TransitionState(statedb, parent, block, true)
if err != nil {
return err
}