forked from cerc-io/plugeth
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.
|
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.
|
Ethereum is currently in its testing phase.
|
||||||
|
|
||||||
|
@ -25,13 +25,14 @@ import (
|
|||||||
|
|
||||||
"github.com/ethereum/go-ethereum/cmd/utils"
|
"github.com/ethereum/go-ethereum/cmd/utils"
|
||||||
"github.com/ethereum/go-ethereum/core/types"
|
"github.com/ethereum/go-ethereum/core/types"
|
||||||
|
"github.com/ethereum/go-ethereum/eth"
|
||||||
"github.com/ethereum/go-ethereum/ethutil"
|
"github.com/ethereum/go-ethereum/ethutil"
|
||||||
"github.com/ethereum/go-ethereum/logger"
|
"github.com/ethereum/go-ethereum/logger"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
ClientIdentifier = "Ethereum(G)"
|
ClientIdentifier = "Ethereum(G)"
|
||||||
Version = "0.7.11"
|
Version = "0.8.0"
|
||||||
)
|
)
|
||||||
|
|
||||||
var clilogger = logger.NewLogger("CLI")
|
var clilogger = logger.NewLogger("CLI")
|
||||||
@ -48,35 +49,26 @@ func main() {
|
|||||||
// precedence: code-internal flag default < config file < environment variables < command line
|
// precedence: code-internal flag default < config file < environment variables < command line
|
||||||
Init() // parsing 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")
|
utils.InitConfig(VmType, ConfigFile, Datadir, "ETH")
|
||||||
ethutil.Config.Diff = DiffTool
|
|
||||||
ethutil.Config.DiffType = DiffType
|
|
||||||
|
|
||||||
utils.InitDataDir(Datadir)
|
ethereum, err := eth.New(ð.Config{
|
||||||
|
Name: ClientIdentifier,
|
||||||
utils.InitLogging(Datadir, LogFile, LogLevel, DebugFile)
|
Version: Version,
|
||||||
|
KeyStore: KeyStore,
|
||||||
db := utils.NewDatabase()
|
DataDir: Datadir,
|
||||||
err := utils.DBSanityCheck(db)
|
LogFile: LogFile,
|
||||||
|
LogLevel: LogLevel,
|
||||||
|
Identifier: Identifier,
|
||||||
|
MaxPeers: MaxPeer,
|
||||||
|
Port: OutboundPort,
|
||||||
|
NATType: PMPGateway,
|
||||||
|
PMPGateway: PMPGateway,
|
||||||
|
KeyRing: KeyRing,
|
||||||
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fmt.Println(err)
|
clilogger.Fatalln(err)
|
||||||
|
|
||||||
os.Exit(1)
|
|
||||||
}
|
}
|
||||||
|
utils.KeyTasks(ethereum.KeyManager(), KeyRing, GenAddr, SecretFile, ExportDir, NonInteractive)
|
||||||
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 Dump {
|
if Dump {
|
||||||
var block *types.Block
|
var block *types.Block
|
||||||
@ -103,11 +95,7 @@ func main() {
|
|||||||
|
|
||||||
fmt.Println(block)
|
fmt.Println(block)
|
||||||
|
|
||||||
os.Exit(0)
|
return
|
||||||
}
|
|
||||||
|
|
||||||
if ShowGenesis {
|
|
||||||
utils.ShowGenesis(ethereum)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if StartMining {
|
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 }
|
model: ListModel { id: pastPeers }
|
||||||
|
|
||||||
Component.onCompleted: {
|
Component.onCompleted: {
|
||||||
|
/*
|
||||||
var ips = eth.pastPeers()
|
var ips = eth.pastPeers()
|
||||||
for(var i = 0; i < ips.length; i++) {
|
for(var i = 0; i < ips.length; i++) {
|
||||||
pastPeers.append({text: ips.get(i)})
|
pastPeers.append({text: ips.get(i)})
|
||||||
}
|
}
|
||||||
|
|
||||||
pastPeers.insert(0, {text: "poc-7.ethdev.com:30303"})
|
pastPeers.insert(0, {text: "poc-7.ethdev.com:30303"})
|
||||||
|
*/
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -20,7 +20,7 @@ Rectangle {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function setBalance() {
|
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)
|
if(menuItem)
|
||||||
menuItem.secondaryTitle = eth.numberToHuman(eth.balanceAt(eth.key().address))
|
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
|
// functions that allow Gui to implement interface guilogger.LogSystem
|
||||||
func (gui *Gui) SetLogLevel(level logger.LogLevel) {
|
func (gui *Gui) SetLogLevel(level logger.LogLevel) {
|
||||||
gui.logLevel = level
|
gui.logLevel = level
|
||||||
gui.stdLog.SetLogLevel(level)
|
gui.eth.Logger().SetLogLevel(level)
|
||||||
gui.config.Save("loglevel", 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()
|
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))
|
self.Logf("callsize %d", len(script))
|
||||||
go func() {
|
go func() {
|
||||||
|
@ -73,7 +73,6 @@ type Gui struct {
|
|||||||
plugins map[string]plugin
|
plugins map[string]plugin
|
||||||
|
|
||||||
miner *miner.Miner
|
miner *miner.Miner
|
||||||
stdLog logger.LogSystem
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create GUI, but doesn't start it
|
// 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
|
// Expose the eth library and the ui library to QML
|
||||||
context.SetVar("gui", gui)
|
context.SetVar("gui", gui)
|
||||||
context.SetVar("eth", gui.uiLib)
|
context.SetVar("eth", gui.uiLib)
|
||||||
context.SetVar("shh", gui.whisper)
|
//context.SetVar("shh", gui.whisper)
|
||||||
|
|
||||||
// Load the main QML interface
|
// Load the main QML interface
|
||||||
data, _ := ethutil.Config.Db.Get([]byte("KeyRing"))
|
data, _ := ethutil.Config.Db.Get([]byte("KeyRing"))
|
||||||
|
@ -26,15 +26,17 @@ import (
|
|||||||
"github.com/ethereum/go-ethereum/cmd/utils"
|
"github.com/ethereum/go-ethereum/cmd/utils"
|
||||||
"github.com/ethereum/go-ethereum/eth"
|
"github.com/ethereum/go-ethereum/eth"
|
||||||
"github.com/ethereum/go-ethereum/logger"
|
"github.com/ethereum/go-ethereum/logger"
|
||||||
|
"github.com/ethereum/go-ethereum/p2p"
|
||||||
"gopkg.in/qml.v1"
|
"gopkg.in/qml.v1"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
ClientIdentifier = "Mist"
|
ClientIdentifier = "Mist"
|
||||||
Version = "0.7.11"
|
Version = "0.8.0"
|
||||||
)
|
)
|
||||||
|
|
||||||
var ethereum *eth.Ethereum
|
var ethereum *eth.Ethereum
|
||||||
|
var mainlogger = logger.NewLogger("MAIN")
|
||||||
|
|
||||||
func run() error {
|
func run() error {
|
||||||
// precedence: code-internal flag default < config file < environment variables < command line
|
// precedence: code-internal flag default < config file < environment variables < command line
|
||||||
@ -43,27 +45,24 @@ func run() error {
|
|||||||
tstart := time.Now()
|
tstart := time.Now()
|
||||||
config := utils.InitConfig(VmType, ConfigFile, Datadir, "ETH")
|
config := utils.InitConfig(VmType, ConfigFile, Datadir, "ETH")
|
||||||
|
|
||||||
utils.InitDataDir(Datadir)
|
ethereum, err := eth.New(ð.Config{
|
||||||
|
Name: ClientIdentifier,
|
||||||
stdLog := utils.InitLogging(Datadir, LogFile, LogLevel, DebugFile)
|
Version: Version,
|
||||||
|
KeyStore: KeyStore,
|
||||||
db := utils.NewDatabase()
|
DataDir: Datadir,
|
||||||
err := utils.DBSanityCheck(db)
|
LogFile: LogFile,
|
||||||
|
LogLevel: LogLevel,
|
||||||
|
Identifier: Identifier,
|
||||||
|
MaxPeers: MaxPeer,
|
||||||
|
Port: OutboundPort,
|
||||||
|
NATType: PMPGateway,
|
||||||
|
PMPGateway: PMPGateway,
|
||||||
|
KeyRing: KeyRing,
|
||||||
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
ErrorWindow(err)
|
mainlogger.Fatalln(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)
|
|
||||||
}
|
}
|
||||||
|
utils.KeyTasks(ethereum.KeyManager(), KeyRing, GenAddr, SecretFile, ExportDir, NonInteractive)
|
||||||
|
|
||||||
if StartRpc {
|
if StartRpc {
|
||||||
utils.StartRpc(ethereum, RpcPort)
|
utils.StartRpc(ethereum, RpcPort)
|
||||||
@ -73,8 +72,7 @@ func run() error {
|
|||||||
utils.StartWebSockets(ethereum)
|
utils.StartWebSockets(ethereum)
|
||||||
}
|
}
|
||||||
|
|
||||||
gui := NewWindow(ethereum, config, clientIdentity, KeyRing, LogLevel)
|
gui := NewWindow(ethereum, config, ethereum.ClientIdentity().(*p2p.SimpleClientIdentity), KeyRing, LogLevel)
|
||||||
gui.stdLog = stdLog
|
|
||||||
|
|
||||||
utils.RegisterInterrupt(func(os.Signal) {
|
utils.RegisterInterrupt(func(os.Signal) {
|
||||||
gui.Stop()
|
gui.Stop()
|
||||||
|
@ -18,7 +18,7 @@ func main() {
|
|||||||
marshaled := elliptic.Marshal(crypto.S256(), key.PublicKey.X, key.PublicKey.Y)
|
marshaled := elliptic.Marshal(crypto.S256(), key.PublicKey.X, key.PublicKey.Y)
|
||||||
|
|
||||||
srv := p2p.Server{
|
srv := p2p.Server{
|
||||||
MaxPeers: 10,
|
MaxPeers: 100,
|
||||||
Identity: p2p.NewSimpleClientIdentity("Ethereum(G)", "0.1", "Peer Server Two", string(marshaled)),
|
Identity: p2p.NewSimpleClientIdentity("Ethereum(G)", "0.1", "Peer Server Two", string(marshaled)),
|
||||||
ListenAddr: ":30301",
|
ListenAddr: ":30301",
|
||||||
NAT: p2p.UPNP(),
|
NAT: p2p.UPNP(),
|
||||||
@ -29,12 +29,12 @@ func main() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// add seed peers
|
// 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 {
|
if err != nil {
|
||||||
fmt.Println("couldn't resolve:", err)
|
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 {}
|
select {}
|
||||||
}
|
}
|
||||||
|
103
cmd/utils/cmd.go
103
cmd/utils/cmd.go
@ -2,9 +2,6 @@ package utils
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
|
||||||
"log"
|
|
||||||
"net"
|
|
||||||
"os"
|
"os"
|
||||||
"os/signal"
|
"os/signal"
|
||||||
"path"
|
"path"
|
||||||
@ -16,11 +13,9 @@ import (
|
|||||||
"github.com/ethereum/go-ethereum/core/types"
|
"github.com/ethereum/go-ethereum/core/types"
|
||||||
"github.com/ethereum/go-ethereum/crypto"
|
"github.com/ethereum/go-ethereum/crypto"
|
||||||
"github.com/ethereum/go-ethereum/eth"
|
"github.com/ethereum/go-ethereum/eth"
|
||||||
"github.com/ethereum/go-ethereum/ethdb"
|
|
||||||
"github.com/ethereum/go-ethereum/ethutil"
|
"github.com/ethereum/go-ethereum/ethutil"
|
||||||
"github.com/ethereum/go-ethereum/logger"
|
"github.com/ethereum/go-ethereum/logger"
|
||||||
"github.com/ethereum/go-ethereum/miner"
|
"github.com/ethereum/go-ethereum/miner"
|
||||||
"github.com/ethereum/go-ethereum/p2p"
|
|
||||||
"github.com/ethereum/go-ethereum/rlp"
|
"github.com/ethereum/go-ethereum/rlp"
|
||||||
"github.com/ethereum/go-ethereum/rpc"
|
"github.com/ethereum/go-ethereum/rpc"
|
||||||
"github.com/ethereum/go-ethereum/xeth"
|
"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 {
|
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)
|
file, err := os.OpenFile(path, os.O_RDWR|os.O_CREATE|os.O_APPEND, 0666)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(fmt.Sprintf("error opening log file '%s': %v", filename, err))
|
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" {
|
if r == "n" || r == "y" {
|
||||||
break
|
break
|
||||||
} else {
|
} else {
|
||||||
fmt.Printf("Yes or no?", r)
|
fmt.Printf("Yes or no? (%s)", r)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return r == "y"
|
return r == "y"
|
||||||
}
|
}
|
||||||
|
|
||||||
func DBSanityCheck(db ethutil.Database) error {
|
func initDataDir(Datadir string) {
|
||||||
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) {
|
|
||||||
_, err := os.Stat(Datadir)
|
_, err := os.Stat(Datadir)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if os.IsNotExist(err) {
|
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 {
|
func InitConfig(vmType int, ConfigFile string, Datadir string, EnvPrefix string) *ethutil.ConfigManager {
|
||||||
InitDataDir(Datadir)
|
initDataDir(Datadir)
|
||||||
cfg := ethutil.ReadConfig(ConfigFile, Datadir, EnvPrefix)
|
cfg := ethutil.ReadConfig(ConfigFile, Datadir, EnvPrefix)
|
||||||
cfg.VmType = vmType
|
cfg.VmType = vmType
|
||||||
|
|
||||||
@ -138,43 +98,6 @@ func exit(err error) {
|
|||||||
os.Exit(status)
|
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) {
|
func StartEthereum(ethereum *eth.Ethereum, UseSeed bool) {
|
||||||
clilogger.Infof("Starting %s", ethereum.ClientIdentity())
|
clilogger.Infof("Starting %s", ethereum.ClientIdentity())
|
||||||
ethereum.Start(UseSeed)
|
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 {
|
func DefaultAssetPath() string {
|
||||||
var assetPath string
|
var assetPath string
|
||||||
// If the current working directory is the go-ethereum dir
|
// If the current working directory is the go-ethereum dir
|
||||||
|
@ -10,6 +10,7 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
type VMEnv struct {
|
type VMEnv struct {
|
||||||
|
chain *core.ChainManager
|
||||||
state *state.StateDB
|
state *state.StateDB
|
||||||
block *types.Block
|
block *types.Block
|
||||||
|
|
||||||
@ -20,8 +21,9 @@ type VMEnv struct {
|
|||||||
Gas *big.Int
|
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{
|
return &VMEnv{
|
||||||
|
chain: chain,
|
||||||
state: state,
|
state: state,
|
||||||
block: block,
|
block: block,
|
||||||
transactor: transactor,
|
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) Coinbase() []byte { return self.block.Coinbase() }
|
||||||
func (self *VMEnv) Time() int64 { return self.block.Time() }
|
func (self *VMEnv) Time() int64 { return self.block.Time() }
|
||||||
func (self *VMEnv) Difficulty() *big.Int { return self.block.Difficulty() }
|
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) GasLimit() *big.Int { return self.block.GasLimit() }
|
||||||
func (self *VMEnv) Value() *big.Int { return self.value }
|
func (self *VMEnv) Value() *big.Int { return self.value }
|
||||||
func (self *VMEnv) State() *state.StateDB { return self.state }
|
func (self *VMEnv) State() *state.StateDB { return self.state }
|
||||||
func (self *VMEnv) Depth() int { return self.depth }
|
func (self *VMEnv) Depth() int { return self.depth }
|
||||||
func (self *VMEnv) SetDepth(i int) { self.depth = i }
|
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) {
|
func (self *VMEnv) AddLog(log state.Log) {
|
||||||
self.state.AddLog(log)
|
self.state.AddLog(log)
|
||||||
}
|
}
|
||||||
|
@ -6,7 +6,6 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"math/big"
|
"math/big"
|
||||||
"sync"
|
"sync"
|
||||||
"time"
|
|
||||||
|
|
||||||
"github.com/ethereum/go-ethereum/core/types"
|
"github.com/ethereum/go-ethereum/core/types"
|
||||||
"github.com/ethereum/go-ethereum/crypto"
|
"github.com/ethereum/go-ethereum/crypto"
|
||||||
@ -22,18 +21,6 @@ import (
|
|||||||
|
|
||||||
var statelogger = logger.NewLogger("BLOCK")
|
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 {
|
type EthManager interface {
|
||||||
BlockManager() *BlockManager
|
BlockManager() *BlockManager
|
||||||
ChainManager() *ChainManager
|
ChainManager() *ChainManager
|
||||||
@ -113,7 +100,7 @@ done:
|
|||||||
txGas := new(big.Int).Set(tx.Gas())
|
txGas := new(big.Int).Set(tx.Gas())
|
||||||
|
|
||||||
cb := state.GetStateObject(coinbase.Address())
|
cb := state.GetStateObject(coinbase.Address())
|
||||||
st := NewStateTransition(cb, tx, state, block)
|
st := NewStateTransition(NewEnv(state, self.bc, tx, block), tx, cb)
|
||||||
_, err = st.TransitionState()
|
_, err = st.TransitionState()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
switch {
|
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
|
// Sync the current block's state to the database and cancelling out the deferred Undo
|
||||||
state.Sync()
|
state.Sync()
|
||||||
|
|
||||||
|
state.Manifest().SetHash(block.Hash())
|
||||||
|
|
||||||
messages := state.Manifest().Messages
|
messages := state.Manifest().Messages
|
||||||
state.Manifest().Reset()
|
state.Manifest().Reset()
|
||||||
|
|
||||||
@ -342,7 +331,7 @@ func (sm *BlockManager) AccumelateRewards(statedb *state.StateDB, block, parent
|
|||||||
To: block.Header().Coinbase,
|
To: block.Header().Coinbase,
|
||||||
Input: nil,
|
Input: nil,
|
||||||
Origin: 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),
|
Value: new(big.Int).Add(reward, block.Reward),
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -271,15 +271,15 @@ func (self *ChainManager) GetBlockByNumber(num uint64) *types.Block {
|
|||||||
self.mu.RLock()
|
self.mu.RLock()
|
||||||
defer self.mu.RUnlock()
|
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) {
|
for ; block != nil; block = self.GetBlock(block.Header().ParentHash) {
|
||||||
if block.Header().Number.Uint64() == num {
|
if block.Header().Number.Uint64() == num {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if block != nil && block.Header().Number.Uint64() == 0 && num != 0 {
|
|
||||||
return nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return block
|
return block
|
||||||
|
@ -4,7 +4,6 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"math/big"
|
"math/big"
|
||||||
|
|
||||||
"github.com/ethereum/go-ethereum/core/types"
|
|
||||||
"github.com/ethereum/go-ethereum/crypto"
|
"github.com/ethereum/go-ethereum/crypto"
|
||||||
"github.com/ethereum/go-ethereum/ethutil"
|
"github.com/ethereum/go-ethereum/ethutil"
|
||||||
"github.com/ethereum/go-ethereum/state"
|
"github.com/ethereum/go-ethereum/state"
|
||||||
@ -28,18 +27,17 @@ import (
|
|||||||
* 6) Derive new state root
|
* 6) Derive new state root
|
||||||
*/
|
*/
|
||||||
type StateTransition struct {
|
type StateTransition struct {
|
||||||
coinbase, receiver []byte
|
coinbase []byte
|
||||||
msg Message
|
msg Message
|
||||||
gas, gasPrice *big.Int
|
gas, gasPrice *big.Int
|
||||||
initialGas *big.Int
|
initialGas *big.Int
|
||||||
value *big.Int
|
value *big.Int
|
||||||
data []byte
|
data []byte
|
||||||
state *state.StateDB
|
state *state.StateDB
|
||||||
block *types.Block
|
|
||||||
|
|
||||||
cb, rec, sen *state.StateObject
|
cb, rec, sen *state.StateObject
|
||||||
|
|
||||||
Env vm.Environment
|
env vm.Environment
|
||||||
}
|
}
|
||||||
|
|
||||||
type Message interface {
|
type Message interface {
|
||||||
@ -69,16 +67,19 @@ func MessageGasValue(msg Message) *big.Int {
|
|||||||
return new(big.Int).Mul(msg.Gas(), msg.GasPrice())
|
return new(big.Int).Mul(msg.Gas(), msg.GasPrice())
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewStateTransition(coinbase *state.StateObject, msg Message, state *state.StateDB, block *types.Block) *StateTransition {
|
func NewStateTransition(env vm.Environment, msg Message, coinbase *state.StateObject) *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}
|
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,
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self *StateTransition) VmEnv() vm.Environment {
|
|
||||||
if self.Env == nil {
|
|
||||||
self.Env = NewEnv(self.state, self.msg, self.block)
|
|
||||||
}
|
|
||||||
|
|
||||||
return self.Env
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self *StateTransition) Coinbase() *state.StateObject {
|
func (self *StateTransition) Coinbase() *state.StateObject {
|
||||||
@ -183,7 +184,7 @@ func (self *StateTransition) TransitionState() (ret []byte, err error) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
vmenv := self.VmEnv()
|
vmenv := self.env
|
||||||
var ref vm.ContextRef
|
var ref vm.ContextRef
|
||||||
if MessageCreatesContract(msg) {
|
if MessageCreatesContract(msg) {
|
||||||
contract := MakeContract(msg, self.state)
|
contract := MakeContract(msg, self.state)
|
||||||
|
@ -13,10 +13,12 @@ type VMEnv struct {
|
|||||||
block *types.Block
|
block *types.Block
|
||||||
msg Message
|
msg Message
|
||||||
depth int
|
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{
|
return &VMEnv{
|
||||||
|
chain: chain,
|
||||||
state: state,
|
state: state,
|
||||||
block: block,
|
block: block,
|
||||||
msg: msg,
|
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) Origin() []byte { return self.msg.From() }
|
||||||
func (self *VMEnv) BlockNumber() *big.Int { return self.block.Number() }
|
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) Coinbase() []byte { return self.block.Coinbase() }
|
||||||
func (self *VMEnv) Time() int64 { return self.block.Time() }
|
func (self *VMEnv) Time() int64 { return self.block.Time() }
|
||||||
func (self *VMEnv) Difficulty() *big.Int { return self.block.Difficulty() }
|
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) GasLimit() *big.Int { return self.block.GasLimit() }
|
||||||
func (self *VMEnv) Value() *big.Int { return self.msg.Value() }
|
func (self *VMEnv) Value() *big.Int { return self.msg.Value() }
|
||||||
func (self *VMEnv) State() *state.StateDB { return self.state }
|
func (self *VMEnv) State() *state.StateDB { return self.state }
|
||||||
func (self *VMEnv) Depth() int { return self.depth }
|
func (self *VMEnv) Depth() int { return self.depth }
|
||||||
func (self *VMEnv) SetDepth(i int) { self.depth = i }
|
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) {
|
func (self *VMEnv) AddLog(log state.Log) {
|
||||||
self.state.AddLog(log)
|
self.state.AddLog(log)
|
||||||
}
|
}
|
||||||
|
@ -1,11 +1,13 @@
|
|||||||
package eth
|
package eth
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"fmt"
|
||||||
"net"
|
"net"
|
||||||
"sync"
|
"sync"
|
||||||
|
|
||||||
"github.com/ethereum/go-ethereum/core"
|
"github.com/ethereum/go-ethereum/core"
|
||||||
"github.com/ethereum/go-ethereum/crypto"
|
"github.com/ethereum/go-ethereum/crypto"
|
||||||
|
"github.com/ethereum/go-ethereum/ethdb"
|
||||||
"github.com/ethereum/go-ethereum/ethutil"
|
"github.com/ethereum/go-ethereum/ethutil"
|
||||||
"github.com/ethereum/go-ethereum/event"
|
"github.com/ethereum/go-ethereum/event"
|
||||||
ethlogger "github.com/ethereum/go-ethereum/logger"
|
ethlogger "github.com/ethereum/go-ethereum/logger"
|
||||||
@ -19,6 +21,24 @@ const (
|
|||||||
seedNodeAddress = "poc-7.ethdev.com:30300"
|
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")
|
var logger = ethlogger.NewLogger("SERV")
|
||||||
|
|
||||||
type Ethereum struct {
|
type Ethereum struct {
|
||||||
@ -38,7 +58,7 @@ type Ethereum struct {
|
|||||||
blockPool *BlockPool
|
blockPool *BlockPool
|
||||||
whisper *whisper.Whisper
|
whisper *whisper.Whisper
|
||||||
|
|
||||||
server *p2p.Server
|
net *p2p.Server
|
||||||
eventMux *event.TypeMux
|
eventMux *event.TypeMux
|
||||||
txSub event.Subscription
|
txSub event.Subscription
|
||||||
blockSub event.Subscription
|
blockSub event.Subscription
|
||||||
@ -47,6 +67,7 @@ type Ethereum struct {
|
|||||||
keyManager *crypto.KeyManager
|
keyManager *crypto.KeyManager
|
||||||
|
|
||||||
clientIdentity p2p.ClientIdentity
|
clientIdentity p2p.ClientIdentity
|
||||||
|
logger ethlogger.LogSystem
|
||||||
|
|
||||||
synclock sync.Mutex
|
synclock sync.Mutex
|
||||||
syncGroup sync.WaitGroup
|
syncGroup sync.WaitGroup
|
||||||
@ -54,7 +75,36 @@ type Ethereum struct {
|
|||||||
Mining bool
|
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)
|
saveProtocolVersion(db)
|
||||||
ethutil.Config.Db = db
|
ethutil.Config.Db = db
|
||||||
@ -64,9 +114,10 @@ func New(db ethutil.Database, identity p2p.ClientIdentity, keyManager *crypto.Ke
|
|||||||
quit: make(chan bool),
|
quit: make(chan bool),
|
||||||
db: db,
|
db: db,
|
||||||
keyManager: keyManager,
|
keyManager: keyManager,
|
||||||
clientIdentity: identity,
|
clientIdentity: clientId,
|
||||||
blacklist: p2p.NewBlacklist(),
|
blacklist: p2p.NewBlacklist(),
|
||||||
eventMux: &event.TypeMux{},
|
eventMux: &event.TypeMux{},
|
||||||
|
logger: logger,
|
||||||
}
|
}
|
||||||
|
|
||||||
eth.chainManager = core.NewChainManager(eth.EventMux())
|
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)
|
ethProto := EthProtocol(eth.txPool, eth.chainManager, eth.blockPool)
|
||||||
protocols := []p2p.Protocol{ethProto, eth.whisper.Protocol()}
|
protocols := []p2p.Protocol{ethProto, eth.whisper.Protocol()}
|
||||||
|
|
||||||
server := &p2p.Server{
|
nat, err := p2p.ParseNAT(config.NATType, config.PMPGateway)
|
||||||
Identity: identity,
|
if err != nil {
|
||||||
MaxPeers: maxPeers,
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
eth.net = &p2p.Server{
|
||||||
|
Identity: clientId,
|
||||||
|
MaxPeers: config.MaxPeers,
|
||||||
Protocols: protocols,
|
Protocols: protocols,
|
||||||
ListenAddr: ":" + port,
|
ListenAddr: ":" + config.Port,
|
||||||
Blacklist: eth.blacklist,
|
Blacklist: eth.blacklist,
|
||||||
NAT: nat,
|
NAT: nat,
|
||||||
}
|
}
|
||||||
|
|
||||||
eth.server = server
|
|
||||||
|
|
||||||
return eth, nil
|
return eth, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -103,6 +157,10 @@ func (s *Ethereum) KeyManager() *crypto.KeyManager {
|
|||||||
return s.keyManager
|
return s.keyManager
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (s *Ethereum) Logger() ethlogger.LogSystem {
|
||||||
|
return s.logger
|
||||||
|
}
|
||||||
|
|
||||||
func (s *Ethereum) ClientIdentity() p2p.ClientIdentity {
|
func (s *Ethereum) ClientIdentity() p2p.ClientIdentity {
|
||||||
return s.clientIdentity
|
return s.clientIdentity
|
||||||
}
|
}
|
||||||
@ -144,20 +202,20 @@ func (s *Ethereum) IsListening() bool {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (s *Ethereum) PeerCount() int {
|
func (s *Ethereum) PeerCount() int {
|
||||||
return s.server.PeerCount()
|
return s.net.PeerCount()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Ethereum) Peers() []*p2p.Peer {
|
func (s *Ethereum) Peers() []*p2p.Peer {
|
||||||
return s.server.Peers()
|
return s.net.Peers()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Ethereum) MaxPeers() int {
|
func (s *Ethereum) MaxPeers() int {
|
||||||
return s.server.MaxPeers
|
return s.net.MaxPeers
|
||||||
}
|
}
|
||||||
|
|
||||||
// Start the ethereum
|
// Start the ethereum
|
||||||
func (s *Ethereum) Start(seed bool) error {
|
func (s *Ethereum) Start(seed bool) error {
|
||||||
err := s.server.Start()
|
err := s.net.Start()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -191,7 +249,7 @@ func (self *Ethereum) SuggestPeer(addr string) error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
self.server.SuggestPeer(netaddr.IP, netaddr.Port, nil)
|
self.net.SuggestPeer(netaddr.IP, netaddr.Port, nil)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -227,7 +285,7 @@ func (self *Ethereum) txBroadcastLoop() {
|
|||||||
// automatically stops if unsubscribe
|
// automatically stops if unsubscribe
|
||||||
for obj := range self.txSub.Chan() {
|
for obj := range self.txSub.Chan() {
|
||||||
event := obj.(core.TxPreEvent)
|
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() {
|
for obj := range self.txSub.Chan() {
|
||||||
switch ev := obj.(type) {
|
switch ev := obj.(type) {
|
||||||
case core.NewMinedBlockEvent:
|
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"
|
"io/ioutil"
|
||||||
"os"
|
"os"
|
||||||
"os/user"
|
"os/user"
|
||||||
|
"path"
|
||||||
"strings"
|
"strings"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -58,3 +59,10 @@ func WriteFile(filePath string, content []byte) error {
|
|||||||
|
|
||||||
return nil
|
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
|
customIdentifier string
|
||||||
os string
|
os string
|
||||||
implementation 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{
|
clientIdentity := &SimpleClientIdentity{
|
||||||
clientIdentifier: clientIdentifier,
|
clientIdentifier: clientIdentifier,
|
||||||
version: version,
|
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 (
|
import (
|
||||||
"hash"
|
"hash"
|
@ -1,4 +1,4 @@
|
|||||||
package core
|
package dagger
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"math/big"
|
"math/big"
|
@ -30,6 +30,12 @@ func (self *Manifest) AddMessage(msg *Message) *Message {
|
|||||||
return msg
|
return msg
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (self *Manifest) SetHash(hash []byte) {
|
||||||
|
for _, message := range self.Messages {
|
||||||
|
message.Block = hash
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
type Messages []*Message
|
type Messages []*Message
|
||||||
type Message struct {
|
type Message struct {
|
||||||
To, From []byte
|
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) Coinbase() []byte { return self.coinbase }
|
||||||
func (self *Env) Time() int64 { return self.time }
|
func (self *Env) Time() int64 { return self.time }
|
||||||
func (self *Env) Difficulty() *big.Int { return self.difficulty }
|
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) State() *state.StateDB { return self.state }
|
||||||
func (self *Env) GasLimit() *big.Int { return self.gasLimit }
|
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) {
|
func (self *Env) AddLog(log state.Log) {
|
||||||
self.logs = append(self.logs, 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)
|
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)
|
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)
|
vmenv := NewEnvFromMap(statedb, env, tx)
|
||||||
|
st := core.NewStateTransition(vmenv, message, coinbase)
|
||||||
vmenv.origin = keyPair.Address()
|
vmenv.origin = keyPair.Address()
|
||||||
st.Env = vmenv
|
|
||||||
ret, err := st.TransitionState()
|
ret, err := st.TransitionState()
|
||||||
statedb.Update(vmenv.Gas)
|
statedb.Update(vmenv.Gas)
|
||||||
|
|
||||||
|
@ -5,7 +5,6 @@ import (
|
|||||||
"math/big"
|
"math/big"
|
||||||
|
|
||||||
"github.com/ethereum/go-ethereum/ethutil"
|
"github.com/ethereum/go-ethereum/ethutil"
|
||||||
"github.com/ethereum/go-ethereum/state"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
type ContextRef interface {
|
type ContextRef interface {
|
||||||
@ -18,7 +17,6 @@ type Context struct {
|
|||||||
caller ContextRef
|
caller ContextRef
|
||||||
object ContextRef
|
object ContextRef
|
||||||
Code []byte
|
Code []byte
|
||||||
message *state.Message
|
|
||||||
|
|
||||||
Gas, UsedGas, Price *big.Int
|
Gas, UsedGas, Price *big.Int
|
||||||
|
|
||||||
@ -26,8 +24,8 @@ type Context struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Create a new context for the given data items
|
// 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 {
|
func NewContext(caller ContextRef, object ContextRef, code []byte, gas, price *big.Int) *Context {
|
||||||
c := &Context{message: msg, caller: caller, object: object, Code: code, Args: nil}
|
c := &Context{caller: caller, object: object, Code: code, Args: nil}
|
||||||
|
|
||||||
// Gas should be a pointer so it can safely be reduced through the run
|
// Gas should be a pointer so it can safely be reduced through the run
|
||||||
// This pointer will be off the state transition
|
// This pointer will be off the state transition
|
||||||
@ -40,13 +38,13 @@ func NewContext(msg *state.Message, caller ContextRef, object ContextRef, code [
|
|||||||
return c
|
return c
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Context) GetOp(x uint64) OpCode {
|
func (c *Context) GetOp(n uint64) OpCode {
|
||||||
return OpCode(c.GetByte(x))
|
return OpCode(c.GetByte(n))
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Context) GetByte(x uint64) byte {
|
func (c *Context) GetByte(n uint64) byte {
|
||||||
if x < uint64(len(c.Code)) {
|
if n < uint64(len(c.Code)) {
|
||||||
return c.Code[x]
|
return c.Code[n]
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0
|
return 0
|
||||||
|
@ -14,11 +14,10 @@ type Environment interface {
|
|||||||
|
|
||||||
Origin() []byte
|
Origin() []byte
|
||||||
BlockNumber() *big.Int
|
BlockNumber() *big.Int
|
||||||
PrevHash() []byte
|
GetHash(n uint64) []byte
|
||||||
Coinbase() []byte
|
Coinbase() []byte
|
||||||
Time() int64
|
Time() int64
|
||||||
Difficulty() *big.Int
|
Difficulty() *big.Int
|
||||||
BlockHash() []byte
|
|
||||||
GasLimit() *big.Int
|
GasLimit() *big.Int
|
||||||
Transfer(from, to Account, amount *big.Int) error
|
Transfer(from, to Account, amount *big.Int) error
|
||||||
AddLog(state.Log)
|
AddLog(state.Log)
|
||||||
@ -31,11 +30,6 @@ type Environment interface {
|
|||||||
Create(me ContextRef, addr, data []byte, gas, price, value *big.Int) ([]byte, error, ContextRef)
|
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 {
|
type Account interface {
|
||||||
SubBalance(amount *big.Int)
|
SubBalance(amount *big.Int)
|
||||||
AddBalance(amount *big.Int)
|
AddBalance(amount *big.Int)
|
||||||
|
@ -59,7 +59,7 @@ const (
|
|||||||
const (
|
const (
|
||||||
|
|
||||||
// 0x40 range - block operations
|
// 0x40 range - block operations
|
||||||
PREVHASH OpCode = 0x40 + iota
|
BLOCKHASH OpCode = 0x40 + iota
|
||||||
COINBASE
|
COINBASE
|
||||||
TIMESTAMP
|
TIMESTAMP
|
||||||
NUMBER
|
NUMBER
|
||||||
@ -216,7 +216,7 @@ var opCodeToString = map[OpCode]string{
|
|||||||
GASPRICE: "TXGASPRICE",
|
GASPRICE: "TXGASPRICE",
|
||||||
|
|
||||||
// 0x40 range - block operations
|
// 0x40 range - block operations
|
||||||
PREVHASH: "PREVHASH",
|
BLOCKHASH: "BLOCKHASH",
|
||||||
COINBASE: "COINBASE",
|
COINBASE: "COINBASE",
|
||||||
TIMESTAMP: "TIMESTAMP",
|
TIMESTAMP: "TIMESTAMP",
|
||||||
NUMBER: "NUMBER",
|
NUMBER: "NUMBER",
|
||||||
|
@ -44,10 +44,10 @@ func (self *DebugVm) Run(me, caller ContextRef, code []byte, value, gas, price *
|
|||||||
To: me.Address(), From: caller.Address(),
|
To: me.Address(), From: caller.Address(),
|
||||||
Input: callData,
|
Input: callData,
|
||||||
Origin: self.env.Origin(),
|
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,
|
Value: value,
|
||||||
})
|
})
|
||||||
context := NewContext(msg, caller, me, code, gas, price)
|
context := NewContext(caller, me, code, gas, price)
|
||||||
|
|
||||||
if self.Recoverable {
|
if self.Recoverable {
|
||||||
// Recover from any require exception
|
// 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) {
|
jump = func(from uint64, to *big.Int) {
|
||||||
p := to.Uint64()
|
p := to.Uint64()
|
||||||
|
|
||||||
nop := OpCode(context.GetOp(p))
|
nop := context.GetOp(p)
|
||||||
if !destinations.Has(p) {
|
if !destinations.Has(p) {
|
||||||
panic(fmt.Sprintf("invalid jump destination (%v) %v", nop, 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)
|
self.Printf(" => %v", context.Price)
|
||||||
|
|
||||||
// 0x40 range
|
// 0x40 range
|
||||||
case PREVHASH:
|
case BLOCKHASH:
|
||||||
prevHash := self.env.PrevHash()
|
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", stack.Peek().Bytes())
|
||||||
|
|
||||||
self.Printf(" => 0x%x", prevHash)
|
|
||||||
case COINBASE:
|
case COINBASE:
|
||||||
coinbase := self.env.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()
|
val, loc := stack.Popn()
|
||||||
statedb.SetState(context.Address(), loc.Bytes(), val)
|
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())
|
self.Printf(" {0x%x : 0x%x}", loc.Bytes(), val.Bytes())
|
||||||
case JUMP:
|
case JUMP:
|
||||||
|
@ -87,7 +87,7 @@ func (self *XEth) ExecuteObject(object *Object, data []byte, value, gas, price *
|
|||||||
|
|
||||||
self.Vm.State = self.World().State().Copy()
|
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())
|
return vmenv.Call(initiator, object.Address(), data, gas.BigInt(), price.BigInt(), value.BigInt())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -10,6 +10,7 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
type VMEnv struct {
|
type VMEnv struct {
|
||||||
|
chain *core.ChainManager
|
||||||
state *state.StateDB
|
state *state.StateDB
|
||||||
block *types.Block
|
block *types.Block
|
||||||
value *big.Int
|
value *big.Int
|
||||||
@ -18,7 +19,7 @@ type VMEnv struct {
|
|||||||
depth int
|
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{
|
return &VMEnv{
|
||||||
state: state,
|
state: state,
|
||||||
block: block,
|
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) Coinbase() []byte { return self.block.Coinbase() }
|
||||||
func (self *VMEnv) Time() int64 { return self.block.Time() }
|
func (self *VMEnv) Time() int64 { return self.block.Time() }
|
||||||
func (self *VMEnv) Difficulty() *big.Int { return self.block.Difficulty() }
|
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) GasLimit() *big.Int { return self.block.GasLimit() }
|
||||||
func (self *VMEnv) Value() *big.Int { return self.value }
|
func (self *VMEnv) Value() *big.Int { return self.value }
|
||||||
func (self *VMEnv) State() *state.StateDB { return self.state }
|
func (self *VMEnv) State() *state.StateDB { return self.state }
|
||||||
func (self *VMEnv) Depth() int { return self.depth }
|
func (self *VMEnv) Depth() int { return self.depth }
|
||||||
func (self *VMEnv) SetDepth(i int) { self.depth = i }
|
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) {
|
func (self *VMEnv) AddLog(log state.Log) {
|
||||||
self.state.AddLog(log)
|
self.state.AddLog(log)
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user