From 95823a8e5401bb48ec0eecf3643af5552fae939c Mon Sep 17 00:00:00 2001 From: Iuri Matias Date: Thu, 8 Oct 2015 15:30:47 -0400 Subject: [PATCH] make deployment async --- demo/spec/contracts/simple_storage_spec.js | 14 ++- lib/blockchain.js | 2 +- lib/compiler.js | 9 -- lib/deploy.js | 123 ++++++++++++++------- lib/index.js | 17 +-- lib/test.js | 73 ------------ 6 files changed, 106 insertions(+), 132 deletions(-) delete mode 100644 lib/test.js diff --git a/demo/spec/contracts/simple_storage_spec.js b/demo/spec/contracts/simple_storage_spec.js index 359d9d15..343612c2 100644 --- a/demo/spec/contracts/simple_storage_spec.js +++ b/demo/spec/contracts/simple_storage_spec.js @@ -1,4 +1,6 @@ var Embark = require('embark-framework'); +var ethersim = require('ethersim'); +var web3 = require('web3'); Embark.init(); Embark.blockchainConfig.loadConfigFile('config/blockchain.yml'); Embark.contractsConfig.loadConfigFile('config/contracts.yml'); @@ -6,7 +8,17 @@ Embark.contractsConfig.loadConfigFile('config/contracts.yml'); var files = ["app/contracts/simple_storage.sol"]; Embark.contractsConfig.init(files, 'development'); -var EmbarkSpec = Embark.tests(files); + +var Manager = ethersim.Manager; +var Provider = ethersim.Provider; + +console.log("initializing"); +var manager = new Manager(); + +web3.setProvider(new Provider(manager)); +abi = Embark.deployContracts('development', files, "/tmp/abi.js", "chains.json", web3); +console.log(abi); +eval(abi); describe("SimpleStorage", function() { beforeAll(function() { diff --git a/lib/blockchain.js b/lib/blockchain.js index c4687831..9ab5deaf 100644 --- a/lib/blockchain.js +++ b/lib/blockchain.js @@ -75,7 +75,7 @@ Blockchain.prototype.run_command = function(address, use_tmp) { cmd += "--unlock " + address + " "; } - if (config.bootNodes.boot == true){ + if (config.bootNodes !== undefined && config.bootNodes.boot == true){ cmd += "--bootnodes "; for (var i = 0; i < config.bootNodes.enodes.length; i++){ cmd += config.bootNodes.enodes[i] + " "; diff --git a/lib/compiler.js b/lib/compiler.js index 7593f0e1..253bbc13 100644 --- a/lib/compiler.js +++ b/lib/compiler.js @@ -10,15 +10,6 @@ Compiler = function(blockchainConfig) { Compiler.prototype.init = function(env) { var config = this.blockchainConfig.config(env); - - try { - web3.setProvider(new web3.providers.HttpProvider("http://" + config.rpcHost + ":" + config.rpcPort)); - primaryAddress = web3.eth.coinbase; - web3.eth.defaultAccount = primaryAddress; - } catch (e) { - throw new Error("can't connect to " + config.rpcHost + ":" + config.rpcPort + " check if an ethereum node is running"); - } - console.log("address is : " + primaryAddress); }; diff --git a/lib/deploy.js b/lib/deploy.js index d75f7e31..9cabca33 100644 --- a/lib/deploy.js +++ b/lib/deploy.js @@ -32,35 +32,68 @@ Deploy = function(env, contractFiles, blockchainConfig, contractsConfig, chainMa console.log("primary account address is : " + primaryAddress); }; -Deploy.prototype.deploy_contract = function(contractObject, contractParams) { - var transactionHash = contractObject["new"].apply(contractObject, contractParams).transactionHash; - var receipt = null; - var time = 0; - while ((receipt = web3.eth.getTransactionReceipt(transactionHash)) === null || receipt.contractAddress === null) { - sleep(1000); - time += 1; - if (time >= this.blockchainConfig.deployTimeout) { - return false; +Deploy.prototype.deploy_contract = function(contractObject, contractParams, cb) { + console.log("called deploy_contract"); + var callback = function(e, contract) { + console.log("got receipt"); + console.log(arguments); + if(!e && contract.address !== undefined) { + console.log("Contract mined! Address: " + contract.address); + cb(contract.address); } - } - return receipt; + else { + console.log("error deploying"); + exit(); + } + }; + + contractParams.push(callback); + + contractObject["new"].apply(contractObject, contractParams); + + //var transactionHash = contractObject["new"].apply(contractObject, contractParams).transactionHash; + //var receipt = null; + //var time = 0; + //while ((receipt = web3.eth.getTransactionReceipt(transactionHash)) === null || receipt.contractAddress === null) { + // sleep(1000); + // time += 1; + // if (time >= this.blockchainConfig.deployTimeout) { + // return false; + // } + //} + //return receipt; } -Deploy.prototype.deploy_contracts = function(env) { +Deploy.prototype.deploy_contracts = function(env, cb) { this.contractsManager.compileContracts(env); - all_contracts = this.contractsManager.all_contracts; + var all_contracts = this.contractsManager.all_contracts; this.contractDB = this.contractsManager.contractDB; - contractDependencies = this.contractsManager.contractDependencies; - this.deployedContracts = {}; - for (k = 0; k < all_contracts.length; k++) { - className = all_contracts[k]; - contract = this.contractDB[className]; + this.deploy_contract_list(all_contracts.length, env, all_contracts, cb); +} + +Deploy.prototype.deploy_contract_list = function(index, env, all_contracts, cb) { + if(index === 0) { + cb(); + } + else { + var _this = this; + this.deploy_contract_list(index - 1, env, all_contracts, function() { + var className = all_contracts[index - 1]; + _this.deploy_a_contract(env, className, cb); + }); + } +} + +Deploy.prototype.deploy_a_contract = function(env, className, cb) { + var contractDependencies = this.contractsManager.contractDependencies; + var contract = this.contractDB[className]; if (contract.deploy === false) { console.log("skipping " + className); - continue; + cb(); + return; } var realArgs = []; @@ -78,6 +111,7 @@ Deploy.prototype.deploy_contracts = function(env) { //console.log("contract " + className + " at " + contractAddress); console.log("contract " + className + " at " + contract.address); + cb(); } else { var chainContract = this.chainManager.getContract(className, contract.compiled.code, realArgs); @@ -86,6 +120,7 @@ Deploy.prototype.deploy_contracts = function(env) { console.log("contract " + className + " is unchanged and already deployed at " + chainContract.address); this.deployedContracts[className] = chainContract.address; this.execute_cmds(contract.onDeploy); + cb(); } else { @@ -101,31 +136,34 @@ Deploy.prototype.deploy_contracts = function(env) { console.log('trying to obtain ' + className + ' address...'); - while((receipt = this.deploy_contract(contractObject, contractParams)) === false) { - console.log("timeout... failed to deploy contract.. retrying..."); - } + var _this = this; + this.deploy_contract(contractObject, contractParams, function(contractAddress) { + console.log("response!"); - var contractAddress = receipt.contractAddress; + if (web3.eth.getCode(contractAddress) === "0x") { + console.log("========="); + console.log("contract was deployed at " + contractAddress + " but doesn't seem to be working"); + console.log("try adjusting your gas values"); + console.log("========="); + } + else { + console.log("deployed " + className + " at " + contractAddress); + _this.chainManager.addContract(className, contract.compiled.code, realArgs, contractAddress); + _this.chainManager.save(); + } - if (web3.eth.getCode(contractAddress) === "0x") { - console.log("========="); - console.log("contract was deployed at " + contractAddress + " but doesn't seem to be working"); - console.log("try adjusting your gas values"); - console.log("========="); - } - else { - console.log("deployed " + className + " at " + contractAddress); - this.chainManager.addContract(className, contract.compiled.code, realArgs, contractAddress); - this.chainManager.save(); - } + _this.deployedContracts[className] = contractAddress; - this.deployedContracts[className] = contractAddress; + _this.execute_cmds(contract.onDeploy); - this.execute_cmds(contract.onDeploy); + cb(); + }); + + //while((receipt = this.deploy_contract(contractObject, contractParams)) === false) { + // console.log("timeout... failed to deploy contract.. retrying..."); + //} } } - } - }; Deploy.prototype.execute_cmds = function(cmds) { @@ -147,11 +185,14 @@ Deploy.prototype.execute_cmds = function(cmds) { } } -Deploy.prototype.generate_abi_file = function() { +Deploy.prototype.generate_abi_file = function(web3) { var result; - result = "web3.setProvider(new web3.providers.HttpProvider('http://" + this.blockchainConfig.rpcHost + ":" + this.blockchainConfig.rpcPort + "'));"; - result += "web3.eth.defaultAccount = web3.eth.accounts[0];"; + result = ""; + if (web3 === undefined) { + result = "web3.setProvider(new web3.providers.HttpProvider('http://" + this.blockchainConfig.rpcHost + ":" + this.blockchainConfig.rpcPort + "'));"; + result += "web3.eth.defaultAccount = web3.eth.accounts[0];"; + } for(className in this.deployedContracts) { var deployedContract = this.deployedContracts[className]; diff --git a/lib/index.js b/lib/index.js index fcc82d3b..b41ba260 100644 --- a/lib/index.js +++ b/lib/index.js @@ -10,7 +10,7 @@ var syncMe = require('sync-me'); var methodmissing = require('methodmissing'); var jasmine = require('jasmine'); -var Tests = require('./test.js'); +//var Tests = require('./test.js'); var Blockchain = require('./blockchain.js'); var Deploy = require('./deploy.js'); var Release = require('./ipfs.js'); @@ -26,9 +26,9 @@ Embark = { this.chainManager = (new ChainManager()); }, - tests: function(contractFiles) { - return new Tests(this.contractsConfig, contractFiles); - }, + //tests: function() { + // return new Tests(); + //}, startBlockchain: function(env, use_tmp) { var chain = new Blockchain(this.blockchainConfig.config(env)); @@ -45,13 +45,16 @@ Embark = { return chain.getStartChainCommand(use_tmp); }, - deployContracts: function(env, contractFiles, destFile, chainFile) { + deployContracts: function(env, contractFiles, destFile, chainFile, cb) { this.contractsConfig.init(contractFiles, env); this.chainManager.loadConfigFile(chainFile) var deploy = new Deploy(env, contractFiles, this.blockchainConfig.config(env), this.contractsConfig, this.chainManager); - deploy.deploy_contracts(env); - return deploy.generate_abi_file(destFile); + deploy.deploy_contracts(env, function() { + console.log("contracts deployed; generating abi file"); + var result = deploy.generate_abi_file(); + cb(result); + }); }, geth: function(env, args) { diff --git a/lib/test.js b/lib/test.js deleted file mode 100644 index 6c957256..00000000 --- a/lib/test.js +++ /dev/null @@ -1,73 +0,0 @@ -var python = require('python').shell; -var mm = require('methodmissing'); -var sync = require('sync-me'); - -py_exec = function(cmd) { - return sync(python, cmd)[1].trim(); -}; - -TestContractWrapper = (function() { - function TestContractWrapper(contract, className, args) { - this.contract = contract.compiled; - this.className = className; - this.args = args; - this.initializeContract(); - } - - TestContractWrapper.prototype.initializeContract = function() { - example_abi = JSON.stringify(this.contract.info.abiDefinition); - example_binary = this.contract.code.slice(2); - - py_exec("example_abi = '" + example_abi + "'"); - py_exec("example_abi"); - py_exec("example_binary = '" + example_binary + "'.decode('hex')"); - py_exec("example_binary"); - - if (this.args === undefined) { - py_exec(this.className + "_contract = EvmContract(example_abi, example_binary, '" + this.className + "')"); - } - else { - py_exec(this.className + "_contract = EvmContract(example_abi, example_binary, '" + this.className + "', [" + this.args.join(",") + "])"); - } - - this.contractVariable = this.className + "_contract"; - }; - - TestContractWrapper.prototype.execCmd = function(method, args) { - var arg_list = []; - for (var key in args) { - var value = args[key]; - arg_list.push(value); - } - - data = py_exec(this.className + "_contract." + method + "(" + arg_list.join(",") + ")"); - return data; - }; - - return TestContractWrapper; - -})(); - -TestContract = function(contract, className, args) { - var wrapper = new TestContractWrapper(contract, className, args); - var Obj = mm(wrapper, function (key, args) { - return wrapper.execCmd(key, args); - }); - return Obj; -} - -test = function(contractsConfig, contractFiles) { - contractsConfig.init(contractFiles, 'development'); - - contractsConfig.compileContracts(); - this.contractDB = contractsConfig.contractDB; -} - -test.prototype.request = function(className, args) { - var contract = this.contractDB[className]; - py_exec("from ethertdd import EvmContract"); - return TestContract(contract, className, args); -} - -module.exports = test; -