gui.go 14.0 KB
Newer Older
O
obscuren 已提交
1 2
/*
	This file is part of go-ethereum
F
Felix Lange 已提交
3

O
obscuren 已提交
4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
	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>
 */
O
obscuren 已提交
21
package main
O
obscuren 已提交
22

O
obscuren 已提交
23 24
import "C"

O
obscuren 已提交
25
import (
O
obscuren 已提交
26
	"bytes"
O
obscuren 已提交
27
	"encoding/json"
O
obscuren 已提交
28
	"fmt"
29
	"io/ioutil"
O
obscuren 已提交
30
	"math/big"
31
	"os"
O
obscuren 已提交
32
	"path"
O
obscuren 已提交
33
	"runtime"
O
obscuren 已提交
34 35 36
	"strconv"
	"strings"
	"time"
O
Removed  
obscuren 已提交
37

O
obscuren 已提交
38 39
	"github.com/ethereum/go-ethereum/core"
	"github.com/ethereum/go-ethereum/core/types"
40
	"github.com/ethereum/go-ethereum/eth"
41 42
	"github.com/ethereum/go-ethereum/ethdb"
	"github.com/ethereum/go-ethereum/ethutil"
O
obscuren 已提交
43
	"github.com/ethereum/go-ethereum/logger"
O
obscuren 已提交
44
	"github.com/ethereum/go-ethereum/miner"
45
	"github.com/ethereum/go-ethereum/p2p"
46
	"github.com/ethereum/go-ethereum/ui/qt/qwhisper"
O
obscuren 已提交
47
	"github.com/ethereum/go-ethereum/xeth"
O
obscuren 已提交
48
	"gopkg.in/qml.v1"
O
obscuren 已提交
49 50
)

O
obscuren 已提交
51
var guilogger = logger.NewLogger("GUI")
52

53 54 55 56 57 58 59
type ServEv byte

const (
	setup ServEv = iota
	update
)

O
obscuren 已提交
60
type Gui struct {
61 62 63
	// The main application window
	win *qml.Window
	// QML Engine
O
obscuren 已提交
64 65
	engine    *qml.Engine
	component *qml.Common
66
	// The ethereum interface
67 68
	eth           *eth.Ethereum
	serviceEvents chan ServEv
O
obscuren 已提交
69

70
	// The public Ethereum library
71 72
	uiLib   *UiLib
	whisper *qwhisper.Whisper
O
obscuren 已提交
73 74 75

	txDb *ethdb.LDBDatabase

O
obscuren 已提交
76
	logLevel logger.LogLevel
Z
go fmt  
zelig 已提交
77
	open     bool
Z
zelig 已提交
78

79
	xeth *xeth.JSXEth
O
obscuren 已提交
80

Z
zelig 已提交
81
	Session        string
82
	clientIdentity *p2p.SimpleClientIdentity
Z
zelig 已提交
83
	config         *ethutil.ConfigManager
M
Maran 已提交
84

O
obscuren 已提交
85 86
	plugins map[string]plugin

O
obscuren 已提交
87
	miner *miner.Miner
O
obscuren 已提交
88 89
}

90
// Create GUI, but doesn't start it
91
func NewWindow(ethereum *eth.Ethereum, config *ethutil.ConfigManager, clientIdentity *p2p.SimpleClientIdentity, session string, logLevel int) *Gui {
O
obscuren 已提交
92 93 94 95
	db, err := ethdb.NewLDBDatabase("tx_database")
	if err != nil {
		panic(err)
	}
O
obscuren 已提交
96

97
	xeth := xeth.NewJSXEth(ethereum)
98 99 100 101 102 103 104 105 106 107 108
	gui := &Gui{eth: ethereum,
		txDb:           db,
		xeth:           xeth,
		logLevel:       logger.LogLevel(logLevel),
		Session:        session,
		open:           false,
		clientIdentity: clientIdentity,
		config:         config,
		plugins:        make(map[string]plugin),
		serviceEvents:  make(chan ServEv, 1),
	}
O
obscuren 已提交
109
	data, _ := ethutil.ReadAllFile(path.Join(ethutil.Config.ExecPath, "plugins.json"))
O
obscuren 已提交
110 111 112
	json.Unmarshal([]byte(data), &gui.plugins)

	return gui
O
obscuren 已提交
113 114
}

