Merge branch 'develop' into rpcfrontier
Conflicts: rpc/api.go rpc/args.go
This commit is contained in:
@ -1,41 +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/>.
|
||||
*/
|
||||
/**
|
||||
* @authors
|
||||
* Gustav Simonsson <gustav.simonsson@gmail.com>
|
||||
*/
|
||||
package main
|
||||
|
||||
import (
|
||||
"flag"
|
||||
"fmt"
|
||||
"os"
|
||||
)
|
||||
|
||||
var (
|
||||
TestFile string
|
||||
)
|
||||
|
||||
func Init() {
|
||||
flag.Usage = func() {
|
||||
fmt.Fprintf(os.Stderr, "%s <testfile>\n", os.Args[0])
|
||||
flag.PrintDefaults()
|
||||
}
|
||||
flag.Parse()
|
||||
|
||||
TestFile = flag.Arg(0)
|
||||
}
|
@ -25,34 +25,26 @@ package main
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"crypto/ecdsa"
|
||||
"encoding/hex"
|
||||
"encoding/json"
|
||||
"flag"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"log"
|
||||
"math/big"
|
||||
"path"
|
||||
"os"
|
||||
"runtime"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/ethereum/go-ethereum/cmd/utils"
|
||||
"github.com/ethereum/go-ethereum/core"
|
||||
types "github.com/ethereum/go-ethereum/core/types"
|
||||
"github.com/ethereum/go-ethereum/eth"
|
||||
"github.com/ethereum/go-ethereum/ethutil"
|
||||
"github.com/ethereum/go-ethereum/ethdb"
|
||||
"github.com/ethereum/go-ethereum/event"
|
||||
"github.com/ethereum/go-ethereum/logger"
|
||||
"github.com/ethereum/go-ethereum/p2p"
|
||||
"github.com/ethereum/go-ethereum/p2p/nat"
|
||||
"github.com/ethereum/go-ethereum/rlp"
|
||||
)
|
||||
|
||||
const (
|
||||
ClientIdentifier = "Ethereum(G)"
|
||||
Version = "0.8.6"
|
||||
)
|
||||
|
||||
type Account struct {
|
||||
Balance string
|
||||
Code string
|
||||
@ -78,6 +70,7 @@ type BlockHeader struct {
|
||||
TransactionsTrie string
|
||||
UncleHash string
|
||||
}
|
||||
|
||||
type Tx struct {
|
||||
Data string
|
||||
GasLimit string
|
||||
@ -103,108 +96,44 @@ type Test struct {
|
||||
Pre map[string]Account
|
||||
}
|
||||
|
||||
var (
|
||||
Identifier string
|
||||
KeyRing string
|
||||
DiffTool bool
|
||||
DiffType string
|
||||
KeyStore string
|
||||
StartRpc bool
|
||||
StartWebSockets bool
|
||||
RpcListenAddress string
|
||||
RpcPort int
|
||||
WsPort int
|
||||
OutboundPort string
|
||||
ShowGenesis bool
|
||||
AddPeer string
|
||||
MaxPeer int
|
||||
GenAddr bool
|
||||
BootNodes string
|
||||
NodeKey *ecdsa.PrivateKey
|
||||
NAT nat.Interface
|
||||
SecretFile string
|
||||
ExportDir string
|
||||
NonInteractive bool
|
||||
Datadir string
|
||||
LogFile string
|
||||
ConfigFile string
|
||||
DebugFile string
|
||||
LogLevel int
|
||||
LogFormat string
|
||||
Dump bool
|
||||
DumpHash string
|
||||
DumpNumber int
|
||||
VmType int
|
||||
ImportChain string
|
||||
SHH bool
|
||||
Dial bool
|
||||
PrintVersion bool
|
||||
MinerThreads int
|
||||
)
|
||||
|
||||
// flags specific to cli client
|
||||
var (
|
||||
StartMining bool
|
||||
StartJsConsole bool
|
||||
InputFile string
|
||||
)
|
||||
|
||||
func main() {
|
||||
init_vars()
|
||||
|
||||
Init()
|
||||
|
||||
if len(TestFile) < 1 {
|
||||
log.Fatal("Please specify test file")
|
||||
}
|
||||
blocks, err := loadBlocksFromTestFile(TestFile)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
flag.Usage = func() {
|
||||
fmt.Fprintf(os.Stderr, "%s <testfile>\n", os.Args[0])
|
||||
flag.PrintDefaults()
|
||||
}
|
||||
flag.Parse()
|
||||
|
||||
runtime.GOMAXPROCS(runtime.NumCPU())
|
||||
logger.AddLogSystem(logger.NewStdLogSystem(os.Stderr, log.LstdFlags, logger.DebugDetailLevel))
|
||||
defer func() { logger.Flush() }()
|
||||
|
||||
defer func() {
|
||||
logger.Flush()
|
||||
}()
|
||||
if len(os.Args) < 2 {
|
||||
utils.Fatalf("Please specify a test file as the first argument.")
|
||||
}
|
||||
blocks, err := loadBlocksFromTestFile(os.Args[1])
|
||||
if err != nil {
|
||||
utils.Fatalf("Could not load blocks: %v", err)
|
||||
}
|
||||
|
||||
//utils.HandleInterrupt()
|
||||
chain := memchain()
|
||||
chain.ResetWithGenesisBlock(blocks[0])
|
||||
if err = chain.InsertChain(types.Blocks{blocks[1]}); err != nil {
|
||||
utils.Fatalf("Error: %v", err)
|
||||
} else {
|
||||
fmt.Println("PASS")
|
||||
}
|
||||
}
|
||||
|
||||
utils.InitConfig(VmType, ConfigFile, Datadir, "ethblocktest")
|
||||
|
||||
ethereum, err := eth.New(ð.Config{
|
||||
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,
|
||||
MinerThreads: MinerThreads,
|
||||
})
|
||||
|
||||
utils.StartEthereumForTest(ethereum)
|
||||
utils.StartRpc(ethereum, RpcListenAddress, RpcPort)
|
||||
|
||||
ethereum.ChainManager().ResetWithGenesisBlock(blocks[0])
|
||||
// bph := ethereum.ChainManager().GetBlock(blocks[1].Header().ParentHash)
|
||||
// fmt.Println("bph: ", bph)
|
||||
|
||||
//fmt.Println("b0: ", hex.EncodeToString(ethutil.Encode(blocks[0].RlpData())))
|
||||
//fmt.Println("b0: ", hex.EncodeToString(blocks[0].Hash()))
|
||||
//fmt.Println("b1: ", hex.EncodeToString(ethutil.Encode(blocks[1].RlpData())))
|
||||
//fmt.Println("b1: ", hex.EncodeToString(blocks[1].Hash()))
|
||||
|
||||
go ethereum.ChainManager().InsertChain(types.Blocks{blocks[1]})
|
||||
fmt.Println("OK! ")
|
||||
ethereum.WaitForShutdown()
|
||||
func memchain() *core.ChainManager {
|
||||
blockdb, err := ethdb.NewMemDatabase()
|
||||
if err != nil {
|
||||
utils.Fatalf("Could not create in-memory database: %v", err)
|
||||
}
|
||||
statedb, err := ethdb.NewMemDatabase()
|
||||
if err != nil {
|
||||
utils.Fatalf("Could not create in-memory database: %v", err)
|
||||
}
|
||||
return core.NewChainManager(blockdb, statedb, new(event.TypeMux))
|
||||
}
|
||||
|
||||
func loadBlocksFromTestFile(filePath string) (blocks types.Blocks, err error) {
|
||||
@ -212,9 +141,8 @@ func loadBlocksFromTestFile(filePath string) (blocks types.Blocks, err error) {
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
bt := *new(map[string]Test)
|
||||
err = json.Unmarshal(fileContent, &bt)
|
||||
if err != nil {
|
||||
bt := make(map[string]Test)
|
||||
if err = json.Unmarshal(fileContent, &bt); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
@ -280,49 +208,6 @@ func loadBlocksFromTestFile(filePath string) (blocks types.Blocks, err error) {
|
||||
return
|
||||
}
|
||||
|
||||
func init_vars() {
|
||||
VmType = 0
|
||||
Identifier = ""
|
||||
KeyRing = ""
|
||||
KeyStore = "db"
|
||||
RpcListenAddress = "127.0.0.1"
|
||||
RpcPort = 8545
|
||||
WsPort = 40404
|
||||
StartRpc = true
|
||||
StartWebSockets = false
|
||||
NonInteractive = false
|
||||
GenAddr = false
|
||||
SecretFile = ""
|
||||
ExportDir = ""
|
||||
LogFile = ""
|
||||
|
||||
timeStr := strconv.FormatInt(time.Now().UnixNano(), 10)
|
||||
|
||||
Datadir = path.Join(ethutil.DefaultDataDir(), timeStr)
|
||||
ConfigFile = path.Join(ethutil.DefaultDataDir(), timeStr, "conf.ini")
|
||||
|
||||
DebugFile = ""
|
||||
LogLevel = 5
|
||||
LogFormat = "std"
|
||||
DiffTool = false
|
||||
DiffType = "all"
|
||||
ShowGenesis = false
|
||||
ImportChain = ""
|
||||
Dump = false
|
||||
DumpHash = ""
|
||||
DumpNumber = -1
|
||||
StartMining = false
|
||||
StartJsConsole = false
|
||||
PrintVersion = false
|
||||
MinerThreads = runtime.NumCPU()
|
||||
|
||||
Dial = false
|
||||
OutboundPort = "30303"
|
||||
BootNodes = ""
|
||||
MaxPeer = 1
|
||||
|
||||
}
|
||||
|
||||
func hex_decode(s string) (res []byte, err error) {
|
||||
return hex.DecodeString(strings.TrimPrefix(s, "0x"))
|
||||
}
|
||||
|
@ -22,11 +22,9 @@ import (
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"os/signal"
|
||||
"path"
|
||||
"strings"
|
||||
|
||||
"github.com/ethereum/go-ethereum/cmd/utils"
|
||||
"github.com/ethereum/go-ethereum/core/types"
|
||||
"github.com/ethereum/go-ethereum/eth"
|
||||
"github.com/ethereum/go-ethereum/ethutil"
|
||||
@ -37,51 +35,123 @@ import (
|
||||
"github.com/peterh/liner"
|
||||
)
|
||||
|
||||
func execJsFile(ethereum *eth.Ethereum, filename string) {
|
||||
file, err := os.Open(filename)
|
||||
if err != nil {
|
||||
utils.Fatalf("%v", err)
|
||||
}
|
||||
content, err := ioutil.ReadAll(file)
|
||||
if err != nil {
|
||||
utils.Fatalf("%v", err)
|
||||
}
|
||||
re := javascript.NewJSRE(xeth.New(ethereum, nil))
|
||||
if _, err := re.Run(string(content)); err != nil {
|
||||
utils.Fatalf("Javascript Error: %v", err)
|
||||
}
|
||||
type prompter interface {
|
||||
AppendHistory(string)
|
||||
Prompt(p string) (string, error)
|
||||
PasswordPrompt(p string) (string, error)
|
||||
}
|
||||
|
||||
type repl struct {
|
||||
type dumbterm struct{ r *bufio.Reader }
|
||||
|
||||
func (r dumbterm) Prompt(p string) (string, error) {
|
||||
fmt.Print(p)
|
||||
return r.r.ReadString('\n')
|
||||
}
|
||||
|
||||
func (r dumbterm) PasswordPrompt(p string) (string, error) {
|
||||
fmt.Println("!! Unsupported terminal, password will echo.")
|
||||
fmt.Print(p)
|
||||
input, err := bufio.NewReader(os.Stdin).ReadString('\n')
|
||||
fmt.Println()
|
||||
return input, err
|
||||
}
|
||||
|
||||
func (r dumbterm) AppendHistory(string) {}
|
||||
|
||||
type jsre struct {
|
||||
re *javascript.JSRE
|
||||
ethereum *eth.Ethereum
|
||||
xeth *xeth.XEth
|
||||
prompt string
|
||||
lr *liner.State
|
||||
ps1 string
|
||||
atexit func()
|
||||
|
||||
prompter
|
||||
}
|
||||
|
||||
func runREPL(ethereum *eth.Ethereum) {
|
||||
xeth := xeth.New(ethereum, nil)
|
||||
repl := &repl{
|
||||
re: javascript.NewJSRE(xeth),
|
||||
xeth: xeth,
|
||||
ethereum: ethereum,
|
||||
prompt: "> ",
|
||||
}
|
||||
repl.initStdFuncs()
|
||||
func newJSRE(ethereum *eth.Ethereum) *jsre {
|
||||
js := &jsre{ethereum: ethereum, ps1: "> "}
|
||||
js.xeth = xeth.New(ethereum, js)
|
||||
js.re = javascript.NewJSRE(js.xeth)
|
||||
js.initStdFuncs()
|
||||
|
||||
if !liner.TerminalSupported() {
|
||||
repl.dumbRead()
|
||||
js.prompter = dumbterm{bufio.NewReader(os.Stdin)}
|
||||
} else {
|
||||
lr := liner.NewLiner()
|
||||
defer lr.Close()
|
||||
js.withHistory(func(hist *os.File) { lr.ReadHistory(hist) })
|
||||
lr.SetCtrlCAborts(true)
|
||||
repl.withHistory(func(hist *os.File) { lr.ReadHistory(hist) })
|
||||
repl.read(lr)
|
||||
repl.withHistory(func(hist *os.File) { hist.Truncate(0); lr.WriteHistory(hist) })
|
||||
js.prompter = lr
|
||||
js.atexit = func() {
|
||||
js.withHistory(func(hist *os.File) { hist.Truncate(0); lr.WriteHistory(hist) })
|
||||
lr.Close()
|
||||
}
|
||||
}
|
||||
return js
|
||||
}
|
||||
|
||||
func (self *jsre) ConfirmTransaction(tx *types.Transaction) bool {
|
||||
p := fmt.Sprintf("Confirm Transaction %v\n[y/n] ", tx)
|
||||
answer, _ := self.Prompt(p)
|
||||
return strings.HasPrefix(strings.Trim(answer, " "), "y")
|
||||
}
|
||||
|
||||
func (self *jsre) UnlockAccount(addr []byte) bool {
|
||||
fmt.Printf("Please unlock account %x.\n", addr)
|
||||
pass, err := self.PasswordPrompt("Passphrase: ")
|
||||
if err != nil {
|
||||
return false
|
||||
}
|
||||
// TODO: allow retry
|
||||
if err := self.ethereum.AccountManager().Unlock(addr, pass); err != nil {
|
||||
return false
|
||||
} else {
|
||||
fmt.Println("Account is now unlocked for this session.")
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
func (self *repl) withHistory(op func(*os.File)) {
|
||||
func (self *jsre) exec(filename string) error {
|
||||
file, err := os.Open(filename)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
content, err := ioutil.ReadAll(file)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if _, err := self.re.Run(string(content)); err != nil {
|
||||
return fmt.Errorf("Javascript Error: %v", err)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (self *jsre) interactive() {
|
||||
for {
|
||||
input, err := self.Prompt(self.ps1)
|
||||
if err != nil {
|
||||
break
|
||||
}
|
||||
if input == "" {
|
||||
continue
|
||||
}
|
||||
str += input + "\n"
|
||||
self.setIndent()
|
||||
if indentCount <= 0 {
|
||||
if input == "exit" {
|
||||
break
|
||||
}
|
||||
hist := str[:len(str)-1]
|
||||
self.AppendHistory(hist)
|
||||
self.parseInput(str)
|
||||
str = ""
|
||||
}
|
||||
}
|
||||
if self.atexit != nil {
|
||||
self.atexit()
|
||||
}
|
||||
}
|
||||
|
||||
func (self *jsre) withHistory(op func(*os.File)) {
|
||||
hist, err := os.OpenFile(path.Join(self.ethereum.DataDir, "history"), os.O_RDWR|os.O_CREATE, os.ModePerm)
|
||||
if err != nil {
|
||||
fmt.Printf("unable to open history file: %v\n", err)
|
||||
@ -91,7 +161,7 @@ func (self *repl) withHistory(op func(*os.File)) {
|
||||
hist.Close()
|
||||
}
|
||||
|
||||
func (self *repl) parseInput(code string) {
|
||||
func (self *jsre) parseInput(code string) {
|
||||
defer func() {
|
||||
if r := recover(); r != nil {
|
||||
fmt.Println("[native] error", r)
|
||||
@ -108,79 +178,21 @@ func (self *repl) parseInput(code string) {
|
||||
var indentCount = 0
|
||||
var str = ""
|
||||
|
||||
func (self *repl) setIndent() {
|
||||
func (self *jsre) setIndent() {
|
||||
open := strings.Count(str, "{")
|
||||
open += strings.Count(str, "(")
|
||||
closed := strings.Count(str, "}")
|
||||
closed += strings.Count(str, ")")
|
||||
indentCount = open - closed
|
||||
if indentCount <= 0 {
|
||||
self.prompt = "> "
|
||||
self.ps1 = "> "
|
||||
} else {
|
||||
self.prompt = strings.Join(make([]string, indentCount*2), "..")
|
||||
self.prompt += " "
|
||||
self.ps1 = strings.Join(make([]string, indentCount*2), "..")
|
||||
self.ps1 += " "
|
||||
}
|
||||
}
|
||||
|
||||
func (self *repl) read(lr *liner.State) {
|
||||
for {
|
||||
input, err := lr.Prompt(self.prompt)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
if input == "" {
|
||||
continue
|
||||
}
|
||||
str += input + "\n"
|
||||
self.setIndent()
|
||||
if indentCount <= 0 {
|
||||
if input == "exit" {
|
||||
return
|
||||
}
|
||||
hist := str[:len(str)-1]
|
||||
lr.AppendHistory(hist)
|
||||
self.parseInput(str)
|
||||
str = ""
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (self *repl) dumbRead() {
|
||||
fmt.Println("Unsupported terminal, line editing will not work.")
|
||||
|
||||
// process lines
|
||||
readDone := make(chan struct{})
|
||||
go func() {
|
||||
r := bufio.NewReader(os.Stdin)
|
||||
loop:
|
||||
for {
|
||||
fmt.Print(self.prompt)
|
||||
line, err := r.ReadString('\n')
|
||||
switch {
|
||||
case err != nil || line == "exit":
|
||||
break loop
|
||||
case line == "":
|
||||
continue
|
||||
default:
|
||||
self.parseInput(line + "\n")
|
||||
}
|
||||
}
|
||||
close(readDone)
|
||||
}()
|
||||
|
||||
// wait for Ctrl-C
|
||||
sigc := make(chan os.Signal, 1)
|
||||
signal.Notify(sigc, os.Interrupt, os.Kill)
|
||||
defer signal.Stop(sigc)
|
||||
|
||||
select {
|
||||
case <-readDone:
|
||||
case <-sigc:
|
||||
os.Stdin.Close() // terminate read
|
||||
}
|
||||
}
|
||||
|
||||
func (self *repl) printValue(v interface{}) {
|
||||
func (self *jsre) printValue(v interface{}) {
|
||||
method, _ := self.re.Vm.Get("prettyPrint")
|
||||
v, err := self.re.Vm.ToValue(v)
|
||||
if err == nil {
|
||||
@ -191,7 +203,7 @@ func (self *repl) printValue(v interface{}) {
|
||||
}
|
||||
}
|
||||
|
||||
func (self *repl) initStdFuncs() {
|
||||
func (self *jsre) initStdFuncs() {
|
||||
t, _ := self.re.Vm.Get("eth")
|
||||
eth := t.Object()
|
||||
eth.Set("connect", self.connect)
|
||||
@ -205,7 +217,7 @@ func (self *repl) initStdFuncs() {
|
||||
* The following methods are natively implemented javascript functions.
|
||||
*/
|
||||
|
||||
func (self *repl) dump(call otto.FunctionCall) otto.Value {
|
||||
func (self *jsre) dump(call otto.FunctionCall) otto.Value {
|
||||
var block *types.Block
|
||||
|
||||
if len(call.ArgumentList) > 0 {
|
||||
@ -236,17 +248,17 @@ func (self *repl) dump(call otto.FunctionCall) otto.Value {
|
||||
return v
|
||||
}
|
||||
|
||||
func (self *repl) stopMining(call otto.FunctionCall) otto.Value {
|
||||
func (self *jsre) stopMining(call otto.FunctionCall) otto.Value {
|
||||
self.xeth.Miner().Stop()
|
||||
return otto.TrueValue()
|
||||
}
|
||||
|
||||
func (self *repl) startMining(call otto.FunctionCall) otto.Value {
|
||||
func (self *jsre) startMining(call otto.FunctionCall) otto.Value {
|
||||
self.xeth.Miner().Start()
|
||||
return otto.TrueValue()
|
||||
}
|
||||
|
||||
func (self *repl) connect(call otto.FunctionCall) otto.Value {
|
||||
func (self *jsre) connect(call otto.FunctionCall) otto.Value {
|
||||
nodeURL, err := call.Argument(0).ToString()
|
||||
if err != nil {
|
||||
return otto.FalseValue()
|
||||
@ -257,7 +269,7 @@ func (self *repl) connect(call otto.FunctionCall) otto.Value {
|
||||
return otto.TrueValue()
|
||||
}
|
||||
|
||||
func (self *repl) export(call otto.FunctionCall) otto.Value {
|
||||
func (self *jsre) export(call otto.FunctionCall) otto.Value {
|
||||
if len(call.ArgumentList) == 0 {
|
||||
fmt.Println("err: require file name")
|
||||
return otto.FalseValue()
|
||||
|
@ -21,19 +21,23 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"fmt"
|
||||
"os"
|
||||
"runtime"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/codegangsta/cli"
|
||||
"github.com/ethereum/go-ethereum/accounts"
|
||||
"github.com/ethereum/go-ethereum/cmd/utils"
|
||||
"github.com/ethereum/go-ethereum/core/types"
|
||||
"github.com/ethereum/go-ethereum/eth"
|
||||
"github.com/ethereum/go-ethereum/ethutil"
|
||||
"github.com/ethereum/go-ethereum/logger"
|
||||
"github.com/ethereum/go-ethereum/state"
|
||||
"github.com/peterh/liner"
|
||||
)
|
||||
|
||||
const (
|
||||
@ -43,12 +47,10 @@ const (
|
||||
|
||||
var (
|
||||
clilogger = logger.NewLogger("CLI")
|
||||
app = cli.NewApp()
|
||||
app = utils.NewApp(Version, "the go-ethereum command line interface")
|
||||
)
|
||||
|
||||
func init() {
|
||||
app.Version = Version
|
||||
app.Usage = "the go-ethereum command-line client"
|
||||
app.Action = run
|
||||
app.HideVersion = true // we have a command to print the version
|
||||
app.Commands = []cli.Command{
|
||||
@ -60,6 +62,23 @@ func init() {
|
||||
The output of this command is supposed to be machine-readable.
|
||||
`,
|
||||
},
|
||||
{
|
||||
Action: accountList,
|
||||
Name: "account",
|
||||
Usage: "manage accounts",
|
||||
Subcommands: []cli.Command{
|
||||
{
|
||||
Action: accountList,
|
||||
Name: "list",
|
||||
Usage: "print account addresses",
|
||||
},
|
||||
{
|
||||
Action: accountCreate,
|
||||
Name: "new",
|
||||
Usage: "create a new account",
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
Action: dump,
|
||||
Name: "dump",
|
||||
@ -93,13 +112,10 @@ runtime will execute the file and exit.
|
||||
Usage: `export blockchain into file`,
|
||||
},
|
||||
}
|
||||
app.Author = ""
|
||||
app.Email = ""
|
||||
app.Flags = []cli.Flag{
|
||||
utils.UnlockedAccountFlag,
|
||||
utils.BootnodesFlag,
|
||||
utils.DataDirFlag,
|
||||
utils.KeyRingFlag,
|
||||
utils.KeyStoreFlag,
|
||||
utils.ListenPortFlag,
|
||||
utils.LogFileFlag,
|
||||
utils.LogFormatFlag,
|
||||
@ -140,38 +156,100 @@ func main() {
|
||||
func run(ctx *cli.Context) {
|
||||
fmt.Printf("Welcome to the FRONTIER\n")
|
||||
utils.HandleInterrupt()
|
||||
eth := utils.GetEthereum(ClientIdentifier, Version, ctx)
|
||||
eth, err := utils.GetEthereum(ClientIdentifier, Version, ctx)
|
||||
if err == accounts.ErrNoKeys {
|
||||
utils.Fatalf(`No accounts configured.
|
||||
Please run 'ethereum account new' to create a new account.`)
|
||||
} else if err != nil {
|
||||
utils.Fatalf("%v", err)
|
||||
}
|
||||
|
||||
startEth(ctx, eth)
|
||||
// this blocks the thread
|
||||
eth.WaitForShutdown()
|
||||
}
|
||||
|
||||
func runjs(ctx *cli.Context) {
|
||||
eth := utils.GetEthereum(ClientIdentifier, Version, ctx)
|
||||
startEth(ctx, eth)
|
||||
if len(ctx.Args()) == 0 {
|
||||
runREPL(eth)
|
||||
eth.Stop()
|
||||
eth.WaitForShutdown()
|
||||
} else if len(ctx.Args()) == 1 {
|
||||
execJsFile(eth, ctx.Args()[0])
|
||||
} else {
|
||||
utils.Fatalf("This command can handle at most one argument.")
|
||||
eth, err := utils.GetEthereum(ClientIdentifier, Version, ctx)
|
||||
if err == accounts.ErrNoKeys {
|
||||
utils.Fatalf(`No accounts configured.
|
||||
Please run 'ethereum account new' to create a new account.`)
|
||||
} else if err != nil {
|
||||
utils.Fatalf("%v", err)
|
||||
}
|
||||
|
||||
startEth(ctx, eth)
|
||||
repl := newJSRE(eth)
|
||||
if len(ctx.Args()) == 0 {
|
||||
repl.interactive()
|
||||
} else {
|
||||
for _, file := range ctx.Args() {
|
||||
repl.exec(file)
|
||||
}
|
||||
}
|
||||
eth.Stop()
|
||||
eth.WaitForShutdown()
|
||||
}
|
||||
|
||||
func startEth(ctx *cli.Context, eth *eth.Ethereum) {
|
||||
utils.StartEthereum(eth)
|
||||
|
||||
// Load startup keys. XXX we are going to need a different format
|
||||
account := ctx.GlobalString(utils.UnlockedAccountFlag.Name)
|
||||
if len(account) > 0 {
|
||||
split := strings.Split(account, ":")
|
||||
if len(split) != 2 {
|
||||
utils.Fatalf("Illegal 'unlock' format (address:password)")
|
||||
}
|
||||
am := utils.GetAccountManager(ctx)
|
||||
// Attempt to unlock the account
|
||||
err := am.Unlock(ethutil.Hex2Bytes(split[0]), split[1])
|
||||
if err != nil {
|
||||
utils.Fatalf("Unlock account failed '%v'", err)
|
||||
}
|
||||
}
|
||||
// Start auxiliary services if enabled.
|
||||
if ctx.GlobalBool(utils.RPCEnabledFlag.Name) {
|
||||
addr := ctx.GlobalString(utils.RPCListenAddrFlag.Name)
|
||||
port := ctx.GlobalInt(utils.RPCPortFlag.Name)
|
||||
utils.StartRpc(eth, addr, port)
|
||||
utils.StartRPC(eth, ctx)
|
||||
}
|
||||
if ctx.GlobalBool(utils.MiningEnabledFlag.Name) {
|
||||
eth.Miner().Start()
|
||||
}
|
||||
}
|
||||
|
||||
func accountList(ctx *cli.Context) {
|
||||
am := utils.GetAccountManager(ctx)
|
||||
accts, err := am.Accounts()
|
||||
if err != nil {
|
||||
utils.Fatalf("Could not list accounts: %v", err)
|
||||
}
|
||||
for _, acct := range accts {
|
||||
fmt.Printf("Address: %#x\n", acct)
|
||||
}
|
||||
}
|
||||
|
||||
func accountCreate(ctx *cli.Context) {
|
||||
am := utils.GetAccountManager(ctx)
|
||||
fmt.Println("The new account will be encrypted with a passphrase.")
|
||||
fmt.Println("Please enter a passphrase now.")
|
||||
auth, err := readPassword("Passphrase: ", true)
|
||||
if err != nil {
|
||||
utils.Fatalf("%v", err)
|
||||
}
|
||||
confirm, err := readPassword("Repeat Passphrase: ", false)
|
||||
if err != nil {
|
||||
utils.Fatalf("%v", err)
|
||||
}
|
||||
if auth != confirm {
|
||||
utils.Fatalf("Passphrases did not match.")
|
||||
}
|
||||
acct, err := am.NewAccount(auth)
|
||||
if err != nil {
|
||||
utils.Fatalf("Could not create the account: %v", err)
|
||||
}
|
||||
fmt.Printf("Address: %#x\n", acct.Address)
|
||||
}
|
||||
|
||||
func importchain(ctx *cli.Context) {
|
||||
if len(ctx.Args()) != 1 {
|
||||
utils.Fatalf("This command requires an argument.")
|
||||
@ -221,12 +299,6 @@ func dump(ctx *cli.Context) {
|
||||
}
|
||||
}
|
||||
|
||||
// hashish returns true for strings that look like hashes.
|
||||
func hashish(x string) bool {
|
||||
_, err := strconv.Atoi(x)
|
||||
return err != nil
|
||||
}
|
||||
|
||||
func version(c *cli.Context) {
|
||||
fmt.Printf(`%v
|
||||
Version: %v
|
||||
@ -238,3 +310,24 @@ GOPATH=%s
|
||||
GOROOT=%s
|
||||
`, ClientIdentifier, Version, eth.ProtocolVersion, eth.NetworkId, runtime.Version(), runtime.GOOS, os.Getenv("GOPATH"), runtime.GOROOT())
|
||||
}
|
||||
|
||||
// hashish returns true for strings that look like hashes.
|
||||
func hashish(x string) bool {
|
||||
_, err := strconv.Atoi(x)
|
||||
return err != nil
|
||||
}
|
||||
|
||||
func readPassword(prompt string, warnTerm bool) (string, error) {
|
||||
if liner.TerminalSupported() {
|
||||
lr := liner.NewLiner()
|
||||
defer lr.Close()
|
||||
return lr.PasswordPrompt(prompt)
|
||||
}
|
||||
if warnTerm {
|
||||
fmt.Println("!! Unsupported terminal, password will be echoed.")
|
||||
}
|
||||
fmt.Print(prompt)
|
||||
input, err := bufio.NewReader(os.Stdin).ReadString('\n')
|
||||
fmt.Println()
|
||||
return input, err
|
||||
}
|
||||
|
@ -59,8 +59,6 @@ func main() {
|
||||
|
||||
logger.AddLogSystem(logger.NewStdLogSystem(os.Stdout, log.LstdFlags, logger.LogLevel(*loglevel)))
|
||||
|
||||
ethutil.ReadConfig("/tmp/evmtest", "/tmp/evm", "")
|
||||
|
||||
db, _ := ethdb.NewMemDatabase()
|
||||
statedb := state.New(nil, db)
|
||||
sender := statedb.NewStateObject([]byte("sender"))
|
||||
|
@ -190,6 +190,11 @@ ApplicationWindow {
|
||||
}
|
||||
}
|
||||
|
||||
MenuItem {
|
||||
text: "Generate key"
|
||||
shortcut: "Ctrl+k"
|
||||
onTriggered: gui.generateKey()
|
||||
}
|
||||
}
|
||||
|
||||
Menu {
|
||||
|
@ -54,7 +54,6 @@ Rectangle {
|
||||
height: 200
|
||||
anchors {
|
||||
left: parent.left
|
||||
right: logLevelSlider.left
|
||||
bottom: parent.bottom
|
||||
top: parent.top
|
||||
}
|
||||
@ -107,46 +106,6 @@ Rectangle {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
TableView {
|
||||
id: logView
|
||||
headerVisible: false
|
||||
anchors {
|
||||
right: logLevelSlider.left
|
||||
left: parent.left
|
||||
bottom: parent.bottom
|
||||
top: parent.top
|
||||
}
|
||||
|
||||
TableViewColumn{ role: "description" ; title: "log" }
|
||||
|
||||
model: logModel
|
||||
}
|
||||
*/
|
||||
|
||||
Slider {
|
||||
id: logLevelSlider
|
||||
value: gui.getLogLevelInt()
|
||||
anchors {
|
||||
right: parent.right
|
||||
top: parent.top
|
||||
bottom: parent.bottom
|
||||
|
||||
rightMargin: 5
|
||||
leftMargin: 5
|
||||
topMargin: 5
|
||||
bottomMargin: 5
|
||||
}
|
||||
|
||||
orientation: Qt.Vertical
|
||||
maximumValue: 5
|
||||
stepSize: 1
|
||||
|
||||
onValueChanged: {
|
||||
gui.setLogLevel(value)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
property var logModel: ListModel {
|
||||
|
@ -28,7 +28,6 @@ import (
|
||||
"github.com/ethereum/go-ethereum/cmd/utils"
|
||||
"github.com/ethereum/go-ethereum/core/types"
|
||||
"github.com/ethereum/go-ethereum/ethutil"
|
||||
"github.com/ethereum/go-ethereum/logger"
|
||||
"github.com/ethereum/go-ethereum/state"
|
||||
)
|
||||
|
||||
@ -37,19 +36,7 @@ type plugin struct {
|
||||
Path string `json:"path"`
|
||||
}
|
||||
|
||||
// LogPrint writes to the GUI log.
|
||||
func (gui *Gui) LogPrint(level logger.LogLevel, msg string) {
|
||||
/*
|
||||
str := strings.TrimRight(s, "\n")
|
||||
lines := strings.Split(str, "\n")
|
||||
|
||||
view := gui.getObjectByName("infoView")
|
||||
for _, line := range lines {
|
||||
view.Call("addLog", line)
|
||||
}
|
||||
*/
|
||||
}
|
||||
func (gui *Gui) Transact(recipient, value, gas, gasPrice, d string) (string, error) {
|
||||
func (gui *Gui) Transact(from, recipient, value, gas, gasPrice, d string) (string, error) {
|
||||
var data string
|
||||
if len(recipient) == 0 {
|
||||
code, err := ethutil.Compile(d, false)
|
||||
@ -61,18 +48,7 @@ func (gui *Gui) Transact(recipient, value, gas, gasPrice, d string) (string, err
|
||||
data = ethutil.Bytes2Hex(utils.FormatTransactionData(d))
|
||||
}
|
||||
|
||||
return gui.xeth.Transact(recipient, value, gas, gasPrice, data)
|
||||
}
|
||||
|
||||
// functions that allow Gui to implement interface guilogger.LogSystem
|
||||
func (gui *Gui) SetLogLevel(level logger.LogLevel) {
|
||||
gui.logLevel = level
|
||||
gui.eth.Logger().SetLogLevel(level)
|
||||
gui.config.Save("loglevel", level)
|
||||
}
|
||||
|
||||
func (gui *Gui) GetLogLevel() logger.LogLevel {
|
||||
return gui.logLevel
|
||||
return gui.xeth.Transact(from, recipient, value, gas, gasPrice, data)
|
||||
}
|
||||
|
||||
func (self *Gui) AddPlugin(pluginPath string) {
|
||||
@ -89,11 +65,6 @@ func (self *Gui) RemovePlugin(pluginPath string) {
|
||||
ethutil.WriteFile(self.eth.DataDir+"/plugins.json", json)
|
||||
}
|
||||
|
||||
// this extra function needed to give int typecast value to gui widget
|
||||
// that sets initial loglevel to default
|
||||
func (gui *Gui) GetLogLevelInt() int {
|
||||
return int(gui.logLevel)
|
||||
}
|
||||
func (self *Gui) DumpState(hash, path string) {
|
||||
var stateDump []byte
|
||||
|
||||
|
@ -1,130 +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/>.
|
||||
*/
|
||||
/**
|
||||
* @authors
|
||||
* Jeffrey Wilcke <i@jev.io>
|
||||
*/
|
||||
package main
|
||||
|
||||
import (
|
||||
"crypto/ecdsa"
|
||||
"flag"
|
||||
"fmt"
|
||||
"log"
|
||||
"os"
|
||||
"path"
|
||||
"runtime"
|
||||
|
||||
"github.com/ethereum/go-ethereum/crypto"
|
||||
"github.com/ethereum/go-ethereum/ethutil"
|
||||
"github.com/ethereum/go-ethereum/logger"
|
||||
"github.com/ethereum/go-ethereum/p2p/nat"
|
||||
"github.com/ethereum/go-ethereum/vm"
|
||||
)
|
||||
|
||||
var (
|
||||
Identifier string
|
||||
KeyRing string
|
||||
KeyStore string
|
||||
StartRpc bool
|
||||
RpcListenAddress string
|
||||
RpcPort int
|
||||
OutboundPort string
|
||||
ShowGenesis bool
|
||||
AddPeer string
|
||||
MaxPeer int
|
||||
GenAddr bool
|
||||
BootNodes string
|
||||
NodeKey *ecdsa.PrivateKey
|
||||
NAT nat.Interface
|
||||
SecretFile string
|
||||
ExportDir string
|
||||
NonInteractive bool
|
||||
Datadir string
|
||||
LogFile string
|
||||
ConfigFile string
|
||||
DebugFile string
|
||||
LogLevel int
|
||||
VmType int
|
||||
MinerThreads int
|
||||
)
|
||||
|
||||
// flags specific to gui client
|
||||
var AssetPath string
|
||||
var defaultConfigFile = path.Join(ethutil.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()
|
||||
}
|
||||
|
||||
flag.IntVar(&VmType, "vm", 0, "Virtual Machine type: 0-1: standard, debug")
|
||||
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")
|
||||
flag.StringVar(&RpcListenAddress, "rpcaddr", "127.0.0.1", "address for json-rpc server to listen on")
|
||||
flag.IntVar(&RpcPort, "rpcport", 8545, "port to start json-rpc server on")
|
||||
flag.BoolVar(&StartRpc, "rpc", true, "start rpc server")
|
||||
flag.BoolVar(&NonInteractive, "y", false, "non-interactive mode (say yes to confirmations)")
|
||||
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")
|
||||
flag.StringVar(&LogFile, "logfile", "", "log file (defaults to standard output)")
|
||||
flag.StringVar(&Datadir, "datadir", ethutil.DefaultDataDir(), "specifies the datadir to use")
|
||||
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", ethutil.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)
|
||||
}
|
||||
}
|
@ -23,7 +23,6 @@ package main
|
||||
import "C"
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
@ -70,20 +69,18 @@ type Gui struct {
|
||||
|
||||
txDb *ethdb.LDBDatabase
|
||||
|
||||
logLevel logger.LogLevel
|
||||
open bool
|
||||
open bool
|
||||
|
||||
xeth *xeth.XEth
|
||||
|
||||
Session string
|
||||
config *ethutil.ConfigManager
|
||||
|
||||
plugins map[string]plugin
|
||||
}
|
||||
|
||||
// Create GUI, but doesn't start it
|
||||
func NewWindow(ethereum *eth.Ethereum, config *ethutil.ConfigManager, session string, logLevel int) *Gui {
|
||||
db, err := ethdb.NewLDBDatabase("tx_database")
|
||||
func NewWindow(ethereum *eth.Ethereum) *Gui {
|
||||
db, err := ethdb.NewLDBDatabase(path.Join(ethereum.DataDir, "tx_database"))
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
@ -92,10 +89,7 @@ func NewWindow(ethereum *eth.Ethereum, config *ethutil.ConfigManager, session st
|
||||
gui := &Gui{eth: ethereum,
|
||||
txDb: db,
|
||||
xeth: xeth,
|
||||
logLevel: logger.LogLevel(logLevel),
|
||||
Session: session,
|
||||
open: false,
|
||||
config: config,
|
||||
plugins: make(map[string]plugin),
|
||||
serviceEvents: make(chan ServEv, 1),
|
||||
}
|
||||
@ -142,18 +136,12 @@ func (gui *Gui) Start(assetPath string) {
|
||||
gui.open = true
|
||||
win.Show()
|
||||
|
||||
// only add the gui guilogger after window is shown otherwise slider wont be shown
|
||||
logger.AddLogSystem(gui)
|
||||
win.Wait()
|
||||
|
||||
// need to silence gui guilogger after window closed otherwise logsystem hangs (but do not save loglevel)
|
||||
gui.logLevel = logger.Silence
|
||||
gui.open = false
|
||||
}
|
||||
|
||||
func (gui *Gui) Stop() {
|
||||
if gui.open {
|
||||
gui.logLevel = logger.Silence
|
||||
gui.open = false
|
||||
gui.win.Hide()
|
||||
}
|
||||
@ -172,7 +160,11 @@ func (gui *Gui) showWallet(context *qml.Context) (*qml.Window, error) {
|
||||
return gui.win, nil
|
||||
}
|
||||
|
||||
func (gui *Gui) ImportKey(filePath string) {
|
||||
func (gui *Gui) GenerateKey() {
|
||||
_, err := gui.eth.AccountManager().NewAccount("hurr")
|
||||
if err != nil {
|
||||
// TODO: UI feedback?
|
||||
}
|
||||
}
|
||||
|
||||
func (gui *Gui) showKeyImport(context *qml.Context) (*qml.Window, error) {
|
||||
@ -191,31 +183,11 @@ func (gui *Gui) createWindow(comp qml.Object) *qml.Window {
|
||||
return gui.win
|
||||
}
|
||||
|
||||
func (gui *Gui) ImportAndSetPrivKey(secret string) bool {
|
||||
err := gui.eth.KeyManager().InitFromString(gui.Session, 0, secret)
|
||||
if err != nil {
|
||||
guilogger.Errorln("unable to import: ", err)
|
||||
return false
|
||||
}
|
||||
guilogger.Errorln("successfully imported: ", err)
|
||||
return true
|
||||
}
|
||||
|
||||
func (gui *Gui) CreateAndSetPrivKey() (string, string, string, string) {
|
||||
err := gui.eth.KeyManager().Init(gui.Session, 0, true)
|
||||
if err != nil {
|
||||
guilogger.Errorln("unable to create key: ", err)
|
||||
return "", "", "", ""
|
||||
}
|
||||
return gui.eth.KeyManager().KeyPair().AsStrings()
|
||||
}
|
||||
|
||||
func (gui *Gui) setInitialChain(ancientBlocks bool) {
|
||||
sBlk := gui.eth.ChainManager().LastBlockHash()
|
||||
blk := gui.eth.ChainManager().GetBlock(sBlk)
|
||||
for ; blk != nil; blk = gui.eth.ChainManager().GetBlock(sBlk) {
|
||||
sBlk = blk.ParentHash()
|
||||
|
||||
gui.processBlock(blk, true)
|
||||
}
|
||||
}
|
||||
@ -259,10 +231,8 @@ func (self *Gui) loadMergedMiningOptions() {
|
||||
}
|
||||
|
||||
func (gui *Gui) insertTransaction(window string, tx *types.Transaction) {
|
||||
addr := gui.address()
|
||||
|
||||
var inout string
|
||||
if bytes.Compare(tx.From(), addr) == 0 {
|
||||
if gui.eth.AccountManager().HasAccount(tx.From()) {
|
||||
inout = "send"
|
||||
} else {
|
||||
inout = "recv"
|
||||
@ -480,14 +450,6 @@ func (gui *Gui) setPeerInfo() {
|
||||
}
|
||||
}
|
||||
|
||||
func (gui *Gui) privateKey() string {
|
||||
return ethutil.Bytes2Hex(gui.eth.KeyManager().PrivateKey())
|
||||
}
|
||||
|
||||
func (gui *Gui) address() []byte {
|
||||
return gui.eth.KeyManager().Address()
|
||||
}
|
||||
|
||||
/*
|
||||
func LoadExtension(path string) (uintptr, error) {
|
||||
lib, err := ffi.NewLibrary(path)
|
||||
|
104
cmd/mist/main.go
104
cmd/mist/main.go
@ -26,10 +26,10 @@ import (
|
||||
"runtime"
|
||||
"time"
|
||||
|
||||
"github.com/codegangsta/cli"
|
||||
"github.com/ethereum/go-ethereum/cmd/utils"
|
||||
"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/ui/qt/webengine"
|
||||
"github.com/obscuren/qml"
|
||||
)
|
||||
@ -39,56 +39,32 @@ const (
|
||||
Version = "0.9.0"
|
||||
)
|
||||
|
||||
var ethereum *eth.Ethereum
|
||||
var mainlogger = logger.NewLogger("MAIN")
|
||||
|
||||
func run() error {
|
||||
webengine.Initialize()
|
||||
|
||||
// precedence: code-internal flag default < config file < environment variables < command line
|
||||
Init() // parsing command line
|
||||
|
||||
tstart := time.Now()
|
||||
config := utils.InitConfig(VmType, ConfigFile, Datadir, "ETH")
|
||||
|
||||
ethereum, err := eth.New(ð.Config{
|
||||
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)
|
||||
var (
|
||||
app = utils.NewApp(Version, "the ether browser")
|
||||
assetPathFlag = cli.StringFlag{
|
||||
Name: "asset_path",
|
||||
Usage: "absolute path to GUI assets directory",
|
||||
Value: ethutil.DefaultAssetPath(),
|
||||
}
|
||||
utils.KeyTasks(ethereum.KeyManager(), KeyRing, GenAddr, SecretFile, ExportDir, NonInteractive)
|
||||
)
|
||||
|
||||
if StartRpc {
|
||||
utils.StartRpc(ethereum, RpcListenAddress, RpcPort)
|
||||
func init() {
|
||||
app.Action = run
|
||||
app.Flags = []cli.Flag{
|
||||
assetPathFlag,
|
||||
|
||||
utils.BootnodesFlag,
|
||||
utils.DataDirFlag,
|
||||
utils.ListenPortFlag,
|
||||
utils.LogFileFlag,
|
||||
utils.LogLevelFlag,
|
||||
utils.MaxPeersFlag,
|
||||
utils.MinerThreadsFlag,
|
||||
utils.NATFlag,
|
||||
utils.NodeKeyFileFlag,
|
||||
utils.RPCListenAddrFlag,
|
||||
utils.RPCPortFlag,
|
||||
}
|
||||
|
||||
gui := NewWindow(ethereum, config, KeyRing, LogLevel)
|
||||
|
||||
utils.RegisterInterrupt(func(os.Signal) {
|
||||
gui.Stop()
|
||||
})
|
||||
go utils.StartEthereum(ethereum)
|
||||
|
||||
fmt.Println("ETH stack took", time.Since(tstart))
|
||||
|
||||
// gui blocks the main thread
|
||||
gui.Start(AssetPath)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func main() {
|
||||
@ -97,15 +73,16 @@ func main() {
|
||||
// This is a bit of a cheat, but ey!
|
||||
os.Setenv("QTWEBKIT_INSPECTOR_SERVER", "127.0.0.1:99999")
|
||||
|
||||
qml.Run(run)
|
||||
|
||||
var interrupted = false
|
||||
utils.RegisterInterrupt(func(os.Signal) {
|
||||
interrupted = true
|
||||
})
|
||||
|
||||
utils.HandleInterrupt()
|
||||
|
||||
if err := app.Run(os.Args); err != nil {
|
||||
fmt.Fprintln(os.Stderr, "Error: ", err)
|
||||
}
|
||||
|
||||
// we need to run the interrupt callbacks in case gui is closed
|
||||
// this skips if we got here by actual interrupt stopping the GUI
|
||||
if !interrupted {
|
||||
@ -113,3 +90,26 @@ func main() {
|
||||
}
|
||||
logger.Flush()
|
||||
}
|
||||
|
||||
func run(ctx *cli.Context) {
|
||||
tstart := time.Now()
|
||||
|
||||
// TODO: show qml popup instead of exiting if initialization fails.
|
||||
ethereum, err := utils.GetEthereum(ClientIdentifier, Version, ctx)
|
||||
if err != nil {
|
||||
utils.Fatalf("%v", err)
|
||||
}
|
||||
utils.StartRPC(ethereum, ctx)
|
||||
go utils.StartEthereum(ethereum)
|
||||
fmt.Println("initializing eth stack took", time.Since(tstart))
|
||||
|
||||
// Open the window
|
||||
qml.Run(func() error {
|
||||
webengine.Initialize()
|
||||
gui := NewWindow(ethereum)
|
||||
utils.RegisterInterrupt(func(os.Signal) { gui.Stop() })
|
||||
// gui blocks the main thread
|
||||
gui.Start(ctx.GlobalString(assetPathFlag.Name))
|
||||
return nil
|
||||
})
|
||||
}
|
||||
|
@ -128,6 +128,7 @@ func (self *UiLib) Transact(params map[string]interface{}) (string, error) {
|
||||
object := mapToTxParams(params)
|
||||
|
||||
return self.XEth.Transact(
|
||||
object["from"],
|
||||
object["to"],
|
||||
object["value"],
|
||||
object["gas"],
|
||||
|
@ -29,13 +29,10 @@ import (
|
||||
|
||||
"github.com/ethereum/go-ethereum/core"
|
||||
"github.com/ethereum/go-ethereum/core/types"
|
||||
"github.com/ethereum/go-ethereum/crypto"
|
||||
"github.com/ethereum/go-ethereum/eth"
|
||||
"github.com/ethereum/go-ethereum/ethutil"
|
||||
"github.com/ethereum/go-ethereum/logger"
|
||||
"github.com/ethereum/go-ethereum/rlp"
|
||||
rpchttp "github.com/ethereum/go-ethereum/rpc/http"
|
||||
"github.com/ethereum/go-ethereum/xeth"
|
||||
)
|
||||
|
||||
var clilogger = logger.NewLogger("CLI")
|
||||
@ -97,18 +94,10 @@ func initDataDir(Datadir string) {
|
||||
}
|
||||
}
|
||||
|
||||
func InitConfig(vmType int, ConfigFile string, Datadir string, EnvPrefix string) *ethutil.ConfigManager {
|
||||
initDataDir(Datadir)
|
||||
cfg := ethutil.ReadConfig(ConfigFile, Datadir, EnvPrefix)
|
||||
cfg.VmType = vmType
|
||||
|
||||
return cfg
|
||||
}
|
||||
|
||||
func exit(err error) {
|
||||
status := 0
|
||||
if err != nil {
|
||||
fmt.Fprintln(os.Stderr, "Fatal: ", err)
|
||||
fmt.Fprintln(os.Stderr, "Fatal:", err)
|
||||
status = 1
|
||||
}
|
||||
logger.Flush()
|
||||
@ -142,47 +131,6 @@ func StartEthereumForTest(ethereum *eth.Ethereum) {
|
||||
})
|
||||
}
|
||||
|
||||
func KeyTasks(keyManager *crypto.KeyManager, KeyRing string, GenAddr bool, SecretFile string, ExportDir string, NonInteractive bool) {
|
||||
var err error
|
||||
switch {
|
||||
case GenAddr:
|
||||
if NonInteractive || confirm("This action overwrites your old private key.") {
|
||||
err = keyManager.Init(KeyRing, 0, true)
|
||||
}
|
||||
exit(err)
|
||||
case len(SecretFile) > 0:
|
||||
SecretFile = ethutil.ExpandHomePath(SecretFile)
|
||||
|
||||
if NonInteractive || confirm("This action overwrites your old private key.") {
|
||||
err = keyManager.InitFromSecretsFile(KeyRing, 0, SecretFile)
|
||||
}
|
||||
exit(err)
|
||||
case len(ExportDir) > 0:
|
||||
err = keyManager.Init(KeyRing, 0, false)
|
||||
if err == nil {
|
||||
err = keyManager.Export(ExportDir)
|
||||
}
|
||||
exit(err)
|
||||
default:
|
||||
// Creates a keypair if none exists
|
||||
err = keyManager.Init(KeyRing, 0, false)
|
||||
if err != nil {
|
||||
exit(err)
|
||||
}
|
||||
}
|
||||
clilogger.Infof("Main address %x\n", keyManager.Address())
|
||||
}
|
||||
|
||||
func StartRpc(ethereum *eth.Ethereum, RpcListenAddress string, RpcPort int) {
|
||||
var err error
|
||||
ethereum.RpcServer, err = rpchttp.NewRpcHttpServer(xeth.New(ethereum, nil), RpcListenAddress, RpcPort)
|
||||
if err != nil {
|
||||
clilogger.Errorf("Could not start RPC interface (port %v): %v", RpcPort, err)
|
||||
} else {
|
||||
go ethereum.RpcServer.Start()
|
||||
}
|
||||
}
|
||||
|
||||
func FormatTransactionData(data string) []byte {
|
||||
d := ethutil.StringToByteFunc(data, func(s string) (ret []byte) {
|
||||
slice := regexp.MustCompile("\\n|\\s").Split(s, 1000000000)
|
||||
|
@ -2,10 +2,15 @@ package utils
|
||||
|
||||
import (
|
||||
"crypto/ecdsa"
|
||||
"fmt"
|
||||
"net"
|
||||
"net/http"
|
||||
"os"
|
||||
"path"
|
||||
"runtime"
|
||||
|
||||
"github.com/codegangsta/cli"
|
||||
"github.com/ethereum/go-ethereum/accounts"
|
||||
"github.com/ethereum/go-ethereum/core"
|
||||
"github.com/ethereum/go-ethereum/crypto"
|
||||
"github.com/ethereum/go-ethereum/eth"
|
||||
@ -15,8 +20,48 @@ import (
|
||||
"github.com/ethereum/go-ethereum/logger"
|
||||
"github.com/ethereum/go-ethereum/p2p"
|
||||
"github.com/ethereum/go-ethereum/p2p/nat"
|
||||
"github.com/ethereum/go-ethereum/rpc"
|
||||
"github.com/ethereum/go-ethereum/xeth"
|
||||
)
|
||||
|
||||
func init() {
|
||||
cli.AppHelpTemplate = `{{.Name}} {{if .Flags}}[global options] {{end}}command{{if .Flags}} [command options]{{end}} [arguments...]
|
||||
|
||||
VERSION:
|
||||
{{.Version}}
|
||||
|
||||
COMMANDS:
|
||||
{{range .Commands}}{{.Name}}{{with .ShortName}}, {{.}}{{end}}{{ "\t" }}{{.Usage}}
|
||||
{{end}}{{if .Flags}}
|
||||
GLOBAL OPTIONS:
|
||||
{{range .Flags}}{{.}}
|
||||
{{end}}{{end}}
|
||||
`
|
||||
|
||||
cli.CommandHelpTemplate = `{{.Name}}{{if .Subcommands}} command{{end}}{{if .Flags}} [command options]{{end}} [arguments...]
|
||||
{{if .Description}}{{.Description}}
|
||||
{{end}}{{if .Subcommands}}
|
||||
SUBCOMMANDS:
|
||||
{{range .Subcommands}}{{.Name}}{{with .ShortName}}, {{.}}{{end}}{{ "\t" }}{{.Usage}}
|
||||
{{end}}{{end}}{{if .Flags}}
|
||||
OPTIONS:
|
||||
{{range .Flags}}{{.}}
|
||||
{{end}}{{end}}
|
||||
`
|
||||
}
|
||||
|
||||
// NewApp creates an app with sane defaults.
|
||||
func NewApp(version, usage string) *cli.App {
|
||||
app := cli.NewApp()
|
||||
app.Name = path.Base(os.Args[0])
|
||||
app.Author = ""
|
||||
app.Authors = nil
|
||||
app.Email = ""
|
||||
app.Version = version
|
||||
app.Usage = usage
|
||||
return app
|
||||
}
|
||||
|
||||
// These are all the command line flags we support.
|
||||
// If you add to this list, please remember to include the
|
||||
// flag in the appropriate command definition.
|
||||
@ -32,20 +77,14 @@ var (
|
||||
Usage: "Virtual Machine type: 0 is standard VM, 1 is debug VM",
|
||||
}
|
||||
*/
|
||||
UnlockedAccountFlag = cli.StringFlag{
|
||||
Name: "unlock",
|
||||
Usage: "Unlock a given account untill this programs exits (address:password)",
|
||||
}
|
||||
VMDebugFlag = cli.BoolFlag{
|
||||
Name: "vmdebug",
|
||||
Usage: "Virtual Machine debug output",
|
||||
}
|
||||
KeyRingFlag = cli.StringFlag{
|
||||
Name: "keyring",
|
||||
Usage: "Name of keyring to be used",
|
||||
Value: "",
|
||||
}
|
||||
KeyStoreFlag = cli.StringFlag{
|
||||
Name: "keystore",
|
||||
Usage: `Where to store keyrings: "db" or "file"`,
|
||||
Value: "db",
|
||||
}
|
||||
DataDirFlag = cli.StringFlag{
|
||||
Name: "datadir",
|
||||
Usage: "Data directory to be used",
|
||||
@ -149,30 +188,24 @@ func GetNodeKey(ctx *cli.Context) (key *ecdsa.PrivateKey) {
|
||||
return key
|
||||
}
|
||||
|
||||
func GetEthereum(clientID, version string, ctx *cli.Context) *eth.Ethereum {
|
||||
ethereum, err := eth.New(ð.Config{
|
||||
Name: p2p.MakeName(clientID, version),
|
||||
KeyStore: ctx.GlobalString(KeyStoreFlag.Name),
|
||||
DataDir: ctx.GlobalString(DataDirFlag.Name),
|
||||
LogFile: ctx.GlobalString(LogFileFlag.Name),
|
||||
LogLevel: ctx.GlobalInt(LogLevelFlag.Name),
|
||||
LogFormat: ctx.GlobalString(LogFormatFlag.Name),
|
||||
MinerThreads: ctx.GlobalInt(MinerThreadsFlag.Name),
|
||||
VmDebug: ctx.GlobalBool(VMDebugFlag.Name),
|
||||
|
||||
MaxPeers: ctx.GlobalInt(MaxPeersFlag.Name),
|
||||
Port: ctx.GlobalString(ListenPortFlag.Name),
|
||||
NAT: GetNAT(ctx),
|
||||
NodeKey: GetNodeKey(ctx),
|
||||
KeyRing: ctx.GlobalString(KeyRingFlag.Name),
|
||||
Shh: true,
|
||||
Dial: true,
|
||||
BootNodes: ctx.GlobalString(BootnodesFlag.Name),
|
||||
func GetEthereum(clientID, version string, ctx *cli.Context) (*eth.Ethereum, error) {
|
||||
return eth.New(ð.Config{
|
||||
Name: p2p.MakeName(clientID, version),
|
||||
DataDir: ctx.GlobalString(DataDirFlag.Name),
|
||||
LogFile: ctx.GlobalString(LogFileFlag.Name),
|
||||
LogLevel: ctx.GlobalInt(LogLevelFlag.Name),
|
||||
LogFormat: ctx.GlobalString(LogFormatFlag.Name),
|
||||
MinerThreads: ctx.GlobalInt(MinerThreadsFlag.Name),
|
||||
AccountManager: GetAccountManager(ctx),
|
||||
VmDebug: ctx.GlobalBool(VMDebugFlag.Name),
|
||||
MaxPeers: ctx.GlobalInt(MaxPeersFlag.Name),
|
||||
Port: ctx.GlobalString(ListenPortFlag.Name),
|
||||
NAT: GetNAT(ctx),
|
||||
NodeKey: GetNodeKey(ctx),
|
||||
Shh: true,
|
||||
Dial: true,
|
||||
BootNodes: ctx.GlobalString(BootnodesFlag.Name),
|
||||
})
|
||||
if err != nil {
|
||||
exit(err)
|
||||
}
|
||||
return ethereum
|
||||
}
|
||||
|
||||
func GetChain(ctx *cli.Context) (*core.ChainManager, ethutil.Database, ethutil.Database) {
|
||||
@ -188,3 +221,27 @@ func GetChain(ctx *cli.Context) (*core.ChainManager, ethutil.Database, ethutil.D
|
||||
}
|
||||
return core.NewChainManager(blockDb, stateDb, new(event.TypeMux)), blockDb, stateDb
|
||||
}
|
||||
|
||||
// Global account manager
|
||||
var km *accounts.Manager
|
||||
|
||||
func GetAccountManager(ctx *cli.Context) *accounts.Manager {
|
||||
dataDir := ctx.GlobalString(DataDirFlag.Name)
|
||||
if km == nil {
|
||||
ks := crypto.NewKeyStorePassphrase(path.Join(dataDir, "keys"))
|
||||
km = accounts.NewManager(ks)
|
||||
}
|
||||
return km
|
||||
}
|
||||
|
||||
func StartRPC(eth *eth.Ethereum, ctx *cli.Context) {
|
||||
addr := ctx.GlobalString(RPCListenAddrFlag.Name)
|
||||
port := ctx.GlobalInt(RPCPortFlag.Name)
|
||||
dataDir := ctx.GlobalString(DataDirFlag.Name)
|
||||
|
||||
l, err := net.Listen("tcp", fmt.Sprintf("%s:%d", addr, port))
|
||||
if err != nil {
|
||||
Fatalf("Can't listen on %s:%d: %v", addr, port, err)
|
||||
}
|
||||
go http.Serve(l, rpc.JSONRPC(xeth.New(eth, nil), dataDir))
|
||||
}
|
||||
|
Reference in New Issue
Block a user