From 0a954152035d467da2772af0e8ad2fffd7216648 Mon Sep 17 00:00:00 2001 From: yann300 Date: Tue, 5 May 2015 16:30:54 +0200 Subject: [PATCH] - provide specific gas value for each tr. - display user friendly gas value (for deploy and register). --- mix/ClientModel.cpp | 19 +++--- mix/ClientModel.h | 2 + mix/qml/DeploymentDialog.qml | 102 ++++++++++++++++---------------- mix/qml/Ether.qml | 4 +- mix/qml/js/NetworkDeployment.js | 25 ++++---- mix/qml/js/TransactionHelper.js | 2 +- 6 files changed, 85 insertions(+), 69 deletions(-) diff --git a/mix/ClientModel.cpp b/mix/ClientModel.cpp index 1be42610c..fa5ec1c27 100644 --- a/mix/ClientModel.cpp +++ b/mix/ClientModel.cpp @@ -137,24 +137,29 @@ void ClientModel::mine() QString ClientModel::newSecret() { KeyPair a = KeyPair::create(); - return QString::fromStdString(toHex(a.secret().ref())); + return QString::fromStdString(dev::toHex(a.secret().ref())); } QString ClientModel::address(QString const& _secret) { - return QString::fromStdString(toHex(KeyPair(Secret(_secret.toStdString())).address().ref())); + return QString::fromStdString(dev::toHex(KeyPair(Secret(_secret.toStdString())).address().ref())); +} + +QString ClientModel::toHex(QString const& _int) +{ + return QString::fromStdString(dev::toHex(dev::u256(_int.toStdString()))); } QString ClientModel::encodeAbiString(QString _string) { ContractCallDataEncoder encoder; - return QString::fromStdString(toHex(encoder.encodeBytes(_string))); + return QString::fromStdString(dev::toHex(encoder.encodeBytes(_string))); } QString ClientModel::encodeStringParam(QString const& _param) { ContractCallDataEncoder encoder; - return QString::fromStdString(toHex(encoder.encodeStringParam(_param, 32))); + return QString::fromStdString(dev::toHex(encoder.encodeStringParam(_param, 32))); } QStringList ClientModel::encodeParams(QVariant const& _param, QString const& _contract, QString const& _function) @@ -179,7 +184,7 @@ QStringList ClientModel::encodeParams(QVariant const& _param, QString const& _co QSolidityType const* type = var->type(); QVariant value = _param.toMap().value(var->name()); encoder.encode(value, type->type()); - ret.push_back(QString::fromStdString(toHex(encoder.encodedData()))); + ret.push_back(QString::fromStdString(dev::toHex(encoder.encodedData()))); } return ret; } @@ -346,7 +351,7 @@ void ClientModel::executeSequence(vector const& _sequence, if (type->type().type == SolidityType::Type::Address && value.toString().startsWith("<") && value.toString().endsWith(">")) { QStringList nb = value.toString().remove("<").remove(">").split(" - "); - value = QVariant(QString::fromStdString("0x" + toHex(deployedContracts.at(nb.back().toInt()).ref()))); + value = QVariant(QString::fromStdString("0x" + dev::toHex(deployedContracts.at(nb.back().toInt()).ref()))); } encoder.encode(value, type->type()); } @@ -616,7 +621,7 @@ RecordLogEntry* ClientModel::lastBlock() const strGas << blockInfo.gasUsed; stringstream strNumber; strNumber << blockInfo.number; - RecordLogEntry* record = new RecordLogEntry(0, QString::fromStdString(strNumber.str()), tr(" - Block - "), tr("Hash: ") + QString(QString::fromStdString(toHex(blockInfo.hash().ref()))), QString(), QString(), QString(), false, RecordLogEntry::RecordType::Block, QString::fromStdString(strGas.str())); + RecordLogEntry* record = new RecordLogEntry(0, QString::fromStdString(strNumber.str()), tr(" - Block - "), tr("Hash: ") + QString(QString::fromStdString(dev::toHex(blockInfo.hash().ref()))), QString(), QString(), QString(), false, RecordLogEntry::RecordType::Block, QString::fromStdString(strGas.str())); QQmlEngine::setObjectOwnership(record, QQmlEngine::JavaScriptOwnership); return record; } diff --git a/mix/ClientModel.h b/mix/ClientModel.h index 3a489622f..91b66c76c 100644 --- a/mix/ClientModel.h +++ b/mix/ClientModel.h @@ -162,6 +162,8 @@ public: Q_INVOKABLE QStringList encodeParams(QVariant const& _param, QString const& _contract, QString const& _function); /// Encode parameter Q_INVOKABLE QString encodeStringParam(QString const& _param); + /// To Hex number + Q_INVOKABLE QString toHex(QString const& _int); public slots: /// Setup state, run transaction sequence, show debugger for the last transaction diff --git a/mix/qml/DeploymentDialog.qml b/mix/qml/DeploymentDialog.qml index 6d26790a5..c8b540946 100644 --- a/mix/qml/DeploymentDialog.qml +++ b/mix/qml/DeploymentDialog.qml @@ -17,6 +17,10 @@ Dialog { width: 735 height: 400 visible: false + property int ownedRegistrarDeployGas: 1179075 + property int ownedRegistrarSetSubRegistrarGas: 44719 + property int ownedRegistrarSetContentHashGas: 43691 + property int urlHintSuggestUrlGas: 62832 property alias applicationUrlEth: applicationUrlEth.text property alias applicationUrlHttp: applicationUrlHttp.text property alias localPackageUrl: localPackageUrl.text @@ -24,9 +28,7 @@ Dialog { property string packageBase64 property string eth: registrarAddr.text property string currentAccount - property string gasToUse: gasToUseInput.text property string gasPrice - property variant gasTotal property variant paramsModel: [] function close() @@ -87,9 +89,8 @@ Dialog { NetworkDeploymentCode.gasPrice(function(price) { gasPrice = price; gasPriceInt.setValue(gasPrice); - gasInt.setValue(NetworkDeploymentCode.gasUsed()); - gasTotal = gasInt.multiply(gasPriceInt); - gasToUseInput.text = gasTotal.value(); + ctrDeployCtrLabel.calculateContractDeployGas(); + ctrRegisterLabel.calculateRegisterGas(); }); } } @@ -126,11 +127,6 @@ Dialog { poolLog.start(); } - BigIntValue - { - id: gasInt - } - BigIntValue { id: gasPriceInt @@ -287,6 +283,10 @@ Dialog { id: statesList textRole: "title" model: projectModel.stateListModel + onCurrentIndexChanged : { + ctrDeployCtrLabel.calculateContractDeployGas(); + ctrRegisterLabel.calculateRegisterGas(); + } } } @@ -324,6 +324,8 @@ Dialog { currentAccount = modelAccounts.get(currentIndex).id; balance.text = balances[currentIndex]; balanceInt.setValue(weiBalances[currentIndex]); + ctrDeployCtrLabel.calculateContractDeployGas(); + ctrRegisterLabel.calculateRegisterGas(); } } model: ListModel { @@ -349,28 +351,47 @@ Dialog { DefaultLabel { text: qsTr("Amount of gas to use for contract deployment: ") + id: ctrDeployCtrLabel + function calculateContractDeployGas() + { + var ether = QEtherHelper.createBigInt(NetworkDeploymentCode.gasUsed()); + var gasTotal = ether.multiply(gasPriceInt); + gasToUseInput.value = QEtherHelper.createEther(gasTotal.value(), QEther.Wei, parent); + gasToUseDeployInput.update(); + } } - DefaultLabel - { - Layout.preferredWidth: 350 + Ether { id: gasToUseInput + displayUnitSelection: false + displayFormattedValue: true + Layout.preferredWidth: 350 } DefaultLabel { text: qsTr("Amount of gas to use for dapp registration: ") + id: ctrRegisterLabel + function calculateRegisterGas() + { + if (!modalDeploymentDialog.visible) + return; + appUrlFormatted.text = NetworkDeploymentCode.formatAppUrl(applicationUrlEth.text).join('/'); + NetworkDeploymentCode.checkPathCreationCost(function(pathCreationCost) + { + var ether = QEtherHelper.createBigInt(pathCreationCost); + var gasTotal = ether.multiply(gasPriceInt); + gasToUseDeployInput.value = QEtherHelper.createEther(gasTotal.value(), QEther.Wei, parent); + gasToUseDeployInput.update(); + }); + } } - BigIntValue - { - id: deployGas; - } - - DefaultLabel - { - Layout.preferredWidth: 350 + Ether { id: gasToUseDeployInput + displayUnitSelection: false + displayFormattedValue: true + Layout.preferredWidth: 350 } DefaultLabel @@ -388,15 +409,7 @@ Dialog { width: 200 id: applicationUrlEth onTextChanged: { - if (!modalDeploymentDialog.visible) - return; - appUrlFormatted.text = NetworkDeploymentCode.formatAppUrl(text).join('/'); - NetworkDeploymentCode.checkPathCreationCost(function(pathCreationCost) - { - deployGas.setValue("" + pathCreationCost + ""); - var gasSpent = deployGas.multiply(gasPriceInt); - gasToUseDeployInput.text = gasSpent.value(); - }); + ctrRegisterLabel.calculateRegisterGas(); } } @@ -431,26 +444,6 @@ Dialog { id: runAction tooltip: qsTr("Deploy contract(s) and Package resources files.") onTriggered: { - if (contractRedeploy.checked) - { - console.log(gasTotal); - if (balanceInt <= gasTotal.add(deployGas)) - { - errorDialog.text = qsTr("Not enough ether to deploy contract."); - errorDialog.open(); - return; - } - } - else - { - if (balanceInt <= deployGas) - { - errorDialog.text = qsTr("Not enough ether to deploy contract."); - errorDialog.open(); - return; - } - } - var inError = []; var ethUrl = NetworkDeploymentCode.formatAppUrl(applicationUrlEth.text); for (var k in ethUrl) @@ -561,6 +554,15 @@ Dialog { iconSource: "qrc:/qml/img/note.png" } + BigIntValue + { + id: registerUrlHintGas + Component.onCompleted: + { + setValue(modalDeploymentDialog.urlHintSuggestUrlGas); + } + } + Action { id: registerAction enabled: rowRegister.isOkToRegister() diff --git a/mix/qml/Ether.qml b/mix/qml/Ether.qml index dd9022b81..7a059e04d 100644 --- a/mix/qml/Ether.qml +++ b/mix/qml/Ether.qml @@ -15,9 +15,11 @@ RowLayout { property bool displayFormattedValue; property bool edit; property variant value; + property bool displayUnitSelection onValueChanged: update() Component.onCompleted: update() + function update() { if (value) @@ -45,13 +47,13 @@ RowLayout { } } readOnly: !edit - visible: edit id: etherValueEdit; } ComboBox { id: units + visible: displayUnitSelection; onCurrentTextChanged: { if (value) diff --git a/mix/qml/js/NetworkDeployment.js b/mix/qml/js/NetworkDeployment.js index bac4b501b..b43dd3637 100644 --- a/mix/qml/js/NetworkDeployment.js +++ b/mix/qml/js/NetworkDeployment.js @@ -23,6 +23,7 @@ .import org.ethereum.qml.QSolidityType 1.0 as QSolidityType Qt.include("TransactionHelper.js") +Qt.include("QEtherHelper.js") var jsonRpcRequestId = 1; @@ -84,7 +85,7 @@ function checkPathCreationCost(callBack) else { deploymentStepChanged(qsTr("Your Dapp can be registered here.")); - callBack((dappUrl.length - 1) * 100000 + 5000); + callBack((dappUrl.length - 1) * (deploymentDialog.ownedRegistrarDeployGas + deploymentDialog.ownedRegistrarSetSubRegistrarGas) + deploymentDialog.ownedRegistrarSetContentHashGas); } }); } @@ -94,7 +95,10 @@ function gasUsed() var gas = 0; var gasCosts = clientModel.gasCosts; for (var g in gasCosts) + { gas += gasCosts[g]; + console.log(" gasCost " + gasCosts[g]); + } return gas; } @@ -152,7 +156,7 @@ function executeTr(trIndex, state, ctrAddresses, callBack) executeTrNextStep(trIndex, state, ctrAddresses, callBack); else { - var gasCost = clientModel.encodeAbiString(clientModel.gasCosts[trIndex]); + var gasCost = clientModel.toHex(clientModel.gasCosts[trIndex]); var rpcParams = { "from": deploymentDialog.currentAccount, "gas": "0x" + gasCost }; var params = replaceParamToken(func.parameters, tr.parameters, ctrAddresses); var encodedParams = clientModel.encodeParams(params, tr.contractId, tr.functionId); @@ -275,6 +279,7 @@ function checkEthPath(dappUrl, checkOnly, callBack) { if (dappUrl.length === 1) { + // convenient for dev purpose, should not be possible in normal env. if (!checkOnly) reserve(deploymentDialog.eth, function() { registerContentHash(deploymentDialog.eth, callBack); // we directly create a dapp under the root registrar. @@ -331,7 +336,6 @@ function isOwner(addr, callBack) function checkRegistration(dappUrl, addr, callBack, checkOnly) { - console.log("checkRegistration " + addr + " " + dappUrl.join('|')); isOwner(addr, function(ret){ if (!ret) { @@ -400,11 +404,11 @@ function continueRegistration(dappUrl, addr, callBack, checkOnly) deploymentStepChanged(txt); //current registrar is owned => ownedregistrar creation and continue. requests = []; - + var gasCost = clientModel.toHex(deploymentDialog.ownedRegistrarDeployGas); requests.push({ jsonrpc: "2.0", method: "eth_sendTransaction", - params: [ { "from": deploymentDialog.currentAccount, "gas": "#ffff", "code": "0x600080547fffffffffffffffffffffffff0000000000000000000000000000000000000000163317815561058990819061003990396000f3007c010000000000000000000000000000000000000000000000000000000060003504630198489281146100a757806302571be3146100d957806321f8a721146100e35780632dff6941146100ed5780633b3b57de1461010d5780635a3a05bd1461013d5780635fd4b08a1461017057806389a69c0e1461017c578063b5c645bd146101b0578063be99a9801461022c578063c3d014d614610264578063d93e75731461029857005b73ffffffffffffffffffffffffffffffffffffffff600435166000908152600160205260409020548060005260206000f35b6000808052602081f35b6000808052602081f35b600435600090815260026020819052604090912001548060005260206000f35b600435600090815260026020908152604082205473ffffffffffffffffffffffffffffffffffffffff1680835291f35b600435600090815260026020908152604082206001015473ffffffffffffffffffffffffffffffffffffffff1680835291f35b60008060005260206000f35b6000546102c89060043590602435903373ffffffffffffffffffffffffffffffffffffffff90811691161461052557610585565b600435600090815260026020819052604090912080546001820154919092015473ffffffffffffffffffffffffffffffffffffffff9283169291909116908273ffffffffffffffffffffffffffffffffffffffff166000528173ffffffffffffffffffffffffffffffffffffffff166020528060405260606000f35b6000546102ce906004359060243590604435903373ffffffffffffffffffffffffffffffffffffffff9081169116146102e0576103af565b6000546102d49060043590602435903373ffffffffffffffffffffffffffffffffffffffff9081169116146103b4576103f1565b6000546102da90600435903373ffffffffffffffffffffffffffffffffffffffff9081169116146103f557610522565b60006000f35b60006000f35b60006000f35b60006000f35b600083815260026020526040902080547fffffffffffffffffffffffff000000000000000000000000000000000000000016831790558061034757827fa6697e974e6a320f454390be03f74955e8978f1a6971ea6730542e37b66179bc60006040a26103ae565b73ffffffffffffffffffffffffffffffffffffffff8216837ff63780e752c6a54a94fc52715dbc5518a3b4c3c2833d301a204226548a2a854560006040a373ffffffffffffffffffffffffffffffffffffffff821660009081526001602052604090208390555b5b505050565b600082815260026020819052604080832090910183905583917fa6697e974e6a320f454390be03f74955e8978f1a6971ea6730542e37b66179bc91a25b5050565b60008181526002602090815260408083205473ffffffffffffffffffffffffffffffffffffffff16835260019091529020548114610432576104b2565b6000818152600260205260408082205473ffffffffffffffffffffffffffffffffffffffff169183917ff63780e752c6a54a94fc52715dbc5518a3b4c3c2833d301a204226548a2a85459190a360008181526002602090815260408083205473ffffffffffffffffffffffffffffffffffffffff16835260019091528120555b600081815260026020819052604080832080547fffffffffffffffffffffffff00000000000000000000000000000000000000009081168255600182018054909116905590910182905582917fa6697e974e6a320f454390be03f74955e8978f1a6971ea6730542e37b66179bc91a25b50565b60008281526002602052604080822060010180547fffffffffffffffffffffffff0000000000000000000000000000000000000000168417905583917fa6697e974e6a320f454390be03f74955e8978f1a6971ea6730542e37b66179bc91a25b505056" } ], + params: [ { "from": deploymentDialog.currentAccount, "gas": "0x" + gasCost, "code": "0x600080547fffffffffffffffffffffffff0000000000000000000000000000000000000000163317815561058990819061003990396000f3007c010000000000000000000000000000000000000000000000000000000060003504630198489281146100a757806302571be3146100d957806321f8a721146100e35780632dff6941146100ed5780633b3b57de1461010d5780635a3a05bd1461013d5780635fd4b08a1461017057806389a69c0e1461017c578063b5c645bd146101b0578063be99a9801461022c578063c3d014d614610264578063d93e75731461029857005b73ffffffffffffffffffffffffffffffffffffffff600435166000908152600160205260409020548060005260206000f35b6000808052602081f35b6000808052602081f35b600435600090815260026020819052604090912001548060005260206000f35b600435600090815260026020908152604082205473ffffffffffffffffffffffffffffffffffffffff1680835291f35b600435600090815260026020908152604082206001015473ffffffffffffffffffffffffffffffffffffffff1680835291f35b60008060005260206000f35b6000546102c89060043590602435903373ffffffffffffffffffffffffffffffffffffffff90811691161461052557610585565b600435600090815260026020819052604090912080546001820154919092015473ffffffffffffffffffffffffffffffffffffffff9283169291909116908273ffffffffffffffffffffffffffffffffffffffff166000528173ffffffffffffffffffffffffffffffffffffffff166020528060405260606000f35b6000546102ce906004359060243590604435903373ffffffffffffffffffffffffffffffffffffffff9081169116146102e0576103af565b6000546102d49060043590602435903373ffffffffffffffffffffffffffffffffffffffff9081169116146103b4576103f1565b6000546102da90600435903373ffffffffffffffffffffffffffffffffffffffff9081169116146103f557610522565b60006000f35b60006000f35b60006000f35b60006000f35b600083815260026020526040902080547fffffffffffffffffffffffff000000000000000000000000000000000000000016831790558061034757827fa6697e974e6a320f454390be03f74955e8978f1a6971ea6730542e37b66179bc60006040a26103ae565b73ffffffffffffffffffffffffffffffffffffffff8216837ff63780e752c6a54a94fc52715dbc5518a3b4c3c2833d301a204226548a2a854560006040a373ffffffffffffffffffffffffffffffffffffffff821660009081526001602052604090208390555b5b505050565b600082815260026020819052604080832090910183905583917fa6697e974e6a320f454390be03f74955e8978f1a6971ea6730542e37b66179bc91a25b5050565b60008181526002602090815260408083205473ffffffffffffffffffffffffffffffffffffffff16835260019091529020548114610432576104b2565b6000818152600260205260408082205473ffffffffffffffffffffffffffffffffffffffff169183917ff63780e752c6a54a94fc52715dbc5518a3b4c3c2833d301a204226548a2a85459190a360008181526002602090815260408083205473ffffffffffffffffffffffffffffffffffffffff16835260019091528120555b600081815260026020819052604080832080547fffffffffffffffffffffffff00000000000000000000000000000000000000009081168255600182018054909116905590910182905582917fa6697e974e6a320f454390be03f74955e8978f1a6971ea6730542e37b66179bc91a25b50565b60008281526002602052604080822060010180547fffffffffffffffffffffffff0000000000000000000000000000000000000000168417905583917fa6697e974e6a320f454390be03f74955e8978f1a6971ea6730542e37b66179bc91a25b505056" } ], id: jsonRpcRequestId++ }); @@ -421,11 +425,12 @@ function continueRegistration(dappUrl, addr, callBack, checkOnly) return; } var crLevel = clientModel.encodeStringParam(dappUrl[0]); + var gasCost = clientModel.toHex(deploymentDialog.ownedRegistrarSetSubRegistrarGas); requests.push({ //setRegister() jsonrpc: "2.0", method: "eth_sendTransaction", - params: [ { "from": deploymentDialog.currentAccount, "gas": "#ffff", "to": '0x' + addr, "data": "0x89a69c0e" + crLevel + deploymentDialog.pad(newCtrAddress) } ], + params: [ { "from": deploymentDialog.currentAccount, "gas": "0x" + gasCost, "to": '0x' + addr, "data": "0x89a69c0e" + crLevel + deploymentDialog.pad(newCtrAddress) } ], id: jsonRpcRequestId++ }); @@ -474,12 +479,12 @@ function registerContentHash(registrar, callBack) console.log(txt); var requests = []; var paramTitle = clientModel.encodeStringParam(projectModel.projectTitle); - + var gasCost = clientModel.toHex(deploymentDialog.ownedRegistrarSetContentHashGas); requests.push({ //setContent() jsonrpc: "2.0", method: "eth_sendTransaction", - params: [ { "from": deploymentDialog.currentAccount, "gas": "0xfffff", "to": '0x' + registrar, "data": "0xc3d014d6" + paramTitle + deploymentDialog.packageHash } ], + params: [ { "from": deploymentDialog.currentAccount, "gas": "0x" + gasCost, "to": '0x' + registrar, "data": "0xc3d014d6" + paramTitle + deploymentDialog.packageHash } ], id: jsonRpcRequestId++ }); rpcCall(requests, function (httpRequest, response) { @@ -494,12 +499,12 @@ function registerToUrlHint() urlHintAddress(function(urlHint){ var requests = []; var paramUrlHttp = clientModel.encodeStringParam(deploymentDialog.applicationUrlHttp); - + var gasCost = clientModel.toHex(deploymentDialog.urlHintSuggestUrlGas); requests.push({ //urlHint => suggestUrl jsonrpc: "2.0", method: "eth_sendTransaction", - params: [ { "to": '0x' + urlHint, "from": deploymentDialog.currentAccount, "gas": "0xfffff", "data": "0x584e86ad" + deploymentDialog.packageHash + paramUrlHttp } ], + params: [ { "to": '0x' + urlHint, "from": deploymentDialog.currentAccount, "gas": "0x" + gasCost, "data": "0x584e86ad" + deploymentDialog.packageHash + paramUrlHttp } ], id: jsonRpcRequestId++ }); diff --git a/mix/qml/js/TransactionHelper.js b/mix/qml/js/TransactionHelper.js index be057917c..b0a5caa9e 100644 --- a/mix/qml/js/TransactionHelper.js +++ b/mix/qml/js/TransactionHelper.js @@ -15,7 +15,7 @@ function defaultTransaction() function rpcCall(requests, callBack) { - var jsonRpcUrl = "http://localhost:8080"; + var jsonRpcUrl = "http://localhost:8545"; var rpcRequest = JSON.stringify(requests); console.log(rpcRequest); var httpRequest = new XMLHttpRequest();