Merge branch 'develop'

This commit is contained in:
Iuri Matias 2015-08-02 08:07:03 -04:00
commit 72dec76cde
18 changed files with 211 additions and 38 deletions

View File

@ -25,7 +25,7 @@ var deploy = function(env, embarkConfig) {
} }
program program
.version('0.7.2') .version('0.7.3')
program.command('new [name]').description('New application').action(function(name) { program.command('new [name]').description('New application').action(function(name) {
if (name === undefined) { if (name === undefined) {

View File

@ -64,7 +64,7 @@ module.exports = (grunt) ->
tasks: ["concat"] tasks: ["concat"]
css: css:
files: ["<%= concat.css.src %>"] files: ["<%= files.css.src %>"]
tasks: ["concat"] tasks: ["concat"]
coffee: coffee:
@ -75,6 +75,10 @@ module.exports = (grunt) ->
files: ["<%= files.contracts.src %>"] files: ["<%= files.contracts.src %>"]
tasks: ["deploy", "concat", "copy"] tasks: ["deploy", "concat", "copy"]
config:
files: ["config/blockchain.yml", "config/contracts.yml"]
tasks: ["deploy", "concat", "copy"]
copy: copy:
html: html:
files: files:

View File

@ -10,7 +10,7 @@
"license": "ISC", "license": "ISC",
"homepage": "", "homepage": "",
"devDependencies": { "devDependencies": {
"embark-framework": "^0.7.2", "embark-framework": "^0.7.3",
"grunt-embark": "^0.2.0", "grunt-embark": "^0.2.0",
"grunt-contrib-clean": "^0.6.0", "grunt-contrib-clean": "^0.6.0",
"grunt-contrib-coffee": "^0.13.0", "grunt-contrib-coffee": "^0.13.0",

View File

@ -5,7 +5,7 @@ Embark.contractsConfig.loadConfigFile('config/contracts.yml');
var files = ["app/contracts/simple_storage.sol"]; var files = ["app/contracts/simple_storage.sol"];
Embark.contractsConfig.init(files); Embark.contractsConfig.init(files, 'development');
var EmbarkSpec = Embark.tests(files); var EmbarkSpec = Embark.tests(files);
describe("SimpleStorage", function() { describe("SimpleStorage", function() {

View File

@ -1,14 +1,15 @@
var miner_var;
if (admin.miner === undefined) {
miner_var = miner;
}
else {
miner_var = admin.miner;
}
miner_var.setEtherbase(web3.eth.accounts[0]);
setInterval(function() { setInterval(function() {
var miner_var;
if (admin.miner === undefined) {
miner_var = miner;
}
else {
miner_var = admin.miner;
}
var minimalAmount = (web3.eth.getBalance(web3.eth.coinbase) >= 15000000000000000000); var minimalAmount = (web3.eth.getBalance(web3.eth.coinbase) >= 15000000000000000000);
var pendingTransactions = function() { var pendingTransactions = function() {
if (web3.eth.pendingTransactions === undefined || web3.eth.pendingTransactions === null) { if (web3.eth.pendingTransactions === undefined || web3.eth.pendingTransactions === null) {

View File

@ -18,6 +18,7 @@ Blockchain.prototype.generate_basic_command = function() {
cmd += "--port " + config.port + " "; cmd += "--port " + config.port + " ";
cmd += "--rpc "; cmd += "--rpc ";
cmd += "--rpcport " + config.rpcPort + " "; cmd += "--rpcport " + config.rpcPort + " ";
cmd += "--rpcaddr " + config.rpcHost + " ";
cmd += "--networkid " + config.networkId + " "; cmd += "--networkid " + config.networkId + " ";
cmd += "--rpccorsdomain \"" + config.rpcWhitelist + "\" "; cmd += "--rpccorsdomain \"" + config.rpcWhitelist + "\" ";

View File

@ -8,15 +8,17 @@ ContractsConfig = function(blockchainConfig, compiler) {
this.contractFiles = []; this.contractFiles = [];
} }
ContractsConfig.prototype.init = function(files) { ContractsConfig.prototype.init = function(files, env) {
this.all_contracts = []; this.all_contracts = [];
this.contractDB = {}; this.contractDB = {};
this.contractFiles = files; this.contractFiles = files;
this.contractDependencies = {}; this.contractDependencies = {};
this.contractStubs = {};
//TODO: have to specify environment otherwise wouldn't work with staging //TODO: have to specify environment otherwise wouldn't work with staging
if (this.blockchainConfig.config != undefined) { if (this.blockchainConfig.config != undefined) {
this.blockchainConfig = this.blockchainConfig.config('development'); //this.blockchainConfig = this.blockchainConfig.config('development');
this.blockchainConfig = this.blockchainConfig.config(env);
} }
}; };
@ -38,6 +40,15 @@ ContractsConfig.prototype.config = function(env) {
return this.contractConfig[env]; return this.contractConfig[env];
}; };
ContractsConfig.prototype.is_a_token = function(target, compiled_contracts) {
for (var className in compiled_contracts) {
if (this.contractStubs[className] && this.contractStubs[className].indexOf(target) >= 0) {
return true;
}
}
return false;
};
ContractsConfig.prototype.compileContracts = function(env) { ContractsConfig.prototype.compileContracts = function(env) {
var contractFile, source, j; var contractFile, source, j;
var contractsConfig = this.config(env); var contractsConfig = this.config(env);
@ -59,6 +70,8 @@ ContractsConfig.prototype.compileContracts = function(env) {
this.contractDependencies[className].push(arg.substr(1)); this.contractDependencies[className].push(arg.substr(1));
} }
} }
this.contractStubs[className] = options.stubs;
} }
} }
@ -68,10 +81,14 @@ ContractsConfig.prototype.compileContracts = function(env) {
contractFile = this.contractFiles[j]; contractFile = this.contractFiles[j];
source = fs.readFileSync(contractFile).toString() source = fs.readFileSync(contractFile).toString()
console.log("compiling " + contractFile);
compiled_contracts = this.compiler.compile(source); compiled_contracts = this.compiler.compile(source);
for (className in compiled_contracts) { for (var className in compiled_contracts) {
var contract = compiled_contracts[className]; var contract = compiled_contracts[className];
if (this.is_a_token(className, compiled_contracts)) {
continue;
}
all_compiled_contracts[className] = contract; all_compiled_contracts[className] = contract;
this.all_contracts.push(className); this.all_contracts.push(className);
this.contractDB[className] = { this.contractDB[className] = {

View File

@ -3,7 +3,12 @@ var fs = require('fs');
var grunt = require('grunt'); var grunt = require('grunt');
var readYaml = require('read-yaml'); var readYaml = require('read-yaml');
var Config = require('./config/config.js'); var Config = require('./config/config.js');
var sleep = require('sleep');
// Ugly, but sleep lib has issues on osx
sleep = function sleep(ms) {
var start = new Date().getTime();
while (new Date().getTime() < start + ms);
}
Deploy = function(env, contractFiles, blockchainConfig, contractsConfig) { Deploy = function(env, contractFiles, blockchainConfig, contractsConfig) {
//this.blockchainConfig = (new Config.Blockchain()).loadConfigFile('config/blockchain.yml').config(env); //this.blockchainConfig = (new Config.Blockchain()).loadConfigFile('config/blockchain.yml').config(env);
@ -22,9 +27,23 @@ Deploy = function(env, contractFiles, blockchainConfig, contractsConfig) {
throw new Error("==== can't connect to " + this.blockchainConfig.rpcHost + ":" + this.blockchainConfig.rpcPort + " check if an ethereum node is running"); throw new Error("==== can't connect to " + this.blockchainConfig.rpcHost + ":" + this.blockchainConfig.rpcPort + " check if an ethereum node is running");
} }
console.log("address is : " + primaryAddress); 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 >= 20) {
return false;
}
}
return receipt;
}
Deploy.prototype.deploy_contracts = function(env) { Deploy.prototype.deploy_contracts = function(env) {
this.contractsManager.compileContracts(env); this.contractsManager.compileContracts(env);
all_contracts = this.contractsManager.all_contracts; all_contracts = this.contractsManager.all_contracts;
@ -64,19 +83,25 @@ Deploy.prototype.deploy_contracts = function(env) {
gasPrice: contract.gasPrice gasPrice: contract.gasPrice
}); });
var transactionHash = contractObject["new"].apply(contractObject, contractParams).transactionHash;
// TODO: get this with sync until a different mechanism is implemented
//this.deployedContracts[className] = contractAddress;
//console.log("address is " + contractAddress);
console.log('trying to obtain ' + className + ' address...'); console.log('trying to obtain ' + className + ' address...');
var receipt = null;
while ((receipt = web3.eth.getTransactionReceipt(transactionHash)) === null || receipt.contractAddress === null) { while((receipt = this.deploy_contract(contractObject, contractParams)) === false) {
sleep.sleep(1); console.log("timeout... failed to deploy contract.. retrying...");
} }
var contractAddress = receipt.contractAddress; 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.deployedContracts[className] = contractAddress; this.deployedContracts[className] = contractAddress;
console.log('address is ' + contractAddress);
console.log("deployed " + className + " at " + contractAddress); console.log("deployed " + className + " at " + contractAddress);
} }

View File

@ -34,7 +34,7 @@ Embark = {
}, },
deployContracts: function(env, contractFiles, destFile) { deployContracts: function(env, contractFiles, destFile) {
this.contractsConfig.init(contractFiles); this.contractsConfig.init(contractFiles, env);
var deploy = new Deploy(env, contractFiles, this.blockchainConfig.config(env), this.contractsConfig); var deploy = new Deploy(env, contractFiles, this.blockchainConfig.config(env), this.contractsConfig);
deploy.deploy_contracts(env); deploy.deploy_contracts(env);
return deploy.generate_abi_file(destFile); return deploy.generate_abi_file(destFile);

View File

@ -57,7 +57,7 @@ TestContract = function(contract, className, args) {
} }
test = function(contractsConfig, contractFiles) { test = function(contractsConfig, contractFiles) {
contractsConfig.init(contractFiles); contractsConfig.init(contractFiles, 'development');
contractsConfig.compileContracts(); contractsConfig.compileContracts();
this.contractDB = contractsConfig.contractDB; this.contractDB = contractsConfig.contractDB;

View File

@ -1,6 +1,6 @@
{ {
"name": "embark-framework", "name": "embark-framework",
"version": "0.7.2", "version": "0.7.3",
"description": "", "description": "",
"scripts": { "scripts": {
"test": "echo \"Error: no test specified\" && exit 1" "test": "echo \"Error: no test specified\" && exit 1"
@ -23,7 +23,6 @@
"python": "^0.0.4", "python": "^0.0.4",
"read-yaml": "^1.0.0", "read-yaml": "^1.0.0",
"shelljs": "^0.5.0", "shelljs": "^0.5.0",
"sleep": "^3.0.0",
"sync-me": "^0.1.1", "sync-me": "^0.1.1",
"toposort": "^0.2.10", "toposort": "^0.2.10",
"web3": "^0.8.1", "web3": "^0.8.1",

View File

@ -47,7 +47,7 @@ describe('embark.config.contracts', function() {
] ]
contractsConfig = new Config.Contracts(blockchainConfig, compiler); contractsConfig = new Config.Contracts(blockchainConfig, compiler);
contractsConfig.loadConfigFile('test/support/contracts.yml'); contractsConfig.loadConfigFile('test/support/contracts.yml');
contractsConfig.init(files); contractsConfig.init(files, 'development');
contractsConfig.compileContracts(); contractsConfig.compileContracts();
}); });
@ -66,7 +66,7 @@ describe('embark.config.contracts', function() {
] ]
contractsConfig = new Config.Contracts(blockchainConfig, compiler); contractsConfig = new Config.Contracts(blockchainConfig, compiler);
contractsConfig.loadConfigFile('test/support/arguments.yml'); contractsConfig.loadConfigFile('test/support/arguments.yml');
contractsConfig.init(files); contractsConfig.init(files, 'development');
contractsConfig.compileContracts('development'); contractsConfig.compileContracts('development');
}); });
@ -82,7 +82,7 @@ describe('embark.config.contracts', function() {
] ]
contractsConfig = new Config.Contracts(blockchainConfig, compiler); contractsConfig = new Config.Contracts(blockchainConfig, compiler);
contractsConfig.loadConfigFile('test/support/instances.yml'); contractsConfig.loadConfigFile('test/support/instances.yml');
contractsConfig.init(files); contractsConfig.init(files, 'development');
contractsConfig.compileContracts('development'); contractsConfig.compileContracts('development');
}); });
@ -91,6 +91,23 @@ describe('embark.config.contracts', function() {
}); });
}); });
context("contracts as arguments to other contracts with stubs", function() {
before(function() {
files = [
'test/support/contracts/crowdsale.sol',
'test/support/contracts/token.sol'
]
contractsConfig = new Config.Contracts(blockchainConfig, compiler);
contractsConfig.loadConfigFile('test/support/arguments2.yml');
contractsConfig.init(files, 'development');
contractsConfig.compileContracts('development');
});
it('add contracts to a list', function() {
assert.deepEqual(contractsConfig.all_contracts, [ "token", "Crowdsale" ]);
});
});
}); });
}); });

