Browse Source

Contract Deployment:

- add files hash
 - add test action (to be removed
cl-refactor
yann300 10 years ago
parent
commit
86d446d2ba
  1. 39
      mix/FileIo.cpp
  2. 2
      mix/FileIo.h
  3. 128
      mix/qml/DeploymentDialog.qml
  4. 2
      mix/qml/TransactionDialog.qml
  5. 189
      mix/qml/js/ProjectModel.js

39
mix/FileIo.cpp

@ -20,6 +20,8 @@
* Ethereum IDE client.
*/
#include <json/json.h>
#include <QJsonObject>
#include <QDebug>
#include <QDirIterator>
#include <QDir>
@ -106,23 +108,18 @@ bool FileIo::fileExists(QString const& _url)
return file.exists();
}
QString FileIo::compress(QString const& _manifest, QString const& _deploymentFolder)
QString FileIo::compress(QString const& _deploymentFolder)
{
Json::Value manifest;
Json::Value entries(Json::arrayValue);
QUrl folder(_deploymentFolder);
QString path(folder.path());
QDir deployDir = QDir(path);
dev::RLPStream str;
QByteArray manifestBytes = "swarm.json";
str.append(bytes(manifestBytes.begin(), manifestBytes.end()));
QByteArray manifestcontentBytes = "application/json";
str.append(bytes(manifestcontentBytes.begin(), manifestcontentBytes.end()));
QByteArray b = _manifest.toUtf8();
str.append(bytes(b.begin(), b.end()));
for (auto item: deployDir.entryInfoList(QDir::Files))
{
QFile qFile(item.filePath());
@ -133,14 +130,34 @@ QString FileIo::compress(QString const& _manifest, QString const& _deploymentFol
str.append(bytes(fileBytes.begin(), fileBytes.end()));
QByteArray contentBytes = QString().toUtf8();
str.append(bytes(contentBytes.begin(), contentBytes.end()));
bytes b = bytes(contentBytes.begin(), contentBytes.end());
str.append(b);
QByteArray _a = qFile.readAll();
str.append(bytes(_a.begin(), _a.end()));
Json::Value f;
f["path"] = "/"; //TODO: Manage relative sub folder
f["file"] = "/" + i.fileName().toStdString();
f["hash"] = toHex(dev::sha3(b).ref());
entries.append(f);
}
qFile.close();
}
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();
str.append(bytes(b.begin(), b.end()));
bytes dapp = str.out();
dev::h256 h = dev::sha3(dapp);
QString ret = QString::fromStdString(toHex(h.ref()));

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& _manifest, QString const& _deploymentFolder);
Q_INVOKABLE QString compress(QString const& _deploymentFolder);
private:
QString getHomePath() const;

128
mix/qml/DeploymentDialog.qml