O
Cleanup  
obscuren 已提交
115 116
func (gui *Gui) Start(assetPath string) {
	defer gui.txDb.Close()
O
obscuren 已提交
117

O
obscuren 已提交
118 119
	guilogger.Infoln("Starting GUI")

120 121
	go gui.service()

122 123
	// Register ethereum functions
	qml.RegisterTypes("Ethereum", 1, 0, []qml.TypeSpec{{
O
obscuren 已提交
124
		Init: func(p *xeth.JSBlock, obj qml.Object) { p.Number = 0; p.Hash = "" },
O
obscuren 已提交
125
	}, {
O
obscuren 已提交
126
		Init: func(p *xeth.JSTransaction, obj qml.Object) { p.Value = ""; p.Hash = ""; p.Address = "" },
127
	}, {
O
obscuren 已提交
128
		Init: func(p *xeth.KeyVal, obj qml.Object) { p.Key = ""; p.Value = "" },
O
obscuren 已提交
129
	}})
130
	// Create a new QML engine
O
Cleanup  
obscuren 已提交
131 132
	gui.engine = qml.NewEngine()
	context := gui.engine.Context()
133
	gui.uiLib = NewUiLib(gui.engine, gui.eth, assetPath)
134
	gui.whisper = qwhisper.New(gui.eth.Whisper())
135 136

	// Expose the eth library and the ui library to QML
137 138
	context.SetVar("gui", gui)
	context.SetVar("eth", gui.uiLib)
O
obscuren 已提交
139
	context.SetVar("shh", gui.whisper)
J
Jarrad Hope 已提交
140

O
obscuren 已提交
141
	win, err := gui.showWallet(context)
O
obscuren 已提交
142
	if err != nil {
O
obscuren 已提交
143
		guilogger.Errorln("asset not found: you can set an alternative asset path on the command line using option 'asset_path'", err)
144

O
obscuren 已提交
145 146 147
		panic(err)
	}

Z
zelig 已提交
148
	gui.open = true
149
	win.Show()
O
obscuren 已提交
150

O
obscuren 已提交
151
	// only add the gui guilogger after window is shown otherwise slider wont be shown
O
obscuren 已提交
152
	logger.AddLogSystem(gui)
O
obscuren 已提交
153
	win.Wait()
O
obscuren 已提交
154

O
obscuren 已提交
155 156
	// need to silence gui guilogger after window closed otherwise logsystem hangs (but do not save loglevel)
	gui.logLevel = logger.Silence
Z
zelig 已提交
157 158 159 160 161
	gui.open = false
}

func (gui *Gui) Stop() {
	if gui.open {
O
obscuren 已提交
162
		gui.logLevel = logger.Silence
Z
zelig 已提交
163 164 165
		gui.open = false
		gui.win.Hide()
	}
166

167
	gui.uiLib.jsEngine.Stop()
168

O
obscuren 已提交
169
	guilogger.Infoln("Stopped")
O
obscuren 已提交
170
}
O
obscuren 已提交
171

O
obscuren 已提交
172
func (gui *Gui) showWallet(context *qml.Context) (*qml.Window, error) {
O
obscuren 已提交
173
	component, err := gui.engine.LoadFile(gui.uiLib.AssetPath("qml/main.qml"))
O
obscuren 已提交
174 175
	if err != nil {
		return nil, err
176
	}
O
obscuren 已提交
177

178
	gui.createWindow(component)
O
obscuren 已提交
179

180 181 182
	return gui.win, nil
}

O
obscuren 已提交
183 184 185
func (gui *Gui) ImportKey(filePath string) {
}

O
obscuren 已提交
186
func (gui *Gui) showKeyImport(context *qml.Context) (*qml.Window, error) {
Z
zelig 已提交
187
	context.SetVar("lib", gui)
O
obscuren 已提交
188 189 190 191 192 193 194 195
	component, err := gui.engine.LoadFile(gui.uiLib.AssetPath("qml/first_run.qml"))
	if err != nil {
		return nil, err
	}
	return gui.createWindow(component), nil
}

