Compare commits

...

46 Commits

Author SHA1 Message Date
3777ead25e Merge branch 'release/0.5.15' 2014-06-26 19:54:09 +02:00
a68bfd215f bump 2014-06-26 19:54:00 +02:00
fd89df4d38 Merge branch 'develop' into release/0.5.15 2014-06-26 19:53:03 +02:00
91bdf9e801 Merge branch 'ethersphere-feature/logging' into develop 2014-06-26 19:52:23 +02:00
ae5ace1619 go fmt 2014-06-26 18:48:08 +01:00
b57ee87485 bump 2014-06-26 19:04:53 +02:00
8100903d92 Increase width of asm instruction 2014-06-26 18:58:37 +02:00
648c418fcd Merge branch 'develop' of github.com:ethereum/go-ethereum into feature/logging 2014-06-26 16:33:40 +01:00
21d86ca486 gui stop
- introduce gui.Stop()
- remember state with open
- stopping ethereum stack is not gui concern, moved to main
- stopping mining, gui and ethereum handled via interrupt callbacks
- ^C triggers exactly the same behaviour as quit via menu
2014-06-26 16:26:14 +01:00
c0a05fcf89 log slider
- only add the gui logger after window is shown otherwise slider wont be shown
- need to silence gui logger after window closed otherwise logsystem hangs
- gui.GetLogLevelInt() extra function needed to give correcty int typecast value to gui widget that sets initial loglevel to default
2014-06-26 12:13:31 +01:00
b89076faa2 Added amount to contract during debugging 2014-06-26 12:10:11 +02:00
2f96652bb4 interrupt handlers now ordered 2014-06-26 10:47:45 +01:00
b3367ec0e3 Added option to not break eachline 2014-06-26 10:37:48 +02:00
9a06efd080 new logger API for upstream merge 2014-06-25 18:28:38 +01:00
6763d28a17 repl.Stop() to only if running, fixes panic after js> exit followed by interrupt 2014-06-25 18:18:22 +01:00
bf57e9603b add newline to help usage msg 2014-06-25 18:09:42 +01:00
096427c3b1 Merge remote-tracking branch 'upstream/develop' into feature/logging 2014-06-25 16:56:03 +01:00
8ee1abecb9 update log levels to include DebugDetail; correct default datadir for ethereal 2014-06-25 16:54:29 +01:00
39c0f7f386 fix logSlider: now has 5 levels, initialized to gui.GetLogLevel which is set through command line flag (defaults to InfoLevel) 2014-06-25 16:53:19 +01:00
1268413ba7 Removed old compile methods 2014-06-25 17:26:16 +02:00
08de13a57b merge upstream 2014-06-25 16:20:26 +01:00
9654b80912 Implemented TX History for ethjs 2014-06-25 16:12:53 +02:00
1e965cb8f5 Moved BlockDo to utils 2014-06-25 09:47:11 +02:00
fd1ddbce68 Save repl history to file and recall on next session 2014-06-24 10:09:02 +02:00
a13aa873c2 Merge branch 'develop' of github.com-obscure:ethereum/go-ethereum into develop 2014-06-24 09:39:25 +02:00
17e8d7519b Renamed execBlock 2014-06-24 09:36:05 +02:00
bcb88e7352 Merge branch 'develop' of github.com:ethereum/go-ethereum into develop 2014-06-23 16:26:01 +02:00
f6aabb7a90 Implements QML Apps. Implements #47
You are welcome Stephan.
2014-06-23 16:25:57 +02:00
6f09a3e820 fix imports in ui_lib and flags cos of defaultAssetPath move; fix logLevel type for gui 2014-06-23 12:38:23 +01:00
34284b7532 merge upstream 2014-06-23 12:30:30 +01:00
1024766514 refactor cli and gui wrapper code. Details:
- all cli functions shared between ethereum and ethereal abstracted to utils/ cmd.go (should be ethcommon or shared or sth)
- simplify main() now readable stepwise
- rename main wrapper files to main.go
- rename commmand line args definition file from config.go to flags.go
- rename Do -> Start to parallel option names
- register interrupt for rpc server stop
- fix interrupt stopping js repl and ethereum
- register interrupt for mining stop
- custom config file option from command line
- debug option from command line
- loglevel option from command line
- changed ethutil.Config API
- default datadir and default config file set together with other flag defaults in wrappers
- default assetpath set together with other command line flags defaults in gui wrapper (not in ethutil.Config or ui/ui_lib)
- options precedence: default < config file < environment variables < command line
2014-06-23 12:25:55 +01:00
456167aca0 fix gitignore to ignore executables 2014-06-23 12:13:06 +01:00
c67cdab221 merge upstream 2014-06-23 12:06:45 +01:00
d060ae6a36 changed logger API, functions that allow Gui to implement ethlog.LogSystem for gui logging 2014-06-23 11:57:00 +01:00
7bcf875c57 add logging for jsre 2014-06-23 11:39:09 +01:00
f90001e938 add logging start/exit to js console 2014-06-23 11:38:14 +01:00
176b780251 Added a execBlock method which replays the given block 2014-06-23 11:28:05 +02:00
2408e38218 Merge branch 'release/0.5.14' into develop 2014-06-20 00:49:00 +02:00
cba4796311 Merge branch 'release/0.5.14' 2014-06-20 00:48:53 +02:00
65cbea2b6a bump 2014-06-20 00:48:48 +02:00
c89566a42f Removed old debugger code 2014-06-20 00:42:53 +02:00
3ec0c719b9 Verbose logging 2014-06-19 13:47:18 +02:00
a32a15ad93 Merge branch 'develop' of github.com:ethereum/go-ethereum into develop 2014-06-18 18:12:31 +01:00
e517fb5f9d Merge branch 'release/0.5.13' into develop 2014-06-16 18:25:07 +02:00
50fdfb127a Merge branch 'develop' of github.com:ethereum/go-ethereum into develop 2014-06-14 13:53:55 +01:00
72df038d25 Merge branch 'develop' of github.com:ethereum/go-ethereum into develop 2014-05-23 18:25:49 +01:00
27 changed files with 803 additions and 649 deletions

3
.gitignore vendored
View File

@ -9,5 +9,6 @@
*un~
.DS_Store
*/**/.DS_Store
./ethereum/ethereum
ethereum/ethereum
ethereal/ethereal

View File