View File

@ -9,7 +9,7 @@ setDeployConfig = function(config) {
var compiler = new Compiler(_blockchainConfig); var compiler = new Compiler(_blockchainConfig);
var contractsConfig = new Config.Contracts(blockchainConfig, compiler); var contractsConfig = new Config.Contracts(blockchainConfig, compiler);
contractsConfig.loadConfigFile(config.contracts); contractsConfig.loadConfigFile(config.contracts);
contractsConfig.init(config.files); contractsConfig.init(config.files, 'development');
compiler.init('development'); compiler.init('development');
return new Deploy('development', config.files, blockchainConfig, contractsConfig); return new Deploy('development', config.files, blockchainConfig, contractsConfig);
} }
@ -66,6 +66,33 @@ describe('embark.deploy', function() {
}); });
}); });
describe('contracts as arguments to other contracts with stubs', function() {
var files = [
'test/support/contracts/crowdsale.sol',
'test/support/contracts/token.sol'
];
describe('#deploy_contracts', function() {
var deploy = setDeployConfig({
files: files,
blockchain: 'test/support/blockchain.yml',
contracts: 'test/support/arguments2.yml'
});
deploy.deploy_contracts("development");
it("should deploy contracts", function() {
var all_contracts = ['token', 'Crowdsale'];
for(var i=0; i < all_contracts.length; i++) {
var className = all_contracts[i];
assert.equal(deploy.deployedContracts.hasOwnProperty(className), true);
}
});
});
});
describe('contracts instances', function() { describe('contracts instances', function() {
var files = [ var files = [
'test/support/contracts/simple_storage.sol' 'test/support/contracts/simple_storage.sol'

View File

@ -0,0 +1,13 @@
development:
token:
args:
Crowdsale:
stubs:
- token
args:
- 0x123
- 100000000000000000000
- 30
- 20000000000000000
- $token
staging:

View File

@ -6,7 +6,7 @@ development:
genesis_block: config/genesis.json genesis_block: config/genesis.json
datadir: /tmp/embark datadir: /tmp/embark
mine_when_needed: true mine_when_needed: true
gas_limit: 500000 gas_limit: 1000000
gas_price: 10000000000000 gas_price: 10000000000000
console: false console: false
account: account:

View File

@ -0,0 +1,51 @@
contract token { mapping (address => uint) public coinBalanceOf; function token() {} function sendCoin(address receiver, uint amount) returns(bool sufficient) { } }
contract Crowdsale {
address public beneficiary;
uint public fundingGoal; uint public amountRaised; uint public deadline; uint public price;
token public tokenReward;
Funder[] public funders;
event FundTransfer(address backer, uint amount, bool isContribution);
/* data structure to hold information about campaign contributors */
struct Funder {
address addr;
uint amount;
}
/* at initialization, setup the owner */
function Crowdsale(address _beneficiary, uint _fundingGoal, uint _duration, uint _price, token _reward) {
beneficiary = _beneficiary;
fundingGoal = _fundingGoal;
deadline = now + _duration * 1 minutes;
price = _price;
tokenReward = token(_reward);
}
/* The function without name is the default function that is called whenever anyone sends funds to a contract */
function () {
uint amount = msg.value;
funders[funders.length++] = Funder({addr: msg.sender, amount: amount});
amountRaised += amount;
tokenReward.sendCoin(msg.sender, amount / price);
FundTransfer(msg.sender, amount, true);
}
modifier afterDeadline() { if (now >= deadline) _ }
/* checks if the goal or time limit has been reached and ends the campaign */
function checkGoalReached() afterDeadline {
if (amountRaised >= fundingGoal){
beneficiary.send(amountRaised);
FundTransfer(beneficiary, amountRaised, false);
} else {
FundTransfer(0, 11, false);
for (uint i = 0; i < funders.length; ++i) {
funders[i].addr.send(funders[i].amount);
FundTransfer(funders[i].addr, funders[i].amount, false);
}
}
suicide(beneficiary);
}
}

View File

@ -0,0 +1,18 @@
contract token {
mapping (address => uint) public coinBalanceOf;
event CoinTransfer(address sender, address receiver, uint amount);
/* Initializes contract with initial supply tokens to the creator of the contract */
function token(uint supply) {
coinBalanceOf[msg.sender] = (supply || 10000);
}
/* Very simple trade function */
function sendCoin(address receiver, uint amount) returns(bool sufficient) {
if (coinBalanceOf[msg.sender] < amount) return false;
coinBalanceOf[msg.sender] -= amount;
coinBalanceOf[receiver] += amount;
CoinTransfer(msg.sender, receiver, amount);
return true;
}
}

View File

@ -14,7 +14,7 @@ describe('embark.test', function() {
var compiler = new Compiler(_blockchainConfig); var compiler = new Compiler(_blockchainConfig);
var contractsConfig = new Config.Contracts(blockchainConfig, compiler); var contractsConfig = new Config.Contracts(blockchainConfig, compiler);
contractsConfig.loadConfigFile('test/support/contracts.yml'); contractsConfig.loadConfigFile('test/support/contracts.yml');
contractsConfig.init(files); contractsConfig.init(files, 'development');
describe('simple test', function() { describe('simple test', function() {
var embarkSpec = new Test(contractsConfig, files); var embarkSpec = new Test(contractsConfig, files);