Merge branch 'poc8' into docbranch
This commit is contained in:
commit
987119cd4a
@ -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(ð.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"
|
||||
]
|
||||
}
|
20
cmd/ethtest/dist/ethereum.js
vendored
20
cmd/ethtest/dist/ethereum.js
vendored
File diff suppressed because one or more lines are too long
29
cmd/ethtest/dist/ethereum.js.map
vendored
29
cmd/ethtest/dist/ethereum.js.map
vendored
File diff suppressed because one or more lines are too long
1
cmd/ethtest/dist/ethereum.min.js
vendored
1
cmd/ethtest/dist/ethereum.min.js
vendored
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() {
|
||||
|
@ -72,8 +72,7 @@ type Gui struct {
|
||||
|
||||
plugins map[string]plugin
|
||||
|
||||
miner *miner.Miner
|
||||
stdLog logger.LogSystem
|
||||
miner *miner.Miner
|
||||
}
|
||||
|
||||
// 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(ð.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)
|
||||
}
|
||||
srv.SuggestPeer(seed.IP, seed.Port, nil)
|
||||
|
||||
select {}
|
||||
}
|
||||
|
103
cmd/utils/cmd.go
103
cmd/utils/cmd.go
@ -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()
|
||||
|
||||
@ -339,10 +328,10 @@ func (sm *BlockManager) AccumelateRewards(statedb *state.StateDB, block, parent
|
||||
account.AddAmount(reward)
|
||||
|
||||
statedb.Manifest().AddMessage(&state.Message{
|
||||
To: block.Header().Coinbase,
|
||||
Input: nil,
|
||||
Origin: nil,
|
||||
Block: block.Hash(), Timestamp: int64(block.Header().Time), Coinbase: block.Header().Coinbase, Number: block.Header().Number,
|
||||
To: block.Header().Coinbase,
|
||||
Input: nil,
|
||||
Origin: nil,
|
||||
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
|
||||
for ; block != nil; block = self.GetBlock(block.Header().ParentHash) {
|
||||
if block.Header().Number.Uint64() == num {
|
||||
break
|
||||
}
|
||||
}
|
||||
var block *types.Block
|
||||
|
||||
if block != nil && block.Header().Number.Uint64() == 0 && num != 0 {
|
||||
return nil
|
||||
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
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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
|
||||
msg Message
|
||||
gas, gasPrice *big.Int
|
||||
initialGas *big.Int
|
||||
value *big.Int
|
||||
data []byte
|
||||
state *state.StateDB
|
||||
block *types.Block
|
||||
coinbase []byte
|
||||
msg Message
|
||||
gas, gasPrice *big.Int
|
||||
initialGas *big.Int
|
||||
value *big.Int
|
||||
data []byte
|
||||
state *state.StateDB
|
||||
|
||||
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
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
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 {
|
||||
@ -15,10 +14,9 @@ type ContextRef interface {
|
||||
}
|
||||
|
||||
type Context struct {
|
||||
caller ContextRef
|
||||
object ContextRef
|
||||
Code []byte
|
||||
message *state.Message
|
||||
caller ContextRef
|
||||
object ContextRef
|
||||
Code []byte
|
||||
|
||||
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",
|
||||
|
@ -42,12 +42,12 @@ func (self *DebugVm) Run(me, caller ContextRef, code []byte, value, gas, price *
|
||||
|
||||
msg := self.env.State().Manifest().AddMessage(&state.Message{
|
||||
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(),
|
||||
Input: callData,
|
||||
Origin: self.env.Origin(),
|
||||
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)
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user