Cleaning up polluted namespaces (#3143)

* Renaming ethcore_ to parity_

* Renaming files

* Renaming poluted EthSigning

* Tidy up the namespaces

* Renaming files to match new structure

* Splitting EthSigning into separate traits

* jsapi move ethcore.* -> parity.*

* Move jsonrpc parity definitions

* Update UI API calls for parity interfaces

* Move jsapi signer interfaces from personal to signer

* Update UI to use signer.* where applicable

* Updsate jsapi subscriptions for signer

* Fix dodgy merge.

* Update README.

* Fix some tests.

* Move parity-only personal.* to parity.*

* Update UI for personal -> parity API moves

* Update subscription APIs after personal -> parity move

* personal. generateAuthorizationToken -> parity. generateAuthorizationToken (UI)

* enode, dappsPort & signerPort (UI)

* Update subscription tests (accountsInfo)

* subscription update

* personal -> parity

* Additional error logging on method failures

* move postTransaction to parity

* Additional debug info with method failures

* Fix personal tests.

* Console wrning shows parameters, error object does not

* Include parity_ signing methods.

* Console log http transport info

* Fix failing tests

* Add RPC stubs for parity_accounts.

* Allow some secure built-in dapps

* Use parity_accounts in place of accountsInfo

* Improve error reporting

* Cleanup GHH error handling
This commit is contained in:
Tomasz Drwięga 2016-11-06 12:51:53 +01:00 committed by Gav Wood
parent 78f2d88182
commit 9c4979681c
101 changed files with 1899 additions and 1466 deletions

View File

@ -1,9 +1,12 @@
# [Parity](https://ethcore.io/parity.html) # [Parity](https://ethcore.io/parity.html)
### Fast, light, and robust Ethereum implementation ### Fast, light, and robust Ethereum implementation
[![Join the chat at https://gitter.im/ethcore/parity.js](https://badges.gitter.im/ethcore/parity.js.svg)](https://gitter.im/ethcore/parity.js?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) [![Build Status][travis-image]][travis-url] [![build status](https://gitlab.ethcore.io/Mirrors/ethcore-parity/badges/master/build.svg)](https://gitlab.ethcore.io/Mirrors/ethcore-parity/commits/master) [![Coverage Status][coveralls-image]][coveralls-url] [![GPLv3][license-image]][license-url]
[![Build Status][travis-image]][travis-url] [![build status](https://gitlab.ethcore.io/Mirrors/ethcore-parity/badges/master/build.svg)](https://gitlab.ethcore.io/Mirrors/ethcore-parity/commits/master) [![Coverage Status][coveralls-image]][coveralls-url] [![Join the chat at https://gitter.im/ethcore/parity][gitter-image]][gitter-url] [![GPLv3][license-image]][license-url] ### Join the chat!
Parity [![Join the chat at https://gitter.im/ethcore/parity][gitter-image]][gitter-url] and
parity.js [![Join the chat at https://gitter.im/ethcore/parity.js](https://badges.gitter.im/ethcore/parity.js.svg)](https://gitter.im/ethcore/parity.js?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
[Internal Documentation][doc-url] [Internal Documentation][doc-url]
@ -21,7 +24,7 @@ Be sure to check out [our wiki][wiki-url] for more information.
[doc-url]: https://ethcore.github.io/parity/ethcore/index.html [doc-url]: https://ethcore.github.io/parity/ethcore/index.html
[wiki-url]: https://github.com/ethcore/parity/wiki [wiki-url]: https://github.com/ethcore/parity/wiki
**Requires Rust version 1.12.0 to build** **Parity requires Rust version 1.12.0 to build**
---- ----
@ -31,12 +34,15 @@ Be sure to check out [our wiki][wiki-url] for more information.
Parity's goal is to be the fastest, lightest, and most secure Ethereum client. We are developing Parity using the sophisticated and Parity's goal is to be the fastest, lightest, and most secure Ethereum client. We are developing Parity using the sophisticated and
cutting-edge Rust programming language. Parity is licensed under the GPLv3, and can be used for all your Ethereum needs. cutting-edge Rust programming language. Parity is licensed under the GPLv3, and can be used for all your Ethereum needs.
By default, Parity will run a JSONRPC server on `127.0.0.1:8545`. This is fully configurable and supports a number Parity comes with a built-in wallet. To access [Parity Wallet](http://127.0.0.1:8080/) this simply go to http://127.0.0.1:8080/. It
of RPC APIs. includes various functionality allowing you to:
- create and manage your Ethereum accounts;
- manage your Ether and any Ethereum tokens;
- create and register your own tokens;
- and much more.
Parity also runs a server for running decentralized apps, or "Dapps", on `http://127.0.0.1:8080`. By default, Parity will also run a JSONRPC server on `127.0.0.1:8545`. This is fully configurable and supports a number
This includes a few useful Dapps, including Ethereum Wallet, Maker OTC, and a node status page. of RPC APIs.
In a near-future release, it will be easy to install Dapps and use them through this web interface.
If you run into an issue while using parity, feel free to file one in this repository If you run into an issue while using parity, feel free to file one in this repository
or hop on our [gitter chat room][gitter-url] to ask a question. We are glad to help! or hop on our [gitter chat room][gitter-url] to ask a question. We are glad to help!

View File

@ -135,10 +135,11 @@ APIs implement the calls as exposed in the [Ethcore JSON Ethereum RPC](https://g
- [ethapi.db](https://github.com/ethcore/ethereum-rpc-json/blob/master/interfaces.md#db) - [ethapi.db](https://github.com/ethcore/ethereum-rpc-json/blob/master/interfaces.md#db)
- [ethapi.eth](https://github.com/ethcore/ethereum-rpc-json/blob/master/interfaces.md#eth) - [ethapi.eth](https://github.com/ethcore/ethereum-rpc-json/blob/master/interfaces.md#eth)
- [ethapi.ethcore](https://github.com/ethcore/ethereum-rpc-json/blob/master/interfaces.md#ethcore) - [ethapi.parity](https://github.com/ethcore/ethereum-rpc-json/blob/master/interfaces.md#parity)
- [ethapi.net](https://github.com/ethcore/ethereum-rpc-json/blob/master/interfaces.md#net) - [ethapi.net](https://github.com/ethcore/ethereum-rpc-json/blob/master/interfaces.md#net)
- [ethapi.personal](https://github.com/ethcore/ethereum-rpc-json/blob/master/interfaces.md#personal) - [ethapi.personal](https://github.com/ethcore/ethereum-rpc-json/blob/master/interfaces.md#personal)
- [ethapi.shh](https://github.com/ethcore/ethereum-rpc-json/blob/master/interfaces.md#shh) - [ethapi.shh](https://github.com/ethcore/ethereum-rpc-json/blob/master/interfaces.md#shh)
- [ethapi.signer](https://github.com/ethcore/ethereum-rpc-json/blob/master/interfaces.md#signer)
- [ethapi.trace](https://github.com/ethcore/ethereum-rpc-json/blob/master/interfaces.md#trace) - [ethapi.trace](https://github.com/ethcore/ethereum-rpc-json/blob/master/interfaces.md#trace)
- [ethapi.web3](https://github.com/ethcore/ethereum-rpc-json/blob/master/interfaces.md#web3) - [ethapi.web3](https://github.com/ethcore/ethereum-rpc-json/blob/master/interfaces.md#web3)

View File

@ -17,7 +17,7 @@
import { Http, Ws } from './transport'; import { Http, Ws } from './transport';
import Contract from './contract'; import Contract from './contract';
import { Db, Eth, Ethcore, Net, Personal, Shh, Trace, Web3 } from './rpc'; import { Db, Eth, Parity, Net, Personal, Shh, Signer, Trace, Web3 } from './rpc';
import Subscriptions from './subscriptions'; import Subscriptions from './subscriptions';
import util from './util'; import util from './util';
import { isFunction } from './util/types'; import { isFunction } from './util/types';
@ -32,10 +32,11 @@ export default class Api {
this._db = new Db(transport); this._db = new Db(transport);
this._eth = new Eth(transport); this._eth = new Eth(transport);
this._ethcore = new Ethcore(transport);
this._net = new Net(transport); this._net = new Net(transport);
this._parity = new Parity(transport);
this._personal = new Personal(transport); this._personal = new Personal(transport);
this._shh = new Shh(transport); this._shh = new Shh(transport);
this._signer = new Signer(transport);
this._trace = new Trace(transport); this._trace = new Trace(transport);
this._web3 = new Web3(transport); this._web3 = new Web3(transport);
@ -50,8 +51,8 @@ export default class Api {
return this._eth; return this._eth;
} }
get ethcore () { get parity () {
return this._ethcore; return this._parity;
} }
get net () { get net () {
@ -66,6 +67,10 @@ export default class Api {
return this._shh; return this._shh;
} }
get signer () {
return this._signer;
}
get trace () { get trace () {
return this._trace; return this._trace;
} }

View File

@ -102,7 +102,7 @@ export default class Contract {
options.gas = gas.toFixed(0); options.gas = gas.toFixed(0);
setState({ state: 'postTransaction', gas }); setState({ state: 'postTransaction', gas });
return this._api.eth.postTransaction(this._encodeOptions(this.constructors[0], options, values)); return this._api.parity.postTransaction(this._encodeOptions(this.constructors[0], options, values));
}) })
.then((requestId) => { .then((requestId) => {
setState({ state: 'checkRequest', requestId }); setState({ state: 'checkRequest', requestId });
@ -166,7 +166,7 @@ export default class Contract {
} }
_pollCheckRequest = (requestId) => { _pollCheckRequest = (requestId) => {
return this._api.pollMethod('eth_checkRequest', requestId); return this._api.pollMethod('parity_checkRequest', requestId);
} }
_pollTransactionReceipt = (txhash, gas) => { _pollTransactionReceipt = (txhash, gas) => {
@ -208,7 +208,7 @@ export default class Contract {
if (!func.constant) { if (!func.constant) {
func.postTransaction = (options, values = []) => { func.postTransaction = (options, values = []) => {
return this._api.eth return this._api.parity
.postTransaction(this._encodeOptions(func, this._addOptionsTo(options), values)); .postTransaction(this._encodeOptions(func, this._addOptionsTo(options), values));
}; };

View File

@ -249,9 +249,9 @@ describe('api/contract/Contract', () => {
before(() => { before(() => {
scope = mockHttp([ scope = mockHttp([
{ method: 'eth_estimateGas', reply: { result: 1000 } }, { method: 'eth_estimateGas', reply: { result: 1000 } },
{ method: 'eth_postTransaction', reply: { result: '0x678' } }, { method: 'parity_postTransaction', reply: { result: '0x678' } },
{ method: 'eth_checkRequest', reply: { result: null } }, { method: 'parity_checkRequest', reply: { result: null } },
{ method: 'eth_checkRequest', reply: { result: '0x890' } }, { method: 'parity_checkRequest', reply: { result: '0x890' } },
{ method: 'eth_getTransactionReceipt', reply: { result: null } }, { method: 'eth_getTransactionReceipt', reply: { result: null } },
{ method: 'eth_getTransactionReceipt', reply: { result: RECEIPT_PEND } }, { method: 'eth_getTransactionReceipt', reply: { result: RECEIPT_PEND } },
{ method: 'eth_getTransactionReceipt', reply: { result: RECEIPT_DONE } }, { method: 'eth_getTransactionReceipt', reply: { result: RECEIPT_DONE } },
@ -266,7 +266,7 @@ describe('api/contract/Contract', () => {
}); });
it('passes the options through to postTransaction (incl. gas calculation)', () => { it('passes the options through to postTransaction (incl. gas calculation)', () => {
expect(scope.body.eth_postTransaction.params).to.deep.equal([ expect(scope.body.parity_postTransaction.params).to.deep.equal([
{ data: '0x123', gas: '0x4b0' } { data: '0x123', gas: '0x4b0' }
]); ]);
}); });
@ -280,8 +280,8 @@ describe('api/contract/Contract', () => {
it('fails when gasUsed == gas', () => { it('fails when gasUsed == gas', () => {
mockHttp([ mockHttp([
{ method: 'eth_estimateGas', reply: { result: 1000 } }, { method: 'eth_estimateGas', reply: { result: 1000 } },
{ method: 'eth_postTransaction', reply: { result: '0x678' } }, { method: 'parity_postTransaction', reply: { result: '0x678' } },
{ method: 'eth_checkRequest', reply: { result: '0x789' } }, { method: 'parity_checkRequest', reply: { result: '0x789' } },
{ method: 'eth_getTransactionReceipt', reply: { result: RECEIPT_EXCP } } { method: 'eth_getTransactionReceipt', reply: { result: RECEIPT_EXCP } }
]); ]);
@ -295,8 +295,8 @@ describe('api/contract/Contract', () => {
it('fails when no code was deployed', () => { it('fails when no code was deployed', () => {
mockHttp([ mockHttp([
{ method: 'eth_estimateGas', reply: { result: 1000 } }, { method: 'eth_estimateGas', reply: { result: 1000 } },
{ method: 'eth_postTransaction', reply: { result: '0x678' } }, { method: 'parity_postTransaction', reply: { result: '0x678' } },
{ method: 'eth_checkRequest', reply: { result: '0x789' } }, { method: 'parity_checkRequest', reply: { result: '0x789' } },
{ method: 'eth_getTransactionReceipt', reply: { result: RECEIPT_DONE } }, { method: 'eth_getTransactionReceipt', reply: { result: RECEIPT_DONE } },
{ method: 'eth_getCode', reply: { result: '0x' } } { method: 'eth_getCode', reply: { result: '0x' } }
]); ]);
@ -360,15 +360,15 @@ describe('api/contract/Contract', () => {
describe('postTransaction', () => { describe('postTransaction', () => {
beforeEach(() => { beforeEach(() => {
scope = mockHttp([{ method: 'eth_postTransaction', reply: { result: ['hashId'] } }]); scope = mockHttp([{ method: 'parity_postTransaction', reply: { result: ['hashId'] } }]);
}); });
it('encodes options and mades an eth_postTransaction call', () => { it('encodes options and mades an parity_postTransaction call', () => {
return func return func
.postTransaction({ someExtras: 'foo' }, VALUES) .postTransaction({ someExtras: 'foo' }, VALUES)
.then(() => { .then(() => {
expect(scope.isDone()).to.be.true; expect(scope.isDone()).to.be.true;
expect(scope.body.eth_postTransaction.params[0]).to.deep.equal({ expect(scope.body.parity_postTransaction.params[0]).to.deep.equal({
someExtras: 'foo', someExtras: 'foo',
to: ADDR, to: ADDR,
data: ENCODED data: ENCODED

View File

@ -39,11 +39,6 @@ export default class Eth {
.execute('eth_call', inOptions(options), inBlockNumber(blockNumber)); .execute('eth_call', inOptions(options), inBlockNumber(blockNumber));
} }
checkRequest (requestId) {
return this._transport
.execute('eth_checkRequest', inNumber16(requestId));
}
coinbase () { coinbase () {
return this._transport return this._transport
.execute('eth_coinbase') .execute('eth_coinbase')
@ -267,11 +262,6 @@ export default class Eth {
.execute('eth_pendingTransactions'); .execute('eth_pendingTransactions');
} }
postTransaction (options) {
return this._transport
.execute('eth_postTransaction', inOptions(options));
}
protocolVersion () { protocolVersion () {
return this._transport return this._transport
.execute('eth_protocolVersion'); .execute('eth_protocolVersion');

View File

@ -1,201 +0,0 @@
// Copyright 2015, 2016 Ethcore (UK) Ltd.
// This file is part of Parity.
// Parity is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
// Parity 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 General Public License for more details.
// You should have received a copy of the GNU General Public License
// along with Parity. If not, see <http://www.gnu.org/licenses/>.
import { inAddress, inData, inNumber16 } from '../../format/input';
import { outAddress, outHistogram, outNumber, outPeers } from '../../format/output';
export default class Ethcore {
constructor (transport) {
this._transport = transport;
}
acceptNonReservedPeers () {
return this._transport
.execute('ethcore_acceptNonReservedPeers');
}
addReservedPeer (encode) {
return this._transport
.execute('ethcore_addReservedPeer', encode);
}
dappsPort () {
return this._transport
.execute('ethcore_dappsPort')
.then(outNumber);
}
defaultExtraData () {
return this._transport
.execute('ethcore_defaultExtraData');
}
devLogs () {
return this._transport
.execute('ethcore_devLogs');
}
devLogsLevels () {
return this._transport
.execute('ethcore_devLogsLevels');
}
dropNonReservedPeers () {
return this._transport
.execute('ethcore_dropNonReservedPeers');
}
enode () {
return this._transport
.execute('ethcore_enode');
}
extraData () {
return this._transport
.execute('ethcore_extraData');
}
gasFloorTarget () {
return this._transport
.execute('ethcore_gasFloorTarget')
.then(outNumber);
}
gasPriceHistogram () {
return this._transport
.execute('ethcore_gasPriceHistogram')
.then(outHistogram);
}
generateSecretPhrase () {
return this._transport
.execute('ethcore_generateSecretPhrase');
}
hashContent (url) {
return this._transport
.execute('ethcore_hashContent', url);
}
minGasPrice () {
return this._transport
.execute('ethcore_minGasPrice')
.then(outNumber);
}
mode () {
return this._transport
.execute('ethcore_mode');
}
netChain () {
return this._transport
.execute('ethcore_netChain');
}
netPeers () {
return this._transport
.execute('ethcore_netPeers')
.then(outPeers);
}
netMaxPeers () {
return this._transport
.execute('ethcore_netMaxPeers')
.then(outNumber);
}
netPort () {
return this._transport
.execute('ethcore_netPort')
.then(outNumber);
}
nodeName () {
return this._transport
.execute('ethcore_nodeName');
}
phraseToAddress (phrase) {
return this._transport
.execute('ethcore_phraseToAddress', phrase)
.then(outAddress);
}
registryAddress () {
return this._transport
.execute('ethcore_registryAddress')
.then(outAddress);
}
removeReservedPeer (encode) {
return this._transport
.execute('ethcore_removeReservedPeer', encode);
}
rpcSettings () {
return this._transport
.execute('ethcore_rpcSettings');
}
setAuthor (address) {
return this._transport
.execute('ethcore_setAuthor', inAddress(address));
}
setExtraData (data) {
return this._transport
.execute('ethcore_setExtraData', inData(data));
}
setGasFloorTarget (quantity) {
return this._transport
.execute('ethcore_setGasFloorTarget', inNumber16(quantity));
}
setMinGasPrice (quantity) {
return this._transport
.execute('ethcore_setMinGasPrice', inNumber16(quantity));
}
setMode (mode) {
return this._transport
.execute('ethcore_setMode', mode);
}
setTransactionsLimit (quantity) {
return this._transport
.execute('ethcore_setTransactionsLimit', inNumber16(quantity));
}
signerPort () {
return this._transport
.execute('ethcore_signerPort')
.then(outNumber);
}
transactionsLimit () {
return this._transport
.execute('ethcore_transactionsLimit')
.then(outNumber);
}
unsignedTransactionsCount () {
return this._transport
.execute('ethcore_unsignedTransactionsCount')
.then(outNumber);
}
}

View File

@ -16,9 +16,10 @@
export Db from './db'; export Db from './db';
export Eth from './eth'; export Eth from './eth';
export Ethcore from './ethcore'; export Parity from './parity';
export Net from './net'; export Net from './net';
export Personal from './personal'; export Personal from './personal';
export Shh from './shh'; export Shh from './shh';
export Signer from './signer';
export Trace from './trace'; export Trace from './trace';
export Web3 from './web3'; export Web3 from './web3';

View File

@ -14,4 +14,4 @@
// You should have received a copy of the GNU General Public License // You should have received a copy of the GNU General Public License
// along with Parity. If not, see <http://www.gnu.org/licenses/>. // along with Parity. If not, see <http://www.gnu.org/licenses/>.
export default from './ethcore'; export default from './parity';

View File

@ -16,12 +16,12 @@
import { createHttpApi } from '../../../../test/e2e/ethapi'; import { createHttpApi } from '../../../../test/e2e/ethapi';
describe('ethapi.ethcore', () => { describe('ethapi.parity', () => {
const ethapi = createHttpApi(); const ethapi = createHttpApi();
describe('gasFloorTarget', () => { describe('gasFloorTarget', () => {
it('returns and translates the target', () => { it('returns and translates the target', () => {
return ethapi.ethcore.gasFloorTarget().then((value) => { return ethapi.parity.gasFloorTarget().then((value) => {
expect(value.gt(0)).to.be.true; expect(value.gt(0)).to.be.true;
}); });
}); });
@ -29,7 +29,7 @@ describe('ethapi.ethcore', () => {
describe('gasPriceHistogram', () => { describe('gasPriceHistogram', () => {
it('returns and translates the target', () => { it('returns and translates the target', () => {
return ethapi.ethcore.gasPriceHistogram().then((result) => { return ethapi.parity.gasPriceHistogram().then((result) => {
expect(Object.keys(result)).to.deep.equal(['bucketBounds', 'counts']); expect(Object.keys(result)).to.deep.equal(['bucketBounds', 'counts']);
expect(result.bucketBounds.length > 0).to.be.true; expect(result.bucketBounds.length > 0).to.be.true;
expect(result.counts.length > 0).to.be.true; expect(result.counts.length > 0).to.be.true;
@ -39,7 +39,7 @@ describe('ethapi.ethcore', () => {
describe('netChain', () => { describe('netChain', () => {
it('returns and the chain', () => { it('returns and the chain', () => {
return ethapi.ethcore.netChain().then((value) => { return ethapi.parity.netChain().then((value) => {
expect(value).to.equal('morden'); expect(value).to.equal('morden');
}); });
}); });
@ -47,7 +47,7 @@ describe('ethapi.ethcore', () => {
describe('netPort', () => { describe('netPort', () => {
it('returns and translates the port', () => { it('returns and translates the port', () => {
return ethapi.ethcore.netPort().then((value) => { return ethapi.parity.netPort().then((value) => {
expect(value.gt(0)).to.be.true; expect(value.gt(0)).to.be.true;
}); });
}); });
@ -55,7 +55,7 @@ describe('ethapi.ethcore', () => {
describe('transactionsLimit', () => { describe('transactionsLimit', () => {
it('returns and translates the limit', () => { it('returns and translates the limit', () => {
return ethapi.ethcore.transactionsLimit().then((value) => { return ethapi.parity.transactionsLimit().then((value) => {
expect(value.gt(0)).to.be.true; expect(value.gt(0)).to.be.true;
}); });
}); });
@ -63,7 +63,7 @@ describe('ethapi.ethcore', () => {
describe('rpcSettings', () => { describe('rpcSettings', () => {
it('returns and translates the settings', () => { it('returns and translates the settings', () => {
return ethapi.ethcore.rpcSettings().then((value) => { return ethapi.parity.rpcSettings().then((value) => {
expect(value).to.be.ok; expect(value).to.be.ok;
}); });
}); });

View File

@ -0,0 +1,273 @@
// Copyright 2015, 2016 Ethcore (UK) Ltd.
// This file is part of Parity.
// Parity is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
// Parity 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 General Public License for more details.
// You should have received a copy of the GNU General Public License
// along with Parity. If not, see <http://www.gnu.org/licenses/>.
import { inAddress, inData, inHex, inNumber16, inOptions } from '../../format/input';
import { outAccountInfo, outAddress, outHistogram, outNumber, outPeers } from '../../format/output';
export default class Parity {
constructor (transport) {
this._transport = transport;
}
acceptNonReservedPeers () {
return this._transport
.execute('parity_acceptNonReservedPeers');
}
accounts () {
return this._transport
.execute('parity_accounts')
.then(outAccountInfo);
}
accountsInfo () {
return this._transport
.execute('parity_accountsInfo')
.then(outAccountInfo);
}
addReservedPeer (encode) {
return this._transport
.execute('parity_addReservedPeer', encode);
}
changePassword (account, password, newPassword) {
return this._transport
.execute('parity_changePassword', inAddress(account), password, newPassword);
}
checkRequest (requestId) {
return this._transport
.execute('parity_checkRequest', inNumber16(requestId));
}
dappsPort () {
return this._transport
.execute('parity_dappsPort')
.then(outNumber);
}
defaultExtraData () {
return this._transport
.execute('parity_defaultExtraData');
}
devLogs () {
return this._transport
.execute('parity_devLogs');
}
devLogsLevels () {
return this._transport
.execute('parity_devLogsLevels');
}
dropNonReservedPeers () {
return this._transport
.execute('parity_dropNonReservedPeers');
}
enode () {
return this._transport
.execute('parity_enode');
}
extraData () {
return this._transport
.execute('parity_extraData');
}
gasFloorTarget () {
return this._transport
.execute('parity_gasFloorTarget')
.then(outNumber);
}
gasPriceHistogram () {
return this._transport
.execute('parity_gasPriceHistogram')
.then(outHistogram);
}
generateSecretPhrase () {
return this._transport
.execute('parity_generateSecretPhrase');
}
hashContent (url) {
return this._transport
.execute('parity_hashContent', url);
}
listGethAccounts () {
return this._transport
.execute('parity_listGethAccounts')
.then((accounts) => (accounts || []).map(outAddress));
}
importGethAccounts (accounts) {
return this._transport
.execute('parity_importGethAccounts', (accounts || []).map(inAddress))
.then((accounts) => (accounts || []).map(outAddress));
}
minGasPrice () {
return this._transport
.execute('parity_minGasPrice')
.then(outNumber);
}
mode () {
return this._transport
.execute('parity_mode');
}
netChain () {
return this._transport
.execute('parity_netChain');
}
netPeers () {
return this._transport
.execute('parity_netPeers')
.then(outPeers);
}
netMaxPeers () {
return this._transport
.execute('parity_netMaxPeers')
.then(outNumber);
}
netPort () {
return this._transport
.execute('parity_netPort')
.then(outNumber);
}
newAccountFromPhrase (phrase, password) {
return this._transport
.execute('parity_newAccountFromPhrase', phrase, password)
.then(outAddress);
}
newAccountFromSecret (secret, password) {
return this._transport
.execute('parity_newAccountFromSecret', inHex(secret), password)
.then(outAddress);
}
newAccountFromWallet (json, password) {
return this._transport
.execute('parity_newAccountFromWallet', json, password)
.then(outAddress);
}
nodeName () {
return this._transport
.execute('parity_nodeName');
}
phraseToAddress (phrase) {
return this._transport
.execute('parity_phraseToAddress', phrase)
.then(outAddress);
}
postTransaction (options) {
return this._transport
.execute('parity_postTransaction', inOptions(options));
}
registryAddress () {
return this._transport
.execute('parity_registryAddress')
.then(outAddress);
}
removeReservedPeer (encode) {
return this._transport
.execute('parity_removeReservedPeer', encode);
}
rpcSettings () {
return this._transport
.execute('parity_rpcSettings');
}
setAccountName (address, name) {
return this._transport
.execute('parity_setAccountName', inAddress(address), name);
}
setAccountMeta (address, meta) {
return this._transport
.execute('parity_setAccountMeta', inAddress(address), JSON.stringify(meta));
}
setAuthor (address) {
return this._transport
.execute('parity_setAuthor', inAddress(address));
}
setExtraData (data) {
return this._transport
.execute('parity_setExtraData', inData(data));
}
setGasFloorTarget (quantity) {
return this._transport
.execute('parity_setGasFloorTarget', inNumber16(quantity));
}
setMinGasPrice (quantity) {
return this._transport
.execute('parity_setMinGasPrice', inNumber16(quantity));
}
setMode (mode) {
return this._transport
.execute('parity_setMode', mode);
}
setTransactionsLimit (quantity) {
return this._transport
.execute('parity_setTransactionsLimit', inNumber16(quantity));
}
signerPort () {
return this._transport
.execute('parity_signerPort')
.then(outNumber);
}
testPassword (account, password) {
return this._transport
.execute('parity_testPassword', inAddress(account), password);
}
transactionsLimit () {
return this._transport
.execute('parity_transactionsLimit')
.then(outNumber);
}
unsignedTransactionsCount () {
return this._transport
.execute('parity_unsignedTransactionsCount')
.then(outNumber);
}
}

View File

@ -18,14 +18,36 @@ import { TEST_HTTP_URL, mockHttp } from '../../../../test/mockRpc';
import { isBigNumber } from '../../../../test/types'; import { isBigNumber } from '../../../../test/types';
import Http from '../../transport/http'; import Http from '../../transport/http';
import Ethcore from './ethcore'; import Parity from './parity';
const instance = new Ethcore(new Http(TEST_HTTP_URL)); const instance = new Parity(new Http(TEST_HTTP_URL));
describe('api/rpc/parity', () => {
describe('accountsInfo', () => {
it('retrieves the available account info', () => {
mockHttp([{ method: 'parity_accountsInfo', reply: {
result: {
'0x63cf90d3f0410092fc0fca41846f596223979195': {
name: 'name', uuid: 'uuid', meta: '{"data":"data"}'
}
}
} }]);
return instance.accountsInfo().then((result) => {
expect(result).to.deep.equal({
'0x63Cf90D3f0410092FC0fca41846f596223979195': {
name: 'name', uuid: 'uuid', meta: {
data: 'data'
}
}
});
});
});
});
describe('api/rpc/Ethcore', () => {
describe('gasFloorTarget', () => { describe('gasFloorTarget', () => {
it('returns the gasfloor, formatted', () => { it('returns the gasfloor, formatted', () => {
mockHttp([{ method: 'ethcore_gasFloorTarget', reply: { result: '0x123456' } }]); mockHttp([{ method: 'parity_gasFloorTarget', reply: { result: '0x123456' } }]);
return instance.gasFloorTarget().then((count) => { return instance.gasFloorTarget().then((count) => {
expect(isBigNumber(count)).to.be.true; expect(isBigNumber(count)).to.be.true;
@ -36,7 +58,7 @@ describe('api/rpc/Ethcore', () => {
describe('minGasPrice', () => { describe('minGasPrice', () => {
it('returns the min gasprice, formatted', () => { it('returns the min gasprice, formatted', () => {
mockHttp([{ method: 'ethcore_minGasPrice', reply: { result: '0x123456' } }]); mockHttp([{ method: 'parity_minGasPrice', reply: { result: '0x123456' } }]);
return instance.minGasPrice().then((count) => { return instance.minGasPrice().then((count) => {
expect(isBigNumber(count)).to.be.true; expect(isBigNumber(count)).to.be.true;
@ -47,7 +69,7 @@ describe('api/rpc/Ethcore', () => {
describe('netMaxPeers', () => { describe('netMaxPeers', () => {
it('returns the max peers, formatted', () => { it('returns the max peers, formatted', () => {
mockHttp([{ method: 'ethcore_netMaxPeers', reply: { result: 25 } }]); mockHttp([{ method: 'parity_netMaxPeers', reply: { result: 25 } }]);
return instance.netMaxPeers().then((count) => { return instance.netMaxPeers().then((count) => {
expect(isBigNumber(count)).to.be.true; expect(isBigNumber(count)).to.be.true;
@ -58,7 +80,7 @@ describe('api/rpc/Ethcore', () => {
describe('newPeers', () => { describe('newPeers', () => {
it('returns the peer structure, formatted', () => { it('returns the peer structure, formatted', () => {
mockHttp([{ method: 'ethcore_netPeers', reply: { result: { active: 123, connected: 456, max: 789 } } }]); mockHttp([{ method: 'parity_netPeers', reply: { result: { active: 123, connected: 456, max: 789 } } }]);
return instance.netPeers().then((peers) => { return instance.netPeers().then((peers) => {
expect(peers.active.eq(123)).to.be.true; expect(peers.active.eq(123)).to.be.true;
@ -70,7 +92,7 @@ describe('api/rpc/Ethcore', () => {
describe('netPort', () => { describe('netPort', () => {
it('returns the connected port, formatted', () => { it('returns the connected port, formatted', () => {
mockHttp([{ method: 'ethcore_netPort', reply: { result: 33030 } }]); mockHttp([{ method: 'parity_netPort', reply: { result: 33030 } }]);
return instance.netPort().then((count) => { return instance.netPort().then((count) => {
expect(isBigNumber(count)).to.be.true; expect(isBigNumber(count)).to.be.true;
@ -81,7 +103,7 @@ describe('api/rpc/Ethcore', () => {
describe('transactionsLimit', () => { describe('transactionsLimit', () => {
it('returns the tx limit, formatted', () => { it('returns the tx limit, formatted', () => {
mockHttp([{ method: 'ethcore_transactionsLimit', reply: { result: 1024 } }]); mockHttp([{ method: 'parity_transactionsLimit', reply: { result: 1024 } }]);
return instance.transactionsLimit().then((count) => { return instance.transactionsLimit().then((count) => {
expect(isBigNumber(count)).to.be.true; expect(isBigNumber(count)).to.be.true;

View File

@ -14,113 +14,31 @@
// You should have received a copy of the GNU General Public License // You should have received a copy of the GNU General Public License
// along with Parity. If not, see <http://www.gnu.org/licenses/>. // along with Parity. If not, see <http://www.gnu.org/licenses/>.
import { inAddress, inHex, inNumber10, inNumber16, inOptions } from '../../format/input'; import { inAddress, inNumber10, inOptions } from '../../format/input';
import { outAccountInfo, outAddress, outSignerRequest } from '../../format/output'; import { outAddress } from '../../format/output';
export default class Personal { export default class Personal {
constructor (transport) { constructor (transport) {
this._transport = transport; this._transport = transport;
} }
accountsInfo () {
return this._transport
.execute('personal_accountsInfo')
.then(outAccountInfo);
}
confirmRequest (requestId, options, password) {
return this._transport
.execute('personal_confirmRequest', inNumber16(requestId), options, password);
}
changePassword (account, password, newPassword) {
return this._transport
.execute('personal_changePassword', inAddress(account), password, newPassword);
}
generateAuthorizationToken () {
return this._transport
.execute('personal_generateAuthorizationToken');
}
listAccounts () { listAccounts () {
return this._transport return this._transport
.execute('personal_listAccounts') .execute('personal_listAccounts')
.then((accounts) => (accounts || []).map(outAddress)); .then((accounts) => (accounts || []).map(outAddress));
} }
listGethAccounts () {
return this._transport
.execute('personal_listGethAccounts')
.then((accounts) => (accounts || []).map(outAddress));
}
importGethAccounts (accounts) {
return this._transport
.execute('personal_importGethAccounts', (accounts || []).map(inAddress))
.then((accounts) => (accounts || []).map(outAddress));
}
newAccount (password) { newAccount (password) {
return this._transport return this._transport
.execute('personal_newAccount', password) .execute('personal_newAccount', password)
.then(outAddress); .then(outAddress);
} }
newAccountFromPhrase (phrase, password) {
return this._transport
.execute('personal_newAccountFromPhrase', phrase, password)
.then(outAddress);
}
newAccountFromSecret (secret, password) {
return this._transport
.execute('personal_newAccountFromSecret', inHex(secret), password)
.then(outAddress);
}
newAccountFromWallet (json, password) {
return this._transport
.execute('personal_newAccountFromWallet', json, password)
.then(outAddress);
}
rejectRequest (requestId) {
return this._transport
.execute('personal_rejectRequest', inNumber16(requestId));
}
requestsToConfirm () {
return this._transport
.execute('personal_requestsToConfirm')
.then((requests) => (requests || []).map(outSignerRequest));
}
setAccountName (address, name) {
return this._transport
.execute('personal_setAccountName', inAddress(address), name);
}
setAccountMeta (address, meta) {
return this._transport
.execute('personal_setAccountMeta', inAddress(address), JSON.stringify(meta));
}
signAndSendTransaction (options, password) { signAndSendTransaction (options, password) {
return this._transport return this._transport
.execute('personal_signAndSendTransaction', inOptions(options), password); .execute('personal_signAndSendTransaction', inOptions(options), password);
} }
signerEnabled () {
return this._transport
.execute('personal_signerEnabled');
}
testPassword (account, password) {
return this._transport
.execute('personal_testPassword', inAddress(account), password);
}
unlockAccount (account, password, duration = 1) { unlockAccount (account, password, duration = 1) {
return this._transport return this._transport
.execute('personal_unlockAccount', inAddress(account), password, inNumber10(duration)); .execute('personal_unlockAccount', inAddress(account), password, inNumber10(duration));

View File

@ -26,28 +26,6 @@ describe('rpc/Personal', () => {
const checksum = '0x63Cf90D3f0410092FC0fca41846f596223979195'; const checksum = '0x63Cf90D3f0410092FC0fca41846f596223979195';
let scope; let scope;
describe('accountsInfo', () => {
it('retrieves the available account info', () => {
scope = mockHttp([{ method: 'personal_accountsInfo', reply: {
result: {
'0x63cf90d3f0410092fc0fca41846f596223979195': {
name: 'name', uuid: 'uuid', meta: '{"data":"data"}'
}
}
} }]);
return instance.accountsInfo().then((result) => {
expect(result).to.deep.equal({
'0x63Cf90D3f0410092FC0fca41846f596223979195': {
name: 'name', uuid: 'uuid', meta: {
data: 'data'
}
}
});
});
});
});
describe('listAccounts', () => { describe('listAccounts', () => {
it('retrieves a list of available accounts', () => { it('retrieves a list of available accounts', () => {
scope = mockHttp([{ method: 'personal_listAccounts', reply: { result: [account] } }]); scope = mockHttp([{ method: 'personal_listAccounts', reply: { result: [account] } }]);

View File

@ -0,0 +1,17 @@
// Copyright 2015, 2016 Ethcore (UK) Ltd.
// This file is part of Parity.
// Parity is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
// Parity 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 General Public License for more details.
// You should have received a copy of the GNU General Public License
// along with Parity. If not, see <http://www.gnu.org/licenses/>.
export default from './signer';

View File

@ -0,0 +1,50 @@
// Copyright 2015, 2016 Ethcore (UK) Ltd.
// This file is part of Parity.
// Parity is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
// Parity 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 General Public License for more details.
// You should have received a copy of the GNU General Public License
// along with Parity. If not, see <http://www.gnu.org/licenses/>.
import { inNumber16 } from '../../format/input';
import { outSignerRequest } from '../../format/output';
export default class Signer {
constructor (transport) {
this._transport = transport;
}
confirmRequest (requestId, options, password) {
return this._transport
.execute('signer_confirmRequest', inNumber16(requestId), options, password);
}
generateAuthorizationToken () {
return this._transport
.execute('signer_generateAuthorizationToken');
}
rejectRequest (requestId) {
return this._transport
.execute('signer_rejectRequest', inNumber16(requestId));
}
requestsToConfirm () {
return this._transport
.execute('signer_requestsToConfirm')
.then((requests) => (requests || []).map(outSignerRequest));
}
signerEnabled () {
return this._transport
.execute('signer_signerEnabled');
}
}

View File

@ -24,9 +24,9 @@ import Signer from './signer';
const events = { const events = {
'logging': { module: 'logging' }, 'logging': { module: 'logging' },
'eth_blockNumber': { module: 'eth' }, 'eth_blockNumber': { module: 'eth' },
'personal_accountsInfo': { module: 'personal' }, 'parity_accountsInfo': { module: 'personal' },
'personal_listAccounts': { module: 'personal' }, 'eth_accounts': { module: 'personal' },
'personal_requestsToConfirm': { module: 'signer' } 'signer_requestsToConfirm': { module: 'signer' }
}; };
export default class Manager { export default class Manager {

View File

@ -37,18 +37,18 @@ export default class Personal {
} }
_listAccounts = () => { _listAccounts = () => {
return this._api.personal return this._api.eth
.listAccounts() .accounts()
.then((accounts) => { .then((accounts) => {
this._updateSubscriptions('personal_listAccounts', null, accounts); this._updateSubscriptions('eth_accounts', null, accounts);
}); });
} }
_accountsInfo = () => { _accountsInfo = () => {
return this._api.personal return this._api.parity
.accountsInfo() .accountsInfo()
.then((info) => { .then((info) => {
this._updateSubscriptions('personal_accountsInfo', null, info); this._updateSubscriptions('parity_accountsInfo', null, info);
}); });
} }
@ -59,16 +59,16 @@ export default class Personal {
} }
switch (data.method) { switch (data.method) {
case 'personal_importGethAccounts': case 'parity_importGethAccounts':
case 'personal_newAccount': case 'personal_newAccount':
case 'personal_newAccountFromPhrase': case 'parity_newAccountFromPhrase':
case 'personal_newAccountFromWallet': case 'parity_newAccountFromWallet':
this._listAccounts(); this._listAccounts();
this._accountsInfo(); this._accountsInfo();
return; return;
case 'personal_setAccountName': case 'parity_setAccountName':
case 'personal_setAccountMeta': case 'parity_setAccountMeta':
this._accountsInfo(); this._accountsInfo();
return; return;
} }

View File

@ -34,14 +34,15 @@ function stubApi (accounts, info) {
return { return {
_calls, _calls,
personal: { parity: {
accountsInfo: () => { accountsInfo: () => {
const stub = sinon.stub().resolves(info || TEST_INFO)(); const stub = sinon.stub().resolves(info || TEST_INFO)();
_calls.accountsInfo.push(stub); _calls.accountsInfo.push(stub);
return stub; return stub;
}, }
},
listAccounts: () => { eth: {
accounts: () => {
const stub = sinon.stub().resolves(accounts || TEST_LIST)(); const stub = sinon.stub().resolves(accounts || TEST_LIST)();
_calls.listAccounts.push(stub); _calls.listAccounts.push(stub);
return stub; return stub;
@ -85,17 +86,17 @@ describe('api/subscriptions/personal', () => {
expect(personal.isStarted).to.be.true; expect(personal.isStarted).to.be.true;
}); });
it('calls personal_accountsInfo', () => { it('calls parity_accountsInfo', () => {
expect(api._calls.accountsInfo.length).to.be.ok; expect(api._calls.accountsInfo.length).to.be.ok;
}); });
it('calls personal_listAccounts', () => { it('calls eth_accounts', () => {
expect(api._calls.listAccounts.length).to.be.ok; expect(api._calls.listAccounts.length).to.be.ok;
}); });
it('updates subscribers', () => { it('updates subscribers', () => {
expect(cb.firstCall).to.have.been.calledWith('personal_listAccounts', null, TEST_LIST); expect(cb.firstCall).to.have.been.calledWith('eth_accounts', null, TEST_LIST);
expect(cb.secondCall).to.have.been.calledWith('personal_accountsInfo', null, TEST_INFO); expect(cb.secondCall).to.have.been.calledWith('parity_accountsInfo', null, TEST_INFO);
}); });
}); });

View File

@ -49,10 +49,10 @@ export default class Signer {
return; return;
} }
return this._api.personal return this._api.signer
.requestsToConfirm() .requestsToConfirm()
.then((requests) => { .then((requests) => {
this._updateSubscriptions('personal_requestsToConfirm', null, requests); this._updateSubscriptions('signer_requestsToConfirm', null, requests);
nextTimeout(); nextTimeout();
}) })
.catch(nextTimeout); .catch(nextTimeout);
@ -65,7 +65,7 @@ export default class Signer {
} }
switch (data.method) { switch (data.method) {
case 'eth_postTransaction': case 'parity_postTransaction':
case 'eth_sendTranasction': case 'eth_sendTranasction':
case 'eth_sendRawTransaction': case 'eth_sendRawTransaction':
this._listRequests(false); this._listRequests(false);

View File

@ -56,6 +56,8 @@ export default class Http extends JsonRpcBase {
if (response.status !== 200) { if (response.status !== 200) {
this._connected = false; this._connected = false;
this.error(JSON.stringify({ status: response.status, statusText: response.statusText })); this.error(JSON.stringify({ status: response.status, statusText: response.statusText }));
console.error(`${method}(${JSON.stringify(params)}): ${response.status}: ${response.statusText}`);
throw new Error(`${response.status}: ${response.statusText}`); throw new Error(`${response.status}: ${response.statusText}`);
} }
@ -66,7 +68,9 @@ export default class Http extends JsonRpcBase {
if (response.error) { if (response.error) {
this.error(JSON.stringify(response)); this.error(JSON.stringify(response));
throw new Error(`${response.error.code}: ${response.error.message}`); console.error(`${method}(${JSON.stringify(params)}): ${response.error.code}: ${response.error.message}`);
throw new Error(`${method}: ${response.error.code}: ${response.error.message}`);
} }
this.log(JSON.stringify(response)); this.log(JSON.stringify(response));

View File

@ -107,7 +107,9 @@ export default class Ws extends JsonRpcBase {
if (result.error) { if (result.error) {
this.error(event.data); this.error(event.data);
reject(new Error(`${result.error.code}: ${result.error.message}`)); console.error(`${method}(${JSON.stringify(params)}): ${result.error.code}: ${result.error.message}`);
reject(new Error(`${method}: ${result.error.code}: ${result.error.message}`));
delete this._messages[result.id]; delete this._messages[result.id];
return; return;
} }

View File

@ -32,7 +32,7 @@ export default class Registry {
return; return;
} }
this._api.ethcore this._api.parity
.registryAddress() .registryAddress()
.then((address) => { .then((address) => {
this._instance = this._api.newContract(abis.registry, address).instance; this._instance = this._api.newContract(abis.registry, address).instance;

View File

@ -83,7 +83,7 @@ export default class Application extends Component {
Promise Promise
.all([ .all([
attachInstances(), attachInstances(),
api.personal.accountsInfo() api.parity.accounts()
]) ])
.then(([{ managerInstance, registryInstance, tokenregInstance }, accountsInfo]) => { .then(([{ managerInstance, registryInstance, tokenregInstance }, accountsInfo]) => {
accountsInfo = accountsInfo || {}; accountsInfo = accountsInfo || {};

View File

@ -296,7 +296,7 @@ export default class Deployment extends Component {
.then((signerRequestId) => { .then((signerRequestId) => {
this.setState({ signerRequestId, deployState: 'Transaction posted, Waiting for transaction authorization' }); this.setState({ signerRequestId, deployState: 'Transaction posted, Waiting for transaction authorization' });
return api.pollMethod('eth_checkRequest', signerRequestId); return api.pollMethod('parity_checkRequest', signerRequestId);
}) })
.then((txHash) => { .then((txHash) => {
this.setState({ txHash, deployState: 'Transaction authorized, Waiting for network confirmations' }); this.setState({ txHash, deployState: 'Transaction authorized, Waiting for network confirmations' });

View File

@ -279,7 +279,7 @@ export default class Send extends Component {
.then((signerRequestId) => { .then((signerRequestId) => {
this.setState({ signerRequestId, sendState: 'Transaction posted, Waiting for transaction authorization' }); this.setState({ signerRequestId, sendState: 'Transaction posted, Waiting for transaction authorization' });
return api.pollMethod('eth_checkRequest', signerRequestId); return api.pollMethod('parity_checkRequest', signerRequestId);
}) })
.then((txHash) => { .then((txHash) => {
this.setState({ txHash, sendState: 'Transaction authorized, Waiting for network confirmations' }); this.setState({ txHash, sendState: 'Transaction authorized, Waiting for network confirmations' });

View File

@ -100,8 +100,8 @@ export function attachInstances () {
return Promise return Promise
.all([ .all([
api.ethcore.registryAddress(), api.parity.registryAddress(),
api.ethcore.netChain() api.parity.netChain()
]) ])
.then(([registryAddress, netChain]) => { .then(([registryAddress, netChain]) => {
const registry = api.newContract(abis.registry, registryAddress).instance; const registry = api.newContract(abis.registry, registryAddress).instance;

View File

@ -11,7 +11,6 @@
<div id="container"></div> <div id="container"></div>
<script src="vendor.js"></script> <script src="vendor.js"></script>
<script src="commons.js"></script> <script src="commons.js"></script>
<script src="/parity-utils/parity.js"></script>
<script src="githubhint.js"></script> <script src="githubhint.js"></script>
</body> </body>
</html> </html>

View File

@ -41,7 +41,9 @@ export default class Application extends Component {
registerBusy: false, registerBusy: false,
registerError: null, registerError: null,
registerState: '', registerState: '',
registerType: 'file' registerType: 'file',
repo: '',
repoError: null
} }
componentDidMount () { componentDidMount () {
@ -206,47 +208,64 @@ export default class Application extends Component {
} }
onChangeCommit = (event) => { onChangeCommit = (event) => {
const commit = event.target.value; let commit = event.target.value;
const commitError = null; const commitError = null;
let hasContent = false;
// TODO: field validation this.setState({ commit, commitError, contentHashError: null }, () => {
const { repo } = this.state || '';
const parts = repo.split('/');
this.setState({ commit, commitError, contentHashError: 'hash lookup in progress' }, () => { hasContent = commit.length !== 0 && parts.length === 2 && parts[0].length !== 0 && parts[1].length !== 0;
const { repo } = this.state; if (!commitError && hasContent) {
this.lookupHash(`https://codeload.github.com/${repo}/zip/${commit}`); this.setState({ contentHashError: 'hash lookup in progress' });
this.lookupHash(`https://codeload.github.com/${repo}/zip/${commit}`);
}
}); });
} }
onChangeRepo = (event) => { onChangeRepo = (event) => {
let repo = event.target.value; let repo = event.target.value;
const repoError = null; const repoError = null;
let hasContent = false;
// TODO: field validation // TODO: field validation
if (!repoError) { if (!repoError) {
repo = repo.replace('https://github.com/', ''); repo = repo.replace('https://github.com/', '');
} }
this.setState({ repo, repoError, contentHashError: 'hash lookup in progress' }, () => { this.setState({ repo, repoError, contentHashError: null }, () => {
const { commit } = this.state; const { commit } = this.state || '';
this.lookupHash(`https://codeload.github.com/${repo}/zip/${commit}`); const parts = repo.split('/');
hasContent = commit.length !== 0 && parts.length === 2 && parts[0].length !== 0 && parts[1].length !== 0;
if (!repoError && hasContent) {
this.setState({ contentHashError: 'hash lookup in progress' });
this.lookupHash(`https://codeload.github.com/${repo}/zip/${commit}`);
}
}); });
} }
onChangeUrl = (event) => { onChangeUrl = (event) => {
let url = event.target.value; let url = event.target.value;
const urlError = null; const urlError = null;
let hasContent = false;
// TODO: field validation // TODO: field validation
if (!urlError) { if (!urlError) {
const parts = url.split('/'); const parts = url.split('/');
hasContent = parts.length !== 0;
if (parts[2] === 'github.com' || parts[2] === 'raw.githubusercontent.com') { if (parts[2] === 'github.com' || parts[2] === 'raw.githubusercontent.com') {
url = `https://raw.githubusercontent.com/${parts.slice(3).join('/')}`.replace('/blob/', '/'); url = `https://raw.githubusercontent.com/${parts.slice(3).join('/')}`.replace('/blob/', '/');
} }
} }
this.setState({ url, urlError, contentHashError: 'hash lookup in progress' }, () => { this.setState({ url, urlError, contentHashError: null }, () => {
this.lookupHash(url); if (!urlError && hasContent) {
this.setState({ contentHashError: 'hash lookup in progress' });
this.lookupHash(url);
}
}); });
} }
@ -271,7 +290,7 @@ export default class Application extends Component {
.then((signerRequestId) => { .then((signerRequestId) => {
this.setState({ signerRequestId, registerState: 'Transaction posted, Waiting for transaction authorization' }); this.setState({ signerRequestId, registerState: 'Transaction posted, Waiting for transaction authorization' });
return api.pollMethod('eth_checkRequest', signerRequestId); return api.pollMethod('parity_checkRequest', signerRequestId);
}) })
.then((txHash) => { .then((txHash) => {
this.setState({ txHash, registerState: 'Transaction authorized, Waiting for network confirmations' }); this.setState({ txHash, registerState: 'Transaction authorized, Waiting for network confirmations' });
@ -285,7 +304,7 @@ export default class Application extends Component {
}); });
}) })
.then((txReceipt) => { .then((txReceipt) => {
this.setState({ txReceipt, registerBusy: false, registerState: 'Network confirmed, Received transaction receipt', url: '', commit: '', commitError: null, contentHash: '', contentHashOwner: null, contentHashError: null }); this.setState({ txReceipt, registerBusy: false, registerState: 'Network confirmed, Received transaction receipt', url: '', commit: '', repo: '', commitError: null, contentHash: '', contentHashOwner: null, contentHashError: null });
}) })
.catch((error) => { .catch((error) => {
console.error('onSend', error); console.error('onSend', error);
@ -298,7 +317,7 @@ export default class Application extends Component {
this.setState({ registerBusy: true, registerState: 'Estimating gas for the transaction' }); this.setState({ registerBusy: true, registerState: 'Estimating gas for the transaction' });
const values = [contentHash, repo, commit]; const values = [contentHash, repo, commit.substr(0, 2) === '0x' ? commit : `0x${commit}`];
const options = { from: fromAddress }; const options = { from: fromAddress };
this.trackRequest( this.trackRequest(
@ -367,7 +386,7 @@ export default class Application extends Component {
console.log(`lookupHash ${url}`); console.log(`lookupHash ${url}`);
api.ethcore api.parity
.hashContent(url) .hashContent(url)
.then((contentHash) => { .then((contentHash) => {
console.log('lookupHash', contentHash); console.log('lookupHash', contentHash);

View File

@ -14,7 +14,7 @@
// You should have received a copy of the GNU General Public License // You should have received a copy of the GNU General Public License
// along with Parity. If not, see <http://www.gnu.org/licenses/>. // along with Parity. If not, see <http://www.gnu.org/licenses/>.
const { api } = window.parity; const api = window.parent.secureApi;
export { export {
api api

View File

@ -18,7 +18,7 @@ import * as abis from '../../contracts/abi';
import { api } from './parity'; import { api } from './parity';
export function attachInterface () { export function attachInterface () {
return api.ethcore return api.parity
.registryAddress() .registryAddress()
.then((registryAddress) => { .then((registryAddress) => {
console.log(`the registry was found at ${registryAddress}`); console.log(`the registry was found at ${registryAddress}`);
@ -29,7 +29,7 @@ export function attachInterface () {
.all([ .all([
registry.getAddress.call({}, [api.util.sha3('githubhint'), 'A']), registry.getAddress.call({}, [api.util.sha3('githubhint'), 'A']),
api.eth.accounts(), api.eth.accounts(),
api.personal.accountsInfo() api.parity.accounts()
]); ]);
}) })
.then(([address, addresses, accountsInfo]) => { .then(([address, addresses, accountsInfo]) => {

View File

@ -29,7 +29,7 @@ export { addresses, accounts, lookup, events, names, records };
export const setContract = (contract) => ({ type: 'set contract', contract }); export const setContract = (contract) => ({ type: 'set contract', contract });
export const fetchContract = () => (dispatch) => export const fetchContract = () => (dispatch) =>
api.ethcore.registryAddress() api.parity.registryAddress()
.then((address) => { .then((address) => {
const contract = api.newContract(registryAbi, address); const contract = api.newContract(registryAbi, address);
dispatch(setContract(contract)); dispatch(setContract(contract));

View File

@ -22,7 +22,7 @@ export const fetch = () => (dispatch) => {
return Promise return Promise
.all([ .all([
api.eth.accounts(), api.eth.accounts(),
api.personal.accountsInfo() api.parity.accounts()
]) ])
.then(([ accounts, data ]) => { .then(([ accounts, data ]) => {
data = data || {}; data = data || {};

View File

@ -39,7 +39,7 @@ const logToEvent = (log) => {
}; };
export function attachInterface (callback) { export function attachInterface (callback) {
return api.ethcore return api.parity
.registryAddress() .registryAddress()
.then((registryAddress) => { .then((registryAddress) => {
console.log(`the registry was found at ${registryAddress}`); console.log(`the registry was found at ${registryAddress}`);
@ -50,7 +50,7 @@ export function attachInterface (callback) {
.all([ .all([
registry.getAddress.call({}, [api.util.sha3('signaturereg'), 'A']), registry.getAddress.call({}, [api.util.sha3('signaturereg'), 'A']),
api.eth.accounts(), api.eth.accounts(),
api.personal.accountsInfo() api.parity.accounts()
]); ]);
}) })
.then(([address, addresses, accountsInfo]) => { .then(([address, addresses, accountsInfo]) => {

View File

@ -38,7 +38,7 @@ export const loadAccounts = () => (dispatch) => {
Promise Promise
.all([ .all([
api.eth.accounts(), api.eth.accounts(),
api.personal.accountsInfo() api.parity.accounts()
]) ])
.then(([ accounts, accountsInfo ]) => { .then(([ accounts, accountsInfo ]) => {
accountsInfo = accountsInfo || {}; accountsInfo = accountsInfo || {};

View File

@ -34,7 +34,7 @@ export const FIND_CONTRACT = 'FIND_CONTRACT';
export const loadContract = () => (dispatch) => { export const loadContract = () => (dispatch) => {
dispatch(setLoading(true)); dispatch(setLoading(true));
api.ethcore api.parity
.registryAddress() .registryAddress()
.then((registryAddress) => { .then((registryAddress) => {
console.log(`registry found at ${registryAddress}`); console.log(`registry found at ${registryAddress}`);

View File

@ -74,7 +74,7 @@ ReactDOM.render(
<Route path='addresses' component={ Addresses } /> <Route path='addresses' component={ Addresses } />
<Route path='address/:address' component={ Address } /> <Route path='address/:address' component={ Address } />
<Route path='apps' component={ Dapps } /> <Route path='apps' component={ Dapps } />
<Route path='app/:type/:name' component={ Dapp } /> <Route path='app/:id' component={ Dapp } />
<Route path='contracts' component={ Contracts } /> <Route path='contracts' component={ Contracts } />
<Route path='contract/:address' component={ Contract } /> <Route path='contract/:address' component={ Contract } />
<Route path='settings' component={ Settings }> <Route path='settings' component={ Settings }>

View File

@ -16,20 +16,22 @@
import db from './interfaces/db'; import db from './interfaces/db';
import eth from './interfaces/eth'; import eth from './interfaces/eth';
import ethcore from './interfaces/ethcore';
import net from './interfaces/net'; import net from './interfaces/net';
import parity from './interfaces/parity';
import personal from './interfaces/personal'; import personal from './interfaces/personal';
import shh from './interfaces/shh'; import shh from './interfaces/shh';
import signer from './interfaces/signer';
import trace from './interfaces/trace'; import trace from './interfaces/trace';
import web3 from './interfaces/web3'; import web3 from './interfaces/web3';
export default { export default {
db: db, db,
eth: eth, eth,
ethcore: ethcore, parity,
net: net, net,
personal: personal, personal,
shh: shh, shh,
trace: trace, signer,
web3: web3 trace,
web3
}; };

View File

@ -86,20 +86,6 @@ export default {
} }
}, },
checkRequest: {
desc: 'Returns the transactionhash of the requestId (received from eth_postTransaction) if the request was confirmed',
params: [
{
type: Quantity,
desc: 'The requestId to check for'
}
],
returns: {
type: Hash,
desc: '32 Bytes - the transaction hash, or the zero hash if the transaction is not yet available'
}
},
coinbase: { coinbase: {
desc: 'Returns the client coinbase address.', desc: 'Returns the client coinbase address.',
params: [], params: [],
@ -823,22 +809,6 @@ export default {
} }
}, },
postTransaction: {
desc: 'Posts a transaction to the Signer.',
params: [
{
type: Object,
desc: 'see [eth_sendTransaction](#eth_sendTransaction)',
format: 'inputCallFormatter'
}
],
returns: {
type: Quantity,
desc: 'The id of the actual transaction',
format: 'utils.toDecimal'
}
},
protocolVersion: { protocolVersion: {
desc: 'Returns the current ethereum protocol version.', desc: 'Returns the current ethereum protocol version.',
params: [], params: [],

View File

@ -26,6 +26,52 @@ export default {
} }
}, },
accounts: {
desc: 'returns a map of accounts as an object',
params: [],
returns: {
type: Array,
desc: 'Account metadata',
details: {
name: {
type: String,
desc: 'Account name'
},
meta: {
type: String,
desc: 'Encoded JSON string the defines additional account metadata'
},
uuid: {
type: String,
desc: 'The account UUID, or null if not available/unknown/not applicable.'
}
}
}
},
accountsInfo: {
desc: 'returns a map of accounts as an object',
params: [],
returns: {
type: Array,
desc: 'Account metadata',
details: {
name: {
type: String,
desc: 'Account name'
},
meta: {
type: String,
desc: 'Encoded JSON string the defines additional account metadata'
},
uuid: {
type: String,
desc: 'The account UUID, or null if not available/unknown/not applicable.'
}
}
}
},
addReservedPeer: { addReservedPeer: {
desc: '?', desc: '?',
params: [ params: [
@ -40,6 +86,20 @@ export default {
} }
}, },
checkRequest: {
desc: 'Returns the transactionhash of the requestId (received from parity_postTransaction) if the request was confirmed',
params: [
{
type: Quantity,
desc: 'The requestId to check for'
}
],
returns: {
type: Hash,
desc: '32 Bytes - the transaction hash, or the zero hash if the transaction is not yet available'
}
},
dappsPort: { dappsPort: {
desc: 'Returns the port the dapps are running on, error if not enabled', desc: 'Returns the port the dapps are running on, error if not enabled',
params: [], params: [],
@ -155,6 +215,29 @@ export default {
} }
}, },
listGethAccounts: {
desc: 'Returns a list of the accounts available from Geth',
params: [],
returns: {
type: Array,
desc: '20 Bytes addresses owned by the client.'
}
},
importGethAccounts: {
desc: 'Imports a list of accounts from geth',
params: [
{
type: Array,
desc: 'List of the geth addresses to import'
}
],
returns: {
type: Array,
desc: 'Array of the imported addresses'
}
},
minGasPrice: { minGasPrice: {
desc: 'Returns currently set minimal gas price', desc: 'Returns currently set minimal gas price',
params: [], params: [],
@ -210,6 +293,60 @@ export default {
} }
}, },
newAccountFromPhrase: {
desc: 'Creates a new account from a recovery passphrase',
params: [
{
type: String,
desc: 'Phrase'
},
{
type: String,
desc: 'Password'
}
],
returns: {
type: Address,
desc: 'The created address'
}
},
newAccountFromSecret: {
desc: 'Creates a new account from a private ethstore secret key',
params: [
{
type: Data,
desc: 'Secret, 32-byte hex'
},
{
type: String,
desc: 'Password'
}
],
returns: {
type: Address,
desc: 'The created address'
}
},
newAccountFromWallet: {
desc: 'Creates a new account from a JSON import',
params: [
{
type: String,
desc: 'JSON'
},
{
type: String,
desc: 'Password'
}
],
returns: {
type: Address,
desc: 'The created address'
}
},
nodeName: { nodeName: {
desc: 'Returns node name (identity)', desc: 'Returns node name (identity)',
params: [], params: [],
@ -233,6 +370,22 @@ export default {
} }
}, },
postTransaction: {
desc: 'Posts a transaction to the Signer.',
params: [
{
type: Object,
desc: 'see [eth_sendTransaction](#eth_sendTransaction)',
format: 'inputCallFormatter'
}
],
returns: {
type: Quantity,
desc: 'The id of the actual transaction',
format: 'utils.toDecimal'
}
},
removeReservedPeer: { removeReservedPeer: {
desc: '?', desc: '?',
params: [ params: [
@ -265,6 +418,42 @@ export default {
} }
}, },
setAccountName: {
desc: 'Sets a name for the account',
params: [
{
type: Address,
desc: 'Address'
},
{
type: String,
desc: 'Name'
}
],
returns: {
type: Object,
desc: 'Returns null in all cases'
}
},
setAccountMeta: {
desc: 'Sets metadata for the account',
params: [
{
type: Address,
desc: 'Address'
},
{
type: String,
desc: 'Metadata (JSON encoded)'
}
],
returns: {
type: Object,
desc: 'Returns null in all cases'
}
},
setAuthor: { setAuthor: {
desc: 'Changes author (coinbase) for mined blocks.', desc: 'Changes author (coinbase) for mined blocks.',
params: [ params: [

View File

@ -17,83 +17,6 @@
import { Address, Data, Quantity } from '../types'; import { Address, Data, Quantity } from '../types';
export default { export default {
accountsInfo: {
desc: 'returns a map of accounts as an object',
params: [],
returns: {
type: Array,
desc: 'Account metadata',
details: {
name: {
type: String,
desc: 'Account name'
},
meta: {
type: String,
desc: 'Encoded JSON string the defines additional account metadata'
},
uuid: {
type: String,
desc: 'The account UUID, or null if not available/unknown/not applicable.'
}
}
}
},
generateAuthorizationToken: {
desc: 'Generates a new authorization token',
params: [],
returns: {
type: String,
desc: 'The new authorization token'
}
},
requestsToConfirm: {
desc: 'Returns a list of the transactions requiring authorization',
params: [],
returns: {
type: Array,
desc: 'A list of the outstanding transactions'
}
},
confirmRequest: {
desc: 'Confirm a request in the signer queue',
params: [
{
type: Quantity,
desc: 'The request id'
},
{
type: Object,
desc: 'The request options'
},
{
type: String,
desc: 'The account password'
}
],
returns: {
type: Boolean,
desc: 'The status of the confirmation'
}
},
rejectRequest: {
desc: 'Rejects a request in the signer queue',
params: [
{
type: Quantity,
desc: 'The request id'
}
],
returns: {
type: Boolean,
desc: 'The status of the rejection'
}
},
listAccounts: { listAccounts: {
desc: 'Returns a list of addresses owned by client.', desc: 'Returns a list of addresses owned by client.',
params: [], params: [],
@ -103,29 +26,6 @@ export default {
} }
}, },
listGethAccounts: {
desc: 'Returns a list of the accounts available from Geth',
params: [],
returns: {
type: Array,
desc: '20 Bytes addresses owned by the client.'
}
},
importGethAccounts: {
desc: 'Imports a list of accounts from geth',
params: [
{
type: Array,
desc: 'List of the geth addresses to import'
}
],
returns: {
type: Array,
desc: 'Array of the imported addresses'
}
},
newAccount: { newAccount: {
desc: 'Creates new account', desc: 'Creates new account',
params: [ params: [
@ -140,96 +40,6 @@ export default {
} }
}, },
newAccountFromPhrase: {
desc: 'Creates a new account from a recovery passphrase',
params: [
{
type: String,
desc: 'Phrase'
},
{
type: String,
desc: 'Password'
}
],
returns: {
type: Address,
desc: 'The created address'
}
},
newAccountFromSecret: {
desc: 'Creates a new account from a private ethstore secret key',
params: [
{
type: Data,
desc: 'Secret, 32-byte hex'
},
{
type: String,
desc: 'Password'
}
],
returns: {
type: Address,
desc: 'The created address'
}
},
newAccountFromWallet: {
desc: 'Creates a new account from a JSON import',
params: [
{
type: String,
desc: 'JSON'
},
{
type: String,
desc: 'Password'
}
],
returns: {
type: Address,
desc: 'The created address'
}
},
setAccountName: {
desc: 'Sets a name for the account',
params: [
{
type: Address,
desc: 'Address'
},
{
type: String,
desc: 'Name'
}
],
returns: {
type: Object,
desc: 'Returns null in all cases'
}
},
setAccountMeta: {
desc: 'Sets metadata for the account',
params: [
{
type: Address,
desc: 'Address'
},
{
type: String,
desc: 'Metadata (JSON encoded)'
}
],
returns: {
type: Object,
desc: 'Returns null in all cases'
}
},
signAndSendTransaction: { signAndSendTransaction: {
desc: 'Sends and signs a transaction given account passphrase. Does not require the account to be unlocked nor unlocks the account for future transactions. ', desc: 'Sends and signs a transaction given account passphrase. Does not require the account to be unlocked nor unlocks the account for future transactions. ',
params: [ params: [
@ -284,15 +94,6 @@ export default {
} }
}, },
signerEnabled: {
desc: 'Returns whether signer is enabled/disabled.',
params: [],
returns: {
type: Boolean,
desc: 'true when enabled, false when disabled'
}
},
unlockAccount: { unlockAccount: {
desc: '?', desc: '?',
params: [ params: [

View File

@ -0,0 +1,82 @@
// Copyright 2015, 2016 Ethcore (UK) Ltd.
// This file is part of Parity.
// Parity is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
// Parity 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 General Public License for more details.
// You should have received a copy of the GNU General Public License
// along with Parity. If not, see <http://www.gnu.org/licenses/>.
import { Quantity } from '../types';
export default {
generateAuthorizationToken: {
desc: 'Generates a new authorization token',
params: [],
returns: {
type: String,
desc: 'The new authorization token'
}
},
requestsToConfirm: {
desc: 'Returns a list of the transactions requiring authorization',
params: [],
returns: {
type: Array,
desc: 'A list of the outstanding transactions'
}
},
confirmRequest: {
desc: 'Confirm a request in the signer queue',
params: [
{
type: Quantity,
desc: 'The request id'
},
{
type: Object,
desc: 'The request options'
},
{
type: String,
desc: 'The account password'
}
],
returns: {
type: Boolean,
desc: 'The status of the confirmation'
}
},
rejectRequest: {
desc: 'Rejects a request in the signer queue',
params: [
{
type: Quantity,
desc: 'The request id'
}
],
returns: {
type: Boolean,
desc: 'The status of the rejection'
}
},
signerEnabled: {
desc: 'Returns whether signer is enabled/disabled.',
params: [],
returns: {
type: Boolean,
desc: 'true when enabled, false when disabled'
}
}
};

View File

@ -133,8 +133,8 @@ export default class AddAddress extends Component {
const { address, name, description } = this.state; const { address, name, description } = this.state;
Promise.all([ Promise.all([
api.personal.setAccountName(address, name), api.parity.setAccountName(address, name),
api.personal.setAccountMeta(address, { api.parity.setAccountMeta(address, {
description, description,
timestamp: Date.now(), timestamp: Date.now(),
deleted: false deleted: false

View File

@ -141,8 +141,8 @@ export default class AddContract extends Component {
const { abiParsed, address, name, description } = this.state; const { abiParsed, address, name, description } = this.state;
Promise.all([ Promise.all([
api.personal.setAccountName(address, name), api.parity.setAccountName(address, name),
api.personal.setAccountMeta(address, { api.parity.setAccountMeta(address, {
contract: true, contract: true,
deleted: false, deleted: false,
timestamp: Date.now(), timestamp: Date.now(),

View File

@ -173,15 +173,15 @@ export default class CreateAccount extends Component {
Promise Promise
.all([ .all([
api.ethcore.generateSecretPhrase(), api.parity.generateSecretPhrase(),
api.ethcore.generateSecretPhrase(), api.parity.generateSecretPhrase(),
api.ethcore.generateSecretPhrase(), api.parity.generateSecretPhrase(),
api.ethcore.generateSecretPhrase(), api.parity.generateSecretPhrase(),
api.ethcore.generateSecretPhrase() api.parity.generateSecretPhrase()
]) ])
.then((phrases) => { .then((phrases) => {
return Promise return Promise
.all(phrases.map((phrase) => api.ethcore.phraseToAddress(phrase))) .all(phrases.map((phrase) => api.parity.phraseToAddress(phrase)))
.then((addresses) => { .then((addresses) => {
const accounts = {}; const accounts = {};

View File

@ -102,7 +102,7 @@ export default class NewGeth extends Component {
const { api } = this.context; const { api } = this.context;
const { accounts } = this.props; const { accounts } = this.props;
api.personal api.parity
.listGethAccounts() .listGethAccounts()
.then((_addresses) => { .then((_addresses) => {
const addresses = (addresses || []).filter((address) => !accounts[address]); const addresses = (addresses || []).filter((address) => !accounts[address]);

View File

@ -208,13 +208,13 @@ export default class CreateAccount extends Component {
}); });
if (createType === 'fromNew' || createType === 'fromPhrase') { if (createType === 'fromNew' || createType === 'fromPhrase') {
return api.personal return api.parity
.newAccountFromPhrase(this.state.phrase, this.state.password) .newAccountFromPhrase(this.state.phrase, this.state.password)
.then((address) => { .then((address) => {
this.setState({ address }); this.setState({ address });
return api.personal return api.parity
.setAccountName(address, this.state.name) .setAccountName(address, this.state.name)
.then(() => api.personal.setAccountMeta(address, { .then(() => api.parity.setAccountMeta(address, {
timestamp: Date.now(), timestamp: Date.now(),
passwordHint: this.state.passwordHint passwordHint: this.state.passwordHint
})); }));
@ -233,13 +233,13 @@ export default class CreateAccount extends Component {
this.newError(error); this.newError(error);
}); });
} else if (createType === 'fromRaw') { } else if (createType === 'fromRaw') {
return api.personal return api.parity
.newAccountFromSecret(this.state.rawKey, this.state.password) .newAccountFromSecret(this.state.rawKey, this.state.password)
.then((address) => { .then((address) => {
this.setState({ address }); this.setState({ address });
return api.personal return api.parity
.setAccountName(address, this.state.name) .setAccountName(address, this.state.name)
.then(() => api.personal.setAccountMeta(address, { .then(() => api.parity.setAccountMeta(address, {
timestamp: Date.now(), timestamp: Date.now(),
passwordHint: this.state.passwordHint passwordHint: this.state.passwordHint
})); }));
@ -258,13 +258,13 @@ export default class CreateAccount extends Component {
this.newError(error); this.newError(error);
}); });
} else if (createType === 'fromGeth') { } else if (createType === 'fromGeth') {
return api.personal return api.parity
.importGethAccounts(this.state.gethAddresses) .importGethAccounts(this.state.gethAddresses)
.then((result) => { .then((result) => {
console.log('result', result); console.log('result', result);
return Promise.all(this.state.gethAddresses.map((address) => { return Promise.all(this.state.gethAddresses.map((address) => {
return api.personal.setAccountName(address, 'Geth Import'); return api.parity.setAccountName(address, 'Geth Import');
})); }));
}) })
.then(() => { .then(() => {
@ -282,16 +282,16 @@ export default class CreateAccount extends Component {
}); });
} }
return api.personal return api.parity
.newAccountFromWallet(this.state.json, this.state.password) .newAccountFromWallet(this.state.json, this.state.password)
.then((address) => { .then((address) => {
this.setState({ this.setState({
address: address address: address
}); });
return api.personal return api.parity
.setAccountName(address, this.state.name) .setAccountName(address, this.state.name)
.then(() => api.personal.setAccountMeta(address, { .then(() => api.parity.setAccountMeta(address, {
timestamp: Date.now(), timestamp: Date.now(),
passwordHint: this.state.passwordHint passwordHint: this.state.passwordHint
})); }));

View File

@ -213,8 +213,8 @@ export default class DeployContract extends Component {
.deploy(options, params, this.onDeploymentState) .deploy(options, params, this.onDeploymentState)
.then((address) => { .then((address) => {
return Promise.all([ return Promise.all([
api.personal.setAccountName(address, name), api.parity.setAccountName(address, name),
api.personal.setAccountMeta(address, { api.parity.setAccountMeta(address, {
abi: abiParsed, abi: abiParsed,
contract: true, contract: true,
timestamp: Date.now(), timestamp: Date.now(),

View File

@ -139,8 +139,8 @@ export default class EditMeta extends Component {
Promise Promise
.all([ .all([
api.personal.setAccountName(account.address, name), api.parity.setAccountName(account.address, name),
api.personal.setAccountMeta(account.address, Object.assign({}, account.meta, meta)) api.parity.setAccountMeta(account.address, Object.assign({}, account.meta, meta))
]) ])
.then(() => this.props.onClose()) .then(() => this.props.onClose())
.catch((error) => { .catch((error) => {

View File

@ -221,7 +221,7 @@ export default class ExecuteContract extends Component {
}) })
.then((requestId) => { .then((requestId) => {
this.setState({ busyState: 'Waiting for authorization in the Parity Signer' }); this.setState({ busyState: 'Waiting for authorization in the Parity Signer' });
return api.pollMethod('eth_checkRequest', requestId); return api.pollMethod('parity_checkRequest', requestId);
}) })
.then((txhash) => { .then((txhash) => {
this.setState({ sending: false, step: 2, txhash, busyState: 'Your transaction has been posted to the network' }); this.setState({ sending: false, step: 2, txhash, busyState: 'Your transaction has been posted to the network' });

View File

@ -183,9 +183,9 @@ export default class FirstRun extends Component {
canCreate: false canCreate: false
}); });
return api.personal return api.parity
.newAccountFromPhrase(phrase, password) .newAccountFromPhrase(phrase, password)
.then((address) => api.personal.setAccountName(address, name)) .then((address) => api.parity.setAccountName(address, name))
.then(() => { .then(() => {
this.onNext(); this.onNext();
}) })

View File

@ -317,7 +317,7 @@ export default class PasswordManager extends Component {
this.setState({ waiting: true, showMessage: false }); this.setState({ waiting: true, showMessage: false });
this.context this.context
.api.personal .api.parity
.testPassword(account.address, currentPass) .testPassword(account.address, currentPass)
.then(correct => { .then(correct => {
const message = correct const message = correct
@ -343,7 +343,7 @@ export default class PasswordManager extends Component {
this.setState({ waiting: true, showMessage: false }); this.setState({ waiting: true, showMessage: false });
this.context this.context
.api.personal .api.parity
.testPassword(account.address, currentPass) .testPassword(account.address, currentPass)
.then(correct => { .then(correct => {
if (!correct) { if (!correct) {
@ -363,11 +363,11 @@ export default class PasswordManager extends Component {
return Promise.all([ return Promise.all([
this.context this.context
.api.personal .api.parity
.setAccountMeta(account.address, meta), .setAccountMeta(account.address, meta),
this.context this.context
.api.personal .api.parity
.changePassword(account.address, currentPass, newPass) .changePassword(account.address, currentPass, newPass)
]) ])
.then(() => { .then(() => {

View File

@ -424,7 +424,7 @@ export default class Transfer extends Component {
options.data = data; options.data = data;
} }
return api.eth.postTransaction(options); return api.parity.postTransaction(options);
} }
_sendToken () { _sendToken () {
@ -455,7 +455,7 @@ export default class Transfer extends Component {
: this._sendToken() : this._sendToken()
).then((requestId) => { ).then((requestId) => {
this.setState({ busyState: 'Waiting for authorization in the Parity Signer' }); this.setState({ busyState: 'Waiting for authorization in the Parity Signer' });
return api.pollMethod('eth_checkRequest', requestId); return api.pollMethod('parity_checkRequest', requestId);
}) })
.then((txhash) => { .then((txhash) => {
this.onNext(); this.onNext();
@ -592,7 +592,7 @@ export default class Transfer extends Component {
Promise Promise
.all([ .all([
api.ethcore.gasPriceHistogram(), api.parity.gasPriceHistogram(),
api.eth.gasPrice() api.eth.gasPrice()
]) ])
.then(([gasPriceHistogram, gasPrice]) => { .then(([gasPriceHistogram, gasPrice]) => {

View File

@ -42,7 +42,7 @@ export default class Balances {
_subscribeAccountsInfo () { _subscribeAccountsInfo () {
this._api this._api
.subscribe('personal_accountsInfo', (error, accountsInfo) => { .subscribe('parity_accountsInfo', (error, accountsInfo) => {
if (error) { if (error) {
return; return;
} }
@ -76,7 +76,7 @@ export default class Balances {
} }
_retrieveTokens () { _retrieveTokens () {
this._api.ethcore this._api.parity
.registryAddress() .registryAddress()
.then((registryAddress) => { .then((registryAddress) => {
const registry = this._api.newContract(abis.registry, registryAddress); const registry = this._api.newContract(abis.registry, registryAddress);

View File

@ -28,9 +28,9 @@ export default class Personal {
_subscribeAccountsInfo () { _subscribeAccountsInfo () {
this._api this._api
.subscribe('personal_accountsInfo', (error, accountsInfo) => { .subscribe('parity_accountsInfo', (error, accountsInfo) => {
if (error) { if (error) {
console.error('personal_accountsInfo', error); console.error('parity_accountsInfo', error);
return; return;
} }

View File

@ -14,22 +14,6 @@
// You should have received a copy of the GNU General Public License // You should have received a copy of the GNU General Public License
// along with Parity. If not, see <http://www.gnu.org/licenses/>. // along with Parity. If not, see <http://www.gnu.org/licenses/>.
// Copyright 2015, 2016 Ethcore (UK) Ltd.
// This file is part of Parity.
// Parity is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
// Parity 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 General Public License for more details.
// You should have received a copy of the GNU General Public License
// along with Parity. If not, see <http://www.gnu.org/licenses/>.
import { signerRequestsToConfirm } from './signerActions'; import { signerRequestsToConfirm } from './signerActions';
export default class Signer { export default class Signer {
@ -44,7 +28,7 @@ export default class Signer {
_subscribeRequestsToConfirm () { _subscribeRequestsToConfirm () {
this._api this._api
.subscribe('personal_requestsToConfirm', (error, pending) => { .subscribe('signer_requestsToConfirm', (error, pending) => {
if (error) { if (error) {
return; return;
} }

View File

@ -51,7 +51,7 @@ export default class SignerMiddleware {
onConfirmStart = (store, action) => { onConfirmStart = (store, action) => {
const { id, password } = action.payload; const { id, password } = action.payload;
this._api.personal this._api.signer
.confirmRequest(id, {}, password) .confirmRequest(id, {}, password)
.then((txHash) => { .then((txHash) => {
console.log('confirmRequest', id, txHash); console.log('confirmRequest', id, txHash);
@ -71,7 +71,7 @@ export default class SignerMiddleware {
onRejectStart = (store, action) => { onRejectStart = (store, action) => {
const id = action.payload; const id = action.payload;
this._api.personal this._api.signer
.rejectRequest(id) .rejectRequest(id)
.then(() => { .then(() => {
store.dispatch(actions.successRejectRequest({ id })); store.dispatch(actions.successRejectRequest({ id }));

View File

@ -31,8 +31,8 @@ export default class Status {
} }
_fetchEnode () { _fetchEnode () {
this._api this._api.parity
.ethcore.enode() .enode()
.then((enode) => { .then((enode) => {
this._store.dispatch(statusCollection({ enode })); this._store.dispatch(statusCollection({ enode }));
}) })
@ -101,16 +101,16 @@ export default class Status {
.all([ .all([
this._api.web3.clientVersion(), this._api.web3.clientVersion(),
this._api.eth.coinbase(), this._api.eth.coinbase(),
this._api.ethcore.defaultExtraData(), this._api.parity.defaultExtraData(),
this._api.ethcore.extraData(), this._api.parity.extraData(),
this._api.ethcore.gasFloorTarget(), this._api.parity.gasFloorTarget(),
this._api.eth.hashrate(), this._api.eth.hashrate(),
this._api.ethcore.minGasPrice(), this._api.parity.minGasPrice(),
this._api.ethcore.netChain(), this._api.parity.netChain(),
this._api.ethcore.netPeers(), this._api.parity.netPeers(),
this._api.ethcore.netPort(), this._api.parity.netPort(),
this._api.ethcore.nodeName(), this._api.parity.nodeName(),
this._api.ethcore.rpcSettings(), this._api.parity.rpcSettings(),
this._api.eth.syncing(), this._api.eth.syncing(),
this._pollTraceMode() this._pollTraceMode()
]) ])
@ -153,8 +153,8 @@ export default class Status {
Promise Promise
.all([ .all([
this._api.ethcore.devLogs(), this._api.parity.devLogs(),
this._api.ethcore.devLogsLevels() this._api.parity.devLogsLevels()
]) ])
.then(([devLogs, devLogsLevels]) => { .then(([devLogs, devLogsLevels]) => {
this._store.dispatch(statusLogs({ this._store.dispatch(statusLogs({

View File

@ -62,7 +62,7 @@ export default class SecureApi extends Api {
case 1: case 1:
if (isConnected) { if (isConnected) {
this._connectState = 2; this._connectState = 2;
this.personal this.parity
.generateAuthorizationToken() .generateAuthorizationToken()
.then((token) => { .then((token) => {
this.updateToken(token, 2); this.updateToken(token, 2);
@ -96,8 +96,8 @@ export default class SecureApi extends Api {
Promise Promise
.all([ .all([
this.ethcore.dappsPort(), this.parity.dappsPort(),
this.ethcore.signerPort() this.parity.signerPort()
]) ])
.then(([dappsPort, signerPort]) => { .then(([dappsPort, signerPort]) => {
this._dappsPort = dappsPort.toNumber(); this._dappsPort = dappsPort.toNumber();

View File

@ -149,7 +149,7 @@ export default class Header extends Component {
const { account } = this.props; const { account } = this.props;
this.setState({ name }, () => { this.setState({ name }, () => {
api.personal api.parity
.setAccountName(account.address, name) .setAccountName(account.address, name)
.catch((error) => { .catch((error) => {
console.error(error); console.error(error);

View File

@ -81,7 +81,7 @@ class Delete extends Component {
account.meta.deleted = true; account.meta.deleted = true;
api.personal api.parity
.setAccountMeta(account.address, account.meta) .setAccountMeta(account.address, account.meta)
.then(() => { .then(() => {
router.push(route); router.push(route);

View File

@ -104,8 +104,8 @@ class Application extends Component {
checkAccounts () { checkAccounts () {
const { api } = this.context; const { api } = this.context;
api.personal api.eth
.listAccounts() .accounts()
.then((accounts) => { .then((accounts) => {
this.setState({ this.setState({
showFirstRun: showFirstRun || accounts.length === 0 showFirstRun: showFirstRun || accounts.length === 0

View File

@ -16,6 +16,9 @@
import React, { Component, PropTypes } from 'react'; import React, { Component, PropTypes } from 'react';
import Contracts from '../../contracts';
import { fetchAvailable } from '../Dapps/registry';
import styles from './dapp.css'; import styles from './dapp.css';
export default class Dapp extends Component { export default class Dapp extends Component {
@ -27,16 +30,39 @@ export default class Dapp extends Component {
params: PropTypes.object params: PropTypes.object
}; };
state = {
app: null
}
componentWillMount () {
this.lookup();
}
render () { render () {
const { name, type } = this.props.params; const { app } = this.state;
const { dappsUrl } = this.context.api; const { dappsUrl } = this.context.api;
let src = `${dappsUrl}/${name}/`; if (!app) {
if (type === 'builtin') { return null;
const dapphost = process.env.NODE_ENV === 'production' }
? `${dappsUrl}/ui`
: ''; let src = null;
src = `${dapphost}/${name}.html`; switch (app.type) {
case 'builtin':
const dapphost = process.env.NODE_ENV === 'production' && !app.secure
? `${dappsUrl}/ui`
: '';
src = `${dapphost}/${app.url}.html`;
break;
case 'local':
src = `${dappsUrl}/${app.id}/`;
break;
case 'network':
src = `${dappsUrl}/${app.contentHash}/`;
break;
default:
console.error('unknown type', app.type);
break;
} }
return ( return (
@ -50,4 +76,30 @@ export default class Dapp extends Component {
</iframe> </iframe>
); );
} }
lookup () {
const { api } = this.context;
const { id } = this.props.params;
const { dappReg } = Contracts.get();
fetchAvailable(api)
.then((available) => {
return available.find((app) => app.id === id);
})
.then((app) => {
if (app.type !== 'network') {
return app;
}
return dappReg
.getContent(app.id)
.then((contentHash) => {
app.contentHash = api.util.bytesToHex(contentHash).substr(2);
return app;
});
})
.then((app) => {
this.setState({ app });
});
}
} }

View File

@ -39,16 +39,7 @@ export default class Summary extends Component {
return null; return null;
} }
let type = 'builtin';
if (app.network) {
type = 'network';
} else if (app.local) {
type = 'local';
}
const url = `/app/${type}/${app.url || app.contentHash || app.id}`;
let image = <div className={ styles.image }>&nbsp;</div>; let image = <div className={ styles.image }>&nbsp;</div>;
if (app.image) { if (app.image) {
image = <img src={ `http://127.0.0.1:${dappsPort}${app.image}` } className={ styles.image } />; image = <img src={ `http://127.0.0.1:${dappsPort}${app.image}` } className={ styles.image } />;
} else if (app.iconUrl) { } else if (app.iconUrl) {
@ -61,7 +52,7 @@ export default class Summary extends Component {
<div className={ styles.description }> <div className={ styles.description }>
<ContainerTitle <ContainerTitle
className={ styles.title } className={ styles.title }
title={ <Link to={ url }>{ app.name }</Link> } title={ <Link to={ `/app/${app.id}` }>{ app.name }</Link> }
byline={ app.description } /> byline={ app.description } />
<div className={ styles.author }>{ app.author }, v{ app.version }</div> <div className={ styles.author }>{ app.author }, v{ app.version }</div>
{ this.props.children } { this.props.children }

View File

@ -55,7 +55,8 @@ const builtinApps = [
name: 'GitHub Hint', name: 'GitHub Hint',
description: 'A mapping of GitHub URLs to hashes for use in contracts as references', description: 'A mapping of GitHub URLs to hashes for use in contracts as references',
author: 'Parity Team <admin@ethcore.io>', author: 'Parity Team <admin@ethcore.io>',
version: '1.0.0' version: '1.0.0',
secure: true
} }
]; ];
@ -81,13 +82,6 @@ function getHost (api) {
} }
export function fetchAvailable (api) { export function fetchAvailable (api) {
// TODO: Since we don't have an extensive GithubHint app, get the value somehow
// RESULT: 0x22cd66e1b05882c0fa17a16d252d3b3ee2238ccbac8153f69a35c83f02ca76ee
// api.ethcore
// .hashContent('https://codeload.github.com/gavofyork/gavcoin/zip/5a9f11ff2ad0d05c565a938ceffdfa0d23af9981')
// .then((sha3) => {
// console.log('archive', sha3);
// });
return fetch(`${getHost(api)}/api/apps`) return fetch(`${getHost(api)}/api/apps`)
.then((response) => { .then((response) => {
return response.ok return response.ok
@ -102,11 +96,11 @@ export function fetchAvailable (api) {
const localApps = _localApps const localApps = _localApps
.filter((app) => !['ui'].includes(app.id)) .filter((app) => !['ui'].includes(app.id))
.map((app) => { .map((app) => {
app.local = true; app.type = 'local';
return app; return app;
}); });
return api.ethcore return api.parity
.registryAddress() .registryAddress()
.then((registryAddress) => { .then((registryAddress) => {
if (new BigNumber(registryAddress).eq(0)) { if (new BigNumber(registryAddress).eq(0)) {
@ -115,13 +109,13 @@ export function fetchAvailable (api) {
const _builtinApps = builtinApps const _builtinApps = builtinApps
.map((app) => { .map((app) => {
app.builtin = true; app.type = 'builtin';
return app; return app;
}); });
return networkApps return networkApps
.map((app) => { .map((app) => {
app.network = true; app.type = 'network';
return app; return app;
}) })
.concat(_builtinApps); .concat(_builtinApps);

View File

@ -89,7 +89,7 @@ export default class Parity extends Component {
onChangeMode = (event, index, mode) => { onChangeMode = (event, index, mode) => {
const { api } = this.context; const { api } = this.context;
api.ethcore api.parity
.setMode(mode) .setMode(mode)
.then((result) => { .then((result) => {
if (result) { if (result) {
@ -104,7 +104,7 @@ export default class Parity extends Component {
loadMode () { loadMode () {
const { api } = this.context; const { api } = this.context;
api.ethcore api.parity
.mode() .mode()
.then((mode) => { .then((mode) => {
this.setState({ mode }); this.setState({ mode });

View File

@ -50,7 +50,7 @@ export default class SignRequest extends Component {
} }
componentWillMount () { componentWillMount () {
this.context.api.ethcore.netChain() this.context.api.parity.netChain()
.then((chain) => { .then((chain) => {
this.setState({ chain }); this.setState({ chain });
}) })

View File

@ -65,7 +65,7 @@ export default class TransactionFinished extends Component {
const totalValue = tUtil.getTotalValue(fee, value); const totalValue = tUtil.getTotalValue(fee, value);
this.setState({ totalValue }); this.setState({ totalValue });
this.context.api.ethcore.netChain() this.context.api.parity.netChain()
.then((chain) => { .then((chain) => {
this.setState({ chain }); this.setState({ chain });
}) })

View File

@ -64,7 +64,7 @@ export default class TransactionPending extends Component {
const gasToDisplay = tUtil.getGasDisplay(gas); const gasToDisplay = tUtil.getGasDisplay(gas);
this.setState({ gasPriceEthmDisplay, totalValue, gasToDisplay }); this.setState({ gasPriceEthmDisplay, totalValue, gasToDisplay });
this.context.api.ethcore.netChain() this.context.api.parity.netChain()
.then((chain) => { .then((chain) => {
this.setState({ chain }); this.setState({ chain });
}) })

View File

@ -87,7 +87,7 @@ export default class MiningSettings extends Component {
onMinGasPriceChange = (newVal) => { onMinGasPriceChange = (newVal) => {
const { api } = this.context; const { api } = this.context;
api.ethcore.setMinGasPrice(numberFromString(newVal)); api.parity.setMinGasPrice(numberFromString(newVal));
}; };
onExtraDataChange = (newVal, isResetToDefault) => { onExtraDataChange = (newVal, isResetToDefault) => {
@ -97,18 +97,18 @@ export default class MiningSettings extends Component {
// In case of resetting to default we are just using raw bytes from defaultExtraData // In case of resetting to default we are just using raw bytes from defaultExtraData
// When user sets new value we can safely send a string that will be converted to hex by formatter. // When user sets new value we can safely send a string that will be converted to hex by formatter.
const val = isResetToDefault ? nodeStatus.defaultExtraData : newVal; const val = isResetToDefault ? nodeStatus.defaultExtraData : newVal;
api.ethcore.setExtraData(val); api.parity.setExtraData(val);
}; };
onAuthorChange = (newVal) => { onAuthorChange = (newVal) => {
const { api } = this.context; const { api } = this.context;
api.ethcore.setAuthor(newVal); api.parity.setAuthor(newVal);
}; };
onGasFloorTargetChange = (newVal) => { onGasFloorTargetChange = (newVal) => {
const { api } = this.context; const { api } = this.context;
api.ethcore.setGasFloorTarget(numberFromString(newVal)); api.parity.setGasFloorTarget(numberFromString(newVal));
}; };
} }

View File

@ -41,13 +41,13 @@ disable = false
port = 8545 port = 8545
interface = "local" interface = "local"
cors = "null" cors = "null"
apis = ["web3", "eth", "net", "ethcore", "traces", "rpc", "personal_safe"] apis = ["web3", "eth", "net", "parity", "traces", "rpc"]
hosts = ["none"] hosts = ["none"]
[ipc] [ipc]
disable = false disable = false
path = "$HOME/.parity/jsonrpc.ipc" path = "$HOME/.parity/jsonrpc.ipc"
apis = ["web3", "eth", "net", "ethcore", "traces", "rpc", "personal", "personal_safe"] apis = ["web3", "eth", "net", "parity", "parity_accounts", "personal", "traces", "rpc"]
[dapps] [dapps]
disable = false disable = false

View File

@ -143,7 +143,7 @@ usage! {
or |c: &Config| otry!(c.rpc).interface.clone(), or |c: &Config| otry!(c.rpc).interface.clone(),
flag_jsonrpc_cors: Option<String> = None, flag_jsonrpc_cors: Option<String> = None,
or |c: &Config| otry!(c.rpc).cors.clone().map(Some), or |c: &Config| otry!(c.rpc).cors.clone().map(Some),
flag_jsonrpc_apis: String = "web3,eth,net,ethcore,traces,rpc,personal_safe", flag_jsonrpc_apis: String = "web3,eth,net,parity,traces,rpc",
or |c: &Config| otry!(c.rpc).apis.clone().map(|vec| vec.join(",")), or |c: &Config| otry!(c.rpc).apis.clone().map(|vec| vec.join(",")),
flag_jsonrpc_hosts: String = "none", flag_jsonrpc_hosts: String = "none",
or |c: &Config| otry!(c.rpc).hosts.clone().map(|vec| vec.join(",")), or |c: &Config| otry!(c.rpc).hosts.clone().map(|vec| vec.join(",")),
@ -153,7 +153,7 @@ usage! {
or |c: &Config| otry!(c.ipc).disable.clone(), or |c: &Config| otry!(c.ipc).disable.clone(),
flag_ipc_path: String = "$HOME/.parity/jsonrpc.ipc", flag_ipc_path: String = "$HOME/.parity/jsonrpc.ipc",
or |c: &Config| otry!(c.ipc).path.clone(), or |c: &Config| otry!(c.ipc).path.clone(),
flag_ipc_apis: String = "web3,eth,net,ethcore,traces,rpc,personal,personal_safe", flag_ipc_apis: String = "web3,eth,net,parity,parity_accounts,traces,rpc",
or |c: &Config| otry!(c.ipc).apis.clone().map(|vec| vec.join(",")), or |c: &Config| otry!(c.ipc).apis.clone().map(|vec| vec.join(",")),
// DAPPS // DAPPS
@ -540,13 +540,13 @@ mod tests {
flag_jsonrpc_port: 8545u16, flag_jsonrpc_port: 8545u16,
flag_jsonrpc_interface: "local".into(), flag_jsonrpc_interface: "local".into(),
flag_jsonrpc_cors: Some("null".into()), flag_jsonrpc_cors: Some("null".into()),
flag_jsonrpc_apis: "web3,eth,net,ethcore,traces,rpc,personal_safe".into(), flag_jsonrpc_apis: "web3,eth,net,parity,traces,rpc".into(),
flag_jsonrpc_hosts: "none".into(), flag_jsonrpc_hosts: "none".into(),
// IPC // IPC
flag_no_ipc: false, flag_no_ipc: false,
flag_ipc_path: "$HOME/.parity/jsonrpc.ipc".into(), flag_ipc_path: "$HOME/.parity/jsonrpc.ipc".into(),
flag_ipc_apis: "web3,eth,net,ethcore,traces,rpc,personal,personal_safe".into(), flag_ipc_apis: "web3,eth,net,parity,parity_accounts,personal,traces,rpc".into(),
// DAPPS // DAPPS
flag_no_dapps: false, flag_no_dapps: false,

View File

@ -107,7 +107,7 @@ API and Console Options:
--jsonrpc-apis APIS Specify the APIs available through the JSONRPC --jsonrpc-apis APIS Specify the APIs available through the JSONRPC
interface. APIS is a comma-delimited list of API interface. APIS is a comma-delimited list of API
name. Possible name are web3, eth, net, personal, name. Possible name are web3, eth, net, personal,
ethcore, ethcore_set, traces, rpc, personal_safe. parity, parity_set, traces, rpc, parity_accounts.
(default: {flag_jsonrpc_apis}). (default: {flag_jsonrpc_apis}).
--jsonrpc-hosts HOSTS List of allowed Host header values. This option will --jsonrpc-hosts HOSTS List of allowed Host header values. This option will
validate the Host header sent by the browser, it validate the Host header sent by the browser, it
@ -284,7 +284,7 @@ Legacy Options:
--geth Run in Geth-compatibility mode. Sets the IPC path --geth Run in Geth-compatibility mode. Sets the IPC path
to be the same as Geth's. Overrides the --ipc-path to be the same as Geth's. Overrides the --ipc-path
and --ipcpath options. Alters RPCs to reflect Geth and --ipcpath options. Alters RPCs to reflect Geth
bugs. bugs. Includes the personal_ RPC by default.
--testnet Geth-compatible testnet mode. Equivalent to --chain --testnet Geth-compatible testnet mode. Equivalent to --chain
testnet --keys-path $HOME/parity/testnet-keys. testnet --keys-path $HOME/parity/testnet-keys.
Overrides the --keys-path option. Overrides the --keys-path option.

View File

@ -509,7 +509,11 @@ impl Configuration {
} }
fn rpc_apis(&self) -> String { fn rpc_apis(&self) -> String {
self.args.flag_rpcapi.clone().unwrap_or(self.args.flag_jsonrpc_apis.clone()) let mut apis = self.args.flag_rpcapi.clone().unwrap_or(self.args.flag_jsonrpc_apis.clone());
if self.args.flag_geth {
apis.push_str(",personal");
}
apis
} }
fn rpc_cors(&self) -> Option<Vec<String>> { fn rpc_cors(&self) -> Option<Vec<String>> {
@ -541,7 +545,13 @@ impl Configuration {
let conf = IpcConfiguration { let conf = IpcConfiguration {
enabled: !(self.args.flag_ipcdisable || self.args.flag_ipc_off || self.args.flag_no_ipc), enabled: !(self.args.flag_ipcdisable || self.args.flag_ipc_off || self.args.flag_no_ipc),
socket_addr: self.ipc_path(), socket_addr: self.ipc_path(),
apis: try!(self.args.flag_ipcapi.clone().unwrap_or(self.args.flag_ipc_apis.clone()).parse()), apis: {
let mut apis = self.args.flag_ipcapi.clone().unwrap_or(self.args.flag_ipc_apis.clone());
if self.args.flag_geth {
apis.push_str("personal");
}
try!(apis.parse())
},
}; };
Ok(conf) Ok(conf)

View File

@ -31,15 +31,25 @@ pub use ethcore_rpc::SignerService;
#[derive(Debug, PartialEq, Clone, Eq, Hash)] #[derive(Debug, PartialEq, Clone, Eq, Hash)]
pub enum Api { pub enum Api {
/// Web3 (Safe)
Web3, Web3,
/// Net (Safe)
Net, Net,
/// Eth (Safe)
Eth, Eth,
PersonalSafe, /// Geth-compatible "personal" API (DEPRECATED; only used in `--geth` mode.)
PersonalAccounts, Personal,
/// Signer - Confirm transactions in Signer (UNSAFE: Passwords, List of transactions)
Signer, Signer,
Ethcore, /// Parity - Custom extensions (Safe)
EthcoreSet, Parity,
/// Parity Accounts extensions (UNSAFE: Passwords, Side Effects (new account))
ParityAccounts,
/// Parity - Set methods (UNSAFE: Side Effects affecting node operation)
ParitySet,
/// Traces (Safe)
Traces, Traces,
/// Rpc (Safe)
Rpc, Rpc,
} }
@ -53,11 +63,11 @@ impl FromStr for Api {
"web3" => Ok(Web3), "web3" => Ok(Web3),
"net" => Ok(Net), "net" => Ok(Net),
"eth" => Ok(Eth), "eth" => Ok(Eth),
"personal" => Ok(PersonalAccounts), "personal" => Ok(Personal),
"personal_safe" => Ok(PersonalSafe),
"signer" => Ok(Signer), "signer" => Ok(Signer),
"ethcore" => Ok(Ethcore), "parity" => Ok(Parity),
"ethcore_set" => Ok(EthcoreSet), "parity_accounts" => Ok(ParityAccounts),
"parity_set" => Ok(ParitySet),
"traces" => Ok(Traces), "traces" => Ok(Traces),
"rpc" => Ok(Rpc), "rpc" => Ok(Rpc),
api => Err(format!("Unknown api: {}", api)) api => Err(format!("Unknown api: {}", api))
@ -119,11 +129,11 @@ fn to_modules(apis: &[Api]) -> BTreeMap<String, String> {
Api::Web3 => ("web3", "1.0"), Api::Web3 => ("web3", "1.0"),
Api::Net => ("net", "1.0"), Api::Net => ("net", "1.0"),
Api::Eth => ("eth", "1.0"), Api::Eth => ("eth", "1.0"),
Api::PersonalSafe => ("personal_safe", "1.0"), Api::Personal => ("personal", "1.0"),
Api::PersonalAccounts => ("personal", "1.0"),
Api::Signer => ("signer", "1.0"), Api::Signer => ("signer", "1.0"),
Api::Ethcore => ("ethcore", "1.0"), Api::Parity => ("parity", "1.0"),
Api::EthcoreSet => ("ethcore_set", "1.0"), Api::ParityAccounts => ("parity_accounts", "1.0"),
Api::ParitySet => ("parity_set", "1.0"),
Api::Traces => ("traces", "1.0"), Api::Traces => ("traces", "1.0"),
Api::Rpc => ("rpc", "1.0"), Api::Rpc => ("rpc", "1.0"),
}; };
@ -134,24 +144,37 @@ fn to_modules(apis: &[Api]) -> BTreeMap<String, String> {
impl ApiSet { impl ApiSet {
pub fn list_apis(&self) -> HashSet<Api> { pub fn list_apis(&self) -> HashSet<Api> {
let mut safe_list = vec![Api::Web3, Api::Net, Api::Eth, Api::Parity, Api::Traces, Api::Rpc]
.into_iter().collect();
match *self { match *self {
ApiSet::List(ref apis) => apis.clone(), ApiSet::List(ref apis) => apis.clone(),
ApiSet::UnsafeContext => { ApiSet::UnsafeContext => safe_list,
vec![Api::Web3, Api::Net, Api::Eth, Api::Ethcore, Api::Traces, Api::Rpc, Api::PersonalSafe]
.into_iter().collect()
},
ApiSet::IpcContext => { ApiSet::IpcContext => {
vec![Api::Web3, Api::Net, Api::Eth, Api::Ethcore, Api::Traces, Api::Rpc, Api::PersonalAccounts, Api::PersonalSafe] safe_list.insert(Api::ParityAccounts);
.into_iter().collect() safe_list
}, },
ApiSet::SafeContext => { ApiSet::SafeContext => {
vec![Api::Web3, Api::Net, Api::Eth, Api::PersonalAccounts, Api::PersonalSafe, Api::Signer, Api::Ethcore, Api::EthcoreSet, Api::Traces, Api::Rpc] safe_list.insert(Api::ParityAccounts);
.into_iter().collect() safe_list.insert(Api::ParitySet);
safe_list.insert(Api::Signer);
safe_list
}, },
} }
} }
} }
macro_rules! add_signing_methods {
($namespace:ident, $server:expr, $deps:expr) => {
let server = &$server;
let deps = &$deps;
if deps.signer_service.is_enabled() {
server.add_delegate($namespace::to_delegate(SigningQueueClient::new(&deps.signer_service, &deps.client, &deps.miner, &deps.secret_store)))
} else {
server.add_delegate($namespace::to_delegate(SigningUnsafeClient::new(&deps.client, &deps.secret_store, &deps.miner)))
}
}
}
pub fn setup_rpc<T: Extendable>(server: T, deps: Arc<Dependencies>, apis: ApiSet) -> T { pub fn setup_rpc<T: Extendable>(server: T, deps: Arc<Dependencies>, apis: ApiSet) -> T {
use ethcore_rpc::v1::*; use ethcore_rpc::v1::*;
@ -183,39 +206,39 @@ pub fn setup_rpc<T: Extendable>(server: T, deps: Arc<Dependencies>, apis: ApiSet
let filter_client = EthFilterClient::new(&deps.client, &deps.miner); let filter_client = EthFilterClient::new(&deps.client, &deps.miner);
server.add_delegate(filter_client.to_delegate()); server.add_delegate(filter_client.to_delegate());
if deps.signer_service.is_enabled() { add_signing_methods!(EthSigning, server, deps);
server.add_delegate(EthSigningQueueClient::new(&deps.signer_service, &deps.client, &deps.miner, &deps.secret_store).to_delegate());
} else {
server.add_delegate(EthSigningUnsafeClient::new(&deps.client, &deps.secret_store, &deps.miner).to_delegate());
}
}, },
Api::PersonalAccounts => { Api::Personal => {
server.add_delegate(PersonalAccountsClient::new(&deps.secret_store, &deps.client, &deps.miner, deps.geth_compatibility).to_delegate()); server.add_delegate(PersonalClient::new(&deps.secret_store, &deps.client, &deps.miner, deps.geth_compatibility).to_delegate());
},
Api::PersonalSafe => {
server.add_delegate(PersonalClient::new(&deps.secret_store, &deps.client).to_delegate());
}, },
Api::Signer => { Api::Signer => {
server.add_delegate(SignerClient::new(&deps.secret_store, &deps.client, &deps.miner, &deps.signer_service).to_delegate()); server.add_delegate(SignerClient::new(&deps.secret_store, &deps.client, &deps.miner, &deps.signer_service).to_delegate());
}, },
Api::Ethcore => { Api::Parity => {
let signer = match deps.signer_service.is_enabled() { let signer = match deps.signer_service.is_enabled() {
true => Some(deps.signer_service.clone()), true => Some(deps.signer_service.clone()),
false => None, false => None,
}; };
server.add_delegate(EthcoreClient::new( server.add_delegate(ParityClient::new(
&deps.client, &deps.client,
&deps.miner, &deps.miner,
&deps.sync, &deps.sync,
&deps.net_service, &deps.net_service,
&deps.secret_store,
deps.logger.clone(), deps.logger.clone(),
deps.settings.clone(), deps.settings.clone(),
signer, signer,
deps.dapps_port, deps.dapps_port,
).to_delegate()) ).to_delegate());
add_signing_methods!(EthSigning, server, deps);
add_signing_methods!(ParitySigning, server, deps);
}, },
Api::EthcoreSet => { Api::ParityAccounts => {
server.add_delegate(EthcoreSetClient::new(&deps.client, &deps.miner, &deps.net_service).to_delegate()) server.add_delegate(ParityAccountsClient::new(&deps.secret_store, &deps.client).to_delegate());
},
Api::ParitySet => {
server.add_delegate(ParitySetClient::new(&deps.client, &deps.miner, &deps.net_service).to_delegate())
}, },
Api::Traces => { Api::Traces => {
server.add_delegate(TracesClient::new(&deps.client, &deps.miner).to_delegate()) server.add_delegate(TracesClient::new(&deps.client, &deps.miner).to_delegate())
@ -238,11 +261,11 @@ mod test {
assert_eq!(Api::Web3, "web3".parse().unwrap()); assert_eq!(Api::Web3, "web3".parse().unwrap());
assert_eq!(Api::Net, "net".parse().unwrap()); assert_eq!(Api::Net, "net".parse().unwrap());
assert_eq!(Api::Eth, "eth".parse().unwrap()); assert_eq!(Api::Eth, "eth".parse().unwrap());
assert_eq!(Api::PersonalAccounts, "personal".parse().unwrap()); assert_eq!(Api::Personal, "personal".parse().unwrap());
assert_eq!(Api::PersonalSafe, "personal_safe".parse().unwrap());
assert_eq!(Api::Signer, "signer".parse().unwrap()); assert_eq!(Api::Signer, "signer".parse().unwrap());
assert_eq!(Api::Ethcore, "ethcore".parse().unwrap()); assert_eq!(Api::Parity, "parity".parse().unwrap());
assert_eq!(Api::EthcoreSet, "ethcore_set".parse().unwrap()); assert_eq!(Api::ParityAccounts, "parity_accounts".parse().unwrap());
assert_eq!(Api::ParitySet, "parity_set".parse().unwrap());
assert_eq!(Api::Traces, "traces".parse().unwrap()); assert_eq!(Api::Traces, "traces".parse().unwrap());
assert_eq!(Api::Rpc, "rpc".parse().unwrap()); assert_eq!(Api::Rpc, "rpc".parse().unwrap());
assert!("rp".parse::<Api>().is_err()); assert!("rp".parse::<Api>().is_err());
@ -260,15 +283,34 @@ mod test {
#[test] #[test]
fn test_api_set_unsafe_context() { fn test_api_set_unsafe_context() {
let expected = vec![Api::Web3, Api::Net, Api::Eth, Api::Ethcore, Api::Traces, Api::Rpc, Api::PersonalSafe] let expected = vec![
.into_iter().collect(); // make sure this list contains only SAFE methods
Api::Web3, Api::Net, Api::Eth, Api::Parity, Api::Traces, Api::Rpc
].into_iter().collect();
assert_eq!(ApiSet::UnsafeContext.list_apis(), expected); assert_eq!(ApiSet::UnsafeContext.list_apis(), expected);
} }
#[test]
fn test_api_set_ipc_context() {
let expected = vec![
// safe
Api::Web3, Api::Net, Api::Eth, Api::Parity, Api::Traces, Api::Rpc,
// semi-safe
Api::ParityAccounts
].into_iter().collect();
assert_eq!(ApiSet::IpcContext.list_apis(), expected);
}
#[test] #[test]
fn test_api_set_safe_context() { fn test_api_set_safe_context() {
let expected = vec![Api::Web3, Api::Net, Api::Eth, Api::PersonalAccounts, Api::PersonalSafe, Api::Signer, Api::Ethcore, Api::EthcoreSet, Api::Traces, Api::Rpc] let expected = vec![
.into_iter().collect(); // safe
Api::Web3, Api::Net, Api::Eth, Api::Parity, Api::Traces, Api::Rpc,
// semi-safe
Api::ParityAccounts,
// Unsafe
Api::ParitySet, Api::Signer,
].into_iter().collect();
assert_eq!(ApiSet::SafeContext.list_apis(), expected); assert_eq!(ApiSet::SafeContext.list_apis(), expected);
} }
} }

View File

@ -27,13 +27,14 @@ macro_rules! take_weak {
mod eth; mod eth;
mod eth_filter; mod eth_filter;
mod eth_signing;
mod ethcore;
mod ethcore_set;
mod net; mod net;
mod parity;
mod parity_accounts;
mod parity_set;
mod personal; mod personal;
mod personal_accounts; mod signer;
mod personal_signer; mod signing;
mod signing_unsafe;
mod rpc; mod rpc;
mod traces; mod traces;
mod web3; mod web3;
@ -41,12 +42,13 @@ mod web3;
pub use self::web3::Web3Client; pub use self::web3::Web3Client;
pub use self::eth::{EthClient, EthClientOptions}; pub use self::eth::{EthClient, EthClientOptions};
pub use self::eth_filter::EthFilterClient; pub use self::eth_filter::EthFilterClient;
pub use self::eth_signing::{EthSigningUnsafeClient, EthSigningQueueClient};
pub use self::net::NetClient; pub use self::net::NetClient;
pub use self::parity::ParityClient;
pub use self::parity_accounts::ParityAccountsClient;
pub use self::parity_set::ParitySetClient;
pub use self::personal::PersonalClient; pub use self::personal::PersonalClient;
pub use self::personal_accounts::PersonalAccountsClient; pub use self::signer::SignerClient;
pub use self::personal_signer::SignerClient; pub use self::signing::SigningQueueClient;
pub use self::ethcore::EthcoreClient; pub use self::signing_unsafe::SigningUnsafeClient;
pub use self::ethcore_set::EthcoreSetClient;
pub use self::traces::TracesClient; pub use self::traces::TracesClient;
pub use self::rpc::RpcClient; pub use self::rpc::RpcClient;

View File

@ -14,16 +14,15 @@
// You should have received a copy of the GNU General Public License // You should have received a copy of the GNU General Public License
// along with Parity. If not, see <http://www.gnu.org/licenses/>. // along with Parity. If not, see <http://www.gnu.org/licenses/>.
//! Ethcore-specific rpc implementation. //! Parity-specific rpc implementation.
use std::{fs, io}; use std::sync::{Arc, Weak};
use std::sync::{mpsc, Arc, Weak};
use std::str::FromStr; use std::str::FromStr;
use std::collections::BTreeMap;
use util::{RotatingLogger, Address, Mutex, sha3}; use util::{RotatingLogger, Address};
use util::misc::version_data; use util::misc::version_data;
use crypto::ecies; use crypto::ecies;
use fetch::{Client as FetchClient, Fetch};
use ethkey::{Brain, Generator}; use ethkey::{Brain, Generator};
use ethstore::random_phrase; use ethstore::random_phrase;
use ethsync::{SyncProvider, ManageNetwork}; use ethsync::{SyncProvider, ManageNetwork};
@ -31,77 +30,57 @@ use ethcore::miner::MinerService;
use ethcore::client::{MiningBlockChainClient}; use ethcore::client::{MiningBlockChainClient};
use ethcore::ids::BlockID; use ethcore::ids::BlockID;
use ethcore::mode::Mode; use ethcore::mode::Mode;
use ethcore::account_provider::AccountProvider;
use jsonrpc_core::Error; use jsonrpc_core::Error;
use v1::traits::Ethcore; use v1::traits::Parity;
use v1::types::{Bytes, U256, H160, H256, H512, Peers, Transaction, RpcSettings, Histogram}; use v1::types::{Bytes, U256, H160, H256, H512, Peers, Transaction, RpcSettings, Histogram};
use v1::helpers::{errors, SigningQueue, SignerService, NetworkSettings}; use v1::helpers::{errors, SigningQueue, SignerService, NetworkSettings};
use v1::helpers::dispatch::DEFAULT_MAC; use v1::helpers::dispatch::DEFAULT_MAC;
use v1::helpers::auto_args::Ready;
/// Ethcore implementation. /// Parity implementation.
pub struct EthcoreClient<C, M, S: ?Sized, F=FetchClient> where pub struct ParityClient<C, M, S: ?Sized> where
C: MiningBlockChainClient, C: MiningBlockChainClient,
M: MinerService, M: MinerService,
S: SyncProvider, S: SyncProvider,
F: Fetch { {
client: Weak<C>, client: Weak<C>,
miner: Weak<M>, miner: Weak<M>,
sync: Weak<S>, sync: Weak<S>,
net: Weak<ManageNetwork>, net: Weak<ManageNetwork>,
accounts: Weak<AccountProvider>,
logger: Arc<RotatingLogger>, logger: Arc<RotatingLogger>,
settings: Arc<NetworkSettings>, settings: Arc<NetworkSettings>,
signer: Option<Arc<SignerService>>, signer: Option<Arc<SignerService>>,
fetch: Mutex<F>,
dapps_port: Option<u16>, dapps_port: Option<u16>,
} }
impl<C, M, S: ?Sized> EthcoreClient<C, M, S> where impl<C, M, S: ?Sized> ParityClient<C, M, S> where
C: MiningBlockChainClient, C: MiningBlockChainClient,
M: MinerService, M: MinerService,
S: SyncProvider, { S: SyncProvider,
/// Creates new `EthcoreClient` with default `Fetch`. {
/// Creates new `ParityClient`.
pub fn new( pub fn new(
client: &Arc<C>, client: &Arc<C>,
miner: &Arc<M>, miner: &Arc<M>,
sync: &Arc<S>, sync: &Arc<S>,
net: &Arc<ManageNetwork>, net: &Arc<ManageNetwork>,
store: &Arc<AccountProvider>,
logger: Arc<RotatingLogger>, logger: Arc<RotatingLogger>,
settings: Arc<NetworkSettings>, settings: Arc<NetworkSettings>,
signer: Option<Arc<SignerService>>, signer: Option<Arc<SignerService>>,
dapps_port: Option<u16>, dapps_port: Option<u16>,
) -> Self { ) -> Self {
Self::with_fetch(client, miner, sync, net, logger, settings, signer, dapps_port) ParityClient {
}
}
impl<C, M, S: ?Sized, F> EthcoreClient<C, M, S, F> where
C: MiningBlockChainClient,
M: MinerService,
S: SyncProvider,
F: Fetch, {
/// Creates new `EthcoreClient` with customizable `Fetch`.
pub fn with_fetch(
client: &Arc<C>,
miner: &Arc<M>,
sync: &Arc<S>,
net: &Arc<ManageNetwork>,
logger: Arc<RotatingLogger>,
settings: Arc<NetworkSettings>,
signer: Option<Arc<SignerService>>,
dapps_port: Option<u16>,
) -> Self {
EthcoreClient {
client: Arc::downgrade(client), client: Arc::downgrade(client),
miner: Arc::downgrade(miner), miner: Arc::downgrade(miner),
sync: Arc::downgrade(sync), sync: Arc::downgrade(sync),
net: Arc::downgrade(net), net: Arc::downgrade(net),
accounts: Arc::downgrade(store),
logger: logger, logger: logger,
settings: settings, settings: settings,
signer: signer, signer: signer,
fetch: Mutex::new(F::default()),
dapps_port: dapps_port, dapps_port: dapps_port,
} }
} }
@ -113,11 +92,10 @@ impl<C, M, S: ?Sized, F> EthcoreClient<C, M, S, F> where
} }
} }
impl<C, M, S: ?Sized, F> Ethcore for EthcoreClient<C, M, S, F> where impl<C, M, S: ?Sized> Parity for ParityClient<C, M, S> where
M: MinerService + 'static, M: MinerService + 'static,
C: MiningBlockChainClient + 'static, C: MiningBlockChainClient + 'static,
S: SyncProvider + 'static, S: SyncProvider + 'static {
F: Fetch + 'static {
fn transactions_limit(&self) -> Result<usize, Error> { fn transactions_limit(&self) -> Result<usize, Error> {
try!(self.active()); try!(self.active());
@ -278,48 +256,6 @@ impl<C, M, S: ?Sized, F> Ethcore for EthcoreClient<C, M, S, F> where
Ok(take_weak!(self.miner).all_transactions().into_iter().map(Into::into).collect::<Vec<_>>()) Ok(take_weak!(self.miner).all_transactions().into_iter().map(Into::into).collect::<Vec<_>>())
} }
fn hash_content(&self, ready: Ready<H256>, url: String) {
let res = self.active();
let hash_content = |result| {
let path = try!(result);
let mut file = io::BufReader::new(try!(fs::File::open(&path)));
// Try to hash
let result = sha3(&mut file);
// Remove file (always)
try!(fs::remove_file(&path));
// Return the result
Ok(try!(result))
};
match res {
Err(e) => ready.ready(Err(e)),
Ok(()) => {
let (tx, rx) = mpsc::channel();
let res = self.fetch.lock().request_async(&url, Default::default(), Box::new(move |result| {
let result = hash_content(result)
.map_err(errors::from_fetch_error)
.map(Into::into);
// Receive ready and invoke with result.
let ready: Ready<H256> = rx.recv().expect(
"recv() fails when `tx` has been dropped, if this closure is invoked `tx` is not dropped (`res == Ok()`); qed"
);
ready.ready(result);
}));
// Either invoke ready right away or transfer it to the closure.
if let Err(e) = res {
ready.ready(Err(errors::from_fetch_error(e)));
} else {
tx.send(ready).expect(
"send() fails when `rx` end is dropped, if `res == Ok()`: `rx` is moved to the closure; qed"
);
}
}
}
}
fn signer_port(&self) -> Result<u16, Error> { fn signer_port(&self) -> Result<u16, Error> {
try!(self.active()); try!(self.active());
@ -361,4 +297,22 @@ impl<C, M, S: ?Sized, F> Ethcore for EthcoreClient<C, M, S, F> where
fn enode(&self) -> Result<String, Error> { fn enode(&self) -> Result<String, Error> {
take_weak!(self.sync).enode().ok_or_else(errors::network_disabled) take_weak!(self.sync).enode().ok_or_else(errors::network_disabled)
} }
fn accounts(&self) -> Result<BTreeMap<String, BTreeMap<String, String>>, Error> {
try!(self.active());
let store = take_weak!(self.accounts);
let info = try!(store.accounts_info().map_err(|e| errors::account("Could not fetch account info.", e)));
let other = store.addresses_info().expect("addresses_info always returns Ok; qed");
Ok(info.into_iter().chain(other.into_iter()).map(|(a, v)| {
let mut m = map![
"name".to_owned() => v.name,
"meta".to_owned() => v.meta
];
if let &Some(ref uuid) = &v.uuid {
m.insert("uuid".to_owned(), format!("{}", uuid));
}
(format!("0x{}", a.hex()), m)
}).collect())
}
} }

View File

@ -16,33 +16,30 @@
//! Account management (personal) rpc implementation //! Account management (personal) rpc implementation
use std::sync::{Arc, Weak}; use std::sync::{Arc, Weak};
use std::collections::BTreeMap;
use util::{Address}; use util::{Address};
use jsonrpc_core::*;
use ethkey::{Brain, Generator}; use ethkey::{Brain, Generator};
use v1::traits::PersonalAccounts;
use v1::types::{H160 as RpcH160, H256 as RpcH256, TransactionRequest};
use v1::helpers::errors;
use v1::helpers::dispatch::sign_and_dispatch;
use ethcore::account_provider::AccountProvider; use ethcore::account_provider::AccountProvider;
use ethcore::client::MiningBlockChainClient; use ethcore::client::MiningBlockChainClient;
use ethcore::miner::MinerService;
use jsonrpc_core::{Value, Error, to_value};
use v1::traits::ParityAccounts;
use v1::types::{H160 as RpcH160, H256 as RpcH256};
use v1::helpers::errors;
/// Account management (personal) rpc implementation. /// Account management (personal) rpc implementation.
pub struct PersonalAccountsClient<C, M> where C: MiningBlockChainClient, M: MinerService { pub struct ParityAccountsClient<C> where C: MiningBlockChainClient {
accounts: Weak<AccountProvider>, accounts: Weak<AccountProvider>,
client: Weak<C>, client: Weak<C>,
miner: Weak<M>,
allow_perm_unlock: bool,
} }
impl<C, M> PersonalAccountsClient<C, M> where C: MiningBlockChainClient, M: MinerService { impl<C> ParityAccountsClient<C> where C: MiningBlockChainClient {
/// Creates new PersonalClient /// Creates new PersonalClient
pub fn new(store: &Arc<AccountProvider>, client: &Arc<C>, miner: &Arc<M>, allow_perm_unlock: bool) -> Self { pub fn new(store: &Arc<AccountProvider>, client: &Arc<C>) -> Self {
PersonalAccountsClient { ParityAccountsClient {
accounts: Arc::downgrade(store), accounts: Arc::downgrade(store),
client: Arc::downgrade(client), client: Arc::downgrade(client),
miner: Arc::downgrade(miner),
allow_perm_unlock: allow_perm_unlock,
} }
} }
@ -53,15 +50,25 @@ impl<C, M> PersonalAccountsClient<C, M> where C: MiningBlockChainClient, M: Mine
} }
} }
impl<C: 'static, M: 'static> PersonalAccounts for PersonalAccountsClient<C, M> where C: MiningBlockChainClient, M: MinerService { impl<C: 'static> ParityAccounts for ParityAccountsClient<C> where C: MiningBlockChainClient {
fn accounts_info(&self) -> Result<BTreeMap<String, Value>, Error> {
fn new_account(&self, pass: String) -> Result<RpcH160, Error> {
try!(self.active()); try!(self.active());
let store = take_weak!(self.accounts); let store = take_weak!(self.accounts);
let info = try!(store.accounts_info().map_err(|e| errors::account("Could not fetch account info.", e)));
let other = store.addresses_info().expect("addresses_info always returns Ok; qed");
store.new_account(&pass) Ok(info.into_iter().chain(other.into_iter()).map(|(a, v)| {
.map(Into::into) let m = map![
.map_err(|e| errors::account("Could not create account.", e)) "name".to_owned() => to_value(&v.name),
"meta".to_owned() => to_value(&v.meta),
"uuid".to_owned() => if let &Some(ref uuid) = &v.uuid {
to_value(uuid)
} else {
Value::Null
}
];
(format!("0x{}", a.hex()), Value::Object(m))
}).collect())
} }
fn new_account_from_phrase(&self, phrase: String, pass: String) -> Result<RpcH160, Error> { fn new_account_from_phrase(&self, phrase: String, pass: String) -> Result<RpcH160, Error> {
@ -92,24 +99,6 @@ impl<C: 'static, M: 'static> PersonalAccounts for PersonalAccountsClient<C, M> w
.map_err(|e| errors::account("Could not create account.", e)) .map_err(|e| errors::account("Could not create account.", e))
} }
fn unlock_account(&self, account: RpcH160, account_pass: String, duration: Option<u64>) -> Result<bool, Error> {
try!(self.active());
let account: Address = account.into();
let store = take_weak!(self.accounts);
let r = match (self.allow_perm_unlock, duration) {
(false, _) => store.unlock_account_temporarily(account, account_pass),
(true, Some(0)) => store.unlock_account_permanently(account, account_pass),
(true, Some(d)) => store.unlock_account_timed(account, account_pass, d as u32 * 1000),
(true, None) => store.unlock_account_timed(account, account_pass, 300_000),
};
match r {
Ok(_) => Ok(true),
// TODO [ToDr] Proper error here?
Err(_) => Ok(false),
}
}
fn test_password(&self, account: RpcH160, password: String) -> Result<bool, Error> { fn test_password(&self, account: RpcH160, password: String) -> Result<bool, Error> {
try!(self.active()); try!(self.active());
let account: Address = account.into(); let account: Address = account.into();
@ -128,18 +117,6 @@ impl<C: 'static, M: 'static> PersonalAccounts for PersonalAccountsClient<C, M> w
.map_err(|e| errors::account("Could not fetch account info.", e)) .map_err(|e| errors::account("Could not fetch account info.", e))
} }
fn sign_and_send_transaction(&self, request: TransactionRequest, password: String) -> Result<RpcH256, Error> {
try!(self.active());
sign_and_dispatch(
&*take_weak!(self.client),
&*take_weak!(self.miner),
&*take_weak!(self.accounts),
request.into(),
Some(password)
)
}
fn set_account_name(&self, addr: RpcH160, name: String) -> Result<bool, Error> { fn set_account_name(&self, addr: RpcH160, name: String) -> Result<bool, Error> {
try!(self.active()); try!(self.active());
let store = take_weak!(self.accounts); let store = take_weak!(self.accounts);
@ -162,6 +139,10 @@ impl<C: 'static, M: 'static> PersonalAccounts for PersonalAccountsClient<C, M> w
Ok(true) Ok(true)
} }
fn set_account_visibility(&self, _address: RpcH160, _dapp: RpcH256, _visible: bool) -> Result<bool, Error> {
Ok(false)
}
fn import_geth_accounts(&self, addresses: Vec<RpcH160>) -> Result<Vec<RpcH160>, Error> { fn import_geth_accounts(&self, addresses: Vec<RpcH160>) -> Result<Vec<RpcH160>, Error> {
let store = take_weak!(self.accounts); let store = take_weak!(self.accounts);

View File

@ -14,36 +14,57 @@
// You should have received a copy of the GNU General Public License // You should have received a copy of the GNU General Public License
// along with Parity. If not, see <http://www.gnu.org/licenses/>. // along with Parity. If not, see <http://www.gnu.org/licenses/>.
/// Ethcore-specific rpc interface for operations altering the settings. /// Parity-specific rpc interface for operations altering the settings.
use std::sync::{Arc, Weak}; use std::{fs, io};
use jsonrpc_core::*; use std::sync::{Arc, Weak, mpsc};
use ethcore::miner::MinerService; use ethcore::miner::MinerService;
use ethcore::client::MiningBlockChainClient; use ethcore::client::MiningBlockChainClient;
use ethcore::mode::Mode; use ethcore::mode::Mode;
use ethsync::ManageNetwork; use ethsync::ManageNetwork;
use v1::helpers::errors; use fetch::{Client as FetchClient, Fetch};
use v1::traits::EthcoreSet; use util::{Mutex, sha3};
use v1::types::{Bytes, H160, U256};
/// Ethcore-specific rpc interface for operations altering the settings. use jsonrpc_core::Error;
pub struct EthcoreSetClient<C, M> where use v1::helpers::auto_args::Ready;
use v1::helpers::errors;
use v1::traits::ParitySet;
use v1::types::{Bytes, H160, H256, U256};
/// Parity-specific rpc interface for operations altering the settings.
pub struct ParitySetClient<C, M, F=FetchClient> where
C: MiningBlockChainClient, C: MiningBlockChainClient,
M: MinerService M: MinerService,
F: Fetch,
{ {
client: Weak<C>, client: Weak<C>,
miner: Weak<M>, miner: Weak<M>,
net: Weak<ManageNetwork>, net: Weak<ManageNetwork>,
fetch: Mutex<F>,
} }
impl<C, M> EthcoreSetClient<C, M> where impl<C, M> ParitySetClient<C, M, FetchClient> where
C: MiningBlockChainClient, C: MiningBlockChainClient,
M: MinerService { M: MinerService
/// Creates new `EthcoreSetClient`. {
/// Creates new `ParitySetClient` with default `FetchClient`.
pub fn new(client: &Arc<C>, miner: &Arc<M>, net: &Arc<ManageNetwork>) -> Self { pub fn new(client: &Arc<C>, miner: &Arc<M>, net: &Arc<ManageNetwork>) -> Self {
EthcoreSetClient { Self::with_fetch(client, miner, net)
}
}
impl<C, M, F> ParitySetClient<C, M, F> where
C: MiningBlockChainClient,
M: MinerService,
F: Fetch,
{
/// Creates new `ParitySetClient` with default `FetchClient`.
pub fn with_fetch(client: &Arc<C>, miner: &Arc<M>, net: &Arc<ManageNetwork>) -> Self {
ParitySetClient {
client: Arc::downgrade(client), client: Arc::downgrade(client),
miner: Arc::downgrade(miner), miner: Arc::downgrade(miner),
net: Arc::downgrade(net), net: Arc::downgrade(net),
fetch: Mutex::new(F::default()),
} }
} }
@ -54,9 +75,11 @@ impl<C, M> EthcoreSetClient<C, M> where
} }
} }
impl<C, M> EthcoreSet for EthcoreSetClient<C, M> where impl<C, M, F> ParitySet for ParitySetClient<C, M, F> where
C: MiningBlockChainClient + 'static, C: MiningBlockChainClient + 'static,
M: MinerService + 'static { M: MinerService + 'static,
F: Fetch + 'static,
{
fn set_min_gas_price(&self, gas_price: U256) -> Result<bool, Error> { fn set_min_gas_price(&self, gas_price: U256) -> Result<bool, Error> {
try!(self.active()); try!(self.active());
@ -159,4 +182,46 @@ impl<C, M> EthcoreSet for EthcoreSetClient<C, M> where
}); });
Ok(true) Ok(true)
} }
fn hash_content(&self, ready: Ready<H256>, url: String) {
let res = self.active();
let hash_content = |result| {
let path = try!(result);
let mut file = io::BufReader::new(try!(fs::File::open(&path)));
// Try to hash
let result = sha3(&mut file);
// Remove file (always)
try!(fs::remove_file(&path));
// Return the result
Ok(try!(result))
};
match res {
Err(e) => ready.ready(Err(e)),
Ok(()) => {
let (tx, rx) = mpsc::channel();
let res = self.fetch.lock().request_async(&url, Default::default(), Box::new(move |result| {
let result = hash_content(result)
.map_err(errors::from_fetch_error)
.map(Into::into);
// Receive ready and invoke with result.
let ready: Ready<H256> = rx.recv().expect(
"recv() fails when `tx` has been dropped, if this closure is invoked `tx` is not dropped (`res == Ok()`); qed"
);
ready.ready(result);
}));
// Either invoke ready right away or transfer it to the closure.
if let Err(e) = res {
ready.ready(Err(errors::from_fetch_error(e)));
} else {
tx.send(ready).expect(
"send() fails when `rx` end is dropped, if `res == Ok()`: `rx` is moved to the closure; qed"
);
}
}
}
}
} }

View File

@ -16,26 +16,34 @@
//! Account management (personal) rpc implementation //! Account management (personal) rpc implementation
use std::sync::{Arc, Weak}; use std::sync::{Arc, Weak};
use std::collections::{BTreeMap};
use jsonrpc_core::*;
use v1::traits::Personal;
use v1::types::{H160 as RpcH160};
use v1::helpers::errors;
use ethcore::account_provider::AccountProvider; use ethcore::account_provider::AccountProvider;
use ethcore::client::MiningBlockChainClient; use ethcore::client::MiningBlockChainClient;
use ethcore::miner::MinerService;
use util::Address;
use jsonrpc_core::Error;
use v1::traits::Personal;
use v1::types::{H160 as RpcH160, H256 as RpcH256, TransactionRequest};
use v1::helpers::errors;
use v1::helpers::dispatch::sign_and_dispatch;
/// Account management (personal) rpc implementation. /// Account management (personal) rpc implementation.
pub struct PersonalClient<C> where C: MiningBlockChainClient { pub struct PersonalClient<C, M> where C: MiningBlockChainClient, M: MinerService {
accounts: Weak<AccountProvider>, accounts: Weak<AccountProvider>,
client: Weak<C>, client: Weak<C>,
miner: Weak<M>,
allow_perm_unlock: bool,
} }
impl<C> PersonalClient<C> where C: MiningBlockChainClient { impl<C, M> PersonalClient<C, M> where C: MiningBlockChainClient, M: MinerService {
/// Creates new PersonalClient /// Creates new PersonalClient
pub fn new(store: &Arc<AccountProvider>, client: &Arc<C>) -> Self { pub fn new(store: &Arc<AccountProvider>, client: &Arc<C>, miner: &Arc<M>, allow_perm_unlock: bool) -> Self {
PersonalClient { PersonalClient {
accounts: Arc::downgrade(store), accounts: Arc::downgrade(store),
client: Arc::downgrade(client), client: Arc::downgrade(client),
miner: Arc::downgrade(miner),
allow_perm_unlock: allow_perm_unlock,
} }
} }
@ -46,8 +54,7 @@ impl<C> PersonalClient<C> where C: MiningBlockChainClient {
} }
} }
impl<C: 'static> Personal for PersonalClient<C> where C: MiningBlockChainClient { impl<C: 'static, M: 'static> Personal for PersonalClient<C, M> where C: MiningBlockChainClient, M: MinerService {
fn accounts(&self) -> Result<Vec<RpcH160>, Error> { fn accounts(&self) -> Result<Vec<RpcH160>, Error> {
try!(self.active()); try!(self.active());
@ -56,23 +63,42 @@ impl<C: 'static> Personal for PersonalClient<C> where C: MiningBlockChainClient
Ok(accounts.into_iter().map(Into::into).collect::<Vec<RpcH160>>()) Ok(accounts.into_iter().map(Into::into).collect::<Vec<RpcH160>>())
} }
fn accounts_info(&self) -> Result<BTreeMap<String, Value>, Error> { fn new_account(&self, pass: String) -> Result<RpcH160, Error> {
try!(self.active()); try!(self.active());
let store = take_weak!(self.accounts); let store = take_weak!(self.accounts);
let info = try!(store.accounts_info().map_err(|e| errors::account("Could not fetch account info.", e)));
let other = store.addresses_info().expect("addresses_info always returns Ok; qed");
Ok(info.into_iter().chain(other.into_iter()).map(|(a, v)| { store.new_account(&pass)
let m = map![ .map(Into::into)
"name".to_owned() => to_value(&v.name), .map_err(|e| errors::account("Could not create account.", e))
"meta".to_owned() => to_value(&v.meta), }
"uuid".to_owned() => if let &Some(ref uuid) = &v.uuid {
to_value(uuid) fn unlock_account(&self, account: RpcH160, account_pass: String, duration: Option<u64>) -> Result<bool, Error> {
} else { try!(self.active());
Value::Null let account: Address = account.into();
} let store = take_weak!(self.accounts);
];
(format!("0x{}", a.hex()), Value::Object(m)) let r = match (self.allow_perm_unlock, duration) {
}).collect()) (false, _) => store.unlock_account_temporarily(account, account_pass),
(true, Some(0)) => store.unlock_account_permanently(account, account_pass),
(true, Some(d)) => store.unlock_account_timed(account, account_pass, d as u32 * 1000),
(true, None) => store.unlock_account_timed(account, account_pass, 300_000),
};
match r {
Ok(_) => Ok(true),
// TODO [ToDr] Proper error here?
Err(_) => Ok(false),
}
}
fn sign_and_send_transaction(&self, request: TransactionRequest, password: String) -> Result<RpcH256, Error> {
try!(self.active());
sign_and_dispatch(
&*take_weak!(self.client),
&*take_weak!(self.miner),
&*take_weak!(self.accounts),
request.into(),
Some(password)
)
} }
} }

View File

@ -14,14 +14,14 @@
// You should have received a copy of the GNU General Public License // You should have received a copy of the GNU General Public License
// along with Parity. If not, see <http://www.gnu.org/licenses/>. // along with Parity. If not, see <http://www.gnu.org/licenses/>.
//! Transactions Confirmations (personal) rpc implementation //! Transactions Confirmations rpc implementation
use std::sync::{Arc, Weak}; use std::sync::{Arc, Weak};
use jsonrpc_core::*; use jsonrpc_core::*;
use ethcore::account_provider::AccountProvider; use ethcore::account_provider::AccountProvider;
use ethcore::client::MiningBlockChainClient; use ethcore::client::MiningBlockChainClient;
use ethcore::miner::MinerService; use ethcore::miner::MinerService;
use v1::traits::PersonalSigner; use v1::traits::Signer;
use v1::types::{TransactionModification, ConfirmationRequest, U256}; use v1::types::{TransactionModification, ConfirmationRequest, U256};
use v1::helpers::{errors, SignerService, SigningQueue, ConfirmationPayload}; use v1::helpers::{errors, SignerService, SigningQueue, ConfirmationPayload};
use v1::helpers::dispatch::{sign_and_dispatch, sign, decrypt}; use v1::helpers::dispatch::{sign_and_dispatch, sign, decrypt};
@ -58,7 +58,7 @@ impl<C: 'static, M: 'static> SignerClient<C, M> where C: MiningBlockChainClient,
} }
} }
impl<C: 'static, M: 'static> PersonalSigner for SignerClient<C, M> where C: MiningBlockChainClient, M: MinerService { impl<C: 'static, M: 'static> Signer for SignerClient<C, M> where C: MiningBlockChainClient, M: MinerService {
fn requests_to_confirm(&self) -> Result<Vec<ConfirmationRequest>, Error> { fn requests_to_confirm(&self) -> Result<Vec<ConfirmationRequest>, Error> {
try!(self.active()); try!(self.active());

View File

@ -14,43 +14,22 @@
// You should have received a copy of the GNU General Public License // You should have received a copy of the GNU General Public License
// along with Parity. If not, see <http://www.gnu.org/licenses/>. // along with Parity. If not, see <http://www.gnu.org/licenses/>.
//! Eth Signing RPC implementation. //! Signing RPC implementation.
use std::sync::{Arc, Weak}; use std::sync::{Arc, Weak};
use jsonrpc_core::*;
use ethcore::account_provider::AccountProvider;
use ethcore::miner::MinerService; use ethcore::miner::MinerService;
use ethcore::client::MiningBlockChainClient; use ethcore::client::MiningBlockChainClient;
use util::{U256, Address, H256, Mutex};
use transient_hashmap::TransientHashMap; use transient_hashmap::TransientHashMap;
use ethcore::account_provider::AccountProvider; use util::{U256, Address, H256, Mutex};
use jsonrpc_core::*;
use v1::helpers::{errors, SigningQueue, ConfirmationPromise, ConfirmationResult, ConfirmationPayload, TransactionRequest as TRequest, FilledTransactionRequest as FilledRequest, SignerService}; use v1::helpers::{errors, SigningQueue, ConfirmationPromise, ConfirmationResult, ConfirmationPayload, TransactionRequest as TRequest, FilledTransactionRequest as FilledRequest, SignerService};
use v1::helpers::dispatch::{default_gas_price, sign_and_dispatch, sign, decrypt}; use v1::helpers::dispatch::{default_gas_price, sign_and_dispatch, sign, decrypt};
use v1::traits::EthSigning; use v1::traits::{EthSigning, ParitySigning};
use v1::types::{TransactionRequest, H160 as RpcH160, H256 as RpcH256, U256 as RpcU256, Bytes as RpcBytes}; use v1::types::{TransactionRequest, H160 as RpcH160, H256 as RpcH256, U256 as RpcU256, Bytes as RpcBytes};
fn fill_optional_fields<C, M>(request: TRequest, client: &C, miner: &M) -> FilledRequest
where C: MiningBlockChainClient, M: MinerService {
FilledRequest {
from: request.from,
to: request.to,
nonce: request.nonce,
gas_price: request.gas_price.unwrap_or_else(|| default_gas_price(client, miner)),
gas: request.gas.unwrap_or_else(|| miner.sensible_gas_limit()),
value: request.value.unwrap_or_else(|| 0.into()),
data: request.data.unwrap_or_else(Vec::new),
}
}
/// Implementation of functions that require signing when no trusted signer is used.
pub struct EthSigningQueueClient<C, M> where C: MiningBlockChainClient, M: MinerService {
signer: Weak<SignerService>,
accounts: Weak<AccountProvider>,
client: Weak<C>,
miner: Weak<M>,
pending: Mutex<TransientHashMap<U256, ConfirmationPromise>>,
}
const MAX_PENDING_DURATION: u64 = 60 * 60; const MAX_PENDING_DURATION: u64 = 60 * 60;
pub enum DispatchResult { pub enum DispatchResult {
@ -58,10 +37,23 @@ pub enum DispatchResult {
Value(Value), Value(Value),
} }
impl<C, M> EthSigningQueueClient<C, M> where C: MiningBlockChainClient, M: MinerService { /// Implementation of functions that require signing when no trusted signer is used.
pub struct SigningQueueClient<C, M> where C: MiningBlockChainClient, M: MinerService {
signer: Weak<SignerService>,
accounts: Weak<AccountProvider>,
client: Weak<C>,
miner: Weak<M>,
pending: Mutex<TransientHashMap<U256, ConfirmationPromise>>,
}
impl<C, M> SigningQueueClient<C, M> where
C: MiningBlockChainClient,
M: MinerService,
{
/// Creates a new signing queue client given shared signing queue. /// Creates a new signing queue client given shared signing queue.
pub fn new(signer: &Arc<SignerService>, client: &Arc<C>, miner: &Arc<M>, accounts: &Arc<AccountProvider>) -> Self { pub fn new(signer: &Arc<SignerService>, client: &Arc<C>, miner: &Arc<M>, accounts: &Arc<AccountProvider>) -> Self {
EthSigningQueueClient { SigningQueueClient {
signer: Arc::downgrade(signer), signer: Arc::downgrade(signer),
accounts: Arc::downgrade(accounts), accounts: Arc::downgrade(accounts),
client: Arc::downgrade(client), client: Arc::downgrade(client),
@ -132,10 +124,10 @@ impl<C, M> EthSigningQueueClient<C, M> where C: MiningBlockChainClient, M: Miner
} }
} }
impl<C, M> EthSigning for EthSigningQueueClient<C, M> impl<C: 'static, M: 'static> ParitySigning for SigningQueueClient<C, M> where
where C: MiningBlockChainClient + 'static, M: MinerService + 'static C: MiningBlockChainClient,
M: MinerService,
{ {
fn post_sign(&self, params: Params) -> Result<Value, Error> { fn post_sign(&self, params: Params) -> Result<Value, Error> {
try!(self.active()); try!(self.active());
self.dispatch_sign(params).map(|result| match result { self.dispatch_sign(params).map(|result| match result {
@ -178,16 +170,6 @@ impl<C, M> EthSigning for EthSigningQueueClient<C, M>
}) })
} }
fn sign(&self, params: Params, ready: Ready) {
let res = self.active().and_then(|_| self.dispatch_sign(params));
self.handle_dispatch(res, ready);
}
fn send_transaction(&self, params: Params, ready: Ready) {
let res = self.active().and_then(|_| self.dispatch_transaction(params));
self.handle_dispatch(res, ready);
}
fn decrypt_message(&self, params: Params, ready: Ready) { fn decrypt_message(&self, params: Params, ready: Ready) {
let res = self.active() let res = self.active()
.and_then(|_| from_params::<(RpcH160, RpcBytes)>(params)) .and_then(|_| from_params::<(RpcH160, RpcBytes)>(params))
@ -205,76 +187,30 @@ impl<C, M> EthSigning for EthSigningQueueClient<C, M>
} }
} }
/// Implementation of functions that require signing when no trusted signer is used. impl<C: 'static, M: 'static> EthSigning for SigningQueueClient<C, M> where
pub struct EthSigningUnsafeClient<C, M> where
C: MiningBlockChainClient, C: MiningBlockChainClient,
M: MinerService { M: MinerService,
client: Weak<C>, {
accounts: Weak<AccountProvider>,
miner: Weak<M>,
}
impl<C, M> EthSigningUnsafeClient<C, M> where
C: MiningBlockChainClient,
M: MinerService {
/// Creates new EthClient.
pub fn new(client: &Arc<C>, accounts: &Arc<AccountProvider>, miner: &Arc<M>)
-> Self {
EthSigningUnsafeClient {
client: Arc::downgrade(client),
miner: Arc::downgrade(miner),
accounts: Arc::downgrade(accounts),
}
}
fn active(&self) -> Result<(), Error> {
// TODO: only call every 30s at most.
take_weak!(self.client).keep_alive();
Ok(())
}
}
impl<C, M> EthSigning for EthSigningUnsafeClient<C, M> where
C: MiningBlockChainClient + 'static,
M: MinerService + 'static {
fn sign(&self, params: Params, ready: Ready) { fn sign(&self, params: Params, ready: Ready) {
ready.ready(self.active() let res = self.active().and_then(|_| self.dispatch_sign(params));
.and_then(|_| from_params::<(RpcH160, RpcH256)>(params)) self.handle_dispatch(res, ready);
.and_then(|(address, msg)| {
sign(&*take_weak!(self.accounts), address.into(), None, msg.into())
}))
} }
fn send_transaction(&self, params: Params, ready: Ready) { fn send_transaction(&self, params: Params, ready: Ready) {
ready.ready(self.active() let res = self.active().and_then(|_| self.dispatch_transaction(params));
.and_then(|_| from_params::<(TransactionRequest, )>(params)) self.handle_dispatch(res, ready);
.and_then(|(request, )| { }
sign_and_dispatch(&*take_weak!(self.client), &*take_weak!(self.miner), &*take_weak!(self.accounts), request.into(), None).map(to_value) }
}))
} fn fill_optional_fields<C, M>(request: TRequest, client: &C, miner: &M) -> FilledRequest
where C: MiningBlockChainClient, M: MinerService {
fn decrypt_message(&self, params: Params, ready: Ready) { FilledRequest {
ready.ready(self.active() from: request.from,
.and_then(|_| from_params::<(RpcH160, RpcBytes)>(params)) to: request.to,
.and_then(|(address, ciphertext)| { nonce: request.nonce,
decrypt(&*take_weak!(self.accounts), address.into(), None, ciphertext.0) gas_price: request.gas_price.unwrap_or_else(|| default_gas_price(client, miner)),
})) gas: request.gas.unwrap_or_else(|| miner.sensible_gas_limit()),
} value: request.value.unwrap_or_else(|| 0.into()),
data: request.data.unwrap_or_else(Vec::new),
fn post_sign(&self, _: Params) -> Result<Value, Error> {
// We don't support this in non-signer mode.
Err(errors::signer_disabled())
}
fn post_transaction(&self, _: Params) -> Result<Value, Error> {
// We don't support this in non-signer mode.
Err(errors::signer_disabled())
}
fn check_request(&self, _: Params) -> Result<Value, Error> {
// We don't support this in non-signer mode.
Err(errors::signer_disabled())
} }
} }

View File

@ -0,0 +1,110 @@
// Copyright 2015, 2016 Ethcore (UK) Ltd.
// This file is part of Parity.
// Parity is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
// Parity 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 General Public License for more details.
// You should have received a copy of the GNU General Public License
// along with Parity. If not, see <http://www.gnu.org/licenses/>.
//! Unsafe Signing RPC implementation.
use std::sync::{Arc, Weak};
use ethcore::account_provider::AccountProvider;
use ethcore::miner::MinerService;
use ethcore::client::MiningBlockChainClient;
use jsonrpc_core::*;
use v1::helpers::errors;
use v1::helpers::dispatch::{sign_and_dispatch, sign, decrypt};
use v1::traits::{EthSigning, ParitySigning};
use v1::types::{TransactionRequest, H160 as RpcH160, H256 as RpcH256, Bytes as RpcBytes};
/// Implementation of functions that require signing when no trusted signer is used.
pub struct SigningUnsafeClient<C, M> where
C: MiningBlockChainClient,
M: MinerService,
{
accounts: Weak<AccountProvider>,
client: Weak<C>,
miner: Weak<M>,
}
impl<C, M> SigningUnsafeClient<C, M> where
C: MiningBlockChainClient,
M: MinerService,
{
/// Creates new SigningUnsafeClient.
pub fn new(client: &Arc<C>, accounts: &Arc<AccountProvider>, miner: &Arc<M>)
-> Self {
SigningUnsafeClient {
client: Arc::downgrade(client),
miner: Arc::downgrade(miner),
accounts: Arc::downgrade(accounts),
}
}
fn active(&self) -> Result<(), Error> {
// TODO: only call every 30s at most.
take_weak!(self.client).keep_alive();
Ok(())
}
}
impl<C: 'static, M: 'static> EthSigning for SigningUnsafeClient<C, M> where
C: MiningBlockChainClient,
M: MinerService,
{
fn sign(&self, params: Params, ready: Ready) {
ready.ready(self.active()
.and_then(|_| from_params::<(RpcH160, RpcH256)>(params))
.and_then(|(address, msg)| {
sign(&*take_weak!(self.accounts), address.into(), None, msg.into())
}))
}
fn send_transaction(&self, params: Params, ready: Ready) {
ready.ready(self.active()
.and_then(|_| from_params::<(TransactionRequest, )>(params))
.and_then(|(request, )| {
sign_and_dispatch(&*take_weak!(self.client), &*take_weak!(self.miner), &*take_weak!(self.accounts), request.into(), None).map(to_value)
}))
}
}
impl<C: 'static, M: 'static> ParitySigning for SigningUnsafeClient<C, M> where
C: MiningBlockChainClient,
M: MinerService,
{
fn decrypt_message(&self, params: Params, ready: Ready) {
ready.ready(self.active()
.and_then(|_| from_params::<(RpcH160, RpcBytes)>(params))
.and_then(|(address, ciphertext)| {
decrypt(&*take_weak!(self.accounts), address.into(), None, ciphertext.0)
}))
}
fn post_sign(&self, _: Params) -> Result<Value, Error> {
// We don't support this in non-signer mode.
Err(errors::signer_disabled())
}
fn post_transaction(&self, _: Params) -> Result<Value, Error> {
// We don't support this in non-signer mode.
Err(errors::signer_disabled())
}
fn check_request(&self, _: Params) -> Result<Value, Error> {
// We don't support this in non-signer mode.
Err(errors::signer_disabled())
}
}

View File

@ -26,6 +26,6 @@ pub mod traits;
pub mod tests; pub mod tests;
pub mod types; pub mod types;
pub use self::traits::{Web3, Eth, EthFilter, EthSigning, Personal, PersonalAccounts, PersonalSigner, Net, Ethcore, EthcoreSet, Traces, Rpc}; pub use self::traits::{Web3, Eth, EthFilter, EthSigning, Net, Parity, ParityAccounts, ParitySet, ParitySigning, Signer, Personal, Traces, Rpc};
pub use self::impls::*; pub use self::impls::*;
pub use self::helpers::{SigningQueue, SignerService, ConfirmationsQueue, NetworkSettings, block_import}; pub use self::helpers::{SigningQueue, SignerService, ConfirmationsQueue, NetworkSettings, block_import};

View File

@ -33,7 +33,7 @@ use util::{U256, H256, Uint, Address};
use jsonrpc_core::IoHandler; use jsonrpc_core::IoHandler;
use ethjson::blockchain::BlockChain; use ethjson::blockchain::BlockChain;
use v1::impls::{EthClient, EthSigningUnsafeClient}; use v1::impls::{EthClient, SigningUnsafeClient};
use v1::types::U256 as NU256; use v1::types::U256 as NU256;
use v1::traits::eth::Eth; use v1::traits::eth::Eth;
use v1::traits::eth_signing::EthSigning; use v1::traits::eth_signing::EthSigning;
@ -140,7 +140,7 @@ impl EthTester {
&external_miner, &external_miner,
Default::default(), Default::default(),
); );
let eth_sign = EthSigningUnsafeClient::new( let eth_sign = SigningUnsafeClient::new(
&client, &client,
&account_provider, &account_provider,
&miner_service &miner_service

View File

@ -27,7 +27,7 @@ use ethcore::receipt::LocalizedReceipt;
use ethcore::transaction::{Transaction, Action}; use ethcore::transaction::{Transaction, Action};
use ethcore::miner::{ExternalMiner, MinerService}; use ethcore::miner::{ExternalMiner, MinerService};
use ethsync::SyncState; use ethsync::SyncState;
use v1::{Eth, EthClient, EthClientOptions, EthFilter, EthFilterClient, EthSigning, EthSigningUnsafeClient}; use v1::{Eth, EthClient, EthClientOptions, EthFilter, EthFilterClient, EthSigning, SigningUnsafeClient};
use v1::tests::helpers::{TestSyncProvider, Config, TestMinerService, TestSnapshotService}; use v1::tests::helpers::{TestSyncProvider, Config, TestMinerService, TestSnapshotService};
use rustc_serialize::hex::ToHex; use rustc_serialize::hex::ToHex;
use time::get_time; use time::get_time;
@ -83,7 +83,7 @@ impl EthTester {
let external_miner = Arc::new(ExternalMiner::new(hashrates.clone())); let external_miner = Arc::new(ExternalMiner::new(hashrates.clone()));
let eth = EthClient::new(&client, &snapshot, &sync, &ap, &miner, &external_miner, options).to_delegate(); let eth = EthClient::new(&client, &snapshot, &sync, &ap, &miner, &external_miner, options).to_delegate();
let filter = EthFilterClient::new(&client, &miner).to_delegate(); let filter = EthFilterClient::new(&client, &miner).to_delegate();
let sign = EthSigningUnsafeClient::new(&client, &ap, &miner).to_delegate(); let sign = SigningUnsafeClient::new(&client, &ap, &miner).to_delegate();
let io = IoHandler::new(); let io = IoHandler::new();
io.add_delegate(eth); io.add_delegate(eth);
io.add_delegate(sign); io.add_delegate(sign);

View File

@ -18,12 +18,13 @@
//! method calls properly. //! method calls properly.
mod eth; mod eth;
mod eth_signing;
mod net; mod net;
mod web3; mod web3;
mod personal; mod personal;
mod personal_signer; mod parity;
mod ethcore; mod parity_accounts;
mod ethcore_set; mod parity_set;
mod rpc; mod rpc;
mod signer;
mod signing;
mod manage_network; mod manage_network;

View File

@ -16,19 +16,19 @@
use std::sync::Arc; use std::sync::Arc;
use util::log::RotatingLogger; use util::log::RotatingLogger;
use util::{Address}; use util::Address;
use ethsync::ManageNetwork; use ethsync::ManageNetwork;
use ethcore::client::{TestBlockChainClient}; use ethcore::client::{TestBlockChainClient};
use ethcore::account_provider::AccountProvider;
use ethstore::ethkey::{Generator, Random}; use ethstore::ethkey::{Generator, Random};
use jsonrpc_core::IoHandler; use jsonrpc_core::IoHandler;
use v1::{Ethcore, EthcoreClient}; use v1::{Parity, ParityClient};
use v1::helpers::{SignerService, NetworkSettings}; use v1::helpers::{SignerService, NetworkSettings};
use v1::tests::helpers::{TestSyncProvider, Config, TestMinerService, TestFetch}; use v1::tests::helpers::{TestSyncProvider, Config, TestMinerService};
use super::manage_network::TestManageNetwork; use super::manage_network::TestManageNetwork;
pub type TestParityClient = ParityClient<TestBlockChainClient, TestMinerService, TestSyncProvider>;
pub type TestEthcoreClient = EthcoreClient<TestBlockChainClient, TestMinerService, TestSyncProvider, TestFetch>;
pub struct Dependencies { pub struct Dependencies {
pub miner: Arc<TestMinerService>, pub miner: Arc<TestMinerService>,
@ -37,6 +37,7 @@ pub struct Dependencies {
pub logger: Arc<RotatingLogger>, pub logger: Arc<RotatingLogger>,
pub settings: Arc<NetworkSettings>, pub settings: Arc<NetworkSettings>,
pub network: Arc<ManageNetwork>, pub network: Arc<ManageNetwork>,
pub accounts: Arc<AccountProvider>,
pub dapps_port: Option<u16>, pub dapps_port: Option<u16>,
} }
@ -59,16 +60,18 @@ impl Dependencies {
rpc_port: 8545, rpc_port: 8545,
}), }),
network: Arc::new(TestManageNetwork), network: Arc::new(TestManageNetwork),
accounts: Arc::new(AccountProvider::transient_provider()),
dapps_port: Some(18080), dapps_port: Some(18080),
} }
} }
pub fn client(&self, signer: Option<Arc<SignerService>>) -> TestEthcoreClient { pub fn client(&self, signer: Option<Arc<SignerService>>) -> TestParityClient {
EthcoreClient::with_fetch( ParityClient::new(
&self.client, &self.client,
&self.miner, &self.miner,
&self.sync, &self.sync,
&self.network, &self.network,
&self.accounts,
self.logger.clone(), self.logger.clone(),
self.settings.clone(), self.settings.clone(),
signer, signer,
@ -90,105 +93,105 @@ impl Dependencies {
} }
#[test] #[test]
fn rpc_ethcore_extra_data() { fn rpc_parity_extra_data() {
let deps = Dependencies::new(); let deps = Dependencies::new();
let io = deps.default_client(); let io = deps.default_client();
let request = r#"{"jsonrpc": "2.0", "method": "ethcore_extraData", "params": [], "id": 1}"#; let request = r#"{"jsonrpc": "2.0", "method": "parity_extraData", "params": [], "id": 1}"#;
let response = r#"{"jsonrpc":"2.0","result":"0x01020304","id":1}"#; let response = r#"{"jsonrpc":"2.0","result":"0x01020304","id":1}"#;
assert_eq!(io.handle_request_sync(request), Some(response.to_owned())); assert_eq!(io.handle_request_sync(request), Some(response.to_owned()));
} }
#[test] #[test]
fn rpc_ethcore_default_extra_data() { fn rpc_parity_default_extra_data() {
use util::misc; use util::misc;
use util::ToPretty; use util::ToPretty;
let deps = Dependencies::new(); let deps = Dependencies::new();
let io = deps.default_client(); let io = deps.default_client();
let request = r#"{"jsonrpc": "2.0", "method": "ethcore_defaultExtraData", "params": [], "id": 1}"#; let request = r#"{"jsonrpc": "2.0", "method": "parity_defaultExtraData", "params": [], "id": 1}"#;
let response = format!(r#"{{"jsonrpc":"2.0","result":"0x{}","id":1}}"#, misc::version_data().to_hex()); let response = format!(r#"{{"jsonrpc":"2.0","result":"0x{}","id":1}}"#, misc::version_data().to_hex());
assert_eq!(io.handle_request_sync(request), Some(response)); assert_eq!(io.handle_request_sync(request), Some(response));
} }
#[test] #[test]
fn rpc_ethcore_gas_floor_target() { fn rpc_parity_gas_floor_target() {
let deps = Dependencies::new(); let deps = Dependencies::new();
let io = deps.default_client(); let io = deps.default_client();
let request = r#"{"jsonrpc": "2.0", "method": "ethcore_gasFloorTarget", "params": [], "id": 1}"#; let request = r#"{"jsonrpc": "2.0", "method": "parity_gasFloorTarget", "params": [], "id": 1}"#;
let response = r#"{"jsonrpc":"2.0","result":"0x3039","id":1}"#; let response = r#"{"jsonrpc":"2.0","result":"0x3039","id":1}"#;
assert_eq!(io.handle_request_sync(request), Some(response.to_owned())); assert_eq!(io.handle_request_sync(request), Some(response.to_owned()));
} }
#[test] #[test]
fn rpc_ethcore_min_gas_price() { fn rpc_parity_min_gas_price() {
let deps = Dependencies::new(); let deps = Dependencies::new();
let io = deps.default_client(); let io = deps.default_client();
let request = r#"{"jsonrpc": "2.0", "method": "ethcore_minGasPrice", "params": [], "id": 1}"#; let request = r#"{"jsonrpc": "2.0", "method": "parity_minGasPrice", "params": [], "id": 1}"#;
let response = r#"{"jsonrpc":"2.0","result":"0x1312d00","id":1}"#; let response = r#"{"jsonrpc":"2.0","result":"0x1312d00","id":1}"#;
assert_eq!(io.handle_request_sync(request), Some(response.to_owned())); assert_eq!(io.handle_request_sync(request), Some(response.to_owned()));
} }
#[test] #[test]
fn rpc_ethcore_dev_logs() { fn rpc_parity_dev_logs() {
let deps = Dependencies::new(); let deps = Dependencies::new();
deps.logger.append("a".to_owned()); deps.logger.append("a".to_owned());
deps.logger.append("b".to_owned()); deps.logger.append("b".to_owned());
let io = deps.default_client(); let io = deps.default_client();
let request = r#"{"jsonrpc": "2.0", "method": "ethcore_devLogs", "params":[], "id": 1}"#; let request = r#"{"jsonrpc": "2.0", "method": "parity_devLogs", "params":[], "id": 1}"#;
let response = r#"{"jsonrpc":"2.0","result":["b","a"],"id":1}"#; let response = r#"{"jsonrpc":"2.0","result":["b","a"],"id":1}"#;
assert_eq!(io.handle_request_sync(request), Some(response.to_owned())); assert_eq!(io.handle_request_sync(request), Some(response.to_owned()));
} }
#[test] #[test]
fn rpc_ethcore_dev_logs_levels() { fn rpc_parity_dev_logs_levels() {
let deps = Dependencies::new(); let deps = Dependencies::new();
let io = deps.default_client(); let io = deps.default_client();
let request = r#"{"jsonrpc": "2.0", "method": "ethcore_devLogsLevels", "params":[], "id": 1}"#; let request = r#"{"jsonrpc": "2.0", "method": "parity_devLogsLevels", "params":[], "id": 1}"#;
let response = r#"{"jsonrpc":"2.0","result":"rpc=trace","id":1}"#; let response = r#"{"jsonrpc":"2.0","result":"rpc=trace","id":1}"#;
assert_eq!(io.handle_request_sync(request), Some(response.to_owned())); assert_eq!(io.handle_request_sync(request), Some(response.to_owned()));
} }
#[test] #[test]
fn rpc_ethcore_transactions_limit() { fn rpc_parity_transactions_limit() {
let deps = Dependencies::new(); let deps = Dependencies::new();
let io = deps.default_client(); let io = deps.default_client();
let request = r#"{"jsonrpc": "2.0", "method": "ethcore_transactionsLimit", "params":[], "id": 1}"#; let request = r#"{"jsonrpc": "2.0", "method": "parity_transactionsLimit", "params":[], "id": 1}"#;
let response = r#"{"jsonrpc":"2.0","result":1024,"id":1}"#; let response = r#"{"jsonrpc":"2.0","result":1024,"id":1}"#;
assert_eq!(io.handle_request_sync(request), Some(response.to_owned())); assert_eq!(io.handle_request_sync(request), Some(response.to_owned()));
} }
#[test] #[test]
fn rpc_ethcore_net_chain() { fn rpc_parity_net_chain() {
let deps = Dependencies::new(); let deps = Dependencies::new();
let io = deps.default_client(); let io = deps.default_client();
let request = r#"{"jsonrpc": "2.0", "method": "ethcore_netChain", "params":[], "id": 1}"#; let request = r#"{"jsonrpc": "2.0", "method": "parity_netChain", "params":[], "id": 1}"#;
let response = r#"{"jsonrpc":"2.0","result":"testchain","id":1}"#; let response = r#"{"jsonrpc":"2.0","result":"testchain","id":1}"#;
assert_eq!(io.handle_request_sync(request), Some(response.to_owned())); assert_eq!(io.handle_request_sync(request), Some(response.to_owned()));
} }
#[test] #[test]
fn rpc_ethcore_net_peers() { fn rpc_parity_net_peers() {
let deps = Dependencies::new(); let deps = Dependencies::new();
let io = deps.default_client(); let io = deps.default_client();
let request = r#"{"jsonrpc": "2.0", "method": "ethcore_netPeers", "params":[], "id": 1}"#; let request = r#"{"jsonrpc": "2.0", "method": "parity_netPeers", "params":[], "id": 1}"#;
let response = "{\"jsonrpc\":\"2.0\",\"result\":{\"active\":0,\"connected\":120,\"max\":50,\"peers\":[{\"caps\":[\"eth/62\",\"eth/63\"],\ let response = "{\"jsonrpc\":\"2.0\",\"result\":{\"active\":0,\"connected\":120,\"max\":50,\"peers\":[{\"caps\":[\"eth/62\",\"eth/63\"],\
\"id\":\"node1\",\"name\":\"Parity/1\",\"network\":{\"localAddress\":\"127.0.0.1:8888\",\"remoteAddress\":\"127.0.0.1:7777\"}\ \"id\":\"node1\",\"name\":\"Parity/1\",\"network\":{\"localAddress\":\"127.0.0.1:8888\",\"remoteAddress\":\"127.0.0.1:7777\"}\
,\"protocols\":{\"eth\":{\"difficulty\":\"0x28\",\"head\":\"0000000000000000000000000000000000000000000000000000000000000032\"\ ,\"protocols\":{\"eth\":{\"difficulty\":\"0x28\",\"head\":\"0000000000000000000000000000000000000000000000000000000000000032\"\
@ -200,101 +203,90 @@ fn rpc_ethcore_net_peers() {
} }
#[test] #[test]
fn rpc_ethcore_net_port() { fn rpc_parity_net_port() {
let deps = Dependencies::new(); let deps = Dependencies::new();
let io = deps.default_client(); let io = deps.default_client();
let request = r#"{"jsonrpc": "2.0", "method": "ethcore_netPort", "params":[], "id": 1}"#; let request = r#"{"jsonrpc": "2.0", "method": "parity_netPort", "params":[], "id": 1}"#;
let response = r#"{"jsonrpc":"2.0","result":30303,"id":1}"#; let response = r#"{"jsonrpc":"2.0","result":30303,"id":1}"#;
assert_eq!(io.handle_request_sync(request), Some(response.to_owned())); assert_eq!(io.handle_request_sync(request), Some(response.to_owned()));
} }
#[test] #[test]
fn rpc_ethcore_rpc_settings() { fn rpc_parity_rpc_settings() {
let deps = Dependencies::new(); let deps = Dependencies::new();
let io = deps.default_client(); let io = deps.default_client();
let request = r#"{"jsonrpc": "2.0", "method": "ethcore_rpcSettings", "params":[], "id": 1}"#; let request = r#"{"jsonrpc": "2.0", "method": "parity_rpcSettings", "params":[], "id": 1}"#;
let response = r#"{"jsonrpc":"2.0","result":{"enabled":true,"interface":"all","port":8545},"id":1}"#; let response = r#"{"jsonrpc":"2.0","result":{"enabled":true,"interface":"all","port":8545},"id":1}"#;
assert_eq!(io.handle_request_sync(request), Some(response.to_owned())); assert_eq!(io.handle_request_sync(request), Some(response.to_owned()));
} }
#[test] #[test]
fn rpc_ethcore_node_name() { fn rpc_parity_node_name() {
let deps = Dependencies::new(); let deps = Dependencies::new();
let io = deps.default_client(); let io = deps.default_client();
let request = r#"{"jsonrpc": "2.0", "method": "ethcore_nodeName", "params":[], "id": 1}"#; let request = r#"{"jsonrpc": "2.0", "method": "parity_nodeName", "params":[], "id": 1}"#;
let response = r#"{"jsonrpc":"2.0","result":"mynode","id":1}"#; let response = r#"{"jsonrpc":"2.0","result":"mynode","id":1}"#;
assert_eq!(io.handle_request_sync(request), Some(response.to_owned())); assert_eq!(io.handle_request_sync(request), Some(response.to_owned()));
} }
#[test] #[test]
fn rpc_ethcore_unsigned_transactions_count() { fn rpc_parity_unsigned_transactions_count() {
let deps = Dependencies::new(); let deps = Dependencies::new();
let io = deps.with_signer(SignerService::new_test(Some(18180))); let io = deps.with_signer(SignerService::new_test(Some(18180)));
let request = r#"{"jsonrpc": "2.0", "method": "ethcore_unsignedTransactionsCount", "params":[], "id": 1}"#; let request = r#"{"jsonrpc": "2.0", "method": "parity_unsignedTransactionsCount", "params":[], "id": 1}"#;
let response = r#"{"jsonrpc":"2.0","result":0,"id":1}"#; let response = r#"{"jsonrpc":"2.0","result":0,"id":1}"#;
assert_eq!(io.handle_request_sync(request), Some(response.to_owned())); assert_eq!(io.handle_request_sync(request), Some(response.to_owned()));
} }
#[test] #[test]
fn rpc_ethcore_unsigned_transactions_count_when_signer_disabled() { fn rpc_parity_unsigned_transactions_count_when_signer_disabled() {
let deps = Dependencies::new(); let deps = Dependencies::new();
let io = deps.default_client(); let io = deps.default_client();
let request = r#"{"jsonrpc": "2.0", "method": "ethcore_unsignedTransactionsCount", "params":[], "id": 1}"#; let request = r#"{"jsonrpc": "2.0", "method": "parity_unsignedTransactionsCount", "params":[], "id": 1}"#;
let response = r#"{"jsonrpc":"2.0","error":{"code":-32030,"message":"Trusted Signer is disabled. This API is not available.","data":null},"id":1}"#; let response = r#"{"jsonrpc":"2.0","error":{"code":-32030,"message":"Trusted Signer is disabled. This API is not available.","data":null},"id":1}"#;
assert_eq!(io.handle_request_sync(request), Some(response.to_owned())); assert_eq!(io.handle_request_sync(request), Some(response.to_owned()));
} }
#[test] #[test]
fn rpc_ethcore_hash_content() { fn rpc_parity_pending_transactions() {
let deps = Dependencies::new(); let deps = Dependencies::new();
let io = deps.default_client(); let io = deps.default_client();
let request = r#"{"jsonrpc": "2.0", "method": "ethcore_hashContent", "params":["https://ethcore.io/assets/images/ethcore-black-horizontal.png"], "id": 1}"#; let request = r#"{"jsonrpc": "2.0", "method": "parity_pendingTransactions", "params":[], "id": 1}"#;
let response = r#"{"jsonrpc":"2.0","result":"0x2be00befcf008bc0e7d9cdefc194db9c75352e8632f48498b5a6bfce9f02c88e","id":1}"#;
assert_eq!(io.handle_request_sync(request), Some(response.to_owned()));
}
#[test]
fn rpc_ethcore_pending_transactions() {
let deps = Dependencies::new();
let io = deps.default_client();
let request = r#"{"jsonrpc": "2.0", "method": "ethcore_pendingTransactions", "params":[], "id": 1}"#;
let response = r#"{"jsonrpc":"2.0","result":[],"id":1}"#; let response = r#"{"jsonrpc":"2.0","result":[],"id":1}"#;
assert_eq!(io.handle_request_sync(request), Some(response.to_owned())); assert_eq!(io.handle_request_sync(request), Some(response.to_owned()));
} }
#[test] #[test]
fn rpc_ethcore_encrypt() { fn rpc_parity_encrypt() {
let deps = Dependencies::new(); let deps = Dependencies::new();
let io = deps.default_client(); let io = deps.default_client();
let key = format!("{:?}", Random.generate().unwrap().public()); let key = format!("{:?}", Random.generate().unwrap().public());
let request = r#"{"jsonrpc": "2.0", "method": "ethcore_encryptMessage", "params":["0x"#.to_owned() + &key + r#"", "0x01"], "id": 1}"#; let request = r#"{"jsonrpc": "2.0", "method": "parity_encryptMessage", "params":["0x"#.to_owned() + &key + r#"", "0x01"], "id": 1}"#;
assert!(io.handle_request_sync(&request).unwrap().contains("result"), "Should return success."); assert!(io.handle_request_sync(&request).unwrap().contains("result"), "Should return success.");
} }
#[test] #[test]
fn rpc_ethcore_signer_port() { fn rpc_parity_signer_port() {
// given // given
let deps = Dependencies::new(); let deps = Dependencies::new();
let io1 = deps.with_signer(SignerService::new_test(Some(18180))); let io1 = deps.with_signer(SignerService::new_test(Some(18180)));
let io2 = deps.default_client(); let io2 = deps.default_client();
// when // when
let request = r#"{"jsonrpc": "2.0", "method": "ethcore_signerPort", "params": [], "id": 1}"#; let request = r#"{"jsonrpc": "2.0", "method": "parity_signerPort", "params": [], "id": 1}"#;
let response1 = r#"{"jsonrpc":"2.0","result":18180,"id":1}"#; let response1 = r#"{"jsonrpc":"2.0","result":18180,"id":1}"#;
let response2 = r#"{"jsonrpc":"2.0","error":{"code":-32030,"message":"Trusted Signer is disabled. This API is not available.","data":null},"id":1}"#; let response2 = r#"{"jsonrpc":"2.0","error":{"code":-32030,"message":"Trusted Signer is disabled. This API is not available.","data":null},"id":1}"#;
@ -304,7 +296,7 @@ fn rpc_ethcore_signer_port() {
} }
#[test] #[test]
fn rpc_ethcore_dapps_port() { fn rpc_parity_dapps_port() {
// given // given
let mut deps = Dependencies::new(); let mut deps = Dependencies::new();
let io1 = deps.default_client(); let io1 = deps.default_client();
@ -312,7 +304,7 @@ fn rpc_ethcore_dapps_port() {
let io2 = deps.default_client(); let io2 = deps.default_client();
// when // when
let request = r#"{"jsonrpc": "2.0", "method": "ethcore_dappsPort", "params": [], "id": 1}"#; let request = r#"{"jsonrpc": "2.0", "method": "parity_dappsPort", "params": [], "id": 1}"#;
let response1 = r#"{"jsonrpc":"2.0","result":18080,"id":1}"#; let response1 = r#"{"jsonrpc":"2.0","result":18080,"id":1}"#;
let response2 = r#"{"jsonrpc":"2.0","error":{"code":-32031,"message":"Dapps Server is disabled. This API is not available.","data":null},"id":1}"#; let response2 = r#"{"jsonrpc":"2.0","error":{"code":-32031,"message":"Dapps Server is disabled. This API is not available.","data":null},"id":1}"#;
@ -322,7 +314,7 @@ fn rpc_ethcore_dapps_port() {
} }
#[test] #[test]
fn rpc_ethcore_next_nonce() { fn rpc_parity_next_nonce() {
let deps = Dependencies::new(); let deps = Dependencies::new();
let address = Address::default(); let address = Address::default();
let io1 = deps.default_client(); let io1 = deps.default_client();
@ -332,7 +324,7 @@ fn rpc_ethcore_next_nonce() {
let request = r#"{ let request = r#"{
"jsonrpc": "2.0", "jsonrpc": "2.0",
"method": "ethcore_nextNonce", "method": "parity_nextNonce",
"params": [""#.to_owned() + &format!("0x{:?}", address) + r#""], "params": [""#.to_owned() + &format!("0x{:?}", address) + r#""],
"id": 1 "id": 1
}"#; }"#;

View File

@ -0,0 +1,118 @@
// Copyright 2015, 2016 Ethcore (UK) Ltd.
// This file is part of Parity.
// Parity is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
// Parity 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 General Public License for more details.
// You should have received a copy of the GNU General Public License
// along with Parity. If not, see <http://www.gnu.org/licenses/>.
use std::sync::Arc;
use ethcore::account_provider::AccountProvider;
use ethcore::client::TestBlockChainClient;
use jsonrpc_core::IoHandler;
use v1::{ParityAccounts, ParityAccountsClient};
struct ParityAccountsTester {
accounts: Arc<AccountProvider>,
io: IoHandler,
// these unused fields are necessary to keep the data alive
// as the handler has only weak pointers.
_client: Arc<TestBlockChainClient>,
}
fn blockchain_client() -> Arc<TestBlockChainClient> {
let client = TestBlockChainClient::new();
Arc::new(client)
}
fn accounts_provider() -> Arc<AccountProvider> {
Arc::new(AccountProvider::transient_provider())
}
fn setup() -> ParityAccountsTester {
let accounts = accounts_provider();
let client = blockchain_client();
let parity_accounts = ParityAccountsClient::new(&accounts, &client);
let io = IoHandler::new();
io.add_delegate(parity_accounts.to_delegate());
let tester = ParityAccountsTester {
accounts: accounts,
io: io,
_client: client,
};
tester
}
#[test]
fn should_be_able_to_get_account_info() {
let tester = setup();
tester.accounts.new_account("").unwrap();
let accounts = tester.accounts.accounts().unwrap();
assert_eq!(accounts.len(), 1);
let address = accounts[0];
let uuid = tester.accounts.accounts_info().unwrap().get(&address).unwrap().uuid.as_ref().unwrap().clone();
tester.accounts.set_account_name(address.clone(), "Test".to_owned()).unwrap();
tester.accounts.set_account_meta(address.clone(), "{foo: 69}".to_owned()).unwrap();
let request = r#"{"jsonrpc": "2.0", "method": "parity_accountsInfo", "params": [], "id": 1}"#;
let res = tester.io.handle_request_sync(request);
let response = format!("{{\"jsonrpc\":\"2.0\",\"result\":{{\"0x{}\":{{\"meta\":\"{{foo: 69}}\",\"name\":\"Test\",\"uuid\":\"{}\"}}}},\"id\":1}}", address.hex(), uuid);
assert_eq!(res, Some(response));
}
#[test]
fn should_be_able_to_set_name() {
let tester = setup();
tester.accounts.new_account("").unwrap();
let accounts = tester.accounts.accounts().unwrap();
assert_eq!(accounts.len(), 1);
let address = accounts[0];
let request = format!(r#"{{"jsonrpc": "2.0", "method": "parity_setAccountName", "params": ["0x{}", "Test"], "id": 1}}"#, address.hex());
let response = r#"{"jsonrpc":"2.0","result":true,"id":1}"#;
let res = tester.io.handle_request_sync(&request);
assert_eq!(res, Some(response.into()));
let uuid = tester.accounts.accounts_info().unwrap().get(&address).unwrap().uuid.as_ref().unwrap().clone();
let request = r#"{"jsonrpc": "2.0", "method": "parity_accountsInfo", "params": [], "id": 1}"#;
let res = tester.io.handle_request_sync(request);
let response = format!("{{\"jsonrpc\":\"2.0\",\"result\":{{\"0x{}\":{{\"meta\":\"{{}}\",\"name\":\"Test\",\"uuid\":\"{}\"}}}},\"id\":1}}", address.hex(), uuid);
assert_eq!(res, Some(response));
}
#[test]
fn should_be_able_to_set_meta() {
let tester = setup();
tester.accounts.new_account("").unwrap();
let accounts = tester.accounts.accounts().unwrap();
assert_eq!(accounts.len(), 1);
let address = accounts[0];
let request = format!(r#"{{"jsonrpc": "2.0", "method": "parity_setAccountMeta", "params": ["0x{}", "{{foo: 69}}"], "id": 1}}"#, address.hex());
let response = r#"{"jsonrpc":"2.0","result":true,"id":1}"#;
let res = tester.io.handle_request_sync(&request);
assert_eq!(res, Some(response.into()));
let uuid = tester.accounts.accounts_info().unwrap().get(&address).unwrap().uuid.as_ref().unwrap().clone();
let request = r#"{"jsonrpc": "2.0", "method": "parity_accountsInfo", "params": [], "id": 1}"#;
let res = tester.io.handle_request_sync(request);
let response = format!("{{\"jsonrpc\":\"2.0\",\"result\":{{\"0x{}\":{{\"meta\":\"{{foo: 69}}\",\"name\":\"{}\",\"uuid\":\"{}\"}}}},\"id\":1}}", address.hex(), uuid, uuid);
assert_eq!(res, Some(response));
}

View File

@ -16,16 +16,18 @@
use std::sync::Arc; use std::sync::Arc;
use std::str::FromStr; use std::str::FromStr;
use jsonrpc_core::IoHandler; use rustc_serialize::hex::FromHex;
use v1::{EthcoreSet, EthcoreSetClient}; use util::{U256, Address};
use ethcore::miner::MinerService; use ethcore::miner::MinerService;
use ethcore::client::TestBlockChainClient; use ethcore::client::TestBlockChainClient;
use v1::tests::helpers::TestMinerService;
use util::{U256, Address};
use rustc_serialize::hex::FromHex;
use super::manage_network::TestManageNetwork;
use ethsync::ManageNetwork; use ethsync::ManageNetwork;
use jsonrpc_core::IoHandler;
use v1::{ParitySet, ParitySetClient};
use v1::tests::helpers::{TestMinerService, TestFetch};
use super::manage_network::TestManageNetwork;
fn miner_service() -> Arc<TestMinerService> { fn miner_service() -> Arc<TestMinerService> {
Arc::new(TestMinerService::default()) Arc::new(TestMinerService::default())
} }
@ -38,19 +40,21 @@ fn network_service() -> Arc<TestManageNetwork> {
Arc::new(TestManageNetwork) Arc::new(TestManageNetwork)
} }
fn ethcore_set_client(client: &Arc<TestBlockChainClient>, miner: &Arc<TestMinerService>, net: &Arc<TestManageNetwork>) -> EthcoreSetClient<TestBlockChainClient, TestMinerService> { pub type TestParitySetClient = ParitySetClient<TestBlockChainClient, TestMinerService, TestFetch>;
EthcoreSetClient::new(client, miner, &(net.clone() as Arc<ManageNetwork>))
fn parity_set_client(client: &Arc<TestBlockChainClient>, miner: &Arc<TestMinerService>, net: &Arc<TestManageNetwork>) -> TestParitySetClient {
ParitySetClient::with_fetch(client, miner, &(net.clone() as Arc<ManageNetwork>))
} }
#[test] #[test]
fn rpc_ethcore_set_min_gas_price() { fn rpc_parity_set_min_gas_price() {
let miner = miner_service(); let miner = miner_service();
let client = client_service(); let client = client_service();
let network = network_service(); let network = network_service();
let io = IoHandler::new(); let io = IoHandler::new();
io.add_delegate(ethcore_set_client(&client, &miner, &network).to_delegate()); io.add_delegate(parity_set_client(&client, &miner, &network).to_delegate());
let request = r#"{"jsonrpc": "2.0", "method": "ethcore_setMinGasPrice", "params":["0xcd1722f3947def4cf144679da39c4c32bdc35681"], "id": 1}"#; let request = r#"{"jsonrpc": "2.0", "method": "parity_setMinGasPrice", "params":["0xcd1722f3947def4cf144679da39c4c32bdc35681"], "id": 1}"#;
let response = r#"{"jsonrpc":"2.0","result":true,"id":1}"#; let response = r#"{"jsonrpc":"2.0","result":true,"id":1}"#;
assert_eq!(io.handle_request_sync(request), Some(response.to_owned())); assert_eq!(io.handle_request_sync(request), Some(response.to_owned()));
@ -58,14 +62,14 @@ fn rpc_ethcore_set_min_gas_price() {
} }
#[test] #[test]
fn rpc_ethcore_set_gas_floor_target() { fn rpc_parity_set_gas_floor_target() {
let miner = miner_service(); let miner = miner_service();
let client = client_service(); let client = client_service();
let network = network_service(); let network = network_service();
let io = IoHandler::new(); let io = IoHandler::new();
io.add_delegate(ethcore_set_client(&client, &miner, &network).to_delegate()); io.add_delegate(parity_set_client(&client, &miner, &network).to_delegate());
let request = r#"{"jsonrpc": "2.0", "method": "ethcore_setGasFloorTarget", "params":["0xcd1722f3947def4cf144679da39c4c32bdc35681"], "id": 1}"#; let request = r#"{"jsonrpc": "2.0", "method": "parity_setGasFloorTarget", "params":["0xcd1722f3947def4cf144679da39c4c32bdc35681"], "id": 1}"#;
let response = r#"{"jsonrpc":"2.0","result":true,"id":1}"#; let response = r#"{"jsonrpc":"2.0","result":true,"id":1}"#;
assert_eq!(io.handle_request_sync(request), Some(response.to_owned())); assert_eq!(io.handle_request_sync(request), Some(response.to_owned()));
@ -73,14 +77,14 @@ fn rpc_ethcore_set_gas_floor_target() {
} }
#[test] #[test]
fn rpc_ethcore_set_extra_data() { fn rpc_parity_set_extra_data() {
let miner = miner_service(); let miner = miner_service();
let client = client_service(); let client = client_service();
let network = network_service(); let network = network_service();
let io = IoHandler::new(); let io = IoHandler::new();
io.add_delegate(ethcore_set_client(&client, &miner, &network).to_delegate()); io.add_delegate(parity_set_client(&client, &miner, &network).to_delegate());
let request = r#"{"jsonrpc": "2.0", "method": "ethcore_setExtraData", "params":["0xcd1722f3947def4cf144679da39c4c32bdc35681"], "id": 1}"#; let request = r#"{"jsonrpc": "2.0", "method": "parity_setExtraData", "params":["0xcd1722f3947def4cf144679da39c4c32bdc35681"], "id": 1}"#;
let response = r#"{"jsonrpc":"2.0","result":true,"id":1}"#; let response = r#"{"jsonrpc":"2.0","result":true,"id":1}"#;
assert_eq!(io.handle_request_sync(request), Some(response.to_owned())); assert_eq!(io.handle_request_sync(request), Some(response.to_owned()));
@ -88,14 +92,14 @@ fn rpc_ethcore_set_extra_data() {
} }
#[test] #[test]
fn rpc_ethcore_set_author() { fn rpc_parity_set_author() {
let miner = miner_service(); let miner = miner_service();
let client = client_service(); let client = client_service();
let network = network_service(); let network = network_service();
let io = IoHandler::new(); let io = IoHandler::new();
io.add_delegate(ethcore_set_client(&client, &miner, &network).to_delegate()); io.add_delegate(parity_set_client(&client, &miner, &network).to_delegate());
let request = r#"{"jsonrpc": "2.0", "method": "ethcore_setAuthor", "params":["0xcd1722f3947def4cf144679da39c4c32bdc35681"], "id": 1}"#; let request = r#"{"jsonrpc": "2.0", "method": "parity_setAuthor", "params":["0xcd1722f3947def4cf144679da39c4c32bdc35681"], "id": 1}"#;
let response = r#"{"jsonrpc":"2.0","result":true,"id":1}"#; let response = r#"{"jsonrpc":"2.0","result":true,"id":1}"#;
assert_eq!(io.handle_request_sync(request), Some(response.to_owned())); assert_eq!(io.handle_request_sync(request), Some(response.to_owned()));
@ -103,16 +107,31 @@ fn rpc_ethcore_set_author() {
} }
#[test] #[test]
fn rpc_ethcore_set_transactions_limit() { fn rpc_parity_set_transactions_limit() {
let miner = miner_service(); let miner = miner_service();
let client = client_service(); let client = client_service();
let network = network_service(); let network = network_service();
let io = IoHandler::new(); let io = IoHandler::new();
io.add_delegate(ethcore_set_client(&client, &miner, &network).to_delegate()); io.add_delegate(parity_set_client(&client, &miner, &network).to_delegate());
let request = r#"{"jsonrpc": "2.0", "method": "ethcore_setTransactionsLimit", "params":[10240240], "id": 1}"#; let request = r#"{"jsonrpc": "2.0", "method": "parity_setTransactionsLimit", "params":[10240240], "id": 1}"#;
let response = r#"{"jsonrpc":"2.0","result":true,"id":1}"#; let response = r#"{"jsonrpc":"2.0","result":true,"id":1}"#;
assert_eq!(io.handle_request_sync(request), Some(response.to_owned())); assert_eq!(io.handle_request_sync(request), Some(response.to_owned()));
assert_eq!(miner.transactions_limit(), 10_240_240); assert_eq!(miner.transactions_limit(), 10_240_240);
} }
#[test]
fn rpc_parity_set_hash_content() {
let miner = miner_service();
let client = client_service();
let network = network_service();
let io = IoHandler::new();
io.add_delegate(parity_set_client(&client, &miner, &network).to_delegate());
let request = r#"{"jsonrpc": "2.0", "method": "parity_hashContent", "params":["https://ethcore.io/assets/images/ethcore-black-horizontal.png"], "id": 1}"#;
let response = r#"{"jsonrpc":"2.0","result":"0x2be00befcf008bc0e7d9cdefc194db9c75352e8632f48498b5a6bfce9f02c88e","id":1}"#;
assert_eq!(io.handle_request_sync(request), Some(response.to_owned()));
}

View File

@ -19,7 +19,7 @@ use std::str::FromStr;
use jsonrpc_core::IoHandler; use jsonrpc_core::IoHandler;
use util::{U256, Uint, Address}; use util::{U256, Uint, Address};
use ethcore::account_provider::AccountProvider; use ethcore::account_provider::AccountProvider;
use v1::{PersonalClient, PersonalAccountsClient, PersonalAccounts, Personal}; use v1::{PersonalClient, Personal};
use v1::tests::helpers::TestMinerService; use v1::tests::helpers::TestMinerService;
use ethcore::client::TestBlockChainClient; use ethcore::client::TestBlockChainClient;
use ethcore::transaction::{Action, Transaction}; use ethcore::transaction::{Action, Transaction};
@ -50,12 +50,10 @@ fn setup() -> PersonalTester {
let accounts = accounts_provider(); let accounts = accounts_provider();
let client = blockchain_client(); let client = blockchain_client();
let miner = miner_service(); let miner = miner_service();
let personal = PersonalClient::new(&accounts, &client); let personal = PersonalClient::new(&accounts, &client, &miner, false);
let personal_accounts = PersonalAccountsClient::new(&accounts, &client, &miner, false);
let io = IoHandler::new(); let io = IoHandler::new();
io.add_delegate(personal.to_delegate()); io.add_delegate(personal.to_delegate());
io.add_delegate(personal_accounts.to_delegate());
let tester = PersonalTester { let tester = PersonalTester {
accounts: accounts, accounts: accounts,
@ -92,66 +90,6 @@ fn new_account() {
assert_eq!(res, Some(response)); assert_eq!(res, Some(response));
} }
#[test]
fn should_be_able_to_get_account_info() {
let tester = setup();
tester.accounts.new_account("").unwrap();
let accounts = tester.accounts.accounts().unwrap();
assert_eq!(accounts.len(), 1);
let address = accounts[0];
let uuid = tester.accounts.accounts_info().unwrap().get(&address).unwrap().uuid.as_ref().unwrap().clone();
tester.accounts.set_account_name(address.clone(), "Test".to_owned()).unwrap();
tester.accounts.set_account_meta(address.clone(), "{foo: 69}".to_owned()).unwrap();
let request = r#"{"jsonrpc": "2.0", "method": "personal_accountsInfo", "params": [], "id": 1}"#;
let res = tester.io.handle_request_sync(request);
let response = format!("{{\"jsonrpc\":\"2.0\",\"result\":{{\"0x{}\":{{\"meta\":\"{{foo: 69}}\",\"name\":\"Test\",\"uuid\":\"{}\"}}}},\"id\":1}}", address.hex(), uuid);
assert_eq!(res, Some(response));
}
#[test]
fn should_be_able_to_set_name() {
let tester = setup();
tester.accounts.new_account("").unwrap();
let accounts = tester.accounts.accounts().unwrap();
assert_eq!(accounts.len(), 1);
let address = accounts[0];
let request = format!(r#"{{"jsonrpc": "2.0", "method": "personal_setAccountName", "params": ["0x{}", "Test"], "id": 1}}"#, address.hex());
let response = r#"{"jsonrpc":"2.0","result":true,"id":1}"#;
let res = tester.io.handle_request_sync(&request);
assert_eq!(res, Some(response.into()));
let uuid = tester.accounts.accounts_info().unwrap().get(&address).unwrap().uuid.as_ref().unwrap().clone();
let request = r#"{"jsonrpc": "2.0", "method": "personal_accountsInfo", "params": [], "id": 1}"#;
let res = tester.io.handle_request_sync(request);
let response = format!("{{\"jsonrpc\":\"2.0\",\"result\":{{\"0x{}\":{{\"meta\":\"{{}}\",\"name\":\"Test\",\"uuid\":\"{}\"}}}},\"id\":1}}", address.hex(), uuid);
assert_eq!(res, Some(response));
}
#[test]
fn should_be_able_to_set_meta() {
let tester = setup();
tester.accounts.new_account("").unwrap();
let accounts = tester.accounts.accounts().unwrap();
assert_eq!(accounts.len(), 1);
let address = accounts[0];
let request = format!(r#"{{"jsonrpc": "2.0", "method": "personal_setAccountMeta", "params": ["0x{}", "{{foo: 69}}"], "id": 1}}"#, address.hex());
let response = r#"{"jsonrpc":"2.0","result":true,"id":1}"#;
let res = tester.io.handle_request_sync(&request);
assert_eq!(res, Some(response.into()));
let uuid = tester.accounts.accounts_info().unwrap().get(&address).unwrap().uuid.as_ref().unwrap().clone();
let request = r#"{"jsonrpc": "2.0", "method": "personal_accountsInfo", "params": [], "id": 1}"#;
let res = tester.io.handle_request_sync(request);
let response = format!("{{\"jsonrpc\":\"2.0\",\"result\":{{\"0x{}\":{{\"meta\":\"{{foo: 69}}\",\"name\":\"{}\",\"uuid\":\"{}\"}}}},\"id\":1}}", address.hex(), uuid, uuid);
assert_eq!(res, Some(response));
}
#[test] #[test]
fn sign_and_send_transaction_with_invalid_password() { fn sign_and_send_transaction_with_invalid_password() {
let tester = setup(); let tester = setup();

View File

@ -21,11 +21,11 @@ use util::{U256, Uint, Address};
use ethcore::account_provider::AccountProvider; use ethcore::account_provider::AccountProvider;
use ethcore::client::TestBlockChainClient; use ethcore::client::TestBlockChainClient;
use ethcore::transaction::{Transaction, Action}; use ethcore::transaction::{Transaction, Action};
use v1::{SignerClient, PersonalSigner}; use v1::{SignerClient, Signer};
use v1::tests::helpers::TestMinerService; use v1::tests::helpers::TestMinerService;
use v1::helpers::{SigningQueue, SignerService, FilledTransactionRequest, ConfirmationPayload}; use v1::helpers::{SigningQueue, SignerService, FilledTransactionRequest, ConfirmationPayload};
struct PersonalSignerTester { struct SignerTester {
signer: Arc<SignerService>, signer: Arc<SignerService>,
accounts: Arc<AccountProvider>, accounts: Arc<AccountProvider>,
io: IoHandler, io: IoHandler,
@ -48,7 +48,7 @@ fn miner_service() -> Arc<TestMinerService> {
Arc::new(TestMinerService::default()) Arc::new(TestMinerService::default())
} }
fn signer_tester() -> PersonalSignerTester { fn signer_tester() -> SignerTester {
let signer = Arc::new(SignerService::new_test(None)); let signer = Arc::new(SignerService::new_test(None));
let accounts = accounts_provider(); let accounts = accounts_provider();
let client = blockchain_client(); let client = blockchain_client();
@ -57,7 +57,7 @@ fn signer_tester() -> PersonalSignerTester {
let io = IoHandler::new(); let io = IoHandler::new();
io.add_delegate(SignerClient::new(&accounts, &client, &miner, &signer).to_delegate()); io.add_delegate(SignerClient::new(&accounts, &client, &miner, &signer).to_delegate());
PersonalSignerTester { SignerTester {
signer: signer, signer: signer,
accounts: accounts, accounts: accounts,
io: io, io: io,
@ -83,7 +83,7 @@ fn should_return_list_of_items_to_confirm() {
tester.signer.add_request(ConfirmationPayload::Sign(1.into(), 5.into())).unwrap(); tester.signer.add_request(ConfirmationPayload::Sign(1.into(), 5.into())).unwrap();
// when // when
let request = r#"{"jsonrpc":"2.0","method":"personal_requestsToConfirm","params":[],"id":1}"#; let request = r#"{"jsonrpc":"2.0","method":"signer_requestsToConfirm","params":[],"id":1}"#;
let response = concat!( let response = concat!(
r#"{"jsonrpc":"2.0","result":["#, r#"{"jsonrpc":"2.0","result":["#,
r#"{"id":"0x1","payload":{"transaction":{"data":"0x","from":"0x0000000000000000000000000000000000000001","gas":"0x989680","gasPrice":"0x2710","nonce":null,"to":"0xd46e8dd67c5d32be8058bb8eb970870f07244567","value":"0x1"}}},"#, r#"{"id":"0x1","payload":{"transaction":{"data":"0x","from":"0x0000000000000000000000000000000000000001","gas":"0x989680","gasPrice":"0x2710","nonce":null,"to":"0xd46e8dd67c5d32be8058bb8eb970870f07244567","value":"0x1"}}},"#,
@ -112,7 +112,7 @@ fn should_reject_transaction_from_queue_without_dispatching() {
assert_eq!(tester.signer.requests().len(), 1); assert_eq!(tester.signer.requests().len(), 1);
// when // when
let request = r#"{"jsonrpc":"2.0","method":"personal_rejectRequest","params":["0x1"],"id":1}"#; let request = r#"{"jsonrpc":"2.0","method":"signer_rejectRequest","params":["0x1"],"id":1}"#;
let response = r#"{"jsonrpc":"2.0","result":true,"id":1}"#; let response = r#"{"jsonrpc":"2.0","result":true,"id":1}"#;
// then // then
@ -137,7 +137,7 @@ fn should_not_remove_transaction_if_password_is_invalid() {
assert_eq!(tester.signer.requests().len(), 1); assert_eq!(tester.signer.requests().len(), 1);
// when // when
let request = r#"{"jsonrpc":"2.0","method":"personal_confirmRequest","params":["0x1",{},"xxx"],"id":1}"#; let request = r#"{"jsonrpc":"2.0","method":"signer_confirmRequest","params":["0x1",{},"xxx"],"id":1}"#;
let response = r#"{"jsonrpc":"2.0","error":{"code":-32021,"message":"Account password is invalid or account does not exist.","data":"SStore(InvalidAccount)"},"id":1}"#; let response = r#"{"jsonrpc":"2.0","error":{"code":-32021,"message":"Account password is invalid or account does not exist.","data":"SStore(InvalidAccount)"},"id":1}"#;
// then // then
@ -153,7 +153,7 @@ fn should_not_remove_sign_if_password_is_invalid() {
assert_eq!(tester.signer.requests().len(), 1); assert_eq!(tester.signer.requests().len(), 1);
// when // when
let request = r#"{"jsonrpc":"2.0","method":"personal_confirmRequest","params":["0x1",{},"xxx"],"id":1}"#; let request = r#"{"jsonrpc":"2.0","method":"signer_confirmRequest","params":["0x1",{},"xxx"],"id":1}"#;
let response = r#"{"jsonrpc":"2.0","error":{"code":-32021,"message":"Account password is invalid or account does not exist.","data":"SStore(InvalidAccount)"},"id":1}"#; let response = r#"{"jsonrpc":"2.0","error":{"code":-32021,"message":"Account password is invalid or account does not exist.","data":"SStore(InvalidAccount)"},"id":1}"#;
// then // then
@ -194,7 +194,7 @@ fn should_confirm_transaction_and_dispatch() {
// when // when
let request = r#"{ let request = r#"{
"jsonrpc":"2.0", "jsonrpc":"2.0",
"method":"personal_confirmRequest", "method":"signer_confirmRequest",
"params":["0x1", {"gasPrice":"0x1000"}, "test"], "params":["0x1", {"gasPrice":"0x1000"}, "test"],
"id":1 "id":1
}"#; }"#;
@ -214,7 +214,7 @@ fn should_generate_new_token() {
// when // when
let request = r#"{ let request = r#"{
"jsonrpc":"2.0", "jsonrpc":"2.0",
"method":"personal_generateAuthorizationToken", "method":"signer_generateAuthorizationToken",
"params":[], "params":[],
"id":1 "id":1
}"#; }"#;

View File

@ -17,12 +17,12 @@
use std::str::FromStr; use std::str::FromStr;
use std::sync::Arc; use std::sync::Arc;
use jsonrpc_core::{IoHandler, to_value, Success}; use jsonrpc_core::{IoHandler, to_value, Success};
use v1::impls::EthSigningQueueClient; use v1::impls::SigningQueueClient;
use v1::traits::{EthSigning, Ethcore}; use v1::traits::{EthSigning, ParitySigning, Parity};
use v1::helpers::{SignerService, SigningQueue}; use v1::helpers::{SignerService, SigningQueue};
use v1::types::{H256 as RpcH256, H520 as RpcH520, Bytes}; use v1::types::{H256 as RpcH256, H520 as RpcH520, Bytes};
use v1::tests::helpers::TestMinerService; use v1::tests::helpers::TestMinerService;
use v1::tests::mocked::ethcore; use v1::tests::mocked::parity;
use util::{Address, FixedHash, Uint, U256, H256, H520}; use util::{Address, FixedHash, Uint, U256, H256, H520};
use ethcore::account_provider::AccountProvider; use ethcore::account_provider::AccountProvider;
@ -31,7 +31,7 @@ use ethcore::transaction::{Transaction, Action};
use ethstore::ethkey::{Generator, Random}; use ethstore::ethkey::{Generator, Random};
use serde_json; use serde_json;
struct EthSigningTester { struct SigningTester {
pub signer: Arc<SignerService>, pub signer: Arc<SignerService>,
pub client: Arc<TestBlockChainClient>, pub client: Arc<TestBlockChainClient>,
pub miner: Arc<TestMinerService>, pub miner: Arc<TestMinerService>,
@ -39,16 +39,19 @@ struct EthSigningTester {
pub io: IoHandler, pub io: IoHandler,
} }
impl Default for EthSigningTester { impl Default for SigningTester {
fn default() -> Self { fn default() -> Self {
let signer = Arc::new(SignerService::new_test(None)); let signer = Arc::new(SignerService::new_test(None));
let client = Arc::new(TestBlockChainClient::default()); let client = Arc::new(TestBlockChainClient::default());
let miner = Arc::new(TestMinerService::default()); let miner = Arc::new(TestMinerService::default());
let accounts = Arc::new(AccountProvider::transient_provider()); let accounts = Arc::new(AccountProvider::transient_provider());
let io = IoHandler::new(); let io = IoHandler::new();
io.add_delegate(EthSigningQueueClient::new(&signer, &client, &miner, &accounts).to_delegate()); let rpc = SigningQueueClient::new(&signer, &client, &miner, &accounts);
io.add_delegate(EthSigning::to_delegate(rpc));
let rpc = SigningQueueClient::new(&signer, &client, &miner, &accounts);
io.add_delegate(ParitySigning::to_delegate(rpc));
EthSigningTester { SigningTester {
signer: signer, signer: signer,
client: client, client: client,
miner: miner, miner: miner,
@ -58,8 +61,8 @@ impl Default for EthSigningTester {
} }
} }
fn eth_signing() -> EthSigningTester { fn eth_signing() -> SigningTester {
EthSigningTester::default() SigningTester::default()
} }
#[test] #[test]
@ -101,7 +104,7 @@ fn should_post_sign_to_queue() {
// when // when
let request = r#"{ let request = r#"{
"jsonrpc": "2.0", "jsonrpc": "2.0",
"method": "eth_postSign", "method": "parity_postSign",
"params": [ "params": [
""#.to_owned() + format!("0x{:?}", address).as_ref() + r#"", ""#.to_owned() + format!("0x{:?}", address).as_ref() + r#"",
"0x0000000000000000000000000000000000000000000000000000000000000005" "0x0000000000000000000000000000000000000000000000000000000000000005"
@ -122,7 +125,7 @@ fn should_check_status_of_request() {
let address = Address::random(); let address = Address::random();
let request = r#"{ let request = r#"{
"jsonrpc": "2.0", "jsonrpc": "2.0",
"method": "eth_postSign", "method": "parity_postSign",
"params": [ "params": [
""#.to_owned() + format!("0x{:?}", address).as_ref() + r#"", ""#.to_owned() + format!("0x{:?}", address).as_ref() + r#"",
"0x0000000000000000000000000000000000000000000000000000000000000005" "0x0000000000000000000000000000000000000000000000000000000000000005"
@ -134,7 +137,7 @@ fn should_check_status_of_request() {
// when // when
let request = r#"{ let request = r#"{
"jsonrpc": "2.0", "jsonrpc": "2.0",
"method": "eth_checkRequest", "method": "parity_checkRequest",
"params": ["0x1"], "params": ["0x1"],
"id": 1 "id": 1
}"#; }"#;
@ -151,7 +154,7 @@ fn should_check_status_of_request_when_its_resolved() {
let address = Address::random(); let address = Address::random();
let request = r#"{ let request = r#"{
"jsonrpc": "2.0", "jsonrpc": "2.0",
"method": "eth_postSign", "method": "parity_postSign",
"params": [ "params": [
""#.to_owned() + format!("0x{:?}", address).as_ref() + r#"", ""#.to_owned() + format!("0x{:?}", address).as_ref() + r#"",
"0x0000000000000000000000000000000000000000000000000000000000000005" "0x0000000000000000000000000000000000000000000000000000000000000005"
@ -164,7 +167,7 @@ fn should_check_status_of_request_when_its_resolved() {
// when // when
let request = r#"{ let request = r#"{
"jsonrpc": "2.0", "jsonrpc": "2.0",
"method": "eth_checkRequest", "method": "parity_checkRequest",
"params": ["0x1"], "params": ["0x1"],
"id": 1 "id": 1
}"#; }"#;
@ -272,15 +275,15 @@ fn should_dispatch_transaction_if_account_is_unlock() {
fn should_decrypt_message_if_account_is_unlocked() { fn should_decrypt_message_if_account_is_unlocked() {
// given // given
let tester = eth_signing(); let tester = eth_signing();
let ethcore = ethcore::Dependencies::new(); let parity = parity::Dependencies::new();
tester.io.add_delegate(ethcore.client(None).to_delegate()); tester.io.add_delegate(parity.client(None).to_delegate());
let (address, public) = tester.accounts.new_account_and_public("test").unwrap(); let (address, public) = tester.accounts.new_account_and_public("test").unwrap();
tester.accounts.unlock_account_permanently(address, "test".into()).unwrap(); tester.accounts.unlock_account_permanently(address, "test".into()).unwrap();
// First encrypt message // First encrypt message
let request = format!("{}0x{:?}{}", let request = format!("{}0x{:?}{}",
r#"{"jsonrpc": "2.0", "method": "ethcore_encryptMessage", "params":[""#, r#"{"jsonrpc": "2.0", "method": "parity_encryptMessage", "params":[""#,
public, public,
r#"", "0x01020304"], "id": 1}"# r#"", "0x01020304"], "id": 1}"#
); );
@ -288,7 +291,7 @@ fn should_decrypt_message_if_account_is_unlocked() {
// then call decrypt // then call decrypt
let request = format!("{}{:?}{}{:?}{}", let request = format!("{}{:?}{}{:?}{}",
r#"{"jsonrpc": "2.0", "method": "ethcore_decryptMessage", "params":["0x"#, r#"{"jsonrpc": "2.0", "method": "parity_decryptMessage", "params":["0x"#,
address, address,
r#"","#, r#"","#,
encrypted.result, encrypted.result,
@ -311,7 +314,7 @@ fn should_add_decryption_to_the_queue() {
// when // when
let request = r#"{ let request = r#"{
"jsonrpc": "2.0", "jsonrpc": "2.0",
"method": "ethcore_decryptMessage", "method": "parity_decryptMessage",
"params": ["0x"#.to_owned() + &format!("{:?}", acc.address()) + r#"", "params": ["0x"#.to_owned() + &format!("{:?}", acc.address()) + r#"",
"0x012345"], "0x012345"],
"id": 1 "id": 1

View File

@ -23,41 +23,18 @@ pub trait EthSigning: Sized + Send + Sync + 'static {
/// Signs the data with given address signature. /// Signs the data with given address signature.
fn sign(&self, _: Params, _: Ready); fn sign(&self, _: Params, _: Ready);
/// Posts sign request asynchronously.
/// Will return a confirmation ID for later use with check_transaction.
fn post_sign(&self, _: Params) -> Result<Value, Error>;
/// Sends transaction; will block for 20s to try to return the /// Sends transaction; will block for 20s to try to return the
/// transaction hash. /// transaction hash.
/// If it cannot yet be signed, it will return a transaction ID for /// If it cannot yet be signed, it will return a transaction ID for
/// later use with check_transaction. /// later use with check_transaction.
fn send_transaction(&self, _: Params, _: Ready); fn send_transaction(&self, _: Params, _: Ready);
/// Posts transaction asynchronously.
/// Will return a transaction ID for later use with check_transaction.
fn post_transaction(&self, _: Params) -> Result<Value, Error>;
/// Checks the progress of a previously posted request (transaction/sign).
/// Should be given a valid send_transaction ID.
/// Returns the transaction hash, the zero hash (not yet available),
/// or the signature,
/// or an error.
fn check_request(&self, _: Params) -> Result<Value, Error>;
/// Decrypt some ECIES-encrypted message.
/// First parameter is the address with which it is encrypted, second is the ciphertext.
fn decrypt_message(&self, _: Params, _: Ready);
/// Should be used to convert object to io delegate. /// Should be used to convert object to io delegate.
fn to_delegate(self) -> IoDelegate<Self> { fn to_delegate(self) -> IoDelegate<Self> {
let mut delegate = IoDelegate::new(Arc::new(self)); let mut delegate = IoDelegate::new(Arc::new(self));
delegate.add_async_method("eth_sign", EthSigning::sign); delegate.add_async_method("eth_sign", EthSigning::sign);
delegate.add_async_method("eth_sendTransaction", EthSigning::send_transaction); delegate.add_async_method("eth_sendTransaction", EthSigning::send_transaction);
delegate.add_async_method("ethcore_decryptMessage", EthSigning::decrypt_message);
delegate.add_method("eth_postSign", EthSigning::post_sign);
delegate.add_method("eth_postTransaction", EthSigning::post_transaction);
delegate.add_method("eth_checkRequest", EthSigning::check_request);
delegate delegate
} }
} }

View File

@ -20,9 +20,12 @@ pub mod web3;
pub mod eth; pub mod eth;
pub mod eth_signing; pub mod eth_signing;
pub mod net; pub mod net;
pub mod parity;
pub mod parity_accounts;
pub mod parity_set;
pub mod parity_signing;
pub mod personal; pub mod personal;
pub mod ethcore; pub mod signer;
pub mod ethcore_set;
pub mod traces; pub mod traces;
pub mod rpc; pub mod rpc;
@ -30,9 +33,12 @@ pub use self::web3::Web3;
pub use self::eth::{Eth, EthFilter}; pub use self::eth::{Eth, EthFilter};
pub use self::eth_signing::EthSigning; pub use self::eth_signing::EthSigning;
pub use self::net::Net; pub use self::net::Net;
pub use self::personal::{Personal, PersonalAccounts, PersonalSigner}; pub use self::parity::Parity;
pub use self::ethcore::Ethcore; pub use self::parity_accounts::ParityAccounts;
pub use self::ethcore_set::EthcoreSet; pub use self::parity_set::ParitySet;
pub use self::parity_signing::ParitySigning;
pub use self::personal::Personal;
pub use self::signer::Signer;
pub use self::traces::Traces; pub use self::traces::Traces;
pub use self::rpc::Rpc; pub use self::rpc::Rpc;

View File

@ -14,128 +14,129 @@
// You should have received a copy of the GNU General Public License // You should have received a copy of the GNU General Public License
// along with Parity. If not, see <http://www.gnu.org/licenses/>. // along with Parity. If not, see <http://www.gnu.org/licenses/>.
//! Ethcore-specific rpc interface. //! Parity-specific rpc interface.
use jsonrpc_core::Error; use jsonrpc_core::Error;
use v1::helpers::auto_args::{Wrap, WrapAsync, Ready}; use std::collections::BTreeMap;
use v1::helpers::auto_args::Wrap;
use v1::types::{H160, H256, H512, U256, Bytes, Peers, Transaction, RpcSettings, Histogram}; use v1::types::{H160, H256, H512, U256, Bytes, Peers, Transaction, RpcSettings, Histogram};
build_rpc_trait! { build_rpc_trait! {
/// Ethcore-specific rpc interface. /// Parity-specific rpc interface.
pub trait Ethcore { pub trait Parity {
/// Returns current transactions limit. /// Returns current transactions limit.
#[rpc(name = "ethcore_transactionsLimit")] #[rpc(name = "parity_transactionsLimit")]
fn transactions_limit(&self) -> Result<usize, Error>; fn transactions_limit(&self) -> Result<usize, Error>;
/// Returns mining extra data. /// Returns mining extra data.
#[rpc(name = "ethcore_extraData")] #[rpc(name = "parity_extraData")]
fn extra_data(&self) -> Result<Bytes, Error>; fn extra_data(&self) -> Result<Bytes, Error>;
/// Returns mining gas floor target. /// Returns mining gas floor target.
#[rpc(name = "ethcore_gasFloorTarget")] #[rpc(name = "parity_gasFloorTarget")]
fn gas_floor_target(&self) -> Result<U256, Error>; fn gas_floor_target(&self) -> Result<U256, Error>;
/// Returns mining gas floor cap. /// Returns mining gas floor cap.
#[rpc(name = "ethcore_gasCeilTarget")] #[rpc(name = "parity_gasCeilTarget")]
fn gas_ceil_target(&self) -> Result<U256, Error>; fn gas_ceil_target(&self) -> Result<U256, Error>;
/// Returns minimal gas price for transaction to be included in queue. /// Returns minimal gas price for transaction to be included in queue.
#[rpc(name = "ethcore_minGasPrice")] #[rpc(name = "parity_minGasPrice")]
fn min_gas_price(&self) -> Result<U256, Error>; fn min_gas_price(&self) -> Result<U256, Error>;
/// Returns latest logs /// Returns latest logs
#[rpc(name = "ethcore_devLogs")] #[rpc(name = "parity_devLogs")]
fn dev_logs(&self) -> Result<Vec<String>, Error>; fn dev_logs(&self) -> Result<Vec<String>, Error>;
/// Returns logs levels /// Returns logs levels
#[rpc(name = "ethcore_devLogsLevels")] #[rpc(name = "parity_devLogsLevels")]
fn dev_logs_levels(&self) -> Result<String, Error>; fn dev_logs_levels(&self) -> Result<String, Error>;
/// Returns chain name /// Returns chain name
#[rpc(name = "ethcore_netChain")] #[rpc(name = "parity_netChain")]
fn net_chain(&self) -> Result<String, Error>; fn net_chain(&self) -> Result<String, Error>;
/// Returns peers details /// Returns peers details
#[rpc(name = "ethcore_netPeers")] #[rpc(name = "parity_netPeers")]
fn net_peers(&self) -> Result<Peers, Error>; fn net_peers(&self) -> Result<Peers, Error>;
/// Returns network port /// Returns network port
#[rpc(name = "ethcore_netPort")] #[rpc(name = "parity_netPort")]
fn net_port(&self) -> Result<u16, Error>; fn net_port(&self) -> Result<u16, Error>;
/// Returns rpc settings /// Returns rpc settings
#[rpc(name = "ethcore_rpcSettings")] #[rpc(name = "parity_rpcSettings")]
fn rpc_settings(&self) -> Result<RpcSettings, Error>; fn rpc_settings(&self) -> Result<RpcSettings, Error>;
/// Returns node name /// Returns node name
#[rpc(name = "ethcore_nodeName")] #[rpc(name = "parity_nodeName")]
fn node_name(&self) -> Result<String, Error>; fn node_name(&self) -> Result<String, Error>;
/// Returns default extra data /// Returns default extra data
#[rpc(name = "ethcore_defaultExtraData")] #[rpc(name = "parity_defaultExtraData")]
fn default_extra_data(&self) -> Result<Bytes, Error>; fn default_extra_data(&self) -> Result<Bytes, Error>;
/// Returns distribution of gas price in latest blocks. /// Returns distribution of gas price in latest blocks.
#[rpc(name = "ethcore_gasPriceHistogram")] #[rpc(name = "parity_gasPriceHistogram")]
fn gas_price_histogram(&self) -> Result<Histogram, Error>; fn gas_price_histogram(&self) -> Result<Histogram, Error>;
/// Returns number of unsigned transactions waiting in the signer queue (if signer enabled) /// Returns number of unsigned transactions waiting in the signer queue (if signer enabled)
/// Returns error when signer is disabled /// Returns error when signer is disabled
#[rpc(name = "ethcore_unsignedTransactionsCount")] #[rpc(name = "parity_unsignedTransactionsCount")]
fn unsigned_transactions_count(&self) -> Result<usize, Error>; fn unsigned_transactions_count(&self) -> Result<usize, Error>;
/// Returns a cryptographically random phrase sufficient for securely seeding a secret key. /// Returns a cryptographically random phrase sufficient for securely seeding a secret key.
#[rpc(name = "ethcore_generateSecretPhrase")] #[rpc(name = "parity_generateSecretPhrase")]
fn generate_secret_phrase(&self) -> Result<String, Error>; fn generate_secret_phrase(&self) -> Result<String, Error>;
/// Returns whatever address would be derived from the given phrase if it were to seed a brainwallet. /// Returns whatever address would be derived from the given phrase if it were to seed a brainwallet.
#[rpc(name = "ethcore_phraseToAddress")] #[rpc(name = "parity_phraseToAddress")]
fn phrase_to_address(&self, String) -> Result<H160, Error>; fn phrase_to_address(&self, String) -> Result<H160, Error>;
/// Returns the value of the registrar for this network. /// Returns the value of the registrar for this network.
#[rpc(name = "ethcore_registryAddress")] #[rpc(name = "parity_registryAddress")]
fn registry_address(&self) -> Result<Option<H160>, Error>; fn registry_address(&self) -> Result<Option<H160>, Error>;
/// Returns all addresses if Fat DB is enabled (`--fat-db`), or null if not. /// Returns all addresses if Fat DB is enabled (`--fat-db`), or null if not.
#[rpc(name = "ethcore_listAccounts")] #[rpc(name = "parity_listAccounts")]
fn list_accounts(&self) -> Result<Option<Vec<H160>>, Error>; fn list_accounts(&self) -> Result<Option<Vec<H160>>, Error>;
/// Returns all storage keys of the given address (first parameter) if Fat DB is enabled (`--fat-db`), /// Returns all storage keys of the given address (first parameter) if Fat DB is enabled (`--fat-db`),
/// or null if not. /// or null if not.
#[rpc(name = "ethcore_listStorageKeys")] #[rpc(name = "parity_listStorageKeys")]
fn list_storage_keys(&self, H160) -> Result<Option<Vec<H256>>, Error>; fn list_storage_keys(&self, H160) -> Result<Option<Vec<H256>>, Error>;
/// Encrypt some data with a public key under ECIES. /// Encrypt some data with a public key under ECIES.
/// First parameter is the 512-byte destination public key, second is the message. /// First parameter is the 512-byte destination public key, second is the message.
#[rpc(name = "ethcore_encryptMessage")] #[rpc(name = "parity_encryptMessage")]
fn encrypt_message(&self, H512, Bytes) -> Result<Bytes, Error>; fn encrypt_message(&self, H512, Bytes) -> Result<Bytes, Error>;
/// Returns all pending transactions from transaction queue. /// Returns all pending transactions from transaction queue.
#[rpc(name = "ethcore_pendingTransactions")] #[rpc(name = "parity_pendingTransactions")]
fn pending_transactions(&self) -> Result<Vec<Transaction>, Error>; fn pending_transactions(&self) -> Result<Vec<Transaction>, Error>;
/// Hash a file content under given URL.
#[rpc(async, name = "ethcore_hashContent")]
fn hash_content(&self, Ready<H256>, String);
/// Returns current Trusted Signer port or an error if signer is disabled. /// Returns current Trusted Signer port or an error if signer is disabled.
#[rpc(name = "ethcore_signerPort")] #[rpc(name = "parity_signerPort")]
fn signer_port(&self) -> Result<u16, Error>; fn signer_port(&self) -> Result<u16, Error>;
/// Returns current Dapps Server port or an error if dapps server is disabled. /// Returns current Dapps Server port or an error if dapps server is disabled.
#[rpc(name = "ethcore_dappsPort")] #[rpc(name = "parity_dappsPort")]
fn dapps_port(&self) -> Result<u16, Error>; fn dapps_port(&self) -> Result<u16, Error>;
/// Returns next nonce for particular sender. Should include all transactions in the queue. /// Returns next nonce for particular sender. Should include all transactions in the queue.
#[rpc(name = "ethcore_nextNonce")] #[rpc(name = "parity_nextNonce")]
fn next_nonce(&self, H160) -> Result<U256, Error>; fn next_nonce(&self, H160) -> Result<U256, Error>;
/// Get the mode. Results one of: "active", "passive", "dark", "offline". /// Get the mode. Results one of: "active", "passive", "dark", "offline".
#[rpc(name = "ethcore_mode")] #[rpc(name = "parity_mode")]
fn mode(&self) -> Result<String, Error>; fn mode(&self) -> Result<String, Error>;
/// Get the enode of this node. /// Get the enode of this node.
#[rpc(name = "ethcore_enode")] #[rpc(name = "parity_enode")]
fn enode(&self) -> Result<String, Error>; fn enode(&self) -> Result<String, Error>;
/// Returns accounts information.
#[rpc(name = "parity_accounts")]
fn accounts(&self) -> Result<BTreeMap<String, BTreeMap<String, String>>, Error>;
} }
} }

View File

@ -0,0 +1,77 @@
// Copyright 2015, 2016 Ethcore (UK) Ltd.
// This file is part of Parity.
// Parity is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
// Parity 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 General Public License for more details.
// You should have received a copy of the GNU General Public License
// along with Parity. If not, see <http://www.gnu.org/licenses/>.
//! Parity Accounts-related rpc interface.
use std::collections::BTreeMap;
use jsonrpc_core::{Value, Error};
use v1::helpers::auto_args::Wrap;
use v1::types::{H160, H256};
build_rpc_trait! {
/// Personal Parity rpc interface.
pub trait ParityAccounts {
/// Returns accounts information.
#[rpc(name = "parity_accountsInfo")]
fn accounts_info(&self) -> Result<BTreeMap<String, Value>, Error>;
/// Creates new account from the given phrase using standard brainwallet mechanism.
/// Second parameter is password for the new account.
#[rpc(name = "parity_newAccountFromPhrase")]
fn new_account_from_phrase(&self, String, String) -> Result<H160, Error>;
/// Creates new account from the given JSON wallet.
/// Second parameter is password for the wallet and the new account.
#[rpc(name = "parity_newAccountFromWallet")]
fn new_account_from_wallet(&self, String, String) -> Result<H160, Error>;
/// Creates new account from the given raw secret.
/// Second parameter is password for the new account.
#[rpc(name = "parity_newAccountFromSecret")]
fn new_account_from_secret(&self, H256, String) -> Result<H160, Error>;
/// Returns true if given `password` would unlock given `account`.
/// Arguments: `account`, `password`.
#[rpc(name = "parity_testPassword")]
fn test_password(&self, H160, String) -> Result<bool, Error>;
/// Changes an account's password.
/// Arguments: `account`, `password`, `new_password`.
#[rpc(name = "parity_changePassword")]
fn change_password(&self, H160, String, String) -> Result<bool, Error>;
/// Set an account's name.
#[rpc(name = "parity_setAccountName")]
fn set_account_name(&self, H160, String) -> Result<bool, Error>;
/// Set an account's metadata string.
#[rpc(name = "parity_setAccountMeta")]
fn set_account_meta(&self, H160, String) -> Result<bool, Error>;
/// Returns accounts information.
#[rpc(name = "parity_setAccountVisiblity")]
fn set_account_visibility(&self, H160, H256, bool) -> Result<bool, Error>;
/// Imports a number of Geth accounts, with the list provided as the argument.
#[rpc(name = "parity_importGethAccounts")]
fn import_geth_accounts(&self, Vec<H160>) -> Result<Vec<H160>, Error>;
/// Returns the accounts available for importing from Geth.
#[rpc(name = "parity_listGethAccounts")]
fn geth_accounts(&self) -> Result<Vec<H160>, Error>;
}
}

View File

@ -14,74 +14,78 @@
// You should have received a copy of the GNU General Public License // You should have received a copy of the GNU General Public License
// along with Parity. If not, see <http://www.gnu.org/licenses/>. // along with Parity. If not, see <http://www.gnu.org/licenses/>.
//! Ethcore-specific rpc interface for operations altering the settings. //! Parity-specific rpc interface for operations altering the settings.
use jsonrpc_core::Error; use jsonrpc_core::Error;
use v1::helpers::auto_args::Wrap; use v1::helpers::auto_args::{Wrap, WrapAsync, Ready};
use v1::types::{Bytes, H160, U256}; use v1::types::{Bytes, H160, H256, U256};
build_rpc_trait! { build_rpc_trait! {
/// Ethcore-specific rpc interface for operations altering the settings. /// Parity-specific rpc interface for operations altering the settings.
pub trait EthcoreSet { pub trait ParitySet {
/// Sets new minimal gas price for mined blocks. /// Sets new minimal gas price for mined blocks.
#[rpc(name = "ethcore_setMinGasPrice")] #[rpc(name = "parity_setMinGasPrice")]
fn set_min_gas_price(&self, U256) -> Result<bool, Error>; fn set_min_gas_price(&self, U256) -> Result<bool, Error>;
/// Sets new gas floor target for mined blocks. /// Sets new gas floor target for mined blocks.
#[rpc(name = "ethcore_setGasFloorTarget")] #[rpc(name = "parity_setGasFloorTarget")]
fn set_gas_floor_target(&self, U256) -> Result<bool, Error>; fn set_gas_floor_target(&self, U256) -> Result<bool, Error>;
/// Sets new gas ceiling target for mined blocks. /// Sets new gas ceiling target for mined blocks.
#[rpc(name = "ethcore_setGasCeilTarget")] #[rpc(name = "parity_setGasCeilTarget")]
fn set_gas_ceil_target(&self, U256) -> Result<bool, Error>; fn set_gas_ceil_target(&self, U256) -> Result<bool, Error>;
/// Sets new extra data for mined blocks. /// Sets new extra data for mined blocks.
#[rpc(name = "ethcore_setExtraData")] #[rpc(name = "parity_setExtraData")]
fn set_extra_data(&self, Bytes) -> Result<bool, Error>; fn set_extra_data(&self, Bytes) -> Result<bool, Error>;
/// Sets new author for mined block. /// Sets new author for mined block.
#[rpc(name = "ethcore_setAuthor")] #[rpc(name = "parity_setAuthor")]
fn set_author(&self, H160) -> Result<bool, Error>; fn set_author(&self, H160) -> Result<bool, Error>;
/// Sets the limits for transaction queue. /// Sets the limits for transaction queue.
#[rpc(name = "ethcore_setTransactionsLimit")] #[rpc(name = "parity_setTransactionsLimit")]
fn set_transactions_limit(&self, usize) -> Result<bool, Error>; fn set_transactions_limit(&self, usize) -> Result<bool, Error>;
/// Sets the maximum amount of gas a single transaction may consume. /// Sets the maximum amount of gas a single transaction may consume.
#[rpc(name = "ethcore_setMaxTransactionGas")] #[rpc(name = "parity_setMaxTransactionGas")]
fn set_tx_gas_limit(&self, U256) -> Result<bool, Error>; fn set_tx_gas_limit(&self, U256) -> Result<bool, Error>;
/// Add a reserved peer. /// Add a reserved peer.
#[rpc(name = "ethcore_addReservedPeer")] #[rpc(name = "parity_addReservedPeer")]
fn add_reserved_peer(&self, String) -> Result<bool, Error>; fn add_reserved_peer(&self, String) -> Result<bool, Error>;
/// Remove a reserved peer. /// Remove a reserved peer.
#[rpc(name = "ethcore_removeReservedPeer")] #[rpc(name = "parity_removeReservedPeer")]
fn remove_reserved_peer(&self, String) -> Result<bool, Error>; fn remove_reserved_peer(&self, String) -> Result<bool, Error>;
/// Drop all non-reserved peers. /// Drop all non-reserved peers.
#[rpc(name = "ethcore_dropNonReservedPeers")] #[rpc(name = "parity_dropNonReservedPeers")]
fn drop_non_reserved_peers(&self) -> Result<bool, Error>; fn drop_non_reserved_peers(&self) -> Result<bool, Error>;
/// Accept non-reserved peers (default behavior) /// Accept non-reserved peers (default behavior)
#[rpc(name = "ethcore_acceptNonReservedPeers")] #[rpc(name = "parity_acceptNonReservedPeers")]
fn accept_non_reserved_peers(&self) -> Result<bool, Error>; fn accept_non_reserved_peers(&self) -> Result<bool, Error>;
/// Start the network. /// Start the network.
/// ///
/// Deprecated. Use `set_mode("active")` instead. /// Deprecated. Use `set_mode("active")` instead.
#[rpc(name = "ethcore_startNetwork")] #[rpc(name = "parity_startNetwork")]
fn start_network(&self) -> Result<bool, Error>; fn start_network(&self) -> Result<bool, Error>;
/// Stop the network. /// Stop the network.
/// ///
/// Deprecated. Use `set_mode("offline")` instead. /// Deprecated. Use `set_mode("offline")` instead.
#[rpc(name = "ethcore_stopNetwork")] #[rpc(name = "parity_stopNetwork")]
fn stop_network(&self) -> Result<bool, Error>; fn stop_network(&self) -> Result<bool, Error>;
/// Set the mode. Argument must be one of: "active", "passive", "dark", "offline". /// Set the mode. Argument must be one of: "active", "passive", "dark", "offline".
#[rpc(name = "ethcore_setMode")] #[rpc(name = "parity_setMode")]
fn set_mode(&self, String) -> Result<bool, Error>; fn set_mode(&self, String) -> Result<bool, Error>;
/// Hash a file content under given URL.
#[rpc(async, name = "parity_hashContent")]
fn hash_content(&self, Ready<H256>, String);
} }
} }

View File

@ -0,0 +1,52 @@
// Copyright 2015, 2016 Ethcore (UK) Ltd.
// This file is part of Parity.
// Parity is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
// Parity 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 General Public License for more details.
// You should have received a copy of the GNU General Public License
// along with Parity. If not, see <http://www.gnu.org/licenses/>.
//! ParitySigning rpc interface.
use std::sync::Arc;
use jsonrpc_core::*;
/// Signing methods implementation relying on unlocked accounts.
pub trait ParitySigning: Sized + Send + Sync + 'static {
/// Posts sign request asynchronously.
/// Will return a confirmation ID for later use with check_transaction.
fn post_sign(&self, _: Params) -> Result<Value, Error>;
/// Posts transaction asynchronously.
/// Will return a transaction ID for later use with check_transaction.
fn post_transaction(&self, _: Params) -> Result<Value, Error>;
/// Checks the progress of a previously posted request (transaction/sign).
/// Should be given a valid send_transaction ID.
/// Returns the transaction hash, the zero hash (not yet available),
/// or the signature,
/// or an error.
fn check_request(&self, _: Params) -> Result<Value, Error>;
/// Decrypt some ECIES-encrypted message.
/// First parameter is the address with which it is encrypted, second is the ciphertext.
fn decrypt_message(&self, _: Params, _: Ready);
/// Should be used to convert object to io delegate.
fn to_delegate(self) -> IoDelegate<Self> {
let mut delegate = IoDelegate::new(Arc::new(self));
delegate.add_method("parity_postSign", ParitySigning::post_sign);
delegate.add_method("parity_postTransaction", ParitySigning::post_transaction);
delegate.add_method("parity_checkRequest", ParitySigning::check_request);
delegate.add_async_method("parity_decryptMessage", ParitySigning::decrypt_message);
delegate
}
}

View File

@ -15,11 +15,10 @@
// along with Parity. If not, see <http://www.gnu.org/licenses/>. // along with Parity. If not, see <http://www.gnu.org/licenses/>.
//! Personal rpc interface. //! Personal rpc interface.
use std::collections::BTreeMap; use jsonrpc_core::Error;
use jsonrpc_core::{Value, Error};
use v1::helpers::auto_args::Wrap; use v1::helpers::auto_args::Wrap;
use v1::types::{H160, H256, U256, TransactionRequest, TransactionModification, ConfirmationRequest}; use v1::types::{H160, H256, TransactionRequest};
build_rpc_trait! { build_rpc_trait! {
/// Personal rpc interface. Safe (read-only) functions. /// Personal rpc interface. Safe (read-only) functions.
@ -28,91 +27,17 @@ build_rpc_trait! {
#[rpc(name = "personal_listAccounts")] #[rpc(name = "personal_listAccounts")]
fn accounts(&self) -> Result<Vec<H160>, Error>; fn accounts(&self) -> Result<Vec<H160>, Error>;
/// Returns accounts information.
#[rpc(name = "personal_accountsInfo")]
fn accounts_info(&self) -> Result<BTreeMap<String, Value>, Error>;
}
}
build_rpc_trait! {
/// Personal rpc methods altering stored accounts or their settings.
pub trait PersonalAccounts {
/// Creates new account (it becomes new current unlocked account) /// Creates new account (it becomes new current unlocked account)
/// Param is the password for the account. /// Param is the password for the account.
#[rpc(name = "personal_newAccount")] #[rpc(name = "personal_newAccount")]
fn new_account(&self, String) -> Result<H160, Error>; fn new_account(&self, String) -> Result<H160, Error>;
/// Creates new account from the given phrase using standard brainwallet mechanism.
/// Second parameter is password for the new account.
#[rpc(name = "personal_newAccountFromPhrase")]
fn new_account_from_phrase(&self, String, String) -> Result<H160, Error>;
/// Creates new account from the given JSON wallet.
/// Second parameter is password for the wallet and the new account.
#[rpc(name = "personal_newAccountFromWallet")]
fn new_account_from_wallet(&self, String, String) -> Result<H160, Error>;
/// Creates new account from the given raw secret.
/// Second parameter is password for the new account.
#[rpc(name = "personal_newAccountFromSecret")]
fn new_account_from_secret(&self, H256, String) -> Result<H160, Error>;
/// Unlocks specified account for use (can only be one unlocked account at one moment) /// Unlocks specified account for use (can only be one unlocked account at one moment)
#[rpc(name = "personal_unlockAccount")] #[rpc(name = "personal_unlockAccount")]
fn unlock_account(&self, H160, String, Option<u64>) -> Result<bool, Error>; fn unlock_account(&self, H160, String, Option<u64>) -> Result<bool, Error>;
/// Returns true if given `password` would unlock given `account`.
/// Arguments: `account`, `password`.
#[rpc(name = "personal_testPassword")]
fn test_password(&self, H160, String) -> Result<bool, Error>;
/// Changes an account's password.
/// Arguments: `account`, `password`, `new_password`.
#[rpc(name = "personal_changePassword")]
fn change_password(&self, H160, String, String) -> Result<bool, Error>;
/// Sends transaction and signs it in single call. The account is not unlocked in such case. /// Sends transaction and signs it in single call. The account is not unlocked in such case.
#[rpc(name = "personal_signAndSendTransaction")] #[rpc(name = "personal_signAndSendTransaction")]
fn sign_and_send_transaction(&self, TransactionRequest, String) -> Result<H256, Error>; fn sign_and_send_transaction(&self, TransactionRequest, String) -> Result<H256, Error>;
/// Set an account's name.
#[rpc(name = "personal_setAccountName")]
fn set_account_name(&self, H160, String) -> Result<bool, Error>;
/// Set an account's metadata string.
#[rpc(name = "personal_setAccountMeta")]
fn set_account_meta(&self, H160, String) -> Result<bool, Error>;
/// Imports a number of Geth accounts, with the list provided as the argument.
#[rpc(name = "personal_importGethAccounts")]
fn import_geth_accounts(&self, Vec<H160>) -> Result<Vec<H160>, Error>;
/// Returns the accounts available for importing from Geth.
#[rpc(name = "personal_listGethAccounts")]
fn geth_accounts(&self) -> Result<Vec<H160>, Error>;
} }
} }
build_rpc_trait! {
/// Personal extension for confirmations rpc interface.
pub trait PersonalSigner {
/// Returns a list of items to confirm.
#[rpc(name = "personal_requestsToConfirm")]
fn requests_to_confirm(&self) -> Result<Vec<ConfirmationRequest>, Error>;
/// Confirm specific request.
#[rpc(name = "personal_confirmRequest")]
fn confirm_request(&self, U256, TransactionModification, String) -> Result<Value, Error>;
/// Reject the confirmation request.
#[rpc(name = "personal_rejectRequest")]
fn reject_request(&self, U256) -> Result<bool, Error>;
/// Generates new authorization token.
#[rpc(name = "personal_generateAuthorizationToken")]
fn generate_token(&self) -> Result<String, Error>;
}
}

Some files were not shown because too many files have changed in this diff Show More