Browse Source

Changes on deployment process:

- Deploy Contract + Package + Register to Registry.
 - Register to UrlHint.
Display Base64 Value
Encrypt
cl-refactor
yann300 10 years ago
parent
commit
21cdd08275
  1. 44
      mix/FileIo.cpp
  2. 2
      mix/FileIo.h
  3. 41
      mix/qml/DeploymentDialog.qml
  4. 2
      mix/qml/ProjectModel.qml
  5. 1
      mix/qml/StatusPane.qml
  6. 60
      mix/qml/js/ProjectModel.js

44
mix/FileIo.cpp

@ -20,7 +20,6 @@
* Ethereum IDE client.
*/
#include <json/json.h>
#include <QJsonObject>
#include <QDebug>
#include <QDirIterator>
@ -29,10 +28,15 @@
#include <QFileInfo>
#include <QTextStream>
#include <QUrl>
#include <json/json.h>
#include <libdevcrypto/CryptoPP.h>
#include <libdevcrypto/Common.h>
#include <libdevcore/RLP.h>
#include <libdevcrypto/SHA3.h>
#include "FileIo.h"
using namespace dev;
using namespace dev::crypto;
using namespace dev::mix;
void FileIo::makeDir(QString const& _url)
@ -108,7 +112,7 @@ bool FileIo::fileExists(QString const& _url)
return file.exists();
}
QString FileIo::compress(QString const& _deploymentFolder)
QStringList FileIo::compress(QString const& _deploymentFolder)
{
Json::Value manifest;
@ -119,6 +123,14 @@ QString FileIo::compress(QString const& _deploymentFolder)
QDir deployDir = QDir(path);
dev::RLPStream str;
int k = 1;
for (auto item: deployDir.entryInfoList(QDir::Files))
{
QFile qFile(item.filePath());
if (qFile.open(QIODevice::ReadOnly | QIODevice::Text))
k++;
}
str.appendList(k);
for (auto item: deployDir.entryInfoList(QDir::Files))
{
@ -126,19 +138,15 @@ QString FileIo::compress(QString const& _deploymentFolder)
if (qFile.open(QIODevice::ReadOnly | QIODevice::Text))
{
QFileInfo i = QFileInfo(qFile.fileName());
QByteArray fileBytes = i.fileName().toUtf8();
str.append(bytes(fileBytes.begin(), fileBytes.end()));
QByteArray contentBytes = QString().toUtf8();
bytes b = bytes(contentBytes.begin(), contentBytes.end());
str.append(b);
QByteArray _a = qFile.readAll();
str.append(bytes(_a.begin(), _a.end()));
bytes b = bytes(_a.begin(), _a.end());
str.append(b);
Json::Value f;
f["path"] = "/"; //TODO: Manage relative sub folder
f["file"] = "/" + i.fileName().toStdString();
f["contentType"] = "application/html"; //TODO: manage multiple content type
f["hash"] = toHex(dev::sha3(b).ref());
entries.append(f);
}
@ -147,12 +155,6 @@ QString FileIo::compress(QString const& _deploymentFolder)
manifest["entries"] = entries;
QByteArray manifestBytes = "swarm.json";
str.append(bytes(manifestBytes.begin(), manifestBytes.end()));
QByteArray manifestcontentBytes = "application/json";
str.append(bytes(manifestcontentBytes.begin(), manifestcontentBytes.end()));
std::stringstream jsonStr;
jsonStr << manifest;
QByteArray b = QString::fromStdString(jsonStr.str()).toUtf8();
@ -160,17 +162,25 @@ QString FileIo::compress(QString const& _deploymentFolder)
bytes dapp = str.out();
dev::h256 h = dev::sha3(dapp);
QString ret = QString::fromStdString(toHex(h.ref()));
//encrypt
KeyPair key(h);
Secp256k1 enc;
enc.encrypt(key.pub(), dapp);
QUrl url(_deploymentFolder + "package.dapp");
QFile compressed(url.path());
QByteArray qFileBytes((char*)dapp.data(), dapp.size());
if (compressed.open(QIODevice::WriteOnly | QIODevice::Text))
{
compressed.write((char*)dapp.data(), dapp.size());
compressed.write(qFileBytes);
compressed.flush();
}
else
error(tr("Error creating package.dapp"));
compressed.close();
QStringList ret;
ret.append(QString::fromStdString(toHex(h.ref())));
ret.append(qFileBytes.toBase64());
return ret;
}

2
mix/FileIo.h

@ -54,7 +54,7 @@ public:
/// Check if file exists
Q_INVOKABLE bool fileExists(QString const& _url);
/// Compress a folder, @returns sha3 of the compressed file.
Q_INVOKABLE QString compress(QString const& _deploymentFolder);
Q_INVOKABLE QStringList compress(QString const& _deploymentFolder);
private:
QString getHomePath() const;

41
mix/qml/DeploymentDialog.qml

@ -14,15 +14,16 @@ Window {
id: modalDeploymentDialog
modality: Qt.ApplicationModal
width: 520
height: 200
height: 350
visible: false
property alias applicationUrlEth: applicationUrlEth.text
property alias applicationUrlHttp: applicationUrlHttp.text
property string urlHintContract: "29a2e6d3c56ef7713a4e7229c3d1a23406f0161a"
property string packageHash
property alias packageBase64: base64Value.text
property string root: "42f6279a5b6d350e1ce2a9ebef05657c79275c6a";
property string eth: "31f6aee7f26e9d3320753c112ed34bcfc3c989b8";
property string wallet: "c4040ef9635e7503bbbc74b73a9385ac78733d09";
property string urlHintContract: "29a2e6d3c56ef7713a4e7229c3d1a23406f0161a"
color: Style.generic.layout.backgroundColor
@ -75,6 +76,17 @@ Window {
{
id: applicationUrlHttp
}
DefaultLabel
{
text: qsTr("Package: ")
}
TextArea
{
id: base64Value
height: 60
}
}
RowLayout
@ -83,7 +95,8 @@ Window {
anchors.right: parent.right;
anchors.bottomMargin: 10
Button {
text: qsTr("Deploy");
text: qsTr("Deploy on Ethereum");
tooltip: qsTr("Deploy the contract and Package ressources files.")
enabled: applicationUrlHttp.text !== ""
onClicked: {
if (Object.keys(projectModel.deploymentAddresses).length > 0)
@ -94,12 +107,11 @@ Window {
}
Button {
text: qsTr("Rebuild Package");
text: qsTr("Register Web Application");
tooltip: qsTr("Register hosted Web Application.")
enabled: Object.keys(projectModel.deploymentAddresses).length > 0 && applicationUrlHttp.text !== ""
onClicked: {
var date = new Date();
var deploymentId = date.toLocaleString(Qt.locale(), "ddMMyyHHmmsszzz");
ProjectModelCode.finalizeDeployment(deploymentId, projectModel.deploymentAddresses);
ProjectModelCode.registerToUrlHint();
}
}
@ -110,13 +122,14 @@ Window {
Button {
text: qsTr("Check Ownership");
visible : false
onClicked: {
var requests = [];
var ethStr = QEtherHelper.createString("eth");
var ethStr = QEtherHelper.createString("mul");
var ethHash = QEtherHelper.createHash(eth);
requests.push({ //owner
/*requests.push({ //owner
jsonrpc: "2.0",
method: "eth_call",
params: [ { "to": '0x' + modalDeploymentDialog.root, "data": "0xec7b9200" + ethStr.encodeValueAsString() } ],
@ -128,6 +141,13 @@ Window {
method: "eth_call",
params: [ { "to": '0x' + modalDeploymentDialog.root, "data": "0x6be16bed" + ethStr.encodeValueAsString() } ],
id: 4
});*/
requests.push({ //register
jsonrpc: "2.0",
method: "eth_call",
params: [ { "to": '0x' + modalDeploymentDialog.wallet, "data": "0x618242da" + ethStr.encodeValueAsString() } ],
id: 4
});
var jsonRpcUrl = "http://localhost:8080";
@ -154,6 +174,7 @@ Window {
Button {
text: qsTr("Generate registrar init");
visible: false
onClicked: {
console.log("registering eth/wallet")
var jsonRpcRequestId = 0;

2
mix/qml/ProjectModel.qml

@ -21,6 +21,7 @@ Item {
signal newProject(var projectData)
signal documentSaved(var documentId)
signal deploymentStarted()
signal deploymentStepChanged(string message)
signal deploymentComplete()
signal deploymentError(string error)
@ -55,6 +56,7 @@ Item {
function getDocumentIndex(documentId) { return ProjectModelCode.getDocumentIndex(documentId); }
function addExistingFiles(paths) { ProjectModelCode.doAddExistingFiles(paths); }
function deployProject() { ProjectModelCode.deployProject(false); }
function registerToUrlHint() { ProjectModelCode.registerToUrlHint(); }
Connections {
target: appContext

1
mix/qml/StatusPane.qml

@ -47,6 +47,7 @@ Rectangle {
onDeploymentStarted: infoMessage(qsTr("Running deployment..."));
onDeploymentError: infoMessage(error);
onDeploymentComplete: infoMessage(qsTr("Deployment complete"));
onDeploymentStepChanged: infoMessage(message);
}
Connections {
target: codeModel

60
mix/qml/js/ProjectModel.js

@ -332,7 +332,7 @@ function startDeployProject()
}
function finalizeDeployment(deploymentId, addresses) {
//create a dir for frontend files and copy them
deploymentStepChanged(qsTr("Packaging application ..."));
var deploymentDir = projectPath + deploymentId + "/";
fileIo.makeDir(deploymentDir);
for (var i = 0; i < projectListModel.count; i++) {
@ -378,10 +378,14 @@ function finalizeDeployment(deploymentId, addresses) {
deploymentAddresses = addresses;
saveProject();
var hash = fileIo.compress(deploymentDir);
var packageRet = fileIo.compress(deploymentDir);
deploymentDialog.packageHash = packageRet[0];
deploymentDialog.packageBase64 = packageRet[1];
var applicationUrlEth = deploymentDialog.applicationUrlEth;
applicationUrlEth = formatAppUrl(applicationUrlEth);
checkRegistration(applicationUrlEth, deploymentDialog.root, hash, function () {
deploymentStepChanged(qsTr("Registering application on Ethereum ..."));
checkRegistration(applicationUrlEth, deploymentDialog.root, function () {
deploymentComplete();
});
}
@ -404,7 +408,6 @@ function rpcCall(requests, callBack)
deploymentError(errorText);
return;
}
console.log(httpRequest.responseText);
callBack(httpRequest.status, httpRequest.responseText)
}
}
@ -412,19 +415,16 @@ function rpcCall(requests, callBack)
}
function checkRegistration(dappUrl, addr, hash, callBack)
function checkRegistration(dappUrl, addr, callBack)
{
console.log("CALL TO " + addr);
var requests = [];
var data = "";
console.log(JSON.stringify(dappUrl));
if (dappUrl.length > 0)
{
//checking path (register).
var str = createString(dappUrl[0]);
data = "0x6be16bed" + str.encodeValueAsString();
console.log("checking if path exists (register) => " + data);
console.log("adrr : " + '0x' + addr + " param " + data);
console.log("checking if path exists (register) => " + JSON.stringify(dappUrl));
requests.push({
jsonrpc: "2.0",
method: "eth_call",
@ -443,7 +443,7 @@ function checkRegistration(dappUrl, addr, hash, callBack)
}
dappUrl.splice(0, 1);
checkRegistration(dappUrl, address, hash, callBack);
checkRegistration(dappUrl, address, callBack);
});
}
else
@ -470,7 +470,6 @@ function checkRegistration(dappUrl, addr, hash, callBack)
var res = JSON.parse(response);
var currentOwner = res[0].result;
var noOwner = currentOwner.replace('0x', '').replace(/0/g, '') === '';
var bOwner = false;
if (noOwner)
{
@ -484,6 +483,7 @@ function checkRegistration(dappUrl, addr, hash, callBack)
}
else
{
var bOwner = false;
currentOwner = normalizeAddress(currentOwner);
for (var u in res[1].result)
{
@ -499,35 +499,39 @@ function checkRegistration(dappUrl, addr, hash, callBack)
return;
}
}
console.log("setContentHash");
requests.push({
//setContent()
jsonrpc: "2.0",
method: "eth_transact",
params: [ { "to": '0x' + addr, "data": "0x5d574e32" + paramTitle.encodeValueAsString() + hash } ],
params: [ { "to": '0x' + addr, "data": "0x5d574e32" + paramTitle.encodeValueAsString() + deploymentDialog.packageHash } ],
id: jsonRpcRequestId++
});
console.log("reserve and register");
rpcCall(requests, function (httpRequest, response) {
requests = [];
var paramUrlHttp = createString(deploymentDialog.applicationUrlHttp);
requests.push({
//urlHint => suggestUrl
jsonrpc: "2.0",
method: "eth_transact",
params: [ { "to": '0x' + deploymentDialog.urlHintContract, "data": "0x4983e19c" + hash + paramUrlHttp.encodeValueAsString() } ],
id: jsonRpcRequestId++
});
rpcCall(requests, function (httpRequest, response) {
callBack();
});
callBack();
});
});
}
}
function registerToUrlHint()
{
deploymentStepChanged(qsTr("Registering application Ressources (" + deploymentDialog.applicationUrlHttp) + ") ...");
var requests = [];
var paramUrlHttp = createString(deploymentDialog.applicationUrlHttp);
requests.push({
//urlHint => suggestUrl
jsonrpc: "2.0",
method: "eth_transact",
params: [ { "to": '0x' + deploymentDialog.urlHintContract, "data": "0x4983e19c" + deploymentDialog.packageHash + paramUrlHttp.encodeValueAsString() } ],
id: jsonRpcRequestId++
});
rpcCall(requests, function (httpRequest, response) {
deploymentComplete();
});
}
function normalizeAddress(addr)
{
addr = addr.replace('0x', '');

Loading…
Cancel
Save