ui_lib.go 4.31 KB
Newer Older
obscuren's avatar
obscuren committed
1 2 3
package ethui

import (
4
	"bitbucket.org/kardianos/osext"
obscuren's avatar
obscuren committed
5
	"github.com/ethereum/eth-go"
obscuren's avatar
obscuren committed
6
	"github.com/ethereum/eth-go/ethchain"
obscuren's avatar
obscuren committed
7
	"github.com/ethereum/eth-go/ethutil"
8
	"github.com/go-qml/qml"
9
	"os"
10 11 12
	"path"
	"path/filepath"
	"runtime"
obscuren's avatar
obscuren committed
13 14
)

obscuren's avatar
obscuren committed
15 16 17 18 19
type memAddr struct {
	Num   string
	Value string
}

obscuren's avatar
obscuren committed
20 21 22 23 24
// UI Library that has some basic functionality exposed
type UiLib struct {
	engine    *qml.Engine
	eth       *eth.Ethereum
	connected bool
25
	assetPath string
obscuren's avatar
obscuren committed
26
	// The main application window
27 28 29
	win      *qml.Window
	Db       *Debugger
	DbWindow *DebuggerWindow
30 31 32 33 34 35 36
}

func NewUiLib(engine *qml.Engine, eth *eth.Ethereum, assetPath string) *UiLib {
	if assetPath == "" {
		assetPath = DefaultAssetPath()
	}
	return &UiLib{engine: engine, eth: eth, assetPath: assetPath}
obscuren's avatar
obscuren committed
37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52
}

// 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)

	go func() {
		win.Show()
		win.Wait()
	}()
}

53
func (ui *UiLib) OpenHtml(path string) {
54 55
	container := NewHtmlApplication(path, ui)
	app := NewExtApplication(container, ui)
56

57 58
	go app.run()
}
59

obscuren's avatar
obscuren committed
60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76
func (ui *UiLib) Muted(content string) {
	component, err := ui.engine.LoadFile(ui.AssetPath("qml/muted.qml"))
	if err != nil {
		ethutil.Config.Log.Debugln(err)

		return
	}
	win := component.CreateWindow(nil)
	go func() {
		path := "file://" + ui.AssetPath("muted/index.html")
		win.Set("url", path)

		win.Show()
		win.Wait()
	}()
}

77
func (ui *UiLib) Connect(button qml.Object) {
obscuren's avatar
obscuren committed
78
	if !ui.connected {
obscuren's avatar
obscuren committed
79
		ui.eth.Start(true)
80 81
		ui.connected = true
		button.Set("enabled", false)
obscuren's avatar
obscuren committed
82 83 84 85 86 87
	}
}

func (ui *UiLib) ConnectToPeer(addr string) {
	ui.eth.ConnectToPeer(addr)
}
88 89

func (ui *UiLib) AssetPath(p string) string {
90
	return path.Join(ui.assetPath, p)
91
}
92 93 94 95
func (self *UiLib) StartDbWithContractAndData(contractHash, data string) {
	dbWindow := NewDebuggerWindow(self)
	object := self.eth.StateManager().CurrentState().GetStateObject(ethutil.FromHex(contractHash))
	if len(object.Script()) > 0 {
96
		dbWindow.SetCode("0x" + ethutil.Hex(object.Script()))
97 98 99 100 101 102 103 104 105 106 107
	}
	dbWindow.SetData(data)

	dbWindow.Show()
}

func (self *UiLib) StartDbWithCode(code string) {
	dbWindow := NewDebuggerWindow(self)
	dbWindow.SetCode("0x" + code)
	dbWindow.Show()
}
108

obscuren's avatar
obscuren committed
109 110
func (self *UiLib) StartDebugger() {
	dbWindow := NewDebuggerWindow(self)
111
	//self.DbWindow = dbWindow
obscuren's avatar
obscuren committed
112 113 114 115

	dbWindow.Show()
}

116
func DefaultAssetPath() string {
117
	var base string
118 119 120 121
	// 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()
obscuren's avatar
obscuren committed
122 123
	if pwd == path.Join(os.Getenv("GOPATH"), "src", "github.com", "ethereum", "go-ethereum", "ethereal") {
		base = path.Join(pwd, "assets")
124 125 126 127 128 129 130 131 132 133 134 135 136
	} 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 = "."
		}
137 138
	}

139
	return base
140
}
obscuren's avatar
obscuren committed
141

obscuren's avatar
obscuren committed
142
func (ui *UiLib) DebugTx(recipient, valueStr, gasStr, gasPriceStr, data string) {
obscuren's avatar
obscuren committed
143 144
	state := ui.eth.BlockChain().CurrentBlock.State()

obscuren's avatar
obscuren committed
145
	script, err := ethutil.Compile(data)
obscuren's avatar
obscuren committed
146
	if err != nil {
147 148 149
		ethutil.Config.Log.Debugln(err)

		return
obscuren's avatar
obscuren committed
150 151
	}

obscuren's avatar
obscuren committed
152
	dis := ethchain.Disassemble(script)
obscuren's avatar
obscuren committed
153
	ui.win.Root().Call("clearAsm")
154

obscuren's avatar
obscuren committed
155 156 157 158
	for _, str := range dis {
		ui.win.Root().Call("setAsm", str)
	}
	// Contract addr as test address
159
	keyPair := ethutil.GetKeyRing().Get(0)
obscuren's avatar
obscuren committed
160 161 162 163
	callerTx :=
		ethchain.NewContractCreationTx(ethutil.Big(valueStr), ethutil.Big(gasStr), ethutil.Big(gasPriceStr), script)
	callerTx.Sign(keyPair.PrivateKey)

obscuren's avatar
obscuren committed
164
	account := ui.eth.StateManager().TransState().GetStateObject(keyPair.Address())
obscuren's avatar
obscuren committed
165 166
	contract := ethchain.MakeContract(callerTx, state)
	callerClosure := ethchain.NewClosure(account, contract, contract.Init(), state, ethutil.Big(gasStr), ethutil.Big(gasPriceStr))
obscuren's avatar
obscuren committed
167 168

	block := ui.eth.BlockChain().CurrentBlock
169
	vm := ethchain.NewVm(state, ui.eth.StateManager(), ethchain.RuntimeVars{
obscuren's avatar
obscuren committed
170 171 172 173 174 175 176 177
		Origin:      account.Address(),
		BlockNumber: block.BlockInfo().Number,
		PrevHash:    block.PrevHash,
		Coinbase:    block.Coinbase,
		Time:        block.Time,
		Diff:        block.Difficulty,
	})

obscuren's avatar
obscuren committed
178
	ui.Db.done = false
obscuren's avatar
obscuren committed
179
	go func() {
obscuren's avatar
obscuren committed
180
		callerClosure.Call(vm, contract.Init(), ui.Db.halting)
obscuren's avatar
obscuren committed
181

obscuren's avatar
obscuren committed
182
		state.Reset()
obscuren's avatar
obscuren committed
183 184

		ui.Db.done = true
obscuren's avatar
obscuren committed
185
	}()
obscuren's avatar
obscuren committed
186
}
obscuren's avatar
obscuren committed
187 188

func (ui *UiLib) Next() {
obscuren's avatar
obscuren committed
189
	ui.Db.Next()
obscuren's avatar
obscuren committed
190
}