Implemented key importing/generation for the GUI
This commit is contained in:
		
							
								
								
									
										155
									
								
								ethereal/assets/qml/first_run.qml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										155
									
								
								ethereal/assets/qml/first_run.qml
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,155 @@ | ||||
| import QtQuick 2.0 | ||||
| import Ethereum 1.0 | ||||
|  | ||||
| // Which ones do we actually need? | ||||
| import QtQuick.Controls 1.0; | ||||
| import QtQuick.Layouts 1.0; | ||||
| import QtQuick.Dialogs 1.0; | ||||
| import QtQuick.Window 2.1; | ||||
| import QtQuick.Controls.Styles 1.1 | ||||
| import QtQuick.Dialogs 1.1 | ||||
|  | ||||
| ApplicationWindow { | ||||
|   id: wizardRoot | ||||
|   width: 500 | ||||
|   height: 400 | ||||
|   title: "Ethereal first run setup" | ||||
|  | ||||
|   Column { | ||||
|     spacing: 5 | ||||
|     anchors.leftMargin: 10 | ||||
|     anchors.left: parent.left | ||||
|  | ||||
|     Text { | ||||
|       visible: true | ||||
|       text: "<h2>Ethereal setup</h2>" | ||||
|     } | ||||
|  | ||||
|     Column { | ||||
|       id: restoreColumn | ||||
|       spacing: 5 | ||||
|       Text { | ||||
|         visible: true | ||||
|         font.pointSize: 14 | ||||
|         text: "Restore your Ethereum account" | ||||
|         id: restoreLabel | ||||
|       } | ||||
|  | ||||
|       TextField { | ||||
|         id: txPrivKey | ||||
|         width: 480 | ||||
|         placeholderText: "Private key or mnemonic words" | ||||
|         focus: true | ||||
|         onTextChanged: { | ||||
|           if(this.text.length == 64){ | ||||
|             detailLabel.text = "Private (hex) key detected." | ||||
|             actionButton.enabled = true | ||||
|           } | ||||
|           else if(this.text.split(" ").length == 24){ | ||||
|             detailLabel.text = "Mnemonic key detected." | ||||
|             actionButton.enabled = true | ||||
|           }else{ | ||||
|             detailLabel.text = "" | ||||
|             actionButton.enabled = false | ||||
|           } | ||||
|         } | ||||
|       } | ||||
|       Row { | ||||
|         spacing: 10 | ||||
|         Button { | ||||
|           id: actionButton | ||||
|           text: "Restore" | ||||
|           enabled: false | ||||
|           onClicked: { | ||||
|            var success = eth.importAndSetPrivKey(txPrivKey.text) | ||||
|            if(success){ | ||||
|              importedDetails.visible = true | ||||
|              restoreColumn.visible = false | ||||
|              newKey.visible = false | ||||
|              wizardRoot.height = 120 | ||||
|            } | ||||
|           } | ||||
|         } | ||||
|         Text { | ||||
|           id: detailLabel | ||||
|           font.pointSize: 12 | ||||
|           anchors.topMargin: 10 | ||||
|         } | ||||
|       } | ||||
|     } | ||||
|     Column { | ||||
|       id: importedDetails | ||||
|       visible: false | ||||
|       Text { | ||||
|         text: "<b>Your account has been imported. Please close the application and restart it again to let the changes take effect.</b>" | ||||
|         wrapMode: Text.WordWrap | ||||
|         width: 460 | ||||
|       } | ||||
|     } | ||||
|     Column { | ||||
|       spacing: 5 | ||||
|       id: newDetailsColumn | ||||
|       visible: false | ||||
|       Text { | ||||
|         font.pointSize: 14 | ||||
|         text: "Your account details" | ||||
|       } | ||||
|       Label { | ||||
|         text: "Address" | ||||
|       } | ||||
|       TextField { | ||||
|         id: addressInput | ||||
|         readOnly:true | ||||
|         width: 480 | ||||
|       } | ||||
|       Label { | ||||
|         text: "Private key" | ||||
|       } | ||||
|       TextField { | ||||
|         id: privkeyInput | ||||
|         readOnly:true | ||||
|         width: 480 | ||||
|       } | ||||
|       Label { | ||||
|         text: "Mnemonic words" | ||||
|       } | ||||
|       TextField { | ||||
|         id: mnemonicInput | ||||
|         readOnly:true | ||||
|         width: 480 | ||||
|       } | ||||
|       Label { | ||||
|         text: "<b>A new account has been created. Please take the time to write down the <i>24 words</i>. You can use those to restore your account at a later date.</b>" | ||||
|         wrapMode: Text.WordWrap | ||||
|         width: 480 | ||||
|       } | ||||
|       Label { | ||||
|         text: "Please restart the application once you have completed the steps above." | ||||
|         wrapMode: Text.WordWrap | ||||
|         width: 480 | ||||
|       } | ||||
|     } | ||||
|  | ||||
|   } | ||||
|   Button { | ||||
|     anchors.right: parent.right | ||||
|     anchors.bottom: parent.bottom | ||||
|     anchors.rightMargin: 10 | ||||
|     anchors.bottomMargin: 10 | ||||
|     id: newKey | ||||
|     text: "I don't have an account yet" | ||||
|     onClicked: { | ||||
|       var res = eth.createAndSetPrivKey() | ||||
|       mnemonicInput.text = res[0] | ||||
|       addressInput.text = res[1] | ||||
|       privkeyInput.text = res[2] | ||||
|  | ||||
|       // Hide restore | ||||
|       restoreColumn.visible = false | ||||
|  | ||||
|       // Show new details | ||||
|       newDetailsColumn.visible = true | ||||
|       newKey.visible = false | ||||
|     } | ||||
|   } | ||||
| } | ||||
| @@ -25,6 +25,35 @@ ApplicationWindow { | ||||
| 			} | ||||
| 		} | ||||
|  | ||||
| 		Menu { | ||||
| 			title: "Test" | ||||
| 			MenuItem { | ||||
| 				text: "Test test" | ||||
| 				shortcut: "Ctrl+t" | ||||
|         onTriggered: { | ||||
|           var win | ||||
|           function finishedLoading(){ | ||||
|             console.log("Trigged") | ||||
|             win = wizard.createObject(root) | ||||
|           } | ||||
|           console.log("Loading wizard") | ||||
|  | ||||
|           var wizard = Qt.createComponent("first_run.qml") | ||||
|           if(wizard.status== Component.Ready){ | ||||
|             console.log("Component is ready") | ||||
|             finishedLoading() | ||||
|           }else if( wizard.status == Component.Error){ | ||||
|             console.log("Error loading component:", wizard.errorString()) | ||||
|           } | ||||
|           else{ | ||||
|             wizard.statusChanged.connect(finishedLoading) | ||||
|             console.log("Component is NOT ready") | ||||
|             win = wizard.createObject(root) | ||||
|           } | ||||
|         } | ||||
| 			} | ||||
| 		} | ||||
|  | ||||
| 		Menu { | ||||
| 			title: "Network" | ||||
| 			MenuItem { | ||||
|   | ||||
| @@ -84,8 +84,6 @@ func main() { | ||||
| 				utils.ImportPrivateKey(ImportKey) | ||||
| 				os.Exit(0) | ||||
| 			} | ||||
| 		} else { | ||||
| 			utils.CreateKeyPair(false) | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
|   | ||||
| @@ -53,7 +53,6 @@ type Gui struct { | ||||
| 	txDb *ethdb.LDBDatabase | ||||
|  | ||||
| 	addr []byte | ||||
|  | ||||
| } | ||||
|  | ||||
| // Create GUI, but doesn't start it | ||||
| @@ -64,10 +63,16 @@ func New(ethereum *eth.Ethereum) *Gui { | ||||
| 		panic(err) | ||||
| 	} | ||||
|  | ||||
| 	data, _ := ethutil.Config.Db.Get([]byte("KeyRing")) | ||||
| 	// On first run we won't have any keys yet, so this would crash. | ||||
| 	// Therefor we check if we are ready to actually start this process | ||||
| 	var addr []byte | ||||
| 	if len(data) > 0 { | ||||
| 		key := ethutil.Config.Db.GetKeys()[0] | ||||
| 	addr := key.Address() | ||||
| 		addr = key.Address() | ||||
|  | ||||
| 		ethereum.StateManager().WatchAddr(addr) | ||||
| 	} | ||||
|  | ||||
| 	return &Gui{eth: ethereum, lib: lib, txDb: db, addr: addr} | ||||
| } | ||||
| @@ -94,7 +99,16 @@ func (ui *Gui) Start(assetPath string) { | ||||
| 	context.SetVar("ui", uiLib) | ||||
|  | ||||
| 	// Load the main QML interface | ||||
| 	component, err := ui.engine.LoadFile(uiLib.AssetPath("qml/wallet.qml")) | ||||
| 	data, _ := ethutil.Config.Db.Get([]byte("KeyRing")) | ||||
| 	var err error | ||||
| 	var component qml.Object | ||||
| 	firstRun := len(data) == 0 | ||||
|  | ||||
| 	if firstRun { | ||||
| 		component, err = ui.engine.LoadFile(uiLib.AssetPath("qml/first_run.qml")) | ||||
| 	} else { | ||||
| 		component, err = ui.engine.LoadFile(uiLib.AssetPath("qml/wallet.qml")) | ||||
| 	} | ||||
| 	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'") | ||||
| 		panic(err) | ||||
| @@ -111,9 +125,11 @@ func (ui *Gui) Start(assetPath string) { | ||||
| 	ethutil.Config.Log.AddLogSystem(ui) | ||||
|  | ||||
| 	// Loads previous blocks | ||||
| 	if firstRun == false { | ||||
| 		go ui.setInitialBlockChain() | ||||
| 		go ui.readPreviousTransactions() | ||||
| 		go ui.update() | ||||
| 	} | ||||
|  | ||||
| 	ui.win.Show() | ||||
| 	ui.win.Wait() | ||||
|   | ||||
| @@ -5,7 +5,9 @@ import ( | ||||
| 	"fmt" | ||||
| 	"github.com/ethereum/eth-go/ethchain" | ||||
| 	"github.com/ethereum/eth-go/ethutil" | ||||
| 	"github.com/ethereum/go-ethereum/utils" | ||||
| 	"github.com/obscuren/mutan" | ||||
| 	"github.com/obscuren/secp256k1-go" | ||||
| 	"strings" | ||||
| ) | ||||
|  | ||||
| @@ -15,6 +17,32 @@ type EthLib struct { | ||||
| 	txPool       *ethchain.TxPool | ||||
| } | ||||
|  | ||||
| func (lib *EthLib) ImportAndSetPrivKey(privKey string) bool { | ||||
| 	fmt.Println(privKey) | ||||
| 	mnemonic := strings.Split(privKey, " ") | ||||
| 	if len(mnemonic) == 24 { | ||||
| 		fmt.Println("Got mnemonic key, importing.") | ||||
| 		key := ethutil.MnemonicDecode(mnemonic) | ||||
| 		utils.ImportPrivateKey(key) | ||||
| 	} else if len(mnemonic) == 1 { | ||||
| 		fmt.Println("Got hex key, importing.") | ||||
| 		utils.ImportPrivateKey(privKey) | ||||
| 	} else { | ||||
| 		fmt.Println("Did not recognise format, exiting.") | ||||
| 		return false | ||||
| 	} | ||||
| 	return true | ||||
| } | ||||
|  | ||||
| func (lib *EthLib) CreateAndSetPrivKey() (string, string, string, string) { | ||||
| 	pub, prv := secp256k1.GenerateKeyPair() | ||||
| 	pair := ðutil.Key{PrivateKey: prv, PublicKey: pub} | ||||
| 	ethutil.Config.Db.Put([]byte("KeyRing"), pair.RlpEncode()) | ||||
| 	mne := ethutil.MnemonicEncode(ethutil.Hex(prv)) | ||||
| 	mnemonicString := strings.Join(mne, " ") | ||||
| 	return mnemonicString, fmt.Sprintf("%x", pair.Address()), fmt.Sprintf("%x", prv), fmt.Sprintf("%x", pub) | ||||
| } | ||||
|  | ||||
| func (lib *EthLib) CreateTx(recipient, valueStr, gasStr, gasPriceStr, data string) (string, error) { | ||||
| 	var hash []byte | ||||
| 	var contractCreation bool | ||||
|   | ||||
		Reference in New Issue
	
	Block a user