func (gui *Gui) createWindow(comp qml.Object) *qml.Window {
196 197
	gui.win = comp.CreateWindow(nil)
	gui.uiLib.win = gui.win
O
obscuren 已提交
198 199

	return gui.win
O
obscuren 已提交
200
}
Z
zelig 已提交
201 202 203 204

func (gui *Gui) ImportAndSetPrivKey(secret string) bool {
	err := gui.eth.KeyManager().InitFromString(gui.Session, 0, secret)
	if err != nil {
O
obscuren 已提交
205
		guilogger.Errorln("unable to import: ", err)
Z
zelig 已提交
206 207
		return false
	}
O
obscuren 已提交
208
	guilogger.Errorln("successfully imported: ", err)
Z
zelig 已提交
209 210 211 212 213 214
	return true
}

func (gui *Gui) CreateAndSetPrivKey() (string, string, string, string) {
	err := gui.eth.KeyManager().Init(gui.Session, 0, true)
	if err != nil {
O
obscuren 已提交
215
		guilogger.Errorln("unable to create key: ", err)
Z
zelig 已提交
216 217 218 219 220
		return "", "", "", ""
	}
	return gui.eth.KeyManager().KeyPair().AsStrings()
}

O
obscuren 已提交
221
func (gui *Gui) setInitialChain(ancientBlocks bool) {
O
obscuren 已提交
222
	sBlk := gui.eth.ChainManager().LastBlockHash()
O
obscuren 已提交
223 224
	blk := gui.eth.ChainManager().GetBlock(sBlk)
	for ; blk != nil; blk = gui.eth.ChainManager().GetBlock(sBlk) {
O
obscuren 已提交
225
		sBlk = blk.ParentHash()
226

M
Maran 已提交
227
		gui.processBlock(blk, true)
228 229 230
	}
}

O
obscuren 已提交
231
func (gui *Gui) loadAddressBook() {
232
	view := gui.getObjectByName("infoView")
233
	nameReg := gui.xeth.World().Config().Get("NameReg")
O
obscuren 已提交
234
	if nameReg != nil {
O
obscuren 已提交
235 236 237 238
		it := nameReg.Trie().Iterator()
		for it.Next() {
			if it.Key[0] != 0 {
				view.Call("addAddress", struct{ Name, Address string }{string(it.Key), ethutil.Bytes2Hex(it.Value)})
239
			}
O
obscuren 已提交
240 241

		}
242
	}
O
obscuren 已提交
243 244
}

245 246 247
func (self *Gui) loadMergedMiningOptions() {
	view := self.getObjectByName("mergedMiningModel")

248
	mergeMining := self.xeth.World().Config().Get("MergeMining")
O
obscuren 已提交
249
	if mergeMining != nil {
250
		i := 0
O
obscuren 已提交
251 252 253 254 255 256 257
		it := mergeMining.Trie().Iterator()
		for it.Next() {
			view.Call("addMergedMiningOption", struct {
				Checked       bool
				Name, Address string
				Id, ItemId    int
			}{false, string(it.Key), ethutil.Bytes2Hex(it.Value), 0, i})
258

O
obscuren 已提交
259
			i++
260

O
obscuren 已提交
261
		}
262 263 264
	}
}

