implement contract tracking

This commit is contained in:
Iuri Matias 2016-09-24 21:10:47 -04:00
parent c3beb51327
commit 03f81c47d7
6 changed files with 132 additions and 10 deletions

20
demo/chains.json Normal file
View File

@ -0,0 +1,20 @@
{
"0xb6cfeab83614da04c03db0fb8a6787a45d0be8d576fcc6f8f457a5a816d22ab3": {
"name": "development",
"networkId": "",
"contracts": {
"288f087742d513019f59539bbf4f07b352e14327e0e7b8ed4bc7c33e34fbc192": {
"address": "0xab47369d82950224a1698d4a856cfa175ba9cf84",
"name": "SimpleStorage"
},
"5a52b16abb7dfccfc675550d0daba1683a3cf7e80fb5f0e199301f7dd57237fb": {
"address": "0xbd2b5c34a2a85d3ae5e903e0015a07868c0d97c3",
"name": "SimpleStorage"
},
"708fa6b699f419627ab3c4c2d9c82f8f1a6fab03c122d0a9ee55d2d0d0ad1e4b": {
"address": "0x7a72b8be758afe7d3e421e7d32c81c605fec333d",
"name": "token"
}
}
}
}

View File

@ -1,11 +1,14 @@
var fs = require('fs'); var fs = require('fs');
var grunt = require('grunt'); var grunt = require('grunt');
// TODO: add wrapper for fs so it can also work in the browser
// can work with both read and save
var Config = function(env) { var Config = function(env) {
this.env = env; this.env = env;
this.blockchainConfig = {}; this.blockchainConfig = {};
this.contractsConfig = {}; this.contractsConfig = {};
this.pipelineConfig = {}; this.pipelineConfig = {};
this.chainTracker = {};
this.assetFiles = {}; this.assetFiles = {};
this.contractsFiles = []; this.contractsFiles = [];
this.configDir = 'config/'; this.configDir = 'config/';
@ -17,12 +20,14 @@ Config.prototype.loadConfigFiles = function(options) {
this.loadPipelineConfigFile(); this.loadPipelineConfigFile();
this.loadBlockchainConfigFile(); this.loadBlockchainConfigFile();
this.loadContractsConfigFile(); this.loadContractsConfigFile();
this.loadChainTrackerFile();
}; };
Config.prototype.reloadConfig = function() { Config.prototype.reloadConfig = function() {
this.loadPipelineConfigFile(); this.loadPipelineConfigFile();
this.loadBlockchainConfigFile(); this.loadBlockchainConfigFile();
this.loadContractsConfigFile(); this.loadContractsConfigFile();
this.loadChainTrackerFile();
}; };
Config.prototype.loadBlockchainConfigFile = function() { Config.prototype.loadBlockchainConfigFile = function() {
@ -51,6 +56,20 @@ Config.prototype.loadPipelineConfigFile = function() {
this.configDir = this.embarkConfig.config; this.configDir = this.embarkConfig.config;
}; };
Config.prototype.loadChainTrackerFile = function() {
//var self = this;
var chainTracker;
try {
chainTracker = JSON.parse(fs.readFileSync("./chains.json"));
}
catch(err) {
//self.logger.info('chains.json file not found, creating it...');
chainTracker = {};
fs.writeFileSync('./chains.json', '{}');
}
this.chainTracker = chainTracker;
};
Config.prototype.loadFiles = function(files) { Config.prototype.loadFiles = function(files) {
var originalFiles = grunt.file.expand({nonull: true}, files); var originalFiles = grunt.file.expand({nonull: true}, files);
var readFiles = []; var readFiles = [];

View File

@ -1,17 +1,45 @@
var async = require('async'); var async = require('async');
var Compiler = require('./compiler.js'); var Compiler = require('./compiler.js');
var DeployTracker = require('./deploy_tracker.js');
var Deploy = function(options) {
this.web3 = options.web3;
this.contractsManager = options.contractsManager;
this.logger = options.logger;
this.env = options.env;
this.deployTracker = new DeployTracker({
logger: options.logger, chainConfig: options.chainConfig, web3: options.web3, env: this.env
});
};
Deploy.prototype.checkAndDeployContract = function(contract, params, callback) {
var self = this;
var trackedChain = self.deployTracker.getContract(contract.className, contract.code, contract.args);
// TODO: need to also check getCode
if (trackedChain) {
self.logger.info(contract.className + " already deployed " + trackedChain.address);
contract.deployedAddress = trackedChain.address;
self.logger.contractsState(self.contractsManager.contractsState());
callback();
} else {
this.deployContract(contract, params, function(err, address) {
self.logger.info("not deployed");
self.deployTracker.trackContract(contract.className, contract.code, contract.args, address);
self.deployTracker.save();
self.logger.contractsState(self.contractsManager.contractsState());
callback();
});
}
var Deploy = function(web3, contractsManager, logger) {
this.web3 = web3;
this.contractsManager = contractsManager;
this.logger = logger;
}; };
Deploy.prototype.deployContract = function(contract, params, callback) { Deploy.prototype.deployContract = function(contract, params, callback) {
var self = this; var self = this;
var contractObject = this.web3.eth.contract(contract.abiDefinition); var contractObject = this.web3.eth.contract(contract.abiDefinition);
var contractParams = params || contract.args; var contractParams = (params || contract.args).slice();
contractParams.push({ contractParams.push({
from: this.web3.eth.coinbase, from: this.web3.eth.coinbase,
@ -27,12 +55,10 @@ Deploy.prototype.deployContract = function(contract, params, callback) {
if (err) { if (err) {
self.logger.error("error deploying contract: " + contract.className); self.logger.error("error deploying contract: " + contract.className);
self.logger.error(err.toString()); self.logger.error(err.toString());
self.logger.contractsState(self.contractsManager.contractsState());
callback(new Error(err)); callback(new Error(err));
} else if (transaction.address !== undefined) { } else if (transaction.address !== undefined) {
self.logger.info(contract.className + " deployed at " + transaction.address); self.logger.info(contract.className + " deployed at " + transaction.address);
contract.deployedAddress = transaction.address; contract.deployedAddress = transaction.address;
self.logger.contractsState(self.contractsManager.contractsState());
callback(null, transaction.address); callback(null, transaction.address);
} }
}); });
@ -47,7 +73,7 @@ Deploy.prototype.deployAll = function(done) {
async.eachOfSeries(this.contractsManager.listContracts(), async.eachOfSeries(this.contractsManager.listContracts(),
function(contract, key, callback) { function(contract, key, callback) {
self.logger.trace(arguments); self.logger.trace(arguments);
self.deployContract(contract, null, callback); self.checkAndDeployContract(contract, null, callback);
}, },
function(err, results) { function(err, results) {
self.logger.info("finished"); self.logger.info("finished");

51
lib/deploy_tracker.js Normal file
View File

@ -0,0 +1,51 @@
var fs = require('fs');
var prettyJson = require("json-honey");
var DeployTracker = function(options) {
this.logger = options.logger;
this.env = options.env;
this.chainConfig = options.chainConfig;
this.web3 = options.web3;
var block = this.web3.eth.getBlock(0);
var chainId = block.hash;
if (this.chainConfig[chainId] === undefined) {
this.chainConfig[chainId] = {contracts: {}};
}
this.currentChain = this.chainConfig[chainId];
this.currentChain.name = this.env;
// TODO: add networkId
this.currentChain.networkId = "";
};
DeployTracker.prototype.loadConfig = function(config) {
this.chainConfig = config;
return this;
};
DeployTracker.prototype.trackContract = function(contractName, code, args, address) {
//this.logger.debug("--- trackContract ---");
//this.logger.debug(this.currentChain.contracts);
//this.logger.debug(code + contractName + args.join(','));
//this.logger.debug(this.web3.sha3(code + contractName + args.join(',')));
this.currentChain.contracts[this.web3.sha3(code + contractName + args.join(','))] = {
name: contractName,
address: address
};
};
DeployTracker.prototype.getContract = function(contractName, code, args) {
return this.currentChain.contracts[this.web3.sha3(code + contractName + args.join(','))];
};
// TODO: abstract this
// chainConfig can be an abstract PersistentObject
DeployTracker.prototype.save = function() {
fs.writeFileSync("./chains.json", prettyJson(this.chainConfig));
};
module.exports = DeployTracker;

View File

@ -210,7 +210,13 @@ var Embark = {
exit(); exit();
} }
var deploy = new Deploy(web3, contractsManager, Embark.logger); var deploy = new Deploy({
web3: web3,
contractsManager: contractsManager,
logger: Embark.logger,
chainConfig: self.config.chainTracker,
env: self.config.env
});
deploy.deployAll(function() { deploy.deployAll(function() {
callback(null, contractsManager); callback(null, contractsManager);
}); });

View File

@ -22,7 +22,7 @@
"commander": "^2.8.1", "commander": "^2.8.1",
"finalhandler": "^0.5.0", "finalhandler": "^0.5.0",
"grunt": "^0.4.5", "grunt": "^0.4.5",
"js-sha3": "^0.3.1", "json-honey": "^0.4.1",
"meteor-build-client": "^0.1.6", "meteor-build-client": "^0.1.6",
"mkdirp": "^0.5.1", "mkdirp": "^0.5.1",
"read-yaml": "^1.0.0", "read-yaml": "^1.0.0",