Merge branch 'poc8' into docbranch

This commit is contained in:
obscuren 2015-01-04 14:39:15 +01:00
commit 987119cd4a
50 changed files with 300 additions and 1899 deletions

@ -13,7 +13,7 @@ Status](http://build.ethdev.com/buildstatusimage?builder=Linux%20Go%20develop%20
Ethereum Go Client © 2014 Jeffrey Wilcke.
Current state: Proof of Concept 0.7
Current state: Proof of Concept 0.8
Ethereum is currently in its testing phase.

@ -25,13 +25,14 @@ import (
"github.com/ethereum/go-ethereum/cmd/utils"
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/eth"
"github.com/ethereum/go-ethereum/ethutil"
"github.com/ethereum/go-ethereum/logger"
)
const (
ClientIdentifier = "Ethereum(G)"
Version = "0.7.11"
Version = "0.8.0"
)
var clilogger = logger.NewLogger("CLI")
@ -48,35 +49,26 @@ func main() {
// precedence: code-internal flag default < config file < environment variables < command line
Init() // parsing command line
// If the difftool option is selected ignore all other log output
if DiffTool || Dump {
LogLevel = 0
}
utils.InitConfig(VmType, ConfigFile, Datadir, "ETH")
ethutil.Config.Diff = DiffTool
ethutil.Config.DiffType = DiffType
utils.InitDataDir(Datadir)
utils.InitLogging(Datadir, LogFile, LogLevel, DebugFile)
db := utils.NewDatabase()
err := utils.DBSanityCheck(db)
ethereum, err := eth.New(&eth.Config{
Name: ClientIdentifier,
Version: Version,
KeyStore: KeyStore,
DataDir: Datadir,
LogFile: LogFile,
LogLevel: LogLevel,
Identifier: Identifier,
MaxPeers: MaxPeer,
Port: OutboundPort,
NATType: PMPGateway,
PMPGateway: PMPGateway,
KeyRing: KeyRing,
})
if err != nil {
fmt.Println(err)
os.Exit(1)
clilogger.Fatalln(err)
}
keyManager := utils.NewKeyManager(KeyStore, Datadir, db)
// create, import, export keys
utils.KeyTasks(keyManager, KeyRing, GenAddr, SecretFile, ExportDir, NonInteractive)
clientIdentity := utils.NewClientIdentity(ClientIdentifier, Version, Identifier, string(keyManager.PublicKey()))
ethereum := utils.NewEthereum(db, clientIdentity, keyManager, utils.NatType(NatType, PMPGateway), OutboundPort, MaxPeer)
utils.KeyTasks(ethereum.KeyManager(), KeyRing, GenAddr, SecretFile, ExportDir, NonInteractive)
if Dump {
var block *types.Block
@ -103,11 +95,7 @@ func main() {
fmt.Println(block)
os.Exit(0)
}
if ShowGenesis {
utils.ShowGenesis(ethereum)
return
}
if StartMining {

@ -1,14 +0,0 @@
This file is part of ethereum.js.
ethereum.js is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
ethereum.js is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with ethereum.js. If not, see <http://www.gnu.org/licenses/>.

@ -1,79 +0,0 @@
# Ethereum JavaScript API
This is the Ethereum compatible JavaScript API using `Promise`s
which implements the [Generic JSON RPC](https://github.com/ethereum/wiki/wiki/Generic-JSON-RPC) spec. It's available on npm as a node module and also for bower and component as an embeddable js
[![NPM version][npm-image]][npm-url] [![Build Status][travis-image]][travis-url] [![dependency status][dep-image]][dep-url] [![dev dependency status][dep-dev-image]][dep-dev-url]
<!-- [![browser support](https://ci.testling.com/ethereum/ethereum.js.png)](https://ci.testling.com/ethereum/ethereum.js) -->
## Installation
### Node.js
npm install ethereum.js
### For browser
Bower
bower install ethereum.js
Component
component install ethereum/ethereum.js
* Include `ethereum.min.js` in your html file.
* Include [es6-promise](https://github.com/jakearchibald/es6-promise) or another ES6-Shim if your browser doesn't support ECMAScript 6.
## Usage
Require the library:
var web3 = require('web3');
Set a provider (QtProvider, WebSocketProvider, HttpRpcProvider)
var web3.setProvider(new web3.providers.WebSocketProvider('ws://localhost:40404/eth'));
There you go, now you can use it:
```
web3.eth.coinbase.then(function(result){
console.log(result);
return web3.eth.balanceAt(result);
}).then(function(balance){
console.log(web3.toDecimal(balance));
}).catch(function(err){
console.log(err);
});
```
For another example see `example/index.html`.
## Building
* `gulp build`
### Testing
**Please note this repo is in it's early stage.**
If you'd like to run a WebSocket ethereum node check out
[go-ethereum](https://github.com/ethereum/go-ethereum).
To install ethereum and spawn a node:
```
go get github.com/ethereum/go-ethereum/ethereum
ethereum -ws -loglevel=4
```
[npm-image]: https://badge.fury.io/js/ethereum.js.png
[npm-url]: https://npmjs.org/package/ethereum.js
[travis-image]: https://travis-ci.org/ethereum/ethereum.js.svg
[travis-url]: https://travis-ci.org/ethereum/ethereum.js
[dep-image]: https://david-dm.org/ethereum/ethereum.js.svg
[dep-url]: https://david-dm.org/ethereum/ethereum.js
[dep-dev-image]: https://david-dm.org/ethereum/ethereum.js/dev-status.svg
[dep-dev-url]: https://david-dm.org/ethereum/ethereum.js#info=devDependencies

@ -1,51 +0,0 @@
{
"name": "ethereum.js",
"namespace": "ethereum",
"version": "0.0.3",
"description": "Ethereum Compatible JavaScript API",
"main": ["./dist/ethereum.js", "./dist/ethereum.min.js"],
"dependencies": {
"es6-promise": "#master"
},
"repository": {
"type": "git",
"url": "https://github.com/ethereum/ethereum.js.git"
},
"homepage": "https://github.com/ethereum/ethereum.js",
"bugs": {
"url": "https://github.com/ethereum/ethereum.js/issues"
},
"keywords": [
"ethereum",
"javascript",
"API"
],
"authors": [
{
"name": "Marek Kotewicz",
"email": "marek@ethdev.com",
"homepage": "https://github.com/debris"
},
{
"name": "Marian Oancea",
"email": "marian@ethdev.com",
"homepage": "https://github.com/cubedro"
}
],
"license": "LGPL-3.0",
"ignore": [
"example",
"lib",
"node_modules",
"package.json",
".bowerrc",
".editorconfig",
".gitignore",
".jshintrc",
".npmignore",
".travis.yml",
"gulpfile.js",
"index.js",
"**/*.txt"
]
}

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

@ -1,75 +0,0 @@
<!doctype>
<html>
<head>
<script type="text/javascript" src="js/es6-promise/promise.min.js"></script>
<script type="text/javascript" src="../dist/ethereum.js"></script>
<script type="text/javascript">
var web3 = require('web3');
web3.setProvider(new web3.providers.AutoProvider());
// solidity source code
var source = "" +
"contract test {\n" +
" function multiply(uint a) returns(uint d) {\n" +
" return a * 7;\n" +
" }\n" +
"}\n";
// contract description, this will be autogenerated somehow
var desc = [{
"name": "multiply",
"inputs": [
{
"name": "a",
"type": "uint256"
}
],
"outputs": [
{
"name": "d",
"type": "uint256"
}
]
}];
var contract;
function createExampleContract() {
// hide create button
document.getElementById('create').style.visibility = 'hidden';
document.getElementById('source').innerText = source;
// create contract
web3.eth.transact({code: web3.eth.solidity(source)}).then(function (address) {
contract = web3.contract(address, desc);
document.getElementById('call').style.visibility = 'visible';
});
}
function callExampleContract() {
// this should be generated by ethereum
var param = document.getElementById('value').value;
// call the contract
contract.multiply(param).call().then(function(res) {
document.getElementById('result').innerText = res[0];
});
}
</script>
</head>
<body>
<h1>contract</h1>
<div id="source"></div>
<div id='create'>
<button type="button" onClick="createExampleContract();">create example contract</button>
</div>
<div id='call' style='visibility: hidden;'>
<input type="number" id="value" onkeyup='callExampleContract()'></input>
</div>
<div id="result"></div>
</body>
</html>

@ -1,41 +0,0 @@
<!doctype>
<html>
<head>
<script type="text/javascript" src="js/es6-promise/promise.min.js"></script>
<script type="text/javascript" src="../dist/ethereum.js"></script>
<script type="text/javascript">
var web3 = require('web3');
web3.setProvider(new web3.providers.AutoProvider());
function watchBalance() {
var coinbase = web3.eth.coinbase;
var originalBalance = 0;
web3.eth.balanceAt(coinbase).then(function (balance) {
originalBalance = web3.toDecimal(balance);
document.getElementById('original').innerText = 'original balance: ' + originalBalance + ' watching...';
});
web3.eth.watch({altered: coinbase}).changed(function() {
web3.eth.balanceAt(coinbase).then(function (balance) {
var currentBalance = web3.toDecimal(balance);
document.getElementById("current").innerText = 'current: ' + currentBalance;
document.getElementById("diff").innerText = 'diff: ' + (currentBalance - originalBalance);
});
});
}
</script>
</head>
<body>
<h1>coinbase balance</h1>
<button type="button" onClick="watchBalance();">watch balance</button>
<div></div>
<div id="original"></div>
<div id="current"></div>
<div id="diff"></div>
</body>
</html>

@ -1,16 +0,0 @@
#!/usr/bin/env node
require('es6-promise').polyfill();
var web3 = require("../index.js");
web3.setProvider(new web3.providers.HttpRpcProvider('http://localhost:8080'));
web3.eth.coinbase.then(function(result){
console.log(result);
return web3.eth.balanceAt(result);
}).then(function(balance){
console.log(web3.toDecimal(balance));
}).catch(function(err){
console.log(err);
});

@ -1,123 +0,0 @@
#!/usr/bin/env node
'use strict';
var path = require('path');
var del = require('del');
var gulp = require('gulp');
var browserify = require('browserify');
var jshint = require('gulp-jshint');
var uglify = require('gulp-uglify');
var rename = require('gulp-rename');
var envify = require('envify/custom');
var unreach = require('unreachable-branch-transform');
var source = require('vinyl-source-stream');
var exorcist = require('exorcist');
var bower = require('bower');
var DEST = './dist/';
var build = function(src, dst) {
return browserify({
debug: true,
insert_global_vars: false,
detectGlobals: false,
bundleExternal: false
})
.require('./' + src + '.js', {expose: 'web3'})
.add('./' + src + '.js')
.transform('envify', {
NODE_ENV: 'build'
})
.transform('unreachable-branch-transform')
.transform('uglifyify', {
mangle: false,
compress: {
dead_code: false,
conditionals: true,
unused: false,
hoist_funs: true,
hoist_vars: true,
negate_iife: false
},
beautify: true,
warnings: true
})
.bundle()
.pipe(exorcist(path.join( DEST, dst + '.js.map')))
.pipe(source(dst + '.js'))
.pipe(gulp.dest( DEST ));
};
var buildDev = function(src, dst) {
return browserify({
debug: true,
insert_global_vars: false,
detectGlobals: false,
bundleExternal: false
})
.require('./' + src + '.js', {expose: 'web3'})
.add('./' + src + '.js')
.transform('envify', {
NODE_ENV: 'build'
})
.transform('unreachable-branch-transform')
.bundle()
.pipe(exorcist(path.join( DEST, dst + '.js.map')))
.pipe(source(dst + '.js'))
.pipe(gulp.dest( DEST ));
};
var uglifyFile = function(file) {
return gulp.src( DEST + file + '.js')
.pipe(uglify())
.pipe(rename(file + '.min.js'))
.pipe(gulp.dest( DEST ));
};
gulp.task('bower', function(cb){
bower.commands.install().on('end', function (installed){
console.log(installed);
cb();
});
});
gulp.task('lint', function(){
return gulp.src(['./*.js', './lib/*.js'])
.pipe(jshint())
.pipe(jshint.reporter('default'));
});
gulp.task('clean', ['lint'], function(cb) {
del([ DEST ], cb);
});
gulp.task('build', ['clean'], function () {
return build('index', 'ethereum');
});
gulp.task('buildQt', ['clean'], function () {
return build('index_qt', 'ethereum');
});
gulp.task('buildDev', ['clean'], function () {
return buildDev('index', 'ethereum');
});
gulp.task('uglify', ['build'], function(){
return uglifyFile('ethereum');
});
gulp.task('uglifyQt', ['buildQt'], function () {
return uglifyFile('ethereum');
});
gulp.task('watch', function() {
gulp.watch(['./lib/*.js'], ['lint', 'prepare', 'build']);
});
gulp.task('default', ['bower', 'lint', 'build', 'uglify']);
gulp.task('qt', ['bower', 'lint', 'buildQt', 'uglifyQt']);
gulp.task('dev', ['bower', 'lint', 'buildDev']);

@ -1,8 +0,0 @@
var web3 = require('./lib/main');
web3.providers.WebSocketProvider = require('./lib/websocket');
web3.providers.HttpRpcProvider = require('./lib/httprpc');
web3.providers.QtProvider = require('./lib/qt');
web3.providers.AutoProvider = require('./lib/autoprovider');
web3.contract = require('./lib/contract');
module.exports = web3;

@ -1,5 +0,0 @@
var web3 = require('./lib/main');
web3.providers.QtProvider = require('./lib/qt');
web3.contract = require('./lib/contract');
module.exports = web3;

@ -1,218 +0,0 @@
/*
This file is part of ethereum.js.
ethereum.js is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
ethereum.js is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with ethereum.js. If not, see <http://www.gnu.org/licenses/>.
*/
/** @file abi.js
* @authors:
* Marek Kotewicz <marek@ethdev.com>
* Gav Wood <g@ethdev.com>
* @date 2014
*/
// TODO: make these be actually accurate instead of falling back onto JS's doubles.
var hexToDec = function (hex) {
return parseInt(hex, 16).toString();
};
var decToHex = function (dec) {
return parseInt(dec).toString(16);
};
var findIndex = function (array, callback) {
var end = false;
var i = 0;
for (; i < array.length && !end; i++) {
end = callback(array[i]);
}
return end ? i - 1 : -1;
};
var findMethodIndex = function (json, methodName) {
return findIndex(json, function (method) {
return method.name === methodName;
});
};
var padLeft = function (string, chars) {
return Array(chars - string.length + 1).join("0") + string;
};
var setupInputTypes = function () {
var prefixedType = function (prefix) {
return function (type, value) {
var expected = prefix;
if (type.indexOf(expected) !== 0) {
return false;
}
var padding = parseInt(type.slice(expected.length)) / 8;
if (typeof value === "number")
value = value.toString(16);
else if (value.indexOf('0x') === 0)
value = value.substr(2);
else
value = (+value).toString(16);
return padLeft(value, padding * 2);
};
};
var namedType = function (name, padding, formatter) {
return function (type, value) {
if (type !== name) {
return false;
}
return padLeft(formatter ? formatter(value) : value, padding * 2);
};
};
var formatBool = function (value) {
return value ? '0x1' : '0x0';
};
return [
prefixedType('uint'),
prefixedType('int'),
prefixedType('hash'),
namedType('address', 20),
namedType('bool', 1, formatBool),
];
};
var inputTypes = setupInputTypes();
var toAbiInput = function (json, methodName, params) {
var bytes = "";
var index = findMethodIndex(json, methodName);
if (index === -1) {
return;
}
bytes = "0x" + padLeft(index.toString(16), 2);
var method = json[index];
for (var i = 0; i < method.inputs.length; i++) {
var found = false;
for (var j = 0; j < inputTypes.length && !found; j++) {
found = inputTypes[j](method.inputs[i].type, params[i]);
}
if (!found) {
console.error('unsupported json type: ' + method.inputs[i].type);
}
bytes += found;
}
return bytes;
};
var setupOutputTypes = function () {
var prefixedType = function (prefix) {
return function (type) {
var expected = prefix;
if (type.indexOf(expected) !== 0) {
return -1;
}
var padding = parseInt(type.slice(expected.length)) / 8;
return padding * 2;
};
};
var namedType = function (name, padding) {
return function (type) {
return name === type ? padding * 2 : -1;
};
};
var formatInt = function (value) {
return value.length <= 8 ? +parseInt(value, 16) : hexToDec(value);
};
var formatHash = function (value) {
return "0x" + value;
};
var formatBool = function (value) {
return value === '1' ? true : false;
};
return [
{ padding: prefixedType('uint'), format: formatInt },
{ padding: prefixedType('int'), format: formatInt },
{ padding: prefixedType('hash'), format: formatHash },
{ padding: namedType('address', 20) },
{ padding: namedType('bool', 1), format: formatBool }
];
};
var outputTypes = setupOutputTypes();
var fromAbiOutput = function (json, methodName, output) {
var index = findMethodIndex(json, methodName);
if (index === -1) {
return;
}
output = output.slice(2);
var result = [];
var method = json[index];
for (var i = 0; i < method.outputs.length; i++) {
var padding = -1;
for (var j = 0; j < outputTypes.length && padding === -1; j++) {
padding = outputTypes[j].padding(method.outputs[i].type);
}
if (padding === -1) {
// not found output parsing
continue;
}
var res = output.slice(0, padding);
var formatter = outputTypes[j - 1].format;
result.push(formatter ? formatter(res) : ("0x" + res));
output = output.slice(padding);
}
return result;
};
var inputParser = function (json) {
var parser = {};
json.forEach(function (method) {
parser[method.name] = function () {
var params = Array.prototype.slice.call(arguments);
return toAbiInput(json, method.name, params);
};
});
return parser;
};
var outputParser = function (json) {
var parser = {};
json.forEach(function (method) {
parser[method.name] = function (output) {
return fromAbiOutput(json, method.name, output);
};
});
return parser;
};
module.exports = {
inputParser: inputParser,
outputParser: outputParser
};

@ -1,103 +0,0 @@
/*
This file is part of ethereum.js.
ethereum.js is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
ethereum.js is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with ethereum.js. If not, see <http://www.gnu.org/licenses/>.
*/
/** @file autoprovider.js
* @authors:
* Marek Kotewicz <marek@ethdev.com>
* Marian Oancea <marian@ethdev.com>
* @date 2014
*/
/*
* @brief if qt object is available, uses QtProvider,
* if not tries to connect over websockets
* if it fails, it uses HttpRpcProvider
*/
// TODO: work out which of the following two lines it is supposed to be...
//if (process.env.NODE_ENV !== 'build') {
if ("build" !== 'build') {/*
var WebSocket = require('ws'); // jshint ignore:line
var web3 = require('./main.js'); // jshint ignore:line
*/}
var AutoProvider = function (userOptions) {
if (web3.haveProvider()) {
return;
}
// before we determine what provider we are, we have to cache request
this.sendQueue = [];
this.onmessageQueue = [];
if (navigator.qt) {
this.provider = new web3.providers.QtProvider();
return;
}
userOptions = userOptions || {};
var options = {
httprpc: userOptions.httprpc || 'http://localhost:8080',
websockets: userOptions.websockets || 'ws://localhost:40404/eth'
};
var self = this;
var closeWithSuccess = function (success) {
ws.close();
if (success) {
self.provider = new web3.providers.WebSocketProvider(options.websockets);
} else {
self.provider = new web3.providers.HttpRpcProvider(options.httprpc);
self.poll = self.provider.poll.bind(self.provider);
}
self.sendQueue.forEach(function (payload) {
self.provider(payload);
});
self.onmessageQueue.forEach(function (handler) {
self.provider.onmessage = handler;
});
};
var ws = new WebSocket(options.websockets);
ws.onopen = function() {
closeWithSuccess(true);
};
ws.onerror = function() {
closeWithSuccess(false);
};
};
AutoProvider.prototype.send = function (payload) {
if (this.provider) {
this.provider.send(payload);
return;
}
this.sendQueue.push(payload);
};
Object.defineProperty(AutoProvider.prototype, 'onmessage', {
set: function (handler) {
if (this.provider) {
this.provider.onmessage = handler;
return;
}
this.onmessageQueue.push(handler);
}
});
module.exports = AutoProvider;

@ -1,65 +0,0 @@
/*
This file is part of ethereum.js.
ethereum.js is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
ethereum.js is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with ethereum.js. If not, see <http://www.gnu.org/licenses/>.
*/
/** @file contract.js
* @authors:
* Marek Kotewicz <marek@ethdev.com>
* @date 2014
*/
// TODO: work out which of the following two lines it is supposed to be...
//if (process.env.NODE_ENV !== 'build') {
if ("build" !== 'build') {/*
var web3 = require('./web3'); // jshint ignore:line
*/}
var abi = require('./abi');
var contract = function (address, desc) {
var inputParser = abi.inputParser(desc);
var outputParser = abi.outputParser(desc);
var contract = {};
desc.forEach(function (method) {
contract[method.name] = function () {
var params = Array.prototype.slice.call(arguments);
var parsed = inputParser[method.name].apply(null, params);
var onSuccess = function (result) {
return outputParser[method.name](result);
};
return {
call: function (extra) {
extra = extra || {};
extra.to = address;
extra.data = parsed;
return web3.eth.call(extra).then(onSuccess);
},
transact: function (extra) {
extra = extra || {};
extra.to = address;
extra.data = parsed;
return web3.eth.transact(extra).then(onSuccess);
}
};
};
});
return contract;
};
module.exports = contract;

@ -1,95 +0,0 @@
/*
This file is part of ethereum.js.
ethereum.js is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
ethereum.js is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with ethereum.js. If not, see <http://www.gnu.org/licenses/>.
*/
/** @file httprpc.js
* @authors:
* Marek Kotewicz <marek@ethdev.com>
* Marian Oancea <marian@ethdev.com>
* @date 2014
*/
// TODO: work out which of the following two lines it is supposed to be...
//if (process.env.NODE_ENV !== 'build') {
if ("build" !== "build") {/*
var XMLHttpRequest = require('xmlhttprequest').XMLHttpRequest; // jshint ignore:line
*/}
var HttpRpcProvider = function (host) {
this.handlers = [];
this.host = host;
};
function formatJsonRpcObject(object) {
return {
jsonrpc: '2.0',
method: object.call,
params: object.args,
id: object._id
};
}
function formatJsonRpcMessage(message) {
var object = JSON.parse(message);
return {
_id: object.id,
data: object.result,
error: object.error
};
}
HttpRpcProvider.prototype.sendRequest = function (payload, cb) {
var data = formatJsonRpcObject(payload);
var request = new XMLHttpRequest();
request.open("POST", this.host, true);
request.send(JSON.stringify(data));
request.onreadystatechange = function () {
if (request.readyState === 4 && cb) {
cb(request);
}
};
};
HttpRpcProvider.prototype.send = function (payload) {
var self = this;
this.sendRequest(payload, function (request) {
self.handlers.forEach(function (handler) {
handler.call(self, formatJsonRpcMessage(request.responseText));
});
});
};
HttpRpcProvider.prototype.poll = function (payload, id) {
var self = this;
this.sendRequest(payload, function (request) {
var parsed = JSON.parse(request.responseText);
if (parsed.error || (parsed.result instanceof Array ? parsed.result.length === 0 : !parsed.result)) {
return;
}
self.handlers.forEach(function (handler) {
handler.call(self, {_event: payload.call, _id: id, data: parsed.result});
});
});
};
Object.defineProperty(HttpRpcProvider.prototype, "onmessage", {
set: function (handler) {
this.handlers.push(handler);
}
});
module.exports = HttpRpcProvider;

@ -1,494 +0,0 @@
/*
This file is part of ethereum.js.
ethereum.js is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
ethereum.js is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with ethereum.js. If not, see <http://www.gnu.org/licenses/>.
*/
/** @file main.js
* @authors:
* Jeffrey Wilcke <jeff@ethdev.com>
* Marek Kotewicz <marek@ethdev.com>
* Marian Oancea <marian@ethdev.com>
* Gav Wood <g@ethdev.com>
* @date 2014
*/
function flattenPromise (obj) {
if (obj instanceof Promise) {
return Promise.resolve(obj);
}
if (obj instanceof Array) {
return new Promise(function (resolve) {
var promises = obj.map(function (o) {
return flattenPromise(o);
});
return Promise.all(promises).then(function (res) {
for (var i = 0; i < obj.length; i++) {
obj[i] = res[i];
}
resolve(obj);
});
});
}
if (obj instanceof Object) {
return new Promise(function (resolve) {
var keys = Object.keys(obj);
var promises = keys.map(function (key) {
return flattenPromise(obj[key]);
});
return Promise.all(promises).then(function (res) {
for (var i = 0; i < keys.length; i++) {
obj[keys[i]] = res[i];
}
resolve(obj);
});
});
}
return Promise.resolve(obj);
}
var web3Methods = function () {
return [
{ name: 'sha3', call: 'web3_sha3' }
];
};
var ethMethods = function () {
var blockCall = function (args) {
return typeof args[0] === "string" ? "eth_blockByHash" : "eth_blockByNumber";
};
var transactionCall = function (args) {
return typeof args[0] === "string" ? 'eth_transactionByHash' : 'eth_transactionByNumber';
};
var uncleCall = function (args) {
return typeof args[0] === "string" ? 'eth_uncleByHash' : 'eth_uncleByNumber';
};
var methods = [
{ name: 'balanceAt', call: 'eth_balanceAt' },
{ name: 'stateAt', call: 'eth_stateAt' },
{ name: 'storageAt', call: 'eth_storageAt' },
{ name: 'countAt', call: 'eth_countAt'},
{ name: 'codeAt', call: 'eth_codeAt' },
{ name: 'transact', call: 'eth_transact' },
{ name: 'call', call: 'eth_call' },
{ name: 'block', call: blockCall },
{ name: 'transaction', call: transactionCall },
{ name: 'uncle', call: uncleCall },
{ name: 'compilers', call: 'eth_compilers' },
{ name: 'lll', call: 'eth_lll' },
{ name: 'solidity', call: 'eth_solidity' },
{ name: 'serpent', call: 'eth_serpent' },
{ name: 'logs', call: 'eth_logs' }
];
return methods;
};
var ethProperties = function () {
return [
{ name: 'coinbase', getter: 'eth_coinbase', setter: 'eth_setCoinbase' },
{ name: 'listening', getter: 'eth_listening', setter: 'eth_setListening' },
{ name: 'mining', getter: 'eth_mining', setter: 'eth_setMining' },
{ name: 'gasPrice', getter: 'eth_gasPrice' },
{ name: 'account', getter: 'eth_account' },
{ name: 'accounts', getter: 'eth_accounts' },
{ name: 'peerCount', getter: 'eth_peerCount' },
{ name: 'defaultBlock', getter: 'eth_defaultBlock', setter: 'eth_setDefaultBlock' },
{ name: 'number', getter: 'eth_number'}
];
};
var dbMethods = function () {
return [
{ name: 'put', call: 'db_put' },
{ name: 'get', call: 'db_get' },
{ name: 'putString', call: 'db_putString' },
{ name: 'getString', call: 'db_getString' }
];
};
var shhMethods = function () {
return [
{ name: 'post', call: 'shh_post' },
{ name: 'newIdentity', call: 'shh_newIdentity' },
{ name: 'haveIdentity', call: 'shh_haveIdentity' },
{ name: 'newGroup', call: 'shh_newGroup' },
{ name: 'addToGroup', call: 'shh_addToGroup' }
];
};
var ethWatchMethods = function () {
var newFilter = function (args) {
return typeof args[0] === 'string' ? 'eth_newFilterString' : 'eth_newFilter';
};
return [
{ name: 'newFilter', call: newFilter },
{ name: 'uninstallFilter', call: 'eth_uninstallFilter' },
{ name: 'getMessages', call: 'eth_filterLogs' }
];
};
var shhWatchMethods = function () {
return [
{ name: 'newFilter', call: 'shh_newFilter' },
{ name: 'uninstallFilter', call: 'shh_uninstallFilter' },
{ name: 'getMessage', call: 'shh_getMessages' }
];
};
var setupMethods = function (obj, methods) {
methods.forEach(function (method) {
obj[method.name] = function () {
return flattenPromise(Array.prototype.slice.call(arguments)).then(function (args) {
var call = typeof method.call === "function" ? method.call(args) : method.call;
return {call: call, args: args};
}).then(function (request) {
return new Promise(function (resolve, reject) {
web3.provider.send(request, function (err, result) {
if (!err) {
resolve(result);
return;
}
reject(err);
});
});
}).catch(function(err) {
console.error(err);
});
};
});
};
var setupProperties = function (obj, properties) {
properties.forEach(function (property) {
var proto = {};
proto.get = function () {
return new Promise(function(resolve, reject) {
web3.provider.send({call: property.getter}, function(err, result) {
if (!err) {
resolve(result);
return;
}
reject(err);
});
});
};
if (property.setter) {
proto.set = function (val) {
return flattenPromise([val]).then(function (args) {
return new Promise(function (resolve) {
web3.provider.send({call: property.setter, args: args}, function (err, result) {
if (!err) {
resolve(result);
return;
}
reject(err);
});
});
}).catch(function (err) {
console.error(err);
});
};
}
Object.defineProperty(obj, property.name, proto);
});
};
// TODO: import from a dependency, don't duplicate.
var hexToDec = function (hex) {
return parseInt(hex, 16).toString();
};
var decToHex = function (dec) {
return parseInt(dec).toString(16);
};
var web3 = {
_callbacks: {},
_events: {},
providers: {},
toAscii: function(hex) {
// Find termination
var str = "";
var i = 0, l = hex.length;
if (hex.substring(0, 2) === '0x')
i = 2;
for(; i < l; i+=2) {
var code = hex.charCodeAt(i);
if(code === 0) {
break;
}
str += String.fromCharCode(parseInt(hex.substr(i, 2), 16));
}
return str;
},
fromAscii: function(str, pad) {
pad = pad === undefined ? 32 : pad;
var hex = this.toHex(str);
while(hex.length < pad*2)
hex += "00";
return "0x" + hex;
},
toDecimal: function (val) {
return hexToDec(val.substring(2));
},
fromDecimal: function (val) {
return "0x" + decToHex(val);
},
toEth: function(str) {
var val = typeof str === "string" ? str.indexOf('0x') == 0 ? parseInt(str.substr(2), 16) : parseInt(str) : str;
var unit = 0;
var units = [ 'wei', 'Kwei', 'Mwei', 'Gwei', 'szabo', 'finney', 'ether', 'grand', 'Mether', 'Gether', 'Tether', 'Pether', 'Eether', 'Zether', 'Yether', 'Nether', 'Dether', 'Vether', 'Uether' ];
while (val > 3000 && unit < units.length - 1)
{
val /= 1000;
unit++;
}
var s = val.toString().length < val.toFixed(2).length ? val.toString() : val.toFixed(2);
while (true) {
var o = s;
s = s.replace(/(\d)(\d\d\d[\.\,])/, function($0, $1, $2) { return $1 + ',' + $2; });
if (o == s)
break;
}
return s + ' ' + units[unit];
},
eth: {
prototype: Object(), // jshint ignore:line
watch: function (params) {
return new Filter(params, ethWatch);
}
},
db: {
prototype: Object() // jshint ignore:line
},
shh: {
prototype: Object(), // jshint ignore:line
watch: function (params) {
return new Filter(params, shhWatch);
}
},
on: function(event, id, cb) {
if(web3._events[event] === undefined) {
web3._events[event] = {};
}
web3._events[event][id] = cb;
return this;
},
off: function(event, id) {
if(web3._events[event] !== undefined) {
delete web3._events[event][id];
}
return this;
},
trigger: function(event, id, data) {
var callbacks = web3._events[event];
if (!callbacks || !callbacks[id]) {
return;
}
var cb = callbacks[id];
cb(data);
}
};
setupMethods(web3, web3Methods());
setupMethods(web3.eth, ethMethods());
setupProperties(web3.eth, ethProperties());
setupMethods(web3.db, dbMethods());
setupMethods(web3.shh, shhMethods());
var ethWatch = {
changed: 'eth_changed'
};
setupMethods(ethWatch, ethWatchMethods());
var shhWatch = {
changed: 'shh_changed'
};
setupMethods(shhWatch, shhWatchMethods());
var ProviderManager = function() {
this.queued = [];
this.polls = [];
this.ready = false;
this.provider = undefined;
this.id = 1;
var self = this;
var poll = function () {
if (self.provider && self.provider.poll) {
self.polls.forEach(function (data) {
data.data._id = self.id;
self.id++;
self.provider.poll(data.data, data.id);
});
}
setTimeout(poll, 12000);
};
poll();
};
ProviderManager.prototype.send = function(data, cb) {
data._id = this.id;
if (cb) {
web3._callbacks[data._id] = cb;
}
data.args = data.args || [];
this.id++;
if(this.provider !== undefined) {
this.provider.send(data);
} else {
console.warn("provider is not set");
this.queued.push(data);
}
};
ProviderManager.prototype.set = function(provider) {
if(this.provider !== undefined && this.provider.unload !== undefined) {
this.provider.unload();
}
this.provider = provider;
this.ready = true;
};
ProviderManager.prototype.sendQueued = function() {
for(var i = 0; this.queued.length; i++) {
// Resend
this.send(this.queued[i]);
}
};
ProviderManager.prototype.installed = function() {
return this.provider !== undefined;
};
ProviderManager.prototype.startPolling = function (data, pollId) {
if (!this.provider || !this.provider.poll) {
return;
}
this.polls.push({data: data, id: pollId});
};
ProviderManager.prototype.stopPolling = function (pollId) {
for (var i = this.polls.length; i--;) {
var poll = this.polls[i];
if (poll.id === pollId) {
this.polls.splice(i, 1);
}
}
};
web3.provider = new ProviderManager();
web3.setProvider = function(provider) {
provider.onmessage = messageHandler;
web3.provider.set(provider);
web3.provider.sendQueued();
};
web3.haveProvider = function() {
return !!web3.provider.provider;
};
var Filter = function(options, impl) {
this.impl = impl;
this.callbacks = [];
var self = this;
this.promise = impl.newFilter(options);
this.promise.then(function (id) {
self.id = id;
web3.on(impl.changed, id, self.trigger.bind(self));
web3.provider.startPolling({call: impl.changed, args: [id]}, id);
});
};
Filter.prototype.arrived = function(callback) {
this.changed(callback);
};
Filter.prototype.changed = function(callback) {
var self = this;
this.promise.then(function(id) {
self.callbacks.push(callback);
});
};
Filter.prototype.trigger = function(messages) {
for(var i = 0; i < this.callbacks.length; i++) {
this.callbacks[i].call(this, messages);
}
};
Filter.prototype.uninstall = function() {
var self = this;
this.promise.then(function (id) {
self.impl.uninstallFilter(id);
web3.provider.stopPolling(id);
web3.off(impl.changed, id);
});
};
Filter.prototype.messages = function() {
var self = this;
return this.promise.then(function (id) {
return self.impl.getMessages(id);
});
};
Filter.prototype.logs = function () {
return this.messages();
};
function messageHandler(data) {
if(data._event !== undefined) {
web3.trigger(data._event, data._id, data.data);
return;
}
if(data._id) {
var cb = web3._callbacks[data._id];
if (cb) {
cb.call(this, data.error, data.data);
delete web3._callbacks[data._id];
}
}
}
module.exports = web3;

@ -1,45 +0,0 @@
/*
This file is part of ethereum.js.
ethereum.js is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
ethereum.js is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with ethereum.js. If not, see <http://www.gnu.org/licenses/>.
*/
/** @file qt.js
* @authors:
* Jeffrey Wilcke <jeff@ethdev.com>
* Marek Kotewicz <marek@ethdev.com>
* @date 2014
*/
var QtProvider = function() {
this.handlers = [];
var self = this;
navigator.qt.onmessage = function (message) {
self.handlers.forEach(function (handler) {
handler.call(self, JSON.parse(message.data));
});
};
};
QtProvider.prototype.send = function(payload) {
navigator.qt.postMessage(JSON.stringify(payload));
};
Object.defineProperty(QtProvider.prototype, "onmessage", {
set: function(handler) {
this.handlers.push(handler);
}
});
module.exports = QtProvider;

@ -1,78 +0,0 @@
/*
This file is part of ethereum.js.
ethereum.js is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
ethereum.js is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with ethereum.js. If not, see <http://www.gnu.org/licenses/>.
*/
/** @file websocket.js
* @authors:
* Jeffrey Wilcke <jeff@ethdev.com>
* Marek Kotewicz <marek@ethdev.com>
* Marian Oancea <marian@ethdev.com>
* @date 2014
*/
// TODO: work out which of the following two lines it is supposed to be...
//if (process.env.NODE_ENV !== 'build') {
if ("build" !== "build") {/*
var WebSocket = require('ws'); // jshint ignore:line
*/}
var WebSocketProvider = function(host) {
// onmessage handlers
this.handlers = [];
// queue will be filled with messages if send is invoked before the ws is ready
this.queued = [];
this.ready = false;
this.ws = new WebSocket(host);
var self = this;
this.ws.onmessage = function(event) {
for(var i = 0; i < self.handlers.length; i++) {
self.handlers[i].call(self, JSON.parse(event.data), event);
}
};
this.ws.onopen = function() {
self.ready = true;
for(var i = 0; i < self.queued.length; i++) {
// Resend
self.send(self.queued[i]);
}
};
};
WebSocketProvider.prototype.send = function(payload) {
if(this.ready) {
var data = JSON.stringify(payload);
this.ws.send(data);
} else {
this.queued.push(payload);
}
};
WebSocketProvider.prototype.onMessage = function(handler) {
this.handlers.push(handler);
};
WebSocketProvider.prototype.unload = function() {
this.ws.close();
};
Object.defineProperty(WebSocketProvider.prototype, "onmessage", {
set: function(provider) { this.onMessage(provider); }
});
module.exports = WebSocketProvider;

@ -1,67 +0,0 @@
{
"name": "ethereum.js",
"namespace": "ethereum",
"version": "0.0.5",
"description": "Ethereum Compatible JavaScript API",
"main": "./index.js",
"directories": {
"lib": "./lib"
},
"dependencies": {
"es6-promise": "*",
"ws": "*",
"xmlhttprequest": "*"
},
"devDependencies": {
"bower": ">=1.3.0",
"browserify": ">=6.0",
"del": ">=0.1.1",
"envify": "^3.0.0",
"exorcist": "^0.1.6",
"gulp": ">=3.4.0",
"gulp-jshint": ">=1.5.0",
"gulp-rename": ">=1.2.0",
"gulp-uglify": ">=1.0.0",
"jshint": ">=2.5.0",
"uglifyify": "^2.6.0",
"unreachable-branch-transform": "^0.1.0",
"vinyl-source-stream": "^1.0.0"
},
"scripts": {
"build": "gulp",
"watch": "gulp watch",
"lint": "gulp lint"
},
"repository": {
"type": "git",
"url": "https://github.com/ethereum/ethereum.js.git"
},
"homepage": "https://github.com/ethereum/ethereum.js",
"bugs": {
"url": "https://github.com/ethereum/ethereum.js/issues"
},
"keywords": [
"ethereum",
"javascript",
"API"
],
"author": "ethdev.com",
"authors": [
{
"name": "Jeffery Wilcke",
"email": "jeff@ethdev.com",
"url": "https://github.com/obscuren"
},
{
"name": "Marek Kotewicz",
"email": "marek@ethdev.com",
"url": "https://github.com/debris"
},
{
"name": "Marian Oancea",
"email": "marian@ethdev.com",
"url": "https://github.com/cubedro"
}
],
"license": "LGPL-3.0"
}

@ -866,12 +866,14 @@ ApplicationWindow {
model: ListModel { id: pastPeers }
Component.onCompleted: {
/*
var ips = eth.pastPeers()
for(var i = 0; i < ips.length; i++) {
pastPeers.append({text: ips.get(i)})
}
pastPeers.insert(0, {text: "poc-7.ethdev.com:30303"})
*/
}
}

@ -20,7 +20,7 @@ Rectangle {
}
function setBalance() {
balance.text = "<b>Balance</b>: " + eth.numberToHuman(eth.balanceAt(eth.key().address))
//balance.text = "<b>Balance</b>: " + eth.numberToHuman(eth.balanceAt(eth.key().address))
if(menuItem)
menuItem.secondaryTitle = eth.numberToHuman(eth.balanceAt(eth.key().address))
}

@ -72,7 +72,7 @@ func (gui *Gui) GetCustomIdentifier() string {
// functions that allow Gui to implement interface guilogger.LogSystem
func (gui *Gui) SetLogLevel(level logger.LogLevel) {
gui.logLevel = level
gui.stdLog.SetLogLevel(level)
gui.eth.Logger().SetLogLevel(level)
gui.config.Save("loglevel", level)
}

@ -151,7 +151,7 @@ func (self *DebuggerWindow) Debug(valueStr, gasStr, gasPriceStr, scriptStr, data
block := self.lib.eth.ChainManager().CurrentBlock()
env := utils.NewEnv(statedb, block, account.Address(), value)
env := utils.NewEnv(self.lib.eth.ChainManager(), statedb, block, account.Address(), value)
self.Logf("callsize %d", len(script))
go func() {

@ -73,7 +73,6 @@ type Gui struct {
plugins map[string]plugin
miner *miner.Miner
stdLog logger.LogSystem
}
// Create GUI, but doesn't start it
@ -113,7 +112,7 @@ func (gui *Gui) Start(assetPath string) {
// Expose the eth library and the ui library to QML
context.SetVar("gui", gui)
context.SetVar("eth", gui.uiLib)
context.SetVar("shh", gui.whisper)
//context.SetVar("shh", gui.whisper)
// Load the main QML interface
data, _ := ethutil.Config.Db.Get([]byte("KeyRing"))

@ -26,15 +26,17 @@ import (
"github.com/ethereum/go-ethereum/cmd/utils"
"github.com/ethereum/go-ethereum/eth"
"github.com/ethereum/go-ethereum/logger"
"github.com/ethereum/go-ethereum/p2p"
"gopkg.in/qml.v1"
)
const (
ClientIdentifier = "Mist"
Version = "0.7.11"
Version = "0.8.0"
)
var ethereum *eth.Ethereum
var mainlogger = logger.NewLogger("MAIN")
func run() error {
// precedence: code-internal flag default < config file < environment variables < command line
@ -43,27 +45,24 @@ func run() error {
tstart := time.Now()
config := utils.InitConfig(VmType, ConfigFile, Datadir, "ETH")
utils.InitDataDir(Datadir)
stdLog := utils.InitLogging(Datadir, LogFile, LogLevel, DebugFile)
db := utils.NewDatabase()
err := utils.DBSanityCheck(db)
ethereum, err := eth.New(&eth.Config{
Name: ClientIdentifier,
Version: Version,
KeyStore: KeyStore,
DataDir: Datadir,
LogFile: LogFile,
LogLevel: LogLevel,
Identifier: Identifier,
MaxPeers: MaxPeer,
Port: OutboundPort,
NATType: PMPGateway,
PMPGateway: PMPGateway,
KeyRing: KeyRing,
})
if err != nil {
ErrorWindow(err)
os.Exit(1)
}
keyManager := utils.NewKeyManager(KeyStore, Datadir, db)
// create, import, export keys
utils.KeyTasks(keyManager, KeyRing, GenAddr, SecretFile, ExportDir, NonInteractive)
clientIdentity := utils.NewClientIdentity(ClientIdentifier, Version, Identifier, string(keyManager.PublicKey()))
ethereum := utils.NewEthereum(db, clientIdentity, keyManager, utils.NatType(NatType, PMPGateway), OutboundPort, MaxPeer)
if ShowGenesis {
utils.ShowGenesis(ethereum)
mainlogger.Fatalln(err)
}
utils.KeyTasks(ethereum.KeyManager(), KeyRing, GenAddr, SecretFile, ExportDir, NonInteractive)
if StartRpc {
utils.StartRpc(ethereum, RpcPort)
@ -73,8 +72,7 @@ func run() error {
utils.StartWebSockets(ethereum)
}
gui := NewWindow(ethereum, config, clientIdentity, KeyRing, LogLevel)
gui.stdLog = stdLog
gui := NewWindow(ethereum, config, ethereum.ClientIdentity().(*p2p.SimpleClientIdentity), KeyRing, LogLevel)
utils.RegisterInterrupt(func(os.Signal) {
gui.Stop()

@ -18,7 +18,7 @@ func main() {
marshaled := elliptic.Marshal(crypto.S256(), key.PublicKey.X, key.PublicKey.Y)
srv := p2p.Server{
MaxPeers: 10,
MaxPeers: 100,
Identity: p2p.NewSimpleClientIdentity("Ethereum(G)", "0.1", "Peer Server Two", string(marshaled)),
ListenAddr: ":30301",
NAT: p2p.UPNP(),
@ -29,12 +29,12 @@ func main() {
}
// add seed peers
seed, err := net.ResolveTCPAddr("tcp", "poc-7.ethdev.com:30300")
seed, err := net.ResolveTCPAddr("tcp", "poc-8.ethdev.com:30303")
if err != nil {
fmt.Println("couldn't resolve:", err)
os.Exit(1)
}
} else {
srv.SuggestPeer(seed.IP, seed.Port, nil)
}
select {}
}

@ -2,9 +2,6 @@ package utils
import (
"fmt"
"io"
"log"
"net"
"os"
"os/signal"
"path"
@ -16,11 +13,9 @@ import (
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/crypto"
"github.com/ethereum/go-ethereum/eth"
"github.com/ethereum/go-ethereum/ethdb"
"github.com/ethereum/go-ethereum/ethutil"
"github.com/ethereum/go-ethereum/logger"
"github.com/ethereum/go-ethereum/miner"
"github.com/ethereum/go-ethereum/p2p"
"github.com/ethereum/go-ethereum/rlp"
"github.com/ethereum/go-ethereum/rpc"
"github.com/ethereum/go-ethereum/xeth"
@ -52,15 +47,8 @@ func RunInterruptCallbacks(sig os.Signal) {
}
}
func AbsolutePath(Datadir string, filename string) string {
if path.IsAbs(filename) {
return filename
}
return path.Join(Datadir, filename)
}
func openLogFile(Datadir string, filename string) *os.File {
path := AbsolutePath(Datadir, filename)
path := ethutil.AbsolutePath(Datadir, filename)
file, err := os.OpenFile(path, os.O_RDWR|os.O_CREATE|os.O_APPEND, 0666)
if err != nil {
panic(fmt.Sprintf("error opening log file '%s': %v", filename, err))
@ -76,23 +64,13 @@ func confirm(message string) bool {
if r == "n" || r == "y" {
break
} else {
fmt.Printf("Yes or no?", r)
fmt.Printf("Yes or no? (%s)", r)
}
}
return r == "y"
}
func DBSanityCheck(db ethutil.Database) error {
d, _ := db.Get([]byte("ProtocolVersion"))
protov := ethutil.NewValue(d).Uint()
if protov != eth.ProtocolVersion && protov != 0 {
return fmt.Errorf("Database version mismatch. Protocol(%d / %d). `rm -rf %s`", protov, eth.ProtocolVersion, ethutil.Config.ExecPath+"/database")
}
return nil
}
func InitDataDir(Datadir string) {
func initDataDir(Datadir string) {
_, err := os.Stat(Datadir)
if err != nil {
if os.IsNotExist(err) {
@ -102,26 +80,8 @@ func InitDataDir(Datadir string) {
}
}
func InitLogging(Datadir string, LogFile string, LogLevel int, DebugFile string) logger.LogSystem {
var writer io.Writer
if LogFile == "" {
writer = os.Stdout
} else {
writer = openLogFile(Datadir, LogFile)
}
sys := logger.NewStdLogSystem(writer, log.LstdFlags, logger.LogLevel(LogLevel))
logger.AddLogSystem(sys)
if DebugFile != "" {
writer = openLogFile(Datadir, DebugFile)
logger.AddLogSystem(logger.NewStdLogSystem(writer, log.LstdFlags, logger.DebugLevel))
}
return sys
}
func InitConfig(vmType int, ConfigFile string, Datadir string, EnvPrefix string) *ethutil.ConfigManager {
InitDataDir(Datadir)
initDataDir(Datadir)
cfg := ethutil.ReadConfig(ConfigFile, Datadir, EnvPrefix)
cfg.VmType = vmType
@ -138,43 +98,6 @@ func exit(err error) {
os.Exit(status)
}
func NewDatabase() ethutil.Database {
db, err := ethdb.NewLDBDatabase("database")
if err != nil {
exit(err)
}
return db
}
func NewClientIdentity(clientIdentifier, version, customIdentifier string, pubkey string) *p2p.SimpleClientIdentity {
return p2p.NewSimpleClientIdentity(clientIdentifier, version, customIdentifier, pubkey)
}
func NatType(natType string, gateway string) (nat p2p.NAT) {
switch natType {
case "UPNP":
nat = p2p.UPNP()
case "PMP":
ip := net.ParseIP(gateway)
if ip == nil {
clilogger.Fatalf("cannot resolve PMP gateway IP %s", gateway)
}
nat = p2p.PMP(ip)
case "":
default:
clilogger.Fatalf("unrecognised NAT type '%s'", natType)
}
return
}
func NewEthereum(db ethutil.Database, clientIdentity p2p.ClientIdentity, keyManager *crypto.KeyManager, nat p2p.NAT, OutboundPort string, MaxPeer int) *eth.Ethereum {
ethereum, err := eth.New(db, clientIdentity, keyManager, nat, OutboundPort, MaxPeer)
if err != nil {
clilogger.Fatalln("eth start err:", err)
}
return ethereum
}
func StartEthereum(ethereum *eth.Ethereum, UseSeed bool) {
clilogger.Infof("Starting %s", ethereum.ClientIdentity())
ethereum.Start(UseSeed)
@ -184,24 +107,6 @@ func StartEthereum(ethereum *eth.Ethereum, UseSeed bool) {
})
}
func ShowGenesis(ethereum *eth.Ethereum) {
clilogger.Infoln(ethereum.ChainManager().Genesis())
exit(nil)
}
func NewKeyManager(KeyStore string, Datadir string, db ethutil.Database) *crypto.KeyManager {
var keyManager *crypto.KeyManager
switch {
case KeyStore == "db":
keyManager = crypto.NewDBKeyManager(db)
case KeyStore == "file":
keyManager = crypto.NewFileKeyManager(Datadir)
default:
exit(fmt.Errorf("unknown keystore type: %s", KeyStore))
}
return keyManager
}
func DefaultAssetPath() string {
var assetPath string
// If the current working directory is the go-ethereum dir

@ -10,6 +10,7 @@ import (
)
type VMEnv struct {
chain *core.ChainManager
state *state.StateDB
block *types.Block
@ -20,8 +21,9 @@ type VMEnv struct {
Gas *big.Int
}
func NewEnv(state *state.StateDB, block *types.Block, transactor []byte, value *big.Int) *VMEnv {
func NewEnv(chain *core.ChainManager, state *state.StateDB, block *types.Block, transactor []byte, value *big.Int) *VMEnv {
return &VMEnv{
chain: chain,
state: state,
block: block,
transactor: transactor,
@ -35,12 +37,18 @@ func (self *VMEnv) PrevHash() []byte { return self.block.ParentHash() }
func (self *VMEnv) Coinbase() []byte { return self.block.Coinbase() }
func (self *VMEnv) Time() int64 { return self.block.Time() }
func (self *VMEnv) Difficulty() *big.Int { return self.block.Difficulty() }
func (self *VMEnv) BlockHash() []byte { return self.block.Hash() }
func (self *VMEnv) GasLimit() *big.Int { return self.block.GasLimit() }
func (self *VMEnv) Value() *big.Int { return self.value }
func (self *VMEnv) State() *state.StateDB { return self.state }
func (self *VMEnv) Depth() int { return self.depth }
func (self *VMEnv) SetDepth(i int) { self.depth = i }
func (self *VMEnv) GetHash(n uint64) []byte {
if block := self.chain.GetBlockByNumber(n); block != nil {
return block.Hash()
}
return nil
}
func (self *VMEnv) AddLog(log state.Log) {
self.state.AddLog(log)
}

@ -6,7 +6,6 @@ import (
"fmt"
"math/big"
"sync"
"time"
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/crypto"
@ -22,18 +21,6 @@ import (
var statelogger = logger.NewLogger("BLOCK")
type Peer interface {
Inbound() bool
LastSend() time.Time
LastPong() int64
Host() []byte
Port() uint16
Version() string
PingTime() string
Connected() *int32
Caps() *ethutil.Value
}
type EthManager interface {
BlockManager() *BlockManager
ChainManager() *ChainManager
@ -113,7 +100,7 @@ done:
txGas := new(big.Int).Set(tx.Gas())
cb := state.GetStateObject(coinbase.Address())
st := NewStateTransition(cb, tx, state, block)
st := NewStateTransition(NewEnv(state, self.bc, tx, block), tx, cb)
_, err = st.TransitionState()
if err != nil {
switch {
@ -232,6 +219,8 @@ func (sm *BlockManager) ProcessWithParent(block, parent *types.Block) (td *big.I
// Sync the current block's state to the database and cancelling out the deferred Undo
state.Sync()
state.Manifest().SetHash(block.Hash())
messages := state.Manifest().Messages
state.Manifest().Reset()
@ -342,7 +331,7 @@ func (sm *BlockManager) AccumelateRewards(statedb *state.StateDB, block, parent
To: block.Header().Coinbase,
Input: nil,
Origin: nil,
Block: block.Hash(), Timestamp: int64(block.Header().Time), Coinbase: block.Header().Coinbase, Number: block.Header().Number,
Timestamp: int64(block.Header().Time), Coinbase: block.Header().Coinbase, Number: block.Header().Number,
Value: new(big.Int).Add(reward, block.Reward),
})

@ -271,15 +271,15 @@ func (self *ChainManager) GetBlockByNumber(num uint64) *types.Block {
self.mu.RLock()
defer self.mu.RUnlock()
block := self.currentBlock
var block *types.Block
if num <= self.currentBlock.Number().Uint64() {
block = self.currentBlock
for ; block != nil; block = self.GetBlock(block.Header().ParentHash) {
if block.Header().Number.Uint64() == num {
break
}
}
if block != nil && block.Header().Number.Uint64() == 0 && num != 0 {
return nil
}
return block

@ -4,7 +4,6 @@ import (
"fmt"
"math/big"
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/crypto"
"github.com/ethereum/go-ethereum/ethutil"
"github.com/ethereum/go-ethereum/state"
@ -28,18 +27,17 @@ import (
* 6) Derive new state root
*/
type StateTransition struct {
coinbase, receiver []byte
coinbase []byte
msg Message
gas, gasPrice *big.Int
initialGas *big.Int
value *big.Int
data []byte
state *state.StateDB
block *types.Block
cb, rec, sen *state.StateObject
Env vm.Environment
env vm.Environment
}
type Message interface {
@ -69,16 +67,19 @@ func MessageGasValue(msg Message) *big.Int {
return new(big.Int).Mul(msg.Gas(), msg.GasPrice())
}
func NewStateTransition(coinbase *state.StateObject, msg Message, state *state.StateDB, block *types.Block) *StateTransition {
return &StateTransition{coinbase.Address(), msg.To(), msg, new(big.Int), new(big.Int).Set(msg.GasPrice()), new(big.Int), msg.Value(), msg.Data(), state, block, coinbase, nil, nil, nil}
}
func (self *StateTransition) VmEnv() vm.Environment {
if self.Env == nil {
self.Env = NewEnv(self.state, self.msg, self.block)
func NewStateTransition(env vm.Environment, msg Message, coinbase *state.StateObject) *StateTransition {
return &StateTransition{
coinbase: coinbase.Address(),
env: env,
msg: msg,
gas: new(big.Int),
gasPrice: new(big.Int).Set(msg.GasPrice()),
initialGas: new(big.Int),
value: msg.Value(),
data: msg.Data(),
state: env.State(),
cb: coinbase,
}
return self.Env
}
func (self *StateTransition) Coinbase() *state.StateObject {
@ -183,7 +184,7 @@ func (self *StateTransition) TransitionState() (ret []byte, err error) {
return
}
vmenv := self.VmEnv()
vmenv := self.env
var ref vm.ContextRef
if MessageCreatesContract(msg) {
contract := MakeContract(msg, self.state)

@ -13,10 +13,12 @@ type VMEnv struct {
block *types.Block
msg Message
depth int
chain *ChainManager
}
func NewEnv(state *state.StateDB, msg Message, block *types.Block) *VMEnv {
func NewEnv(state *state.StateDB, chain *ChainManager, msg Message, block *types.Block) *VMEnv {
return &VMEnv{
chain: chain,
state: state,
block: block,
msg: msg,
@ -25,16 +27,21 @@ func NewEnv(state *state.StateDB, msg Message, block *types.Block) *VMEnv {
func (self *VMEnv) Origin() []byte { return self.msg.From() }
func (self *VMEnv) BlockNumber() *big.Int { return self.block.Number() }
func (self *VMEnv) PrevHash() []byte { return self.block.ParentHash() }
func (self *VMEnv) Coinbase() []byte { return self.block.Coinbase() }
func (self *VMEnv) Time() int64 { return self.block.Time() }
func (self *VMEnv) Difficulty() *big.Int { return self.block.Difficulty() }
func (self *VMEnv) BlockHash() []byte { return self.block.Hash() }
func (self *VMEnv) GasLimit() *big.Int { return self.block.GasLimit() }
func (self *VMEnv) Value() *big.Int { return self.msg.Value() }
func (self *VMEnv) State() *state.StateDB { return self.state }
func (self *VMEnv) Depth() int { return self.depth }
func (self *VMEnv) SetDepth(i int) { self.depth = i }
func (self *VMEnv) GetHash(n uint64) []byte {
if block := self.chain.GetBlockByNumber(n); block != nil {
return block.Hash()
}
return nil
}
func (self *VMEnv) AddLog(log state.Log) {
self.state.AddLog(log)
}

@ -1,11 +1,13 @@
package eth
import (
"fmt"
"net"
"sync"
"github.com/ethereum/go-ethereum/core"
"github.com/ethereum/go-ethereum/crypto"
"github.com/ethereum/go-ethereum/ethdb"
"github.com/ethereum/go-ethereum/ethutil"
"github.com/ethereum/go-ethereum/event"
ethlogger "github.com/ethereum/go-ethereum/logger"
@ -19,6 +21,24 @@ const (
seedNodeAddress = "poc-7.ethdev.com:30300"
)
type Config struct {
Name string
Version string
Identifier string
KeyStore string
DataDir string
LogFile string
LogLevel int
KeyRing string
MaxPeers int
Port string
NATType string
PMPGateway string
KeyManager *crypto.KeyManager
}
var logger = ethlogger.NewLogger("SERV")
type Ethereum struct {
@ -38,7 +58,7 @@ type Ethereum struct {
blockPool *BlockPool
whisper *whisper.Whisper
server *p2p.Server
net *p2p.Server
eventMux *event.TypeMux
txSub event.Subscription
blockSub event.Subscription
@ -47,6 +67,7 @@ type Ethereum struct {
keyManager *crypto.KeyManager
clientIdentity p2p.ClientIdentity
logger ethlogger.LogSystem
synclock sync.Mutex
syncGroup sync.WaitGroup
@ -54,7 +75,36 @@ type Ethereum struct {
Mining bool
}
func New(db ethutil.Database, identity p2p.ClientIdentity, keyManager *crypto.KeyManager, nat p2p.NAT, port string, maxPeers int) (*Ethereum, error) {
func New(config *Config) (*Ethereum, error) {
// Boostrap database
logger := ethlogger.New(config.DataDir, config.LogFile, config.LogLevel)
db, err := ethdb.NewLDBDatabase("database")
if err != nil {
return nil, err
}
// Perform database sanity checks
d, _ := db.Get([]byte("ProtocolVersion"))
protov := ethutil.NewValue(d).Uint()
if protov != ProtocolVersion && protov != 0 {
return nil, fmt.Errorf("Database version mismatch. Protocol(%d / %d). `rm -rf %s`", protov, ProtocolVersion, ethutil.Config.ExecPath+"/database")
}
// Create new keymanager
var keyManager *crypto.KeyManager
switch config.KeyStore {
case "db":
keyManager = crypto.NewDBKeyManager(db)
case "file":
keyManager = crypto.NewFileKeyManager(config.DataDir)
default:
return nil, fmt.Errorf("unknown keystore type: %s", config.KeyStore)
}
// Initialise the keyring
keyManager.Init(config.KeyRing, 0, false)
// Create a new client id for this instance. This will help identifying the node on the network
clientId := p2p.NewSimpleClientIdentity(config.Name, config.Version, config.Identifier, keyManager.PublicKey())
saveProtocolVersion(db)
ethutil.Config.Db = db
@ -64,9 +114,10 @@ func New(db ethutil.Database, identity p2p.ClientIdentity, keyManager *crypto.Ke
quit: make(chan bool),
db: db,
keyManager: keyManager,
clientIdentity: identity,
clientIdentity: clientId,
blacklist: p2p.NewBlacklist(),
eventMux: &event.TypeMux{},
logger: logger,
}
eth.chainManager = core.NewChainManager(eth.EventMux())
@ -85,17 +136,20 @@ func New(db ethutil.Database, identity p2p.ClientIdentity, keyManager *crypto.Ke
ethProto := EthProtocol(eth.txPool, eth.chainManager, eth.blockPool)
protocols := []p2p.Protocol{ethProto, eth.whisper.Protocol()}
server := &p2p.Server{
Identity: identity,
MaxPeers: maxPeers,
nat, err := p2p.ParseNAT(config.NATType, config.PMPGateway)
if err != nil {
return nil, err
}
eth.net = &p2p.Server{
Identity: clientId,
MaxPeers: config.MaxPeers,
Protocols: protocols,
ListenAddr: ":" + port,
ListenAddr: ":" + config.Port,
Blacklist: eth.blacklist,
NAT: nat,
}
eth.server = server
return eth, nil
}
@ -103,6 +157,10 @@ func (s *Ethereum) KeyManager() *crypto.KeyManager {
return s.keyManager
}
func (s *Ethereum) Logger() ethlogger.LogSystem {
return s.logger
}
func (s *Ethereum) ClientIdentity() p2p.ClientIdentity {
return s.clientIdentity
}
@ -144,20 +202,20 @@ func (s *Ethereum) IsListening() bool {
}
func (s *Ethereum) PeerCount() int {
return s.server.PeerCount()
return s.net.PeerCount()
}
func (s *Ethereum) Peers() []*p2p.Peer {
return s.server.Peers()
return s.net.Peers()
}
func (s *Ethereum) MaxPeers() int {
return s.server.MaxPeers
return s.net.MaxPeers
}
// Start the ethereum
func (s *Ethereum) Start(seed bool) error {
err := s.server.Start()
err := s.net.Start()
if err != nil {
return err
}
@ -191,7 +249,7 @@ func (self *Ethereum) SuggestPeer(addr string) error {
return err
}
self.server.SuggestPeer(netaddr.IP, netaddr.Port, nil)
self.net.SuggestPeer(netaddr.IP, netaddr.Port, nil)
return nil
}
@ -227,7 +285,7 @@ func (self *Ethereum) txBroadcastLoop() {
// automatically stops if unsubscribe
for obj := range self.txSub.Chan() {
event := obj.(core.TxPreEvent)
self.server.Broadcast("eth", TxMsg, []interface{}{event.Tx.RlpData()})
self.net.Broadcast("eth", TxMsg, []interface{}{event.Tx.RlpData()})
}
}
@ -236,7 +294,7 @@ func (self *Ethereum) blockBroadcastLoop() {
for obj := range self.txSub.Chan() {
switch ev := obj.(type) {
case core.NewMinedBlockEvent:
self.server.Broadcast("eth", NewBlockMsg, ev.Block.RlpData())
self.net.Broadcast("eth", NewBlockMsg, ev.Block.RlpData())
}
}
}

@ -4,6 +4,7 @@ import (
"io/ioutil"
"os"
"os/user"
"path"
"strings"
)
@ -58,3 +59,10 @@ func WriteFile(filePath string, content []byte) error {
return nil
}
func AbsolutePath(Datadir string, filename string) string {
if path.IsAbs(filename) {
return filename
}
return path.Join(Datadir, filename)
}

33
logger/log.go Normal file

@ -0,0 +1,33 @@
package logger
import (
"fmt"
"io"
"log"
"os"
"github.com/ethereum/go-ethereum/ethutil"
)
func openLogFile(datadir string, filename string) *os.File {
path := ethutil.AbsolutePath(datadir, filename)
file, err := os.OpenFile(path, os.O_RDWR|os.O_CREATE|os.O_APPEND, 0666)
if err != nil {
panic(fmt.Sprintf("error opening log file '%s': %v", filename, err))
}
return file
}
func New(datadir string, logFile string, logLevel int) LogSystem {
var writer io.Writer
if logFile == "" {
writer = os.Stdout
} else {
writer = openLogFile(datadir, logFile)
}
sys := NewStdLogSystem(writer, log.LstdFlags, LogLevel(logLevel))
AddLogSystem(sys)
return sys
}

@ -17,10 +17,10 @@ type SimpleClientIdentity struct {
customIdentifier string
os string
implementation string
pubkey string
pubkey []byte
}
func NewSimpleClientIdentity(clientIdentifier string, version string, customIdentifier string, pubkey string) *SimpleClientIdentity {
func NewSimpleClientIdentity(clientIdentifier string, version string, customIdentifier string, pubkey []byte) *SimpleClientIdentity {
clientIdentity := &SimpleClientIdentity{
clientIdentifier: clientIdentifier,
version: version,

23
p2p/nat.go Normal file

@ -0,0 +1,23 @@
package p2p
import (
"fmt"
"net"
)
func ParseNAT(natType string, gateway string) (nat NAT, err error) {
switch natType {
case "UPNP":
nat = UPNP()
case "PMP":
ip := net.ParseIP(gateway)
if ip == nil {
return nil, fmt.Errorf("cannot resolve PMP gateway IP %s", gateway)
}
nat = PMP(ip)
case "":
default:
return nil, fmt.Errorf("unrecognised NAT type '%s'", natType)
}
return
}

@ -1,4 +1,4 @@
package core
package dagger
import (
"hash"

@ -1,4 +1,4 @@
package core
package dagger
import (
"math/big"

@ -30,6 +30,12 @@ func (self *Manifest) AddMessage(msg *Message) *Message {
return msg
}
func (self *Manifest) SetHash(hash []byte) {
for _, message := range self.Messages {
message.Block = hash
}
}
type Messages []*Message
type Message struct {
To, From []byte

@ -55,9 +55,11 @@ func (self *Env) PrevHash() []byte { return self.parent }
func (self *Env) Coinbase() []byte { return self.coinbase }
func (self *Env) Time() int64 { return self.time }
func (self *Env) Difficulty() *big.Int { return self.difficulty }
func (self *Env) BlockHash() []byte { return nil }
func (self *Env) State() *state.StateDB { return self.state }
func (self *Env) GasLimit() *big.Int { return self.gasLimit }
func (self *Env) GetHash(n uint64) []byte {
return nil
}
func (self *Env) AddLog(log state.Log) {
self.logs = append(self.logs, log)
}
@ -126,10 +128,9 @@ func RunState(statedb *state.StateDB, env, tx map[string]string) ([]byte, state.
message := NewMessage(keyPair.Address(), to, data, value, gas, price)
Log.DebugDetailf("message{ to: %x, from %x, value: %v, gas: %v, price: %v }\n", message.to[:4], message.from[:4], message.value, message.gas, message.price)
st := core.NewStateTransition(coinbase, message, statedb, nil)
vmenv := NewEnvFromMap(statedb, env, tx)
st := core.NewStateTransition(vmenv, message, coinbase)
vmenv.origin = keyPair.Address()
st.Env = vmenv
ret, err := st.TransitionState()
statedb.Update(vmenv.Gas)

@ -5,7 +5,6 @@ import (
"math/big"
"github.com/ethereum/go-ethereum/ethutil"
"github.com/ethereum/go-ethereum/state"
)
type ContextRef interface {
@ -18,7 +17,6 @@ type Context struct {
caller ContextRef
object ContextRef
Code []byte
message *state.Message
Gas, UsedGas, Price *big.Int
@ -26,8 +24,8 @@ type Context struct {
}
// Create a new context for the given data items
func NewContext(msg *state.Message, caller ContextRef, object ContextRef, code []byte, gas, price *big.Int) *Context {
c := &Context{message: msg, caller: caller, object: object, Code: code, Args: nil}
func NewContext(caller ContextRef, object ContextRef, code []byte, gas, price *big.Int) *Context {
c := &Context{caller: caller, object: object, Code: code, Args: nil}
// Gas should be a pointer so it can safely be reduced through the run
// This pointer will be off the state transition
@ -40,13 +38,13 @@ func NewContext(msg *state.Message, caller ContextRef, object ContextRef, code [
return c
}
func (c *Context) GetOp(x uint64) OpCode {
return OpCode(c.GetByte(x))
func (c *Context) GetOp(n uint64) OpCode {
return OpCode(c.GetByte(n))
}
func (c *Context) GetByte(x uint64) byte {
if x < uint64(len(c.Code)) {
return c.Code[x]
func (c *Context) GetByte(n uint64) byte {
if n < uint64(len(c.Code)) {
return c.Code[n]
}
return 0

@ -14,11 +14,10 @@ type Environment interface {
Origin() []byte
BlockNumber() *big.Int
PrevHash() []byte
GetHash(n uint64) []byte
Coinbase() []byte
Time() int64
Difficulty() *big.Int
BlockHash() []byte
GasLimit() *big.Int
Transfer(from, to Account, amount *big.Int) error
AddLog(state.Log)
@ -31,11 +30,6 @@ type Environment interface {
Create(me ContextRef, addr, data []byte, gas, price, value *big.Int) ([]byte, error, ContextRef)
}
type Object interface {
GetStorage(key *big.Int) *ethutil.Value
SetStorage(key *big.Int, value *ethutil.Value)
}
type Account interface {
SubBalance(amount *big.Int)
AddBalance(amount *big.Int)

@ -59,7 +59,7 @@ const (
const (
// 0x40 range - block operations
PREVHASH OpCode = 0x40 + iota
BLOCKHASH OpCode = 0x40 + iota
COINBASE
TIMESTAMP
NUMBER
@ -216,7 +216,7 @@ var opCodeToString = map[OpCode]string{
GASPRICE: "TXGASPRICE",
// 0x40 range - block operations
PREVHASH: "PREVHASH",
BLOCKHASH: "BLOCKHASH",
COINBASE: "COINBASE",
TIMESTAMP: "TIMESTAMP",
NUMBER: "NUMBER",

@ -44,10 +44,10 @@ func (self *DebugVm) Run(me, caller ContextRef, code []byte, value, gas, price *
To: me.Address(), From: caller.Address(),
Input: callData,
Origin: self.env.Origin(),
Block: self.env.BlockHash(), Timestamp: self.env.Time(), Coinbase: self.env.Coinbase(), Number: self.env.BlockNumber(),
Timestamp: self.env.Time(), Coinbase: self.env.Coinbase(), Number: self.env.BlockNumber(),
Value: value,
})
context := NewContext(msg, caller, me, code, gas, price)
context := NewContext(caller, me, code, gas, price)
if self.Recoverable {
// Recover from any require exception
@ -83,7 +83,7 @@ func (self *DebugVm) Run(me, caller ContextRef, code []byte, value, gas, price *
jump = func(from uint64, to *big.Int) {
p := to.Uint64()
nop := OpCode(context.GetOp(p))
nop := context.GetOp(p)
if !destinations.Has(p) {
panic(fmt.Sprintf("invalid jump destination (%v) %v", nop, p))
}
@ -516,12 +516,15 @@ func (self *DebugVm) Run(me, caller ContextRef, code []byte, value, gas, price *
self.Printf(" => %v", context.Price)
// 0x40 range
case PREVHASH:
prevHash := self.env.PrevHash()
case BLOCKHASH:
num := stack.Pop()
if num.Cmp(new(big.Int).Sub(self.env.BlockNumber(), ethutil.Big256)) < 0 {
stack.Push(ethutil.Big0)
} else {
stack.Push(ethutil.BigD(self.env.GetHash(num.Uint64())))
}
stack.Push(ethutil.BigD(prevHash))
self.Printf(" => 0x%x", prevHash)
self.Printf(" => 0x%x", stack.Peek().Bytes())
case COINBASE:
coinbase := self.env.Coinbase()
@ -614,7 +617,7 @@ func (self *DebugVm) Run(me, caller ContextRef, code []byte, value, gas, price *
val, loc := stack.Popn()
statedb.SetState(context.Address(), loc.Bytes(), val)
context.message.AddStorageChange(loc.Bytes())
msg.AddStorageChange(loc.Bytes())
self.Printf(" {0x%x : 0x%x}", loc.Bytes(), val.Bytes())
case JUMP:

@ -87,7 +87,7 @@ func (self *XEth) ExecuteObject(object *Object, data []byte, value, gas, price *
self.Vm.State = self.World().State().Copy()
vmenv := NewEnv(self.Vm.State, block, value.BigInt(), initiator.Address())
vmenv := NewEnv(self.chainManager, self.Vm.State, block, value.BigInt(), initiator.Address())
return vmenv.Call(initiator, object.Address(), data, gas.BigInt(), price.BigInt(), value.BigInt())
}

@ -10,6 +10,7 @@ import (
)
type VMEnv struct {
chain *core.ChainManager
state *state.StateDB
block *types.Block
value *big.Int
@ -18,7 +19,7 @@ type VMEnv struct {
depth int
}
func NewEnv(state *state.StateDB, block *types.Block, value *big.Int, sender []byte) *VMEnv {
func NewEnv(chain *core.ChainManager, state *state.StateDB, block *types.Block, value *big.Int, sender []byte) *VMEnv {
return &VMEnv{
state: state,
block: block,
@ -33,12 +34,18 @@ func (self *VMEnv) PrevHash() []byte { return self.block.ParentHash() }
func (self *VMEnv) Coinbase() []byte { return self.block.Coinbase() }
func (self *VMEnv) Time() int64 { return self.block.Time() }
func (self *VMEnv) Difficulty() *big.Int { return self.block.Difficulty() }
func (self *VMEnv) BlockHash() []byte { return self.block.Hash() }
func (self *VMEnv) GasLimit() *big.Int { return self.block.GasLimit() }
func (self *VMEnv) Value() *big.Int { return self.value }
func (self *VMEnv) State() *state.StateDB { return self.state }
func (self *VMEnv) Depth() int { return self.depth }
func (self *VMEnv) SetDepth(i int) { self.depth = i }
func (self *VMEnv) GetHash(n uint64) []byte {
if block := self.chain.GetBlockByNumber(n); block != nil {
return block.Hash()
}
return nil
}
func (self *VMEnv) AddLog(log state.Log) {
self.state.AddLog(log)
}