265
func (gui *Gui) insertTransaction(window string, tx *types.Transaction) {
266
	nameReg := gui.xeth.World().Config().Get("NameReg")
Z
zelig 已提交
267
	addr := gui.address()
O
obscuren 已提交
268

O
obscuren 已提交
269
	var inout string
270
	if bytes.Compare(tx.From(), addr) == 0 {
O
obscuren 已提交
271 272 273 274 275 276
		inout = "send"
	} else {
		inout = "recv"
	}

	var (
O
obscuren 已提交
277
		ptx  = xeth.NewJSTx(tx)
278 279
		send = nameReg.Storage(tx.From())
		rec  = nameReg.Storage(tx.To())
O
obscuren 已提交
280 281 282
		s, r string
	)

O
obscuren 已提交
283
	if core.MessageCreatesContract(tx) {
284
		rec = nameReg.Storage(core.AddressFromMessage(tx))
O
obscuren 已提交
285 286 287 288 289
	}

	if send.Len() != 0 {
		s = strings.Trim(send.Str(), "\x00")
	} else {
290
		s = ethutil.Bytes2Hex(tx.From())
O
obscuren 已提交
291 292 293 294
	}
	if rec.Len() != 0 {
		r = strings.Trim(rec.Str(), "\x00")
	} else {
O
obscuren 已提交
295
		if core.MessageCreatesContract(tx) {
296
			r = ethutil.Bytes2Hex(core.AddressFromMessage(tx))
O
obscuren 已提交
297
		} else {
298
			r = ethutil.Bytes2Hex(tx.To())
O
obscuren 已提交
299
		}
O
obscuren 已提交
300 301 302 303
	}
	ptx.Sender = s
	ptx.Address = r

304
	if window == "post" {
O
obscuren 已提交
305
		//gui.getObjectByName("transactionView").Call("addTx", ptx, inout)
306 307 308
	} else {
		gui.getObjectByName("pendingTxView").Call("addTx", ptx, inout)
	}
O
obscuren 已提交
309
}
O
obscuren 已提交
310

O
obscuren 已提交
311
func (gui *Gui) readPreviousTransactions() {
O
obscuren 已提交
312
	it := gui.txDb.NewIterator()
O
obscuren 已提交
313
	for it.Next() {
314
		tx := types.NewTransactionFromBytes(it.Value())
O
obscuren 已提交
315 316

		gui.insertTransaction("post", tx)
O
obscuren 已提交
317

O
obscuren 已提交
318 319 320 321
	}
	it.Release()
}

322
func (gui *Gui) processBlock(block *types.Block, initial bool) {
323
	name := strings.Trim(gui.xeth.World().Config().Get("NameReg").Storage(block.Coinbase()).Str(), "\x00")
O
obscuren 已提交
324
	b := xeth.NewJSBlock(block)
325 326
	b.Name = name

327
	gui.getObjectByName("chainView").Call("addBlock", b, initial)
O
obscuren 已提交
328 329
}

330 331 332 333
func (gui *Gui) setWalletValue(amount, unconfirmedFunds *big.Int) {
	var str string
	if unconfirmedFunds != nil {
		pos := "+"
O
obscuren 已提交
334
		if unconfirmedFunds.Cmp(big.NewInt(0)) < 0 {
335 336 337 338 339 340 341 342 343 344 345
			pos = "-"
		}
		val := ethutil.CurrencyToString(new(big.Int).Abs(ethutil.BigCopy(unconfirmedFunds)))
		str = fmt.Sprintf("%v (%s %v)", ethutil.CurrencyToString(amount), pos, val)
	} else {
		str = fmt.Sprintf("%v", ethutil.CurrencyToString(amount))
	}

	gui.win.Root().Call("setWalletValue", str)
}

O
obscuren 已提交
346 347 348 349
func (self *Gui) getObjectByName(objectName string) qml.Object {
	return self.win.Root().ObjectByName(objectName)
}

350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391
func loadJavascriptAssets(gui *Gui) (jsfiles string) {
	for _, fn := range []string{"ext/q.js", "ext/eth.js/main.js", "ext/eth.js/qt.js", "ext/setup.js"} {
		f, err := os.Open(gui.uiLib.AssetPath(fn))
		if err != nil {
			fmt.Println(err)
			continue
		}

		content, err := ioutil.ReadAll(f)
		if err != nil {
			fmt.Println(err)
			continue
		}
		jsfiles += string(content)
	}

	return
}

func (gui *Gui) SendCommand(cmd ServEv) {
	gui.serviceEvents <- cmd
}

func (gui *Gui) service() {
	for ev := range gui.serviceEvents {
		switch ev {
		case setup:
			go gui.setup()
		case update:
			go gui.update()
		}
	}
}