@ -6,8 +6,10 @@ import QtQuick.Controls.Styles 1.3
import org.ethereum.qml.QEther 1.0
import "js/TransactionHelper.js" as TransactionHelper
import "js/ProjectModel.js" as ProjectModelCode
import "js/QEtherHelper.js" as QEtherHelper
import "."
Window {
id: modalDeploymentDialog
modality: Qt.ApplicationModal
@ -16,6 +18,12 @@ Window {
visible: false
property alias applicationUrlEth: applicationUrlEth.text
property alias applicationUrlHttp: applicationUrlHttp.text
property string root: "42f6279a5b6d350e1ce2a9ebef05657c79275c6a";
property string eth: "31f6aee7f26e9d3320753c112ed34bcfc3c989b8";
property string wallet: "c4040ef9635e7503bbbc74b73a9385ac78733d09";
property string urlHintContract: "29a2e6d3c56ef7713a4e7229c3d1a23406f0161a"
color: Style.generic.layout.backgroundColor
function close()
@ -30,6 +38,16 @@ Window {
visible = true;
}
function pad(h)
{
// TODO move this to QHashType class
while (h.length < 64)
{
h = '0' + h;
}
return h;
}
GridLayout
{
columns: 2
@ -89,5 +107,115 @@ Window {
text: qsTr("Close");
onClicked: close();
}
Button {
text: qsTr("Check Ownership");
onClicked: {
var requests = [];
var ethStr = QEtherHelper.createString("eth");
var ethHash = QEtherHelper.createHash(eth);
requests.push({ //owner
jsonrpc: "2.0",
method: "eth_call",
params: [ { "to": '0x' + modalDeploymentDialog.root, "data": "0xec7b9200" + ethStr.encodeValueAsString() } ],
id: 3
});
requests.push({ //register
jsonrpc: "2.0",
method: "eth_call",
params: [ { "to": '0x' + modalDeploymentDialog.root, "data": "0x6be16bed" + ethStr.encodeValueAsString() } ],
id: 4
});
var jsonRpcUrl = "http://localhost:8080";
var rpcRequest = JSON.stringify(requests);
var httpRequest = new XMLHttpRequest();
httpRequest.open("POST", jsonRpcUrl, true);
httpRequest.setRequestHeader("Content-type", "application/json");
httpRequest.setRequestHeader("Content-length", rpcRequest.length);
httpRequest.setRequestHeader("Connection", "close");
httpRequest.onreadystatechange = function() {
if (httpRequest.readyState === XMLHttpRequest.DONE) {
if (httpRequest.status === 200) {
console.log(httpRequest.responseText);
} else {
var errorText = qsTr("path registration failed ") + httpRequest.status;
console.log(errorText);
}
}
}
httpRequest.send(rpcRequest);
}
}
Button {
text: qsTr("Generate registrar init");
onClicked: {
console.log("registering eth/wallet")
var jsonRpcRequestId = 0;
var requests = [];
var ethStr = QEtherHelper.createString("eth");
var ethHash = QEtherHelper.createHash(eth);
requests.push({ //reserve
jsonrpc: "2.0",
method: "eth_transact",
params: [ { "to": '0x' + modalDeploymentDialog.root, "data": "0x1c83171b" + ethStr.encodeValueAsString() } ],
id: jsonRpcRequestId++
});
console.log("0x7d2e3ce9" + ethStr.encodeValueAsString() + pad(eth));
console.log(ethStr.encodeValueAsString());
console.log(pad(eth));
requests.push({ //setRegister
jsonrpc: "2.0",
method: "eth_transact",
params: [ { "to": '0x' + modalDeploymentDialog.root, "data": "0x96077307" + ethStr.encodeValueAsString() + pad(eth) /*ethHash.encodeValueAsString()*/ } ],
id: jsonRpcRequestId++
});
var walletStr = QEtherHelper.createString("wallet");
var walletHash = QEtherHelper.createHash(wallet);
requests.push({ //reserve
jsonrpc: "2.0",
method: "eth_transact",
params: [ { "to": '0x' + modalDeploymentDialog.eth, "data": "0x1c83171b" + walletStr.encodeValueAsString() } ],
id: jsonRpcRequestId++
});
requests.push({ //setRegister
jsonrpc: "2.0",
method: "eth_transact",
params: [ { "to": '0x' + modalDeploymentDialog.eth, "data": "0x96077307" + walletStr.encodeValueAsString() + pad(wallet) } ],
id: jsonRpcRequestId++
});
var jsonRpcUrl = "http://localhost:8080";
var rpcRequest = JSON.stringify(requests);
var httpRequest = new XMLHttpRequest();
httpRequest.open("POST", jsonRpcUrl, true);
httpRequest.setRequestHeader("Content-type", "application/json");
httpRequest.setRequestHeader("Content-length", rpcRequest.length);
httpRequest.setRequestHeader("Connection", "close");
httpRequest.onreadystatechange = function() {
if (httpRequest.readyState === XMLHttpRequest.DONE) {
if (httpRequest.status === 200) {
console.log(httpRequest.responseText);
} else {
var errorText = qsTr("path registration failed ") + httpRequest.status;
console.log(errorText);
}
}
}
httpRequest.send(rpcRequest);
}
}
}
}

2
mix/qml/TransactionDialog.qml

@ -405,7 +405,7 @@ Window {
return boolViewComp;
else if (type.indexOf("string") !== -1)
return stringViewComp;
else if (type.indexOf("hash") !== -1)
else if (type.indexOf("hash") !== -1 || type.indexOf("address") !== -1)
return hashViewComp;
else
return null;

189
mix/qml/js/ProjectModel.js

@ -23,8 +23,6 @@ Qt.include("QEtherHelper.js")
var htmlTemplate = "<html>\n<head>\n<script>\n</script>\n</head>\n<body>\n<script>\n</script>\n</body>\n</html>";
var contractTemplate = "contract Contract {\n}\n";
var registrarContract = "6fcdee8688e44aebdcddf28a8d87318d38f695ff" /*"0000000000000000000000000000000000000a28"*/
var hintContract = "c4040ef9635e7503bbbc74b73a9385ac78733d09"
function saveAll() {
saveProject();
@ -337,9 +335,6 @@ function finalizeDeployment(deploymentId, addresses) {
//create a dir for frontend files and copy them
var deploymentDir = projectPath + deploymentId + "/";
fileIo.makeDir(deploymentDir);
var manifest = {
entries: []
};
for (var i = 0; i < projectListModel.count; i++) {
var doc = projectListModel.get(i);
if (doc.isContract)
@ -362,12 +357,6 @@ function finalizeDeployment(deploymentId, addresses) {
}
else
fileIo.copyFile(doc.path, deploymentDir + doc.fileName);
var jsonFile = {
path: '/' + doc.fileName,
file: '/' + doc.fileName
}
manifest.entries.push(jsonFile);
}
//write deployment js
var deploymentJs =
@ -389,89 +378,168 @@ function finalizeDeployment(deploymentId, addresses) {
deploymentAddresses = addresses;
saveProject();
var hash = fileIo.compress(JSON.stringify(manifest), deploymentDir);
var hash = fileIo.compress(deploymentDir);
var applicationUrlEth = deploymentDialog.applicationUrlEth;
var applicationUrlHttp = deploymentDialog.applicationUrlHttp;
applicationUrlEth = formatAppUrl(applicationUrlEth);
checkRegistration(applicationUrlEth, registrarContract, hash, function () {
checkRegistration(applicationUrlEth, deploymentDialog.root, hash, function () {
deploymentComplete();
});
}
function rpcCall(requests, callBack)
{
var jsonRpcUrl = "http://localhost:8080";
var rpcRequest = JSON.stringify(requests);
var httpRequest = new XMLHttpRequest();
httpRequest.open("POST", jsonRpcUrl, true);
httpRequest.setRequestHeader("Content-type", "application/json");
httpRequest.setRequestHeader("Content-length", rpcRequest.length);
httpRequest.setRequestHeader("Connection", "close");
httpRequest.onreadystatechange = function() {
if (httpRequest.readyState === XMLHttpRequest.DONE) {
if (httpRequest.status !== 200)
{
var errorText = qsTr("Deployment error: Error while registering Dapp ") + httpRequest.status;
console.log(errorText);
deploymentError(errorText);
return;
}
console.log(httpRequest.responseText);
callBack(httpRequest.status, httpRequest.responseText)
}
}
httpRequest.send(rpcRequest);
}
function checkRegistration(dappUrl, addr, hash, callBack)
{
console.log("CALL TO " + addr);
var requests = [];
var data = "";
console.log(JSON.stringify(dappUrl));
if (dappUrl.length > 0)
{
//checking path (addr).
//checking path (register).
var str = createString(dappUrl[0]);
data = "6be16bed" + str.encodeValueAsString();
data = "0x6be16bed" + str.encodeValueAsString();
console.log("checking if path exists (register) => " + data);
console.log("adrr : " + '0x' + addr + " param " + data);
requests.push({
jsonrpc: "2.0",
method: "eth_call",
params: [ { "to": addr, "data": data } ],
params: [ { "to": '0x' + addr, "data": data } ],
id: jsonRpcRequestId++
});
rpcCall(requests, function (httpRequest, response) {
var address = JSON.parse(response)[0].result.replace('0x', '');
if (address === "")
{
var errorTxt = qsTr("Path does not exists " + JSON.stringify(dappUrl) + " cannot continue");
deploymentError(errorTxt);
console.log(errorTxt);
return;
}
dappUrl.splice(0, 1);
checkRegistration(dappUrl, address, hash, callBack);
});
}
else
{
//finalize (setContentHash).
finalize = true;
var paramTitle = createString(projectModel.projectTitle);
var paramHash = createHash(hash);
data = "5d574e32" + paramTitle.encodeValueAsString() + paramHash.encodeValueAsString();
console.log("finalize (setRegister) => " + data);
requests.push({
jsonrpc: "2.0",
method: "eth_transact",
params: [ { "to": addr, "data": data } ],
id: jsonRpcRequestId++
});
//owner()
jsonrpc: "2.0",
method: "eth_call",
params: [ { "to": '0x' + addr, "data": "0xec7b9200" + paramTitle.encodeValueAsString() } ],
id: jsonRpcRequestId++
});
var paramWebUrl = createString(deploymentDialog.applicationUrlHttp);
var dataHint = "4983e19c" + paramHash.encodeValueAsString() + paramWebUrl.encodeValueAsString();
requests.push({
//accounts
jsonrpc: "2.0",
method: "eth_transact",
params: [ { "to": hintContract, "data": dataHint } ],
method: "eth_accounts",
params: null,
id: jsonRpcRequestId++
});
}
var jsonRpcUrl = "http://localhost:8080";
var rpcRequest = JSON.stringify(requests);
var httpRequest = new XMLHttpRequest();
httpRequest.open("POST", jsonRpcUrl, true);
httpRequest.setRequestHeader("Content-type", "application/json");
httpRequest.setRequestHeader("Content-length", rpcRequest.length);
httpRequest.setRequestHeader("Connection", "close");
httpRequest.onreadystatechange = function() {
if (httpRequest.readyState === XMLHttpRequest.DONE) {
if (httpRequest.status === 200) {
console.log(httpRequest.responseText);
if (dappUrl.length > 0)
rpcCall(requests, function (httpRequest, response) {
requests = [];
var res = JSON.parse(response);
var currentOwner = res[0].result;
var noOwner = currentOwner.replace('0x', '').replace(/0/g, '') === '';
var bOwner = false;
if (noOwner)
{
requests.push({
//reserve()
jsonrpc: "2.0",
method: "eth_transact",
params: [ { "to": '0x' + addr, "data": "0x1c83171b" + paramTitle.encodeValueAsString() } ],
id: jsonRpcRequestId++
});
}
else
{
currentOwner = normalizeAddress(currentOwner);
for (var u in res[1].result)
{
var address = JSON.parse(httpRequest.responseText)[0].result.replace('0x', '');
if (address === "")
deploymentError(qsTr("This Eth Dapp path has not been registered"));
else
{
dappUrl.splice(0, 1);
checkRegistration(dappUrl, address, hash, callBack);
}
if (normalizeAddress(res[1].result[u]) === currentOwner)
bOwner = true;
}
if (!bOwner)
{
var errorTxt = qsTr("Current user is not the owner of this path. Cannot continue")
deploymentError(errorTxt);
console.log(errorTxt);
return;
}
else
callBack();
} else {
var errorText = qsTr("Deployment error: Error while registering Dapp ") + httpRequest.status;
console.log(errorText);
deploymentError(errorText);
}
}
requests.push({
//setContent()
jsonrpc: "2.0",
method: "eth_transact",
params: [ { "to": '0x' + addr, "data": "0x5d574e32" + paramTitle.encodeValueAsString() + hash } ],
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();
});
});
});
}
httpRequest.send(rpcRequest);
}
function normalizeAddress(addr)
{
addr = addr.replace('0x', '');
var i = 0;
for (var k in addr)
{
if (addr[k] !== "0")
break;
else
i++;
}
return addr.substring(i);
}
function formatAppUrl(url)
@ -499,3 +567,4 @@ function formatAppUrl(url)
return ret;
}
}

Loading…
Cancel
Save