@ -5,7 +5,7 @@ Ethereum
Ethereum Go Client © 2014 Jeffrey Wilcke.
Current state: Proof of Concept 5.0 RC13.
Current state: Proof of Concept 0.5.15.
For the development package please see the [eth-go package](https://github.com/ethereum/eth-go).

View File

@ -10,9 +10,9 @@ ApplicationWindow {
visible: false
title: "IceCREAM"
minimumWidth: 1280
minimumHeight: 900
minimumHeight: 700
width: 1290
height: 900
height: 700
property alias codeText: codeEditor.text
property alias dataText: rawDataField.text
@ -42,7 +42,7 @@ ApplicationWindow {
TableView {
id: asmTableView
width: 200
TableViewColumn{ role: "value" ; title: "" ; width: 100 }
TableViewColumn{ role: "value" ; title: "" ; width: 200 }
model: asmModel
}
@ -56,7 +56,7 @@ ApplicationWindow {
Rectangle {
color: "#00000000"
height: 500
height: 330
anchors.left: parent.left
anchors.right: parent.right
@ -208,6 +208,12 @@ ApplicationWindow {
}
text: "Next"
}
CheckBox {
id: breakEachLine
objectName: "breakEachLine"
text: "Break each instruction"
checked: true
}
}
}

View File

@ -58,6 +58,9 @@ window.eth = {
getBalanceAt: function(address, cb) {
postData({call: "getBalance", args: [address]}, cb);
},
getTransactionsFor: function(address, cb) {
postData({call: "getTransactionsFor", args: [address]}, cb);
},
getSecretToAddress: function(sec, cb) {
postData({call: "getSecretToAddress", args: [sec]}, cb);

View File

@ -0,0 +1,22 @@
import QtQuick 2.0
import QtQuick.Controls 1.0;
import QtQuick.Layouts 1.0;
import Ethereum 1.0
ApplicationWindow {
minimumWidth: 500
maximumWidth: 500
maximumHeight: 400
minimumHeight: 400
function onNewBlockCb(block) {
console.log("Please overwrite onNewBlock(block):", block)
}
function onObjectChangeCb(stateObject) {
console.log("Please overwrite onObjectChangeCb(object)", stateObject)
}
function onStorageChangeCb(storageObject) {
var ev = ["storage", storageObject.stateAddress, storageObject.address].join(":");
console.log("Please overwrite onStorageChangeCb(object)", ev)
}
}

View File

@ -3,33 +3,68 @@ import QtQuick.Controls 1.0;
import QtQuick.Layouts 1.0;
import Ethereum 1.0
ApplicationWindow {
minimumWidth: 500
maximumWidth: 500
maximumHeight: 100
minimumHeight: 100
QmlApp {
minimumWidth: 350
maximumWidth: 350
maximumHeight: 80
minimumHeight: 80
title: "Ethereum Dice"
title: "Generic Coin"
TextField {
id: textField
anchors.verticalCenter: parent.verticalCenter
anchors.horizontalCenter: parent.horizontalCenter
placeholderText: "Amount"
property string contractAddr: "f299f6c74515620e4c4cd8fe3d205b5c4f2e25c8"
property string addr: "2ef47100e0787b915105fd5e3f4ff6752079d5cb"
Component.onCompleted: {
eth.watch(contractAddr, addr)
eth.watch(addr, contractAddr)
setAmount()
}
Label {
id: txHash
anchors.bottom: textField.top
anchors.bottomMargin: 5
anchors.horizontalCenter: parent.horizontalCenter
function onStorageChangeCb(storageObject) {
setAmount()
}
Button {
anchors.top: textField.bottom
anchors.horizontalCenter: parent.horizontalCenter
anchors.topMargin: 5
text: "Place bet"
onClicked: {
txHash.text = eth.createTx("e6716f9544a56c530d868e4bfbacb172315bdead", textField.text)
function setAmount(){
var state = eth.getStateObject(contractAddr)
var storage = state.getStorage(addr)
amountLabel.text = storage
}
Column {
spacing: 5
Row {
spacing: 20
Label {
id: genLabel
text: "Generic coin balance:"
}
Label {
id: amountLabel
}
}
Row {
spacing: 20
TextField {
id: address
placeholderText: "Address"
}
TextField {
id: amount
placeholderText: "Amount"
}
}
Button {
text: "Send coins"
onClicked: {
var privKey = eth.getKey().privateKey
if(privKey){
var result = eth.transact(privKey, contractAddr, 0,"100000","250", "0x" + address.text + "\n" + amount.text)
resultTx.text = result.hash
}
}
}
Label {
id: resultTx
}
}
}

View File

@ -319,7 +319,7 @@ ApplicationWindow {
Slider {
id: logLevelSlider
value: 1
value: eth.getLogLevelInt()
anchors {
right: parent.right
top: parent.top
@ -332,7 +332,7 @@ ApplicationWindow {
}
orientation: Qt.Vertical
maximumValue: 3
maximumValue: 5
stepSize: 1
onValueChanged: {
@ -372,7 +372,15 @@ ApplicationWindow {
onAccepted: {
//ui.open(openAppDialog.fileUrl.toString())
//ui.openHtml(Qt.resolvedUrl(ui.assetPath("test.html")))
ui.openHtml(openAppDialog.fileUrl.toString())
var path = openAppDialog.fileUrl.toString()
console.log(path)
var ext = path.split('.').pop()
console.log(ext)
if(ext == "html" || ext == "htm") {
ui.openHtml(path)
}else if(ext == "qml"){
ui.openQml(path)
}
}
}

View File

@ -103,6 +103,12 @@ ApplicationWindow {
postData(data._seed,stateObject)
break
case "getTransactionsFor":
require(1);
var txs = eth.getTransactionsFor(data.args[0], true)
postData(data._seed, txs)
break
case "getBalance":
require(1);

View File

@ -9,7 +9,7 @@
<script type="text/javascript">
var jefcoinAddr = "de0bd4ea1947deabf1749d7ed633f289358c9f6c"
var jefcoinAddr = "22fa3ebce6ef9ca661a960104d3087eec040011e"
var mAddr = ""
function createTransaction() {
@ -17,7 +17,7 @@ function createTransaction() {
var amount = document.querySelector("#amount").value.pad(32);
var data = (addr + amount).unbin();
eth.transact(mAddr, jefcoinAddr, 0, "10000000", "250", data, function(receipt) {
eth.transact(mAddr, jefcoinAddr, 0, "50000", "1000000", data, function(receipt) {
debug("received tx hash:", reciept.address)
})
}

View File

@ -1,43 +0,0 @@
package main
import (
"flag"
)
var Identifier string
//var StartMining bool
var StartRpc bool
var RpcPort int
var UseUPnP bool
var OutboundPort string
var ShowGenesis bool
var AddPeer string
var MaxPeer int
var GenAddr bool
var UseSeed bool
var ImportKey string
var ExportKey bool
var AssetPath string
var Datadir string
func Init() {
flag.StringVar(&Identifier, "id", "", "Custom client identifier")
flag.StringVar(&OutboundPort, "port", "30303", "listening port")
flag.BoolVar(&UseUPnP, "upnp", false, "enable UPnP support")
flag.IntVar(&MaxPeer, "maxpeer", 10, "maximum desired peers")
flag.IntVar(&RpcPort, "rpcport", 8080, "port to start json-rpc server on")
flag.BoolVar(&StartRpc, "rpc", false, "start rpc server")
flag.StringVar(&AssetPath, "asset_path", "", "absolute path to GUI assets directory")
flag.BoolVar(&ShowGenesis, "genesis", false, "prints genesis header and exits")
flag.BoolVar(&UseSeed, "seed", true, "seed peers")
flag.BoolVar(&GenAddr, "genaddr", false, "create a new priv/pub key")
flag.BoolVar(&ExportKey, "export", false, "export private key")
flag.StringVar(&ImportKey, "import", "", "imports the given private key (hex)")
flag.StringVar(&Datadir, "datadir", ".ethereal", "specifies the datadir to use. Takes precedence over config file.")
flag.Parse()
}

View File

@ -1,142 +0,0 @@
package main
import (
"fmt"
"github.com/ethereum/eth-go"
"github.com/ethereum/eth-go/ethutil"
"github.com/ethereum/go-ethereum/ethereal/ui"
"github.com/ethereum/go-ethereum/utils"
"github.com/go-qml/qml"
"github.com/rakyll/globalconf"
"log"
"os"
"os/signal"
"path"
"runtime"
)
const Debug = true
// Register interrupt handlers so we can stop the ethereum
func RegisterInterupts(s *eth.Ethereum) {
// Buffered chan of one is enough
c := make(chan os.Signal, 1)
// Notify about interrupts for now
signal.Notify(c, os.Interrupt)
go func() {
for sig := range c {
fmt.Printf("Shutting down (%v) ... \n", sig)
s.Stop()
}
}()
}
func main() {
Init()
qml.Init(nil)
runtime.GOMAXPROCS(runtime.NumCPU())
g, err := globalconf.NewWithOptions(&globalconf.Options{
Filename: path.Join(ethutil.ApplicationFolder(Datadir), "conf.ini"),
})
if err != nil {
fmt.Println(err)
} else {
g.ParseAll()
}
ethutil.ReadConfig(Datadir, ethutil.LogFile|ethutil.LogStd, g, Identifier)
// Instantiated a eth stack
ethereum, err := eth.New(eth.CapDefault, UseUPnP)
if err != nil {
log.Println("eth start err:", err)
return
}
ethereum.Port = OutboundPort
if GenAddr {
fmt.Println("This action overwrites your old private key. Are you sure? (y/n)")
var r string
fmt.Scanln(&r)
for ; ; fmt.Scanln(&r) {
if r == "n" || r == "y" {
break
} else {
fmt.Printf("Yes or no?", r)
}
}
if r == "y" {
utils.CreateKeyPair(true)
}
os.Exit(0)
} else {
if len(ImportKey) > 0 {
fmt.Println("This action overwrites your old private key. Are you sure? (y/n)")
var r string
fmt.Scanln(&r)
for ; ; fmt.Scanln(&r) {
if r == "n" || r == "y" {
break
} else {
fmt.Printf("Yes or no?", r)
}
}
if r == "y" {
utils.ImportPrivateKey(ImportKey)
os.Exit(0)
}
}
}
if ExportKey {
keyPair := ethutil.GetKeyRing().Get(0)
fmt.Printf(`
Generating new address and keypair.
Please keep your keys somewhere save.
++++++++++++++++ KeyRing +++++++++++++++++++
addr: %x
prvk: %x
pubk: %x
++++++++++++++++++++++++++++++++++++++++++++
save these words so you can restore your account later: %s
`, keyPair.Address(), keyPair.PrivateKey, keyPair.PublicKey)
os.Exit(0)
}
if ShowGenesis {
fmt.Println(ethereum.BlockChain().Genesis())
os.Exit(0)
}
/*
if StartMining {
utils.DoMining(ethereum)
}
*/
if StartRpc {
utils.DoRpc(ethereum, RpcPort)
}
log.Printf("Starting Ethereum GUI v%s\n", ethutil.Config.Ver)
// Set the max peers
ethereum.MaxPeers = MaxPeer
gui := ethui.New(ethereum)
ethereum.Start(UseSeed)
gui.Start(AssetPath)
// Wait for shutdown
ethereum.WaitForShutdown()
}

95
ethereal/flags.go Normal file
View File

@ -0,0 +1,95 @@
package main
import (
"bitbucket.org/kardianos/osext"
"flag"
"fmt"
"github.com/ethereum/eth-go/ethlog"
"os"
"os/user"
"path"
"path/filepath"
"runtime"
)
var Identifier string
var StartRpc bool
var RpcPort int
var UseUPnP bool
var OutboundPort string
var ShowGenesis bool
var AddPeer string
var MaxPeer int
var GenAddr bool
var UseSeed bool
var ImportKey string
var ExportKey bool
var NonInteractive bool
var Datadir string
var LogFile string
var ConfigFile string
var DebugFile string
var LogLevel int
// flags specific to gui client
var AssetPath string
func defaultAssetPath() string {
var assetPath string
// If the current working directory is the go-ethereum dir
// assume a debug build and use the source directory as
// asset directory.
pwd, _ := os.Getwd()
if pwd == path.Join(os.Getenv("GOPATH"), "src", "github.com", "ethereum", "go-ethereum", "ethereal") {
assetPath = path.Join(pwd, "assets")
} else {
switch runtime.GOOS {
case "darwin":
// Get Binary Directory
exedir, _ := osext.ExecutableFolder()
assetPath = filepath.Join(exedir, "../Resources")
case "linux":
assetPath = "/usr/share/ethereal"
case "window":
fallthrough
default:
assetPath = "."
}
}
return assetPath
}
func defaultDataDir() string {
usr, _ := user.Current()
return path.Join(usr.HomeDir, ".ethereal")
}
var defaultConfigFile = path.Join(defaultDataDir(), "conf.ini")
func Init() {
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.StringVar(&Identifier, "id", "", "Custom client identifier")
flag.StringVar(&OutboundPort, "port", "30303", "listening port")
flag.BoolVar(&UseUPnP, "upnp", false, "enable UPnP support")
flag.IntVar(&MaxPeer, "maxpeer", 10, "maximum desired peers")
flag.IntVar(&RpcPort, "rpcport", 8080, "port to start json-rpc server on")
flag.BoolVar(&StartRpc, "rpc", false, "start rpc server")
flag.BoolVar(&NonInteractive, "y", false, "non-interactive mode (say yes to confirmations)")
flag.BoolVar(&UseSeed, "seed", true, "seed peers")
flag.BoolVar(&GenAddr, "genaddr", false, "create a new priv/pub key")
flag.BoolVar(&ExportKey, "export", false, "export private key")
flag.StringVar(&LogFile, "logfile", "", "log file (defaults to standard output)")
flag.StringVar(&ImportKey, "import", "", "imports the given private key (hex)")
flag.StringVar(&Datadir, "datadir", 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(ethlog.InfoLevel), "loglevel: 0-5: silent,error,warn,info,debug,debug detail)")
flag.StringVar(&AssetPath, "asset_path", defaultAssetPath(), "absolute path to GUI assets directory")
flag.Parse()
}

61
ethereal/main.go Normal file
View File

@ -0,0 +1,61 @@
package main
import (
"github.com/ethereum/eth-go/ethlog"
"github.com/ethereum/go-ethereum/ethereal/ui"
"github.com/ethereum/go-ethereum/utils"
"github.com/go-qml/qml"
"os"
"runtime"
)
func main() {
runtime.GOMAXPROCS(runtime.NumCPU())
qml.Init(nil)
var interrupted = false
utils.RegisterInterrupt(func(os.Signal) {
interrupted = true
})
utils.HandleInterrupt()
// precedence: code-internal flag default < config file < environment variables < command line
Init() // parsing command line
utils.InitConfig(ConfigFile, Datadir, Identifier, "ETH")
utils.InitDataDir(Datadir)
utils.InitLogging(Datadir, LogFile, LogLevel, DebugFile)
ethereum := utils.NewEthereum(UseUPnP, OutboundPort, MaxPeer)
// create, import, export keys
utils.KeyTasks(GenAddr, ImportKey, ExportKey, NonInteractive)
if ShowGenesis {
utils.ShowGenesis(ethereum)
}
if StartRpc {
utils.StartRpc(ethereum, RpcPort)
}
gui := ethui.New(ethereum, LogLevel)
utils.RegisterInterrupt(func(os.Signal) {
gui.Stop()
})
utils.StartEthereum(ethereum, UseSeed)
// gui blocks the main thread
gui.Start(AssetPath)
// 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 {
utils.RunInterruptCallbacks(os.Interrupt)
}
// this blocks the thread
ethereum.WaitForShutdown()
ethlog.Flush()
}

View File

@ -26,7 +26,7 @@ func NewDebuggerWindow(lib *UiLib) *DebuggerWindow {
}
win := component.CreateWindow(nil)
db := &Debugger{win, make(chan bool), make(chan bool), true, false}
db := &Debugger{win, make(chan bool), make(chan bool), true, false, true}
return &DebuggerWindow{engine: engine, win: win, lib: lib, Db: db}
}
@ -59,6 +59,7 @@ func (self *DebuggerWindow) Debug(valueStr, gasStr, gasPriceStr, scriptStr, data
if !self.Db.done {
self.Db.Q <- true
}
self.Db.breakOnInstr = self.win.Root().ObjectByName("breakEachLine").Bool("checked")
defer func() {
if r := recover(); r != nil {
@ -78,7 +79,6 @@ func (self *DebuggerWindow) Debug(valueStr, gasStr, gasPriceStr, scriptStr, data
var err error
script := ethutil.StringToByteFunc(scriptStr, func(s string) (ret []byte) {
ret, err = ethutil.Compile(s)
fmt.Printf("%x\n", ret)
return
})
@ -96,28 +96,34 @@ func (self *DebuggerWindow) Debug(valueStr, gasStr, gasPriceStr, scriptStr, data
self.win.Root().Call("setAsm", str)
}
gas := ethutil.Big(gasStr)
gasPrice := ethutil.Big(gasPriceStr)
// Contract addr as test address
keyPair := ethutil.GetKeyRing().Get(0)
callerTx := ethchain.NewContractCreationTx(ethutil.Big(valueStr), gas, gasPrice, script)
var (
gas = ethutil.Big(gasStr)
gasPrice = ethutil.Big(gasPriceStr)
value = ethutil.Big(valueStr)
// Contract addr as test address
keyPair = ethutil.GetKeyRing().Get(0)
callerTx = ethchain.NewContractCreationTx(ethutil.Big(valueStr), gas, gasPrice, script)
)
callerTx.Sign(keyPair.PrivateKey)
state := self.lib.eth.BlockChain().CurrentBlock.State()
account := self.lib.eth.StateManager().TransState().GetAccount(keyPair.Address())
contract := ethchain.MakeContract(callerTx, state)
contract.Amount = value
callerClosure := ethchain.NewClosure(account, contract, script, state, gas, gasPrice)
block := self.lib.eth.BlockChain().CurrentBlock
vm := ethchain.NewVm(state, self.lib.eth.StateManager(), ethchain.RuntimeVars{
Block: block,
Origin: account.Address(),
BlockNumber: block.BlockInfo().Number,
BlockNumber: block.Number,
PrevHash: block.PrevHash,
Coinbase: block.Coinbase,
Time: block.Time,
Diff: block.Difficulty,
Value: ethutil.Big(valueStr),
})
vm.Verbose = true
self.Db.done = false
self.Logf("callsize %d", len(script))
@ -163,6 +169,7 @@ type Debugger struct {
N chan bool
Q chan bool
done, interrupt bool
breakOnInstr bool
}
type storeVal struct {
@ -189,16 +196,18 @@ func (d *Debugger) halting(pc int, op ethchain.OpCode, mem *ethchain.Memory, sta
d.win.Root().Call("setStorage", storeVal{fmt.Sprintf("% x", key), fmt.Sprintf("% x", node.Str())})
})
out:
for {
select {
case <-d.N:
break out
case <-d.Q:
d.interrupt = true
d.clearBuffers()
if d.breakOnInstr {
out:
for {
select {
case <-d.N:
break out
case <-d.Q:
d.interrupt = true
d.clearBuffers()
return false
return false
}
}
}

View File

@ -6,6 +6,7 @@ import (
"github.com/ethereum/eth-go"
"github.com/ethereum/eth-go/ethchain"
"github.com/ethereum/eth-go/ethdb"
"github.com/ethereum/eth-go/ethlog"
"github.com/ethereum/eth-go/ethpub"
"github.com/ethereum/eth-go/ethutil"
"github.com/ethereum/go-ethereum/utils"
@ -15,6 +16,8 @@ import (
"time"
)
var logger = ethlog.NewLogger("GUI")
type Gui struct {
// The main application window
win *qml.Window
@ -32,11 +35,13 @@ type Gui struct {
addr []byte
pub *ethpub.PEthereum
pub *ethpub.PEthereum
logLevel ethlog.LogLevel
open bool
}
// Create GUI, but doesn't start it
func New(ethereum *eth.Ethereum) *Gui {
func New(ethereum *eth.Ethereum, logLevel int) *Gui {
lib := &EthLib{stateManager: ethereum.StateManager(), blockChain: ethereum.BlockChain(), txPool: ethereum.TxPool()}
db, err := ethdb.NewLDBDatabase("tx_database")
if err != nil {
@ -52,11 +57,11 @@ func New(ethereum *eth.Ethereum) *Gui {
pub := ethpub.NewPEthereum(ethereum)
return &Gui{eth: ethereum, lib: lib, txDb: db, addr: addr, pub: pub}
return &Gui{eth: ethereum, lib: lib, txDb: db, addr: addr, pub: pub, logLevel: ethlog.LogLevel(logLevel), open: false}
}
func (gui *Gui) Start(assetPath string) {
const version = "0.5.0 RC13"
const version = "0.5.0 RC15"
defer gui.txDb.Close()
@ -86,25 +91,39 @@ func (gui *Gui) Start(assetPath string) {
var win *qml.Window
var err error
var addlog = false
if len(data) == 0 {
win, err = gui.showKeyImport(context)
} else {
win, err = gui.showWallet(context)
ethutil.Config.Log.AddLogSystem(gui)
addlog = true
}
if err != nil {
ethutil.Config.Log.Infoln("FATAL: asset not found: you can set an alternative asset path on on the command line using option 'asset_path'", err)
logger.Errorln("asset not found: you can set an alternative asset path on the command line using option 'asset_path'", err)
panic(err)
}
ethutil.Config.Log.Infoln("[GUI] Starting GUI")
logger.Infoln("Starting GUI")
gui.open = true
win.Show()
// only add the gui logger after window is shown otherwise slider wont be shown
if addlog {
ethlog.AddLogSystem(gui)
}
win.Wait()
// need to silence gui logger after window closed otherwise logsystem hangs
gui.SetLogLevel(ethlog.Silence)
gui.open = false
}
gui.eth.Stop()
func (gui *Gui) Stop() {
if gui.open {
gui.SetLogLevel(ethlog.Silence)
gui.open = false
gui.win.Hide()
}
logger.Infoln("Stopped")
}
func (gui *Gui) ToggleMining() {
@ -154,10 +173,6 @@ func (gui *Gui) createWindow(comp qml.Object) *qml.Window {
gui.win = win
gui.uiLib.win = win
db := &Debugger{gui.win, make(chan bool), make(chan bool), true, false}
gui.lib.Db = db
gui.uiLib.Db = db
return gui.win
}
func (gui *Gui) setInitialBlockChain() {
@ -315,22 +330,6 @@ func (gui *Gui) setPeerInfo() {
}
}
// Logging functions that log directly to the GUI interface
func (gui *Gui) Println(v ...interface{}) {
str := strings.TrimRight(fmt.Sprintln(v...), "\n")
lines := strings.Split(str, "\n")
for _, line := range lines {
gui.win.Root().Call("addLog", line)
}
}
func (gui *Gui) Printf(format string, v ...interface{}) {
str := strings.TrimRight(fmt.Sprintf(format, v...), "\n")
lines := strings.Split(str, "\n")
for _, line := range lines {
gui.win.Root().Call("addLog", line)
}
}
func (gui *Gui) RegisterName(name string) {
keyPair := ethutil.GetKeyRing().Get(0)
name = fmt.Sprintf("\"%s\"\n1", name)
@ -357,6 +356,34 @@ func (gui *Gui) ClientId() string {
return ethutil.Config.Identifier
}
func (gui *Gui) SetLogLevel(level int) {
ethutil.Config.Log.SetLevel(level)
// functions that allow Gui to implement interface ethlog.LogSystem
func (gui *Gui) SetLogLevel(level ethlog.LogLevel) {
gui.logLevel = level
}
func (gui *Gui) GetLogLevel() ethlog.LogLevel {
return gui.logLevel
}
// 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 (gui *Gui) Println(v ...interface{}) {
gui.printLog(fmt.Sprintln(v...))
}
func (gui *Gui) Printf(format string, v ...interface{}) {
gui.printLog(fmt.Sprintf(format, v...))
}
// Print function that logs directly to the GUI
func (gui *Gui) printLog(s string) {
str := strings.TrimRight(s, "\n")
lines := strings.Split(str, "\n")
for _, line := range lines {
gui.win.Root().Call("addLog", line)
}
}

View File

@ -96,11 +96,11 @@ func (app *HtmlApplication) NewWatcher(quitChan chan bool) {
app.watcher.Close()
break out
case <-app.watcher.Event:
//ethutil.Config.Log.Debugln("Got event:", ev)
//logger.Debugln("Got event:", ev)
app.webView.Call("reload")
case err := <-app.watcher.Error:
// TODO: Do something here
ethutil.Config.Log.Infoln("Watcher error:", err)
logger.Infoln("Watcher error:", err)
}
}
}()

59
ethereal/ui/qml_app.go Normal file
View File

@ -0,0 +1,59 @@
package ethui
import (
"github.com/ethereum/eth-go/ethchain"
"github.com/ethereum/eth-go/ethpub"
"github.com/ethereum/eth-go/ethutil"
"github.com/go-qml/qml"
)
type QmlApplication struct {
win *qml.Window
engine *qml.Engine
lib *UiLib
path string
}
func NewQmlApplication(path string, lib *UiLib) *QmlApplication {
engine := qml.NewEngine()
return &QmlApplication{engine: engine, path: path, lib: lib}
}
func (app *QmlApplication) Create() error {
component, err := app.engine.LoadFile(app.path)
if err != nil {
logger.Warnln(err)
}
app.win = component.CreateWindow(nil)
return nil
}
func (app *QmlApplication) Destroy() {
app.engine.Destroy()
}
func (app *QmlApplication) NewWatcher(quitChan chan bool) {
}
// Events
func (app *QmlApplication) NewBlock(block *ethchain.Block) {
pblock := &ethpub.PBlock{Number: int(block.BlockInfo().Number), Hash: ethutil.Hex(block.Hash())}
app.win.Call("onNewBlockCb", pblock)
}
func (app *QmlApplication) ObjectChanged(stateObject *ethchain.StateObject) {
app.win.Call("onObjectChangeCb", ethpub.NewPStateObject(stateObject))
}
func (app *QmlApplication) StorageChanged(storageObject *ethchain.StorageState) {
app.win.Call("onStorageChangeCb", ethpub.NewPStorageState(storageObject))
}
// Getters
func (app *QmlApplication) Engine() *qml.Engine {
return app.engine
}
func (app *QmlApplication) Window() *qml.Window {
return app.win
}

View File

@ -1,15 +1,10 @@
package ethui
import (
"bitbucket.org/kardianos/osext"
"github.com/ethereum/eth-go"
"github.com/ethereum/eth-go/ethchain"
"github.com/ethereum/eth-go/ethutil"
"github.com/go-qml/qml"
"os"
"path"
"path/filepath"
"runtime"
)
type memAddr struct {
@ -30,24 +25,14 @@ type UiLib struct {
}
func NewUiLib(engine *qml.Engine, eth *eth.Ethereum, assetPath string) *UiLib {
if assetPath == "" {
assetPath = DefaultAssetPath()
}
return &UiLib{engine: engine, eth: eth, assetPath: assetPath}
}
// Opens a QML file (external application)
func (ui *UiLib) Open(path string) {
component, err := ui.engine.LoadFile(path[7:])
if err != nil {
ethutil.Config.Log.Debugln(err)
}
win := component.CreateWindow(nil)
func (ui *UiLib) OpenQml(path string) {
container := NewQmlApplication(path[7:], ui)
app := NewExtApplication(container, ui)
go func() {
win.Show()
win.Wait()
}()
go app.run()
}
func (ui *UiLib) OpenHtml(path string) {
@ -60,7 +45,7 @@ func (ui *UiLib) OpenHtml(path string) {
func (ui *UiLib) Muted(content string) {
component, err := ui.engine.LoadFile(ui.AssetPath("qml/muted.qml"))
if err != nil {
ethutil.Config.Log.Debugln(err)
logger.Debugln(err)
return
}
@ -89,6 +74,7 @@ func (ui *UiLib) ConnectToPeer(addr string) {
func (ui *UiLib) AssetPath(p string) string {
return path.Join(ui.assetPath, p)
}
func (self *UiLib) StartDbWithContractAndData(contractHash, data string) {
dbWindow := NewDebuggerWindow(self)
object := self.eth.StateManager().CurrentState().GetStateObject(ethutil.FromHex(contractHash))
@ -112,79 +98,3 @@ func (self *UiLib) StartDebugger() {
dbWindow.Show()
}
func DefaultAssetPath() string {
var base string
// If the current working directory is the go-ethereum dir
// assume a debug build and use the source directory as
// asset directory.
pwd, _ := os.Getwd()
if pwd == path.Join(os.Getenv("GOPATH"), "src", "github.com", "ethereum", "go-ethereum", "ethereal") {
base = path.Join(pwd, "assets")
} else {
switch runtime.GOOS {
case "darwin":
// Get Binary Directory
exedir, _ := osext.ExecutableFolder()
base = filepath.Join(exedir, "../Resources")
case "linux":
base = "/usr/share/ethereal"
case "window":
fallthrough
default:
base = "."
}
}
return base
}
func (ui *UiLib) DebugTx(recipient, valueStr, gasStr, gasPriceStr, data string) {
state := ui.eth.BlockChain().CurrentBlock.State()
script, err := ethutil.Compile(data)
if err != nil {
ethutil.Config.Log.Debugln(err)
return
}
dis := ethchain.Disassemble(script)
ui.win.Root().Call("clearAsm")
for _, str := range dis {
ui.win.Root().Call("setAsm", str)
}
// Contract addr as test address
keyPair := ethutil.GetKeyRing().Get(0)
callerTx :=
ethchain.NewContractCreationTx(ethutil.Big(valueStr), ethutil.Big(gasStr), ethutil.Big(gasPriceStr), script)
callerTx.Sign(keyPair.PrivateKey)
account := ui.eth.StateManager().TransState().GetStateObject(keyPair.Address())
contract := ethchain.MakeContract(callerTx, state)
callerClosure := ethchain.NewClosure(account, contract, contract.Init(), state, ethutil.Big(gasStr), ethutil.Big(gasPriceStr))
block := ui.eth.BlockChain().CurrentBlock
vm := ethchain.NewVm(state, ui.eth.StateManager(), ethchain.RuntimeVars{
Origin: account.Address(),
BlockNumber: block.BlockInfo().Number,
PrevHash: block.PrevHash,
Coinbase: block.Coinbase,
Time: block.Time,
Diff: block.Difficulty,
})
ui.Db.done = false
go func() {
callerClosure.Call(vm, contract.Init(), ui.Db.halting)
state.Reset()
ui.Db.done = true
}()
}
func (ui *UiLib) Next() {
ui.Db.Next()
}

32
ethereum/cmd.go Normal file
View File

@ -0,0 +1,32 @@
package main
import (
"github.com/ethereum/eth-go"
"github.com/ethereum/go-ethereum/utils"
"io/ioutil"
"os"
)
func InitJsConsole(ethereum *eth.Ethereum) {
repl := NewJSRepl(ethereum)
go repl.Start()
utils.RegisterInterrupt(func(os.Signal) {
repl.Stop()
})
}
func ExecJsFile(ethereum *eth.Ethereum, InputFile string) {
file, err := os.Open(InputFile)
if err != nil {
logger.Fatalln(err)
}
content, err := ioutil.ReadAll(file)
if err != nil {
logger.Fatalln(err)
}
re := NewJSRE(ethereum)
utils.RegisterInterrupt(func(os.Signal) {
re.Stop()
})
re.Run(string(content))
}

View File

@ -1,193 +0,0 @@
package main
import (
"fmt"
"github.com/ethereum/eth-go"
"github.com/ethereum/eth-go/ethutil"
"github.com/ethereum/go-ethereum/utils"
"github.com/rakyll/globalconf"
"io/ioutil"
"log"
"os"
"os/signal"
"path"
"runtime"
"strings"
)
const Debug = true
func RegisterInterrupt(cb func(os.Signal)) {
go func() {
// Buffered chan of one is enough
c := make(chan os.Signal, 1)
// Notify about interrupts for now
signal.Notify(c, os.Interrupt)
for sig := range c {
cb(sig)
}
}()
}
func confirm(message string) bool {
fmt.Println(message, "Are you sure? (y/n)")
var r string
fmt.Scanln(&r)
for ; ; fmt.Scanln(&r) {
if r == "n" || r == "y" {
break
} else {
fmt.Printf("Yes or no?", r)
}
}
return r == "y"
}
func main() {
Init()
runtime.GOMAXPROCS(runtime.NumCPU())
// set logger
var logSys *log.Logger
flags := log.LstdFlags
var lt ethutil.LoggerType
if StartJsConsole || len(InputFile) > 0 {
lt = ethutil.LogFile
} else {
lt = ethutil.LogFile | ethutil.LogStd
}
g, err := globalconf.NewWithOptions(&globalconf.Options{
Filename: path.Join(ethutil.ApplicationFolder(Datadir), "conf.ini"),
})
if err != nil {
fmt.Println(err)
} else {
g.ParseAll()
}
ethutil.ReadConfig(Datadir, lt, g, Identifier)
logger := ethutil.Config.Log
if LogFile != "" {
logfile, err := os.OpenFile(LogFile, os.O_RDWR|os.O_CREATE|os.O_APPEND, 0666)
if err != nil {
panic(fmt.Sprintf("error opening log file '%s': %v", LogFile, err))
}
defer logfile.Close()
log.SetOutput(logfile)
logSys = log.New(logfile, "", flags)
logger.AddLogSystem(logSys)
} else {
logSys = log.New(os.Stdout, "", flags)
}
// Instantiated a eth stack
ethereum, err := eth.New(eth.CapDefault, UseUPnP)
if err != nil {
log.Println("eth start err:", err)
return
}
ethereum.Port = OutboundPort
// bookkeeping tasks
switch {
case GenAddr:
if NonInteractive || confirm("This action overwrites your old private key.") {
utils.CreateKeyPair(true)
}
os.Exit(0)
case len(ImportKey) > 0:
if NonInteractive || confirm("This action overwrites your old private key.") {
mnemonic := strings.Split(ImportKey, " ")
if len(mnemonic) == 24 {
logSys.Println("Got mnemonic key, importing.")
key := ethutil.MnemonicDecode(mnemonic)
utils.ImportPrivateKey(key)
} else if len(mnemonic) == 1 {
logSys.Println("Got hex key, importing.")
utils.ImportPrivateKey(ImportKey)
} else {
logSys.Println("Did not recognise format, exiting.")
}
}
os.Exit(0)
case ExportKey:
keyPair := ethutil.GetKeyRing().Get(0)
fmt.Printf(`
Generating new address and keypair.
Please keep your keys somewhere save.
++++++++++++++++ KeyRing +++++++++++++++++++
addr: %x
prvk: %x
pubk: %x
++++++++++++++++++++++++++++++++++++++++++++
save these words so you can restore your account later: %s
`, keyPair.Address(), keyPair.PrivateKey, keyPair.PublicKey)
os.Exit(0)
case ShowGenesis:
logSys.Println(ethereum.BlockChain().Genesis())
os.Exit(0)
default:
// Creates a keypair if non exists
utils.CreateKeyPair(false)
}
// client
logger.Infoln(fmt.Sprintf("Starting Ethereum v%s", ethutil.Config.Ver))
// Set the max peers
ethereum.MaxPeers = MaxPeer
// Set Mining status
ethereum.Mining = StartMining
if StartMining {
utils.DoMining(ethereum)
}
if StartJsConsole {
repl := NewJSRepl(ethereum)
go repl.Start()
RegisterInterrupt(func(os.Signal) {
repl.Stop()
})
} else if len(InputFile) > 0 {
file, err := os.Open(InputFile)
if err != nil {
ethutil.Config.Log.Fatal(err)
}
content, err := ioutil.ReadAll(file)
if err != nil {
ethutil.Config.Log.Fatal(err)
}
re := NewJSRE(ethereum)
RegisterInterrupt(func(os.Signal) {
re.Stop()
})
re.Run(string(content))
}
if StartRpc {
utils.DoRpc(ethereum, RpcPort)
}
RegisterInterrupt(func(sig os.Signal) {
fmt.Printf("Shutting down (%v) ... \n", sig)
ethereum.Stop()
})
ethereum.Start(UseSeed)
// Wait for shutdown
ethereum.WaitForShutdown()
}

View File

@ -3,11 +3,13 @@ package main
import (
"flag"
"fmt"
"github.com/ethereum/eth-go/ethlog"
"os"
"os/user"
"path"
)
var Identifier string
var StartMining bool
var StartRpc bool
var RpcPort int
var UseUPnP bool
@ -19,16 +21,28 @@ var GenAddr bool
var UseSeed bool
var ImportKey string
var ExportKey bool
var LogFile string
var NonInteractive bool
var Datadir string
var LogFile string
var ConfigFile string
var DebugFile string
var LogLevel int
// flags specific to cli client
var StartMining bool
var StartJsConsole bool
var InputFile string
var Datadir string
func defaultDataDir() string {
usr, _ := user.Current()
return path.Join(usr.HomeDir, ".ethereum")
}
var defaultConfigFile = path.Join(defaultDataDir(), "conf.ini")
func Init() {
flag.Usage = func() {
fmt.Fprintf(os.Stderr, "%s [options] [filename]:\n", os.Args[0])
fmt.Fprintf(os.Stderr, "%s [options] [filename]:\noptions precedence: default < config file < environment variables < command line\n", os.Args[0])
flag.PrintDefaults()
}
@ -38,17 +52,19 @@ func Init() {
flag.IntVar(&MaxPeer, "maxpeer", 10, "maximum desired peers")
flag.IntVar(&RpcPort, "rpcport", 8080, "port to start json-rpc server on")
flag.BoolVar(&StartRpc, "rpc", false, "start rpc server")
flag.BoolVar(&StartJsConsole, "js", false, "exp")
flag.BoolVar(&StartMining, "mine", false, "start dagger mining")
flag.BoolVar(&NonInteractive, "y", false, "non-interactive mode (say yes to confirmations)")
flag.BoolVar(&UseSeed, "seed", true, "seed peers")
flag.BoolVar(&GenAddr, "genaddr", false, "create a new priv/pub key")
flag.BoolVar(&ExportKey, "export", false, "export private key")
flag.StringVar(&LogFile, "logfile", "", "log file (defaults to standard output)")
flag.StringVar(&ImportKey, "import", "", "imports the given private key (hex)")
flag.StringVar(&Datadir, "datadir", 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(ethlog.InfoLevel), "loglevel: 0-5: silent,error,warn,info,debug,debug detail)")
flag.StringVar(&Datadir, "datadir", ".ethereum", "specifies the datadir to use. Takes precedence over config file.")
flag.BoolVar(&StartMining, "mine", false, "start dagger mining")
flag.BoolVar(&StartJsConsole, "js", false, "launches javascript console")
flag.Parse()

View File

@ -4,6 +4,7 @@ import (
"fmt"
"github.com/ethereum/eth-go"
"github.com/ethereum/eth-go/ethchain"
"github.com/ethereum/eth-go/ethlog"
"github.com/ethereum/eth-go/ethpub"
"github.com/ethereum/eth-go/ethutil"
"github.com/ethereum/go-ethereum/utils"
@ -14,6 +15,8 @@ import (
"path/filepath"
)
var jsrelogger = ethlog.NewLogger("JSRE")
type JSRE struct {
ethereum *eth.Ethereum
vm *otto.Otto
@ -31,7 +34,7 @@ func (jsre *JSRE) LoadExtFile(path string) {
if err == nil {
jsre.vm.Run(result)
} else {
ethutil.Config.Log.Debugln("Could not load file:", path)
jsrelogger.Debugln("Could not load file:", path)
}
}
@ -65,6 +68,8 @@ func NewJSRE(ethereum *eth.Ethereum) *JSRE {
re.initStdFuncs()
jsrelogger.Infoln("started")
return re
}
@ -99,6 +104,7 @@ func (self *JSRE) Stop() {
close(self.blockChan)
close(self.quitChan)
close(self.changeChan)
jsrelogger.Infoln("stopped")
}
func (self *JSRE) mainLoop() {
@ -138,6 +144,7 @@ func (self *JSRE) initStdFuncs() {
eth.Set("require", self.require)
eth.Set("stopMining", self.stopMining)
eth.Set("startMining", self.startMining)
eth.Set("execBlock", self.execBlock)
}
/*
@ -207,3 +214,18 @@ func (self *JSRE) require(call otto.FunctionCall) otto.Value {
return t
}
func (self *JSRE) execBlock(call otto.FunctionCall) otto.Value {
hash, err := call.Argument(0).ToString()
if err != nil {
return otto.UndefinedValue()
}
err = utils.BlockDo(self.ethereum, ethutil.FromHex(hash))
if err != nil {
fmt.Println(err)
return otto.FalseValue()
}
return otto.TrueValue()
}

53
ethereum/main.go Normal file
View File

@ -0,0 +1,53 @@
package main
import (
"github.com/ethereum/eth-go/ethlog"
"github.com/ethereum/go-ethereum/utils"
"runtime"
)
var logger = ethlog.NewLogger("CLI")
func main() {
runtime.GOMAXPROCS(runtime.NumCPU())
utils.HandleInterrupt()
// precedence: code-internal flag default < config file < environment variables < command line
Init() // parsing command line
utils.InitConfig(ConfigFile, Datadir, Identifier, "ETH")
utils.InitDataDir(Datadir)
utils.InitLogging(Datadir, LogFile, LogLevel, DebugFile)
ethereum := utils.NewEthereum(UseUPnP, OutboundPort, MaxPeer)
// create, import, export keys
utils.KeyTasks(GenAddr, ImportKey, ExportKey, NonInteractive)
if ShowGenesis {
utils.ShowGenesis(ethereum)
}
if StartMining {
utils.StartMining(ethereum)
}
// better reworked as cases
if StartJsConsole {
InitJsConsole(ethereum)
} else if len(InputFile) > 0 {
ExecJsFile(ethereum, InputFile)
}
if StartRpc {
utils.StartRpc(ethereum, RpcPort)
}
utils.StartEthereum(ethereum, UseSeed)
// this blocks the thread
ethereum.WaitForShutdown()
ethlog.Flush()
}

View File

@ -1,10 +1,15 @@
package main
import (
"bufio"
"fmt"
"github.com/ethereum/eth-go"
"github.com/ethereum/eth-go/ethpub"
"github.com/ethereum/eth-go/ethutil"
"github.com/obscuren/otto"
"io"
"os"
"path"
)
type Repl interface {
@ -16,18 +21,48 @@ type JSRepl struct {
re *JSRE
prompt string
history *os.File
running bool
}
func NewJSRepl(ethereum *eth.Ethereum) *JSRepl {
return &JSRepl{re: NewJSRE(ethereum), prompt: "> "}
hist, err := os.OpenFile(path.Join(ethutil.Config.ExecPath, "history"), os.O_RDWR|os.O_CREATE, os.ModePerm)
if err != nil {
panic(err)
}
return &JSRepl{re: NewJSRE(ethereum), prompt: "> ", history: hist}
}
func (self *JSRepl) Start() {
self.read()
if !self.running {
self.running = true
logger.Infoln("init JS Console")
reader := bufio.NewReader(self.history)
for {
line, err := reader.ReadString('\n')
if err != nil && err == io.EOF {
break
} else if err != nil {
fmt.Println("error reading history", err)
break
}
addHistory(line[:len(line)-1])
}
self.read()
}
}
func (self *JSRepl) Stop() {
self.re.Stop()
if self.running {
self.running = false
self.re.Stop()
logger.Infoln("exit JS Console")
self.history.Close()
}
}
func (self *JSRepl) parseInput(code string) {

View File

@ -102,7 +102,9 @@ L:
break L
}
addHistory(str[:len(str)-1]) //allow user to recall this line
hist := str[:len(str)-1]
addHistory(hist) //allow user to recall this line
self.history.WriteString(str)
self.parseInput(str)

View File

@ -1,19 +1,186 @@
package utils
import (
"fmt"
"github.com/ethereum/eth-go"
"github.com/ethereum/eth-go/ethlog"
"github.com/ethereum/eth-go/ethminer"
"github.com/ethereum/eth-go/ethpub"
"github.com/ethereum/eth-go/ethrpc"
"github.com/ethereum/eth-go/ethutil"
"io"
"log"
"os"
"os/signal"
"path"
"strings"
"time"
)
func DoRpc(ethereum *eth.Ethereum, RpcPort int) {
var logger = ethlog.NewLogger("CLI")
var interruptCallbacks = []func(os.Signal){}
// Register interrupt handlers callbacks
func RegisterInterrupt(cb func(os.Signal)) {
interruptCallbacks = append(interruptCallbacks, cb)
}
// go routine that call interrupt handlers in order of registering
func HandleInterrupt() {
c := make(chan os.Signal, 1)
go func() {
signal.Notify(c, os.Interrupt)
for sig := range c {
logger.Errorf("Shutting down (%v) ... \n", sig)
RunInterruptCallbacks(sig)
}
}()
}
func RunInterruptCallbacks(sig os.Signal) {
for _, cb := range interruptCallbacks {
cb(sig)
}
}
func AbsolutePath(Datadir string, filename string) string {
if path.IsAbs(filename) {
return filename
}
return path.Join(Datadir, filename)
}
func openLogFile(Datadir string, filename string) *os.File {
path := AbsolutePath(Datadir, filename)
file, err := os.OpenFile(path, os.O_RDWR|os.O_CREATE|os.O_APPEND, 0666)
if err != nil {
panic(fmt.Sprintf("error opening log file '%s': %v", filename, err))
}
return file
}
func confirm(message string) bool {
fmt.Println(message, "Are you sure? (y/n)")
var r string
fmt.Scanln(&r)
for ; ; fmt.Scanln(&r) {
if r == "n" || r == "y" {
break
} else {
fmt.Printf("Yes or no?", r)
}
}
return r == "y"
}
func InitDataDir(Datadir string) {
_, err := os.Stat(Datadir)
if err != nil {
if os.IsNotExist(err) {
fmt.Printf("Debug logging directory '%s' doesn't exist, creating it\n", Datadir)
os.Mkdir(Datadir, 0777)
}
}
}
func InitLogging(Datadir string, LogFile string, LogLevel int, DebugFile string) {
var writer io.Writer
if LogFile == "" {
writer = os.Stdout
} else {
writer = openLogFile(Datadir, LogFile)
}
ethlog.AddLogSystem(ethlog.NewStdLogSystem(writer, log.LstdFlags, ethlog.LogLevel(LogLevel)))
if DebugFile != "" {
writer = openLogFile(Datadir, DebugFile)
ethlog.AddLogSystem(ethlog.NewStdLogSystem(writer, log.LstdFlags, ethlog.DebugLevel))
}
}
func InitConfig(ConfigFile string, Datadir string, Identifier string, EnvPrefix string) {
InitDataDir(Datadir)
ethutil.ReadConfig(ConfigFile, Datadir, Identifier, EnvPrefix)
ethutil.Config.Set("rpcport", "700")
}
func exit(status int) {
ethlog.Flush()
os.Exit(status)
}
func NewEthereum(UseUPnP bool, OutboundPort string, MaxPeer int) *eth.Ethereum {
ethereum, err := eth.New(eth.CapDefault, UseUPnP)
if err != nil {
logger.Fatalln("eth start err:", err)
}
ethereum.Port = OutboundPort
ethereum.MaxPeers = MaxPeer
return ethereum
}
func StartEthereum(ethereum *eth.Ethereum, UseSeed bool) {
logger.Infof("Starting Ethereum v%s", ethutil.Config.Ver)
ethereum.Start(UseSeed)
RegisterInterrupt(func(sig os.Signal) {
ethereum.Stop()
ethlog.Flush()
})
}
func ShowGenesis(ethereum *eth.Ethereum) {
logger.Infoln(ethereum.BlockChain().Genesis())
exit(0)
}
func KeyTasks(GenAddr bool, ImportKey string, ExportKey bool, NonInteractive bool) {
switch {
case GenAddr:
if NonInteractive || confirm("This action overwrites your old private key.") {
CreateKeyPair(true)
}
exit(0)
case len(ImportKey) > 0:
if NonInteractive || confirm("This action overwrites your old private key.") {
// import should be from file
mnemonic := strings.Split(ImportKey, " ")
if len(mnemonic) == 24 {
logger.Infoln("Got mnemonic key, importing.")
key := ethutil.MnemonicDecode(mnemonic)
ImportPrivateKey(key)
} else if len(mnemonic) == 1 {
logger.Infoln("Got hex key, importing.")
ImportPrivateKey(ImportKey)
} else {
logger.Errorln("Did not recognise format, exiting.")
}
}
exit(0)
case ExportKey: // this should be exporting to a filename
keyPair := ethutil.GetKeyRing().Get(0)
fmt.Printf(`
Generating new address and keypair.
Please keep your keys somewhere save.
++++++++++++++++ KeyRing +++++++++++++++++++
addr: %x
prvk: %x
pubk: %x
++++++++++++++++++++++++++++++++++++++++++++
save these words so you can restore your account later: %s
`, keyPair.Address(), keyPair.PrivateKey, keyPair.PublicKey)
exit(0)
default:
// Creates a keypair if none exists
CreateKeyPair(false)
}
}
func StartRpc(ethereum *eth.Ethereum, RpcPort int) {
var err error
ethereum.RpcServer, err = ethrpc.NewJsonRpcServer(ethpub.NewPEthereum(ethereum), RpcPort)
if err != nil {
ethutil.Config.Log.Infoln("Could not start RPC interface:", err)
logger.Errorf("Could not start RPC interface (port %v): %v", RpcPort, err)
} else {
go ethereum.RpcServer.Start()
}
@ -21,54 +188,58 @@ func DoRpc(ethereum *eth.Ethereum, RpcPort int) {
var miner ethminer.Miner
func DoMining(ethereum *eth.Ethereum) {
// Set Mining status
ethereum.Mining = true
func StartMining(ethereum *eth.Ethereum) bool {
if !ethereum.Mining {
ethereum.Mining = true
if ethutil.GetKeyRing().Len() == 0 {
ethutil.Config.Log.Infoln("No address found, can't start mining")
return
}
keyPair := ethutil.GetKeyRing().Get(0)
addr := keyPair.Address()
go func() {
miner = ethminer.NewDefaultMiner(addr, ethereum)
// Give it some time to connect with peers
time.Sleep(3 * time.Second)
for ethereum.IsUpToDate() == false {
time.Sleep(5 * time.Second)
if ethutil.GetKeyRing().Len() == 0 {
logger.Errorln("No address found, can't start mining")
ethereum.Mining = false
return true //????
}
keyPair := ethutil.GetKeyRing().Get(0)
addr := keyPair.Address()
ethutil.Config.Log.Infoln("Miner started")
miner := ethminer.NewDefaultMiner(addr, ethereum)
miner.Start()
}()
go func() {
miner = ethminer.NewDefaultMiner(addr, ethereum)
// Give it some time to connect with peers
time.Sleep(3 * time.Second)
logger.Infoln("Miner started")
miner := ethminer.NewDefaultMiner(addr, ethereum)
miner.Start()
}()
RegisterInterrupt(func(os.Signal) {
StopMining(ethereum)
})
return true
}
return false
}
func StopMining(ethereum *eth.Ethereum) bool {
if ethereum.Mining {
miner.Stop()
ethutil.Config.Log.Infoln("Miner stopped")
logger.Infoln("Miner stopped")
ethereum.Mining = false
return true
}
return false
}
func StartMining(ethereum *eth.Ethereum) bool {
if !ethereum.Mining {
DoMining(ethereum)
return true
// Replay block
func BlockDo(ethereum *eth.Ethereum, hash []byte) error {
block := ethereum.BlockChain().GetBlock(hash)
if block == nil {
return fmt.Errorf("unknown block %x", hash)
}
return false
parent := ethereum.BlockChain().GetBlock(block.PrevHash)
_, err := ethereum.StateManager().ApplyDiff(parent.State(), parent, block)
if err != nil {
return err
}
return nil
}

View File

@ -1,41 +0,0 @@
package utils
import (
"fmt"
"github.com/obscuren/mutan"
"strings"
)
// General compile function
func Compile(script string) ([]byte, error) {
byteCode, errors := mutan.Compile(strings.NewReader(script), false)
if len(errors) > 0 {
var errs string
for _, er := range errors {
if er != nil {
errs += er.Error()
}
}
return nil, fmt.Errorf("%v", errs)
}
return byteCode, nil
}
func CompileScript(script string) ([]byte, []byte, error) {
// Preprocess
mainInput, initInput := mutan.PreParse(script)
// Compile main script
mainScript, err := Compile(mainInput)
if err != nil {
return nil, nil, err
}
// Compile init script
initScript, err := Compile(initInput)
if err != nil {
return nil, nil, err
}
return mainScript, initScript, nil
}