func (gui *Gui) setup() {
	for gui.win == nil {
		time.Sleep(time.Millisecond * 200)
	}

	for _, plugin := range gui.plugins {
		guilogger.Infoln("Loading plugin ", plugin.Name)
		gui.win.Root().Call("addPlugin", plugin.Path, "")
392 393 394
	}

	go func() {
O
obscuren 已提交
395
		go gui.setInitialChain(false)
396
		gui.loadAddressBook()
397
		gui.loadMergedMiningOptions()
398 399
		gui.setPeerInfo()
	}()
400

401 402 403
	// Inject javascript files each time navigation is requested.
	// Unfortunately webview.experimental.userScripts injects _after_
	// the page has loaded which kind of renders it useless...
O
obscuren 已提交
404
	//jsfiles := loadJavascriptAssets(gui)
405
	gui.getObjectByName("webView").On("navigationRequested", func() {
O
obscuren 已提交
406
		//gui.getObjectByName("webView").Call("injectJs", jsfiles)
407
	})
408

409
	gui.whisper.SetView(gui.getObjectByName("whisperView"))
O
obscuren 已提交
410

411 412
	gui.SendCommand(update)
}
O
obscuren 已提交
413

414 415
// Simple go routine function that updates the list of peers in the GUI
func (gui *Gui) update() {
O
obscuren 已提交
416
	peerUpdateTicker := time.NewTicker(5 * time.Second)
O
obscuren 已提交
417
	generalUpdateTicker := time.NewTicker(500 * time.Millisecond)
O
obscuren 已提交
418
	statsUpdateTicker := time.NewTicker(5 * time.Second)
M
Maran 已提交
419

O
obscuren 已提交
420
	state := gui.eth.ChainManager().TransState()
O
obscuren 已提交
421

O
obscuren 已提交
422
	gui.win.Root().Call("setWalletValue", fmt.Sprintf("%v", ethutil.CurrencyToString(state.GetAccount(gui.address()).Balance())))
O
obscuren 已提交
423 424

	lastBlockLabel := gui.getObjectByName("lastBlockLabel")
O
obscuren 已提交
425
	miningLabel := gui.getObjectByName("miningLabel")
O
obscuren 已提交
426

F
Felix Lange 已提交
427
	events := gui.eth.EventMux().Subscribe(
428
		//eth.PeerListEvent{},
O
obscuren 已提交
429 430 431
		core.NewBlockEvent{},
		core.TxPreEvent{},
		core.TxPostEvent{},
F
Felix Lange 已提交
432 433
	)

434 435 436 437 438 439 440 441 442 443 444 445
	defer events.Unsubscribe()
	for {
		select {
		case ev, isopen := <-events.Chan():
			if !isopen {
				return
			}
			switch ev := ev.(type) {
			case core.NewBlockEvent:
				gui.processBlock(ev.Block, false)
				if bytes.Compare(ev.Block.Coinbase(), gui.address()) == 0 {
					gui.setWalletValue(gui.eth.ChainManager().State().GetBalance(gui.address()), nil)
Z
zelig 已提交
446
				}
O
Cleanup  
obscuren 已提交
447

448 449
			case core.TxPreEvent:
				tx := ev.Tx
450

451 452
				tstate := gui.eth.ChainManager().TransState()
				cstate := gui.eth.ChainManager().State()
453

454 455 456
				taccount := tstate.GetAccount(gui.address())
				caccount := cstate.GetAccount(gui.address())
				unconfirmedFunds := new(big.Int).Sub(taccount.Balance(), caccount.Balance())
O
obscuren 已提交
457

458 459
				gui.setWalletValue(taccount.Balance(), unconfirmedFunds)
				gui.insertTransaction("pre", tx)
O
obscuren 已提交
460

461 462 463
			case core.TxPostEvent:
				tx := ev.Tx
				object := state.GetAccount(gui.address())
O
obscuren 已提交
464

465 466
				if bytes.Compare(tx.From(), gui.address()) == 0 {
					object.SubAmount(tx.Value())
F
Felix Lange 已提交
467

468 469 470
					gui.txDb.Put(tx.Hash(), tx.RlpEncode())
				} else if bytes.Compare(tx.To(), gui.address()) == 0 {
					object.AddAmount(tx.Value())
471

472
					gui.txDb.Put(tx.Hash(), tx.RlpEncode())
Z
zelig 已提交
473
				}
Z
zelig 已提交
474

475 476
				gui.setWalletValue(object.Balance(), nil)
				state.UpdateStateObject(object)
O
obscuren 已提交
477
			}
478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500

		case <-peerUpdateTicker.C:
			gui.setPeerInfo()
		case <-generalUpdateTicker.C:
			statusText := "#" + gui.eth.ChainManager().CurrentBlock().Number().String()
			lastBlockLabel.Set("text", statusText)
			miningLabel.Set("text", "Mining @ "+strconv.FormatInt(gui.uiLib.miner.GetPow().GetHashrate(), 10)+"Khash")

			/*
				blockLength := gui.eth.BlockPool().BlocksProcessed
				chainLength := gui.eth.BlockPool().ChainLength

				var (
					pct      float64 = 1.0 / float64(chainLength) * float64(blockLength)
					dlWidget         = gui.win.Root().ObjectByName("downloadIndicator")
					dlLabel          = gui.win.Root().ObjectByName("downloadLabel")
				)
				dlWidget.Set("value", pct)
				dlLabel.Set("text", fmt.Sprintf("%d / %d", blockLength, chainLength))
			*/

		case <-statsUpdateTicker.C:
			gui.setStatsPane()
O
obscuren 已提交
501
		}
502
	}
O
obscuren 已提交
503 504
}

