From de9dff33977e13362620c58dc66647885c851bea Mon Sep 17 00:00:00 2001 From: Iuri Matias Date: Wed, 1 Jul 2015 19:49:49 -0400 Subject: [PATCH] refactor: determine contract dependencies + add specs --- lib/config/contracts.js | 45 +++++++++++++++++++++++++++++- lib/deploy.js | 42 ++-------------------------- package.json | 3 +- test/config.contracts.js | 19 +++++++++++++ test/support/arguments.yml | 14 ++++++++++ test/support/contracts/wallet.sol | 8 ++++++ test/support/contracts/wallets.sol | 9 ++++++ 7 files changed, 98 insertions(+), 42 deletions(-) create mode 100644 test/support/arguments.yml create mode 100644 test/support/contracts/wallet.sol create mode 100644 test/support/contracts/wallets.sol diff --git a/lib/config/contracts.js b/lib/config/contracts.js index d18619625..e21549b34 100644 --- a/lib/config/contracts.js +++ b/lib/config/contracts.js @@ -1,12 +1,15 @@ +indexOf = [].indexOf || function(item) { for (var i = 0, l = this.length; i < l; i++) { if (i in this && this[i] === item) return i; } return -1; }; var readYaml = require('read-yaml'); var fs = require('fs'); var Blockchain = require('./blockchain.js'); +var toposort = require('toposort'); ContractsConfig = function(files, blockchainConfig, web3) { this.all_contracts = []; this.contractDB = {}; this.contractFiles = files; this.web3 = web3; + this.contractDependencies = {}; try { this.web3.setProvider(new this.web3.providers.HttpProvider("http://" + blockchainConfig.rpcHost + ":" + blockchainConfig.rpcPort)); @@ -38,8 +41,27 @@ ContractsConfig.prototype.config = function(env) { return this.contractConfig[env]; } -ContractsConfig.prototype.compileContracts = function() { +ContractsConfig.prototype.compileContracts = function(env) { var contractFile, source, j; + var contractsConfig = this.config(env); + + if (contractsConfig != null) { + for (className in contractsConfig) { + options = contractsConfig[className]; + if (options.args == null) continue; + + ref = options.args; + for (j = 0; j < ref.length; j++) { + arg = ref[j]; + if (arg[0] === "$") { + if (this.contractDependencies[className] === void 0) { + this.contractDependencies[className] = []; + } + this.contractDependencies[className].push(arg.substr(1)); + } + } + } + } for (j = 0; j < this.contractFiles.length; j++) { contractFile = this.contractFiles[j]; @@ -53,6 +75,27 @@ ContractsConfig.prototype.compileContracts = function() { this.contractDB[className] = contract; } } + + this.sortContracts(); +} + +ContractsConfig.prototype.sortContracts = function() { + var converted_dependencies = [], i; + + for(contract in this.contractDependencies) { + var dependencies = this.contractDependencies[contract]; + for(i=0; i < dependencies.length; i++) { + converted_dependencies.push([contract, dependencies[i]]); + } + } + + var orderedDependencies = toposort(converted_dependencies).reverse(); + + this.all_contracts = this.all_contracts.sort(function(a,b) { + var order_a = orderedDependencies.indexOf(a); + var order_b = orderedDependencies.indexOf(b); + return order_a - order_b; + });; } module.exports = ContractsConfig diff --git a/lib/deploy.js b/lib/deploy.js index 764fcfc91..4bd679dd0 100644 --- a/lib/deploy.js +++ b/lib/deploy.js @@ -27,48 +27,10 @@ deployContracts = function(env, contractFiles, destFile) { result = "web3.setProvider(new web3.providers.HttpProvider('http://" + blockchainConfig.rpcHost + ":" + blockchainConfig.rpcPort + "'));"; result += "web3.eth.defaultAccount = web3.eth.accounts[0];"; - contractDependencies = {}; - - if (contractsConfig != null) { - for (className in contractsConfig) { - options = contractsConfig[className]; - if (options.args == null) { - continue; - } - ref = options.args; - for (i = 0, len = ref.length; i < len; i++) { - arg = ref[i]; - if (arg[0] === "$") { - if (contractDependencies[className] === void 0) { - contractDependencies[className] = []; - } - contractDependencies[className].push(arg.substr(1)); - } - } - } - } - - contractsManager.compileContracts(); + contractsManager.compileContracts(env); all_contracts = contractsManager.all_contracts; contractDB = contractsManager.contractDB; - - all_contracts.sort((function(_this) { - return function(a, b) { - var contract_1, contract_2; - contract_1 = contractDependencies[a]; - contract_2 = contractDependencies[b]; - if (indexOf.call(contract_1, a) >= 0 && indexOf.call(contract_2, b) >= 0) { - console.log("looks like you have a circular dependency between " + a + " and " + b); - return exit; - } else if (indexOf.call(contract_1, b) >= 0) { - return 1; - } else if (indexOf.call(contract_2, a) >= 0) { - return -1; - } else { - return 0; - } - }; - })(this)); + contractDependencies = contractsManager.contractDependencies; deployedContracts = {}; diff --git a/package.json b/package.json index 256051ffe..aae94e0df 100644 --- a/package.json +++ b/package.json @@ -34,7 +34,8 @@ "sync-me": "^0.1.1", "python": "^0.0.4", "methodmissing": "^0.0.3", - "jasmine": "^2.3.1" + "jasmine": "^2.3.1", + "toposort": "^0.2.10" }, "author": "Iuri Matias ", "contributors": [], diff --git a/test/config.contracts.js b/test/config.contracts.js index a8c6fa522..33795e994 100644 --- a/test/config.contracts.js +++ b/test/config.contracts.js @@ -56,6 +56,25 @@ describe('embark.config.contracts', function() { assert.deepEqual(contractsConfig.all_contracts, [ "SimpleStorage", "AnotherStorage" ]); }); }); + + context("contracts as arguments to other contracts", function() { + before(function() { + files = [ + 'test/support/contracts/wallet.sol', + 'test/support/contracts/simple_storage.sol', + 'test/support/contracts/another_storage.sol', + 'test/support/contracts/wallets.sol' + ] + contractsConfig = new Config.Contracts(files, blockchainConfig, web3); + contractsConfig.loadConfigFile('test/support/arguments.yml'); + contractsConfig.compileContracts('development'); + }); + + it('add contracts to a list', function() { + assert.deepEqual(contractsConfig.all_contracts, [ "SimpleStorage", "AnotherStorage", "Wallet", "Wallets" ]); + }); + }); }); + }); diff --git a/test/support/arguments.yml b/test/support/arguments.yml new file mode 100644 index 000000000..fc0fe03bf --- /dev/null +++ b/test/support/arguments.yml @@ -0,0 +1,14 @@ +development: + Wallet: + args: + - $AnotherStorage + SimpleStorage: + args: + - 100 + AnotherStorage: + args: + - 100 + Wallets: + args: + - $Wallet +staging: diff --git a/test/support/contracts/wallet.sol b/test/support/contracts/wallet.sol new file mode 100644 index 000000000..576e8648f --- /dev/null +++ b/test/support/contracts/wallet.sol @@ -0,0 +1,8 @@ +contract Wallet { + address currency; + + function Wallet(address c) { + currency = c; + } + +} diff --git a/test/support/contracts/wallets.sol b/test/support/contracts/wallets.sol new file mode 100644 index 000000000..38e3f0eb8 --- /dev/null +++ b/test/support/contracts/wallets.sol @@ -0,0 +1,9 @@ +contract Wallets { + address wallet; + + function Wallet(address w) { + wallet = w; + } + +} +