O
obscuren 已提交
505 506 507 508 509
func (gui *Gui) setStatsPane() {
	var memStats runtime.MemStats
	runtime.ReadMemStats(&memStats)

	statsPane := gui.getObjectByName("statsPane")
O
obscuren 已提交
510
	statsPane.Set("text", fmt.Sprintf(`###### Mist %s (%s) #######
O
obscuren 已提交
511 512

eth %d (p2p = %d)
O
obscuren 已提交
513 514 515 516 517 518 519 520 521 522

CPU:        # %d
Goroutines: # %d
CGoCalls:   # %d

Alloc:      %d
Heap Alloc: %d

CGNext:     %x
NumGC:      %d
O
obscuren 已提交
523
`, Version, runtime.Version(),
524
		eth.ProtocolVersion, 2,
O
obscuren 已提交
525
		runtime.NumCPU, runtime.NumGoroutine(), runtime.NumCgoCall(),
O
obscuren 已提交
526 527 528 529 530
		memStats.Alloc, memStats.HeapAlloc,
		memStats.NextGC, memStats.NumGC,
	))
}

O
obscuren 已提交
531 532
func (gui *Gui) setPeerInfo() {
	gui.win.Root().Call("setPeers", fmt.Sprintf("%d / %d", gui.eth.PeerCount(), gui.eth.MaxPeers))
M
Maran 已提交
533
	gui.win.Root().Call("resetPeers")
534
	for _, peer := range gui.xeth.Peers() {
M
Maran 已提交
535 536
		gui.win.Root().Call("addPeer", peer)
	}
O
obscuren 已提交
537 538
}

Z
zelig 已提交
539 540 541 542 543 544 545
func (gui *Gui) privateKey() string {
	return ethutil.Bytes2Hex(gui.eth.KeyManager().PrivateKey())
}

func (gui *Gui) address() []byte {
	return gui.eth.KeyManager().Address()
}
O
obscuren 已提交
546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577

/*
func LoadExtension(path string) (uintptr, error) {
	lib, err := ffi.NewLibrary(path)
	if err != nil {
		return 0, err
	}

	so, err := lib.Fct("sharedObject", ffi.Pointer, nil)
	if err != nil {
		return 0, err
	}

	ptr := so()

		err = lib.Close()
		if err != nil {
			return 0, err
		}

	return ptr.Interface().(uintptr), nil
}
*/
/*
	vec, errr := LoadExtension("/Users/jeffrey/Desktop/build-libqmltest-Desktop_Qt_5_2_1_clang_64bit-Debug/liblibqmltest_debug.dylib")
	fmt.Printf("Fetched vec with addr: %#x\n", vec)
	if errr != nil {
		fmt.Println(errr)
	} else {
		context.SetVar("vec", (unsafe.Pointer)(vec))
	}
*/