From 6062aa5dcd5ef6eae95d07e0dede9a7a01ef5ef8 Mon Sep 17 00:00:00 2001 From: "Denis S. Soldatov aka General-Beck" Date: Wed, 8 Mar 2017 23:49:34 +0300 Subject: [PATCH 01/71] fix windows build rm parity.pdb --- .gitlab-ci.yml | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index a11cbc2a6..6d8215354 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -460,9 +460,8 @@ windows: - zip win-installer.zip InstallParity.exe InstallParity.exe.md5 - md5sums win-installer.zip > win-installer.zip.md5 - cd ..\target\release\ - - md5sums parity.exe parity.pdb > parity.md5 - md5sums parity.exe > parity.exe.md5 - - zip parity.zip parity.exe parity.pdb parity.md5 + - zip parity.zip parity.exe parity.md5 - md5sums parity.zip > parity.zip.md5 - cd ..\.. - aws configure set aws_access_key_id %s3_key% From ea020948fcf2833ffaebc4184af0bdfd8fcabc0a Mon Sep 17 00:00:00 2001 From: "Denis S. Soldatov aka General-Beck" Date: Thu, 9 Mar 2017 01:34:00 +0300 Subject: [PATCH 02/71] push-release<->build --- .gitlab-ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 6d8215354..32cb7e947 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -1,8 +1,8 @@ stages: - test - js-build - - build - push-release + - build variables: GIT_DEPTH: "3" SIMPLECOV: "true" From 5342a482b5f5658f67f225747bc5f61dad9347e2 Mon Sep 17 00:00:00 2001 From: Nicolas Gotchac Date: Thu, 9 Mar 2017 16:55:57 +0100 Subject: [PATCH 03/71] Fixes to the Registry dapp (#4838) * Fix wrong ABI methods * Fix --- js/src/dapps/registry/Lookup/actions.js | 17 ++++++++++++----- js/src/dapps/registry/Records/actions.js | 5 +++-- js/src/dapps/registry/ui/image.js | 2 +- 3 files changed, 16 insertions(+), 8 deletions(-) diff --git a/js/src/dapps/registry/Lookup/actions.js b/js/src/dapps/registry/Lookup/actions.js index 6f80fac0d..514039272 100644 --- a/js/src/dapps/registry/Lookup/actions.js +++ b/js/src/dapps/registry/Lookup/actions.js @@ -14,7 +14,7 @@ // You should have received a copy of the GNU General Public License // along with Parity. If not, see . -import { sha3 } from '../parity.js'; +import { api, sha3 } from '../parity.js'; import { getOwner } from '../util/registry'; export const clear = () => ({ type: 'lookup clear' }); @@ -34,14 +34,21 @@ export const lookup = (name, key) => (dispatch, getState) => { return; } - const getAddress = contract.functions - .find((f) => f.name === 'getAddress'); + const method = key === 'A' + ? contract.instance.getAddress + : contract.instance.getData; name = name.toLowerCase(); dispatch(lookupStart(name, key)); - getAddress.call({}, [ sha3.text(name), key ]) - .then((address) => dispatch(success('lookup', address))) + method.call({}, [ sha3.text(name), key ]) + .then((result) => { + if (key !== 'A') { + result = api.util.bytesToHex(result); + } + + dispatch(success('lookup', result)); + }) .catch((err) => { console.error(`could not lookup ${key} for ${name}`); if (err) { diff --git a/js/src/dapps/registry/Records/actions.js b/js/src/dapps/registry/Records/actions.js index 11c2ec405..9f0d1beff 100644 --- a/js/src/dapps/registry/Records/actions.js +++ b/js/src/dapps/registry/Records/actions.js @@ -46,8 +46,9 @@ export const update = (name, key, value) => (dispatch, getState) => { throw new Error(`you are not the owner of "${name}"`); } - const fnName = key === 'A' ? 'setAddress' : 'set'; - const method = contract.instance[fnName]; + const method = key === 'A' + ? contract.instance.setAddress + : contract.instance.setData || contract.instance.set; const options = { from: account.address diff --git a/js/src/dapps/registry/ui/image.js b/js/src/dapps/registry/ui/image.js index 1aee21457..3f0a90abe 100644 --- a/js/src/dapps/registry/ui/image.js +++ b/js/src/dapps/registry/ui/image.js @@ -34,7 +34,7 @@ export default (address) => { return ( { From b19663581616cb878f1e3a8e24b2f2924cd8e137 Mon Sep 17 00:00:00 2001 From: GitLab Build Bot Date: Thu, 9 Mar 2017 16:09:29 +0000 Subject: [PATCH 04/71] [ci skip] js-precompiled 20170309-160350 --- Cargo.lock | 2 +- js/package.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 6924cfe00..f93042443 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1706,7 +1706,7 @@ dependencies = [ [[package]] name = "parity-ui-precompiled" version = "1.4.0" -source = "git+https://github.com/ethcore/js-precompiled.git#9eef2b78d363560fe942062caaaa7f6b1d64dd17" +source = "git+https://github.com/ethcore/js-precompiled.git#eff97db9fbbe974894056a80b382eb71d6438147" dependencies = [ "parity-dapps-glue 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", ] diff --git a/js/package.json b/js/package.json index 85d906b88..7deacc6e8 100644 --- a/js/package.json +++ b/js/package.json @@ -1,6 +1,6 @@ { "name": "parity.js", - "version": "1.7.3", + "version": "1.7.4", "main": "release/index.js", "jsnext:main": "src/index.js", "author": "Parity Team ", From bd00256e0c4697bc0dd17f22dd5b96a546fbac04 Mon Sep 17 00:00:00 2001 From: Nicolas Gotchac Date: Thu, 9 Mar 2017 19:55:11 +0100 Subject: [PATCH 05/71] Uniq array of ids (#4843) --- js/src/util/dapps.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/js/src/util/dapps.js b/js/src/util/dapps.js index dd522dc1b..a82b2ae1c 100644 --- a/js/src/util/dapps.js +++ b/js/src/util/dapps.js @@ -140,7 +140,7 @@ export function fetchRegistryAppIds () { return (new BigNumber(appId)).gt(0) && !builtinApps.find((app) => app.id === appId); }); - return appIds; + return uniq(appIds); }) .catch((error) => { console.warn('DappsStore:fetchRegistryAppIds', error); From 3478c16e10f24bca3cc1321e387a732c12d41dbc Mon Sep 17 00:00:00 2001 From: Nicolas Gotchac Date: Thu, 9 Mar 2017 19:55:48 +0100 Subject: [PATCH 06/71] Added React Hot Reload to dapps + TokenDeplpoy fix (#4846) --- js/src/dapps/githubhint.js | 18 +++++++++++- js/src/dapps/localtx.js | 18 +++++++++++- js/src/dapps/signaturereg.js | 18 +++++++++++- js/src/dapps/tokendeploy.js | 41 ++++++++++++++++++++++------ js/src/dapps/tokendeploy/services.js | 2 +- js/src/dapps/tokenreg.js | 20 ++++++++++++-- 6 files changed, 103 insertions(+), 14 deletions(-) diff --git a/js/src/dapps/githubhint.js b/js/src/dapps/githubhint.js index 14db7c7b3..1e55b91f5 100644 --- a/js/src/dapps/githubhint.js +++ b/js/src/dapps/githubhint.js @@ -16,6 +16,7 @@ import ReactDOM from 'react-dom'; import React from 'react'; +import { AppContainer } from 'react-hot-loader'; import injectTapEventPlugin from 'react-tap-event-plugin'; injectTapEventPlugin(); @@ -27,6 +28,21 @@ import '../../assets/fonts/RobotoMono/font.css'; import './style.css'; ReactDOM.render( - , + + + , document.querySelector('#container') ); + +if (module.hot) { + module.hot.accept('./githubhint/Application/index.js', () => { + require('./githubhint/Application/index.js'); + + ReactDOM.render( + + + , + document.querySelector('#container') + ); + }); +} diff --git a/js/src/dapps/localtx.js b/js/src/dapps/localtx.js index 8d8db8caf..4625ded20 100644 --- a/js/src/dapps/localtx.js +++ b/js/src/dapps/localtx.js @@ -16,6 +16,7 @@ import ReactDOM from 'react-dom'; import React from 'react'; +import { AppContainer } from 'react-hot-loader'; import injectTapEventPlugin from 'react-tap-event-plugin'; injectTapEventPlugin(); @@ -27,6 +28,21 @@ import '../../assets/fonts/RobotoMono/font.css'; import './style.css'; ReactDOM.render( - , + + + , document.querySelector('#container') ); + +if (module.hot) { + module.hot.accept('./localtx/Application/index.js', () => { + require('./localtx/Application/index.js'); + + ReactDOM.render( + + + , + document.querySelector('#container') + ); + }); +} diff --git a/js/src/dapps/signaturereg.js b/js/src/dapps/signaturereg.js index c20e45170..61b67aab0 100644 --- a/js/src/dapps/signaturereg.js +++ b/js/src/dapps/signaturereg.js @@ -16,6 +16,7 @@ import ReactDOM from 'react-dom'; import React from 'react'; +import { AppContainer } from 'react-hot-loader'; import injectTapEventPlugin from 'react-tap-event-plugin'; injectTapEventPlugin(); @@ -27,6 +28,21 @@ import '../../assets/fonts/RobotoMono/font.css'; import './style.css'; ReactDOM.render( - , + + + , document.querySelector('#container') ); + +if (module.hot) { + module.hot.accept('./signaturereg/Application/index.js', () => { + require('./signaturereg/Application/index.js'); + + ReactDOM.render( + + + , + document.querySelector('#container') + ); + }); +} diff --git a/js/src/dapps/tokendeploy.js b/js/src/dapps/tokendeploy.js index a1808199e..b6de05d05 100644 --- a/js/src/dapps/tokendeploy.js +++ b/js/src/dapps/tokendeploy.js @@ -17,6 +17,7 @@ import ReactDOM from 'react-dom'; import React from 'react'; import { Redirect, Router, Route, hashHistory } from 'react-router'; +import { AppContainer } from 'react-hot-loader'; import injectTapEventPlugin from 'react-tap-event-plugin'; injectTapEventPlugin(); @@ -31,13 +32,37 @@ import '../../assets/fonts/RobotoMono/font.css'; import './style.css'; ReactDOM.render( - - - - - - - - , + + + + + + + + + + , document.querySelector('#container') ); + +if (module.hot) { + module.hot.accept('./tokendeploy/Application/index.js', () => { + require('./tokendeploy/Application/index.js'); + require('./tokendeploy/Overview/index.js'); + require('./tokendeploy/Transfer/index.js'); + + ReactDOM.render( + + + + + + + + + + , + document.querySelector('#container') + ); + }); +} diff --git a/js/src/dapps/tokendeploy/services.js b/js/src/dapps/tokendeploy/services.js index 9ca4c4f56..6cfeff05f 100644 --- a/js/src/dapps/tokendeploy/services.js +++ b/js/src/dapps/tokendeploy/services.js @@ -119,7 +119,7 @@ export function attachInstances () { .all([ api.parity.registryAddress(), api.parity.netChain(), - api.partiy.netVersion() + api.net.version() ]) .then(([registryAddress, netChain, _netVersion]) => { const registry = api.newContract(abis.registry, registryAddress).instance; diff --git a/js/src/dapps/tokenreg.js b/js/src/dapps/tokenreg.js index 5c6bb4bd1..3e8dc9b19 100644 --- a/js/src/dapps/tokenreg.js +++ b/js/src/dapps/tokenreg.js @@ -17,6 +17,7 @@ import ReactDOM from 'react-dom'; import React from 'react'; import { Provider } from 'react-redux'; +import { AppContainer } from 'react-hot-loader'; import injectTapEventPlugin from 'react-tap-event-plugin'; injectTapEventPlugin(); @@ -29,10 +30,25 @@ import '../../assets/fonts/RobotoMono/font.css'; import './style.css'; ReactDOM.render( - ( + - ), + , document.querySelector('#container') ); + +if (module.hot) { + module.hot.accept('./tokenreg/Container.js', () => { + require('./tokenreg/Container.js'); + + ReactDOM.render( + + + + + , + document.querySelector('#container') + ); + }); +} From 3bb66d03eedcc33a95418911d95b57311989fee5 Mon Sep 17 00:00:00 2001 From: Nicolas Gotchac Date: Thu, 9 Mar 2017 19:56:10 +0100 Subject: [PATCH 07/71] Fix method decoding (#4845) * Fix contract deployment method decoding in Signer * Linting --- js/src/ui/MethodDecoding/methodDecodingStore.js | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/js/src/ui/MethodDecoding/methodDecodingStore.js b/js/src/ui/MethodDecoding/methodDecodingStore.js index 05a8f8546..1b8671465 100644 --- a/js/src/ui/MethodDecoding/methodDecodingStore.js +++ b/js/src/ui/MethodDecoding/methodDecodingStore.js @@ -138,6 +138,10 @@ export default class MethodDecodingStore { return Promise.resolve(result); } + if (!transaction.to) { + return this.decodeContractCreation(result); + } + let signature; try { @@ -206,7 +210,7 @@ export default class MethodDecodingStore { }); } - decodeContractCreation (data, contractAddress) { + decodeContractCreation (data, contractAddress = '') { const result = { ...data, contract: true, From 5e54c0fa915335400f292efdae842b8dce22afdd Mon Sep 17 00:00:00 2001 From: GitLab Build Bot Date: Thu, 9 Mar 2017 19:09:36 +0000 Subject: [PATCH 08/71] [ci skip] js-precompiled 20170309-190359 --- Cargo.lock | 2 +- js/package.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index f93042443..b54bd27db 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1706,7 +1706,7 @@ dependencies = [ [[package]] name = "parity-ui-precompiled" version = "1.4.0" -source = "git+https://github.com/ethcore/js-precompiled.git#eff97db9fbbe974894056a80b382eb71d6438147" +source = "git+https://github.com/ethcore/js-precompiled.git#76a31e0424a11a8249ee0d9c9696b1cb7b2a71c1" dependencies = [ "parity-dapps-glue 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", ] diff --git a/js/package.json b/js/package.json index 7deacc6e8..87a45b5aa 100644 --- a/js/package.json +++ b/js/package.json @@ -1,6 +1,6 @@ { "name": "parity.js", - "version": "1.7.4", + "version": "1.7.5", "main": "release/index.js", "jsnext:main": "src/index.js", "author": "Parity Team ", From be87151f1cfe8359134a464dcb240fde2e538d3c Mon Sep 17 00:00:00 2001 From: Nicolas Gotchac Date: Fri, 10 Mar 2017 10:08:16 +0100 Subject: [PATCH 09/71] Fix TxViewer when no `to` (contract deployment) (#4847) * Added React Hot Reload to dapps + TokenDeplpoy fix * Fixes to the LocalTx dapp * Don't send the nonce for mined transactions * Don't encode empty to values for options --- js/src/api/format/input.js | 9 ++- js/src/api/format/input.spec.js | 7 ++ .../dapps/localtx/Application/application.css | 24 ++++++ .../dapps/localtx/Application/application.js | 1 - .../dapps/localtx/Transaction/transaction.css | 8 ++ .../dapps/localtx/Transaction/transaction.js | 75 ++++++++++++------- 6 files changed, 93 insertions(+), 31 deletions(-) diff --git a/js/src/api/format/input.js b/js/src/api/format/input.js index 74ddd4e56..34871c911 100644 --- a/js/src/api/format/input.js +++ b/js/src/api/format/input.js @@ -143,8 +143,15 @@ export function inOptions (options) { if (options) { Object.keys(options).forEach((key) => { switch (key) { - case 'from': case 'to': + // Don't encode the `to` option if it's empty + // (eg. contract deployments) + if (options[key]) { + options[key] = inAddress(options[key]); + } + break; + + case 'from': options[key] = inAddress(options[key]); break; diff --git a/js/src/api/format/input.spec.js b/js/src/api/format/input.spec.js index 450ff61cc..4b82bd1ef 100644 --- a/js/src/api/format/input.spec.js +++ b/js/src/api/format/input.spec.js @@ -208,6 +208,13 @@ describe('api/format/input', () => { }); }); + it('does not encode an empty `to` value', () => { + const options = { to: '' }; + const formatted = inOptions(options); + + expect(formatted.to).to.equal(''); + }); + ['gas', 'gasPrice', 'value', 'minBlock', 'nonce'].forEach((input) => { it(`formats ${input} number as hexnumber`, () => { const block = {}; diff --git a/js/src/dapps/localtx/Application/application.css b/js/src/dapps/localtx/Application/application.css index 4b5f0bc31..15762c5d4 100644 --- a/js/src/dapps/localtx/Application/application.css +++ b/js/src/dapps/localtx/Application/application.css @@ -15,5 +15,29 @@ th { text-align: center; } + + td { + text-align: center; + } + } + + button { + background-color: rgba(0, 136, 170, 1); + border: none; + border-radius: 5px; + color: white; + font-size: 1rem; + padding: 0.5em 1em; + width: 100%; + + &:hover { + background-color: rgba(0, 136, 170, 0.8); + cursor: pointer; + } + } + + input { + font-size: 1rem; + padding: 0.5em 1em; } } diff --git a/js/src/dapps/localtx/Application/application.js b/js/src/dapps/localtx/Application/application.js index a36eb84f4..8efadcf1a 100644 --- a/js/src/dapps/localtx/Application/application.js +++ b/js/src/dapps/localtx/Application/application.js @@ -70,7 +70,6 @@ export default class Application extends Component { local[tx.hash].transaction = tx; local[tx.hash].stats = data.stats; }); - // Convert local transactions to array const localTransactions = Object.keys(local).map(hash => { const data = local[hash]; diff --git a/js/src/dapps/localtx/Transaction/transaction.css b/js/src/dapps/localtx/Transaction/transaction.css index c49d9479f..b06942ed7 100644 --- a/js/src/dapps/localtx/Transaction/transaction.css +++ b/js/src/dapps/localtx/Transaction/transaction.css @@ -6,6 +6,14 @@ } } +.txhash { + display: inline-block; + overflow: hidden; + padding-right: 3ch; + text-overflow: ellipsis; + width: 10ch; +} + .transaction { td { padding: 7px 15px; diff --git a/js/src/dapps/localtx/Transaction/transaction.js b/js/src/dapps/localtx/Transaction/transaction.js index 56a697853..554c2b757 100644 --- a/js/src/dapps/localtx/Transaction/transaction.js +++ b/js/src/dapps/localtx/Transaction/transaction.js @@ -31,8 +31,8 @@ class BaseTransaction extends Component { renderHash (hash) { return ( - - { this.shortHash(hash) } + + { hash } ); } @@ -206,7 +206,10 @@ export class LocalTransaction extends BaseTransaction { From - Gas Price / Gas + Gas Price + + + Gas Status @@ -224,18 +227,18 @@ export class LocalTransaction extends BaseTransaction { toggleResubmit = () => { const { transaction } = this.props; - const { isResubmitting, gasPrice } = this.state; + const { isResubmitting } = this.state; - this.setState({ + const nextState = { isResubmitting: !isResubmitting - }); + }; - if (gasPrice === null) { - this.setState({ - gasPrice: `0x${transaction.gasPrice.toString(16)}`, - gas: `0x${transaction.gas.toString(16)}` - }); + if (!isResubmitting) { + nextState.gasPrice = api.util.fromWei(transaction.gasPrice, 'shannon').toNumber(); + nextState.gas = transaction.gas.div(1000000).toNumber(); } + + this.setState(nextState); }; setGasPrice = el => { @@ -251,16 +254,15 @@ export class LocalTransaction extends BaseTransaction { }; sendTransaction = () => { - const { transaction } = this.props; + const { transaction, status } = this.props; const { gasPrice, gas } = this.state; const newTransaction = { from: transaction.from, - to: transaction.to, - nonce: transaction.nonce, value: transaction.value, data: transaction.input, - gasPrice, gas + gasPrice: api.util.toWei(gasPrice, 'shannon'), + gas: new BigNumber(gas).mul(1000000) }; this.setState({ @@ -268,11 +270,21 @@ export class LocalTransaction extends BaseTransaction { isSending: true }); - const closeSending = () => this.setState({ - isSending: false, - gasPrice: null, - gas: null - }); + const closeSending = () => { + this.setState({ + isSending: false, + gasPrice: null, + gas: null + }); + }; + + if (transaction.to) { + newTransaction.to = transaction.to; + } + + if (!['mined', 'replaced'].includes(status)) { + newTransaction.nonce = transaction.nonce; + } api.eth.sendTransaction(newTransaction) .then(closeSending) @@ -290,9 +302,9 @@ export class LocalTransaction extends BaseTransaction { const resubmit = isSending ? ( 'sending...' ) : ( - + ); return ( @@ -308,7 +320,8 @@ export class LocalTransaction extends BaseTransaction { { this.renderGasPrice(transaction) } -
+ + { this.renderGas(transaction) } @@ -345,9 +358,9 @@ export class LocalTransaction extends BaseTransaction { return ( - + { this.renderHash(transaction.hash) } @@ -357,20 +370,24 @@ export class LocalTransaction extends BaseTransaction { + shannon + + + MGas - + ); From aedc473f64e72ded88077be3b9854a77ec071e0f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20Drwi=C4=99ga?= Date: Fri, 10 Mar 2017 10:11:37 +0100 Subject: [PATCH 10/71] Lowering threshold for transactions above gas limit (#4831) --- ethcore/src/miner/transaction_queue.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ethcore/src/miner/transaction_queue.rs b/ethcore/src/miner/transaction_queue.rs index d686a3ff5..9a3e6af1a 100644 --- a/ethcore/src/miner/transaction_queue.rs +++ b/ethcore/src/miner/transaction_queue.rs @@ -485,7 +485,7 @@ pub struct AccountDetails { } /// Transactions with `gas > (gas_limit + gas_limit * Factor(in percents))` are not imported to the queue. -const GAS_LIMIT_HYSTERESIS: usize = 10; // (100/GAS_LIMIT_HYSTERESIS) % +const GAS_LIMIT_HYSTERESIS: usize = 200; // (100/GAS_LIMIT_HYSTERESIS) % /// Describes the strategy used to prioritize transactions in the queue. #[cfg_attr(feature="dev", allow(enum_variant_names))] @@ -1867,7 +1867,7 @@ pub mod test { // then assert_eq!(unwrap_tx_err(res), TransactionError::GasLimitExceeded { - limit: U256::from(55_000), // Should be 110% of set_gas_limit + limit: U256::from(50_250), // Should be 100.5% of set_gas_limit got: gas, }); let stats = txq.status(); From 608c0dc613ea6d1ec4c8ddb50a1100d1de008a85 Mon Sep 17 00:00:00 2001 From: "Denis S. Soldatov aka General-Beck" Date: Fri, 10 Mar 2017 12:12:16 +0300 Subject: [PATCH 11/71] CI: test coverage (for core) (#4832) * test coverage * update gitlab add `git submodule update --init --recursive` * test exec coverage in docker runner * tags kcov --- .gitlab-ci.yml | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 32cb7e947..e71b99ec0 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -503,6 +503,18 @@ docker-build: - sh scripts/docker-build.sh $DOCKER_TAG tags: - docker +test-coverage: + stage: test + only: + - coverage + script: + - git submodule update --init --recursive + - scripts/cov.sh + - COVERAGE=$(grep -Po 'covered":.*?[^\\]"' target/kcov/index.json | grep "[0-9]*\.[0-9]" -o) + - echo "Coverage:" $COVERAGE + tags: + - kcov + allow_failure: true test-darwin: stage: test only: From 0ab0cb1173f96c718cb1da4d2bbdad4f6547cc81 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20Drwi=C4=99ga?= Date: Fri, 10 Mar 2017 10:25:13 +0100 Subject: [PATCH 12/71] Fix RPC errors. Implement geth-compatibility option to return correct pending nonce. (#4837) --- parity/rpc_apis.rs | 1 + rpc/src/v1/helpers/errors.rs | 12 ++++++ rpc/src/v1/impls/eth.rs | 48 ++++++++++++++++------- rpc/src/v1/impls/light/eth.rs | 2 +- rpc/src/v1/impls/light/parity.rs | 2 +- rpc/src/v1/impls/parity.rs | 2 +- rpc/src/v1/tests/helpers/miner_service.rs | 17 ++++++++ rpc/src/v1/tests/mocked/eth.rs | 33 ++++++++++++++-- 8 files changed, 96 insertions(+), 21 deletions(-) diff --git a/parity/rpc_apis.rs b/parity/rpc_apis.rs index 548e84995..469245c19 100644 --- a/parity/rpc_apis.rs +++ b/parity/rpc_apis.rs @@ -215,6 +215,7 @@ pub fn setup_rpc(stats: Arc, deps: Arc, apis: ApiSet) -> &deps.miner, &deps.external_miner, EthClientOptions { + pending_nonce_from_queue: deps.geth_compatibility, allow_pending_receipt_query: !deps.geth_compatibility, send_block_number_in_get_work: !deps.geth_compatibility, } diff --git a/rpc/src/v1/helpers/errors.rs b/rpc/src/v1/helpers/errors.rs index 0be3f7240..1f98b922d 100644 --- a/rpc/src/v1/helpers/errors.rs +++ b/rpc/src/v1/helpers/errors.rs @@ -37,6 +37,7 @@ mod codes { pub const TRANSACTION_ERROR: i64 = -32010; pub const EXECUTION_ERROR: i64 = -32015; pub const EXCEPTION_ERROR: i64 = -32016; + pub const DATABASE_ERROR: i64 = -32017; pub const ACCOUNT_LOCKED: i64 = -32020; pub const PASSWORD_INVALID: i64 = -32021; pub const ACCOUNT_ERROR: i64 = -32023; @@ -100,6 +101,9 @@ pub fn account(error: &str, details: T) -> Error { } } +/// Internal error signifying a logic error in code. +/// Should not be used when function can just fail +/// because of invalid parameters or incomplete node state. pub fn internal(error: &str, data: T) -> Error { Error { code: ErrorCode::InternalError, @@ -216,6 +220,14 @@ pub fn encryption_error(error: T) -> Error { } } +pub fn database_error(error: T) -> Error { + Error { + code: ErrorCode::ServerError(codes::DATABASE_ERROR), + message: "Database error.".into(), + data: Some(Value::String(format!("{:?}", error))), + } +} + pub fn from_fetch_error(error: T) -> Error { Error { code: ErrorCode::ServerError(codes::FETCH_ERROR), diff --git a/rpc/src/v1/impls/eth.rs b/rpc/src/v1/impls/eth.rs index 6df8f5278..8da7063f4 100644 --- a/rpc/src/v1/impls/eth.rs +++ b/rpc/src/v1/impls/eth.rs @@ -58,15 +58,28 @@ const EXTRA_INFO_PROOF: &'static str = "Object exists in in blockchain (fetched /// Eth RPC options pub struct EthClientOptions { + /// Return nonce from transaction queue when pending block not available. + pub pending_nonce_from_queue: bool, /// Returns receipt from pending blocks pub allow_pending_receipt_query: bool, /// Send additional block number when asking for work pub send_block_number_in_get_work: bool, } +impl EthClientOptions { + /// Creates new default `EthClientOptions` and allows alterations + /// by provided function. + pub fn with(fun: F) -> Self { + let mut options = Self::default(); + fun(&mut options); + options + } +} + impl Default for EthClientOptions { fn default() -> Self { EthClientOptions { + pending_nonce_from_queue: false, allow_pending_receipt_query: true, send_block_number_in_get_work: true, } @@ -227,7 +240,7 @@ impl EthClient where store .note_dapp_used(dapp.clone()) .and_then(|_| store.dapp_addresses(dapp)) - .map_err(|e| errors::internal("Could not fetch accounts.", e)) + .map_err(|e| errors::account("Could not fetch accounts.", e)) } } @@ -352,18 +365,16 @@ impl Eth for EthClient where fn balance(&self, address: RpcH160, num: Trailing) -> BoxFuture { let address = address.into(); + let client = take_weakf!(self.client); let res = match num.0.clone() { BlockNumber::Pending => { - let client = take_weakf!(self.client); match take_weakf!(self.miner).balance(&*client, &address) { Some(balance) => Ok(balance.into()), - None => Err(errors::internal("Unable to load balance from database", "")) + None => Err(errors::database_error("latest balance missing")) } } id => { - let client = take_weakf!(self.client); - try_bf!(check_known(&*client, id.clone())); match client.balance(&address, id.into()) { Some(balance) => Ok(balance.into()), @@ -384,7 +395,7 @@ impl Eth for EthClient where let client = take_weakf!(self.client); match take_weakf!(self.miner).storage_at(&*client, &address, &H256::from(position)) { Some(s) => Ok(s.into()), - None => Err(errors::internal("Unable to load storage from database", "")) + None => Err(errors::database_error("latest storage missing")) } } id => { @@ -403,17 +414,26 @@ impl Eth for EthClient where fn transaction_count(&self, address: RpcH160, num: Trailing) -> BoxFuture { let address: Address = RpcH160::into(address); + let client = take_weakf!(self.client); + let miner = take_weakf!(self.miner); + let res = match num.0.clone() { - BlockNumber::Pending => { - let client = take_weakf!(self.client); - match take_weakf!(self.miner).nonce(&*client, &address) { + BlockNumber::Pending if self.options.pending_nonce_from_queue => { + let nonce = miner.last_nonce(&address) + .map(|n| n + 1.into()) + .or_else(|| miner.nonce(&*client, &address)); + match nonce { Some(nonce) => Ok(nonce.into()), - None => Err(errors::internal("Unable to load nonce from database", "")) + None => Err(errors::database_error("latest nonce missing")) + } + } + BlockNumber::Pending => { + match miner.nonce(&*client, &address) { + Some(nonce) => Ok(nonce.into()), + None => Err(errors::database_error("latest nonce missing")) } } id => { - let client = take_weakf!(self.client); - try_bf!(check_known(&*client, id.clone())); match client.nonce(&address, id.into()) { Some(nonce) => Ok(nonce.into()), @@ -464,7 +484,7 @@ impl Eth for EthClient where let client = take_weakf!(self.client); match take_weakf!(self.miner).code(&*client, &address) { Some(code) => Ok(code.map_or_else(Bytes::default, Bytes::new)), - None => Err(errors::internal("Unable to load code from database", "")) + None => Err(errors::database_error("latest code missing")) } } id => { @@ -597,7 +617,7 @@ impl Eth for EthClient where number: None }) } - }).unwrap_or(Err(Error::internal_error())) // no work found. + }).unwrap_or(Err(errors::internal("No work found.", ""))) } fn submit_work(&self, nonce: RpcH64, pow_hash: RpcH256, mix_hash: RpcH256) -> Result { diff --git a/rpc/src/v1/impls/light/eth.rs b/rpc/src/v1/impls/light/eth.rs index f889faf00..9b0c92e9c 100644 --- a/rpc/src/v1/impls/light/eth.rs +++ b/rpc/src/v1/impls/light/eth.rs @@ -263,7 +263,7 @@ impl Eth for EthClient { let accounts = self.accounts .note_dapp_used(dapp.clone()) .and_then(|_| self.accounts.dapp_addresses(dapp)) - .map_err(|e| errors::internal("Could not fetch accounts.", e)) + .map_err(|e| errors::account("Could not fetch accounts.", e)) .map(|accs| accs.into_iter().map(Into::::into).collect()); future::done(accounts).boxed() diff --git a/rpc/src/v1/impls/light/parity.rs b/rpc/src/v1/impls/light/parity.rs index 332088dd6..1f056b89e 100644 --- a/rpc/src/v1/impls/light/parity.rs +++ b/rpc/src/v1/impls/light/parity.rs @@ -87,7 +87,7 @@ impl Parity for ParityClient { let dapp_accounts = store .note_dapp_used(dapp.clone().into()) .and_then(|_| store.dapp_addresses(dapp.into())) - .map_err(|e| errors::internal("Could not fetch accounts.", e))? + .map_err(|e| errors::account("Could not fetch accounts.", e))? .into_iter().collect::>(); let info = store.accounts_info().map_err(|e| errors::account("Could not fetch account info.", e))?; diff --git a/rpc/src/v1/impls/parity.rs b/rpc/src/v1/impls/parity.rs index 820aa6670..503dfcce6 100644 --- a/rpc/src/v1/impls/parity.rs +++ b/rpc/src/v1/impls/parity.rs @@ -119,7 +119,7 @@ impl Parity for ParityClient where let dapp_accounts = store .note_dapp_used(dapp.clone().into()) .and_then(|_| store.dapp_addresses(dapp.into())) - .map_err(|e| errors::internal("Could not fetch accounts.", e))? + .map_err(|e| errors::account("Could not fetch accounts.", e))? .into_iter().collect::>(); let info = store.accounts_info().map_err(|e| errors::account("Could not fetch account info.", e))?; diff --git a/rpc/src/v1/tests/helpers/miner_service.rs b/rpc/src/v1/tests/helpers/miner_service.rs index 01dd9edc7..c667e408b 100644 --- a/rpc/src/v1/tests/helpers/miner_service.rs +++ b/rpc/src/v1/tests/helpers/miner_service.rs @@ -16,6 +16,7 @@ //! Test implementation of miner service. +use std::collections::hash_map::Entry; use util::{Address, H256, Bytes, U256, FixedHash, Uint}; use util::standard::*; use ethcore::error::{Error, CallError}; @@ -72,6 +73,22 @@ impl Default for TestMinerService { } } +impl TestMinerService { + /// Increments last nonce for given address. + pub fn increment_last_nonce(&self, address: Address) { + let mut last_nonces = self.last_nonces.write(); + match last_nonces.entry(address) { + Entry::Occupied(mut occupied) => { + let val = *occupied.get(); + *occupied.get_mut() = val + 1.into(); + }, + Entry::Vacant(vacant) => { + vacant.insert(0.into()); + }, + } + } +} + impl MinerService for TestMinerService { /// Returns miner's status. diff --git a/rpc/src/v1/tests/mocked/eth.rs b/rpc/src/v1/tests/mocked/eth.rs index 2432b55e7..6603bd722 100644 --- a/rpc/src/v1/tests/mocked/eth.rs +++ b/rpc/src/v1/tests/mocked/eth.rs @@ -468,6 +468,32 @@ fn rpc_eth_transaction_count() { assert_eq!(EthTester::default().io.handle_request_sync(request), Some(response.to_owned())); } +#[test] +fn rpc_eth_transaction_count_next_nonce() { + let tester = EthTester::new_with_options(EthClientOptions::with(|mut options| { + options.pending_nonce_from_queue = true; + })); + tester.miner.increment_last_nonce(1.into()); + + let request1 = r#"{ + "jsonrpc": "2.0", + "method": "eth_getTransactionCount", + "params": ["0x0000000000000000000000000000000000000001", "pending"], + "id": 1 + }"#; + let response1 = r#"{"jsonrpc":"2.0","result":"0x1","id":1}"#; + assert_eq!(tester.io.handle_request_sync(request1), Some(response1.to_owned())); + + let request2 = r#"{ + "jsonrpc": "2.0", + "method": "eth_getTransactionCount", + "params": ["0x0000000000000000000000000000000000000002", "pending"], + "id": 1 + }"#; + let response2 = r#"{"jsonrpc":"2.0","result":"0x0","id":1}"#; + assert_eq!(tester.io.handle_request_sync(request2), Some(response2.to_owned())); +} + #[test] fn rpc_eth_block_transaction_count_by_hash() { let request = r#"{ @@ -1076,10 +1102,9 @@ fn rpc_get_work_returns_correct_work_package() { #[test] fn rpc_get_work_should_not_return_block_number() { - let eth_tester = EthTester::new_with_options(EthClientOptions { - allow_pending_receipt_query: true, - send_block_number_in_get_work: false, - }); + let eth_tester = EthTester::new_with_options(EthClientOptions::with(|mut options| { + options.send_block_number_in_get_work = false; + })); eth_tester.miner.set_author(Address::from_str("d46e8dd67c5d32be8058bb8eb970870f07244567").unwrap()); let request = r#"{"jsonrpc": "2.0", "method": "eth_getWork", "params": [], "id": 1}"#; From 9047b4b487e5e67ac5fbaf20ba79ad6476a31456 Mon Sep 17 00:00:00 2001 From: Arkadiy Paronyan Date: Fri, 10 Mar 2017 10:25:40 +0100 Subject: [PATCH 13/71] Supress USB error message (#4839) --- ethcore/src/account_provider/mod.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ethcore/src/account_provider/mod.rs b/ethcore/src/account_provider/mod.rs index 2f6d49e75..5bb183d0b 100755 --- a/ethcore/src/account_provider/mod.rs +++ b/ethcore/src/account_provider/mod.rs @@ -152,7 +152,7 @@ impl AccountProvider { manager.set_key_path(if settings.hardware_wallet_classic_key { KeyPath::EthereumClassic } else { KeyPath::Ethereum }); hardware_store = Some(manager) }, - Err(e) => warn!("Error initializing hardware wallets: {}", e), + Err(e) => debug!("Error initializing hardware wallets: {}", e), } } AccountProvider { From 6eefecf31e42d8af5da03e61cf948035f718588b Mon Sep 17 00:00:00 2001 From: "Denis S. Soldatov aka General-Beck" Date: Fri, 10 Mar 2017 13:23:34 +0300 Subject: [PATCH 14/71] build docker with custom branch or tag [ci -skip] --- docker/hub/README.md | 2 ++ 1 file changed, 2 insertions(+) create mode 100644 docker/hub/README.md diff --git a/docker/hub/README.md b/docker/hub/README.md new file mode 100644 index 000000000..072307a32 --- /dev/null +++ b/docker/hub/README.md @@ -0,0 +1,2 @@ +Usage +`docker build --build-arg BUILD_TAG=branch_or_tag_name --no-cache=true --tag ethcore/parity:branch_or_tag_name .` From ca963137e9550b89f4019ccd77fd0aa3409bb7f2 Mon Sep 17 00:00:00 2001 From: "Denis S. Soldatov aka General-Beck" Date: Fri, 10 Mar 2017 13:24:18 +0300 Subject: [PATCH 15/71] Update README.md [ci skip] --- docker/hub/README.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/docker/hub/README.md b/docker/hub/README.md index 072307a32..6253f53f0 100644 --- a/docker/hub/README.md +++ b/docker/hub/README.md @@ -1,2 +1,3 @@ Usage -`docker build --build-arg BUILD_TAG=branch_or_tag_name --no-cache=true --tag ethcore/parity:branch_or_tag_name .` + +```docker build --build-arg BUILD_TAG=branch_or_tag_name --no-cache=true --tag ethcore/parity:branch_or_tag_name .``` From 8edee76f8b78a878833c1187926e10fa37bfa4a3 Mon Sep 17 00:00:00 2001 From: Jaco Greeff Date: Fri, 10 Mar 2017 11:38:27 +0100 Subject: [PATCH 16/71] Pull steps from actual available steps (#4848) --- js/src/modals/DeployContract/deployContract.js | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/js/src/modals/DeployContract/deployContract.js b/js/src/modals/DeployContract/deployContract.js index 14930d312..802de64fb 100644 --- a/js/src/modals/DeployContract/deployContract.js +++ b/js/src/modals/DeployContract/deployContract.js @@ -142,12 +142,13 @@ class DeployContract extends Component { render () { const { step, deployError, rejected, inputs } = this.state; - const realStep = Object.keys(STEPS).findIndex((k) => k === step); - const realSteps = deployError || rejected - ? null - : Object.keys(STEPS) - .filter((k) => k !== 'CONTRACT_PARAMETERS' || inputs.length > 0) - .map((k) => STEPS[k]); + const realStepKeys = deployError || rejected + ? [] + : Object.keys(STEPS).filter((k) => k !== 'CONTRACT_PARAMETERS' || inputs.length > 0); + const realStep = realStepKeys.findIndex((k) => k === step); + const realSteps = realStepKeys.length + ? realStepKeys.map((k) => STEPS[k]) + : null; const title = realSteps ? null From d98b7aab612d8d38e10dbd959f5ea67e74ca42c8 Mon Sep 17 00:00:00 2001 From: Nicolas Gotchac Date: Fri, 10 Mar 2017 11:52:27 +0100 Subject: [PATCH 17/71] Wait for the value to have changed in the input (#4844) --- js/src/ui/Form/Input/input.js | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/js/src/ui/Form/Input/input.js b/js/src/ui/Form/Input/input.js index 44906ad93..64ec544b9 100644 --- a/js/src/ui/Form/Input/input.js +++ b/js/src/ui/Form/Input/input.js @@ -214,6 +214,7 @@ export default class Input extends Component { onChange = (event, value) => { event.persist(); + this.setValue(value, () => { this.props.onChange && this.props.onChange(event, value); }); @@ -231,12 +232,10 @@ export default class Input extends Component { } onPaste = (event) => { - const { value } = event.target; - const pasted = event.clipboardData.getData('Text'); - + // Wait for the onChange handler to be called window.setTimeout(() => { - this.onSubmit(value + pasted); - }, 0); + this.onSubmit(this.state.value); + }, 200); } onKeyDown = (event) => { From 4e5fd92e67d7f5efecf2f00f1376a38583ce3600 Mon Sep 17 00:00:00 2001 From: Jaco Greeff Date: Fri, 10 Mar 2017 12:04:40 +0100 Subject: [PATCH 18/71] Extract i18n from shared UI components (#4834) * Actionbar i18n * ui Errors i18n * Features i18n * GapPriceSelector i18n * WIP * WIP #2 * Update methodDecoding * ModalBox -> functional * Signer pages i18n (missed previously) * Update ModalBox tests * Update variable --- js/src/ui/Actionbar/Export/export.js | 12 +- js/src/ui/Actionbar/Search/search.js | 12 +- js/src/ui/Errors/errors.js | 37 +- js/src/ui/Features/defaults.js | 31 +- .../CustomTooltip/customTooltip.js | 15 +- js/src/ui/Icons/index.js | 2 + js/src/ui/MethodDecoding/methodDecoding.js | 342 ++++++++++++------ js/src/ui/ModalBox/body.js | 35 ++ js/src/ui/ModalBox/modalBox.js | 68 +--- js/src/ui/ModalBox/modalBox.spec.js | 24 +- js/src/ui/ModalBox/summary.js | 37 ++ .../Signer/containers/Embedded/embedded.js | 6 +- .../containers/RequestsPage/requestsPage.js | 30 +- 13 files changed, 452 insertions(+), 199 deletions(-) create mode 100644 js/src/ui/ModalBox/body.js create mode 100644 js/src/ui/ModalBox/summary.js diff --git a/js/src/ui/Actionbar/Export/export.js b/js/src/ui/Actionbar/Export/export.js index b64ab8797..c5fd2f18a 100644 --- a/js/src/ui/Actionbar/Export/export.js +++ b/js/src/ui/Actionbar/Export/export.js @@ -15,11 +15,12 @@ // along with Parity. If not, see . import React, { Component, PropTypes } from 'react'; +import { FormattedMessage } from 'react-intl'; import FileSaver from 'file-saver'; -import FileDownloadIcon from 'material-ui/svg-icons/file/file-download'; import Button from '../../Button'; +import { FileDownloadIcon } from '../../Icons'; class ActionbarExport extends Component { static propTypes = { @@ -38,7 +39,12 @@ class ActionbarExport extends Component { ); } - onClick = (event) => { + handleClick = (event) => { if (this.props.disabled) { + event.preventDefault(); + event.stopPropagation(); return; } diff --git a/js/src/dapps/dappreg/ButtonBar/buttonBar.js b/js/src/dapps/dappreg/ButtonBar/buttonBar.js deleted file mode 100644 index cce4bb7aa..000000000 --- a/js/src/dapps/dappreg/ButtonBar/buttonBar.js +++ /dev/null @@ -1,106 +0,0 @@ -// Copyright 2015-2017 Parity Technologies (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 . - -import React, { Component } from 'react'; -import { observer } from 'mobx-react'; - -import DappsStore from '../dappsStore'; -import ModalStore from '../modalStore'; - -import Button from '../Button'; -import styles from './buttonBar.css'; - -@observer -export default class ButtonBar extends Component { - dappsStore = DappsStore.instance(); - modalStore = ModalStore.instance(); - - render () { - let buttons = []; - - if (this.dappsStore.isEditing || this.dappsStore.isNew) { - buttons = [ - + ); + } + + renderButtons () { + const { contractBadgereg, contractDappreg, isBadgeDeploying, isContractDeploying, isDappDeploying, haveAllBadges, haveAllContracts, haveAllDapps, registry } = this.store; + const disableRegistry = registry.address || registry.isDeploying; + const disableContracts = !registry.address || isContractDeploying || haveAllContracts; + const disableDapps = !contractDappreg.address || isDappDeploying || haveAllDapps; + const disableBadges = !registry.address || !contractBadgereg.address || isBadgeDeploying || haveAllBadges; + + return ( +
+ { this.renderButton('registry', this.deployRegistry, disableRegistry) } + { this.renderButton('contracts', this.deployContracts, disableContracts) } + { this.renderButton('badges', this.deployBadges, disableBadges) } + { this.renderButton('apps', this.deployApps, disableDapps) } +
+ ); + } + + renderContracts (isBadges, isExternal) { + const { badges, contracts, contractBadgereg, registry } = this.store; + const regaddress = isBadges + ? contractBadgereg.address + : registry.address; + + return ( +
+

+ { + isExternal + ? 'External ' + : '' + }{ + isBadges + ? 'Badges ' + : 'Contracts ' + }(registry { regaddress || 'unknown' }) +

+
+ { + isExternal || isBadges + ? null + : ( + + ) + } + { + (isBadges ? badges : contracts) + .filter((contract) => contract.isExternal === isExternal) + .map((contract) => { + return ( + + ); + }) + } +
+
+ ); + } + + renderApps (isExternal) { + const { apps, contractDappreg, contractGithubhint } = this.store; + const isDisabled = !contractDappreg.isOnChain || !contractGithubhint.isOnChain; + + return ( +
+

+ { + isExternal + ? 'External ' + : '' + }Applications (registry { + contractDappreg.address + ? contractDappreg.address + : 'unknown' + }) +

+
+ { + apps + .filter((app) => app.isExternal === isExternal) + .map((app) => { + return ( + + ); + }) + } +
+
+ ); + } + + deployApps = () => { + return this.store.deployApps(); + } + + deployBadges = () => { + return this.store.deployBadges(); + } + + deployContracts = () => { + return this.store.deployContracts(); + } + + deployRegistry = () => { + return this.store.deployRegistry(); + } +} diff --git a/js/src/dapps/chaindeploy/Application/index.js b/js/src/dapps/chaindeploy/Application/index.js new file mode 100644 index 000000000..3d8d1ca3b --- /dev/null +++ b/js/src/dapps/chaindeploy/Application/index.js @@ -0,0 +1,17 @@ +// Copyright 2015-2017 Parity Technologies (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 . + +export default from './application'; diff --git a/js/src/dapps/chaindeploy/Contract/contract.js b/js/src/dapps/chaindeploy/Contract/contract.js new file mode 100644 index 000000000..1f0b158d2 --- /dev/null +++ b/js/src/dapps/chaindeploy/Contract/contract.js @@ -0,0 +1,132 @@ +// Copyright 2015-2017 Parity Technologies (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 . + +import React, { Component, PropTypes } from 'react'; + +import ListItem, { Header, Row } from '../ListItem'; + +export default class Contract extends Component { + static propTypes = { + contract: PropTypes.object.isRequired, + disabled: PropTypes.bool + } + + render () { + const { contract, disabled } = this.props; + const location = contract.id === 'registry' + ? 'chain' + : 'registry'; + + return ( + +
+ { contract.id } was { + contract.address + ? 'deployed' + : 'not found' + } +
+ + { + contract.address + ? contract.address + : 'no address' + } + + + { + contract.hasLatestCode + ? 'has latest available code' + : 'does not have latest code' + } + + + { + contract.isOnChain + ? `registered on ${location}` + : `not registered on ${location}` + } + + { this.renderBadgeInfo() } +
+ ); + } + + renderBadgeInfo () { + const { contract } = this.props; + + if (!contract.isBadge) { + return null; + } + + return [ + + { + contract.isBadgeRegistered + ? 'found in badgereg' + : 'not found in badgereg' + } + , + + { + contract.badgeImageHash + ? `badge imageHash ${contract.badgeImageHash}` + : 'has not registered a badge imageHash' + } + , + + { + contract.badgeImageMatch + ? 'has latest badge imageHash' + : 'does not have latest badge imageHash' + } + + ]; + } +} diff --git a/js/src/dapps/chaindeploy/Contract/index.js b/js/src/dapps/chaindeploy/Contract/index.js new file mode 100644 index 000000000..74c58e942 --- /dev/null +++ b/js/src/dapps/chaindeploy/Contract/index.js @@ -0,0 +1,17 @@ +// Copyright 2015-2017 Parity Technologies (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 . + +export default from './contract'; diff --git a/js/src/dapps/chaindeploy/Dapp/dapp.js b/js/src/dapps/chaindeploy/Dapp/dapp.js new file mode 100644 index 000000000..5a997c295 --- /dev/null +++ b/js/src/dapps/chaindeploy/Dapp/dapp.js @@ -0,0 +1,98 @@ +// Copyright 2015-2017 Parity Technologies (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 . + +import React, { Component, PropTypes } from 'react'; + +import ListItem, { Header, Row } from '../ListItem'; + +export default class Dapp extends Component { + static propTypes = { + dapp: PropTypes.object.isRequired, + disabled: PropTypes.bool + } + + render () { + const { dapp, disabled } = this.props; + + return ( + +
+ { dapp.name } +
+ + { + dapp.isOnChain + ? 'found in dappreg' + : 'not found in dappreg' + } + + { this.renderHash(dapp, 'image') } + { this.renderHash(dapp, 'manifest') } + { this.renderHash(dapp, 'content') } +
+ ); + } + + renderHash (dapp, type) { + if (!dapp.source[`${type}Hash`]) { + return null; + } + + const isMatch = dapp[`${type}Match`]; + const hash = dapp[`${type}Hash`]; + + return [ + + { + hash + ? `${type}Hash ${hash}` + : `has not registered an ${type}Hash` + } + , + + { + isMatch + ? `has latest ${type}Hash` + : `does not have latest ${type}Hash` + } + + ]; + } +} diff --git a/js/src/dapps/chaindeploy/Dapp/index.js b/js/src/dapps/chaindeploy/Dapp/index.js new file mode 100644 index 000000000..3d3281389 --- /dev/null +++ b/js/src/dapps/chaindeploy/Dapp/index.js @@ -0,0 +1,17 @@ +// Copyright 2015-2017 Parity Technologies (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 . + +export default from './dapp'; diff --git a/js/src/dapps/chaindeploy/ListItem/Header/header.js b/js/src/dapps/chaindeploy/ListItem/Header/header.js new file mode 100644 index 000000000..e9be01eea --- /dev/null +++ b/js/src/dapps/chaindeploy/ListItem/Header/header.js @@ -0,0 +1,45 @@ +// Copyright 2015-2017 Parity Technologies (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 . + +import React, { Component, PropTypes } from 'react'; + +import Icon from '../Icon'; + +import styles from '../listItem.css'; + +export default class Header extends Component { + static propTypes = { + children: PropTypes.node.isRequired, + isBusy: PropTypes.bool, + isOk: PropTypes.bool + } + + render () { + const { children, isBusy, isOk } = this.props; + + return ( +
+ +
+ { children } +
+
+ ); + } +} diff --git a/js/src/dapps/chaindeploy/ListItem/Header/index.js b/js/src/dapps/chaindeploy/ListItem/Header/index.js new file mode 100644 index 000000000..aef90266f --- /dev/null +++ b/js/src/dapps/chaindeploy/ListItem/Header/index.js @@ -0,0 +1,17 @@ +// Copyright 2015-2017 Parity Technologies (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 . + +export default from './header'; diff --git a/js/src/dapps/chaindeploy/ListItem/Icon/icon.js b/js/src/dapps/chaindeploy/ListItem/Icon/icon.js new file mode 100644 index 000000000..1f32622e5 --- /dev/null +++ b/js/src/dapps/chaindeploy/ListItem/Icon/icon.js @@ -0,0 +1,53 @@ +// Copyright 2015-2017 Parity Technologies (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 . + +import React, { Component, PropTypes } from 'react'; + +import styles from '../listItem.css'; + +export default class Icon extends Component { + static propTypes = { + isBusy: PropTypes.bool, + isOk: PropTypes.bool + } + + render () { + const { isBusy, isOk } = this.props; + + return ( +
+ { + isOk + ? '\u2714' + : ( + isBusy + ? '\u29d6' + : '\u2716' + ) + } +
+ ); + } +} diff --git a/js/src/dapps/chaindeploy/ListItem/Icon/index.js b/js/src/dapps/chaindeploy/ListItem/Icon/index.js new file mode 100644 index 000000000..f43e02c49 --- /dev/null +++ b/js/src/dapps/chaindeploy/ListItem/Icon/index.js @@ -0,0 +1,17 @@ +// Copyright 2015-2017 Parity Technologies (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 . + +export default from './icon'; diff --git a/js/src/dapps/chaindeploy/ListItem/Row/index.js b/js/src/dapps/chaindeploy/ListItem/Row/index.js new file mode 100644 index 000000000..5f2c62dee --- /dev/null +++ b/js/src/dapps/chaindeploy/ListItem/Row/index.js @@ -0,0 +1,17 @@ +// Copyright 2015-2017 Parity Technologies (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 . + +export default from './row'; diff --git a/js/src/dapps/chaindeploy/ListItem/Row/row.js b/js/src/dapps/chaindeploy/ListItem/Row/row.js new file mode 100644 index 000000000..0982e0321 --- /dev/null +++ b/js/src/dapps/chaindeploy/ListItem/Row/row.js @@ -0,0 +1,54 @@ +// Copyright 2015-2017 Parity Technologies (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 . + +import React, { Component, PropTypes } from 'react'; + +import Icon from '../Icon'; + +import styles from '../listItem.css'; + +export default class Row extends Component { + static propTypes = { + children: PropTypes.node.isRequired, + disabled: PropTypes.bool, + isBusy: PropTypes.bool, + isOk: PropTypes.bool + } + + render () { + const { children, disabled, isBusy, isOk } = this.props; + + return ( +
+ +
+ { children } +
+
+ ); + } +} diff --git a/js/src/dapps/chaindeploy/ListItem/index.js b/js/src/dapps/chaindeploy/ListItem/index.js new file mode 100644 index 000000000..7c79e3241 --- /dev/null +++ b/js/src/dapps/chaindeploy/ListItem/index.js @@ -0,0 +1,20 @@ +// Copyright 2015-2017 Parity Technologies (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 . + +export Header from './Header'; +export Row from './Row'; + +export default from './listItem'; diff --git a/js/src/dapps/chaindeploy/ListItem/listItem.css b/js/src/dapps/chaindeploy/ListItem/listItem.css new file mode 100644 index 000000000..47d6d481d --- /dev/null +++ b/js/src/dapps/chaindeploy/ListItem/listItem.css @@ -0,0 +1,94 @@ +/* Copyright 2015-2017 Parity Technologies (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 . +*/ + +.listItem { + box-sizing: border-box; + flex: 0 1 33.33%; + max-width: 33.33%; + padding: 0.5em; + position: relative; + + .body { + background: rgba(0, 0, 0, 0.025); + border-radius: 0.25em; + box-sizing: border-box; + display: flex; + flex-direction: column; + flex-wrap: nowrap; + overflow: hidden; + padding: 0.75em; + } + + .status { + background: #f80; + border-radius: 0.25em; + color: white; + font-size: 0.75em; + line-height: 1em; + opacity: 0.9; + padding: 0.5em; + position: absolute; + right: 1em; + top: 1em; + } +} + +.header, +.details { + display: flex; + line-height: 1.5em; + padding: 0.125em 0; + position: relative; + white-space: nowrap; + + .title { + display: inline-block; + overflow: hidden; + text-overflow: ellipsis; + vertical-align: top; + } +} + +.details { + margin-left: 2em; +} + +.icon { + border-radius: 0.25em; + display: inline-block; + flex: 0 0 1.5em; + height: 1.5em; + margin-right: 0.5em; + opacity: 0.75; + text-align: center; + vertical-align: middle; + width: 1.5em; + + &.error { + box-shadow: inset 0 0 0 2px rgb(200, 0, 0); + color: rgb(200, 0, 0); + } + + &.ok { + box-shadow: inset 0 0 0 2px rgb(0, 200, 0); + color: rgb(0, 200, 0); + } +} + +.muted { + opacity: 0.25; +} diff --git a/js/src/dapps/chaindeploy/ListItem/listItem.js b/js/src/dapps/chaindeploy/ListItem/listItem.js new file mode 100644 index 000000000..c670123f9 --- /dev/null +++ b/js/src/dapps/chaindeploy/ListItem/listItem.js @@ -0,0 +1,63 @@ +// Copyright 2015-2017 Parity Technologies (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 . + +import React, { Component, PropTypes } from 'react'; + +import styles from './listItem.css'; + +export default class ListItem extends Component { + static propTypes = { + children: PropTypes.node.isRequired, + disabled: PropTypes.bool, + status: PropTypes.string + } + + render () { + const { children, disabled } = this.props; + + return ( +
+
+ { children } +
+ { this.renderStatus() } +
+ ); + } + + renderStatus () { + const { status } = this.props; + + if (!status) { + return null; + } + + return ( +
+ { status } +
+ ); + } +} diff --git a/js/src/dapps/chaindeploy/_dapps.js b/js/src/dapps/chaindeploy/_dapps.js new file mode 100644 index 000000000..b2ce1d4be --- /dev/null +++ b/js/src/dapps/chaindeploy/_dapps.js @@ -0,0 +1,43 @@ +// Copyright 2015-2017 Parity Technologies (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 . + +import builtinsJson from '~/views/Dapps/builtin.json'; + +const REGISTER_URLS = { + console: 'https://raw.githubusercontent.com/ethcore/console/3ea0dbfefded359ccdbea37bc4cf350c0aa16948/console.jpeg', + dappreg: 'https://raw.githubusercontent.com/ethcore/dapp-assets/cdd6ac4f1e2f11619bed72a53ae71217dffe19ad/dapps/legos-64x64.png', + githubhint: 'https://raw.githubusercontent.com/ethcore/dapp-assets/b88e983abaa1a6a6345b8d9448c15b117ddb540e/dapps/link-64x64.jpg', + localtx: 'https://raw.githubusercontent.com/ethcore/dapp-assets/cdd6ac4f1e2f11619bed72a53ae71217dffe19ad/dapps/stack-64x64.png', + registry: 'https://raw.githubusercontent.com/ethcore/dapp-assets/b88e983abaa1a6a6345b8d9448c15b117ddb540e/dapps/register-64x64.jpg', + signaturereg: 'https://raw.githubusercontent.com/ethcore/dapp-assets/b88e983abaa1a6a6345b8d9448c15b117ddb540e/dapps/hex-64x64.jpg', + tokendeploy: 'https://raw.githubusercontent.com/ethcore/dapp-assets/b88e983abaa1a6a6345b8d9448c15b117ddb540e/dapps/interlock-64x64.png', + tokenreg: 'https://raw.githubusercontent.com/ethcore/dapp-assets/b88e983abaa1a6a6345b8d9448c15b117ddb540e/dapps/coins-64x64.jpg', + web: 'https://raw.githubusercontent.com/ethcore/dapp-assets/ec6138115d0e1f45258969cd90b3b274e0ff2258/dapps/earth-64x64.jpg' +}; + +const builtins = builtinsJson + .filter((app) => app.id) + .map((app) => { + app.source = { + imageUrl: REGISTER_URLS[app.id] + }; + + return app; + }); + +export { + builtins +}; diff --git a/js/src/dapps/chaindeploy/contracts/abi/jg-voting.json b/js/src/dapps/chaindeploy/contracts/abi/jg-voting.json new file mode 100644 index 000000000..83a07ef7c --- /dev/null +++ b/js/src/dapps/chaindeploy/contracts/abi/jg-voting.json @@ -0,0 +1 @@ +[{"constant":true,"inputs":[],"name":"count","outputs":[{"name":"","type":"uint256"}],"payable":false,"type":"function"},{"constant":true,"inputs":[],"name":"totalVotes","outputs":[{"name":"","type":"uint256"}],"payable":false,"type":"function"},{"constant":false,"inputs":[{"name":"_newOwner","type":"address"}],"name":"setOwner","outputs":[],"payable":false,"type":"function"},{"constant":true,"inputs":[{"name":"_index","type":"uint256"}],"name":"hasSenderVoted","outputs":[{"name":"","type":"bool"}],"payable":false,"type":"function"},{"constant":false,"inputs":[{"name":"_index","type":"uint256"},{"name":"_answer","type":"uint256"}],"name":"newAnswer","outputs":[{"name":"","type":"bool"}],"payable":true,"type":"function"},{"constant":false,"inputs":[{"name":"_fee","type":"uint256"}],"name":"setQuestionFee","outputs":[{"name":"","type":"bool"}],"payable":false,"type":"function"},{"constant":true,"inputs":[],"name":"questionFee","outputs":[{"name":"","type":"uint256"}],"payable":false,"type":"function"},{"constant":true,"inputs":[],"name":"owner","outputs":[{"name":"","type":"address"}],"payable":false,"type":"function"},{"constant":true,"inputs":[{"name":"_index","type":"uint256"}],"name":"get","outputs":[{"name":"closed","type":"bool"},{"name":"owner","type":"address"},{"name":"question","type":"string"},{"name":"balanceNo","type":"uint256"},{"name":"balanceYes","type":"uint256"},{"name":"balanceMaybe","type":"uint256"},{"name":"votesNo","type":"uint256"},{"name":"votesYes","type":"uint256"},{"name":"votesMaybe","type":"uint256"}],"payable":false,"type":"function"},{"constant":false,"inputs":[],"name":"drain","outputs":[{"name":"","type":"bool"}],"payable":false,"type":"function"},{"constant":false,"inputs":[{"name":"_question","type":"string"}],"name":"newQuestion","outputs":[{"name":"","type":"bool"}],"payable":true,"type":"function"},{"constant":true,"inputs":[],"name":"totalBalance","outputs":[{"name":"","type":"uint256"}],"payable":false,"type":"function"},{"constant":true,"inputs":[],"name":"answerFee","outputs":[{"name":"","type":"uint256"}],"payable":false,"type":"function"},{"constant":false,"inputs":[{"name":"_index","type":"uint256"}],"name":"closeQuestion","outputs":[{"name":"","type":"bool"}],"payable":false,"type":"function"},{"constant":false,"inputs":[{"name":"_fee","type":"uint256"}],"name":"setAnswerFee","outputs":[{"name":"","type":"bool"}],"payable":false,"type":"function"},{"inputs":[],"payable":false,"type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"name":"owner","type":"address"},{"indexed":true,"name":"index","type":"uint256"},{"indexed":false,"name":"question","type":"string"}],"name":"NewQuestion","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"index","type":"uint256"},{"indexed":true,"name":"answer","type":"uint256"},{"indexed":false,"name":"value","type":"uint256"}],"name":"NewAnswer","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"old","type":"address"},{"indexed":true,"name":"current","type":"address"}],"name":"NewOwner","type":"event"}] diff --git a/js/src/dapps/chaindeploy/contracts/badgereg.js b/js/src/dapps/chaindeploy/contracts/badgereg.js new file mode 100644 index 000000000..ccd6b28c1 --- /dev/null +++ b/js/src/dapps/chaindeploy/contracts/badgereg.js @@ -0,0 +1,30 @@ +// Copyright 2015-2017 Parity Technologies (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 . + +import abi from '~/contracts/abi/badgereg'; +import { compiler, source as sourceUrl, output as byteCode } from './code/badgereg'; + +const id = 'badgereg'; +const deployParams = []; + +export { + abi, + byteCode, + compiler, + deployParams, + id, + sourceUrl +}; diff --git a/js/src/dapps/chaindeploy/contracts/code/badgereg.json b/js/src/dapps/chaindeploy/contracts/code/badgereg.json new file mode 100644 index 000000000..e6613ed26 --- /dev/null +++ b/js/src/dapps/chaindeploy/contracts/code/badgereg.json @@ -0,0 +1,5 @@ +{ + "compiler": "v0.4.9+commit.364da425", + "source": "https://github.com/ethcore/contracts/blob/58842b92c00e3c45a84b6d0ac9b842f016dde50a/BadgeReg.sol", + "output": "0x606060405260008054600160a060020a03191633600160a060020a0316179055670de0b6b3a7640000600455341561003357fe5b5b610a6f806100436000396000f300606060405236156100bf5763ffffffff60e060020a60003504166313af403581146100c15780631e7a505f146100df5780632c0f5f591461010a5780635b8066451461014557806369fe0e2d146101675780637958533a1461017c5780638da5cb5b146101a45780639890220b146101d0578063a02b161e146101e2578063ac4ce2c6146101f7578063b72e717d14610218578063c0f6faed1461025b578063dd93890b14610299578063ddbcb5cb146102b4578063ddca3f43146102e6575bfe5b34156100c957fe5b6100dd600160a060020a0360043516610308565b005b6100f6600160a060020a036004351660243561037c565b604080519115158252519081900360200190f35b341561011257fe5b61011d600435610392565b60408051938452600160a060020a039283166020850152911682820152519081900360600190f35b341561014d57fe5b6101556103ef565b60408051918252519081900360200190f35b341561016f57fe5b6100dd6004356103f6565b005b341561018457fe5b61015560043560243561041b565b60408051918252519081900360200190f35b34156101ac57fe5b6101b461045a565b60408051600160a060020a039092168252519081900360200190f35b34156101d857fe5b6100dd610469565b005b34156101ea57fe5b6100dd6004356104bc565b005b34156101ff57fe5b6100dd600435600160a060020a03602435166105ee565b005b341561022057fe5b610234600160a060020a0360043516610721565b604080519384526020840192909252600160a060020a031682820152519081900360600190f35b341561026357fe5b61026e600435610789565b60408051600160a060020a039485168152602081019390935292168183015290519081900360600190f35b34156102a157fe5b6100dd6004356024356044356107dc565b005b6100f6600160a060020a036004358116906024359060443516610899565b604080519115158252519081900360200190f35b34156102ee57fe5b6101556109cc565b60408051918252519081900360200190f35b60005433600160a060020a0390811691161461032357610378565b60008054604051600160a060020a03808516939216917f70aea8d848e8a90fb7661b227dc522eb6395c3dac71b63cb59edd5c9899b236491a360008054600160a060020a031916600160a060020a0383161790555b5b50565b6000610389838333610899565b90505b92915050565b60008181526002602052604081205460038054600019909201929182918291859081106103bb57fe5b906000526020600020906004020160005b5080546002820154600160a060020a03918216955016925090505b509193909250565b6003545b90565b60005433600160a060020a0390811691161461041157610378565b60048190555b5b50565b600060038381548110151561042c57fe5b906000526020600020906004020160005b506000838152600391909101602052604090205490505b92915050565b600054600160a060020a031681565b60005433600160a060020a03908116911614610484576104b8565b604051600160a060020a0333811691309091163180156108fc02916000818181858888f1935050505015156104b857610000565b5b5b565b60005433600160a060020a039081169116146104d757610378565b806003828154811015156104e757fe5b906000526020600020906004020160005b50600101546040517f844e89a9d524dabb877007aa0e9c395e8938fcfee93ece70c2cd0353db79c8e590600090a36001600060038381548110151561053957fe5b906000526020600020906004020160005b5054600160a060020a03168152602081019190915260400160009081208190556003805460029291908490811061057d57fe5b906000526020600020906004020160005b50600101548152602081019190915260400160009081205560038054829081106105b457fe5b906000526020600020906004020160005b508054600160a060020a03199081168255600060018301556002909101805490911690555b5b50565b60008233600160a060020a031660038281548110151561060a57fe5b906000526020600020906004020160005b5060020154600160a060020a0316146106335761071b565b600160a060020a03831660009081526001602052604090205483901561065857610718565b600380548690811061066657fe5b906000526020600020906004020160005b505460038054600160a060020a03909216945085918790811061069657fe5b906000526020600020906004020160005b508054600160a060020a031916600160a060020a039283161790558381166000908152600160209081526040808320839055928716808352918390208890558251918252915187927fa5d871c0e725767cd5aefc99c53aeca35f09dcc268145cbb13b74a7e2f48f196928290030190a25b5b505b50505050565b600160a060020a038116600090815260016020526040812054600380546000199092019291829182918590811061075457fe5b906000526020600020906004020160005b5060018101546002820154909450600160a060020a0316925090505b509193909250565b60006000600060006003858154811015156107a057fe5b906000526020600020906004020160005b50805460018201546002830154600160a060020a03928316975090955016925090505b509193909250565b8233600160a060020a03166003828154811015156107f657fe5b906000526020600020906004020160005b5060020154600160a060020a03161461081f5761071b565b8160038581548110151561082f57fe5b906000526020600020906004020160005b50600085815260039190910160209081526040918290209290925580518481529051859287927f7991c63a749706fd298fc2387764d640be6e714307b6357b1d3c2ce35cba3b52929081900390910190a35b5b50505050565b60006004543410156108aa576109c5565b600160a060020a0384166000908152600160205260409020548490156108cf576109c3565b6000848152600260205260409020548490156108ea576109c0565b60038054600181016108fc83826109d2565b916000526020600020906004020160005b5060408051606081018252600160a060020a03808b1680835260208084018c9052918a169284018390528454600160a060020a03199081168217865560018087018d905560029687018054909216909417905560035460008281529383528484208190558b8452948252918390208490558251918252915160001993909301935088927febbfb6376bef000063e6e33494e4c543a6197091a04eb6a6f55013d85a1c5386929181900390910190a3600192505b5b505b505b9392505050565b60045481565b8154818355818115116109fe576004028160040283600052602060002091820191016109fe9190610a04565b5b505050565b6103f391905b80821115610a3c578054600160a060020a03199081168255600060018301556002820180549091169055600401610a0a565b5090565b905600a165627a7a72305820526fc95faec325cec5dd3e1bb67c165265282c5fc6db21e96197060b823aaa490029" +} diff --git a/js/src/dapps/chaindeploy/contracts/code/dappreg.json b/js/src/dapps/chaindeploy/contracts/code/dappreg.json new file mode 100644 index 000000000..eae53272a --- /dev/null +++ b/js/src/dapps/chaindeploy/contracts/code/dappreg.json @@ -0,0 +1,5 @@ +{ + "compiler": "v0.4.9+commit.364da425", + "source": "https://github.com/ethcore/contracts/blob/225bf022ddd967af2b9ea188e8f611489ca5d7fe/DappReg.sol", + "output": "0x606060405260008054600160a060020a03191633600160a060020a0316179055670de0b6b3a7640000600355341561003357fe5b5b6106ee806100436000396000f300606060405236156100a95763ffffffff60e060020a6000350416630257c48c81146100ab57806306661abd146100d357806313af4035146100f55780631a0919dc1461011357806369fe0e2d146101285780638da5cb5b1461013d5780638eaa6ac01461016957806391cd242d1461019d5780639890220b146101b8578063c52bd836146101ca578063ddca3f43146101eb578063e0886f901461020d578063e1fa8e8414610241575bfe5b34156100b357fe5b6100c160043560243561024e565b60408051918252519081900360200190f35b34156100db57fe5b6100c1610272565b60408051918252519081900360200190f35b34156100fd57fe5b610111600160a060020a0360043516610279565b005b341561011b57fe5b6101116004356102ed565b005b341561013057fe5b610111600435610388565b005b341561014557fe5b61014d6103ad565b60408051600160a060020a039092168252519081900360200190f35b341561017157fe5b61017c6004356103bc565b60408051928352600160a060020a0390911660208301528051918290030190f35b34156101a557fe5b6101116004356024356044356103e4565b005b34156101c057fe5b61011161046d565b005b34156101d257fe5b610111600435600160a060020a03602435166104c0565b005b34156101f357fe5b6100c161054e565b60408051918252519081900360200190f35b341561021557fe5b61017c600435610554565b60408051928352600160a060020a0390911660208301528051918290030190f35b6101116004356105ab565b005b60008281526001602090815260408083208484526002019091529020545b92915050565b6002545b90565b60005433600160a060020a0390811691161461029457610000565b60008054604051600160a060020a03808516939216917f70aea8d848e8a90fb7661b227dc522eb6395c3dac71b63cb59edd5c9899b236491a360008054600160a060020a031916600160a060020a0383161790555b5b50565b60008181526001602081905260409091200154819033600160a060020a0390811691161480159061032d575060005433600160a060020a03908116911614155b1561033757610000565b60008281526001602081905260408083208381559091018054600160a060020a03191690555183917fe17fec26316aebe957e188549d659a89f359c49766bcc0ae2fb7ded274ffe14691a25b5b5050565b60005433600160a060020a039081169116146103a357610000565b60038190555b5b50565b600054600160a060020a031681565b6000818152600160208190526040909120805491810154600160a060020a0316905b50915091565b60008381526001602081905260409091200154839033600160a060020a0390811691161461041157610000565b600084815260016020908152604080832086845260020182529182902084905581518481529151859287927f4dcd4fb147bb133a0da8fbf4e5fc3ddd64f04d4b3f6cbee584374b889d28c78d92918290030190a35b5b50505050565b60005433600160a060020a0390811691161461048857610000565b604051600160a060020a0333811691309091163180156108fc02916000818181858888f1935050505015156104bc57610000565b5b5b565b60008281526001602081905260409091200154829033600160a060020a039081169116146104ed57610000565b60008381526001602081905260408083209091018054600160a060020a031916600160a060020a0386169081179091559051909185917fd3d10d874a10020c2bce719499d1fd8756d880b128eb2945dd01b3830854e7169190a35b5b505050565b60035481565b6000600060006001600060028681548110151561056d57fe5b906000526020600020900160005b50548152602081019190915260400160002080546001820154909450600160a060020a0316925090505b50915091565b6003543410156105ba57610000565b6000818152600160205260409020548190156105d557610000565b60028054600181016105e78382610677565b916000526020600020900160005b508390555060408051808201825283815233600160a060020a0390811660208084018281526000888152600192839052868120955186559051949091018054600160a060020a0319169490931693909317909155915184917f7d917fcbc9a29a9705ff9936ffa599500e4fd902e4486bae317414fe967b307c91a35b5b505b50565b815481835581811511610548576000838152602090206105489181019083016106a1565b5b505050565b61027691905b808211156106bb57600081556001016106a7565b5090565b905600a165627a7a7230582011d8a45e381635e9de17e14cc4de97a1e17758cfac1fd25e8a5bc1d5f4d1da9d0029" +} diff --git a/js/src/dapps/chaindeploy/contracts/code/gavcoin.json b/js/src/dapps/chaindeploy/contracts/code/gavcoin.json new file mode 100644 index 000000000..dbf53fdeb --- /dev/null +++ b/js/src/dapps/chaindeploy/contracts/code/gavcoin.json @@ -0,0 +1,5 @@ +{ + "compiler": "v0.4.9+commit.364da425", + "source": "https://github.com/ethcore/contracts/blob/58842b92c00e3c45a84b6d0ac9b842f016dde50a/GavCoin.sol", + "output": "0x606060405266038d7ea4c680006002556305f5e100600355341561001f57fe5b5b6108008061002f6000396000f300606060405236156100885763ffffffff60e060020a600035041663095ea7b3811461009f57806318160ddd146100d257806323b872dd146100f457806329cbdc861461012d57806355234ec0146101465780635af36e3e1461016857806370a0823114610192578063a035b1fe146101c0578063a9059cbb146101e2578063dd62ed3e14610215575b61009d5b61009a3360ff60020a610249565b5b565b005b34156100a757fe5b6100be600160a060020a0360043516602435610390565b604080519115158252519081900360200190f35b34156100da57fe5b6100e2610416565b60408051918252519081900360200190f35b34156100fc57fe5b6100be600160a060020a036004358116906024351660443561041c565b604080519115158252519081900360200190f35b61009d600160a060020a036004351660243561052a565b005b341561014e57fe5b6100e2610539565b60408051918252519081900360200190f35b341561017057fe5b6100be60043560243561053f565b604080519115158252519081900360200190f35b341561019a57fe5b6100e2600160a060020a03600435166106d0565b60408051918252519081900360200190f35b34156101c857fe5b6100e26106ef565b60408051918252519081900360200190f35b34156101ea57fe5b6100be600160a060020a03600435166024356106f5565b604080519115158252519081900360200190f35b341561021d57fe5b6100e2600160a060020a03600435811690602435166107a3565b60408051918252519081900360200190f35b34600080805b60008411801561026157508460025411155b1561038757600354600254620f424091025b0492508284116102835783610285565b825b9150600254620f4240830281151561029957fe5b33600160a060020a03166000818152600160208181526040808420805497909604968701865560028054855295830190915280832080548701905584548352808320909101805463ffffffff191662093a80420163ffffffff161790558154850182559254925193945084937f689dcb02b6a65e0e2f1d23ef47c1ec86604ffbed0bcb65f20150cfc7d5e5a9489190a4600380548290039081905593829003931515610382576002805466038d7ea4c6800001908190556305f5e1006003556040517f23c3dae768238f239632b5c4acb89485b440e0fa72481c4aad9f9b4f9b5a0a5f90600090a25b61024f565b5b505050505050565b600082600160a060020a031633600160a060020a03167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925846040518082815260200191505060405180910390a350600160a060020a0333811660009081526001602081815260408084209487168452600290940190529190208054830190555b92915050565b60005481565b600160a060020a038316600090815260016020526040812054849083908190101561044657610521565b600160a060020a0380871660009081526001602090815260408083203394851684526002019091529020548791908690819010156104835761051c565b87600160a060020a031689600160a060020a03167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef896040518082815260200191505060405180910390a3600160a060020a03808a166000908152600160208181526040808420338616855260028101835281852080548e900390559183905281548c9003909155928b16825291902080548901905595505b5b5050505b50509392505050565b6105348282610249565b5b5050565b60035481565b600160a060020a0333166000908152600160208181526040808420868552909201905281205483908390819010806105a35750600160a060020a03331660009081526001602081815260408084208685528301909152909120015463ffffffff1642105b156105ad576106c8565b33600160a060020a0381166000908152600160205260409020548590819010156105d6576106c4565b60405186908890600160a060020a033316907f73f04af9dcc582a923ec15d3eea990fe34adabfff2879e28d44572e01a54abb690600090a433600160a060020a0316600090815260016020818152604080842080548b9003815584548b0185558b855290920190529020805487900390819055151561068457600160a060020a03331660009081526001602081815260408084208b85528301909152822091825501805463ffffffff191690555b600160a060020a0333166108fc620f4240888a025b604051919004801590920291906000818181858888f1935050505015156106bf57610000565b600194505b5b50505b505092915050565b600160a060020a0381166000908152600160205260409020545b919050565b60025481565b33600160a060020a038116600090815260016020526040812054909190839081901015610721576106c8565b84600160a060020a031633600160a060020a03167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef866040518082815260200191505060405180910390a3600160a060020a03338116600090815260016020526040808220805488900390559187168152208054850190555b5b505092915050565b600160a060020a03808316600090815260016020908152604080832093851683526002909301905220545b929150505600a165627a7a72305820ca533a37c92e41888bda66ae0e66415d21a61c60027b269bca633d85b727875c0029" +} diff --git a/js/src/dapps/chaindeploy/contracts/code/githubhint.json b/js/src/dapps/chaindeploy/contracts/code/githubhint.json new file mode 100644 index 000000000..1dedacfe8 --- /dev/null +++ b/js/src/dapps/chaindeploy/contracts/code/githubhint.json @@ -0,0 +1,5 @@ +{ + "compiler": "v0.4.9+commit.364da425", + "source": "https://github.com/ethcore/contracts/blob/58842b92c00e3c45a84b6d0ac9b842f016dde50a/GithubHint.sol", + "output": "0x6060604052341561000c57fe5b5b6105868061001c6000396000f300606060405263ffffffff60e060020a60003504166302f2008d81146100425780632196ae0d1461009b578063267b6922146101055780637c8c6643146101c9575bfe5b341561004a57fe5b60408051602060046024803582810135601f810185900485028601850190965285855261009995833595939460449493929092019181908401838280828437509496506101de95505050505050565b005b34156100a357fe5b60408051602060046024803582810135601f81018590048502860185019096528585526100999583359593946044949392909201918190840183828082843750949650505092356bffffffffffffffffffffffff191692506102be915050565b005b341561010d57fe5b6101186004356103b1565b604080516bffffffffffffffffffffffff1984166020820152600160a060020a03831691810191909152606080825284546002600019610100600184161502019091160490820181905281906080820190869080156101b85780601f1061018d576101008083540402835291602001916101b8565b820191906000526020600020905b81548152906001019060200180831161019b57829003601f168201915b505094505050505060405180910390f35b34156101d157fe5b6100996004356103de565b005b6000828152602081905260409020600201548290600160a060020a031615801590610227575060008181526020819052604090206002015433600160a060020a03908116911614155b15610231576102b8565b6040805160608101825283815260006020808301829052600160a060020a0333168385015286825281815292902081518051929391926102749284920190610472565b506020820151600182018054606060020a909204600160a060020a031992831617905560409092015160029091018054600160a060020a0392909216919092161790555b5b505050565b6000838152602081905260409020600201548390600160a060020a031615801590610307575060008181526020819052604090206002015433600160a060020a03908116911614155b15610311576103aa565b604080516060810182528481526bffffffffffffffffffffffff198416602080830191909152600160a060020a0333168284015260008781528082529290922081518051929391926103669284920190610472565b506020820151600182018054606060020a909204600160a060020a031992831617905560409092015160029091018054600160a060020a0392909216919092161790555b5b50505050565b600060208190529081526040902060018101546002820154606060020a90910290600160a060020a031683565b6000818152602081905260409020600201548190600160a060020a031615801590610427575060008181526020819052604090206002015433600160a060020a03908116911614155b156104315761046d565b60008281526020819052604081209061044a82826104f1565b50600181018054600160a060020a03199081169091556002909101805490911690555b5b5050565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f106104b357805160ff19168380011785556104e0565b828001600101855582156104e0579182015b828111156104e05782518255916020019190600101906104c5565b5b506104ed929150610539565b5090565b50805460018160011615610100020316600290046000825580601f106105175750610535565b601f0160209004906000526020600020908101906105359190610539565b5b50565b61055791905b808211156104ed576000815560010161053f565b5090565b905600a165627a7a72305820a83571409e7b0cc4fe48edd09087f315930ab4e017c62b6d100462285a8f4ae70029" +} diff --git a/js/src/dapps/chaindeploy/contracts/code/jg-voting.json b/js/src/dapps/chaindeploy/contracts/code/jg-voting.json new file mode 100644 index 000000000..08ec4d0ed --- /dev/null +++ b/js/src/dapps/chaindeploy/contracts/code/jg-voting.json @@ -0,0 +1,5 @@ +{ + "compiler": "v0.4.9+commit.364da425", + "source": "https://github.com/jacogr/dapp-voting/blob/9b20754b13b9a387704c0955d88b51d2e0e1896d/src/solidity/Voting.sol", + "output": "0x606060405260008054600160a060020a03191633600160a060020a0316178155600281905560038190556004556611c37937e0800060055534156200004057fe5b5b60408051808201909152600781527f48756e6772793f0000000000000000000000000000000000000000000000000060208201526200008e906401000000006200090a6200009682021704565b505b620003af565b60008054819033600160a060020a03908116911614801590620000ba575060055434105b15620000c65762000000565b82600481511080620000d9575060a08151115b15620000e55762000000565b60018054925082810190620000fb908262000244565b50336001838154811015156200010d57fe5b906000526020600020906005020160005b508054600160a060020a03929092166101000261010060a860020a031990921691909117905560018054859190849081106200015657fe5b906000526020600020906005020160005b5060010190805190602001906200018092919062000279565b508133600160a060020a03167f7793f929911ad07e07894a20378f1eccce0fb493486c569d74045731fb583b8e866040518080602001828103825283818151815260200191508051906020019080838360008314620001fc575b805182526020831115620001fc57601f199092019160209182019101620001da565b505050905090810190601f168015620002295780820380516001836020036101000a031916815260200191505b509250505060405180910390a3600192505b5b505b50919050565b8154818355818115116200027357600502816005028360005260206000209182019101620002739190620002ff565b5b505050565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f10620002bc57805160ff1916838001178555620002ec565b82800160010185558215620002ec579182015b82811115620002ec578251825591602001919060010190620002cf565b5b50620002fb9291506200033f565b5090565b6200033c91905b80821115620002fb578054600160a860020a031916815560006200032e600183018262000363565b5060050162000306565b5090565b90565b6200033c91905b80821115620002fb576000815560010162000346565b5090565b90565b50805460018160011615610100020316600290046000825580601f106200038b5750620003ab565b601f016020900490600052602060002090810190620003ab91906200033f565b5b50565b610d2f80620003bf6000396000f300606060405236156100bf5763ffffffff60e060020a60003504166306661abd81146100c15780630d15fd77146100e357806313af40351461010557806331d3164714610123578063476c494c1461014a5780634df6ca2a1461016c5780638a55b54d146101935780638da5cb5b146101b55780639507d39a146101e15780639890220b146102c7578063a3f66b46146102eb578063ad7a672f1461034d578063bd12b4b51461036f578063c09f32e814610391578063f41c1c93146103b8575bfe5b34156100c957fe5b6100d16103df565b60408051918252519081900360200190f35b34156100eb57fe5b6100d16103e6565b60408051918252519081900360200190f35b341561010d57fe5b610121600160a060020a03600435166103ec565b005b341561012b57fe5b61013660043561046d565b604080519115158252519081900360200190f35b6101366004356024356104b8565b604080519115158252519081900360200190f35b341561017457fe5b6101366004356106c3565b604080519115158252519081900360200190f35b341561019b57fe5b6100d16106ee565b60408051918252519081900360200190f35b34156101bd57fe5b6101c56106f4565b60408051600160a060020a039092168252519081900360200190f35b34156101e957fe5b6101f4600435610703565b604051808a15151515815260200189600160a060020a0316600160a060020a0316815260200180602001888152602001878152602001868152602001858152602001848152602001838152602001828103825289818151815260200191508051906020019080838360008314610285575b80518252602083111561028557601f199092019160209182019101610265565b505050905090810190601f1680156102b15780820380516001836020036101000a031916815260200191505b509a505050505050505050505060405180910390f35b34156102cf57fe5b6101366108b2565b604080519115158252519081900360200190f35b610136600480803590602001908201803590602001908080601f0160208091040260200160405190810160405280939291908181526020018383808284375094965061090a95505050505050565b604080519115158252519081900360200190f35b341561035557fe5b6100d1610ab5565b60408051918252519081900360200190f35b341561037757fe5b6100d1610abb565b60408051918252519081900360200190f35b341561039957fe5b610136600435610ac1565b604080519115158252519081900360200190f35b34156103c057fe5b610136600435610b63565b604080519115158252519081900360200190f35b6001545b90565b60035481565b60005433600160a060020a0390811691161461040757610000565b60008054604051600160a060020a03808516939216917f70aea8d848e8a90fb7661b227dc522eb6395c3dac71b63cb59edd5c9899b236491a36000805473ffffffffffffffffffffffffffffffffffffffff1916600160a060020a0383161790555b5b50565b600060018281548110151561047e57fe5b906000526020600020906005020160005b50600160a060020a0333166000908152600491909101602052604090205460ff1690505b919050565b6000805433600160a060020a039081169116148015906104d9575060045434105b156104e357610000565b600154839081106104f357610000565b8360018181548110151561050357fe5b906000526020600020906005020160005b505460ff1615156001141561052857610000565b8460018181548110151561053857fe5b906000526020600020906005020160005b50600160a060020a0333166000908152600491909101602052604090205460ff1615156001141561057957610000565b84600281111561058857610000565b60038054600190810190915560028054600160a060020a0333163101905580548190899081106105b457fe5b906000526020600020906005020160005b5033600160a060020a031660008181526004929092016020526040909120805460ff191692151592909217909155600180549131918990811061060457fe5b906000526020600020906005020160005b50600088815260029190910160205260409020805490910190556001805481908990811061063f57fe5b906000526020600020906005020160005b506000888152600391909101602090815260409182902080549093019092558051600160a060020a033316318152905188928a927f8b8ed2ef61b90da02f78bd8647287f46833d5b11467db4451e5c4b165485bf46929081900390910190a3600194505b5b505b505b505b505b92915050565b6000805433600160a060020a039081169116146106df57610000565b50600581905560015b5b919050565b60055481565b600054600160a060020a031681565b6000600061070f610b8e565b600060006000600060006000600060018b81548110151561072c57fe5b906000526020600020906005020160005b5090508060000160009054906101000a900460ff1699508060000160019054906101000a9004600160a060020a03169850806001018054600181600116156101000203166002900480601f0160208091040260200160405190810160405280929190818152602001828054600181600116156101000203166002900480156108065780601f106107db57610100808354040283529160200191610806565b820191906000526020600020905b8154815290600101906020018083116107e957829003601f168201915b505050505097508060020160006000815260200190815260200160002054965080600201600060018152602001908152602001600020549550806002016000600281526020019081526020016000205494508060030160006000815260200190815260200160002054935080600301600060018152602001908152602001600020549250806003016000600281526020019081526020016000205491505b509193959799909294969850565b6000805433600160a060020a039081169116146108ce57610000565b604051600160a060020a0333811691309091163180156108fc02916000818181858888f19350505050151561090257610000565b5060015b5b90565b60008054819033600160a060020a0390811691161480159061092d575060055434105b1561093757610000565b82600481511080610949575060a08151115b1561095357610000565b600180549250828101906109679082610ba0565b503360018381548110151561097857fe5b906000526020600020906005020160005b508054600160a060020a03929092166101000274ffffffffffffffffffffffffffffffffffffffff001990921691909117905560018054859190849081106109cd57fe5b906000526020600020906005020160005b5060010190805190602001906109f5929190610bd2565b508133600160a060020a03167f7793f929911ad07e07894a20378f1eccce0fb493486c569d74045731fb583b8e866040518080602001828103825283818151815260200191508051906020019080838360008314610a6e575b805182526020831115610a6e57601f199092019160209182019101610a4e565b505050905090810190601f168015610a9a5780820380516001836020036101000a031916815260200191505b509250505060405180910390a3600192505b5b505b50919050565b60025481565b60045481565b60008133600160a060020a0316600182815481101515610add57fe5b906000526020600020906005020160005b50546101009004600160a060020a031614801590610b1b575060005433600160a060020a03908116911614155b15610b2557610000565b6001600184815481101515610b3657fe5b906000526020600020906005020160005b50805460ff1916911515919091179055600191505b5b50919050565b6000805433600160a060020a03908116911614610b7f57610000565b50600481905560015b5b919050565b60408051602081019091526000815290565b815481835581811511610bcc57600502816005028360005260206000209182019101610bcc9190610c51565b5b505050565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f10610c1357805160ff1916838001178555610c40565b82800160010185558215610c40579182015b82811115610c40578251825591602001919060010190610c25565b5b50610c4d929150610c9a565b5090565b6103e391905b80821115610c4d57805474ffffffffffffffffffffffffffffffffffffffffff191681556000610c8a6001830182610cbb565b50600501610c57565b5090565b90565b6103e391905b80821115610c4d5760008155600101610ca0565b5090565b90565b50805460018160011615610100020316600290046000825580601f10610ce15750610469565b601f0160209004906000526020600020908101906104699190610c9a565b5b505600a165627a7a72305820b084dcce4e3d78f8a86c925f6c3f2ed689e3674655482541076a1a22f6cdedad0029" +} diff --git a/js/src/dapps/chaindeploy/contracts/code/registry.json b/js/src/dapps/chaindeploy/contracts/code/registry.json new file mode 100644 index 000000000..6976dee58 --- /dev/null +++ b/js/src/dapps/chaindeploy/contracts/code/registry.json @@ -0,0 +1,5 @@ +{ + "compiler": "v0.4.9+commit.364da425", + "source": "https://github.com/ethcore/contracts/blob/b1e0348144793e4ce6f7d6d2c4c7d0bb4ae9765e/SimpleRegistry.sol", + "output": "0x606060405260008054600160a060020a03191633600160a060020a0316179055670de0b6b3a7640000600355341561003357fe5b5b611b2f806100436000396000f300606060405236156101225763ffffffff60e060020a60003504166306b2ff47811461012457806313af40351461015457806319362a28146101725780633f3935d1146101df578063432ced04146102495780634f39ca59146102685780636795dbcd1461028f57806369fe0e2d1461030257806379ce9fac146103295780638da5cb5b1461035c57806390b97fc11461038857806392698814146103f15780639890220b14610418578063ac4e73f91461043c578063ac72c120146104b1578063c3a3582514610388578063ddca3f4314610541578063deb931a214610563578063df57b74214610592578063e30bd740146105c1578063eadf976014610172578063ef5454d6146106ca578063f25eb5c11461073f578063f6d339e414610751575bfe5b341561012c57fe5b610140600160a060020a03600435166107c7565b604080519115158252519081900360200190f35b341561015c57fe5b610170600160a060020a03600435166107fa565b005b341561017a57fe5b60408051602060046024803582810135601f81018590048502860185019096528585526101409583359593946044949392909201918190840183828082843750949650509335935061086e92505050565b604080519115158252519081900360200190f35b34156101e757fe5b610140600480803590602001908201803590602001908080601f01602080910402602001604051908101604052809392919081815260200183838082843750949650610a1495505050505050565b604080519115158252519081900360200190f35b610140600435610b6e565b604080519115158252519081900360200190f35b341561027057fe5b610140600435610c03565b604080519115158252519081900360200190f35b341561029757fe5b60408051602060046024803582810135601f81018590048502860185019096528585526102e69583359593946044949392909201918190840183828082843750949650610cc495505050505050565b60408051600160a060020a039092168252519081900360200190f35b341561030a57fe5b610140600435610d40565b604080519115158252519081900360200190f35b341561033157fe5b610140600435600160a060020a0360243516610d9e565b604080519115158252519081900360200190f35b341561036457fe5b6102e6610e2e565b60408051600160a060020a039092168252519081900360200190f35b341561039057fe5b60408051602060046024803582810135601f81018590048502860185019096528585526103df9583359593946044949392909201918190840183828082843750949650610cc495505050505050565b60408051918252519081900360200190f35b34156103f957fe5b610140600435610eb9565b604080519115158252519081900360200190f35b341561042057fe5b610140610ed9565b604080519115158252519081900360200190f35b341561044457fe5b610140600480803590602001908201803590602001908080601f0160208091040260200160405190810160405280939291908181526020018383808284375094965050509235600160a060020a03169250610f6e915050565b604080519115158252519081900360200190f35b34156104b957fe5b6101406004356112ac565b604080519115158252519081900360200190f35b341561039057fe5b60408051602060046024803582810135601f81018590048502860185019096528585526103df9583359593946044949392909201918190840183828082843750949650610cc495505050505050565b60408051918252519081900360200190f35b341561054957fe5b6103df61134c565b60408051918252519081900360200190f35b341561056b57fe5b6102e6600435611352565b60408051600160a060020a039092168252519081900360200190f35b341561059a57fe5b6102e6600435611370565b60408051600160a060020a039092168252519081900360200190f35b34156105c957fe5b6105dd600160a060020a0360043516611392565b604080516020808252835181830152835191928392908301918501908083838215610623575b80518252602083111561062357601f199092019160209182019101610603565b505050905090810190601f16801561064f5780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b341561017a57fe5b60408051602060046024803582810135601f81018590048502860185019096528585526101409583359593946044949392909201918190840183828082843750949650509335935061086e92505050565b604080519115158252519081900360200190f35b34156106d257fe5b610140600480803590602001908201803590602001908080601f0160208091040260200160405190810160405280939291908181526020018383808284375094965050509235600160a060020a031692506115e8915050565b604080519115158252519081900360200190f35b341561074757fe5b6101706116c6565b005b341561075957fe5b60408051602060046024803582810135601f8101859004850286018501909652858552610140958335959394604494939290920191819084018382808284375094965050509235600160a060020a0316925061185a915050565b604080519115158252519081900360200190f35b600160a060020a03811660009081526002602081905260409091205460001961010060018316150201160415155b919050565b60005433600160a060020a039081169116146108155761086a565b60008054604051600160a060020a03808516939216917f70aea8d848e8a90fb7661b227dc522eb6395c3dac71b63cb59edd5c9899b236491a360008054600160a060020a031916600160a060020a0383161790555b5b50565b600083815260016020526040812054849033600160a060020a0390811691161461089757610a0b565b6000858152600160209081526040918290209151865186936002019288929182918401908083835b602083106108de5780518252601f1990920191602091820191016108bf565b51815160209384036101000a60001901801990921691161790529201948552506040519384900381018420949094555050855186928291908401908083835b6020831061093c5780518252601f19909201916020918201910161091d565b51815160209384036101000a6000190180199092169116179052604080519290940182900382208183528a51838301528a519096508b95507fb829c3e412537bbe794c048ccb9e4605bb4aaaa8e4d4c15c1a6e0c2adc1716ea948b94508392908301919085019080838382156109cd575b8051825260208311156109cd57601f1990920191602091820191016109ad565b505050905090810190601f1680156109f95780820380516001836020036101000a031916815260200191505b509250505060405180910390a3600191505b5b509392505050565b60008133600160a060020a031660016000836040518082805190602001908083835b60208310610a555780518252601f199092019160209182019101610a36565b51815160209384036101000a6000190180199092169116179052604080519290940182900390912086528501959095529290920160002060010154600160a060020a0316939093149250610aab91505057610b67565b600160a060020a03331660009081526002602090815260409091208451610ad492860190611a09565b5033600160a060020a0316836040518082805190602001908083835b60208310610b0f5780518252601f199092019160209182019101610af0565b5181516020939093036101000a60001901801990911692169190911790526040519201829003822093507f098ae8581bb8bd9af1beaf7f2e9f51f31a8e5a8bfada4e303a645d71d9c9192092506000919050a3600191505b5b50919050565b6000818152600160205260408120548290600160a060020a031615610b9257610b67565b600354341015610ba157610b67565b6000838152600160205260408082208054600160a060020a03191633600160a060020a03169081179091559051909185917f4963513eca575aba66fdcd25f267aae85958fe6fb97e75fa25d783f1a091a2219190a3600191505b5b5b50919050565b600081815260016020526040812054829033600160a060020a03908116911614610c2c57610b67565b600083815260016020818152604080842090920154600160a060020a03168352600290528120610c5b91611a88565b60008381526001602081905260408083208054600160a060020a03199081168255920180549092169091555133600160a060020a03169185917fef1961b4d2909dc23643b309bfe5c3e5646842d98c3a58517037ef3871185af39190a3600191505b5b50919050565b600082815260016020908152604080832090518451600290920192859282918401908083835b60208310610d095780518252601f199092019160209182019101610cea565b51815160209384036101000a6000190180199092169116179052920194855250604051938490030190922054925050505b92915050565b6000805433600160a060020a03908116911614610d5c576107f5565b60038290556040805183815290517f6bbc57480a46553fa4d156ce702beef5f3ad66303b0ed1a5d4cb44966c6584c39181900360200190a15060015b5b919050565b600082815260016020526040812054839033600160a060020a03908116911614610dc757610e26565b6000848152600160205260408082208054600160a060020a031916600160a060020a0387811691821790925591519192339091169187917f7b97c62130aa09acbbcbf7482630e756592496f1759eaf702f469cf64dfb779491a4600191505b5b5092915050565b600054600160a060020a031681565b600082815260016020908152604080832090518451600290920192859282918401908083835b60208310610d095780518252601f199092019160209182019101610cea565b51815160209384036101000a6000190180199092169116179052920194855250604051938490030190922054925050505b92915050565b600081815260016020526040902054600160a060020a031615155b919050565b6000805433600160a060020a03908116911614610ef557610f6a565b60408051600160a060020a03301631815290517fdef931299fe61d176f949118058530c1f3f539dcb6950b4e372c9b835c33ca079181900360200190a1604051600160a060020a0333811691309091163180156108fc02916000818181858888f193505050501515610f6657610000565b5060015b5b90565b60006000836040518082805190602001908083835b60208310610fa25780518252601f199092019160209182019101610f83565b51815160209384036101000a6000190180199092169116179052604080519290940182900390912060008181526001909252929020549193505033600160a060020a039081169116149050610ff6576112a3565b846040518082805190602001908083835b602083106110265780518252601f199092019160209182019101611007565b51815160209384036101000a60001901801990921691161790526040805192909401829003909120600081815260019283905293909320015491955050600160a060020a03161580159250905061111257506000828152600160208181526040808420830154600160a060020a031684526002918290529283902092518354869493919283928592908116156101000260001901160480156110ff5780601f106110dd5761010080835404028352918201916110ff565b820191906000526020600020905b8154815290600101906020018083116110eb575b5050915050604051809103902060001916145b156111eb57600082815260016020818152604080842090920154600160a060020a0316835260029052812061114691611a88565b6000828152600160208181526040928390209091015491518751600160a060020a039093169288928291908401908083835b602083106111975780518252601f199092019160209182019101611178565b5181516020939093036101000a60001901801990911692169190911790526040519201829003822093507f12491ad95fd945e444d88a894ffad3c21959880a4dcd8af99d4ae4ffc71d4abd92506000919050a35b6000828152600160208181526040928390209091018054600160a060020a031916600160a060020a0388169081179091559151875188928291908401908083835b6020831061124b5780518252601f19909201916020918201910161122c565b5181516020939093036101000a60001901801990911692169190911790526040519201829003822093507f728435a0031f6a04538fcdd24922a7e06bc7bc945db03e83d22122d1bc5f28df92506000919050a3600192505b5b505092915050565b60008181526001602081905260409091200154600160a060020a031615155b919050565b600082815260016020908152604080832090518451600290920192859282918401908083835b60208310610d095780518252601f199092019160209182019101610cea565b51815160209384036101000a6000190180199092169116179052920194855250604051938490030190922054925050505b92915050565b60035481565b600081815260016020526040902054600160a060020a03165b919050565b60008181526001602081905260409091200154600160a060020a03165b919050565b61139a611ad0565b600160a060020a038216600090815260026020818152604092839020805484516001821615610100026000190190911693909304601f81018390048302840183019094528383529192908301828280156114355780601f1061140a57610100808354040283529160200191611435565b820191906000526020600020905b81548152906001019060200180831161141857829003601f168201915b505050505090505b919050565b600083815260016020526040812054849033600160a060020a0390811691161461089757610a0b565b6000858152600160209081526040918290209151865186936002019288929182918401908083835b602083106108de5780518252601f1990920191602091820191016108bf565b51815160209384036101000a60001901801990921691161790529201948552506040519384900381018420949094555050855186928291908401908083835b6020831061093c5780518252601f19909201916020918201910161091d565b51815160209384036101000a6000190180199092169116179052604080519290940182900382208183528a51838301528a519096508b95507fb829c3e412537bbe794c048ccb9e4605bb4aaaa8e4d4c15c1a6e0c2adc1716ea948b94508392908301919085019080838382156109cd575b8051825260208311156109cd57601f1990920191602091820191016109ad565b505050905090810190601f1680156109f95780820380516001836020036101000a031916815260200191505b509250505060405180910390a3600191505b5b509392505050565b6000805433600160a060020a0390811691161461160457610d3a565b600160a060020a0382166000908152600260209081526040909120845161162d92860190611a09565b5081600160a060020a0316836040518082805190602001908083835b602083106116685780518252601f199092019160209182019101611649565b5181516020939093036101000a60001901801990911692169190911790526040519201829003822093507f098ae8581bb8bd9af1beaf7f2e9f51f31a8e5a8bfada4e303a645d71d9c9192092506000919050a35060015b5b92915050565b33600160a060020a03166002600033600160a060020a0316600160a060020a0316815260200190815260200160002060405180828054600181600116156101000203166002900480156117505780601f1061172e576101008083540402835291820191611750565b820191906000526020600020905b81548152906001019060200180831161173c575b505060405190819003812092507f12491ad95fd945e444d88a894ffad3c21959880a4dcd8af99d4ae4ffc71d4abd9150600090a3600160006002600033600160a060020a0316600160a060020a0316815260200190815260200160002060405180828054600181600116156101000203166002900480156118085780601f106117e6576101008083540402835291820191611808565b820191906000526020600020905b8154815290600101906020018083116117f4575b50506040805191829003909120845260208085019590955292830160009081206001018054600160a060020a031916905533600160a060020a0316815260029094525050812061185791611a88565b5b565b600083815260016020526040812054849033600160a060020a0390811691161461188357610a0b565b60008581526001602090815260409182902091518651600160a060020a038716936002019288929182918401908083835b602083106108de5780518252601f1990920191602091820191016108bf565b51815160209384036101000a60001901801990921691161790529201948552506040519384900381018420949094555050855186928291908401908083835b6020831061093c5780518252601f19909201916020918201910161091d565b51815160209384036101000a6000190180199092169116179052604080519290940182900382208183528a51838301528a519096508b95507fb829c3e412537bbe794c048ccb9e4605bb4aaaa8e4d4c15c1a6e0c2adc1716ea948b94508392908301919085019080838382156109cd575b8051825260208311156109cd57601f1990920191602091820191016109ad565b505050905090810190601f1680156109f95780820380516001836020036101000a031916815260200191505b509250505060405180910390a3600191505b5b509392505050565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f10611a4a57805160ff1916838001178555611a77565b82800160010185558215611a77579182015b82811115611a77578251825591602001919060010190611a5c565b5b50611a84929150611ae2565b5090565b50805460018160011615610100020316600290046000825580601f10611aae575061086a565b601f01602090049060005260206000209081019061086a9190611ae2565b5b50565b60408051602081019091526000815290565b610f6a91905b80821115611a845760008155600101611ae8565b5090565b905600a165627a7a723058202a8f09bd2a20f43dfe4c6adb69bf4bfa211cda23787d972cd6e33eee989cafc50029" +} diff --git a/js/src/dapps/chaindeploy/contracts/code/signaturereg.json b/js/src/dapps/chaindeploy/contracts/code/signaturereg.json new file mode 100644 index 000000000..c3caf9276 --- /dev/null +++ b/js/src/dapps/chaindeploy/contracts/code/signaturereg.json @@ -0,0 +1,5 @@ +{ + "compiler": "v0.4.9+commit.364da425", + "source": "https://github.com/ethcore/contracts/blob/58842b92c00e3c45a84b6d0ac9b842f016dde50a/SignatureReg.sol", + "output": "0x606060405260008054600160a060020a03191633600160a060020a0316178155600255341561002a57fe5b5b60408051808201909152601081527f726567697374657228737472696e67290000000000000000000000000000000060208201526100759064010000000061036661007c82021704565b505b61031c565b60006100f7826040518082805190602001908083835b602083106100b15780518252601f199092019160209182019101610092565b6001836020036101000a0380198251168184511680821785525050505050509050019150506040518091039020836100ff640100000000026103d6176401000000009004565b90505b919050565b7fffffffff000000000000000000000000000000000000000000000000000000008216600090815260016020819052604082205484916002908216156101000260001901909116041561015157610274565b7fffffffff000000000000000000000000000000000000000000000000000000008416600090815260016020908152604090912084516101939286019061027c565b5060028054600101905560408051602080825285518183015285517fffffffff00000000000000000000000000000000000000000000000000000000881693600160a060020a033316937f50e01e16719d6c699e516c57f4c514e77f6bc21a978d33f23980acdddbcbd0b293899391928392908301918501908083838215610236575b80518252602083111561023657601f199092019160209182019101610216565b505050905090810190601f1680156102625780820380516001836020036101000a031916815260200191505b509250505060405180910390a3600191505b5b5092915050565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f106102bd57805160ff19168380011785556102ea565b828001600101855582156102ea579182015b828111156102ea5782518255916020019190600101906102cf565b5b506102f79291506102fb565b5090565b61031991905b808211156102f75760008155600101610301565b5090565b90565b6105d78061032b6000396000f3006060604052361561005c5763ffffffff60e060020a60003504166313af4035811461005e5780633015a5211461007c5780638da5cb5b1461009e5780639890220b146100ca578063b46bcdaa146100dc578063f2c298be14610179575bfe5b341561006657fe5b61007a600160a060020a03600435166101e3565b005b341561008457fe5b61008c610264565b60408051918252519081900360200190f35b34156100a657fe5b6100ae61026a565b60408051600160a060020a039092168252519081900360200190f35b34156100d257fe5b61007a610279565b005b34156100e457fe5b6100f9600160e060020a0319600435166102cc565b60408051602080825283518183015283519192839290830191850190808383821561013f575b80518252602083111561013f57601f19909201916020918201910161011f565b505050905090810190601f16801561016b5780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b341561018157fe5b6101cf600480803590602001908201803590602001908080601f0160208091040260200160405190810160405280939291908181526020018383808284375094965061036695505050505050565b604080519115158252519081900360200190f35b60005433600160a060020a039081169116146101fe57610260565b60008054604051600160a060020a03808516939216917f70aea8d848e8a90fb7661b227dc522eb6395c3dac71b63cb59edd5c9899b236491a36000805473ffffffffffffffffffffffffffffffffffffffff1916600160a060020a0383161790555b5b50565b60025481565b600054600160a060020a031681565b60005433600160a060020a03908116911614610294576102c8565b604051600160a060020a0333811691309091163180156108fc02916000818181858888f1935050505015156102c857610000565b5b5b565b60016020818152600092835260409283902080548451600294821615610100026000190190911693909304601f810183900483028401830190945283835291929083018282801561035e5780601f106103335761010080835404028352916020019161035e565b820191906000526020600020905b81548152906001019060200180831161034157829003601f168201915b505050505081565b60006103ce826040518082805190602001908083835b6020831061039b5780518252601f19909201916020918201910161037c565b6001836020036101000a0380198251168184511680821785525050505050509050019150506040518091039020836103d6565b90505b919050565b600160e060020a03198216600090815260016020819052604082205484916002908216156101000260001901909116041561041057610503565b600160e060020a031984166000908152600160209081526040909120845161043a9286019061050b565b506002805460010190556040805160208082528551818301528551600160e060020a0319881693600160a060020a033316937f50e01e16719d6c699e516c57f4c514e77f6bc21a978d33f23980acdddbcbd0b2938993919283929083019185019080838382156104c5575b8051825260208311156104c557601f1990920191602091820191016104a5565b505050905090810190601f1680156104f15780820380516001836020036101000a031916815260200191505b509250505060405180910390a3600191505b5b5092915050565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f1061054c57805160ff1916838001178555610579565b82800160010185558215610579579182015b8281111561057957825182559160200191906001019061055e565b5b5061058692915061058a565b5090565b6105a891905b808211156105865760008155600101610590565b5090565b905600a165627a7a723058206830357dde798fafa19dd78a4460c047f76cc132713db13442c5da7485fc0ff40029" +} diff --git a/js/src/dapps/chaindeploy/contracts/code/tokendeploy.json b/js/src/dapps/chaindeploy/contracts/code/tokendeploy.json new file mode 100644 index 000000000..b04fdb38b --- /dev/null +++ b/js/src/dapps/chaindeploy/contracts/code/tokendeploy.json @@ -0,0 +1,5 @@ +{ + "compiler": "v0.4.9+commit.364da425", + "source": "https://github.com/ethcore/contracts/blob/0ca02d60066202432305c8e9b1cbf33267478ab3/BasicCoin.sol", + "output": "0x606060405260008054600160a060020a03191633600160a060020a0316179055341561002757fe5b5b610f43806100376000396000f3006060604052361561007d5763ffffffff60e060020a600035041663061ea8cc811461007f57806306661abd146100ad57806313af4035146100cf5780635001f3b5146100ed5780638da5cb5b1461010f5780639507d39a1461013b5780639890220b14610179578063acfdfd1c1461018b578063c00ca38314610236575bfe5b341561008757fe5b61009b600160a060020a0360043516610280565b60408051918252519081900360200190f35b34156100b557fe5b61009b61029f565b60408051918252519081900360200190f35b34156100d757fe5b6100eb600160a060020a03600435166102a6565b005b34156100f557fe5b61009b610327565b60408051918252519081900360200190f35b341561011757fe5b61011f61032e565b60408051600160a060020a039092168252519081900360200190f35b341561014357fe5b61014e60043561033d565b60408051600160a060020a039485168152928416602084015292168183015290519081900360600190f35b341561018157fe5b6100eb610392565b005b60408051602060046024803582810135601f8101859004850286018501909652858552610222958335959394604494939290920191819084018382808284375050604080516020601f89358b0180359182018390048302840183019094528083529799988101979196509182019450925082915084018382808284375094965050509235600160a060020a031692506103e5915050565b604080519115158252519081900360200190f35b341561023e57fe5b61014e600160a060020a036004351660243561079b565b60408051600160a060020a039485168152928416602084015292168183015290519081900360600190f35b600160a060020a0381166000908152600260205260409020545b919050565b6001545b90565b60005433600160a060020a039081169116146102c157610000565b60008054604051600160a060020a03808516939216917f70aea8d848e8a90fb7661b227dc522eb6395c3dac71b63cb59edd5c9899b236491a36000805473ffffffffffffffffffffffffffffffffffffffff1916600160a060020a0383161790555b5b50565b620f424081565b600054600160a060020a031681565b600060006000600060018581548110151561035457fe5b906000526020600020906003020160005b50805460018201546002830154600160a060020a039283169750908216955016925090505b509193909250565b60005433600160a060020a039081169116146103ad57610000565b604051600160a060020a0333811691309091163180156108fc02916000818181858888f1935050505015156103e157610000565b5b5b565b60008181808088336103f56107eb565b918252600160a060020a03166020820152604080519182900301906000f080151561041c57fe5b925061042733610280565b915083600160a060020a031663ddca3f436000604051602001526040518163ffffffff1660e060020a028152600401809050602060405180830381600087803b151561046f57fe5b60325a03f1151561047c57fe5b50506040805151600160a060020a03331660009081526002602052919091209092506001840191506104ae90826107fb565b50600154600160a060020a03331660009081526002602052604090208054849081106104d657fe5b906000526020600020900160005b5055600180548082016104f78382610825565b916000526020600020906003020160005b60606040519081016040528087600160a060020a0316815260200133600160a060020a0316815260200188600160a060020a0316815250909190915060008201518160000160006101000a815481600160a060020a030219169083600160a060020a0316021790555060208201518160010160006101000a815481600160a060020a030219169083600160a060020a0316021790555060408201518160020160006101000a815481600160a060020a030219169083600160a060020a0316021790555050505083600160a060020a0316637b1a547c82858b620f42408c336000604051602001526040518763ffffffff1660e060020a0281526004018086600160a060020a0316600160a060020a03168152602001806020018581526020018060200184600160a060020a0316600160a060020a03168152602001838103835287818151815260200191508051906020019080838360008314610686575b80518252602083111561068657601f199092019160209182019101610666565b505050905090810190601f1680156106b25780820380516001836020036101000a031916815260200191505b50838103825285518152855160209182019187019080838382156106f1575b8051825260208311156106f157601f1990920191602091820191016106d1565b505050905090810190601f16801561071d5780820380516001836020036101000a031916815260200191505b509750505050505050506020604051808303818588803b151561073c57fe5b61235a5a03f1151561074a57fe5b5050604051600160a060020a03808716935087811692503316907f454b0172f64812df0cd504c2bd7df7aab8ff328a54d946b4bd0fa7c527adf9cc90600090a4600194505b50505050949350505050565b600160a060020a03821660009081526002602052604081208054829182916107dd9190869081106107c857fe5b906000526020600020900160005b505461033d565b9250925092505b9250925092565b604051610650806108c883390190565b81548183558181151161081f5760008381526020902061081f918101908301610857565b5b505050565b81548183558181151161081f5760030281600302836000526020600020918201910161081f9190610878565b5b505050565b6102a391905b80821115610871576000815560010161085d565b5090565b90565b6102a391905b8082111561087157805473ffffffffffffffffffffffffffffffffffffffff19908116825560018201805482169055600282018054909116905560030161087e565b5090565b905600606060405260008054600160a060020a03191633600160a060020a0316179055341561002757fe5b6040516040806106508339810160405280516020909101515b600034111561004e57610000565b8180151561005b57610000565b600183905560008054600160a060020a031916600160a060020a038416908117825581526002602052604090208390555b5b505b50505b6105af806100a16000396000f3006060604052361561007d5763ffffffff60e060020a600035041663095ea7b3811461009257806313af4035146100c557806318160ddd146100e357806323b872dd146101055780635001f3b51461013e57806370a08231146101605780638da5cb5b1461018e578063a9059cbb146101ba578063dd62ed3e146101ed575b341561008557fe5b6100905b610000565b565b005b341561009a57fe5b6100b1600160a060020a0360043516602435610221565b604080519115158252519081900360200190f35b34156100cd57fe5b610090600160a060020a03600435166102b6565b005b34156100eb57fe5b6100f3610337565b60408051918252519081900360200190f35b341561010d57fe5b6100b1600160a060020a036004358116906024351660443561033d565b604080519115158252519081900360200190f35b341561014657fe5b6100f361045d565b60408051918252519081900360200190f35b341561016857fe5b6100f3600160a060020a0360043516610464565b60408051918252519081900360200190f35b341561019657fe5b61019e610483565b60408051600160a060020a039092168252519081900360200190f35b34156101c257fe5b6100b1600160a060020a0360043516602435610492565b604080519115158252519081900360200190f35b34156101f557fe5b6100f3600160a060020a0360043581169060243516610552565b60408051918252519081900360200190f35b6000600034111561023157610000565b82600160a060020a031633600160a060020a03167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925846040518082815260200191505060405180910390a350600160a060020a0333811660009081526002602090815260408083209386168352600193840190915290208054830190555b5b92915050565b60005433600160a060020a039081169116146102d157610000565b60008054604051600160a060020a03808516939216917f70aea8d848e8a90fb7661b227dc522eb6395c3dac71b63cb59edd5c9899b236491a36000805473ffffffffffffffffffffffffffffffffffffffff1916600160a060020a0383161790555b5b50565b60015481565b6000600034111561034d57610000565b600160a060020a038416600090815260026020526040902054849083908190101561037757610000565b600160a060020a0380871660009081526002602090815260408083203394851684526001019091529020548791908690819010156103b457610000565b87600160a060020a031689600160a060020a03167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef896040518082815260200191505060405180910390a3600160a060020a03808a16600090815260026020818152604080842033861685526001808201845282862080548f900390559390925281548c9003909155928b16825291902080548901905595505b5b5050505b50505b9392505050565b620f424081565b600160a060020a0381166000908152600260205260409020545b919050565b600054600160a060020a031681565b600060003411156104a257610000565b33600160a060020a0381166000908152600260205260409020548390819010156104cb57610000565b84600160a060020a031633600160a060020a03167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef866040518082815260200191505060405180910390a3600160a060020a0333811660009081526002602052604080822080548890039055918716815220805485019055600192505b5b50505b92915050565b600160a060020a03808316600090815260026020908152604080832093851683526001909301905220545b929150505600a165627a7a72305820b5bf89a0a85c15df1e9717e49be06fe1a4f9dcc1e0cebf5483dd1c0bcd14a0910029a165627a7a723058207f96b7ad40c02cfaeaf29e65c79456dd3fd9828c9d3fbaf801fb60010456c3880029" +} diff --git a/js/src/dapps/chaindeploy/contracts/code/tokenreg.json b/js/src/dapps/chaindeploy/contracts/code/tokenreg.json new file mode 100644 index 000000000..bd96f16b1 --- /dev/null +++ b/js/src/dapps/chaindeploy/contracts/code/tokenreg.json @@ -0,0 +1,5 @@ +{ + "compiler": "v0.4.9+commit.364da425", + "source": "https://github.com/ethcore/contracts/blob/58842b92c00e3c45a84b6d0ac9b842f016dde50a/TokenReg.sol", + "output": "0x606060405260008054600160a060020a03191633600160a060020a0316179055670de0b6b3a7640000600455341561003357fe5b5b611473806100436000396000f300606060405236156100b45763ffffffff60e060020a600035041663044215c681146100b657806313af4035146101df57806366b42dcb146101fd57806369fe0e2d146102ab5780637958533a146102c05780637b1a547c146102e8578063891de9ed146103a15780638da5cb5b146104bc5780639890220b146104e85780639f181b5e146104fa578063a02b161e1461051c578063b72e717d14610531578063dd93890b1461066a578063ddca3f4314610685575bfe5b34156100be57fe5b6100c96004356106a7565b60408051600160a060020a038088168252918101859052908216608082015260a060208083018281528751928401929092528651606084019160c0850191908901908083838215610135575b80518252602083111561013557601f199092019160209182019101610115565b505050905090810190601f1680156101615780820380516001836020036101000a031916815260200191505b50838103825285518152855160209182019187019080838382156101a0575b8051825260208311156101a057601f199092019160209182019101610180565b505050905090810190601f1680156101cc5780820380516001836020036101000a031916815260200191505b5097505050505050505060405180910390f35b34156101e757fe5b6101fb600160a060020a036004351661083a565b005b60408051602060046024803582810135601f8101859004850286018501909652858552610297958335600160a060020a0316959394604494939290920191819084018382808284375050604080516020601f818a01358b0180359182018390048302840183018552818452989a8a359a9099940197509195509182019350915081908401838280828437509496506108ae95505050505050565b604080519115158252519081900360200190f35b34156102b357fe5b6101fb6004356108c8565b005b34156102c857fe5b6102d66004356024356108ed565b60408051918252519081900360200190f35b60408051602060046024803582810135601f8101859004850286018501909652858552610297958335600160a060020a0316959394604494939290920191819084018382808284375050604080516020601f818a01358b0180359182018390048302840183018552818452989a8a359a90999401975091955091820193509150819084018382808284375094965050509235600160a060020a0316925061092c915050565b604080519115158252519081900360200190f35b34156103a957fe5b6103f7600480803590602001908201803590602001908080601f01602080910402602001604051908101604052809392919081815260200183838082843750949650610c6695505050505050565b6040518086815260200185600160a060020a0316600160a060020a031681526020018481526020018060200183600160a060020a0316600160a060020a0316815260200182810382528481815181526020019150805190602001908083836000831461047e575b80518252602083111561047e57601f19909201916020918201910161045e565b505050905090810190601f1680156104aa5780820380516001836020036101000a031916815260200191505b50965050505050505060405180910390f35b34156104c457fe5b6104cc610dca565b60408051600160a060020a039092168252519081900360200190f35b34156104f057fe5b6101fb610dd9565b005b341561050257fe5b6102d6610e2c565b60408051918252519081900360200190f35b341561052457fe5b6101fb600435610e33565b005b341561053957fe5b61054d600160a060020a0360043516611047565b60405180868152602001806020018581526020018060200184600160a060020a0316600160a060020a03168152602001838103835287818151815260200191508051906020019080838360008314610135575b80518252602083111561013557601f199092019160209182019101610115565b505050905090810190601f1680156101615780820380516001836020036101000a031916815260200191505b50838103825285518152855160209182019187019080838382156101a0575b8051825260208311156101a057601f199092019160209182019101610180565b505050905090810190601f1680156101cc5780820380516001836020036101000a031916815260200191505b5097505050505050505060405180910390f35b341561067257fe5b6101fb6004356024356044356111f3565b005b341561068d57fe5b6102d66112b0565b60408051918252519081900360200190f35b60006106b16112b6565b60006106bb6112b6565b600060006003878154811015156106ce57fe5b906000526020600020906006020160005b50805460018083018054604080516020601f600260001997861615610100029790970190941695909504928301859004850281018501909152818152600160a060020a039094169a5093945091929083018282801561077f5780601f106107545761010080835404028352916020019161077f565b820191906000526020600020905b81548152906001019060200180831161076257829003601f168201915b505050600280850154600386018054604080516020601f6000196101006001871615020190941696909604928301869004860281018601909152818152969b50919950935091508301828280156108175780601f106107ec57610100808354040283529160200191610817565b820191906000526020600020905b8154815290600101906020018083116107fa57829003601f168201915b50505050600483015491945050600160a060020a031691505b5091939590929450565b60005433600160a060020a03908116911614610855576108aa565b60008054604051600160a060020a03808516939216917f70aea8d848e8a90fb7661b227dc522eb6395c3dac71b63cb59edd5c9899b236491a360008054600160a060020a031916600160a060020a0383161790555b5b50565b60006108bd858585853361092c565b90505b949350505050565b60005433600160a060020a039081169116146108e3576108aa565b60048190555b5b50565b60006003838154811015156108fe57fe5b906000526020600020906006020160005b506000838152600591909101602052604090205490505b92915050565b600060045434101561093d57610c5d565b600160a060020a03861660009081526001602052604090205486901561096257610c5b565b8551869060031461097257610c59565b866002816040518082805190602001908083835b602083106109a55780518252601f199092019160209182019101610986565b51815160209384036101000a60001901801990921691161790529201948552506040519384900301909220541591506109df905057610c56565b60038054600181016109f183826112c8565b916000526020600020906006020160005b506040805160a081018252600160a060020a03808e1680835260208084018f90529383018d9052606083018c9052908a1660808301528354600160a060020a0319161783558b51909291610a5d9160018401918e01906112fa565b506040820151600282015560608201518051610a839160038401916020909101906112fa565b506080919091015160049091018054600160a060020a031916600160a060020a03928316179055600354908b1660009081526001602090815260409182902083905590518b519293506002928c928291908401908083835b60208310610afa5780518252601f199092019160209182019101610adb565b51815160001960209485036101000a81019182169119929092161790915293909101958652604051958690038101862096909655506003548d519101948d9493508392508401908083835b60208310610b645780518252601f199092019160209182019101610b45565b6001836020036101000a03801982511681845116808217855250505050505090500191505060405180910390207f25074d730da65a10e171fe5589d2182313ef00da38d23a9ae3b78923568bdf2d8b896040518083600160a060020a0316600160a060020a0316815260200180602001828103825283818151815260200191508051906020019080838360008314610c17575b805182526020831115610c1757601f199092019160209182019101610bf7565b505050905090810190601f168015610c435780820380516001836020036101000a031916815260200191505b50935050505060405180910390a3600193505b5b505b505b505b95945050505050565b600060006000610c746112b6565b6000600060016002886040518082805190602001908083835b60208310610cac5780518252601f199092019160209182019101610c8d565b6001836020036101000a038019825116818451168082178552505050505050905001915050908152602001604051809103902054039550600386815481101515610cf257fe5b906000526020600020906006020160005b5080546002808301546003840180546040805160206101006001851615026000190190931695909504601f8101839004830286018301909152808552600160a060020a039095169a50919850939450909291908301828280156108175780601f106107ec57610100808354040283529160200191610817565b820191906000526020600020905b8154815290600101906020018083116107fa57829003601f168201915b50505050600483015491945050600160a060020a031691505b5091939590929450565b600054600160a060020a031681565b60005433600160a060020a03908116911614610df457610e28565b604051600160a060020a0333811691309091163180156108fc02916000818181858888f193505050501515610e2857610000565b5b5b565b6003545b90565b60005433600160a060020a03908116911614610e4e576108aa565b80600382815481101515610e5e57fe5b906000526020600020906006020160005b506001016040518082805460018160011615610100020316600290048015610ece5780601f10610eac576101008083540402835291820191610ece565b820191906000526020600020905b815481529060010190602001808311610eba575b505060405190819003812092507f96e76fa77fea85d8abeb7533fdb8288c214bb1dcf1f867c8f36a95f1f509c1759150600090a360016000600383815481101515610f1557fe5b906000526020600020906006020160005b5054600160a060020a031681526020810191909152604001600090812055600380546002919083908110610f5657fe5b906000526020600020906006020160005b506001016040518082805460018160011615610100020316600290048015610fc65780601f10610fa4576101008083540402835291820191610fc6565b820191906000526020600020905b815481529060010190602001808311610fb2575b50509283525050604051908190036020019020600090556003805482908110610feb57fe5b906000526020600020906006020160005b8154600160a060020a0319168255611018600183016000611379565b60028201600090556003820160006110309190611379565b506004018054600160a060020a03191690555b5b50565b60006110516112b6565b600061105b6112b6565b600160a060020a03851660009081526001602052604081205460038054600019909201965082918790811061108c57fe5b906000526020600020906006020160005b509050806001018054600181600116156101000203166002900480601f01602080910402602001604051908101604052809291908181526020018280546001816001161561010002031660029004801561077f5780601f106107545761010080835404028352916020019161077f565b820191906000526020600020905b81548152906001019060200180831161076257829003601f168201915b505050600280850154600386018054604080516020601f6000196101006001871615020190941696909604928301869004860281018601909152818152969b50919950935091508301828280156108175780601f106107ec57610100808354040283529160200191610817565b820191906000526020600020905b8154815290600101906020018083116107fa57829003601f168201915b50505050600483015491945050600160a060020a031691505b5091939590929450565b8233600160a060020a031660038281548110151561120d57fe5b906000526020600020906006020160005b5060040154600160a060020a031614611236576112a9565b8160038581548110151561124657fe5b906000526020600020906006020160005b50600085815260059190910160209081526040918290209290925580518481529051859287927f7991c63a749706fd298fc2387764d640be6e714307b6357b1d3c2ce35cba3b52929081900390910190a35b5b50505050565b60045481565b60408051602081019091526000815290565b8154818355818115116112f4576006028160060283600052602060002091820191016112f491906113c1565b5b505050565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f1061133b57805160ff1916838001178555611368565b82800160010185558215611368579182015b8281111561136857825182559160200191906001019061134d565b5b50611375929150611426565b5090565b50805460018160011615610100020316600290046000825580601f1061139f57506108aa565b601f0160209004906000526020600020908101906108aa9190611426565b5b50565b610e3091905b80821115611375578054600160a060020a031916815560006113ec6001830182611379565b60028201600090556003820160006114049190611379565b50600481018054600160a060020a03191690556006016113c7565b5090565b90565b610e3091905b80821115611375576000815560010161142c565b5090565b905600a165627a7a72305820ab1d1a18270ba278cc2f74cd1b7b547cdcd6308a9df1dec1120fa9f6199b1f480029" +} diff --git a/js/src/dapps/chaindeploy/contracts/code/verifyEmail.json b/js/src/dapps/chaindeploy/contracts/code/verifyEmail.json new file mode 100644 index 000000000..fff3fb07d --- /dev/null +++ b/js/src/dapps/chaindeploy/contracts/code/verifyEmail.json @@ -0,0 +1,5 @@ +{ + "compiler": "v0.4.9+commit.364da425", + "source": "https://github.com/ethcore/contracts/blob/e5afdacc716ca743ceddf80978d4e6b2b465dbe9/ProofOfEmail.sol", + "output": "0x606060405260008054600160a060020a03191633600160a060020a0316178155600355341561002a57fe5b5b6108a48061003a6000396000f300606060405236156100ca5763ffffffff60e060020a60003504166306b2ff4781146100cc57806313af4035146100fc5780632650b9881461011a5780634b59e8801461018c57806359c87d70146101b05780636795dbcd146101bd57806369fe0e2d1461023057806370c4d5f214610245578063797af627146103255780638da5cb5b1461034c5780639890220b14610378578063ac72c1201461038a578063cc1d4c02146103b1578063ddca3f43146103e1578063df57b74214610403578063e30bd74014610432575bfe5b34156100d457fe5b6100e8600160a060020a03600435166104ce565b604080519115158252519081900360200190f35b341561010457fe5b610118600160a060020a03600435166104d6565b005b341561012257fe5b60408051602060046024803582810135601f810185900485028601850190965285855261017a958335600160a060020a0316959394604494939290920191819084018382808284375094965061055795505050505050565b60408051918252519081900360200190f35b341561019457fe5b610118600160a060020a0360043516602435604435610577565b005b6101186004356105eb565b005b34156101c557fe5b60408051602060046024803582810135601f8101859004850286018501909652858552610214958335959394604494939290920191819084018382808284375094965061063595505050505050565b60408051600160a060020a039092168252519081900360200190f35b341561023857fe5b610118600435610654565b005b341561024d57fe5b60408051602060046024803582810135601f81018590048502860185019096528585526102a5958335600160a060020a0316959394604494939290920191819084018382808284375094965061067995505050505050565b6040805160208082528351818301528351919283929083019185019080838382156102eb575b8051825260208311156102eb57601f1990920191602091820191016102cb565b505050905090810190601f1680156103175780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b341561032d57fe5b6100e8600435610688565b604080519115158252519081900360200190f35b341561035457fe5b610214610791565b60408051600160a060020a039092168252519081900360200190f35b341561038057fe5b6101186107a0565b005b341561039257fe5b6100e86004356107f3565b604080519115158252519081900360200190f35b34156103b957fe5b6100e8600160a060020a0360043516610813565b604080519115158252519081900360200190f35b34156103e957fe5b61017a610834565b60408051918252519081900360200190f35b341561040b57fe5b61021460043561083a565b60408051600160a060020a039092168252519081900360200190f35b341561043a57fe5b6102a5600160a060020a0360043516610858565b6040805160208082528351818301528351919283929083019185019080838382156102eb575b8051825260208311156102eb57601f1990920191602091820191016102cb565b505050905090810190601f1680156103175780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b60005b919050565b60005433600160a060020a039081169116146104f157610553565b60008054604051600160a060020a03808516939216917f70aea8d848e8a90fb7661b227dc522eb6395c3dac71b63cb59edd5c9899b236491a36000805473ffffffffffffffffffffffffffffffffffffffff1916600160a060020a0383161790555b5b50565b600160a060020a0382166000908152600260205260409020545b92915050565b60005433600160a060020a03908116911614610592576105e5565b600082815260046020908152604091829020839055815184815291518392600160a060020a038716927f76babef7e9f1065118be3f9d7094016a1cc06dd12811501c7712deb22144f37b92918290030190a35b5b505050565b6003543410156105fa57610553565b6040518190600160a060020a033316907f070669e6be82aa9b077a096b0f9617893a4dc5cb05897e27fd7a6112c8e6629e90600090a35b5b50565b600082815260016020526040902054600160a060020a03165b92915050565b60005433600160a060020a0390811691161461066f57610553565b60038190555b5b50565b610571610866565b5b92915050565b6040805182815281516020918190038201902060009081526004909152908120548015156106b55761078b565b6040805184815281516020918190038201902060009081526004825282812081905583815260019091522054600160a060020a031615158061070e5750600160a060020a03331660009081526002602052604090205415155b156107185761078b565b6000818152600160209081526040808320805473ffffffffffffffffffffffffffffffffffffffff191633600160a060020a031690811790915580845260029092528083208490555190917fd415b905d4dd806bfba99a7a0e6351bd0c9db3a9912add21c0e6bef4479f673f91a2600191505b50919050565b600054600160a060020a031681565b60005433600160a060020a039081169116146107bb576107ef565b604051600160a060020a0333811691309091163180156108fc02916000818181858888f1935050505015156107ef57610000565b5b5b565b600081815260016020526040902054600160a060020a031615155b919050565b600160a060020a03811660009081526002602052604090205415155b919050565b60035481565b600081815260016020526040902054600160a060020a03165b919050565b6104d1610866565b5b919050565b604080516020810190915260008152905600a165627a7a7230582081d03388dd06c78ee4098c4f1e23cd3c25e38d249d5da59962c6b28ec6e20ea70029" +} diff --git a/js/src/dapps/chaindeploy/contracts/code/verifySms.json b/js/src/dapps/chaindeploy/contracts/code/verifySms.json new file mode 100644 index 000000000..79b9c0459 --- /dev/null +++ b/js/src/dapps/chaindeploy/contracts/code/verifySms.json @@ -0,0 +1,5 @@ +{ + "compiler": "v0.4.9+commit.364da425", + "source": "https://github.com/ethcore/contracts/blob/58842b92c00e3c45a84b6d0ac9b842f016dde50a/SMSVerification.sol", + "output": "0x606060405260008054600160a060020a033316600160a060020a03199182168117909255600280549091169091179055666a94d74f430000600455341561004257fe5b5b6109a0806100526000396000f300606060405236156100ca5763ffffffff60e060020a60003504166313af403581146100cc57806314253887146100ea578063338cdca1146101085780633da5c3ce146101125780635283f3391461013357806369fe0e2d146101af57806374a8f103146101c4578063797af627146101e25780638da5cb5b146102095780639890220b14610235578063c89e436114610247578063ca4cbf6714610273578063ca5eb5e1146102e5578063cc1d4c0214610303578063ddca3f4314610333578063fc2525ab14610273575bfe5b34156100d457fe5b6100e8600160a060020a03600435166103c7565b005b34156100f257fe5b6100e8600160a060020a0360043516610448565b005b6100e86104b4565b005b341561011a57fe5b6100e8600160a060020a0360043516602435610521565b005b341561013b57fe5b60408051602060046024803582810135601f8101859004850286018501909652858552610193958335600160a060020a0316959394604494939290920191819084018382808284375094965061059295505050505050565b60408051600160a060020a039092168252519081900360200190f35b34156101b757fe5b6100e8600435610623565b005b34156101cc57fe5b6100e8600160a060020a0360043516610648565b005b34156101ea57fe5b6101f56004356106d9565b604080519115158252519081900360200190f35b341561021157fe5b610193610771565b60408051600160a060020a039092168252519081900360200190f35b341561023d57fe5b6100e8610780565b005b341561024f57fe5b6101936107d3565b60408051600160a060020a039092168252519081900360200190f35b341561027b57fe5b60408051602060046024803582810135601f81018590048502860185019096528585526102d3958335600160a060020a0316959394604494939290920191819084018382808284375094965061059295505050505050565b60408051918252519081900360200190f35b34156102ed57fe5b6100e8600160a060020a0360043516610873565b005b341561030b57fe5b6101f5600160a060020a03600435166108bb565b604080519115158252519081900360200190f35b341561033b57fe5b6102d36108dd565b60408051918252519081900360200190f35b341561027b57fe5b60408051602060046024803582810135601f81018590048502860185019096528585526102d3958335600160a060020a0316959394604494939290920191819084018382808284375094965061059295505050505050565b60408051918252519081900360200190f35b60005433600160a060020a039081169116146103e257610444565b60008054604051600160a060020a03808516939216917f70aea8d848e8a90fb7661b227dc522eb6395c3dac71b63cb59edd5c9899b236491a36000805473ffffffffffffffffffffffffffffffffffffffff1916600160a060020a0383161790555b5b50565b60025433600160a060020a0390811691161461046357610444565b600160a060020a0381166000818152600160208190526040808320805460ff1916909217909155517fd415b905d4dd806bfba99a7a0e6351bd0c9db3a9912add21c0e6bef4479f673f9190a25b5b50565b6004543410156104c35761051e565b600160a060020a03331660009081526001602052604090205460ff16156104e95761051e565b604051600160a060020a033316907f039f711c9c18dd815b225b1424855e6118e746c6b5d688907f10c4dd29ebe92a90600090a25b5b565b60025433600160a060020a0390811691161461053c5761058d565b600160a060020a038216600081815260036020908152604091829020849055815184815291517fa9a343b39eac85ffb326e93ecd46785b814e72dc9f2b33bb0b4a315ba2859f439281900390910190a25b5b5050565b60006001600084600160a060020a0316600160a060020a03168152602001908152602001600020600101826040518082805190602001908083835b602083106105ec5780518252601f1990920191602091820191016105cd565b51815160209384036101000a6000190180199092169116179052920194855250604051938490030190922054925050505b92915050565b60005433600160a060020a0390811691161461063e57610444565b60048190555b5b50565b60025433600160a060020a0390811691161461066357610444565b600160a060020a038116600090815260016020526040902054819060ff16151561068c5761058d565b600160a060020a038216600081815260016020526040808220805460ff19169055517fb6fa8b8bd5eab60f292eca876e3ef90722275b785309d84b1de113ce0b8c4e749190a25b5b505b50565b6040805182815281516020918190038201902033600160a060020a031660009081526003909252918120549091146107105761076c565b600160a060020a0333166000818152600360209081526040808320839055600191829052808320805460ff1916909217909155517fd415b905d4dd806bfba99a7a0e6351bd0c9db3a9912add21c0e6bef4479f673f9190a25060015b919050565b600054600160a060020a031681565b60005433600160a060020a0390811691161461079b5761051e565b604051600160a060020a0333811691309091163180156108fc02916000818181858888f19350505050151561051e57610000565b5b5b565b600254600160a060020a031681565b60006001600084600160a060020a0316600160a060020a03168152602001908152602001600020600101826040518082805190602001908083835b602083106105ec5780518252601f1990920191602091820191016105cd565b51815160209384036101000a6000190180199092169116179052920194855250604051938490030190922054925050505b92915050565b60005433600160a060020a0390811691161461088e57610444565b6002805473ffffffffffffffffffffffffffffffffffffffff1916600160a060020a0383161790555b5b50565b600160a060020a03811660009081526001602052604090205460ff165b919050565b60045481565b60006001600084600160a060020a0316600160a060020a03168152602001908152602001600020600101826040518082805190602001908083835b602083106105ec5780518252601f1990920191602091820191016105cd565b51815160209384036101000a6000190180199092169116179052920194855250604051938490030190922054925050505b929150505600a165627a7a72305820f6beb9c0ae3b45609ad6fc26c1b74600cbaa5f0088ca07be3e9c392a12b2c6150029" +} diff --git a/js/src/dapps/chaindeploy/contracts/dappreg.js b/js/src/dapps/chaindeploy/contracts/dappreg.js new file mode 100644 index 000000000..71379bf8b --- /dev/null +++ b/js/src/dapps/chaindeploy/contracts/dappreg.js @@ -0,0 +1,30 @@ +// Copyright 2015-2017 Parity Technologies (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 . + +import abi from '~/contracts/abi/dappreg'; +import { compiler, source as sourceUrl, output as byteCode } from './code/dappreg'; + +const id = 'dappreg'; // 7bbc4f1a27628781b96213e781a1b8eec6982c1db8fac739af6e4c5a55862c03 +const deployParams = []; + +export { + abi, + byteCode, + compiler, + deployParams, + id, + sourceUrl +}; diff --git a/js/src/dapps/chaindeploy/contracts/gavcoin.js b/js/src/dapps/chaindeploy/contracts/gavcoin.js new file mode 100644 index 000000000..f7518ef53 --- /dev/null +++ b/js/src/dapps/chaindeploy/contracts/gavcoin.js @@ -0,0 +1,32 @@ +// Copyright 2015-2017 Parity Technologies (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 . + +import abi from '~/contracts/abi/gavcoin'; +import { compiler, source as sourceUrl, output as byteCode } from './code/gavcoin'; + +const isExternal = true; +const id = 'gavcoin'; +const deployParams = []; + +export { + abi, + byteCode, + compiler, + deployParams, + id, + isExternal, + sourceUrl +}; diff --git a/js/src/dapps/chaindeploy/contracts/githubhint.js b/js/src/dapps/chaindeploy/contracts/githubhint.js new file mode 100644 index 000000000..5198e38b5 --- /dev/null +++ b/js/src/dapps/chaindeploy/contracts/githubhint.js @@ -0,0 +1,30 @@ +// Copyright 2015-2017 Parity Technologies (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 . + +import abi from '~/contracts/abi/githubhint'; +import { compiler, source as sourceUrl, output as byteCode } from './code/githubhint'; + +const id = 'githubhint'; +const deployParams = []; + +export { + abi, + byteCode, + compiler, + deployParams, + id, + sourceUrl +}; diff --git a/js/src/dapps/chaindeploy/contracts/index.js b/js/src/dapps/chaindeploy/contracts/index.js new file mode 100644 index 000000000..5e066f758 --- /dev/null +++ b/js/src/dapps/chaindeploy/contracts/index.js @@ -0,0 +1,52 @@ +// Copyright 2015-2017 Parity Technologies (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 . + +import * as badgereg from './badgereg'; +import * as dappreg from './dappreg'; +import * as gavcoin from './gavcoin'; +import * as githubhint from './githubhint'; +import * as jgvoting from './jg-voting'; +import * as registry from './registry'; +import * as signaturereg from './signaturereg'; +import * as tokendeployMgr from './tokendeployMgr'; +import * as tokendeployReg from './tokendeployReg'; +import * as tokenreg from './tokenreg'; +import * as verifyEmail from './verifyEmail'; +import * as verifySms from './verifySms'; +import * as wallet from './wallet'; + +const contracts = [ + // builtin + githubhint, + badgereg, + dappreg, + signaturereg, + tokenreg, + tokendeployReg, + tokendeployMgr, + verifyEmail, + verifySms, + wallet, + + // external + gavcoin, + jgvoting +]; + +export { + contracts, + registry +}; diff --git a/js/src/dapps/chaindeploy/contracts/jg-voting.js b/js/src/dapps/chaindeploy/contracts/jg-voting.js new file mode 100644 index 000000000..8ffbed3c5 --- /dev/null +++ b/js/src/dapps/chaindeploy/contracts/jg-voting.js @@ -0,0 +1,32 @@ +// Copyright 2015-2017 Parity Technologies (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 . + +import abi from './abi/jg-voting'; +import { compiler, source as sourceUrl, output as byteCode } from './code/jg-voting'; + +const isExternal = true; +const id = 'jg-voting'; +const deployParams = []; + +export { + abi, + byteCode, + compiler, + deployParams, + id, + isExternal, + sourceUrl +}; diff --git a/js/src/dapps/chaindeploy/contracts/registry.js b/js/src/dapps/chaindeploy/contracts/registry.js new file mode 100644 index 000000000..1b44f4245 --- /dev/null +++ b/js/src/dapps/chaindeploy/contracts/registry.js @@ -0,0 +1,30 @@ +// Copyright 2015-2017 Parity Technologies (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 . + +import abi from '~/contracts/abi/registry2'; +import { compiler, source as sourceUrl, output as byteCode } from './code/registry'; + +const id = 'registry'; +const deployParams = []; + +export { + abi, + byteCode, + compiler, + deployParams, + id, + sourceUrl +}; diff --git a/js/src/dapps/chaindeploy/contracts/signaturereg.js b/js/src/dapps/chaindeploy/contracts/signaturereg.js new file mode 100644 index 000000000..6d9f9bf60 --- /dev/null +++ b/js/src/dapps/chaindeploy/contracts/signaturereg.js @@ -0,0 +1,30 @@ +// Copyright 2015-2017 Parity Technologies (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 . + +import abi from '~/contracts/abi/signaturereg'; +import { compiler, source as sourceUrl, output as byteCode } from './code/signaturereg'; + +const id = 'signaturereg'; +const deployParams = []; + +export { + abi, + byteCode, + compiler, + deployParams, + id, + sourceUrl +}; diff --git a/js/src/dapps/chaindeploy/contracts/tokendeployMgr.js b/js/src/dapps/chaindeploy/contracts/tokendeployMgr.js new file mode 100644 index 000000000..d07435fdd --- /dev/null +++ b/js/src/dapps/chaindeploy/contracts/tokendeployMgr.js @@ -0,0 +1,30 @@ +// Copyright 2015-2017 Parity Technologies (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 . + +import abi from '~/contracts/abi/basiccoinmanager'; +import { compiler, source as sourceUrl, output as byteCode } from './code/tokendeploy'; + +const id = 'basiccoinmgr'; +const deployParams = []; + +export { + abi, + byteCode, + compiler, + deployParams, + id, + sourceUrl +}; diff --git a/js/src/dapps/chaindeploy/contracts/tokendeployReg.js b/js/src/dapps/chaindeploy/contracts/tokendeployReg.js new file mode 100644 index 000000000..1db07e91a --- /dev/null +++ b/js/src/dapps/chaindeploy/contracts/tokendeployReg.js @@ -0,0 +1,28 @@ +// Copyright 2015-2017 Parity Technologies (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 . + +import { abi, sourceUrl, deployParams, compiler, byteCode } from './tokenreg'; + +const id = 'basiccoinreg'; + +export { + abi, + byteCode, + compiler, + deployParams, + id, + sourceUrl +}; diff --git a/js/src/dapps/chaindeploy/contracts/tokenreg.js b/js/src/dapps/chaindeploy/contracts/tokenreg.js new file mode 100644 index 000000000..11ee29fa1 --- /dev/null +++ b/js/src/dapps/chaindeploy/contracts/tokenreg.js @@ -0,0 +1,30 @@ +// Copyright 2015-2017 Parity Technologies (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 . + +import abi from '~/contracts/abi/tokenreg'; +import { compiler, source as sourceUrl, output as byteCode } from './code/tokenreg'; + +const id = 'tokenreg'; +const deployParams = []; + +export { + abi, + byteCode, + compiler, + deployParams, + id, + sourceUrl +}; diff --git a/js/src/dapps/chaindeploy/contracts/verifyEmail.js b/js/src/dapps/chaindeploy/contracts/verifyEmail.js new file mode 100644 index 000000000..d011f4c51 --- /dev/null +++ b/js/src/dapps/chaindeploy/contracts/verifyEmail.js @@ -0,0 +1,37 @@ +// Copyright 2015-2017 Parity Technologies (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 . + +import abi from '~/contracts/abi/email-verification'; +import { compiler, source as sourceUrl, output as byteCode } from './code/verifyEmail'; + +const isBadge = true; +const id = 'emailverification'; +const deployParams = []; +const badgeSource = { + imageUrl: 'https://raw.githubusercontent.com/ethcore/dapp-assets/c4721a87cb95375da91f8699438d8d7907b3f5e9/certifications/email-verification.svg', + imageHash: '0x5617a14da2a0c210939da6eafb734e60906f64a504c3e107812668860a752dc6' +}; + +export { + abi, + badgeSource, + byteCode, + compiler, + deployParams, + id, + isBadge, + sourceUrl +}; diff --git a/js/src/dapps/chaindeploy/contracts/verifySms.js b/js/src/dapps/chaindeploy/contracts/verifySms.js new file mode 100644 index 000000000..59bf1ba36 --- /dev/null +++ b/js/src/dapps/chaindeploy/contracts/verifySms.js @@ -0,0 +1,37 @@ +// Copyright 2015-2017 Parity Technologies (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 . + +import abi from '~/contracts/abi/sms-verification'; +import { compiler, source as sourceUrl, output as byteCode } from './code/verifySms'; + +const isBadge = true; +const id = 'smsverification'; +const deployParams = []; +const badgeSource = { + imageUrl: 'https://raw.githubusercontent.com/ethcore/dapp-assets/1b1beb57ab1f4d3a93a12711b233b5cded791a2f/certifications/sms-verification.svg', + imageHash: '0x49fa653c35c0a9ce128579883babd673ad4cfc94bf9f1cfe96a2bbc30a7552c6' +}; + +export { + abi, + badgeSource, + byteCode, + compiler, + deployParams, + id, + isBadge, + sourceUrl +}; diff --git a/js/src/dapps/chaindeploy/contracts/wallet.js b/js/src/dapps/chaindeploy/contracts/wallet.js new file mode 100644 index 000000000..6639cba80 --- /dev/null +++ b/js/src/dapps/chaindeploy/contracts/wallet.js @@ -0,0 +1,29 @@ +// Copyright 2015-2017 Parity Technologies (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 . + +import { walletCompiler as compiler, walletLibrary as byteCode, walletLibraryABI as abiJson, walletLibraryRegKey as id, walletSource as sourceUrl } from '~/contracts/code/wallet'; + +const abi = JSON.parse(abiJson); +const deployParams = []; + +export { + abi, + byteCode, + compiler, + deployParams, + id, + sourceUrl +}; diff --git a/js/src/dapps/chaindeploy/dapps/console.js b/js/src/dapps/chaindeploy/dapps/console.js new file mode 100644 index 000000000..f67165502 --- /dev/null +++ b/js/src/dapps/chaindeploy/dapps/console.js @@ -0,0 +1,33 @@ +// Copyright 2015-2017 Parity Technologies (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 . + +import builtins from '~/views/Dapps/builtin.json'; + +const id = 'console'; +const app = builtins.find((app) => app.url === id); +const hashId = app.id; +const source = { + imageUrl: 'https://raw.githubusercontent.com/ethcore/console/3ea0dbfefded359ccdbea37bc4cf350c0aa16948/console.jpeg', + imageHash: '0xc3962e2eab7afaeb9cd11522381723afbafdc41dc7ba31bee472e187c4459e81' +}; +const name = app.name; + +export { + hashId, + id, + name, + source +}; diff --git a/js/src/dapps/chaindeploy/dapps/dappreg.js b/js/src/dapps/chaindeploy/dapps/dappreg.js new file mode 100644 index 000000000..a9baae82a --- /dev/null +++ b/js/src/dapps/chaindeploy/dapps/dappreg.js @@ -0,0 +1,33 @@ +// Copyright 2015-2017 Parity Technologies (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 . + +import builtins from '~/views/Dapps/builtin.json'; + +const id = 'dappreg'; +const app = builtins.find((app) => app.url === id); +const hashId = app.id; +const source = { + imageUrl: 'https://raw.githubusercontent.com/ethcore/dapp-assets/cdd6ac4f1e2f11619bed72a53ae71217dffe19ad/dapps/legos-64x64.png', + imageHash: '0xa8feea35c761cc6c2fe862fe336419f11ca5421f578757720a899b89fc1df154' +}; +const name = app.name; + +export { + hashId, + id, + name, + source +}; diff --git a/js/src/dapps/chaindeploy/dapps/gavcoin.js b/js/src/dapps/chaindeploy/dapps/gavcoin.js new file mode 100644 index 000000000..6fd8b1d86 --- /dev/null +++ b/js/src/dapps/chaindeploy/dapps/gavcoin.js @@ -0,0 +1,41 @@ +// Copyright 2015-2017 Parity Technologies (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 . + +import { api } from '../parity'; + +const isExternal = true; +const id = 'gavcoin'; +const hashId = api.util.sha3(id); +const source = { + imageUrl: 'https://raw.githubusercontent.com/ethcore/dapp-assets/9e135f76fe9ba61e2d8ccbd72ed144c26c450780/tokens/gavcoin-64x64.png', + imageHash: '0xd40679a3a234d8421c678d64f4df3308859e8ad07ac95ce4a228aceb96955287', + manifestUrl: 'https://raw.githubusercontent.com/gavofyork/gavcoin/eb2f8dc4d3ad4dd5f4562690525b7cfedc9681ba/manifest.json', + manifestHash: '0xd582c572fbef8015837f2c1a8798f2c3149a1d9d655b4020edb1bbece725371d', + contentUrl: { + repo: 'gavofyork/gavcoin', + commit: '0xeb2f8dc4d3ad4dd5f4562690525b7cfedc9681ba' + }, + contentHash: '0x0b6c7b3fc8dad3edb39fd1465904ce9a11938ef18f08f8115f275047ba249530' +}; +const name = 'GavCoin'; + +export { + hashId, + id, + isExternal, + name, + source +}; diff --git a/js/src/dapps/chaindeploy/dapps/githubhint.js b/js/src/dapps/chaindeploy/dapps/githubhint.js new file mode 100644 index 000000000..d723cb61c --- /dev/null +++ b/js/src/dapps/chaindeploy/dapps/githubhint.js @@ -0,0 +1,33 @@ +// Copyright 2015-2017 Parity Technologies (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 . + +import builtins from '~/views/Dapps/builtin.json'; + +const id = 'githubhint'; +const app = builtins.find((app) => app.url === id); +const hashId = app.id; +const source = { + imageUrl: 'https://raw.githubusercontent.com/ethcore/dapp-assets/b88e983abaa1a6a6345b8d9448c15b117ddb540e/dapps/link-64x64.jpg', + imageHash: '0x6568901e711886e2c61eef1bbc7e2d8d37a27b9eb3e9e270eda8548f2ec796e8' +}; +const name = app.name; + +export { + hashId, + id, + name, + source +}; diff --git a/js/src/dapps/chaindeploy/dapps/index.js b/js/src/dapps/chaindeploy/dapps/index.js new file mode 100644 index 000000000..e95bf5648 --- /dev/null +++ b/js/src/dapps/chaindeploy/dapps/index.js @@ -0,0 +1,50 @@ +// Copyright 2015-2017 Parity Technologies (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 . + +import * as consolejs from './console'; +import * as dappreg from './dappreg'; +import * as gavcoin from './gavcoin'; +import * as githubhint from './githubhint'; +import * as jgvoting from './jg-voting'; +import * as jgwhenblock from './jg-whenblock'; +import * as localtx from './localtx'; +import * as registry from './registry'; +import * as signaturereg from './signaturereg'; +import * as tokendeploy from './tokendeploy'; +import * as tokenreg from './tokenreg'; +import * as web from './web'; + +const apps = [ + // builtin + consolejs, + dappreg, + githubhint, + localtx, + registry, + signaturereg, + tokendeploy, + tokenreg, + web, + + // external + gavcoin, + jgvoting, + jgwhenblock +]; + +export { + apps +}; diff --git a/js/src/dapps/chaindeploy/dapps/jg-voting.js b/js/src/dapps/chaindeploy/dapps/jg-voting.js new file mode 100644 index 000000000..899e95894 --- /dev/null +++ b/js/src/dapps/chaindeploy/dapps/jg-voting.js @@ -0,0 +1,41 @@ +// Copyright 2015-2017 Parity Technologies (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 . + +import { api } from '../parity'; + +const isExternal = true; +const id = 'jg-voting'; +const hashId = api.util.sha3(id); +const source = { + imageUrl: 'https://raw.githubusercontent.com/jacogr/dapp-voting/038ff4074544f2babc7aed9c4ac3dc070b85b804/assets/images/vote.jpg', + imageHash: '0x3620828e1a745d2714e9f37dc2d47cdab5ef9982190a845b5e7665b7a7767661', + manifestUrl: 'https://raw.githubusercontent.com/jacogr/dapp-voting/682f0fe4b86508a1a2487de6c7c61f7b100ba5b2/manifest.json', + manifestHash: '0x9b83e01f87d225e7bfdd305c51319504ff9b4cf8d517ca4b64f606762e72f59e', + contentUrl: { + repo: 'jacogr/dapp-voting', + commit: '0x7d941597e862a600a60b9d6ecd3a6f606d96cd7b' + }, + contentHash: '0x9fcc0910f6a8c4e45715d41aea2d287da31bf1d7321003fc66df6a012ce2d753' +}; +const name = 'Yes, No, Maybe'; + +export { + hashId, + id, + isExternal, + name, + source +}; diff --git a/js/src/dapps/chaindeploy/dapps/jg-whenblock.js b/js/src/dapps/chaindeploy/dapps/jg-whenblock.js new file mode 100644 index 000000000..0005ca454 --- /dev/null +++ b/js/src/dapps/chaindeploy/dapps/jg-whenblock.js @@ -0,0 +1,39 @@ +// Copyright 2015-2017 Parity Technologies (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 . + +const isExternal = true; +const id = 'whenarewethere'; +const hashId = '0xfef3bfded03695e38a9ff476a0999e1fa421e72d1fb3b55a87d6c2bdb6fc18ef'; +const source = { + imageUrl: 'https://raw.githubusercontent.com/jacogr/dapp-when-are-we-there/167aa4d904c5aa6246d0d6d6f41c4ed8a56889cd/assets/images/clock.jpg', + imageHash: '0x2534b44f685b6399bf63f86679128216c43e9a58be1dfb58533923f0bcffeba7', + manifestUrl: 'https://raw.githubusercontent.com/jacogr/dapp-when-are-we-there/bf72dc3033711a3ab41bec3c1249638f70bae768/manifest.json', + manifestHash: '0xfe26f6a19ea9393d69bc5d8c73c5072ccf126f51c10c135b42d6bf162d774fd9', + contentUrl: { + repo: 'jacogr/dapp-when-are-we-there', + commit: '0xbf72dc3033711a3ab41bec3c1249638f70bae768' + }, + contentHash: '0x3505cbbef5c2243eedba07d340d4abccfaa3cfb799f51827e33c9721a5254d13' +}; +const name = 'When are we there'; + +export { + hashId, + id, + isExternal, + name, + source +}; diff --git a/js/src/dapps/chaindeploy/dapps/localtx.js b/js/src/dapps/chaindeploy/dapps/localtx.js new file mode 100644 index 000000000..e6dd59fbe --- /dev/null +++ b/js/src/dapps/chaindeploy/dapps/localtx.js @@ -0,0 +1,33 @@ +// Copyright 2015-2017 Parity Technologies (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 . + +import builtins from '~/views/Dapps/builtin.json'; + +const id = 'localtx'; +const app = builtins.find((app) => app.url === id); +const hashId = app.id; +const source = { + imageUrl: 'https://raw.githubusercontent.com/ethcore/dapp-assets/cdd6ac4f1e2f11619bed72a53ae71217dffe19ad/dapps/stack-64x64.png', + imageHash: '0x22b924801e1971659a51956dcdfc5a2d592d8bdd03780dd72d5bc4c84b595b4c' +}; +const name = app.name; + +export { + hashId, + id, + name, + source +}; diff --git a/js/src/dapps/chaindeploy/dapps/registry.js b/js/src/dapps/chaindeploy/dapps/registry.js new file mode 100644 index 000000000..d6addaaac --- /dev/null +++ b/js/src/dapps/chaindeploy/dapps/registry.js @@ -0,0 +1,33 @@ +// Copyright 2015-2017 Parity Technologies (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 . + +import builtins from '~/views/Dapps/builtin.json'; + +const id = 'registry'; +const app = builtins.find((app) => app.url === id); +const hashId = app.id; +const source = { + imageUrl: 'https://raw.githubusercontent.com/ethcore/dapp-assets/b88e983abaa1a6a6345b8d9448c15b117ddb540e/dapps/register-64x64.jpg', + imageHash: '0xf7100024052cd78b5e043287c05392b5db0bfce5caedd6d39555d40283ef0a1c' +}; +const name = app.name; + +export { + hashId, + id, + name, + source +}; diff --git a/js/src/dapps/chaindeploy/dapps/signaturereg.js b/js/src/dapps/chaindeploy/dapps/signaturereg.js new file mode 100644 index 000000000..3ce1442c3 --- /dev/null +++ b/js/src/dapps/chaindeploy/dapps/signaturereg.js @@ -0,0 +1,33 @@ +// Copyright 2015-2017 Parity Technologies (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 . + +import builtins from '~/views/Dapps/builtin.json'; + +const id = 'signaturereg'; +const app = builtins.find((app) => app.url === id); +const hashId = app.id; +const source = { + imageUrl: 'https://raw.githubusercontent.com/ethcore/dapp-assets/b88e983abaa1a6a6345b8d9448c15b117ddb540e/dapps/hex-64x64.jpg', + imageHash: '0x26f7f2415cd5cbbffa58e8119fdbdd7181cac79119dd7f6ba6ee99d7f4445640' +}; +const name = app.name; + +export { + hashId, + id, + name, + source +}; diff --git a/js/src/dapps/chaindeploy/dapps/tokendeploy.js b/js/src/dapps/chaindeploy/dapps/tokendeploy.js new file mode 100644 index 000000000..5f15bd903 --- /dev/null +++ b/js/src/dapps/chaindeploy/dapps/tokendeploy.js @@ -0,0 +1,33 @@ +// Copyright 2015-2017 Parity Technologies (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 . + +import builtins from '~/views/Dapps/builtin.json'; + +const id = 'tokendeploy'; +const app = builtins.find((app) => app.url === id); +const hashId = app.id; +const source = { + imageUrl: 'https://raw.githubusercontent.com/ethcore/dapp-assets/b88e983abaa1a6a6345b8d9448c15b117ddb540e/dapps/interlock-64x64.png', + imageHash: '0xde104baf02aec783e0bffc624514ee267dbcb455382375e3ffa715790c1c939f' +}; +const name = app.name; + +export { + hashId, + id, + name, + source +}; diff --git a/js/src/dapps/chaindeploy/dapps/tokenreg.js b/js/src/dapps/chaindeploy/dapps/tokenreg.js new file mode 100644 index 000000000..0e59f004e --- /dev/null +++ b/js/src/dapps/chaindeploy/dapps/tokenreg.js @@ -0,0 +1,33 @@ +// Copyright 2015-2017 Parity Technologies (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 . + +import builtins from '~/views/Dapps/builtin.json'; + +const id = 'tokenreg'; +const app = builtins.find((app) => app.url === id); +const hashId = app.id; +const source = { + imageUrl: 'https://raw.githubusercontent.com/ethcore/dapp-assets/b88e983abaa1a6a6345b8d9448c15b117ddb540e/dapps/coins-64x64.jpg', + imageHash: '0xe23d429d15de98c7878d92bc90b79c7afabe1b04c2ad5e3e2c89adc8f439edc9' +}; +const name = app.name; + +export { + hashId, + id, + name, + source +}; diff --git a/js/src/dapps/chaindeploy/dapps/web.js b/js/src/dapps/chaindeploy/dapps/web.js new file mode 100644 index 000000000..c8d45cb32 --- /dev/null +++ b/js/src/dapps/chaindeploy/dapps/web.js @@ -0,0 +1,33 @@ +// Copyright 2015-2017 Parity Technologies (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 . + +import builtins from '~/views/Dapps/builtin.json'; + +const id = 'web'; +const app = builtins.find((app) => app.url === id); +const hashId = app.id; +const source = { + imageUrl: 'https://raw.githubusercontent.com/ethcore/dapp-assets/ec6138115d0e1f45258969cd90b3b274e0ff2258/dapps/earth-64x64.jpg', + imageHash: '0x0b9b62a9262f75461191d4e8bf686c56528cbc0fe885c1f5878052ca8b2f65bf' +}; +const name = app.name; + +export { + hashId, + id, + name, + source +}; diff --git a/js/src/dapps/chaindeploy/parity.js b/js/src/dapps/chaindeploy/parity.js new file mode 100644 index 000000000..1dea0d696 --- /dev/null +++ b/js/src/dapps/chaindeploy/parity.js @@ -0,0 +1,21 @@ +// Copyright 2015-2017 Parity Technologies (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 . + +const api = window.parity.api; + +export { + api +}; diff --git a/js/src/dapps/chaindeploy/store.js b/js/src/dapps/chaindeploy/store.js new file mode 100644 index 000000000..07b693135 --- /dev/null +++ b/js/src/dapps/chaindeploy/store.js @@ -0,0 +1,714 @@ +// Copyright 2015-2017 Parity Technologies (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 . + +import { action, computed, observable } from 'mobx'; + +import { contracts as contractsInfo, registry as registryInfo } from './contracts'; +import { apps } from './dapps'; +import { api } from './parity'; +import { executeContract, isValidNumber, validateCode } from './utils'; + +export default class ContractsStore { + @observable apps = null; + @observable badges = null; + @observable contracts = null; + @observable error = null; + @observable registry = null; + + constructor () { + this.apps = apps; + this.badges = contractsInfo.filter((contract) => contract.isBadge); + this.contracts = contractsInfo.filter((contract) => !contract.isBadge); + this.registry = registryInfo; + + api.subscribe('eth_blockNumber', this.onNewBlockNumber); + } + + @computed get contractBadgereg () { + return this.contracts.find((contract) => contract.id === 'badgereg'); + } + + @computed get contractDappreg () { + return this.contracts.find((contract) => contract.id === 'dappreg'); + } + + @computed get contractGithubhint () { + return this.contracts.find((contract) => contract.id === 'githubhint'); + } + + @computed get contractTokenreg () { + return this.contracts.find((contract) => contract.id === 'tokenreg'); + } + + @computed get isBadgeDeploying () { + return this.badges + .filter((contract) => contract.isDeploying) + .length !== 0; + } + + @computed get isContractDeploying () { + return this.contracts + .filter((contract) => contract.isDeploying) + .length !== 0; + } + + @computed get isDappDeploying () { + return this.apps + .filter((app) => app.isDeploying) + .length !== 0; + } + + @computed get haveAllBadges () { + return this.badges + .filter((contract) => !contract.instance || !contract.hasLatestCode || !contract.badgeImageHash || !contract.badgeImageMatch || !contract.isBadgeRegistered) + .length === 0; + } + + @computed get haveAllContracts () { + return this.contracts + .filter((contract) => !contract.instance || !contract.hasLatestCode) + .length === 0; + } + + @computed get haveAllDapps () { + return this.apps + .filter((app) => { + return !app.isOnChain || + !app.imageHash || !app.imageMatch || + (app.source.contentHash && !app.contentMatch) || + (app.source.manifestHash && !app.manifestMatch); + }) + .length === 0; + } + + @action refreshApps = () => { + this.apps = [].concat(this.apps.peek()); + } + + @action refreshContracts = () => { + this.badges = [].concat(this.badges.peek()); + this.contracts = [].concat(this.contracts.peek()); + } + + @action setError = (error) => { + console.error(error); + + this.error = error.message + ? error.message + : error; + } + + @action setRegistryAddress = (address, isOnChain = false) => { + if (this.registry.address !== address || !this.registry.instance) { + console.log(`registry found at ${address}`); + + this.registry = Object.assign({}, this.registry, { + address, + instance: api.newContract(this.registry.abi, address).instance, + isOnChain + }); + } + } + + @action setRegistryCode (byteCode) { + this.registry.hasLatestCode = validateCode(this.registry.byteCode, byteCode); + } + + @action setRegistryDeploying = (isDeploying = false) => { + this.registry = Object.assign({}, this.registry, { + isDeploying, + status: isDeploying + ? 'Deploying contract' + : null + }); + } + + @action setBadgeId = (badge, badgeId) => { + badge.badgeId = badgeId; + badge.isBadgeRegistered = true; + + this.refreshContracts(); + } + + @action setBadgeImageHash = (badge, imageHash) => { + badge.badgeImageHash = imageHash; + badge.badgeImageMatch = badge.badgeSource.imageHash === imageHash; + + this.refreshContracts(); + } + + @action setContractAddress = (contract, address, isOnChain = false) => { + if (contract.address !== address || !contract.instance || contract.isOnChain !== isOnChain) { + console.log(`${contract.id} found at ${address}`); + + contract.address = address; + contract.instance = api.newContract(contract.abi, address).instance; + contract.isOnChain = isOnChain; + + this.refreshContracts(); + } + } + + @action setContractCode (contract, byteCode) { + contract.hasLatestCode = validateCode(contract.byteCode, byteCode); + + this.refreshContracts(); + } + + @action setContractDeploying = (contract, isDeploying = false) => { + contract.isDeploying = isDeploying; + contract.status = isDeploying + ? 'Deploying contract' + : null; + + this.refreshContracts(); + } + + @action setContractStatus = (contract, status) => { + contract.status = status; + + this.refreshContracts(); + } + + @action setAppDeploying = (app, isDeploying = false) => { + app.isDeploying = isDeploying; + app.status = isDeploying + ? 'Registering app' + : null; + + this.refreshApps(); + } + + @action setAppFound = (app, isOnChain = false) => { + if (app.isOnChain !== isOnChain) { + console.log(`${app.name} found on dappreg`); + + app.isOnChain = isOnChain; + + this.refreshApps(); + } + } + + @action setAppContentHash = (app, contentHash) => { + if (app.contentHash !== contentHash) { + console.log(`${app.name} has contentHash ${contentHash}`); + + app.contentHash = contentHash; + app.contentMatch = contentHash === app.source.contentHash; + + this.refreshApps(); + } + } + + @action setAppImageHash = (app, imageHash) => { + if (app.imageHash !== imageHash) { + console.log(`${app.name} has imageHash ${imageHash}`); + + app.imageHash = imageHash; + app.imageMatch = imageHash === app.source.imageHash; + + this.refreshApps(); + } + } + + @action setAppManifestHash = (app, manifestHash) => { + if (app.manifestHash !== manifestHash) { + console.log(`${app.name} has manifestHash ${manifestHash}`); + + app.manifestHash = manifestHash; + app.manifestMatch = manifestHash === app.source.manifestHash; + + this.refreshApps(); + } + } + + @action setAppStatus = (app, status) => { + console.log(app.id, status); + + app.status = status; + + this.refreshApps(); + } + + deployApp = (app) => { + console.log(`Registering application ${app.id}`); + + this.setAppDeploying(app, true); + + const options = {}; + const values = [app.hashId]; + + return api.parity + .defaultAccount() + .then((defaultAccount) => { + options.from = defaultAccount; + + if (app.isOnChain) { + return true; + } + + return this.contractDappreg.instance + .fee.call({}, []) + .then((fee) => { + options.value = fee; + + return executeContract(app.id, this.contractDappreg, 'register', options, values); + }); + }) + .then(() => { + if (app.imageHash && app.imageMatch) { + return true; + } + + this.setAppStatus(app, 'Registering image url'); + + return this + .registerHash(app.source.imageHash, app.source.imageUrl, options.from) + .then(() => this.setAppMeta(app, 'IMG', app.source.imageHash, options.from)); + }) + .then(() => { + if (!app.source.manifestHash || app.manifestMatch) { + return true; + } + + this.setAppStatus(app, 'Registering manifest url'); + + return this + .registerHash(app.source.manifestHash, app.source.manifestUrl, options.from) + .then(() => this.setAppMeta(app, 'MANIFEST', app.source.manifestHash, options.from)); + }) + .then(() => { + if (!app.source.contentHash || app.contentMatch) { + return true; + } + + this.setAppStatus(app, 'Registering content url'); + + return this + .registerRepo(app.source.contentHash, app.source.contentUrl, options.from) + .then(() => this.setAppMeta(app, 'CONTENT', app.source.contentHash, options.from)); + }) + .catch(() => { + return null; + }) + .then(() => { + this.setAppDeploying(app, false); + }); + } + + deployApps = () => { + this.apps + .filter((app) => { + return !app.isDeploying && + ( + !app.isOnChain || + (!app.imageHash || !app.imageMatch) || + (app.source.contentHash && !app.contentMatch) || + (app.source.manifestHash && !app.manifestMatch) + ); + }) + .forEach(this.deployApp); + } + + _deployContract = (contract) => { + console.log(`Deploying contract ${contract.id}`); + + const options = { + data: contract.byteCode + }; + + return api.parity + .defaultAccount() + .then((defaultAccount) => { + options.from = defaultAccount; + + return api + .newContract(contract.abi) + .deploy(options, contract.deployParams, (error, data) => { + if (error) { + console.error(contract.id, error); + } else { + console.log(contract.id, data); + } + }) + .then((contractAddress) => { + return [contractAddress, defaultAccount]; + }); + }); + } + + deployContract = (contract) => { + if (contract.hasLatestCode) { + return Promise.resolve(false); + } + + let defaultAccount = '0x0'; + + this.setContractDeploying(contract, true); + + return this + ._deployContract(contract) + .then(([address, _defaultAccount]) => { + const isOnChain = contract.isOnChain; + + defaultAccount = _defaultAccount; + + this.setContractAddress(contract, address); + + return isOnChain + ? true + : this.reserveAddress(contract, defaultAccount); + }) + .then(() => { + return this.registerAddress(contract, defaultAccount); + }) + .catch(() => { + return null; + }) + .then(() => { + this.setContractDeploying(contract, false); + }); + } + + deployBadge = (badge) => { + let defaultAccount; + + return this + .deployContract(badge) + .then(() => { + this.setContractDeploying(badge, true); + + return api.parity.defaultAccount(); + }) + .then((_defaultAccount) => { + defaultAccount = _defaultAccount; + + if (badge.isBadgeRegistered) { + return true; + } + + this.setContractStatus(badge, 'Registering with badgereg'); + + return this.registerBadge(badge, defaultAccount); + }) + .then(() => { + if (badge.badgeImageMatch) { + return true; + } + + this.setContractStatus(badge, 'Registering image url'); + + return this + .registerHash(badge.badgeSource.imageHash, badge.badgeSource.imageUrl, defaultAccount) + .then(() => this.registerBadgeImage(badge, badge.badgeSource.imageHash, defaultAccount)); + }) + .then(() => { + this.setContractDeploying(badge, false); + }); + } + + deployContracts = () => { + this.contracts + .filter((contract) => !contract.isDeploying && (!contract.instance || !contract.hasLatestCode)) + .forEach(this.deployContract); + } + + deployBadges = () => { + this.badges + .filter((contract) => !contract.isDeploying && (!contract.instance || !contract.hasLatestCode || !contract.badgeImageHash || !contract.badgeImageMatch || !contract.isBadgeRegistered)) + .forEach(this.deployBadge); + } + + deployRegistry = () => { + this.setRegistryDeploying(true); + + return this + ._deployContract(this.registry) + .then(([address]) => { + this.setRegistryDeploying(false); + this.setRegistryAddress(address); + }); + } + + registerBadge = (badge, fromAddress) => { + const options = { + from: fromAddress + }; + const values = [badge.address, api.util.sha3.text(badge.id.toLowerCase())]; + + return this.contractBadgereg.instance + .fee.call({}, []) + .then((fee) => { + options.value = fee; + + return executeContract(badge.id, this.contractBadgereg, 'register', options, values); + }); + } + + registerBadgeImage = (badge, hash, fromAddress) => { + const options = { + from: fromAddress + }; + const values = [badge.badgeId, 'IMG', hash]; + + this.setContractStatus(badge, 'Setting meta IMG'); + + return executeContract(badge.id, this.contractBadgereg, 'setMeta', options, values); + } + + setAppMeta = (app, key, meta, fromAddress) => { + const options = { + from: fromAddress + }; + const values = [app.hashId, key, meta]; + + this.setAppStatus(app, `Setting meta ${key}`); + + return executeContract(app.id, this.contractDappreg, 'setMeta', options, values); + } + + reserveAddress = (contract, fromAddress) => { + const options = { from: fromAddress }; + const values = [api.util.sha3.text(contract.id.toLowerCase())]; + + this.setContractStatus(contract, 'Reserving name'); + + return this.registry.instance + .fee.call({}, []) + .then((value) => { + options.value = value; + + return executeContract(contract.id, this.registry, 'reserve', options, values); + }); + } + + registerAddress = (contract, fromAddress) => { + const options = { from: fromAddress }; + const values = [api.util.sha3.text(contract.id.toLowerCase()), 'A', contract.address]; + + this.setContractStatus(contract, 'Setting lookup address'); + + return executeContract(contract.id, this.registry, 'setAddress', options, values); + } + + registerRepo = (hash, content, fromAddress) => { + const options = { + from: fromAddress + }; + const values = [hash, content.repo || content, content.commit || 0]; + + return this.contractGithubhint.instance + .entries.call({}, [hash]) + .then(([imageUrl, commit, owner]) => { + if (isValidNumber(owner)) { + return true; + } + + return executeContract(hash, this.contractGithubhint, 'hint', options, values); + }) + .catch(() => false); + } + + registerHash = (hash, url, fromAddress) => { + const options = { + from: fromAddress + }; + const values = [hash, url]; + + return this.contractGithubhint.instance + .entries.call({}, [hash]) + .then(([imageUrl, commit, owner]) => { + if (isValidNumber(owner)) { + return true; + } + + return executeContract(hash, this.contractGithubhint, 'hintURL', options, values); + }) + .catch(() => false); + } + + findRegistry = () => { + if (this.registry.address && this.registry.hasLatestCode) { + return Promise.resolve(this.registry); + } + + return api.parity + .registryAddress() + .then((address) => { + if (isValidNumber(address)) { + this.setRegistryAddress(address, true); + } + + return api.eth.getCode(address); + }) + .then((byteCode) => { + this.setRegistryCode(byteCode); + }); + } + + findApps = () => { + if (!this.contractDappreg.instance) { + return Promise.resolve(false); + } + + return Promise + .all( + this.apps.map((app) => { + return app.isOnChain + ? Promise.resolve([[0]]) + : this.contractDappreg.instance.get.call({}, [app.hashId]); + }) + ) + .then((apps) => { + apps.forEach(([_id, owner], index) => { + const id = api.util.bytesToHex(_id); + + if (isValidNumber(id)) { + this.setAppFound(this.apps[index], true); + } + }); + + return Promise.all( + this.apps.map((app) => { + return !app.isOnChain || (app.imageHash && app.imageMatch) + ? Promise.resolve([[0], [0], [0]]) + : Promise.all([ + this.contractDappreg.instance.meta.call({}, [app.hashId, 'CONTENT']), + this.contractDappreg.instance.meta.call({}, [app.hashId, 'IMG']), + this.contractDappreg.instance.meta.call({}, [app.hashId, 'MANIFEST']) + ]); + }) + ); + }) + .then((hashes) => { + hashes.forEach(([content, image, manifest], index) => { + const contentHash = api.util.bytesToHex(content); + const imageHash = api.util.bytesToHex(image); + const manifestHash = api.util.bytesToHex(manifest); + + if (isValidNumber(contentHash)) { + this.setAppContentHash(this.apps[index], contentHash); + } + + if (isValidNumber(imageHash)) { + this.setAppImageHash(this.apps[index], imageHash); + } + + if (isValidNumber(manifestHash)) { + this.setAppManifestHash(this.apps[index], manifestHash); + } + }); + }); + } + + findBadges = () => { + if (!this.contractBadgereg.instance) { + return Promise.resolve(false); + } + + return this + .findContracts(this.badges) + .then(() => { + return Promise.all( + this.badges.map((badge) => { + return badge.isBadgeRegistered + ? Promise.resolve([0, 0, 0]) + : this.contractBadgereg.instance.fromAddress.call({}, [badge.address]); + }) + ); + }) + .then((badgeInfos) => { + badgeInfos.forEach(([id, name, owner], index) => { + if (isValidNumber(owner)) { + this.setBadgeId(this.badges[index], id); + } + }); + + return Promise + .all( + this.badges.map((badge) => { + return !badge.isBadgeRegistered + ? Promise.resolve([0]) + : this.contractBadgereg.instance.meta.call({}, [badge.badgeId, 'IMG']); + }) + ); + }) + .then((images) => { + images.forEach((imageBytes, index) => { + const imageHash = api.util.bytesToHex(imageBytes); + + if (isValidNumber(imageHash)) { + this.setBadgeImageHash(this.badges[index], imageHash); + } + }); + }); + } + + findContracts = (contracts = this.contracts) => { + if (!this.registry.instance) { + return Promise.resolve(false); + } + + return Promise + .all( + contracts.map((contract) => { + const hashId = api.util.sha3.text(contract.id.toLowerCase()); + + return contract.isOnChain + ? Promise.resolve([0, 0]) + : Promise.all([ + this.registry.instance.getAddress.call({}, [hashId, 'A']), + this.registry.instance.getOwner.call({}, [hashId]) + ]); + }) + ) + .then((addresses) => { + addresses.forEach(([address, owner], index) => { + if (isValidNumber(owner) && isValidNumber(address)) { + this.setContractAddress(contracts[index], address, true); + } + }); + + return Promise.all( + contracts.map((contract) => { + return !contract.address || contract.hasLatestCode + ? Promise.resolve(null) + : api.eth.getCode(contract.address); + }) + ); + }) + .then((codes) => { + codes.forEach((byteCode, index) => { + if (byteCode) { + this.setContractCode(contracts[index], byteCode); + } + }); + }); + } + + onNewBlockNumber = (error, blockNumber) => { + if (error) { + return; + } + + return this + .findRegistry() + .then(this.findContracts) + .then(this.findApps) + .then(this.findBadges) + .catch(this.setError); + } +} diff --git a/js/src/dapps/chaindeploy/utils.js b/js/src/dapps/chaindeploy/utils.js new file mode 100644 index 000000000..87e7279e3 --- /dev/null +++ b/js/src/dapps/chaindeploy/utils.js @@ -0,0 +1,82 @@ +// Copyright 2015-2017 Parity Technologies (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 . + +import BigNumber from 'bignumber.js'; + +import { api } from './parity'; + +export function validateCode (source, retrieved) { + const original = source.substr(12); + const bytecode = retrieved.substr(12); + + const knownHash = api.util.sha3(original.slice(-1 * bytecode.length)); + const codeHash = api.util.sha3(bytecode); + + return knownHash === codeHash; +} + +export function isValidNumber (number) { + return number && !(new BigNumber(number)).isZero(); +} + +export function executeContract (logId, contract, funcName, options, values) { + const func = contract.instance[funcName]; + + return func + .estimateGas(options, values) + .then((gasEst) => { + options.gas = gasEst.mul(1.2); + + return trackRequest( + func.postTransaction(options, values), + (error, data) => { + if (error) { + console.error(logId, error); + } else { + console.log(logId, data); + } + } + ); + }); +} + +export function trackRequest (promise, callback) { + return promise + .then((requestId) => { + callback(null, { state: 'checkRequest', requestId }); + + return api.pollMethod('parity_checkRequest', requestId); + }) + .then((txHash) => { + callback(null, { state: 'getTransactionReceipt', txHash }); + + return api.pollMethod('eth_getTransactionReceipt', txHash, (receipt) => { + if (!receipt || !receipt.blockNumber || receipt.blockNumber.eq(0)) { + return false; + } + + return true; + }); + }) + .then((receipt) => { + callback(null, { state: 'hasReceipt', receipt }); + }) + .catch((error) => { + callback(error); + + throw error; + }); +} diff --git a/js/src/dapps/dappreg/dappsStore.js b/js/src/dapps/dappreg/dappsStore.js index ea2e6f054..c6f45922a 100644 --- a/js/src/dapps/dappreg/dappsStore.js +++ b/js/src/dapps/dappreg/dappsStore.js @@ -20,12 +20,15 @@ import { flatten } from 'lodash'; import * as abis from '~/contracts/abi'; import Contracts from '~/contracts'; -import builtins from '~/views/Dapps/builtin.json'; +import builtinJson from '~/views/Dapps/builtin.json'; + import Dapp from './dappStore.js'; import { deleteDapp, registerDapp, updateDapp } from './utils'; import { api, trackRequest } from './parity'; +const builtins = builtinJson.filter((app) => app.id); + let instance = null; export default class DappsStore { diff --git a/js/src/util/dapps.js b/js/src/util/dapps.js index a82b2ae1c..2ca416e1a 100644 --- a/js/src/util/dapps.js +++ b/js/src/util/dapps.js @@ -21,7 +21,9 @@ import Contracts from '~/contracts'; import { hashToImageUrl } from '~/redux/util'; import { bytesToHex } from '~/api/util/format'; -import builtinApps from '~/views/Dapps/builtin.json'; +import builtinJson from '~/views/Dapps/builtin.json'; + +const builtinApps = builtinJson.filter((app) => app.id); function getHost (api) { const host = process.env.DAPPS_URL || diff --git a/js/src/views/Dapps/builtin.json b/js/src/views/Dapps/builtin.json index 45dccb327..97ebcc0cc 100644 --- a/js/src/views/Dapps/builtin.json +++ b/js/src/views/Dapps/builtin.json @@ -1,4 +1,12 @@ [ + { + "url": "chaindeploy", + "name": "Chain Deployment", + "description": "Deploy all basic contracts, names & applications to the network", + "author": "Parity Team ", + "version": "1.0.0", + "visible": false + }, { "id": "0xf9f2d620c2e08f83e45555247146c62185e4ab7cf82a4b9002a265a0d020348f", "url": "tokendeploy", From b7862ac23a021f0f10a7e8212450d1cddd243d51 Mon Sep 17 00:00:00 2001 From: Jaco Greeff Date: Mon, 13 Mar 2017 12:52:02 +0100 Subject: [PATCH 42/71] Update parity-ui-precompiled with branch (#4850) * Update parity-ui-precompiled with branch * In-place sed via -i * Explicitly specify branch * Only in-place edit branch (thanks @ngotchac) * Add override & single-line comment --- dapps/ui/Cargo.toml | 3 ++- js/scripts/release.sh | 2 ++ 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/dapps/ui/Cargo.toml b/dapps/ui/Cargo.toml index 2ab128ad5..17fc2d448 100644 --- a/dapps/ui/Cargo.toml +++ b/dapps/ui/Cargo.toml @@ -11,7 +11,8 @@ rustc_version = "0.1" [dependencies] parity-ui-dev = { path = "../../js", optional = true } -parity-ui-precompiled = { git = "https://github.com/ethcore/js-precompiled.git", optional = true } +# This is managed by the js/scripts/release.sh script on CI - keep it in a single line +parity-ui-precompiled = { git = "https://github.com/ethcore/js-precompiled.git", optional = true, branch = "master" } [features] no-precompiled-js = ["parity-ui-dev"] diff --git a/js/scripts/release.sh b/js/scripts/release.sh index 80c0fc819..be19e217e 100755 --- a/js/scripts/release.sh +++ b/js/scripts/release.sh @@ -89,11 +89,13 @@ fi echo "*** Updating cargo parity-ui-precompiled#$PRECOMPILED_HASH" git submodule update +sed -i "/^parity-ui-precompiled/ { s/branch = \".*\"/branch = \"$BRANCH\"/g; }" dapps/ui/Cargo.toml cargo update -p parity-ui-precompiled # --precise "$PRECOMPILED_HASH" echo "*** Committing updated files" git add js +git add dapps/ui/Cargo.toml git add Cargo.lock git commit -m "[ci skip] js-precompiled $UTCDATE" git push origin HEAD:refs/heads/$BRANCH 2>$GITLOG From fddbc9e5cb5fe9c1d8e161c91828b2a2ff6fd337 Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Mon, 13 Mar 2017 14:54:56 +0300 Subject: [PATCH 43/71] Secretstore DKG protocol draft + distributed encryption/decryption tests (#4725) * ECDKG protocol prototype * added test for enc/dec math * get rid of decryption_session * added licenses * fix after merge * get rid of unused serde dependency * doc * decryption session [without commutative enc] * failed_dec_session * fixed tests * added commen * added more decryption session tests * helper to localize an issue * more computations to localize error * decryption_session::SessionParams * added tests for EC math to localize problem --- ethkey/src/error.rs | 6 + ethkey/src/math.rs | 43 + ethkey/src/secret.rs | 51 + .../src/key_server_cluster/cluster.rs | 90 ++ .../key_server_cluster/decryption_session.rs | 707 ++++++++++ .../key_server_cluster/encryption_session.rs | 1197 +++++++++++++++++ secret_store/src/key_server_cluster/math.rs | 338 +++++ .../src/key_server_cluster/message.rs | 168 +++ secret_store/src/key_server_cluster/mod.rs | 76 ++ secret_store/src/lib.rs | 1 + 10 files changed, 2677 insertions(+) create mode 100644 secret_store/src/key_server_cluster/cluster.rs create mode 100644 secret_store/src/key_server_cluster/decryption_session.rs create mode 100644 secret_store/src/key_server_cluster/encryption_session.rs create mode 100644 secret_store/src/key_server_cluster/math.rs create mode 100644 secret_store/src/key_server_cluster/message.rs create mode 100644 secret_store/src/key_server_cluster/mod.rs diff --git a/ethkey/src/error.rs b/ethkey/src/error.rs index bc5dd9fa4..0ac2d221a 100644 --- a/ethkey/src/error.rs +++ b/ethkey/src/error.rs @@ -51,6 +51,12 @@ impl fmt::Display for Error { } } +impl Into for Error { + fn into(self) -> String { + format!("{}", self) + } +} + impl From<::secp256k1::Error> for Error { fn from(e: ::secp256k1::Error) -> Error { match e { diff --git a/ethkey/src/math.rs b/ethkey/src/math.rs index 45e5d04e6..536f4ee7d 100644 --- a/ethkey/src/math.rs +++ b/ethkey/src/math.rs @@ -36,6 +36,17 @@ pub fn public_add(public: &mut Public, other: &Public) -> Result<(), Error> { Ok(()) } +/// Inplace sub one public key from another (EC point - EC point) +pub fn public_sub(public: &mut Public, other: &Public) -> Result<(), Error> { + let mut key_neg_other = to_secp256k1_public(other)?; + key_neg_other.mul_assign(&SECP256K1, &key::MINUS_ONE_KEY)?; + + let mut key_public = to_secp256k1_public(public)?; + key_public.add_assign(&SECP256K1, &key_neg_other)?; + set_public(public, &key_public); + Ok(()) +} + /// Return base point of secp256k1 pub fn generation_point() -> Public { let mut public_sec_raw = [0u8; 65]; @@ -64,3 +75,35 @@ fn set_public(public: &mut Public, key_public: &key::PublicKey) { let key_public_serialized = key_public.serialize_vec(&SECP256K1, false); public.copy_from_slice(&key_public_serialized[1..65]); } + +#[cfg(test)] +mod tests { + use super::super::{Random, Generator}; + use super::{public_add, public_sub}; + + #[test] + fn public_addition_is_commutative() { + let public1 = Random.generate().unwrap().public().clone(); + let public2 = Random.generate().unwrap().public().clone(); + + let mut left = public1.clone(); + public_add(&mut left, &public2).unwrap(); + + let mut right = public2.clone(); + public_add(&mut right, &public1).unwrap(); + + assert_eq!(left, right); + } + + #[test] + fn public_addition_is_reversible_with_subtraction() { + let public1 = Random.generate().unwrap().public().clone(); + let public2 = Random.generate().unwrap().public().clone(); + + let mut sum = public1.clone(); + public_add(&mut sum, &public2).unwrap(); + public_sub(&mut sum, &public2).unwrap(); + + assert_eq!(sum, public1); + } +} diff --git a/ethkey/src/secret.rs b/ethkey/src/secret.rs index d8696ef73..9c9fd05ad 100644 --- a/ethkey/src/secret.rs +++ b/ethkey/src/secret.rs @@ -130,3 +130,54 @@ impl Deref for Secret { &self.inner } } + +#[cfg(test)] +mod tests { + use std::str::FromStr; + use super::super::{Random, Generator}; + use super::Secret; + + #[test] + fn multiplicating_secret_inversion_with_secret_gives_one() { + let secret = Random.generate().unwrap().secret().clone(); + let mut inversion = secret.clone(); + inversion.inv().unwrap(); + inversion.mul(&secret).unwrap(); + assert_eq!(inversion, Secret::from_str("0000000000000000000000000000000000000000000000000000000000000001").unwrap()); + } + + #[test] + fn secret_inversion_is_reversible_with_inversion() { + let secret = Random.generate().unwrap().secret().clone(); + let mut inversion = secret.clone(); + inversion.inv().unwrap(); + inversion.inv().unwrap(); + assert_eq!(inversion, secret); + } + + #[test] + fn secret_pow() { + let secret = Random.generate().unwrap().secret().clone(); + + let mut pow0 = secret.clone(); + pow0.pow(0).unwrap(); + assert_eq!(pow0, Secret::from_str("0000000000000000000000000000000000000000000000000000000000000001").unwrap()); + + let mut pow1 = secret.clone(); + pow1.pow(1).unwrap(); + assert_eq!(pow1, secret); + + let mut pow2 = secret.clone(); + pow2.pow(2).unwrap(); + let mut pow2_expected = secret.clone(); + pow2_expected.mul(&secret).unwrap(); + assert_eq!(pow2, pow2_expected); + + let mut pow3 = secret.clone(); + pow3.pow(3).unwrap(); + let mut pow3_expected = secret.clone(); + pow3_expected.mul(&secret).unwrap(); + pow3_expected.mul(&secret).unwrap(); + assert_eq!(pow3, pow3_expected); + } +} diff --git a/secret_store/src/key_server_cluster/cluster.rs b/secret_store/src/key_server_cluster/cluster.rs new file mode 100644 index 000000000..5f6c99808 --- /dev/null +++ b/secret_store/src/key_server_cluster/cluster.rs @@ -0,0 +1,90 @@ +// Copyright 2015-2017 Parity Technologies (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 . + +use key_server_cluster::{Error, NodeId}; +use key_server_cluster::message::Message; + +/// Cluster access for single encryption/decryption participant. +pub trait Cluster { + /// Broadcast message to all other nodes. + fn broadcast(&self, message: Message) -> Result<(), Error>; + /// Send message to given node. + fn send(&self, to: &NodeId, message: Message) -> Result<(), Error>; + /// Blacklist node, close connection and remove all pending messages. + fn blacklist(&self, node: &NodeId); +} + +#[cfg(test)] +pub mod tests { + use std::collections::VecDeque; + use parking_lot::Mutex; + use key_server_cluster::{NodeId, Error}; + use key_server_cluster::message::Message; + use key_server_cluster::cluster::Cluster; + + #[derive(Debug)] + pub struct DummyCluster { + id: NodeId, + data: Mutex, + } + + #[derive(Debug, Default)] + struct DummyClusterData { + nodes: Vec, + messages: VecDeque<(NodeId, Message)>, + } + + impl DummyCluster { + pub fn new(id: NodeId) -> Self { + DummyCluster { + id: id, + data: Mutex::new(DummyClusterData::default()) + } + } + + pub fn node(&self) -> NodeId { + self.id.clone() + } + + pub fn add_node(&self, node: NodeId) { + self.data.lock().nodes.push(node); + } + + pub fn take_message(&self) -> Option<(NodeId, Message)> { + self.data.lock().messages.pop_front() + } + } + + impl Cluster for DummyCluster { + fn broadcast(&self, message: Message) -> Result<(), Error> { + let mut data = self.data.lock(); + let all_nodes: Vec<_> = data.nodes.iter().cloned().filter(|n| n != &self.id).collect(); + for node in all_nodes { + data.messages.push_back((node, message.clone())); + } + Ok(()) + } + + fn send(&self, to: &NodeId, message: Message) -> Result<(), Error> { + debug_assert!(&self.id != to); + self.data.lock().messages.push_back((to.clone(), message)); + Ok(()) + } + + fn blacklist(&self, _node: &NodeId) { + } + } +} diff --git a/secret_store/src/key_server_cluster/decryption_session.rs b/secret_store/src/key_server_cluster/decryption_session.rs new file mode 100644 index 000000000..d4160851e --- /dev/null +++ b/secret_store/src/key_server_cluster/decryption_session.rs @@ -0,0 +1,707 @@ +// Copyright 2015-2017 Parity Technologies (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 . + +use std::collections::{BTreeSet, BTreeMap}; +use std::sync::Arc; +use parking_lot::Mutex; +use ethkey::{self, Secret, Public, Signature}; +use key_server_cluster::{Error, AclStorage, EncryptedData, NodeId, SessionId}; +use key_server_cluster::cluster::Cluster; +use key_server_cluster::math; +use key_server_cluster::message::{Message, InitializeDecryptionSession, ConfirmDecryptionInitialization, + RequestPartialDecryption, PartialDecryption}; + +/// Distributed decryption session. +/// Based on "ECDKG: A Distributed Key Generation Protocol Based on Elliptic Curve Discrete Logarithm" paper: +/// http://citeseerx.ist.psu.edu/viewdoc/download?doi=10.1.1.124.4128&rep=rep1&type=pdf +/// Brief overview: +/// 1) initialization: master node (which has received request for decrypting the secret) requests all other nodes to decrypt the secret +/// 2) ACL check: all nodes which have received the request are querying ACL-contract to check if requestor has access to the document +/// 3) partial decryption: every node which has succussfully checked access for the requestor do a partial decryption +/// 4) decryption: master node receives all partial decryptions of the secret and restores the secret +pub struct Session { + /// Encryption session id. + id: SessionId, + /// Decryption session access key. + access_key: Secret, + /// Public identifier of this node. + self_node_id: NodeId, + /// Encrypted data. + encrypted_data: EncryptedData, + /// ACL storate to check access to the resource. + acl_storage: Arc, + /// Cluster which allows this node to send messages to other nodes in the cluster. + cluster: Arc, + /// Mutable session data. + data: Mutex, +} + +/// Session creation parameters +pub struct SessionParams { + /// Session identifier. + pub id: SessionId, + /// Session access key. + pub access_key: Secret, + /// Id of node, on which this session is running. + pub self_node_id: Public, + /// Encrypted data (result of running encryption_session::Session). + pub encrypted_data: EncryptedData, + /// ACL storage. + pub acl_storage: Arc, + /// Cluster + pub cluster: Arc, +} + +#[derive(Debug)] +/// Mutable data of encryption (distributed key generation) session. +struct SessionData { + /// Current state of the session. + state: SessionState, + + // === Values, filled when session initialization just starts === + /// Reference to the node, which has started this session. + master: Option, + /// Public key of requestor. + requestor: Option, + + // === Values, filled during session initialization === + /// Nodes, which have been requested for decryption initialization. + requested_nodes: BTreeSet, + /// Nodes, which have responded with reject to initialization request. + rejected_nodes: BTreeSet, + /// Nodes, which have responded with confirm to initialization request. + confirmed_nodes: BTreeSet, + + // === Values, filled during partial decryption === + /// Shadow points, received from nodes as a response to partial decryption request. + shadow_points: BTreeMap, + + /// === Values, filled during final decryption === + /// Decrypted secret + decrypted_secret: Option, +} + +#[derive(Debug)] +struct NodeData { + /// Node-generated shadow point. + shadow_point: Option, +} + +#[derive(Debug, Clone, PartialEq)] +pub enum SessionState { + /// Every node starts in this state. + WaitingForInitialization, + /// Master node waits for other nodes to confirm decryption. + WaitingForInitializationConfirm, + /// Waiting for partial decrypion request. + WaitingForPartialDecryptionRequest, + /// Waiting for partial decryption responses. + WaitingForPartialDecryption, + /// Decryption session is finished for this node. + Finished, + /// Decryption session is failed for this node. + Failed, +} + +impl Session { + /// Create new decryption session. + pub fn new(params: SessionParams) -> Result { + check_encrypted_data(¶ms.self_node_id, ¶ms.encrypted_data)?; + + Ok(Session { + id: params.id, + access_key: params.access_key, + self_node_id: params.self_node_id, + encrypted_data: params.encrypted_data, + acl_storage: params.acl_storage, + cluster: params.cluster, + data: Mutex::new(SessionData { + state: SessionState::WaitingForInitialization, + master: None, + requestor: None, + requested_nodes: BTreeSet::new(), + rejected_nodes: BTreeSet::new(), + confirmed_nodes: BTreeSet::new(), + shadow_points: BTreeMap::new(), + decrypted_secret: None, + }) + }) + } + + /// Get this node Id. + pub fn node(&self) -> &NodeId { + &self.self_node_id + } + + /// Get this session access key. + pub fn access_key(&self) -> &Secret { + &self.access_key + } + + /// Get current session state. + pub fn state(&self) -> SessionState { + self.data.lock().state.clone() + } + + /// Get decrypted secret + pub fn decrypted_secret(&self) -> Option { + self.data.lock().decrypted_secret.clone() + } + + /// Initialize decryption session. + pub fn initialize(&self, requestor_signature: Signature) -> Result<(), Error> { + let mut data = self.data.lock(); + + // check state + if data.state != SessionState::WaitingForInitialization { + return Err(Error::InvalidStateForRequest); + } + + // recover requestor signature + let requestor_public = ethkey::recover(&requestor_signature, &self.id)?; + + // update state + data.master = Some(self.node().clone()); + data.state = SessionState::WaitingForInitializationConfirm; + data.requestor = Some(requestor_public.clone()); + data.requested_nodes.extend(self.encrypted_data.id_numbers.keys().cloned()); + + // ..and finally check access on our's own + let is_requestor_allowed_to_read = self.acl_storage.check(&requestor_public, &self.id).unwrap_or(false); + process_initialization_response(&self.encrypted_data, &mut *data, self.node(), is_requestor_allowed_to_read)?; + + // check if we have enough nodes to decrypt data + match data.state { + // not enough nodes => pass initialization message to all other nodes + SessionState::WaitingForInitializationConfirm => { + for node in self.encrypted_data.id_numbers.keys().filter(|n| *n != self.node()) { + self.cluster.send(node, Message::InitializeDecryptionSession(InitializeDecryptionSession { + session: self.id.clone(), + sub_session: self.access_key.clone(), + requestor_signature: requestor_signature.clone(), + }))?; + } + }, + // we can decrypt data on our own + SessionState::WaitingForPartialDecryption => unimplemented!(), + // we can not decrypt data + SessionState::Failed => (), + // cannot reach other states + _ => unreachable!("process_initialization_response can change state to WaitingForPartialDecryption or Failed; checked that we are in WaitingForInitializationConfirm state above; qed"), + } + + Ok(()) + } + + /// When session initialization message is received. + pub fn on_initialize_session(&self, sender: NodeId, message: InitializeDecryptionSession) -> Result<(), Error> { + debug_assert!(self.id == message.session); + debug_assert!(self.access_key == message.sub_session); + debug_assert!(&sender != self.node()); + + let mut data = self.data.lock(); + + // check state + if data.state != SessionState::WaitingForInitialization { + return Err(Error::InvalidStateForRequest); + } + + // recover requestor signature + let requestor_public = ethkey::recover(&message.requestor_signature, &self.id)?; + + // check access + let is_requestor_allowed_to_read = self.acl_storage.check(&requestor_public, &self.id).unwrap_or(false); + data.state = if is_requestor_allowed_to_read { SessionState::WaitingForPartialDecryptionRequest } + else { SessionState::Failed }; + data.requestor = Some(requestor_public); + + // respond to master node + data.master = Some(sender.clone()); + self.cluster.send(&sender, Message::ConfirmDecryptionInitialization(ConfirmDecryptionInitialization { + session: self.id.clone(), + sub_session: self.access_key.clone(), + is_confirmed: is_requestor_allowed_to_read, + })) + } + + /// When session initialization confirmation message is reeived. + pub fn on_confirm_initialization(&self, sender: NodeId, message: ConfirmDecryptionInitialization) -> Result<(), Error> { + debug_assert!(self.id == message.session); + debug_assert!(self.access_key == message.sub_session); + debug_assert!(&sender != self.node()); + + let mut data = self.data.lock(); + + // check state + if data.state != SessionState::WaitingForInitializationConfirm { + // if there were enough confirmations/rejections before this message + // we have already moved to the next state + return Ok(()); + } + + // update state + process_initialization_response(&self.encrypted_data, &mut *data, &sender, message.is_confirmed)?; + + // check if we have enough nodes to decrypt data + match data.state { + // we do not yet have enough nodes for decryption + SessionState::WaitingForInitializationConfirm => Ok(()), + // we have enough nodes for decryption + SessionState::WaitingForPartialDecryption => { + let confirmed_nodes: BTreeSet<_> = data.confirmed_nodes.clone(); + for node in data.confirmed_nodes.iter().filter(|n| n != &self.node()) { + self.cluster.send(node, Message::RequestPartialDecryption(RequestPartialDecryption { + session: self.id.clone(), + sub_session: self.access_key.clone(), + nodes: confirmed_nodes.clone(), + }))?; + } + + assert!(data.confirmed_nodes.remove(self.node())); + + let shadow_point = { + let requestor = data.requestor.as_ref().expect("requestor public is filled during initialization; WaitingForPartialDecryption follows initialization; qed"); + do_partial_decryption(self.node(), &requestor, &data.confirmed_nodes, &self.access_key, &self.encrypted_data)? + }; + data.shadow_points.insert(self.node().clone(), shadow_point); + + Ok(()) + }, + // we can not have enough nodes for decryption + SessionState::Failed => Ok(()), + // cannot reach other states + _ => unreachable!("process_initialization_response can change state to WaitingForPartialDecryption or Failed; checked that we are in WaitingForInitializationConfirm state above; qed"), + } + } + + /// When partial decryption is requested. + pub fn on_partial_decryption_requested(&self, sender: NodeId, message: RequestPartialDecryption) -> Result<(), Error> { + debug_assert!(self.id == message.session); + debug_assert!(self.access_key == message.sub_session); + debug_assert!(&sender != self.node()); + + // check message + if message.nodes.len() != self.encrypted_data.threshold + 1 { + return Err(Error::InvalidMessage); + } + + let mut data = self.data.lock(); + + // check state + if data.master != Some(sender) { + return Err(Error::InvalidMessage); + } + if data.state != SessionState::WaitingForPartialDecryptionRequest { + return Err(Error::InvalidStateForRequest); + } + + // calculate shadow point + let shadow_point = { + let requestor = data.requestor.as_ref().expect("requestor public is filled during initialization; WaitingForPartialDecryptionRequest follows initialization; qed"); + do_partial_decryption(self.node(), &requestor, &message.nodes, &self.access_key, &self.encrypted_data)? + }; + self.cluster.send(&sender, Message::PartialDecryption(PartialDecryption { + session: self.id.clone(), + sub_session: self.access_key.clone(), + shadow_point: shadow_point, + }))?; + + // update sate + data.state = SessionState::Finished; + + Ok(()) + } + + /// When partial decryption is received. + pub fn on_partial_decryption(&self, sender: NodeId, message: PartialDecryption) -> Result<(), Error> { + debug_assert!(self.id == message.session); + debug_assert!(self.access_key == message.sub_session); + debug_assert!(&sender != self.node()); + + let mut data = self.data.lock(); + + // check state + if data.state != SessionState::WaitingForPartialDecryption { + return Err(Error::InvalidStateForRequest); + } + + if !data.confirmed_nodes.remove(&sender) { + return Err(Error::InvalidStateForRequest); + } + data.shadow_points.insert(sender, message.shadow_point); + + // check if we have enough shadow points to decrypt the secret + if data.shadow_points.len() != self.encrypted_data.threshold + 1 { + return Ok(()); + } + + // decrypt the secret using shadow points + let joint_shadow_point = math::compute_joint_shadow_point(data.shadow_points.values())?; + let decrypted_secret = math::decrypt_with_joint_shadow(&self.access_key, &self.encrypted_data.encrypted_point, &joint_shadow_point)?; + data.decrypted_secret = Some(decrypted_secret); + data.state = SessionState::Finished; + + Ok(()) + } +} + +fn check_encrypted_data(self_node_id: &Public, encrypted_data: &EncryptedData) -> Result<(), Error> { + use key_server_cluster::encryption_session::{check_cluster_nodes, check_threshold}; + + let nodes = encrypted_data.id_numbers.keys().cloned().collect(); + check_cluster_nodes(self_node_id, &nodes)?; + check_threshold(encrypted_data.threshold, &nodes)?; + + Ok(()) +} + +fn process_initialization_response(encrypted_data: &EncryptedData, data: &mut SessionData, node: &NodeId, check_result: bool) -> Result<(), Error> { + if !data.requested_nodes.remove(node) { + return Err(Error::InvalidMessage); + } + + match check_result { + true => { + data.confirmed_nodes.insert(node.clone()); + + // check if we have enough nodes to do a decryption? + if data.confirmed_nodes.len() == encrypted_data.threshold + 1 { + data.state = SessionState::WaitingForPartialDecryption; + } + }, + false => { + data.rejected_nodes.insert(node.clone()); + + // check if we still can receive enough confirmations to do a decryption? + if encrypted_data.id_numbers.len() - data.rejected_nodes.len() < encrypted_data.threshold + 1 { + data.state = SessionState::Failed; + } + }, + } + + Ok(()) +} + +fn do_partial_decryption(node: &NodeId, _requestor_public: &Public, participants: &BTreeSet, access_key: &Secret, encrypted_data: &EncryptedData) -> Result { + let node_id_number = &encrypted_data.id_numbers[node]; + let node_secret_share = &encrypted_data.secret_share; + let other_id_numbers = participants.iter() + .filter(|id| *id != node) + .map(|id| &encrypted_data.id_numbers[id]); + // TODO: commutative encryption using _requestor_public + let node_shadow = math::compute_node_shadow(node_id_number, node_secret_share, other_id_numbers)?; + math::compute_node_shadow_point(access_key, &encrypted_data.common_point, &node_shadow) +} + +#[cfg(test)] +mod tests { + use std::sync::Arc; + use std::str::FromStr; + use std::collections::BTreeMap; + use super::super::super::acl_storage::DummyAclStorage; + use ethkey::{self, Random, Generator, Public, Secret}; + use key_server_cluster::{NodeId, EncryptedData, SessionId, Error}; + use key_server_cluster::cluster::tests::DummyCluster; + use key_server_cluster::decryption_session::{Session, SessionParams, SessionState}; + use key_server_cluster::message::{self, Message}; + + const SECRET_PLAIN: &'static str = "d2b57ae7619e070af0af6bc8c703c0cd27814c54d5d6a999cacac0da34ede279ca0d9216e85991029e54e2f0c92ee0bd30237725fa765cbdbfc4529489864c5f"; + + fn prepare_decryption_sessions() -> (Vec>, Vec>, Vec) { + // prepare encrypted data + cluster configuration for scheme 4-of-5 + let session_id = SessionId::default(); + let access_key = Random.generate().unwrap().secret().clone(); + let secret_shares = vec![ + Secret::from_str("834cb736f02d9c968dfaf0c37658a1d86ff140554fc8b59c9fdad5a8cf810eec").unwrap(), + Secret::from_str("5a3c1d90fafafa66bb808bcc464354a98b05e6b2c95b5f609d4511cdd1b17a0b").unwrap(), + Secret::from_str("71bf61e7848e08e3a8486c308ce521bdacfebcf9116a0151447eb301f3a2d0e9").unwrap(), + Secret::from_str("80c0e5e2bea66fa9b2e07f7ce09630a9563e8242446d5ee63221feb09c4338f4").unwrap(), + Secret::from_str("c06546b5669877ba579ca437a5602e89425c53808c708d44ccd6afcaa4610fad").unwrap(), + ]; + let id_numbers: Vec<(NodeId, Secret)> = vec![ + ("b486d3840218837b035c66196ecb15e6b067ca20101e11bd5e626288ab6806ecc70b8307012626bd512bad1559112d11d21025cef48cc7a1d2f3976da08f36c8".into(), + Secret::from_str("281b6bf43cb86d0dc7b98e1b7def4a80f3ce16d28d2308f934f116767306f06c").unwrap()), + ("1395568277679f7f583ab7c0992da35f26cde57149ee70e524e49bdae62db3e18eb96122501e7cbb798b784395d7bb5a499edead0706638ad056d886e56cf8fb".into(), + Secret::from_str("00125d85a05e5e63e214cb60fe63f132eec8a103aa29266b7e6e6c5b7597230b").unwrap()), + ("99e82b163b062d55a64085bacfd407bb55f194ba5fb7a1af9c34b84435455520f1372e0e650a4f91aed0058cb823f62146ccb5599c8d13372c300dea866b69fc".into(), + Secret::from_str("f43ac0fba42a5b6ed95707d2244659e89ba877b1c9b82c0d0a9dcf834e80fc62").unwrap()), + ("7e05df9dd077ec21ed4bc45c9fe9e0a43d65fa4be540630de615ced5e95cf5c3003035eb713317237d7667feeeb64335525158f5f7411f67aca9645169ea554c".into(), + Secret::from_str("5a324938dfb2516800487d25ab7289ba8ec38811f77c3df602e4e65e3c9acd9f").unwrap()), + ("321977760d1d8e15b047a309e4c7fe6f355c10bb5a06c68472b676926427f69f229024fa2692c10da167d14cdc77eb95d0fce68af0a0f704f0d3db36baa83bb2".into(), + Secret::from_str("12cf422d50002d04e52bd4906fd7f5f235f051ca36abfe37e061f8da248008d8").unwrap()), + ]; + let common_point: Public = "6962be696e1bcbba8e64cc7fddf140f854835354b5804f3bb95ae5a2799130371b589a131bd39699ac7174ccb35fc4342dab05331202209582fc8f3a40916ab0".into(); + let encrypted_point: Public = "b07031982bde9890e12eff154765f03c56c3ab646ad47431db5dd2d742a9297679c4c65b998557f8008469afd0c43d40b6c5f6c6a1c7354875da4115237ed87a".into(); + let encrypted_datas: Vec<_> = (0..5).map(|i| EncryptedData { + threshold: 3, + id_numbers: id_numbers.clone().into_iter().collect(), + secret_share: secret_shares[i].clone(), + common_point: common_point.clone(), + encrypted_point: encrypted_point.clone(), + }).collect(); + let acl_storages: Vec<_> = (0..5).map(|_| Arc::new(DummyAclStorage::default())).collect(); + let clusters: Vec<_> = (0..5).map(|i| Arc::new(DummyCluster::new(id_numbers.iter().nth(i).clone().unwrap().0))).collect(); + let sessions: Vec<_> = (0..5).map(|i| Session::new(SessionParams { + id: session_id.clone(), + access_key: access_key.clone(), + self_node_id: id_numbers.iter().nth(i).clone().unwrap().0, + encrypted_data: encrypted_datas[i].clone(), + acl_storage: acl_storages[i].clone(), + cluster: clusters[i].clone() + }).unwrap()).collect(); + + (clusters, acl_storages, sessions) + } + + fn do_messages_exchange(clusters: &[Arc], sessions: &[Session]) { + do_messages_exchange_until(clusters, sessions, |_, _, _| false); + } + + fn do_messages_exchange_until(clusters: &[Arc], sessions: &[Session], mut cond: F) where F: FnMut(&NodeId, &NodeId, &Message) -> bool { + while let Some((from, to, message)) = clusters.iter().filter_map(|c| c.take_message().map(|(to, msg)| (c.node(), to, msg))).next() { + let session = &sessions[sessions.iter().position(|s| s.node() == &to).unwrap()]; + if cond(&from, &to, &message) { + break; + } + + match message { + Message::InitializeDecryptionSession(message) => session.on_initialize_session(from, message).unwrap(), + Message::ConfirmDecryptionInitialization(message) => session.on_confirm_initialization(from, message).unwrap(), + Message::RequestPartialDecryption(message) => session.on_partial_decryption_requested(from, message).unwrap(), + Message::PartialDecryption(message) => session.on_partial_decryption(from, message).unwrap(), + _ => panic!("unexpected"), + } + } + } + + #[test] + fn fails_to_construct_in_cluster_of_single_node() { + let mut nodes = BTreeMap::new(); + let self_node_id = Random.generate().unwrap().public().clone(); + nodes.insert(self_node_id, Random.generate().unwrap().secret().clone()); + match Session::new(SessionParams { + id: SessionId::default(), + access_key: Random.generate().unwrap().secret().clone(), + self_node_id: self_node_id.clone(), + encrypted_data: EncryptedData { + threshold: 0, + id_numbers: nodes, + secret_share: Random.generate().unwrap().secret().clone(), + common_point: Random.generate().unwrap().public().clone(), + encrypted_point: Random.generate().unwrap().public().clone(), + }, + acl_storage: Arc::new(DummyAclStorage::default()), + cluster: Arc::new(DummyCluster::new(self_node_id.clone())), + }) { + Err(Error::InvalidNodesCount) => (), + _ => panic!("unexpected"), + } + } + + #[test] + fn fails_to_construct_if_not_a_part_of_cluster() { + let mut nodes = BTreeMap::new(); + let self_node_id = Random.generate().unwrap().public().clone(); + nodes.insert(Random.generate().unwrap().public().clone(), Random.generate().unwrap().secret().clone()); + nodes.insert(Random.generate().unwrap().public().clone(), Random.generate().unwrap().secret().clone()); + match Session::new(SessionParams { + id: SessionId::default(), + access_key: Random.generate().unwrap().secret().clone(), + self_node_id: self_node_id.clone(), + encrypted_data: EncryptedData { + threshold: 0, + id_numbers: nodes, + secret_share: Random.generate().unwrap().secret().clone(), + common_point: Random.generate().unwrap().public().clone(), + encrypted_point: Random.generate().unwrap().public().clone(), + }, + acl_storage: Arc::new(DummyAclStorage::default()), + cluster: Arc::new(DummyCluster::new(self_node_id.clone())), + }) { + Err(Error::InvalidNodesConfiguration) => (), + _ => panic!("unexpected"), + } + } + + #[test] + fn fails_to_construct_if_threshold_is_wrong() { + let mut nodes = BTreeMap::new(); + let self_node_id = Random.generate().unwrap().public().clone(); + nodes.insert(self_node_id.clone(), Random.generate().unwrap().secret().clone()); + nodes.insert(Random.generate().unwrap().public().clone(), Random.generate().unwrap().secret().clone()); + match Session::new(SessionParams { + id: SessionId::default(), + access_key: Random.generate().unwrap().secret().clone(), + self_node_id: self_node_id.clone(), + encrypted_data: EncryptedData { + threshold: 2, + id_numbers: nodes, + secret_share: Random.generate().unwrap().secret().clone(), + common_point: Random.generate().unwrap().public().clone(), + encrypted_point: Random.generate().unwrap().public().clone(), + }, + acl_storage: Arc::new(DummyAclStorage::default()), + cluster: Arc::new(DummyCluster::new(self_node_id.clone())), + }) { + Err(Error::InvalidThreshold) => (), + _ => panic!("unexpected"), + } + } + + #[test] + fn fails_to_initialize_when_already_initialized() { + let (_, _, sessions) = prepare_decryption_sessions(); + assert_eq!(sessions[0].initialize(ethkey::sign(Random.generate().unwrap().secret(), &SessionId::default()).unwrap()).unwrap(), ()); + assert_eq!(sessions[0].initialize(ethkey::sign(Random.generate().unwrap().secret(), &SessionId::default()).unwrap()).unwrap_err(), Error::InvalidStateForRequest); + } + + #[test] + fn fails_to_accept_initialization_when_already_initialized() { + let (_, _, sessions) = prepare_decryption_sessions(); + assert_eq!(sessions[0].initialize(ethkey::sign(Random.generate().unwrap().secret(), &SessionId::default()).unwrap()).unwrap(), ()); + assert_eq!(sessions[0].on_initialize_session(sessions[1].node().clone(), message::InitializeDecryptionSession { + session: SessionId::default(), + sub_session: sessions[0].access_key().clone(), + requestor_signature: ethkey::sign(Random.generate().unwrap().secret(), &SessionId::default()).unwrap(), + }).unwrap_err(), Error::InvalidStateForRequest); + } + + #[test] + fn fails_to_partial_decrypt_if_not_waiting() { + let (_, _, sessions) = prepare_decryption_sessions(); + assert_eq!(sessions[1].on_initialize_session(sessions[0].node().clone(), message::InitializeDecryptionSession { + session: SessionId::default(), + sub_session: sessions[0].access_key().clone(), + requestor_signature: ethkey::sign(Random.generate().unwrap().secret(), &SessionId::default()).unwrap(), + }).unwrap(), ()); + assert_eq!(sessions[1].on_partial_decryption_requested(sessions[0].node().clone(), message::RequestPartialDecryption { + session: SessionId::default(), + sub_session: sessions[0].access_key().clone(), + nodes: sessions.iter().map(|s| s.node().clone()).take(4).collect(), + }).unwrap(), ()); + assert_eq!(sessions[1].on_partial_decryption_requested(sessions[0].node().clone(), message::RequestPartialDecryption { + session: SessionId::default(), + sub_session: sessions[0].access_key().clone(), + nodes: sessions.iter().map(|s| s.node().clone()).take(4).collect(), + }).unwrap_err(), Error::InvalidStateForRequest); + } + + #[test] + fn fails_to_partial_decrypt_if_requested_by_slave() { + let (_, _, sessions) = prepare_decryption_sessions(); + assert_eq!(sessions[1].on_initialize_session(sessions[0].node().clone(), message::InitializeDecryptionSession { + session: SessionId::default(), + sub_session: sessions[0].access_key().clone(), + requestor_signature: ethkey::sign(Random.generate().unwrap().secret(), &SessionId::default()).unwrap(), + }).unwrap(), ()); + assert_eq!(sessions[1].on_partial_decryption_requested(sessions[2].node().clone(), message::RequestPartialDecryption { + session: SessionId::default(), + sub_session: sessions[0].access_key().clone(), + nodes: sessions.iter().map(|s| s.node().clone()).take(4).collect(), + }).unwrap_err(), Error::InvalidMessage); + } + + #[test] + fn fails_to_partial_decrypt_if_wrong_number_of_nodes_participating() { + let (_, _, sessions) = prepare_decryption_sessions(); + assert_eq!(sessions[1].on_initialize_session(sessions[0].node().clone(), message::InitializeDecryptionSession { + session: SessionId::default(), + sub_session: sessions[0].access_key().clone(), + requestor_signature: ethkey::sign(Random.generate().unwrap().secret(), &SessionId::default()).unwrap(), + }).unwrap(), ()); + assert_eq!(sessions[1].on_partial_decryption_requested(sessions[0].node().clone(), message::RequestPartialDecryption { + session: SessionId::default(), + sub_session: sessions[0].access_key().clone(), + nodes: sessions.iter().map(|s| s.node().clone()).take(2).collect(), + }).unwrap_err(), Error::InvalidMessage); + } + + #[test] + fn fails_to_accept_partial_decrypt_if_not_waiting() { + let (_, _, sessions) = prepare_decryption_sessions(); + assert_eq!(sessions[0].on_partial_decryption(sessions[1].node().clone(), message::PartialDecryption { + session: SessionId::default(), + sub_session: sessions[0].access_key().clone(), + shadow_point: Random.generate().unwrap().public().clone(), + }).unwrap_err(), Error::InvalidStateForRequest); + } + + #[test] + fn fails_to_accept_partial_decrypt_twice() { + let (clusters, _, sessions) = prepare_decryption_sessions(); + sessions[0].initialize(ethkey::sign(Random.generate().unwrap().secret(), &SessionId::default()).unwrap()).unwrap(); + + let mut pd_from = None; + let mut pd_msg = None; + do_messages_exchange_until(&clusters, &sessions, |from, _, msg| match msg { + &Message::PartialDecryption(ref msg) => { + pd_from = Some(from.clone()); + pd_msg = Some(msg.clone()); + true + }, + _ => false, + }); + + assert_eq!(sessions[0].on_partial_decryption(pd_from.clone().unwrap(), pd_msg.clone().unwrap()).unwrap(), ()); + assert_eq!(sessions[0].on_partial_decryption(pd_from.unwrap(), pd_msg.unwrap()).unwrap_err(), Error::InvalidStateForRequest); + } + + #[test] + fn complete_dec_session() { + let (clusters, _, sessions) = prepare_decryption_sessions(); + + // now let's try to do a decryption + let key_pair = Random.generate().unwrap(); + let signature = ethkey::sign(key_pair.secret(), &SessionId::default()).unwrap(); + sessions[0].initialize(signature).unwrap(); + + do_messages_exchange(&clusters, &sessions); + + // now check that: + // 1) 4 of 5 sessions are in Finished state + assert_eq!(sessions.iter().filter(|s| s.state() == SessionState::Finished).count(), 4); + // 2) 1 session is in WaitingForPartialDecryptionRequest state + assert_eq!(sessions.iter().filter(|s| s.state() == SessionState::WaitingForPartialDecryptionRequest).count(), 1); + // 3) 1 session has decrypted key value + assert!(sessions.iter().skip(1).all(|s| s.decrypted_secret().is_none())); + assert_eq!(sessions[0].decrypted_secret(), Some(SECRET_PLAIN.into())); + } + + #[test] + fn failed_dec_session() { + let (clusters, acl_storages, sessions) = prepare_decryption_sessions(); + + // now let's try to do a decryption + let key_pair = Random.generate().unwrap(); + let signature = ethkey::sign(key_pair.secret(), &SessionId::default()).unwrap(); + sessions[0].initialize(signature).unwrap(); + + // we need 4 out of 5 nodes to agree to do a decryption + // let's say that 2 of these nodes are disagree + acl_storages[1].prohibit(key_pair.public().clone(), SessionId::default()); + acl_storages[2].prohibit(key_pair.public().clone(), SessionId::default()); + + do_messages_exchange(&clusters, &sessions); + + // now check that: + // 1) 3 of 5 sessions are in Failed state + assert_eq!(sessions.iter().filter(|s| s.state() == SessionState::Failed).count(), 3); + // 2) 2 of 5 sessions are in WaitingForPartialDecryptionRequest state + assert_eq!(sessions.iter().filter(|s| s.state() == SessionState::WaitingForPartialDecryptionRequest).count(), 2); + // 3) 0 sessions have decrypted key value + assert!(sessions.iter().all(|s| s.decrypted_secret().is_none())); + } +} diff --git a/secret_store/src/key_server_cluster/encryption_session.rs b/secret_store/src/key_server_cluster/encryption_session.rs new file mode 100644 index 000000000..6f5705a73 --- /dev/null +++ b/secret_store/src/key_server_cluster/encryption_session.rs @@ -0,0 +1,1197 @@ +// Copyright 2015-2017 Parity Technologies (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 . + +use std::collections::{BTreeSet, BTreeMap, VecDeque}; +use std::fmt::{Debug, Formatter, Error as FmtError}; +use std::sync::Arc; +use parking_lot::Mutex; +use ethkey::{Public, Secret}; +use key_server_cluster::{Error, NodeId, SessionId}; +use key_server_cluster::math; +use key_server_cluster::cluster::Cluster; +use key_server_cluster::message::{Message, InitializeSession, ConfirmInitialization, CompleteInitialization, + KeysDissemination, Complaint, ComplaintResponse, PublicKeyShare}; + +/// Encryption (distributed key generation) session. +/// Based on "ECDKG: A Distributed Key Generation Protocol Based on Elliptic Curve Discrete Logarithm" paper: +/// http://citeseerx.ist.psu.edu/viewdoc/download?doi=10.1.1.124.4128&rep=rep1&type=pdf +/// Brief overview: +/// 1) initialization: master node (which has received request for generating joint public + secret) initializes the session on all other nodes +/// 2) key dissemination (KD): all nodes are generating secret + public values and send these to appropriate nodes +/// 3) key verification (KV): all nodes are checking values, received for other nodes and complaining if keys are wrong +/// 4) key check phase (KC): nodes are processing complaints, received from another nodes +/// 5) key generation phase (KG): nodes are exchanging with information, enough to generate joint public key +pub struct Session { + /// Unique session id. + id: SessionId, + /// Public identifier of this node. + self_node_id: NodeId, + /// Cluster which allows this node to send messages to other nodes in the cluster. + cluster: Arc, + /// Mutable session data. + data: Mutex, +} + +#[derive(Debug)] +/// Mutable data of encryption (distributed key generation) session. +struct SessionData { + /// Current state of the session. + state: SessionState, + + // === Values, filled when session initialization just starts === + /// Reference to the node, which has started this session. + master: Option, + + // === Values, filled when session initialization is completed === + /// Threshold value for this DKG. Only `threshold + 1` will be able to collectively recreate joint secret, + /// and thus - decrypt message, encrypted with joint public. + threshold: Option, + /// Random point, jointly generated by every node in the cluster. + derived_point: Option, + /// Nodes-specific data. + nodes: BTreeMap, + + // === Values, filled during KD phase === + /// Value of polynom1[0], generated by this node. + secret_coeff: Option, + + // === Values, filled during KG phase === + /// Secret share, which this node holds. Persistent + private. + secret_share: Option, + + /// === Values, filled when DKG session is completed successfully === + /// Jointly generated public key, which can be used to encrypt secret. Public. + joint_public: Option, +} + +#[derive(Debug, Clone)] +/// Mutable node-specific data. +struct NodeData { + /// Random unique scalar. Persistent. + pub id_number: Secret, + + // === Values, filled during KD phase === + /// Secret value1, which has been sent to this node. + pub secret1_sent: Option, + /// Secret value2, which has been sent to this node. + pub secret2_sent: Option, + /// Secret value1, which has been received from this node. + pub secret1: Option, + /// Secret value2, which has been received from this node. + pub secret2: Option, + /// Public values, which have been received from this node. + pub publics: Option>, + + /// === Values, filled during KC phase === + /// Nodes, complaining against this node. + pub complaints: BTreeSet, + + /// === Values, filled during KG phase === + /// Public share, which has been received from this node. + pub public_share: Option, +} + +#[derive(Debug, Clone, PartialEq)] +/// Schedule for visiting other nodes of cluster. +pub struct EveryOtherNodeVisitor { + /// Already visited nodes. + visited: BTreeSet, + /// Not yet visited nodes. + unvisited: VecDeque, + /// Nodes, which are currently visited. + in_progress: BTreeSet, +} + +#[derive(Debug, Clone, PartialEq)] +/// Encryption (distributed key generation) session state. +pub enum SessionState { + // === Initialization states === + /// Every node starts in this state. + WaitingForInitialization, + /// Master node asks every other node to confirm initialization. + /// Derived point is generated by all nodes in the cluster. + WaitingForInitializationConfirm(EveryOtherNodeVisitor), + /// Slave nodes are in this state until initialization completion is reported by master node. + WaitingForInitializationComplete, + + // === KD phase states === + /// Node is waiting for generated keys from every other node. + WaitingForKeysDissemination, + + // === KC phase states === + /// Keys check currently occurs. + KeyCheck, + + // === KG phase states === + /// Node is waiting for joint public key share to be received from every other node. + WaitingForPublicKeyShare, + + // === Final states of the session === + /// Joint public key generation is completed. + Finished, + /// Joint public key generation is failed. + Failed, +} + +impl Session { + /// Create new encryption session. + pub fn new(id: SessionId, self_node_id: Public, cluster: Arc) -> Self { + Session { + id: id, + self_node_id: self_node_id, + cluster: cluster, + data: Mutex::new(SessionData { + state: SessionState::WaitingForInitialization, + master: None, + threshold: None, + derived_point: None, + nodes: BTreeMap::new(), + secret_coeff: None, + secret_share: None, + joint_public: None, + }), + } + } + + /// Get this node Id. + pub fn node(&self) -> &NodeId { + &self.self_node_id + } + + /// Get current session state. + pub fn state(&self) -> SessionState { + self.data.lock().state.clone() + } + + /// Get joint public key. + pub fn joint_public_key(&self) -> Option { + self.data.lock().joint_public.clone() + } + + #[cfg(test)] + /// Get derived point. + pub fn derived_point(&self) -> Option { + self.data.lock().derived_point.clone() + } + + #[cfg(test)] + /// Get qualified nodes. + pub fn qualified_nodes(&self) -> BTreeSet { + self.data.lock().nodes.keys().cloned().collect() + } + + /// Start new session initialization. This must be called on master node. + pub fn initialize(&self, threshold: usize, nodes: BTreeSet) -> Result<(), Error> { + check_cluster_nodes(self.node(), &nodes)?; + check_threshold(threshold, &nodes)?; + + let mut data = self.data.lock(); + + // check state + if data.state != SessionState::WaitingForInitialization { + return Err(Error::InvalidStateForRequest); + } + + // update state + data.master = Some(self.node().clone()); + data.threshold = Some(threshold); + for node_id in &nodes { + // generate node identification parameter + let node_id_number = math::generate_random_scalar()?; + data.nodes.insert(node_id.clone(), NodeData::with_id_number(node_id_number)); + } + + let mut visit_policy = EveryOtherNodeVisitor::new(self.node(), data.nodes.keys().cloned()); + let next_node = visit_policy.next_node().expect("at least two nodes are in cluster"); + data.state = SessionState::WaitingForInitializationConfirm(visit_policy); + + // start initialization + let derived_point = math::generate_random_point()?; + self.cluster.send(&next_node, Message::InitializeSession(InitializeSession { + session: self.id.clone(), + derived_point: derived_point, + })) + } + + /// When session initialization message is received. + pub fn on_initialize_session(&self, sender: NodeId, mut message: InitializeSession) -> Result<(), Error> { + debug_assert!(self.id == message.session); + debug_assert!(&sender != self.node()); + + let mut data = self.data.lock(); + + // check state + if data.state != SessionState::WaitingForInitialization { + return Err(Error::InvalidStateForRequest); + } + + // update derived point with random scalar + math::update_random_point(&mut message.derived_point)?; + + // send confirmation back to master node + self.cluster.send(&sender, Message::ConfirmInitialization(ConfirmInitialization { + session: self.id.clone(), + derived_point: message.derived_point, + }))?; + + // update state + data.master = Some(sender); + data.state = SessionState::WaitingForInitializationComplete; + + Ok(()) + } + + /// When session initialization confirmation message is reeived. + pub fn on_confirm_initialization(&self, sender: NodeId, mut message: ConfirmInitialization) -> Result<(), Error> { + debug_assert!(self.id == message.session); + debug_assert!(&sender != self.node()); + + let mut data = self.data.lock(); + debug_assert!(data.nodes.contains_key(&sender)); + + // check state && select new node to be initialized + let next_receiver = match data.state { + SessionState::WaitingForInitializationConfirm(ref mut visit_policy) => { + if !visit_policy.mark_visited(&sender) { + return Err(Error::InvalidStateForRequest); + } + + visit_policy.next_node() + }, + _ => return Err(Error::InvalidStateForRequest), + }; + + // proceed message + match next_receiver { + Some(next_receiver) => { + return self.cluster.send(&next_receiver, Message::InitializeSession(InitializeSession { + session: self.id.clone(), + derived_point: message.derived_point, + })); + }, + None => { + // update point once again to make sure that derived point is not generated by last node + math::update_random_point(&mut message.derived_point)?; + + // remember derived point + data.derived_point = Some(message.derived_point.clone()); + + // broadcast derived point && other session paraeters to every other node + self.cluster.broadcast(Message::CompleteInitialization(CompleteInitialization { + session: self.id.clone(), + nodes: data.nodes.iter().map(|(id, data)| (id.clone(), data.id_number.clone())).collect(), + threshold: data.threshold.expect("threshold is filled in initialization phase; KD phase follows initialization phase; qed"), + derived_point: message.derived_point, + }))?; + }, + } + + // now it is time for keys dissemination (KD) phase + drop(data); + self.disseminate_keys() + } + + /// When session initialization completion message is received. + pub fn on_complete_initialization(&self, sender: NodeId, message: CompleteInitialization) -> Result<(), Error> { + debug_assert!(self.id == message.session); + debug_assert!(&sender != self.node()); + + // check message + let nodes_ids = message.nodes.keys().cloned().collect(); + check_cluster_nodes(self.node(), &nodes_ids)?; + check_threshold(message.threshold, &nodes_ids)?; + + let mut data = self.data.lock(); + + // check state + if data.state != SessionState::WaitingForInitializationComplete { + return Err(Error::InvalidStateForRequest); + } + if data.master != Some(sender) { + return Err(Error::InvalidMessage); + } + + // remember passed data + data.threshold = Some(message.threshold); + data.derived_point = Some(message.derived_point); + data.nodes = message.nodes.into_iter().map(|(id, number)| (id, NodeData::with_id_number(number))).collect(); + + // now it is time for keys dissemination (KD) phase + drop(data); + self.disseminate_keys() + } + + /// When keys dissemination message is received. + pub fn on_keys_dissemination(&self, sender: NodeId, message: KeysDissemination) -> Result<(), Error> { + debug_assert!(self.id == message.session); + debug_assert!(&sender != self.node()); + + let mut data = self.data.lock(); + debug_assert!(data.nodes.contains_key(&sender)); + + // check state + if data.state != SessionState::WaitingForKeysDissemination { + return Err(Error::InvalidStateForRequest); + } + + // check message + let threshold = data.threshold.expect("threshold is filled in initialization phase; KD phase follows initialization phase; qed"); + if message.publics.len() != threshold + 1 { + return Err(Error::InvalidMessage); + } + + // update node data + { + let node_data = data.nodes.get_mut(&sender).ok_or(Error::InvalidMessage)?; + if node_data.secret1.is_some() || node_data.secret2.is_some() || node_data.publics.is_some() { + return Err(Error::InvalidStateForRequest); + } + + node_data.secret1 = Some(message.secret1); + node_data.secret2 = Some(message.secret2); + node_data.publics = Some(message.publics); + } + + // check if we have received keys from every other node + if data.nodes.iter().any(|(node_id, node_data)| node_id != self.node() && (node_data.publics.is_none() || node_data.secret1.is_none() || node_data.secret2.is_none())) { + return Ok(()) + } + + // key verification (KV) phase: check that other nodes have passed correct secrets + let derived_point = data.derived_point.clone().expect("derived point generated on initialization phase; KV phase follows initialization phase; qed"); + let number_id = data.nodes[self.node()].id_number.clone(); + for (node_id, node_data) in data.nodes.iter_mut().filter(|&(node_id, _)| node_id != self.node()) { + let secret1 = node_data.secret1.as_ref().expect("keys received on KD phase; KV phase follows KD phase; qed"); + let secret2 = node_data.secret2.as_ref().expect("keys received on KD phase; KV phase follows KD phase; qed"); + let publics = node_data.publics.as_ref().expect("keys received on KD phase; KV phase follows KD phase; qed"); + let is_key_verification_ok = math::keys_verification(threshold, &derived_point, &number_id, + secret1, secret2, publics)?; + + if !is_key_verification_ok { + node_data.complaints.insert(self.node().clone()); + self.cluster.broadcast(Message::Complaint(Complaint { + session: self.id.clone(), + against: node_id.clone(), + }))?; + } + } + + // update state + data.state = SessionState::KeyCheck; + + Ok(()) + } + + /// When complaint is received. + pub fn on_complaint(&self, sender: NodeId, message: Complaint) -> Result<(), Error> { + debug_assert!(self.id == message.session); + debug_assert!(&sender != self.node()); + + let mut data = self.data.lock(); + debug_assert!(data.nodes.contains_key(&sender)); + + // check state + if data.state != SessionState::KeyCheck && data.state != SessionState::WaitingForKeysDissemination { + // message can be received after timeout is passed + // => encryption is already in progress + // => we can not treat it as an error + return Ok(()); + } + + // respond to complaint + if &message.against == self.node() { + let secret1_sent = data.nodes[&sender].secret1_sent.clone().expect("secrets were sent on KD phase; KC phase follows KD phase; qed"); + let secret2_sent = data.nodes[&sender].secret2_sent.clone().expect("secrets were sent on KD phase; KC phase follows KD phase; qed"); + + // someone is complaining against us => let's respond + return self.cluster.broadcast(Message::ComplaintResponse(ComplaintResponse { + session: self.id.clone(), + secret1: secret1_sent, + secret2: secret2_sent, + })); + } + + // someone is complaining against someone else => let's remember this + let threshold = data.threshold.expect("threshold is filled in initialization phase; KD phase follows initialization phase; qed"); + let is_critical_complaints_num = { + let node = data.nodes.get_mut(&message.against).ok_or(Error::InvalidMessage)?; + node.complaints.insert(sender); + node.complaints.len() >= threshold + 1 + }; + + if is_critical_complaints_num { + // too many complaints => exclude from session + Session::disqualify_node(&message.against, &*self.cluster, &mut *data); + } + + Ok(()) + } + + /// When complaint response is received + pub fn on_complaint_response(&self, sender: NodeId, message: ComplaintResponse) -> Result<(), Error> { + debug_assert!(self.id == message.session); + debug_assert!(&sender != self.node()); + + let mut data = self.data.lock(); + debug_assert!(data.nodes.contains_key(&sender)); + + // check state + if data.state != SessionState::KeyCheck { + // in theory this message can be received before KeyCheck (in WaitingForKeysDissemination state) + // => but the fact that someone is complaining about keys means that sender has already sent its keys + // => complaint response can't reach us before keys, as the cluster guarantees that messages are received in FIFO order + + // message can be received after timeout is passed + // => encryption is already in progress + // => we can not treat it as an error + return Ok(()); + } + + // check keys again + let is_key_verification_ok = { + let threshold = data.threshold.expect("threshold is filled in initialization phase; KD phase follows initialization phase; qed"); + let derived_point = data.derived_point.as_ref().expect("derived point generated on initialization phase; KV phase follows initialization phase; qed"); + let number_id = &data.nodes[self.node()].id_number; + let node_data = data.nodes.get(&sender).expect("cluster guarantees to deliver messages from qualified nodes only; qed"); + let publics = node_data.publics.as_ref().expect("keys received on KD phase; KV phase follows KD phase; qed"); + math::keys_verification(threshold, derived_point, number_id, &message.secret1, &message.secret2, publics)? + }; + + if !is_key_verification_ok { + Session::disqualify_node(&sender, &*self.cluster, &mut *data); + } else { + let node_data = data.nodes.get_mut(&sender).expect("cluster guarantees to deliver messages from qualified nodes only; qed"); + node_data.secret1 = Some(message.secret1); + node_data.secret2 = Some(message.secret2); + node_data.complaints.remove(self.node()); + } + + Ok(()) + } + + /// When KC-phase timeout is expired, it is time to start KG phase. + pub fn start_key_generation_phase(&self) -> Result<(), Error> { + let mut data = self.data.lock(); + + if data.state != SessionState::KeyCheck { + return Err(Error::InvalidStateForRequest); + } + + // calculate public share + let self_public_share = { + let self_secret_coeff = data.secret_coeff.as_ref().expect("secret_coeff is generated on KD phase; KG phase follows KD phase; qed"); + math::compute_public_share(self_secret_coeff)? + }; + + // calculate self secret + public shares + let self_secret_share = { + let secret_values_iter = data.nodes.values() + .map(|n| n.secret1.as_ref().expect("keys received on KD phase; KG phase follows KD phase; qed")); + math::compute_secret_share(secret_values_iter)? + }; + + // update state + data.state = SessionState::WaitingForPublicKeyShare; + data.secret_share = Some(self_secret_share); + let self_node = data.nodes.get_mut(self.node()).expect("node is always qualified by himself; qed"); + self_node.public_share = Some(self_public_share.clone()); + + // broadcast self public key share + self.cluster.broadcast(Message::PublicKeyShare(PublicKeyShare { + session: self.id.clone(), + public_share: self_public_share, + })) + } + + /// When public key share is received. + pub fn on_public_key_share(&self, sender: NodeId, message: PublicKeyShare) -> Result<(), Error> { + let mut data = self.data.lock(); + + // check state + if data.state != SessionState::WaitingForPublicKeyShare { + return Err(Error::InvalidStateForRequest); + } + + // update node data with received public share + { + let node_data = &mut data.nodes.get_mut(&sender).ok_or(Error::InvalidMessage)?; + if node_data.public_share.is_some() { + return Err(Error::InvalidMessage); + } + + node_data.public_share = Some(message.public_share); + } + + // if there's also nodes, which has not sent us their public shares - do nothing + if data.nodes.iter().any(|(node_id, node_data)| node_id != self.node() && node_data.public_share.is_none()) { + return Ok(()); + } + + // else - calculate joint public key && finish session + data.joint_public = { + let public_shares = data.nodes.values().map(|n| n.public_share.as_ref().expect("keys received on KD phase; KG phase follows KD phase; qed")); + Some(math::compute_joint_public(public_shares)?) + }; + data.state = SessionState::Finished; + + Ok(()) + } + + /// Keys dissemination (KD) phase + fn disseminate_keys(&self) -> Result<(), Error> { + let mut data = self.data.lock(); + + // pick 2t + 2 random numbers as polynomial coefficients for 2 polynoms + let threshold = data.threshold.expect("threshold is filled on initialization phase; KD phase follows initialization phase; qed"); + let polynom1 = math::generate_random_polynom(threshold)?; + let polynom2 = math::generate_random_polynom(threshold)?; + data.secret_coeff = Some(polynom1[0].clone()); + + // compute t+1 public values + let publics = math::public_values_generation(threshold, + data.derived_point.as_ref().expect("keys dissemination occurs after derived point is agreed; qed"), + &polynom1, + &polynom2)?; + + // compute secret values for every other node + for (node, node_data) in data.nodes.iter_mut() { + let secret1 = math::compute_polynom(&polynom1, &node_data.id_number)?; + let secret2 = math::compute_polynom(&polynom2, &node_data.id_number)?; + + // send a message containing secret1 && secret2 to other node + if node != self.node() { + node_data.secret1_sent = Some(secret1.clone()); + node_data.secret2_sent = Some(secret2.clone()); + + self.cluster.send(&node, Message::KeysDissemination(KeysDissemination { + session: self.id.clone(), + secret1: secret1, + secret2: secret2, + publics: publics.clone(), + }))?; + } else { + node_data.secret1 = Some(secret1); + node_data.secret2 = Some(secret2); + node_data.publics = Some(publics.clone()); + } + } + + // update state + data.state = SessionState::WaitingForKeysDissemination; + + Ok(()) + } + + /// Disqualify node + fn disqualify_node(node: &NodeId, cluster: &Cluster, data: &mut SessionData) { + let threshold = data.threshold + .expect("threshold is filled on initialization phase; node can only be disqualified during KC phase; KC phase follows initialization phase; qed"); + + // blacklist node + cluster.blacklist(&node); + // too many complaints => exclude from session + data.nodes.remove(&node); + // check if secret still can be reconstructed + if data.nodes.len() < threshold + 1 { + // not enough nodes => session is failed + data.state = SessionState::Failed; + } + } +} + +impl EveryOtherNodeVisitor { + pub fn new(self_id: &NodeId, nodes: I) -> Self where I: Iterator { + EveryOtherNodeVisitor { + visited: BTreeSet::new(), + unvisited: nodes.filter(|n| n != self_id).collect(), + in_progress: BTreeSet::new(), + } + } + + pub fn next_node(&mut self) -> Option { + let next_node = self.unvisited.pop_front(); + if let Some(ref next_node) = next_node { + self.in_progress.insert(next_node.clone()); + } + next_node + } + + pub fn mark_visited(&mut self, node: &NodeId) -> bool { + if !self.in_progress.remove(node) { + return false; + } + self.visited.insert(node.clone()) + } +} + +impl NodeData { + fn with_id_number(node_id_number: Secret) -> Self { + NodeData { + id_number: node_id_number, + complaints: BTreeSet::new(), + secret1_sent: None, + secret2_sent: None, + secret1: None, + secret2: None, + publics: None, + public_share: None, + } + } +} + +impl Debug for Session { + fn fmt(&self, f: &mut Formatter) -> Result<(), FmtError> { + write!(f, "Encryption session {} on {}", self.id, self.self_node_id) + } +} + +pub fn check_cluster_nodes(self_node_id: &NodeId, nodes: &BTreeSet) -> Result<(), Error> { + // at least two nodes must be in cluster + if nodes.len() < 2 { + return Err(Error::InvalidNodesCount); + } + // this node must be a part of cluster + if !nodes.contains(self_node_id) { + return Err(Error::InvalidNodesConfiguration); + } + + Ok(()) +} + +pub fn check_threshold(threshold: usize, nodes: &BTreeSet) -> Result<(), Error> { + // at least threshold + 1 nodes are required to collectively decrypt message + if threshold >= nodes.len() { + return Err(Error::InvalidThreshold); + } + + Ok(()) +} + +#[cfg(test)] +mod tests { + use std::sync::Arc; + use std::collections::{BTreeSet, BTreeMap}; + use ethkey::{Random, Generator}; + use key_server_cluster::{NodeId, SessionId, Error}; + use key_server_cluster::message::{self, Message}; + use key_server_cluster::cluster::tests::DummyCluster; + use key_server_cluster::encryption_session::{Session, SessionState}; + use key_server_cluster::math; + use key_server_cluster::math::tests::do_encryption_and_decryption; + + #[derive(Debug)] + struct Node { + pub cluster: Arc, + pub session: Session, + } + + #[derive(Debug)] + struct MessageLoop { + pub session_id: SessionId, + pub nodes: BTreeMap, + } + + impl MessageLoop { + pub fn new(nodes_num: usize) -> Self { + let mut nodes = BTreeMap::new(); + let session_id = SessionId::default(); + for _ in 0..nodes_num { + let key_pair = Random.generate().unwrap(); + let node_id = key_pair.public().clone(); + let cluster = Arc::new(DummyCluster::new(node_id.clone())); + let session = Session::new(session_id.clone(), node_id.clone(), cluster.clone()); + nodes.insert(node_id, Node { cluster: cluster, session: session }); + } + + let nodes_ids: Vec<_> = nodes.keys().cloned().collect(); + for node in nodes.values() { + for node_id in &nodes_ids { + node.cluster.add_node(node_id.clone()); + } + } + + MessageLoop { + session_id: session_id, + nodes: nodes, + } + } + + pub fn master(&self) -> &Session { + &self.nodes.values().nth(0).unwrap().session + } + + pub fn first_slave(&self) -> &Session { + &self.nodes.values().nth(1).unwrap().session + } + + pub fn second_slave(&self) -> &Session { + &self.nodes.values().nth(2).unwrap().session + } + + pub fn third_slave(&self) -> &Session { + &self.nodes.values().nth(3).unwrap().session + } + + pub fn take_message(&mut self) -> Option<(NodeId, NodeId, Message)> { + self.nodes.values() + .filter_map(|n| n.cluster.take_message().map(|m| (n.session.node().clone(), m.0, m.1))) + .nth(0) + } + + pub fn process_message(&mut self, msg: (NodeId, NodeId, Message)) -> Result<(), Error> { + match msg.2 { + Message::InitializeSession(message) => self.nodes[&msg.1].session.on_initialize_session(msg.0, message), + Message::ConfirmInitialization(message) => self.nodes[&msg.1].session.on_confirm_initialization(msg.0, message), + Message::CompleteInitialization(message) => self.nodes[&msg.1].session.on_complete_initialization(msg.0, message), + Message::KeysDissemination(message) => self.nodes[&msg.1].session.on_keys_dissemination(msg.0, message), + Message::Complaint(message) => self.nodes[&msg.1].session.on_complaint(msg.0, message), + Message::ComplaintResponse(message) => self.nodes[&msg.1].session.on_complaint_response(msg.0, message), + Message::PublicKeyShare(message) => self.nodes[&msg.1].session.on_public_key_share(msg.0, message), + _ => panic!("unexpected"), + } + } + + pub fn take_and_process_message(&mut self) -> Result<(), Error> { + let msg = self.take_message().unwrap(); + self.process_message(msg) + } + + pub fn take_and_process_all_messages(&mut self) -> Result<(), Error> { + while let Some(msg) = self.take_message() { + self.process_message(msg)?; + } + Ok(()) + } + } + + fn make_simple_cluster(threshold: usize, num_nodes: usize) -> Result<(SessionId, NodeId, NodeId, MessageLoop), Error> { + let l = MessageLoop::new(num_nodes); + l.master().initialize(threshold, l.nodes.keys().cloned().collect())?; + + let session_id = l.session_id.clone(); + let master_id = l.master().node().clone(); + let slave_id = l.first_slave().node().clone(); + Ok((session_id, master_id, slave_id, l)) + } + + #[test] + fn fails_to_initialize_in_cluster_of_single_node() { + assert_eq!(make_simple_cluster(0, 1).unwrap_err(), Error::InvalidNodesCount); + } + + #[test] + fn fails_to_initialize_if_not_a_part_of_cluster() { + let node_id = math::generate_random_point().unwrap(); + let cluster = Arc::new(DummyCluster::new(node_id.clone())); + let session = Session::new(SessionId::default(), node_id.clone(), cluster); + let cluster_nodes: BTreeSet<_> = (0..2).map(|_| math::generate_random_point().unwrap()).collect(); + assert_eq!(session.initialize(0, cluster_nodes).unwrap_err(), Error::InvalidNodesConfiguration); + } + + #[test] + fn fails_to_initialize_if_threshold_is_wrong() { + assert_eq!(make_simple_cluster(2, 2).unwrap_err(), Error::InvalidThreshold); + } + + #[test] + fn fails_to_initialize_when_already_initialized() { + let (_, _, _, l) = make_simple_cluster(0, 2).unwrap(); + assert_eq!(l.master().initialize(0, l.nodes.keys().cloned().collect()).unwrap_err(), Error::InvalidStateForRequest); + } + + #[test] + fn fails_to_accept_initialization_when_already_initialized() { + let (sid, m, _, mut l) = make_simple_cluster(0, 2).unwrap(); + l.take_and_process_message().unwrap(); + assert_eq!(l.first_slave().on_initialize_session(m, message::InitializeSession { + session: sid, + derived_point: math::generate_random_point().unwrap(), + }).unwrap_err(), Error::InvalidStateForRequest); + } + + #[test] + fn slave_updates_derived_point_on_initialization() { + let (_, _, _, mut l) = make_simple_cluster(0, 2).unwrap(); + let passed_point = match l.take_message().unwrap() { + (f, t, Message::InitializeSession(message)) => { + let point = message.derived_point.clone(); + l.process_message((f, t, Message::InitializeSession(message))).unwrap(); + point + }, + _ => panic!("unexpected"), + }; + + match l.take_message().unwrap() { + (_, _, Message::ConfirmInitialization(message)) => assert!(passed_point != message.derived_point), + _ => panic!("unexpected"), + } + } + + #[test] + fn fails_to_accept_initialization_confirmation_if_already_accepted_from_the_same_node() { + let (sid, _, s, mut l) = make_simple_cluster(0, 3).unwrap(); + l.take_and_process_message().unwrap(); + l.take_and_process_message().unwrap(); + l.take_and_process_message().unwrap(); + assert_eq!(l.master().on_confirm_initialization(s, message::ConfirmInitialization { + session: sid, + derived_point: math::generate_random_point().unwrap(), + }).unwrap_err(), Error::InvalidStateForRequest); + } + + #[test] + fn fails_to_accept_initialization_confirmation_if_initialization_already_completed() { + let (sid, _, s, mut l) = make_simple_cluster(0, 2).unwrap(); + l.take_and_process_message().unwrap(); + l.take_and_process_message().unwrap(); + assert_eq!(l.master().on_confirm_initialization(s, message::ConfirmInitialization { + session: sid, + derived_point: math::generate_random_point().unwrap(), + }).unwrap_err(), Error::InvalidStateForRequest); + } + + #[test] + fn master_updates_derived_point_on_initialization_completion() { + let (_, _, _, mut l) = make_simple_cluster(0, 2).unwrap(); + l.take_and_process_message().unwrap(); + let passed_point = match l.take_message().unwrap() { + (f, t, Message::ConfirmInitialization(message)) => { + let point = message.derived_point.clone(); + l.process_message((f, t, Message::ConfirmInitialization(message))).unwrap(); + point + }, + _ => panic!("unexpected"), + }; + + assert!(passed_point != l.master().derived_point().unwrap()); + } + + #[test] + fn fails_to_complete_initialization_in_cluster_of_single_node() { + let (sid, m, s, l) = make_simple_cluster(0, 2).unwrap(); + let mut nodes = BTreeMap::new(); + nodes.insert(s, math::generate_random_scalar().unwrap()); + assert_eq!(l.first_slave().on_complete_initialization(m, message::CompleteInitialization { + session: sid, + nodes: nodes, + threshold: 0, + derived_point: math::generate_random_point().unwrap(), + }).unwrap_err(), Error::InvalidNodesCount); + } + + #[test] + fn fails_to_complete_initialization_if_not_a_part_of_cluster() { + let (sid, m, _, l) = make_simple_cluster(0, 2).unwrap(); + let mut nodes = BTreeMap::new(); + nodes.insert(m, math::generate_random_scalar().unwrap()); + nodes.insert(math::generate_random_point().unwrap(), math::generate_random_scalar().unwrap()); + assert_eq!(l.first_slave().on_complete_initialization(m, message::CompleteInitialization { + session: sid, + nodes: nodes, + threshold: 0, + derived_point: math::generate_random_point().unwrap(), + }).unwrap_err(), Error::InvalidNodesConfiguration); + } + + #[test] + fn fails_to_complete_initialization_if_threshold_is_wrong() { + let (sid, m, s, l) = make_simple_cluster(0, 2).unwrap(); + let mut nodes = BTreeMap::new(); + nodes.insert(m, math::generate_random_scalar().unwrap()); + nodes.insert(s, math::generate_random_scalar().unwrap()); + assert_eq!(l.first_slave().on_complete_initialization(m, message::CompleteInitialization { + session: sid, + nodes: nodes, + threshold: 2, + derived_point: math::generate_random_point().unwrap(), + }).unwrap_err(), Error::InvalidThreshold); + } + + #[test] + fn fails_to_complete_initialization_if_not_waiting_for_it() { + let (sid, m, s, l) = make_simple_cluster(0, 2).unwrap(); + let mut nodes = BTreeMap::new(); + nodes.insert(m, math::generate_random_scalar().unwrap()); + nodes.insert(s, math::generate_random_scalar().unwrap()); + assert_eq!(l.first_slave().on_complete_initialization(m, message::CompleteInitialization { + session: sid, + nodes: nodes, + threshold: 0, + derived_point: math::generate_random_point().unwrap(), + }).unwrap_err(), Error::InvalidStateForRequest); + } + + #[test] + fn fails_to_complete_initialization_from_non_master_node() { + let (sid, m, s, mut l) = make_simple_cluster(0, 3).unwrap(); + l.take_and_process_message().unwrap(); + l.take_and_process_message().unwrap(); + l.take_and_process_message().unwrap(); + l.take_and_process_message().unwrap(); + let mut nodes = BTreeMap::new(); + nodes.insert(m, math::generate_random_scalar().unwrap()); + nodes.insert(s, math::generate_random_scalar().unwrap()); + nodes.insert(l.second_slave().node().clone(), math::generate_random_scalar().unwrap()); + assert_eq!(l.first_slave().on_complete_initialization(l.second_slave().node().clone(), message::CompleteInitialization { + session: sid, + nodes: nodes, + threshold: 0, + derived_point: math::generate_random_point().unwrap(), + }).unwrap_err(), Error::InvalidMessage); + } + + #[test] + fn fails_to_accept_keys_dissemination_if_not_waiting_for_it() { + let (sid, _, s, l) = make_simple_cluster(0, 2).unwrap(); + assert_eq!(l.master().on_keys_dissemination(s, message::KeysDissemination { + session: sid, + secret1: math::generate_random_scalar().unwrap(), + secret2: math::generate_random_scalar().unwrap(), + publics: vec![math::generate_random_point().unwrap()], + }).unwrap_err(), Error::InvalidStateForRequest); + } + + #[test] + fn fails_to_accept_keys_dissemination_if_wrong_number_of_publics_passed() { + let (sid, m, _, mut l) = make_simple_cluster(0, 3).unwrap(); + l.take_and_process_message().unwrap(); // m -> s1: InitializeSession + l.take_and_process_message().unwrap(); // m -> s2: InitializeSession + l.take_and_process_message().unwrap(); // s1 -> m: ConfirmInitialization + l.take_and_process_message().unwrap(); // s2 -> m: ConfirmInitialization + l.take_and_process_message().unwrap(); // m -> s1: CompleteInitialization + l.take_and_process_message().unwrap(); // m -> s2: CompleteInitialization + l.take_and_process_message().unwrap(); // m -> s1: KeysDissemination + assert_eq!(l.first_slave().on_keys_dissemination(m, message::KeysDissemination { + session: sid, + secret1: math::generate_random_scalar().unwrap(), + secret2: math::generate_random_scalar().unwrap(), + publics: vec![math::generate_random_point().unwrap(), math::generate_random_point().unwrap()], + }).unwrap_err(), Error::InvalidMessage); + } + + #[test] + fn fails_to_accept_keys_dissemination_second_time_from_the_same_node() { + let (sid, m, _, mut l) = make_simple_cluster(0, 3).unwrap(); + l.take_and_process_message().unwrap(); // m -> s1: InitializeSession + l.take_and_process_message().unwrap(); // m -> s2: InitializeSession + l.take_and_process_message().unwrap(); // s1 -> m: ConfirmInitialization + l.take_and_process_message().unwrap(); // s2 -> m: ConfirmInitialization + l.take_and_process_message().unwrap(); // m -> s1: CompleteInitialization + l.take_and_process_message().unwrap(); // m -> s2: CompleteInitialization + l.take_and_process_message().unwrap(); // m -> s1: KeysDissemination + assert_eq!(l.first_slave().on_keys_dissemination(m, message::KeysDissemination { + session: sid, + secret1: math::generate_random_scalar().unwrap(), + secret2: math::generate_random_scalar().unwrap(), + publics: vec![math::generate_random_point().unwrap()], + }).unwrap_err(), Error::InvalidStateForRequest); + } + + #[test] + fn defends_if_receives_complain_on_himself() { + let (sid, m, s, mut l) = make_simple_cluster(1, 3).unwrap(); + l.take_and_process_all_messages().unwrap(); + l.master().on_complaint(s, message::Complaint { + session: sid, + against: m, + }).unwrap(); + match l.take_message().unwrap() { + (_, _, Message::ComplaintResponse(_)) => (), + _ => panic!("unexpected"), + } + } + + #[test] + fn node_is_disqualified_if_enough_complaints_received() { + let (sid, _, s, mut l) = make_simple_cluster(1, 4).unwrap(); + l.take_and_process_all_messages().unwrap(); + l.master().on_complaint(l.second_slave().node().clone(), message::Complaint { + session: sid, + against: s.clone(), + }).unwrap(); + l.master().on_complaint(l.third_slave().node().clone(), message::Complaint { + session: sid, + against: s, + }).unwrap(); + assert_eq!(l.master().qualified_nodes().len(), 3); + } + + #[test] + fn node_is_not_disqualified_if_enough_complaints_received_from_the_same_node() { + let (sid, _, s, mut l) = make_simple_cluster(1, 4).unwrap(); + l.take_and_process_all_messages().unwrap(); + l.master().on_complaint(l.second_slave().node().clone(), message::Complaint { + session: sid, + against: s.clone(), + }).unwrap(); + l.master().on_complaint(l.second_slave().node().clone(), message::Complaint { + session: sid, + against: s, + }).unwrap(); + assert_eq!(l.master().qualified_nodes().len(), 4); + } + + #[test] + fn node_is_disqualified_if_responds_to_complain_with_invalid_data() { + let (sid, _, _, mut l) = make_simple_cluster(1, 3).unwrap(); + l.take_and_process_message().unwrap(); // m -> s1: InitializeSession + l.take_and_process_message().unwrap(); // m -> s2: InitializeSession + l.take_and_process_message().unwrap(); // s1 -> m: ConfirmInitialization + l.take_and_process_message().unwrap(); // s2 -> m: ConfirmInitialization + l.take_and_process_message().unwrap(); // m -> s1: CompleteInitialization + l.take_and_process_message().unwrap(); // m -> s2: CompleteInitialization + l.take_and_process_message().unwrap(); // m -> s1: KeysDissemination + l.take_and_process_message().unwrap(); // m -> s2: KeysDissemination + l.take_and_process_message().unwrap(); // s1 -> m: KeysDissemination + l.take_and_process_message().unwrap(); // s1 -> s2: KeysDissemination + let s2 = l.second_slave().node().clone(); + l.master().on_keys_dissemination(s2.clone(), message::KeysDissemination { + session: sid.clone(), + secret1: math::generate_random_scalar().unwrap(), + secret2: math::generate_random_scalar().unwrap(), + publics: vec![math::generate_random_point().unwrap(), math::generate_random_point().unwrap()], + }).unwrap(); + assert_eq!(l.master().qualified_nodes().len(), 3); + l.master().on_complaint_response(s2, message::ComplaintResponse { + session: sid, + secret1: math::generate_random_scalar().unwrap(), + secret2: math::generate_random_scalar().unwrap(), + }).unwrap(); + assert_eq!(l.master().qualified_nodes().len(), 2); + } + + #[test] + fn node_is_not_disqualified_if_responds_to_complain_with_valid_data() { + let (sid, _, _, mut l) = make_simple_cluster(1, 3).unwrap(); + l.take_and_process_message().unwrap(); // m -> s1: InitializeSession + l.take_and_process_message().unwrap(); // m -> s2: InitializeSession + l.take_and_process_message().unwrap(); // s1 -> m: ConfirmInitialization + l.take_and_process_message().unwrap(); // s2 -> m: ConfirmInitialization + l.take_and_process_message().unwrap(); // m -> s1: CompleteInitialization + l.take_and_process_message().unwrap(); // m -> s2: CompleteInitialization + l.take_and_process_message().unwrap(); // m -> s1: KeysDissemination + l.take_and_process_message().unwrap(); // m -> s2: KeysDissemination + l.take_and_process_message().unwrap(); // s1 -> m: KeysDissemination + l.take_and_process_message().unwrap(); // s1 -> s2: KeysDissemination + let (f, t, msg) = match l.take_message() { + Some((f, t, Message::KeysDissemination(msg))) => (f, t, msg), + _ => panic!("unexpected"), + }; + assert_eq!(&f, l.second_slave().node()); + assert_eq!(&t, l.master().node()); + l.master().on_keys_dissemination(f.clone(), message::KeysDissemination { + session: sid.clone(), + secret1: math::generate_random_scalar().unwrap(), + secret2: math::generate_random_scalar().unwrap(), + publics: msg.publics.clone(), + }).unwrap(); + assert_eq!(l.master().qualified_nodes().len(), 3); + l.master().on_complaint_response(f, message::ComplaintResponse { + session: sid, + secret1: msg.secret1, + secret2: msg.secret2, + }).unwrap(); + assert_eq!(l.master().qualified_nodes().len(), 3); + } + + #[test] + fn should_not_start_key_generation_when_not_in_key_check_state() { + let (_, _, _, l) = make_simple_cluster(1, 3).unwrap(); + assert_eq!(l.master().start_key_generation_phase().unwrap_err(), Error::InvalidStateForRequest); + } + + #[test] + fn should_not_accept_public_key_share_when_is_not_waiting_for_it() { + let (sid, _, s, l) = make_simple_cluster(1, 3).unwrap(); + assert_eq!(l.master().on_public_key_share(s, message::PublicKeyShare { + session: sid, + public_share: math::generate_random_point().unwrap(), + }).unwrap_err(), Error::InvalidStateForRequest); + } + + #[test] + fn should_not_accept_public_key_share_when_receiving_twice() { + let (sid, m, _, mut l) = make_simple_cluster(0, 3).unwrap(); + l.take_and_process_all_messages().unwrap(); + l.master().start_key_generation_phase().unwrap(); + l.first_slave().start_key_generation_phase().unwrap(); + let (f, t, msg) = match l.take_message() { + Some((f, t, Message::PublicKeyShare(msg))) => (f, t, msg), + _ => panic!("unexpected"), + }; + assert_eq!(&f, l.master().node()); + assert_eq!(&t, l.first_slave().node()); + l.process_message((f, t, Message::PublicKeyShare(msg.clone()))).unwrap(); + assert_eq!(l.first_slave().on_public_key_share(m, message::PublicKeyShare { + session: sid, + public_share: math::generate_random_point().unwrap(), + }).unwrap_err(), Error::InvalidMessage); + } + + #[test] + fn complete_enc_dec_session() { + // TODO: when number of nodes, needed to decrypt message is odd, algorithm won't work + // let test_cases = [/*(0, 2), */(1, 2), (1, 3), (2, 3), (1, 4), (2, 4), (3, 4), (1, 5), (2, 5), (3, 5), (4, 5), + // (1, 10), (2, 10), (3, 10), (4, 10), (5, 10), (6, 10), (7, 10), (8, 10), (9, 10)]; + let test_cases = [(3, 5)]; + for &(threshold, num_nodes) in &test_cases { + let mut l = MessageLoop::new(num_nodes); + l.master().initialize(threshold, l.nodes.keys().cloned().collect()).unwrap(); + assert_eq!(l.nodes.len(), num_nodes); + + // let nodes do initialization + keys dissemination + while let Some((from, to, message)) = l.take_message() { + l.process_message((from, to, message)).unwrap(); + } + + // check that all nodes are waiting for complaint timeout is passed + for node in l.nodes.values() { + let state = node.session.state(); + assert_eq!(state, SessionState::KeyCheck); + + // simulate timeout pass + node.session.start_key_generation_phase().unwrap(); + } + + // let nodes do joint public generation + while let Some((from, to, message)) = l.take_message() { + l.process_message((from, to, message)).unwrap(); + } + + // check that all nodes has finished joint public generation + let joint_public_key = l.master().joint_public_key().unwrap(); + for node in l.nodes.values() { + let state = node.session.state(); + assert_eq!(state, SessionState::Finished); + assert_eq!(node.session.joint_public_key().as_ref(), Some(&joint_public_key)); + } + + // now let's encrypt some secret (which is a point on EC) + let document_secret_plain = Random.generate().unwrap().public().clone(); + let all_nodes_id_numbers: Vec<_> = l.master().data.lock().nodes.values().map(|n| n.id_number.clone()).collect(); + let all_nodes_secret_shares: Vec<_> = l.nodes.values().map(|n| n.session.data.lock().secret_share.as_ref().unwrap().clone()).collect(); + let document_secret_decrypted = do_encryption_and_decryption(threshold, &joint_public_key, + &all_nodes_id_numbers, + &all_nodes_secret_shares, + None, + document_secret_plain.clone() + ).0; + assert_eq!(document_secret_plain, document_secret_decrypted); + } + } + + // TODO: add test where some nodes are disqualified from session +} diff --git a/secret_store/src/key_server_cluster/math.rs b/secret_store/src/key_server_cluster/math.rs new file mode 100644 index 000000000..4da17ebc7 --- /dev/null +++ b/secret_store/src/key_server_cluster/math.rs @@ -0,0 +1,338 @@ +// Copyright 2015-2017 Parity Technologies (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 . + +use ethkey::{Public, Secret, Random, Generator, math}; +use key_server_cluster::Error; + +#[derive(Debug)] +/// Encryption result. +pub struct EncryptedSecret { + /// Common encryption point. + pub common_point: Public, + /// Ecnrypted point. + pub encrypted_point: Public, +} + +/// Generate random scalar +pub fn generate_random_scalar() -> Result { + Ok(Random.generate()?.secret().clone()) +} + +/// Generate random point +pub fn generate_random_point() -> Result { + Ok(Random.generate()?.public().clone()) +} + +/// Update point by multiplying to random scalar +pub fn update_random_point(point: &mut Public) -> Result<(), Error> { + Ok(math::public_mul_secret(point, &generate_random_scalar()?)?) +} + +/// Generate random polynom of threshold degree +pub fn generate_random_polynom(threshold: usize) -> Result, Error> { + let mut polynom: Vec<_> = Vec::with_capacity(threshold + 1); + for _ in 0..threshold + 1 { + polynom.push(generate_random_scalar()?); + } + debug_assert_eq!(polynom.len(), threshold + 1); + Ok(polynom) +} + +/// Compute value of polynom, using `node_number` as argument +pub fn compute_polynom(polynom: &[Secret], node_number: &Secret) -> Result { + debug_assert!(!polynom.is_empty()); + + let mut result = polynom[0].clone(); + for i in 1..polynom.len() { + // calculate pow(node_number, i) + let mut appendum = node_number.clone(); + appendum.pow(i)?; + + // calculate coeff * pow(point, i) + appendum.mul(&polynom[i])?; + + // calculate result + coeff * pow(point, i) + result.add(&appendum)?; + } + + Ok(result) +} + +/// Generate public keys for other participants. +pub fn public_values_generation(threshold: usize, derived_point: &Public, polynom1: &[Secret], polynom2: &[Secret]) -> Result, Error> { + debug_assert_eq!(polynom1.len(), threshold + 1); + debug_assert_eq!(polynom2.len(), threshold + 1); + + // compute t+1 public values + let mut publics = Vec::with_capacity(threshold + 1); + for i in 0..threshold + 1 { + let coeff1 = &polynom1[i]; + + let mut multiplication1 = math::generation_point(); + math::public_mul_secret(&mut multiplication1, &coeff1)?; + + let coeff2 = &polynom2[i]; + let mut multiplication2 = derived_point.clone(); + math::public_mul_secret(&mut multiplication2, &coeff2)?; + + math::public_add(&mut multiplication1, &multiplication2)?; + + publics.push(multiplication1); + } + debug_assert_eq!(publics.len(), threshold + 1); + + Ok(publics) +} + +/// Check keys passed by other participants. +pub fn keys_verification(threshold: usize, derived_point: &Public, number_id: &Secret, secret1: &Secret, secret2: &Secret, publics: &[Public]) -> Result { + // calculate left part + let mut multiplication1 = math::generation_point(); + math::public_mul_secret(&mut multiplication1, secret1)?; + + let mut multiplication2 = derived_point.clone(); + math::public_mul_secret(&mut multiplication2, secret2)?; + + math::public_add(&mut multiplication1, &multiplication2)?; + let left = multiplication1; + + // calculate right part + let mut right = publics[0].clone(); + for i in 1..threshold + 1 { + let mut secret_pow = number_id.clone(); + secret_pow.pow(i)?; + + let mut public_k = publics[i].clone(); + math::public_mul_secret(&mut public_k, &secret_pow)?; + + math::public_add(&mut right, &public_k)?; + } + + Ok(left == right) +} + +/// Compute secret share. +pub fn compute_secret_share<'a, I>(mut secret_values: I) -> Result where I: Iterator { + let mut secret_share = secret_values.next().expect("compute_secret_share is called when cluster has at least one node; qed").clone(); + while let Some(secret_value) = secret_values.next() { + secret_share.add(secret_value)?; + } + Ok(secret_share) +} + +/// Compute public key share. +pub fn compute_public_share(self_secret_value: &Secret) -> Result { + let mut public_share = math::generation_point(); + math::public_mul_secret(&mut public_share, self_secret_value)?; + Ok(public_share) +} + +/// Compute joint public key. +pub fn compute_joint_public<'a, I>(mut public_shares: I) -> Result where I: Iterator { + let mut joint_public = public_shares.next().expect("compute_joint_public is called when cluster has at least one node; qed").clone(); + while let Some(public_share) = public_shares.next() { + math::public_add(&mut joint_public, &public_share)?; + } + Ok(joint_public) +} + +#[cfg(test)] +/// Compute joint secret key. +pub fn compute_joint_secret<'a, I>(mut secret_coeffs: I) -> Result where I: Iterator { + let mut joint_secret = secret_coeffs.next().expect("compute_joint_private is called when cluster has at least one node; qed").clone(); + while let Some(secret_coeff) = secret_coeffs.next() { + joint_secret.add(secret_coeff)?; + } + Ok(joint_secret) +} + +/// Encrypt secret with joint public key. +pub fn encrypt_secret(secret: Public, joint_public: &Public) -> Result { + // this is performed by KS-cluster client (or KS master) + let key_pair = Random.generate()?; + + // k * T + let mut common_point = math::generation_point(); + math::public_mul_secret(&mut common_point, key_pair.secret())?; + + // M + k * y + let mut encrypted_point = joint_public.clone(); + math::public_mul_secret(&mut encrypted_point, key_pair.secret())?; + math::public_add(&mut encrypted_point, &secret)?; + + Ok(EncryptedSecret { + common_point: common_point, + encrypted_point: encrypted_point, + }) +} + +/// Compute shadow for the node. +pub fn compute_node_shadow<'a, I>(node_number: &Secret, node_secret_share: &Secret, mut other_nodes_numbers: I) -> Result where I: Iterator { + let other_node_number = other_nodes_numbers.next().expect("compute_node_shadow is called when at least two nodes are required to decrypt secret; qed"); + let mut shadow = node_number.clone(); + shadow.sub(other_node_number)?; + shadow.inv()?; + shadow.mul(other_node_number)?; + while let Some(other_node_number) = other_nodes_numbers.next() { + let mut shadow_element = node_number.clone(); + shadow_element.sub(other_node_number)?; + shadow_element.inv()?; + shadow_element.mul(other_node_number)?; + shadow.mul(&shadow_element)?; + } + + shadow.mul(&node_secret_share)?; + Ok(shadow) +} + +/// Compute shadow point for the node. +pub fn compute_node_shadow_point(access_key: &Secret, common_point: &Public, node_shadow: &Secret) -> Result { + let mut shadow_key = access_key.clone(); + shadow_key.mul(node_shadow)?; + let mut node_shadow_point = common_point.clone(); + math::public_mul_secret(&mut node_shadow_point, &shadow_key)?; + Ok(node_shadow_point) +} + +/// Compute joint shadow point. +pub fn compute_joint_shadow_point<'a, I>(mut nodes_shadow_points: I) -> Result where I: Iterator { + let mut joint_shadow_point = nodes_shadow_points.next().expect("compute_joint_shadow_point is called when at least two nodes are required to decrypt secret; qed").clone(); + while let Some(node_shadow_point) = nodes_shadow_points.next() { + math::public_add(&mut joint_shadow_point, &node_shadow_point)?; + } + Ok(joint_shadow_point) +} + +#[cfg(test)] +/// Compute joint shadow point (version for tests). +pub fn compute_joint_shadow_point_test<'a, I>(access_key: &Secret, common_point: &Public, mut nodes_shadows: I) -> Result where I: Iterator { + let mut joint_shadow = nodes_shadows.next().expect("compute_joint_shadow_point_test is called when at least two nodes are required to decrypt secret; qed").clone(); + while let Some(node_shadow) = nodes_shadows.next() { + joint_shadow.add(node_shadow)?; + } + joint_shadow.mul(access_key)?; + + let mut joint_shadow_point = common_point.clone(); + math::public_mul_secret(&mut joint_shadow_point, &joint_shadow)?; + Ok(joint_shadow_point) +} + +/// Decrypt data using joint shadow point. +pub fn decrypt_with_joint_shadow(access_key: &Secret, encrypted_point: &Public, joint_shadow_point: &Public) -> Result { + let mut inv_access_key = access_key.clone(); + inv_access_key.inv()?; + + let mut decrypted_point = joint_shadow_point.clone(); + math::public_mul_secret(&mut decrypted_point, &inv_access_key)?; + math::public_add(&mut decrypted_point, encrypted_point)?; + + Ok(decrypted_point) +} + +/// Decrypt data using joint secret (version for tests). +pub fn decrypt_with_joint_secret(encrypted_point: &Public, common_point: &Public, joint_secret: &Secret) -> Result { + let mut common_point_mul = common_point.clone(); + math::public_mul_secret(&mut common_point_mul, joint_secret)?; + + let mut decrypted_point = encrypted_point.clone(); + math::public_sub(&mut decrypted_point, &common_point_mul)?; + + Ok(decrypted_point) +} + +#[cfg(test)] +pub mod tests { + use ethkey::KeyPair; + use super::*; + + pub fn do_encryption_and_decryption(t: usize, joint_public: &Public, id_numbers: &[Secret], secret_shares: &[Secret], joint_secret: Option<&Secret>, document_secret_plain: Public) -> (Public, Public) { + // === PART2: encryption using joint public key === + + // the next line is executed on KeyServer-client + let encrypted_secret = encrypt_secret(document_secret_plain.clone(), &joint_public).unwrap(); + + // === PART3: decryption === + + // next line is executed on KeyServer client + let access_key = generate_random_scalar().unwrap(); + + // use t + 1 nodes to compute joint shadow point + let nodes_shadows: Vec<_> = (0..t + 1).map(|i| + compute_node_shadow(&id_numbers[i], &secret_shares[i], id_numbers.iter() + .enumerate() + .filter(|&(j, _)| j != i) + .take(t) + .map(|(_, id_number)| id_number)).unwrap()).collect(); + let nodes_shadow_points: Vec<_> = nodes_shadows.iter().map(|s| compute_node_shadow_point(&access_key, &encrypted_secret.common_point, s).unwrap()).collect(); + assert_eq!(nodes_shadows.len(), t + 1); + assert_eq!(nodes_shadow_points.len(), t + 1); + + let joint_shadow_point = compute_joint_shadow_point(nodes_shadow_points.iter()).unwrap(); + let joint_shadow_point_test = compute_joint_shadow_point_test(&access_key, &encrypted_secret.common_point, nodes_shadows.iter()).unwrap(); + assert_eq!(joint_shadow_point, joint_shadow_point_test); + + // decrypt encrypted secret using joint shadow point + let document_secret_decrypted = decrypt_with_joint_shadow(&access_key, &encrypted_secret.encrypted_point, &joint_shadow_point).unwrap(); + + // decrypt encrypted secret using joint secret [just for test] + let document_secret_decrypted_test = match joint_secret { + Some(joint_secret) => decrypt_with_joint_secret(&encrypted_secret.encrypted_point, &encrypted_secret.common_point, joint_secret).unwrap(), + None => document_secret_decrypted.clone(), + }; + + (document_secret_decrypted, document_secret_decrypted_test) + } + + #[test] + fn full_encryption_math_session() { + let test_cases = [(1, 3)]; + for &(t, n) in &test_cases { + // === PART1: DKG === + + // data, gathered during initialization + let id_numbers: Vec<_> = (0..n).map(|_| generate_random_scalar().unwrap()).collect(); + + // data, generated during keys dissemination + let polynoms1: Vec<_> = (0..n).map(|_| generate_random_polynom(t).unwrap()).collect(); + let secrets1: Vec<_> = (0..n).map(|i| (0..n).map(|j| compute_polynom(&polynoms1[i], &id_numbers[j]).unwrap()).collect::>()).collect(); + + // data, generated during keys generation + let public_shares: Vec<_> = (0..n).map(|i| compute_public_share(&polynoms1[i][0]).unwrap()).collect(); + let secret_shares: Vec<_> = (0..n).map(|i| compute_secret_share(secrets1.iter().map(|s| &s[i])).unwrap()).collect(); + + // joint public key, as a result of DKG + let joint_public = compute_joint_public(public_shares.iter()).unwrap(); + + // compute joint private key [just for test] + let joint_secret = compute_joint_secret(polynoms1.iter().map(|p| &p[0])).unwrap(); + let joint_key_pair = KeyPair::from_secret(joint_secret.clone()).unwrap(); + assert_eq!(&joint_public, joint_key_pair.public()); + + // check secret shares computation [just for test] + let secret_shares_polynom: Vec<_> = (0..t + 1).map(|k| compute_secret_share(polynoms1.iter().map(|p| &p[k])).unwrap()).collect(); + let secret_shares_calculated_from_polynom: Vec<_> = id_numbers.iter().map(|id_number| compute_polynom(&*secret_shares_polynom, id_number).unwrap()).collect(); + assert_eq!(secret_shares, secret_shares_calculated_from_polynom); + + // now encrypt and decrypt data + let document_secret_plain = generate_random_point().unwrap(); + let (document_secret_decrypted, document_secret_decrypted_test) = + do_encryption_and_decryption(t, &joint_public, &id_numbers, &secret_shares, Some(&joint_secret), document_secret_plain.clone()); + + assert_eq!(document_secret_plain, document_secret_decrypted_test); + assert_eq!(document_secret_plain, document_secret_decrypted); + } + } +} diff --git a/secret_store/src/key_server_cluster/message.rs b/secret_store/src/key_server_cluster/message.rs new file mode 100644 index 000000000..800dcf705 --- /dev/null +++ b/secret_store/src/key_server_cluster/message.rs @@ -0,0 +1,168 @@ +// Copyright 2015-2017 Parity Technologies (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 . + +use std::collections::{BTreeSet, BTreeMap}; +use ethkey::{Public, Secret, Signature}; +use key_server_cluster::{NodeId, SessionId}; + +#[derive(Clone, Debug)] +/// All possible messages that can be sent during DKG. +pub enum Message { + /// Initialize new DKG session. + InitializeSession(InitializeSession), + /// Confirm DKG session initialization. + ConfirmInitialization(ConfirmInitialization), + /// Broadcast data, calculated during session initialization phase. + CompleteInitialization(CompleteInitialization), + /// Generated keys are sent to every node. + KeysDissemination(KeysDissemination), + /// Complaint against another node is broadcasted. + Complaint(Complaint), + /// Complaint response is broadcasted. + ComplaintResponse(ComplaintResponse), + /// Broadcast self public key portion. + PublicKeyShare(PublicKeyShare), + + /// Initialize decryption session. + InitializeDecryptionSession(InitializeDecryptionSession), + /// Confirm/reject decryption session initialization. + ConfirmDecryptionInitialization(ConfirmDecryptionInitialization), + /// Request partial decryption from node. + RequestPartialDecryption(RequestPartialDecryption), + /// Partial decryption is completed + PartialDecryption(PartialDecryption), +} + +#[derive(Clone, Debug)] +/// Initialize new DKG session. +pub struct InitializeSession { + /// Session Id. + pub session: SessionId, + /// Derived generation point. Starting from originator, every node must multiply this + /// point by random scalar (unknown by other nodes). At the end of initialization + /// `point` will be some (k1 * k2 * ... * kn) * G = `point` where `(k1 * k2 * ... * kn)` + /// is unknown for every node. + pub derived_point: Public, +} + +#[derive(Clone, Debug)] +/// Confirm DKG session initialization. +pub struct ConfirmInitialization { + /// Session Id. + pub session: SessionId, + /// Derived generation point. + pub derived_point: Public, +} + +#[derive(Clone, Debug)] +/// Broadcast generated point to every other node. +pub struct CompleteInitialization { + /// Session Id. + pub session: SessionId, + /// All session participants along with their identification numbers. + pub nodes: BTreeMap, + /// Decryption threshold. During decryption threshold-of-route.len() nodes must came to + /// consensus to successfully decrypt message. + pub threshold: usize, + /// Derived generation point. + pub derived_point: Public, +} + +#[derive(Clone, Debug)] +/// Generated keys are sent to every node. +pub struct KeysDissemination { + /// Session Id. + pub session: SessionId, + /// Secret 1. + pub secret1: Secret, + /// Secret 2. + pub secret2: Secret, + /// Public values. + pub publics: Vec, +} + +#[derive(Clone, Debug)] +/// Complaint against node is broadcasted. +pub struct Complaint { + /// Session Id. + pub session: SessionId, + /// Public values. + pub against: NodeId, +} + +#[derive(Clone, Debug)] +/// Node is responding to complaint. +pub struct ComplaintResponse { + /// Session Id. + pub session: SessionId, + /// Secret 1. + pub secret1: Secret, + /// Secret 2. + pub secret2: Secret, +} + +#[derive(Clone, Debug)] +/// Node is sharing its public key share. +pub struct PublicKeyShare { + /// Session Id. + pub session: SessionId, + /// Public key share. + pub public_share: Public, +} + +#[derive(Clone, Debug)] +/// Node is requested to decrypt data, encrypted in given session. +pub struct InitializeDecryptionSession { + /// Encryption session Id. + pub session: SessionId, + /// Decryption session Id. + pub sub_session: Secret, + /// Requestor signature. + pub requestor_signature: Signature, +} + +#[derive(Clone, Debug)] +/// Node is responding to decryption request. +pub struct ConfirmDecryptionInitialization { + /// Encryption session Id. + pub session: SessionId, + /// Decryption session Id. + pub sub_session: Secret, + /// Is node confirmed to make a decryption?. + pub is_confirmed: bool, +} + +#[derive(Clone, Debug)] +/// Node is requested to do a partial decryption. +pub struct RequestPartialDecryption { + /// Encryption session Id. + pub session: SessionId, + /// Decryption session Id. + pub sub_session: Secret, + /// Nodes that are agreed to do a decryption. + pub nodes: BTreeSet, +} + +#[derive(Clone, Debug)] +/// Node has partially decrypted the secret. +pub struct PartialDecryption { + /// Encryption session Id. + pub session: SessionId, + /// Decryption session Id. + pub sub_session: Secret, + /// Partially decrypted secret. + pub shadow_point: Public, +} diff --git a/secret_store/src/key_server_cluster/mod.rs b/secret_store/src/key_server_cluster/mod.rs new file mode 100644 index 000000000..5d0dacd11 --- /dev/null +++ b/secret_store/src/key_server_cluster/mod.rs @@ -0,0 +1,76 @@ +// Copyright 2015-2017 Parity Technologies (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 . + +#![allow(dead_code)] // TODO: remove me + +use std::collections::BTreeMap; +use ethkey::{self, Public, Secret, Signature}; +use super::types::all::DocumentAddress; + +pub use super::acl_storage::AclStorage; + +pub type NodeId = Public; +pub type SessionId = DocumentAddress; +pub type SessionIdSignature = Signature; + +#[derive(Debug, PartialEq)] +/// Errors which can occur during encryption/decryption session +pub enum Error { + /// Invalid number of nodes. + /// There must be at least two nodes participating in encryption. + /// There must be at least one node participating in decryption. + InvalidNodesCount, + /// Node which is required to start encryption/decryption session is not a part of cluster. + InvalidNodesConfiguration, + /// Invalid threshold value has been passed. + /// Threshold value must be in [0; n - 1], where n is a number of nodes participating in the encryption. + InvalidThreshold, + /// Current state of encryption/decryption session does not allow to proceed request. + /// This means that either there is some comm-failure or node is misbehaving/cheating. + InvalidStateForRequest, + /// Some data in passed message was recognized as invalid. + /// This means that node is misbehaving/cheating. + InvalidMessage, + /// Cryptographic error. + EthKey(String), +} + +#[derive(Debug, Clone)] +/// Data, which is stored on every node after DKG && encryption is completed. +pub struct EncryptedData { + /// Decryption threshold (at least threshold + 1 nodes are required to decrypt data). + threshold: usize, + /// Nodes ids numbers. + id_numbers: BTreeMap, + /// Node secret share. + secret_share: Secret, + /// Common (shared) encryption point. + common_point: Public, + /// Encrypted point. + encrypted_point: Public, +} + +impl From for Error { + fn from(err: ethkey::Error) -> Self { + Error::EthKey(err.into()) + } +} + +mod cluster; +mod decryption_session; +mod encryption_session; +mod math; +mod message; diff --git a/secret_store/src/lib.rs b/secret_store/src/lib.rs index 390ae1e5e..41d658963 100644 --- a/secret_store/src/lib.rs +++ b/secret_store/src/lib.rs @@ -26,6 +26,7 @@ extern crate ethcore_ipc as ipc; extern crate ethcrypto; extern crate ethkey; +mod key_server_cluster; mod types; mod traits { From 8a37f9599ffd573bdc1f275dad6be9a824a60f42 Mon Sep 17 00:00:00 2001 From: Nicolas Gotchac Date: Mon, 13 Mar 2017 13:19:43 +0100 Subject: [PATCH 44/71] Reload UI on network switch (#4864) * Reload UI on network switch * Don't bither with timeout. --- js/src/redux/providers/chainMiddleware.js | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/js/src/redux/providers/chainMiddleware.js b/js/src/redux/providers/chainMiddleware.js index 3920eb7c3..2df40ed86 100644 --- a/js/src/redux/providers/chainMiddleware.js +++ b/js/src/redux/providers/chainMiddleware.js @@ -29,7 +29,10 @@ export default class ChainMiddleware { const { nodeStatus } = store.getState(); if (newChain !== nodeStatus.netChain && nodeStatus.netChain !== DEFAULT_NETCHAIN) { - store.dispatch(showSnackbar(`Switched to ${newChain}. Please reload the page.`, 60000)); + store.dispatch(showSnackbar(`Switched to ${newChain}. The UI will reload now...`)); + setTimeout(() => { + window.location.reload(); + }, 0); // Fetch the new balances without notifying the user of any change BalancesProvider.get(store).fetchAllBalances({ From 29bed6ff691370cb5e6d0d76b7b44d64642909fd Mon Sep 17 00:00:00 2001 From: GitLab Build Bot Date: Mon, 13 Mar 2017 12:32:24 +0000 Subject: [PATCH 45/71] [ci skip] js-precompiled 20170313-122643 --- Cargo.lock | 2 +- js/package.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index f5e41f647..93d3d0ac7 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1706,7 +1706,7 @@ dependencies = [ [[package]] name = "parity-ui-precompiled" version = "1.4.0" -source = "git+https://github.com/ethcore/js-precompiled.git#d5eaa484594b30d0be267ba670400a840f749b08" +source = "git+https://github.com/ethcore/js-precompiled.git#24514f56ade650f54b97c2cff4e27d798b274e41" dependencies = [ "parity-dapps-glue 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", ] diff --git a/js/package.json b/js/package.json index ebc979344..b4ea09a50 100644 --- a/js/package.json +++ b/js/package.json @@ -1,6 +1,6 @@ { "name": "parity.js", - "version": "1.7.11", + "version": "1.7.12", "main": "release/index.js", "jsnext:main": "src/index.js", "author": "Parity Team ", From e0d554e0cae45c17646cf9c0c3cdd18978b3ec19 Mon Sep 17 00:00:00 2001 From: Arkadiy Paronyan Date: Mon, 13 Mar 2017 17:47:43 +0100 Subject: [PATCH 46/71] Recalculate receipt roots in close_and_lock (#4884) --- ethcore/res/ethereum/transition_test.json | 1 + ethcore/src/block.rs | 1 - 2 files changed, 1 insertion(+), 1 deletion(-) diff --git a/ethcore/res/ethereum/transition_test.json b/ethcore/res/ethereum/transition_test.json index aebea2b4f..1b502f087 100644 --- a/ethcore/res/ethereum/transition_test.json +++ b/ethcore/res/ethereum/transition_test.json @@ -139,6 +139,7 @@ } }, "params": { + "eip98Transition": "0x7fffffffffffffff", "accountStartNonce": "0x00", "maximumExtraDataSize": "0x20", "minGasLimit": "0x1388", diff --git a/ethcore/src/block.rs b/ethcore/src/block.rs index 67425ca86..14f3df799 100644 --- a/ethcore/src/block.rs +++ b/ethcore/src/block.rs @@ -553,7 +553,6 @@ pub fn enact( b.set_extra_data(header.extra_data().clone()).unwrap_or_else(|e| warn!("Couldn't set extradata: {}. Ignoring.", e)); b.set_uncles_hash(header.uncles_hash().clone()); b.set_transactions_root(header.transactions_root().clone()); - b.set_receipts_root(header.receipts_root().clone()); push_transactions(&mut b, transactions)?; for u in uncles { From 7525cb5ee4a83133c1d38ca4b14d7b43ac31a556 Mon Sep 17 00:00:00 2001 From: Jaco Greeff Date: Tue, 14 Mar 2017 11:23:50 +0100 Subject: [PATCH 47/71] trigger js-precompiled build (#4898) --- js/scripts/test.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/js/scripts/test.js b/js/scripts/test.js index f7bfd140f..cadf88a52 100644 --- a/js/scripts/test.js +++ b/js/scripts/test.js @@ -1 +1,2 @@ -// test script 7 +// test script 8 +// trigger rebuild on master 15 Mar 2017, 11:19 From 84fcefba1b8b28f6c9bb82263e608d5ade00a381 Mon Sep 17 00:00:00 2001 From: GitLab Build Bot Date: Tue, 14 Mar 2017 10:32:58 +0000 Subject: [PATCH 48/71] [ci skip] js-precompiled 20170314-103037 --- Cargo.lock | 2 +- js/package.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 93d3d0ac7..1a443a6fd 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1706,7 +1706,7 @@ dependencies = [ [[package]] name = "parity-ui-precompiled" version = "1.4.0" -source = "git+https://github.com/ethcore/js-precompiled.git#24514f56ade650f54b97c2cff4e27d798b274e41" +source = "git+https://github.com/ethcore/js-precompiled.git#fb3d34c729535009bbd0c97dba0dfb4e89a33a88" dependencies = [ "parity-dapps-glue 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", ] diff --git a/js/package.json b/js/package.json index b4ea09a50..bbd76cea7 100644 --- a/js/package.json +++ b/js/package.json @@ -1,6 +1,6 @@ { "name": "parity.js", - "version": "1.7.12", + "version": "1.7.13", "main": "release/index.js", "jsnext:main": "src/index.js", "author": "Parity Team ", From ef3569741c954be8d137974e4cbe54d3b9beed08 Mon Sep 17 00:00:00 2001 From: maciejhirsz Date: Tue, 14 Mar 2017 11:39:01 +0100 Subject: [PATCH 49/71] Spelling :) --- js/src/modals/CreateAccount/CreationType/creationType.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/js/src/modals/CreateAccount/CreationType/creationType.js b/js/src/modals/CreateAccount/CreationType/creationType.js index 9c0fb1b4f..392db7445 100644 --- a/js/src/modals/CreateAccount/CreationType/creationType.js +++ b/js/src/modals/CreateAccount/CreationType/creationType.js @@ -130,7 +130,7 @@ export default class CreationType extends Component {
{ this.renderList(createType) } From 43871e393c99d80f7a9bb6a70a7be3054aeaddba Mon Sep 17 00:00:00 2001 From: Arkadiy Paronyan Date: Tue, 14 Mar 2017 11:41:56 +0100 Subject: [PATCH 50/71] Additional kovan params (#4892) --- ethcore/res/ethereum/kovan.json | 3 ++- ethcore/src/client/client.rs | 2 +- ethcore/src/spec/spec.rs | 3 +++ ethcore/src/verification/canon_verifier.rs | 4 ++-- ethcore/src/verification/noop_verifier.rs | 2 +- ethcore/src/verification/verification.rs | 4 ++-- ethcore/src/verification/verifier.rs | 2 +- json/src/spec/params.rs | 3 +++ 8 files changed, 15 insertions(+), 8 deletions(-) diff --git a/ethcore/res/ethereum/kovan.json b/ethcore/res/ethereum/kovan.json index e9c059aaa..330b00c58 100644 --- a/ethcore/res/ethereum/kovan.json +++ b/ethcore/res/ethereum/kovan.json @@ -30,7 +30,8 @@ "params": { "maximumExtraDataSize": "0x20", "minGasLimit": "0x1388", - "networkID" : "0x2A" + "networkID" : "0x2A", + "validateReceipts" : false }, "genesis": { "seal": { diff --git a/ethcore/src/client/client.rs b/ethcore/src/client/client.rs index 5ddc83762..06889a538 100644 --- a/ethcore/src/client/client.rs +++ b/ethcore/src/client/client.rs @@ -393,7 +393,7 @@ impl Client { })?; // Final Verification - if let Err(e) = self.verifier.verify_block_final(header, locked_block.block().header()) { + if let Err(e) = self.verifier.verify_block_final(header, locked_block.block().header(), self.engine().params().validate_receipts) { warn!(target: "client", "Stage 4 block verification failed for #{} ({})\nError: {:?}", header.number(), header.hash(), e); return Err(()); } diff --git a/ethcore/src/spec/spec.rs b/ethcore/src/spec/spec.rs index 078908db4..3b7f84acf 100644 --- a/ethcore/src/spec/spec.rs +++ b/ethcore/src/spec/spec.rs @@ -55,6 +55,8 @@ pub struct CommonParams { pub fork_block: Option<(BlockNumber, H256)>, /// Number of first block where EIP-98 rules begin. pub eip98_transition: BlockNumber, + /// Validate block receipts root. + pub validate_receipts: bool, } impl From for CommonParams { @@ -68,6 +70,7 @@ impl From for CommonParams { min_gas_limit: p.min_gas_limit.into(), fork_block: if let (Some(n), Some(h)) = (p.fork_block, p.fork_hash) { Some((n.into(), h.into())) } else { None }, eip98_transition: p.eip98_transition.map_or(0, Into::into), + validate_receipts: p.validate_receipts.unwrap_or(true), } } } diff --git a/ethcore/src/verification/canon_verifier.rs b/ethcore/src/verification/canon_verifier.rs index 849f7caad..67d7e0e85 100644 --- a/ethcore/src/verification/canon_verifier.rs +++ b/ethcore/src/verification/canon_verifier.rs @@ -31,7 +31,7 @@ impl Verifier for CanonVerifier { verification::verify_block_family(header, bytes, engine, bc) } - fn verify_block_final(&self, expected: &Header, got: &Header) -> Result<(), Error> { - verification::verify_block_final(expected, got) + fn verify_block_final(&self, expected: &Header, got: &Header, receipts: bool) -> Result<(), Error> { + verification::verify_block_final(expected, got, receipts) } } diff --git a/ethcore/src/verification/noop_verifier.rs b/ethcore/src/verification/noop_verifier.rs index 2fcd877f5..b60dbed2e 100644 --- a/ethcore/src/verification/noop_verifier.rs +++ b/ethcore/src/verification/noop_verifier.rs @@ -31,7 +31,7 @@ impl Verifier for NoopVerifier { Ok(()) } - fn verify_block_final(&self, _expected: &Header, _got: &Header) -> Result<(), Error> { + fn verify_block_final(&self, _expected: &Header, _got: &Header, _receipts: bool) -> Result<(), Error> { Ok(()) } } diff --git a/ethcore/src/verification/verification.rs b/ethcore/src/verification/verification.rs index 34a4ccbd0..c2c932066 100644 --- a/ethcore/src/verification/verification.rs +++ b/ethcore/src/verification/verification.rs @@ -178,7 +178,7 @@ pub fn verify_block_family(header: &Header, bytes: &[u8], engine: &Engine, bc: & } /// Phase 4 verification. Check block information against transaction enactment results, -pub fn verify_block_final(expected: &Header, got: &Header) -> Result<(), Error> { +pub fn verify_block_final(expected: &Header, got: &Header, check_receipts: bool) -> Result<(), Error> { if expected.gas_used() != got.gas_used() { return Err(From::from(BlockError::InvalidGasUsed(Mismatch { expected: expected.gas_used().clone(), found: got.gas_used().clone() }))) } @@ -188,7 +188,7 @@ pub fn verify_block_final(expected: &Header, got: &Header) -> Result<(), Error> if expected.state_root() != got.state_root() { return Err(From::from(BlockError::InvalidStateRoot(Mismatch { expected: expected.state_root().clone(), found: got.state_root().clone() }))) } - if expected.receipts_root() != got.receipts_root() { + if check_receipts && expected.receipts_root() != got.receipts_root() { return Err(From::from(BlockError::InvalidReceiptsRoot(Mismatch { expected: expected.receipts_root().clone(), found: got.receipts_root().clone() }))) } Ok(()) diff --git a/ethcore/src/verification/verifier.rs b/ethcore/src/verification/verifier.rs index e5dabd392..9f0173003 100644 --- a/ethcore/src/verification/verifier.rs +++ b/ethcore/src/verification/verifier.rs @@ -26,5 +26,5 @@ pub trait Verifier: Send + Sync { /// Verify a block relative to its parent and uncles. fn verify_block_family(&self, header: &Header, bytes: &[u8], engine: &Engine, bc: &BlockProvider) -> Result<(), Error>; /// Do a final verification check for an enacted header vs its expected counterpart. - fn verify_block_final(&self, expected: &Header, got: &Header) -> Result<(), Error>; + fn verify_block_final(&self, expected: &Header, got: &Header, receipts: bool) -> Result<(), Error>; } diff --git a/json/src/spec/params.rs b/json/src/spec/params.rs index 26cedcf4a..1b2622316 100644 --- a/json/src/spec/params.rs +++ b/json/src/spec/params.rs @@ -53,6 +53,9 @@ pub struct Params { /// See `CommonParams` docs. #[serde(rename="eip98Transition")] pub eip98_transition: Option, + /// See `CommonParams` docs. + #[serde(rename="validateReceipts")] + pub validate_receipts: Option, } #[cfg(test)] From 43d391501e6ec4b1f77faf3a2ed4b23374185eff Mon Sep 17 00:00:00 2001 From: GitLab Build Bot Date: Tue, 14 Mar 2017 11:06:46 +0000 Subject: [PATCH 51/71] [ci skip] js-precompiled 20170314-110423 --- Cargo.lock | 2 +- js/package.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 1a443a6fd..813eb5239 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1706,7 +1706,7 @@ dependencies = [ [[package]] name = "parity-ui-precompiled" version = "1.4.0" -source = "git+https://github.com/ethcore/js-precompiled.git#fb3d34c729535009bbd0c97dba0dfb4e89a33a88" +source = "git+https://github.com/ethcore/js-precompiled.git#c9c37a8c4f83ae80c28d54a6e6b2e0d6e9c4e096" dependencies = [ "parity-dapps-glue 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", ] diff --git a/js/package.json b/js/package.json index bbd76cea7..fb6c6da7c 100644 --- a/js/package.json +++ b/js/package.json @@ -1,6 +1,6 @@ { "name": "parity.js", - "version": "1.7.13", + "version": "1.7.14", "main": "release/index.js", "jsnext:main": "src/index.js", "author": "Parity Team ", From 5031221369eebfb836f03f5562de5db65a6eb45a Mon Sep 17 00:00:00 2001 From: Arkadiy Paronyan Date: Tue, 14 Mar 2017 13:02:46 +0100 Subject: [PATCH 52/71] Removed libudev-dev --- scripts/deb-build.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/deb-build.sh b/scripts/deb-build.sh index ec11c056a..682cbcbbf 100644 --- a/scripts/deb-build.sh +++ b/scripts/deb-build.sh @@ -25,7 +25,7 @@ echo "Homepage: https://ethcore.io" >> $control echo "Vcs-Git: git://github.com/ethcore/parity.git" >> $control echo "Vcs-Browser: https://github.com/ethcore/parity" >> $control echo "Architecture: $1" >> $control -echo "Depends: libssl1.0.0 (>=1.0.0), libudev-dev" >> $control +echo "Depends: libssl1.0.0 (>=1.0.0)" >> $control echo "Description: Ethereum network client by Ethcore" >> $control #build .deb package From e12bde8e5a7b8d82e8ce3d815081bcb5787f7aba Mon Sep 17 00:00:00 2001 From: Jaco Greeff Date: Tue, 14 Mar 2017 13:03:44 +0100 Subject: [PATCH 53/71] Move background z-index to -1 (#4893) --- js/src/ui/Portal/portal.css | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/js/src/ui/Portal/portal.css b/js/src/ui/Portal/portal.css index 7d66c0a9a..2e6ff8370 100644 --- a/js/src/ui/Portal/portal.css +++ b/js/src/ui/Portal/portal.css @@ -51,7 +51,7 @@ $popoverZ: 3600; left: 0; right: 0; opacity: 0.25; - z-index: 0; + z-index: -1; } .overlay { From 7c45178076b1caf487fc1229f134627de95b66d3 Mon Sep 17 00:00:00 2001 From: Jaco Greeff Date: Tue, 14 Mar 2017 13:04:00 +0100 Subject: [PATCH 54/71] Add intitial max-width to sections (#4895) --- js/src/ui/SectionList/sectionList.css | 1 + 1 file changed, 1 insertion(+) diff --git a/js/src/ui/SectionList/sectionList.css b/js/src/ui/SectionList/sectionList.css index 14e8bffd1..4613371ad 100644 --- a/js/src/ui/SectionList/sectionList.css +++ b/js/src/ui/SectionList/sectionList.css @@ -44,6 +44,7 @@ $widthExpanded: 42%; box-sizing: border-box; display: flex; flex: 0 1 $widthNormal; + max-width: $widthNormal; opacity: 0.85; padding: 0.25em; From 2dca24cc28ab06fdab3a4b183ca59913022d0ae3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20Drwi=C4=99ga?= Date: Tue, 14 Mar 2017 13:04:32 +0100 Subject: [PATCH 55/71] Traces error handling (#4849) --- ethcore/src/client/error.rs | 10 ---- ethcore/src/trace/error.rs | 41 ------------- ethcore/src/trace/mod.rs | 2 - rpc/src/v1/helpers/errors.rs | 22 +++---- rpc/src/v1/helpers/fake_sign.rs | 43 ++++++++++++++ rpc/src/v1/helpers/mod.rs | 1 + rpc/src/v1/impls/eth.rs | 23 ++------ rpc/src/v1/impls/light/trace.rs | 12 ++-- rpc/src/v1/impls/traces.rs | 95 +++++++++++-------------------- rpc/src/v1/tests/mocked/parity.rs | 8 +-- rpc/src/v1/tests/mocked/traces.rs | 84 +++++++++++++++++++++++++-- rpc/src/v1/traits/traces.rs | 12 ++-- 12 files changed, 188 insertions(+), 165 deletions(-) delete mode 100644 ethcore/src/trace/error.rs create mode 100644 rpc/src/v1/helpers/fake_sign.rs diff --git a/ethcore/src/client/error.rs b/ethcore/src/client/error.rs index 9f22673b7..ff8b6d2ce 100644 --- a/ethcore/src/client/error.rs +++ b/ethcore/src/client/error.rs @@ -14,7 +14,6 @@ // You should have received a copy of the GNU General Public License // along with Parity. If not, see . -use trace::Error as TraceError; use util::UtilError; use std::fmt::{Display, Formatter, Error as FmtError}; @@ -23,8 +22,6 @@ use util::trie::TrieError; /// Client configuration errors. #[derive(Debug)] pub enum Error { - /// TraceDB configuration error. - Trace(TraceError), /// TrieDB-related error. Trie(TrieError), /// Database error @@ -33,12 +30,6 @@ pub enum Error { Util(UtilError), } -impl From for Error { - fn from(err: TraceError) -> Self { - Error::Trace(err) - } -} - impl From for Error { fn from(err: TrieError) -> Self { Error::Trie(err) @@ -60,7 +51,6 @@ impl From> for Error where Error: From { impl Display for Error { fn fmt(&self, f: &mut Formatter) -> Result<(), FmtError> { match *self { - Error::Trace(ref err) => write!(f, "{}", err), Error::Trie(ref err) => write!(f, "{}", err), Error::Util(ref err) => write!(f, "{}", err), Error::Database(ref s) => write!(f, "Database error: {}", s), diff --git a/ethcore/src/trace/error.rs b/ethcore/src/trace/error.rs deleted file mode 100644 index 081045d85..000000000 --- a/ethcore/src/trace/error.rs +++ /dev/null @@ -1,41 +0,0 @@ -// Copyright 2015-2017 Parity Technologies (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 . - -//! `TraceDB` errors. - -use std::fmt::{Display, Formatter, Error as FmtError}; - -const RESYNC_ERR: &'static str = -"Your current parity installation has synced without transaction tracing. -To use Parity with transaction tracing, you'll need to resync with tracing. -To do this, remove or move away your current database and restart parity. e.g.: - -> mv ~/.parity/906a34e69aec8c0d /tmp -> parity"; - -/// `TraceDB` errors. -#[derive(Debug)] -pub enum Error { - /// Returned when tracing is enabled, - /// but database does not contain traces of old transactions. - ResyncRequired, -} - -impl Display for Error { - fn fmt(&self, f: &mut Formatter) -> Result<(), FmtError> { - write!(f, "{}", RESYNC_ERR) - } -} diff --git a/ethcore/src/trace/mod.rs b/ethcore/src/trace/mod.rs index c63890ae9..2d13e3260 100644 --- a/ethcore/src/trace/mod.rs +++ b/ethcore/src/trace/mod.rs @@ -19,7 +19,6 @@ mod bloom; mod config; mod db; -mod error; mod executive_tracer; mod import; mod noop_tracer; @@ -28,7 +27,6 @@ pub use types::trace_types::{filter, flat, localized, trace}; pub use types::trace_types::error::Error as TraceError; pub use self::config::Config; pub use self::db::TraceDB; -pub use self::error::Error; pub use types::trace_types::trace::{VMTrace, VMOperation, VMExecutedOperation, MemoryDiff, StorageDiff}; pub use types::trace_types::flat::{FlatTrace, FlatTransactionTraces, FlatBlockTraces}; pub use self::noop_tracer::{NoopTracer, NoopVMTracer}; diff --git a/rpc/src/v1/helpers/errors.rs b/rpc/src/v1/helpers/errors.rs index 1f98b922d..e8fcee303 100644 --- a/rpc/src/v1/helpers/errors.rs +++ b/rpc/src/v1/helpers/errors.rs @@ -32,7 +32,6 @@ mod codes { pub const NO_WORK: i64 = -32001; pub const NO_AUTHOR: i64 = -32002; pub const NO_NEW_WORK: i64 = -32003; - pub const NOT_ENOUGH_DATA: i64 = -32006; pub const UNKNOWN_ERROR: i64 = -32009; pub const TRANSACTION_ERROR: i64 = -32010; pub const EXECUTION_ERROR: i64 = -32015; @@ -41,9 +40,6 @@ mod codes { pub const ACCOUNT_LOCKED: i64 = -32020; pub const PASSWORD_INVALID: i64 = -32021; pub const ACCOUNT_ERROR: i64 = -32023; - pub const SIGNER_DISABLED: i64 = -32030; - pub const DAPPS_DISABLED: i64 = -32031; - pub const NETWORK_DISABLED: i64 = -32035; pub const REQUEST_REJECTED: i64 = -32040; pub const REQUEST_REJECTED_LIMIT: i64 = -32041; pub const REQUEST_NOT_FOUND: i64 = -32042; @@ -174,9 +170,9 @@ pub fn no_author() -> Error { pub fn not_enough_data() -> Error { Error { - code: ErrorCode::ServerError(codes::NOT_ENOUGH_DATA), + code: ErrorCode::ServerError(codes::UNSUPPORTED_REQUEST), message: "The node does not have enough data to compute the given statistic.".into(), - data: None + data: None, } } @@ -190,25 +186,25 @@ pub fn token(e: String) -> Error { pub fn signer_disabled() -> Error { Error { - code: ErrorCode::ServerError(codes::SIGNER_DISABLED), + code: ErrorCode::ServerError(codes::UNSUPPORTED_REQUEST), message: "Trusted Signer is disabled. This API is not available.".into(), - data: None + data: None, } } pub fn dapps_disabled() -> Error { Error { - code: ErrorCode::ServerError(codes::DAPPS_DISABLED), + code: ErrorCode::ServerError(codes::UNSUPPORTED_REQUEST), message: "Dapps Server is disabled. This API is not available.".into(), - data: None + data: None, } } pub fn network_disabled() -> Error { Error { - code: ErrorCode::ServerError(codes::NETWORK_DISABLED), + code: ErrorCode::ServerError(codes::UNSUPPORTED_REQUEST), message: "Network is disabled or not yet up.".into(), - data: None + data: None, } } @@ -321,7 +317,7 @@ pub fn from_call_error(error: CallError) -> Error { pub fn unknown_block() -> Error { Error { - code: ErrorCode::ServerError(codes::UNSUPPORTED_REQUEST), + code: ErrorCode::InvalidParams, message: "Unknown block number".into(), data: None, } diff --git a/rpc/src/v1/helpers/fake_sign.rs b/rpc/src/v1/helpers/fake_sign.rs new file mode 100644 index 000000000..c8e835bb3 --- /dev/null +++ b/rpc/src/v1/helpers/fake_sign.rs @@ -0,0 +1,43 @@ +// Copyright 2015-2017 Parity Technologies (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 . + +use std::sync::Weak; +use ethcore::client::MiningBlockChainClient; +use ethcore::miner::MinerService; +use ethcore::transaction::{Transaction, SignedTransaction, Action}; + +use jsonrpc_core::Error; +use v1::helpers::CallRequest; +use v1::helpers::dispatch::default_gas_price; + +pub fn sign_call( + client: &Weak, + miner: &Weak, + request: CallRequest, +) -> Result { + let client = take_weak!(client); + let miner = take_weak!(miner); + let from = request.from.unwrap_or(0.into()); + + Ok(Transaction { + nonce: request.nonce.unwrap_or_else(|| client.latest_nonce(&from)), + action: request.to.map_or(Action::Create, Action::Call), + gas: request.gas.unwrap_or(50_000_000.into()), + gas_price: request.gas_price.unwrap_or_else(|| default_gas_price(&*client, &*miner)), + value: request.value.unwrap_or(0.into()), + data: request.data.map_or_else(Vec::new, |d| d.to_vec()) + }.fake_sign(from)) +} diff --git a/rpc/src/v1/helpers/mod.rs b/rpc/src/v1/helpers/mod.rs index 1d6bd14f3..ae8990cdc 100644 --- a/rpc/src/v1/helpers/mod.rs +++ b/rpc/src/v1/helpers/mod.rs @@ -19,6 +19,7 @@ pub mod errors; pub mod block_import; pub mod dispatch; +pub mod fake_sign; pub mod informant; mod network_settings; diff --git a/rpc/src/v1/impls/eth.rs b/rpc/src/v1/impls/eth.rs index 341ab13d8..52bc2de71 100644 --- a/rpc/src/v1/impls/eth.rs +++ b/rpc/src/v1/impls/eth.rs @@ -23,7 +23,7 @@ use std::sync::{Arc, Weak}; use futures::{self, future, BoxFuture, Future}; use rlp::{self, UntrustedRlp, View}; use time::get_time; -use util::{H160, H256, Address, U256, H64, Uint}; +use util::{H160, H256, Address, U256, H64}; use util::sha3::Hashable; use util::Mutex; @@ -36,14 +36,14 @@ use ethcore::filter::Filter as EthcoreFilter; use ethcore::header::{Header as BlockHeader, BlockNumber as EthBlockNumber}; use ethcore::log_entry::LogEntry; use ethcore::miner::{MinerService, ExternalMinerService}; -use ethcore::transaction::{Transaction as EthTransaction, SignedTransaction, Action}; +use ethcore::transaction::SignedTransaction; use ethcore::snapshot::SnapshotService; use ethsync::{SyncProvider}; use jsonrpc_core::Error; use jsonrpc_macros::Trailing; -use v1::helpers::{CallRequest as CRequest, errors, limit_logs}; +use v1::helpers::{errors, limit_logs, fake_sign}; use v1::helpers::dispatch::{Dispatcher, FullDispatcher, default_gas_price}; use v1::helpers::block_import::is_major_importing; use v1::traits::Eth; @@ -222,19 +222,6 @@ impl EthClient where Ok(Some(block)) } - fn sign_call(&self, request: CRequest) -> Result { - let (client, miner) = (take_weak!(self.client), take_weak!(self.miner)); - let from = request.from.unwrap_or(Address::zero()); - Ok(EthTransaction { - nonce: request.nonce.unwrap_or_else(|| client.latest_nonce(&from)), - action: request.to.map_or(Action::Create, Action::Call), - gas: request.gas.unwrap_or(U256::from(50_000_000)), - gas_price: request.gas_price.unwrap_or_else(|| default_gas_price(&*client, &*miner)), - value: request.value.unwrap_or_else(U256::zero), - data: request.data.map_or_else(Vec::new, |d| d.to_vec()) - }.fake_sign(from)) - } - fn dapp_accounts(&self, dapp: DappId) -> Result, Error> { let store = take_weak!(self.accounts); store @@ -654,7 +641,7 @@ impl Eth for EthClient where fn call(&self, request: CallRequest, num: Trailing) -> BoxFuture { let request = CallRequest::into(request); - let signed = match self.sign_call(request) { + let signed = match fake_sign::sign_call(&self.client, &self.miner, request) { Ok(signed) => signed, Err(e) => return future::err(e).boxed(), }; @@ -672,7 +659,7 @@ impl Eth for EthClient where fn estimate_gas(&self, request: CallRequest, num: Trailing) -> BoxFuture { let request = CallRequest::into(request); - let signed = match self.sign_call(request) { + let signed = match fake_sign::sign_call(&self.client, &self.miner, request) { Ok(signed) => signed, Err(e) => return future::err(e).boxed(), }; diff --git a/rpc/src/v1/impls/light/trace.rs b/rpc/src/v1/impls/light/trace.rs index 5f785ed1b..00d19dc24 100644 --- a/rpc/src/v1/impls/light/trace.rs +++ b/rpc/src/v1/impls/light/trace.rs @@ -27,15 +27,15 @@ use v1::types::{TraceFilter, LocalizedTrace, BlockNumber, Index, CallRequest, By pub struct TracesClient; impl Traces for TracesClient { - fn filter(&self, _filter: TraceFilter) -> Result, Error> { + fn filter(&self, _filter: TraceFilter) -> Result>, Error> { Err(errors::light_unimplemented(None)) } - fn block_traces(&self, _block_number: BlockNumber) -> Result, Error> { + fn block_traces(&self, _block_number: BlockNumber) -> Result>, Error> { Err(errors::light_unimplemented(None)) } - fn transaction_traces(&self, _transaction_hash: H256) -> Result, Error> { + fn transaction_traces(&self, _transaction_hash: H256) -> Result>, Error> { Err(errors::light_unimplemented(None)) } @@ -43,15 +43,15 @@ impl Traces for TracesClient { Err(errors::light_unimplemented(None)) } - fn call(&self, _request: CallRequest, _flags: Vec, _block: Trailing) -> Result, Error> { + fn call(&self, _request: CallRequest, _flags: Vec, _block: Trailing) -> Result { Err(errors::light_unimplemented(None)) } - fn raw_transaction(&self, _raw_transaction: Bytes, _flags: Vec, _block: Trailing) -> Result, Error> { + fn raw_transaction(&self, _raw_transaction: Bytes, _flags: Vec, _block: Trailing) -> Result { Err(errors::light_unimplemented(None)) } - fn replay_transaction(&self, _transaction_hash: H256, _flags: Vec) -> Result, Error> { + fn replay_transaction(&self, _transaction_hash: H256, _flags: Vec) -> Result { Err(errors::light_unimplemented(None)) } } diff --git a/rpc/src/v1/impls/traces.rs b/rpc/src/v1/impls/traces.rs index 9fe92518b..b4be40a56 100644 --- a/rpc/src/v1/impls/traces.rs +++ b/rpc/src/v1/impls/traces.rs @@ -19,14 +19,14 @@ use std::sync::{Weak, Arc}; use rlp::{UntrustedRlp, View}; -use ethcore::client::{BlockChainClient, CallAnalytics, TransactionId, TraceId}; +use ethcore::client::{MiningBlockChainClient, CallAnalytics, TransactionId, TraceId}; use ethcore::miner::MinerService; -use ethcore::transaction::{Transaction as EthTransaction, SignedTransaction, Action}; +use ethcore::transaction::SignedTransaction; use jsonrpc_core::Error; use jsonrpc_macros::Trailing; use v1::traits::Traces; -use v1::helpers::{errors, CallRequest as CRequest}; +use v1::helpers::{errors, fake_sign}; use v1::types::{TraceFilter, LocalizedTrace, BlockNumber, Index, CallRequest, Bytes, TraceResults, H256}; fn to_call_analytics(flags: Vec) -> CallAnalytics { @@ -38,12 +38,12 @@ fn to_call_analytics(flags: Vec) -> CallAnalytics { } /// Traces api implementation. -pub struct TracesClient where C: BlockChainClient, M: MinerService { +pub struct TracesClient { client: Weak, miner: Weak, } -impl TracesClient where C: BlockChainClient, M: MinerService { +impl TracesClient { /// Creates new Traces client. pub fn new(client: &Arc, miner: &Arc) -> Self { TracesClient { @@ -51,86 +51,59 @@ impl TracesClient where C: BlockChainClient, M: MinerService { miner: Arc::downgrade(miner), } } - - // TODO: share with eth.rs - fn sign_call(&self, request: CRequest) -> Result { - let client = take_weak!(self.client); - let miner = take_weak!(self.miner); - let from = request.from.unwrap_or(0.into()); - Ok(EthTransaction { - nonce: request.nonce.unwrap_or_else(|| client.latest_nonce(&from)), - action: request.to.map_or(Action::Create, Action::Call), - gas: request.gas.unwrap_or(50_000_000.into()), - gas_price: request.gas_price.unwrap_or_else(|| miner.sensible_gas_price()), - value: request.value.unwrap_or(0.into()), - data: request.data.map_or_else(Vec::new, |d| d.to_vec()) - }.fake_sign(from)) - } } -impl Traces for TracesClient where C: BlockChainClient + 'static, M: MinerService + 'static { - fn filter(&self, filter: TraceFilter) -> Result, Error> { - let client = take_weak!(self.client); - let traces = client.filter_traces(filter.into()); - let traces = traces.map_or_else(Vec::new, |traces| traces.into_iter().map(LocalizedTrace::from).collect()); - Ok(traces) +impl Traces for TracesClient where C: MiningBlockChainClient + 'static, M: MinerService + 'static { + fn filter(&self, filter: TraceFilter) -> Result>, Error> { + Ok(take_weak!(self.client).filter_traces(filter.into()) + .map(|traces| traces.into_iter().map(LocalizedTrace::from).collect())) } - fn block_traces(&self, block_number: BlockNumber) -> Result, Error> { - let client = take_weak!(self.client); - let traces = client.block_traces(block_number.into()); - let traces = traces.map_or_else(Vec::new, |traces| traces.into_iter().map(LocalizedTrace::from).collect()); - Ok(traces) + fn block_traces(&self, block_number: BlockNumber) -> Result>, Error> { + Ok(take_weak!(self.client).block_traces(block_number.into()) + .map(|traces| traces.into_iter().map(LocalizedTrace::from).collect())) } - fn transaction_traces(&self, transaction_hash: H256) -> Result, Error> { - let client = take_weak!(self.client); - let traces = client.transaction_traces(TransactionId::Hash(transaction_hash.into())); - let traces = traces.map_or_else(Vec::new, |traces| traces.into_iter().map(LocalizedTrace::from).collect()); - Ok(traces) + fn transaction_traces(&self, transaction_hash: H256) -> Result>, Error> { + Ok(take_weak!(self.client).transaction_traces(TransactionId::Hash(transaction_hash.into())) + .map(|traces| traces.into_iter().map(LocalizedTrace::from).collect())) } fn trace(&self, transaction_hash: H256, address: Vec) -> Result, Error> { - let client = take_weak!(self.client); let id = TraceId { transaction: TransactionId::Hash(transaction_hash.into()), address: address.into_iter().map(|i| i.value()).collect() }; - let trace = client.trace(id); - let trace = trace.map(LocalizedTrace::from); - Ok(trace) + Ok(take_weak!(self.client).trace(id) + .map(LocalizedTrace::from)) } - fn call(&self, request: CallRequest, flags: Vec, block: Trailing) -> Result, Error> { + fn call(&self, request: CallRequest, flags: Vec, block: Trailing) -> Result { let block = block.0; let request = CallRequest::into(request); - let signed = self.sign_call(request)?; - Ok(match take_weak!(self.client).call(&signed, block.into(), to_call_analytics(flags)) { - Ok(e) => Some(TraceResults::from(e)), - _ => None, - }) + let signed = fake_sign::sign_call(&self.client, &self.miner, request)?; + + take_weak!(self.client).call(&signed, block.into(), to_call_analytics(flags)) + .map(TraceResults::from) + .map_err(errors::from_call_error) } - fn raw_transaction(&self, raw_transaction: Bytes, flags: Vec, block: Trailing) -> Result, Error> { + fn raw_transaction(&self, raw_transaction: Bytes, flags: Vec, block: Trailing) -> Result { let block = block.0; - UntrustedRlp::new(&raw_transaction.into_vec()).as_val() - .map_err(|e| errors::invalid_params("Transaction is not valid RLP", e)) - .and_then(|tx| SignedTransaction::new(tx).map_err(errors::from_transaction_error)) - .and_then(|signed| { - Ok(match take_weak!(self.client).call(&signed, block.into(), to_call_analytics(flags)) { - Ok(e) => Some(TraceResults::from(e)), - _ => None, - }) - }) + let tx = UntrustedRlp::new(&raw_transaction.into_vec()).as_val().map_err(|e| errors::invalid_params("Transaction is not valid RLP", e))?; + let signed = SignedTransaction::new(tx).map_err(errors::from_transaction_error)?; + + take_weak!(self.client).call(&signed, block.into(), to_call_analytics(flags)) + .map(TraceResults::from) + .map_err(errors::from_call_error) } - fn replay_transaction(&self, transaction_hash: H256, flags: Vec) -> Result, Error> { - Ok(match take_weak!(self.client).replay(TransactionId::Hash(transaction_hash.into()), to_call_analytics(flags)) { - Ok(e) => Some(TraceResults::from(e)), - _ => None, - }) + fn replay_transaction(&self, transaction_hash: H256, flags: Vec) -> Result { + take_weak!(self.client).replay(TransactionId::Hash(transaction_hash.into()), to_call_analytics(flags)) + .map(TraceResults::from) + .map_err(errors::from_call_error) } } diff --git a/rpc/src/v1/tests/mocked/parity.rs b/rpc/src/v1/tests/mocked/parity.rs index a53a86447..59cde8594 100644 --- a/rpc/src/v1/tests/mocked/parity.rs +++ b/rpc/src/v1/tests/mocked/parity.rs @@ -357,7 +357,7 @@ fn rpc_parity_unsigned_transactions_count_when_signer_disabled() { let io = deps.default_client(); 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":-32000,"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())); } @@ -393,7 +393,7 @@ fn rpc_parity_signer_port() { // when let request = r#"{"jsonrpc": "2.0", "method": "parity_signerPort", "params": [], "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":-32000,"message":"Trusted Signer is disabled. This API is not available.","data":null},"id":1}"#; // then assert_eq!(io1.handle_request_sync(request), Some(response1.to_owned())); @@ -411,7 +411,7 @@ fn rpc_parity_dapps_port() { // when let request = r#"{"jsonrpc": "2.0", "method": "parity_dappsPort", "params": [], "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":-32000,"message":"Dapps Server is disabled. This API is not available.","data":null},"id":1}"#; // then assert_eq!(io1.handle_request_sync(request), Some(response1.to_owned())); @@ -429,7 +429,7 @@ fn rpc_parity_dapps_interface() { // when let request = r#"{"jsonrpc": "2.0", "method": "parity_dappsInterface", "params": [], "id": 1}"#; let response1 = r#"{"jsonrpc":"2.0","result":"127.0.0.1","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":-32000,"message":"Dapps Server is disabled. This API is not available.","data":null},"id":1}"#; // then assert_eq!(io1.handle_request_sync(request), Some(response1.to_owned())); diff --git a/rpc/src/v1/tests/mocked/traces.rs b/rpc/src/v1/tests/mocked/traces.rs index 1d7c36a2b..83a266d2f 100644 --- a/rpc/src/v1/tests/mocked/traces.rs +++ b/rpc/src/v1/tests/mocked/traces.rs @@ -16,17 +16,17 @@ use std::sync::Arc; -use ethcore::executed::{CallType, Executed}; +use ethcore::executed::{CallType, Executed, CallError}; use ethcore::trace::trace::{Action, Res, Call}; use ethcore::trace::LocalizedTrace; -use ethcore::client::{TestBlockChainClient}; +use ethcore::client::TestBlockChainClient; use jsonrpc_core::IoHandler; use v1::tests::helpers::{TestMinerService}; use v1::{Traces, TracesClient}; struct Tester { - _client: Arc, + client: Arc, _miner: Arc, io: IoHandler, } @@ -69,7 +69,7 @@ fn io() -> Tester { io.extend_with(traces.to_delegate()); Tester { - _client: client, + client: client, _miner: miner, io: io, } @@ -85,6 +85,17 @@ fn rpc_trace_filter() { assert_eq!(tester.io.handle_request_sync(request), Some(response.to_owned())); } +#[test] +fn rpc_trace_filter_missing_trace() { + let tester = io(); + *tester.client.traces.write() = None; + + let request = r#"{"jsonrpc":"2.0","method":"trace_filter","params": [{}],"id":1}"#; + let response = r#"{"jsonrpc":"2.0","result":null,"id":1}"#; + + assert_eq!(tester.io.handle_request_sync(request), Some(response.to_owned())); +} + #[test] fn rpc_trace_block() { let tester = io(); @@ -95,6 +106,17 @@ fn rpc_trace_block() { assert_eq!(tester.io.handle_request_sync(request), Some(response.to_owned())); } +#[test] +fn rpc_trace_block_missing_traces() { + let tester = io(); + *tester.client.traces.write() = None; + + let request = r#"{"jsonrpc":"2.0","method":"trace_block","params": ["0x10"],"id":1}"#; + let response = r#"{"jsonrpc":"2.0","result":null,"id":1}"#; + + assert_eq!(tester.io.handle_request_sync(request), Some(response.to_owned())); +} + #[test] fn rpc_trace_transaction() { let tester = io(); @@ -105,6 +127,17 @@ fn rpc_trace_transaction() { assert_eq!(tester.io.handle_request_sync(request), Some(response.to_owned())); } +#[test] +fn rpc_trace_transaction_missing_trace() { + let tester = io(); + *tester.client.traces.write() = None; + + let request = r#"{"jsonrpc":"2.0","method":"trace_transaction","params":["0x0000000000000000000000000000000000000000000000000000000000000005"],"id":1}"#; + let response = r#"{"jsonrpc":"2.0","result":null,"id":1}"#; + + assert_eq!(tester.io.handle_request_sync(request), Some(response.to_owned())); +} + #[test] fn rpc_trace_get() { let tester = io(); @@ -115,6 +148,16 @@ fn rpc_trace_get() { assert_eq!(tester.io.handle_request_sync(request), Some(response.to_owned())); } +#[test] +fn rpc_trace_get_missing_trace() { + let tester = io(); + *tester.client.traces.write() = None; + + let request = r#"{"jsonrpc":"2.0","method":"trace_get","params":["0x0000000000000000000000000000000000000000000000000000000000000005", ["0","0","0"]],"id":1}"#; + let response = r#"{"jsonrpc":"2.0","result":null,"id":1}"#; + assert_eq!(tester.io.handle_request_sync(request), Some(response.to_owned())); +} + #[test] fn rpc_trace_call() { let tester = io(); @@ -125,6 +168,17 @@ fn rpc_trace_call() { assert_eq!(tester.io.handle_request_sync(request), Some(response.to_owned())); } +#[test] +fn rpc_trace_call_state_pruned() { + let tester = io(); + *tester.client.execution_result.write() = Some(Err(CallError::StatePruned)); + + let request = r#"{"jsonrpc":"2.0","method":"trace_call","params":[{}, ["stateDiff", "vmTrace", "trace"]],"id":1}"#; + let response = r#"{"jsonrpc":"2.0","error":{"code":-32000,"message":"This request is not supported because your node is running with state pruning. Run with --pruning=archive.","data":null},"id":1}"#; + + assert_eq!(tester.io.handle_request_sync(request), Some(response.to_owned())); +} + #[test] fn rpc_trace_raw_transaction() { let tester = io(); @@ -135,6 +189,17 @@ fn rpc_trace_raw_transaction() { assert_eq!(tester.io.handle_request_sync(request), Some(response.to_owned())); } +#[test] +fn rpc_trace_raw_transaction_state_pruned() { + let tester = io(); + *tester.client.execution_result.write() = Some(Err(CallError::StatePruned)); + + let request = r#"{"jsonrpc":"2.0","method":"trace_rawTransaction","params":["0xf869018609184e72a0008276c094d46e8dd67c5d32be8058bb8eb970870f07244567849184e72a801ba0617f39c1a107b63302449c476d96a6cb17a5842fc98ff0c5bcf4d5c4d8166b95a009fdb6097c6196b9bbafc3a59f02f38d91baeef23d0c60a8e4f23c7714cea3a9", ["stateDiff", "vmTrace", "trace"]],"id":1}"#; + let response = r#"{"jsonrpc":"2.0","error":{"code":-32000,"message":"This request is not supported because your node is running with state pruning. Run with --pruning=archive.","data":null},"id":1}"#; + + assert_eq!(tester.io.handle_request_sync(request), Some(response.to_owned())); +} + #[test] fn rpc_trace_replay_transaction() { let tester = io(); @@ -144,3 +209,14 @@ fn rpc_trace_replay_transaction() { assert_eq!(tester.io.handle_request_sync(request), Some(response.to_owned())); } + +#[test] +fn rpc_trace_replay_transaction_state_pruned() { + let tester = io(); + *tester.client.execution_result.write() = Some(Err(CallError::StatePruned)); + + let request = r#"{"jsonrpc":"2.0","method":"trace_replayTransaction","params":["0x0000000000000000000000000000000000000000000000000000000000000005", ["trace", "stateDiff", "vmTrace"]],"id":1}"#; + let response = r#"{"jsonrpc":"2.0","error":{"code":-32000,"message":"This request is not supported because your node is running with state pruning. Run with --pruning=archive.","data":null},"id":1}"#; + + assert_eq!(tester.io.handle_request_sync(request), Some(response.to_owned())); +} diff --git a/rpc/src/v1/traits/traces.rs b/rpc/src/v1/traits/traces.rs index fa2b14cf3..64b37ac1d 100644 --- a/rpc/src/v1/traits/traces.rs +++ b/rpc/src/v1/traits/traces.rs @@ -25,7 +25,7 @@ build_rpc_trait! { pub trait Traces { /// Returns traces matching given filter. #[rpc(name = "trace_filter")] - fn filter(&self, TraceFilter) -> Result, Error>; + fn filter(&self, TraceFilter) -> Result>, Error>; /// Returns transaction trace at given index. #[rpc(name = "trace_get")] @@ -33,22 +33,22 @@ build_rpc_trait! { /// Returns all traces of given transaction. #[rpc(name = "trace_transaction")] - fn transaction_traces(&self, H256) -> Result, Error>; + fn transaction_traces(&self, H256) -> Result>, Error>; /// Returns all traces produced at given block. #[rpc(name = "trace_block")] - fn block_traces(&self, BlockNumber) -> Result, Error>; + fn block_traces(&self, BlockNumber) -> Result>, Error>; /// Executes the given call and returns a number of possible traces for it. #[rpc(name = "trace_call")] - fn call(&self, CallRequest, Vec, Trailing) -> Result, Error>; + fn call(&self, CallRequest, Vec, Trailing) -> Result; /// Executes the given raw transaction and returns a number of possible traces for it. #[rpc(name = "trace_rawTransaction")] - fn raw_transaction(&self, Bytes, Vec, Trailing) -> Result, Error>; + fn raw_transaction(&self, Bytes, Vec, Trailing) -> Result; /// Executes the transaction with the given hash and returns a number of possible traces for it. #[rpc(name = "trace_replayTransaction")] - fn replay_transaction(&self, H256, Vec) -> Result, Error>; + fn replay_transaction(&self, H256, Vec) -> Result; } } From 57770ce84c71b7578885e7f00b0900523876ac2d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20Drwi=C4=99ga?= Date: Tue, 14 Mar 2017 13:08:55 +0100 Subject: [PATCH 56/71] Renaming evm binary to avoid conflicts. (#4899) --- .gitlab-ci.yml | 18 +++++++++--------- evmbin/Cargo.toml | 4 ++-- 2 files changed, 11 insertions(+), 11 deletions(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index f0d3fb682..49f967761 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -26,14 +26,14 @@ linux-stable: - cargo build -j $(nproc) --release -p ethstore - cargo build -j $(nproc) --release -p ethkey - strip target/release/parity - - strip target/release/evm + - strip target/release/parity-evm - strip target/release/ethstore - strip target/release/ethkey - export SHA3=$(target/release/parity tools hash target/release/parity) - md5sum target/release/parity > parity.md5 - sh scripts/deb-build.sh amd64 - cp target/release/parity deb/usr/bin/parity - - cp target/release/evm deb/usr/bin/evm + - cp target/release/parity-evm deb/usr/bin/parity-evm - cp target/release/ethstore deb/usr/bin/ethstore - cp target/release/ethkey deb/usr/bin/ethkey - export VER=$(grep -m 1 version Cargo.toml | awk '{print $3}' | tr -d '"' | tr -d "\n") @@ -55,9 +55,9 @@ linux-stable: artifacts: paths: - target/release/parity - - target/release/parity/evmbin - - target/release/parity/ethstore - - target/release/parity/ethkey + - target/release/parity-evm + - target/release/ethstore + - target/release/ethkey name: "stable-x86_64-unknown-linux-gnu_parity" linux-stable-debian: stage: build @@ -73,14 +73,14 @@ linux-stable-debian: - cargo build -j $(nproc) --release -p ethstore - cargo build -j $(nproc) --release -p ethkey - strip target/release/parity - - strip target/release/evm + - strip target/release/parity-evm - strip target/release/ethstore - strip target/release/ethkey - export SHA3=$(target/release/parity tools hash target/release/parity) - md5sum target/release/parity > parity.md5 - sh scripts/deb-build.sh amd64 - cp target/release/parity deb/usr/bin/parity - - cp target/release/evm deb/usr/bin/evm + - cp target/release/parity-evm deb/usr/bin/parity-evm - cp target/release/ethstore deb/usr/bin/ethstore - cp target/release/ethkey deb/usr/bin/ethkey - export VER=$(grep -m 1 version Cargo.toml | awk '{print $3}' | tr -d '"' | tr -d "\n") @@ -503,7 +503,7 @@ docker-build: - sh scripts/docker-build.sh $DOCKER_TAG tags: - docker -test-coverage: +test-coverage: stage: test only: - coverage @@ -511,7 +511,7 @@ test-coverage: - git submodule update --init --recursive - scripts/cov.sh - COVERAGE=$(grep -Po 'covered":.*?[^\\]"' target/kcov/index.json | grep "[0-9]*\.[0-9]" -o) - - echo "Coverage:" $COVERAGE + - echo "Coverage:" $COVERAGE tags: - kcov allow_failure: true diff --git a/evmbin/Cargo.toml b/evmbin/Cargo.toml index 98193a5c3..7f671d384 100644 --- a/evmbin/Cargo.toml +++ b/evmbin/Cargo.toml @@ -5,11 +5,11 @@ version = "0.1.0" authors = ["Parity Technologies "] [lib] -name = "evm" +name = "evmbin" path = "./src/main.rs" [[bin]] -name = "evm" +name = "parity-evm" path = "./src/main.rs" [dependencies] From 1959f0ae125d401e6b0e33db3c26fdbd577f6388 Mon Sep 17 00:00:00 2001 From: "Denis S. Soldatov aka General-Beck" Date: Tue, 14 Mar 2017 20:21:51 +0300 Subject: [PATCH 57/71] fix docker-build [ci skip] --- scripts/docker-build.sh | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/scripts/docker-build.sh b/scripts/docker-build.sh index b9724cd2f..01bffc48f 100644 --- a/scripts/docker-build.sh +++ b/scripts/docker-build.sh @@ -1,4 +1,5 @@ #!/bin/bash cd docker/hub -docker build --build-arg BUILD_TAG=$1 --no-cache=true --tag ethcore/parity:$1 . +if [ "$1" == "latest" ]; then DOCKER_BUILD_TAG="beta-release"; fi +docker build --build-arg BUILD_TAG=$DOCKER_BUILD_TAG --no-cache=true --tag ethcore/parity:$1 . docker push ethcore/parity:$1 From b27138e93fef8246ab4923f46311ead986f44afa Mon Sep 17 00:00:00 2001 From: Marek Kotewicz Date: Wed, 15 Mar 2017 12:13:19 +0100 Subject: [PATCH 58/71] Updated gcc crate to remove one of duplicated dependencies (#4909) --- Cargo.lock | 42 +++++++++++++++++------------------------- Cargo.toml | 2 +- ethcore/Cargo.toml | 2 +- 3 files changed, 19 insertions(+), 27 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 813eb5239..ac7f7f259 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -31,7 +31,7 @@ dependencies = [ "isatty 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "jsonrpc-core 6.0.0 (git+https://github.com/ethcore/jsonrpc.git?branch=parity-1.6)", "log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", - "num_cpus 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", + "num_cpus 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "number_prefix 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)", "parity-hash-fetch 1.7.0", "parity-ipfs-api 1.7.0", @@ -347,7 +347,7 @@ version = "0.5.6" source = "git+https://github.com/ethcore/rust-secp256k1#98ad9b9ecae44a563efdd64273bcebc6b4ed81c6" dependencies = [ "arrayvec 0.3.16 (registry+https://github.com/rust-lang/crates.io-index)", - "gcc 0.3.35 (registry+https://github.com/rust-lang/crates.io-index)", + "gcc 0.3.43 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.16 (registry+https://github.com/rust-lang/crates.io-index)", "rand 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-serialize 0.3.19 (registry+https://github.com/rust-lang/crates.io-index)", @@ -405,7 +405,7 @@ dependencies = [ "linked-hash-map 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", "lru-cache 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "num_cpus 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", + "num_cpus 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "rand 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)", "rlp 0.1.0", "rust-crypto 0.2.36 (registry+https://github.com/rust-lang/crates.io-index)", @@ -886,10 +886,10 @@ dependencies = [ [[package]] name = "gcc" -version = "0.3.35" +version = "0.3.43" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "rayon 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", + "rayon 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -936,7 +936,7 @@ name = "hidapi" version = "0.3.1" source = "git+https://github.com/ethcore/hidapi-rs#9a127c1dca7e327e4fdd428406a76c9f5ef48563" dependencies = [ - "gcc 0.3.35 (registry+https://github.com/rust-lang/crates.io-index)", + "gcc 0.3.43 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.16 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1191,7 +1191,7 @@ name = "libusb-sys" version = "0.2.3" source = "git+https://github.com/ethcore/libusb-sys#c10b1180646c9dc3f23a9b6bb825abcd3b7487ce" dependencies = [ - "gcc 0.3.35 (registry+https://github.com/rust-lang/crates.io-index)", + "gcc 0.3.43 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.16 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1255,7 +1255,7 @@ name = "miniz-sys" version = "0.1.7" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "gcc 0.3.35 (registry+https://github.com/rust-lang/crates.io-index)", + "gcc 0.3.43 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.16 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1390,7 +1390,7 @@ name = "nanomsg-sys" version = "0.5.0" source = "git+https://github.com/ethcore/nanomsg.rs.git#c40fe442c9afaea5b38009a3d992ca044dcceb00" dependencies = [ - "gcc 0.3.35 (registry+https://github.com/rust-lang/crates.io-index)", + "gcc 0.3.43 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.16 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1532,14 +1532,6 @@ name = "num-traits" version = "0.1.32" source = "registry+https://github.com/rust-lang/crates.io-index" -[[package]] -name = "num_cpus" -version = "0.2.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "libc 0.2.16 (registry+https://github.com/rust-lang/crates.io-index)", -] - [[package]] name = "num_cpus" version = "1.2.0" @@ -1877,11 +1869,12 @@ dependencies = [ [[package]] name = "rayon" -version = "0.4.2" +version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "deque 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", - "num_cpus 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.16 (registry+https://github.com/rust-lang/crates.io-index)", + "num_cpus 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "rand 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1949,7 +1942,7 @@ name = "rocksdb-sys" version = "0.3.0" source = "git+https://github.com/ethcore/rust-rocksdb#64c63ccbe1f62c2e2b39262486f9ba813793af58" dependencies = [ - "gcc 0.3.35 (registry+https://github.com/rust-lang/crates.io-index)", + "gcc 0.3.43 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.16 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -2004,7 +1997,7 @@ name = "rust-crypto" version = "0.2.36" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "gcc 0.3.35 (registry+https://github.com/rust-lang/crates.io-index)", + "gcc 0.3.43 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.16 (registry+https://github.com/rust-lang/crates.io-index)", "rand 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-serialize 0.3.19 (registry+https://github.com/rust-lang/crates.io-index)", @@ -2156,7 +2149,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" name = "sha3" version = "0.1.0" dependencies = [ - "gcc 0.3.35 (registry+https://github.com/rust-lang/crates.io-index)", + "gcc 0.3.43 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -2608,7 +2601,7 @@ dependencies = [ "checksum flate2 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)" = "3eeb481e957304178d2e782f2da1257f1434dfecbae883bafb61ada2a9fea3bb" "checksum futures 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)" = "c1913eb7083840b1bbcbf9631b7fda55eaf35fe7ead13cca034e8946f9e2bc41" "checksum futures-cpupool 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "bb982bb25cd8fa5da6a8eb3a460354c984ff1113da82bcb4f0b0862b5795db82" -"checksum gcc 0.3.35 (registry+https://github.com/rust-lang/crates.io-index)" = "91ecd03771effb0c968fd6950b37e89476a578aaf1c70297d8e92b6516ec3312" +"checksum gcc 0.3.43 (registry+https://github.com/rust-lang/crates.io-index)" = "c07c758b972368e703a562686adb39125707cc1ef3399da8c019fc6c2498a75d" "checksum gdi32-sys 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "0912515a8ff24ba900422ecda800b52f4016a56251922d397c576bf92c690518" "checksum glob 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)" = "8be18de09a56b60ed0edf84bc9df007e30040691af7acd1c41874faac5895bfb" "checksum hamming 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "65043da274378d68241eb9a8f8f8aa54e349136f7b8e12f63e3ef44043cc30e1" @@ -2672,7 +2665,6 @@ dependencies = [ "checksum num-iter 0.1.32 (registry+https://github.com/rust-lang/crates.io-index)" = "287a1c9969a847055e1122ec0ea7a5c5d6f72aad97934e131c83d5c08ab4e45c" "checksum num-rational 0.1.32 (registry+https://github.com/rust-lang/crates.io-index)" = "48cdcc9ff4ae2a8296805ac15af88b3d88ce62128ded0cb74ffb63a587502a84" "checksum num-traits 0.1.32 (registry+https://github.com/rust-lang/crates.io-index)" = "51eab148f171aefad295f8cece636fc488b9b392ef544da31ea4b8ef6b9e9c39" -"checksum num_cpus 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)" = "51fedae97a05f7353612fe017ab705a37e6db8f4d67c5c6fe739a9e70d6eed09" "checksum num_cpus 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "55aabf4e2d6271a2e4e4c0f2ea1f5b07cc589cc1a9e9213013b54a76678ca4f3" "checksum number_prefix 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)" = "084d05f4bf60621a9ac9bde941a410df548f4de9545f06e5ee9d3aef4b97cd77" "checksum odds 0.2.12 (registry+https://github.com/rust-lang/crates.io-index)" = "b28c06e81b0f789122d415d6394b5fe849bde8067469f4c2980d3cdc10c78ec1" @@ -2702,7 +2694,7 @@ dependencies = [ "checksum quine-mc_cluskey 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "a6683b0e23d80813b1a535841f0048c1537d3f86d63c999e8373b39a9b0eb74a" "checksum quote 0.3.10 (registry+https://github.com/rust-lang/crates.io-index)" = "6732e32663c9c271bfc7c1823486b471f18c47a2dbf87c066897b7b51afc83be" "checksum rand 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)" = "2791d88c6defac799c3f20d74f094ca33b9332612d9aef9078519c82e4fe04a5" -"checksum rayon 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "655df67c314c30fa3055a365eae276eb88aa4f3413a352a1ab32c1320eda41ea" +"checksum rayon 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "50c575b58c2b109e2fbc181820cbe177474f35610ff9e357dc75f6bac854ffbf" "checksum regex 0.1.68 (registry+https://github.com/rust-lang/crates.io-index)" = "b4329b8928a284580a1c63ec9d846b12f6d3472317243ff7077aff11f23f2b29" "checksum regex-syntax 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "841591b1e05609a643e3b4d0045fce04f701daba7151ddcd3ad47b080693d5a9" "checksum reqwest 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3bef9ed8fdfcc30947d6b774938dc0c3f369a474efe440df2c7f278180b2d2e6" diff --git a/Cargo.toml b/Cargo.toml index 2a01d2c8e..7ff9b0521 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -11,7 +11,7 @@ env_logger = "0.3" rustc-serialize = "0.3" docopt = "0.6" time = "0.1" -num_cpus = "0.2" +num_cpus = "1.2" number_prefix = "0.2" rpassword = "0.2.1" semver = "0.5" diff --git a/ethcore/Cargo.toml b/ethcore/Cargo.toml index 64010fadf..39bf20070 100644 --- a/ethcore/Cargo.toml +++ b/ethcore/Cargo.toml @@ -15,7 +15,7 @@ log = "0.3" env_logger = "0.3" rustc-serialize = "0.3" rust-crypto = "0.2.34" -num_cpus = "0.2" +num_cpus = "1.2" crossbeam = "0.2.9" lazy_static = "0.2" bloomchain = "0.1" From e4c61a5fab8c421922afd1784c1bb1c870da1a05 Mon Sep 17 00:00:00 2001 From: Nicolas Gotchac Date: Wed, 15 Mar 2017 13:40:18 +0100 Subject: [PATCH 59/71] Add Vaults logic to First Run (#4894) (#4914) --- js/src/modals/FirstRun/Welcome/welcome.js | 4 +- js/src/ui/Portal/portal.js | 7 +++- js/src/views/Application/store.js | 45 ++++++++++++++++++++--- 3 files changed, 47 insertions(+), 9 deletions(-) diff --git a/js/src/modals/FirstRun/Welcome/welcome.js b/js/src/modals/FirstRun/Welcome/welcome.js index 629ec47bc..df438d112 100644 --- a/js/src/modals/FirstRun/Welcome/welcome.js +++ b/js/src/modals/FirstRun/Welcome/welcome.js @@ -49,7 +49,7 @@ export default class FirstRun extends Component { defaultMessage='As part of a new installation, the next few steps will guide you through the process of setting up you Parity instance and your associated accounts. Our aim is to make it as simple as possible and to get you up and running in record-time, so please bear with us. Once completed you will have -' />

-

+

-

+

{ this.firstrunVisible = visible; - store.set('showFirstRun', !!visible); + + // There's no need to write to storage that the + // First Run should be visible + if (!visible) { + store.set(LS_FIRST_RUN_KEY, !!visible); + } + } + + /** + * Migrate the old LocalStorage ket format + * to the new one + */ + _migrateStore () { + const oldValue = store.get(OLD_LS_FIRST_RUN_KEY); + const newValue = store.get(LS_FIRST_RUN_KEY); + + if (newValue === undefined && oldValue !== undefined) { + store.set(LS_FIRST_RUN_KEY, oldValue); + store.remove(OLD_LS_FIRST_RUN_KEY); + } } _checkAccounts () { - this._api.parity - .allAccountsInfo() - .then((info) => { + return Promise + .all([ + this._api.parity.listVaults(), + this._api.parity.allAccountsInfo() + ]) + .then(([ vaults, info ]) => { const accounts = Object.keys(info).filter((address) => info[address].uuid); + // Has accounts if any vaults or accounts + const hasAccounts = (accounts && accounts.length > 0) || (vaults && vaults.length > 0); - this.toggleFirstrun(this.firstrunVisible || !accounts || !accounts.length); + // Show First Run if no accounts and no vaults + this.toggleFirstrun(this.firstrunVisible || !hasAccounts); }) .catch((error) => { console.error('checkAccounts', error); From 240ea8a13693206d71c257b14c61ff55c43308a4 Mon Sep 17 00:00:00 2001 From: GitLab Build Bot Date: Wed, 15 Mar 2017 12:50:47 +0000 Subject: [PATCH 60/71] [ci skip] js-precompiled 20170315-124802 --- Cargo.lock | 2 +- js/package.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index ac7f7f259..0249f6b84 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1698,7 +1698,7 @@ dependencies = [ [[package]] name = "parity-ui-precompiled" version = "1.4.0" -source = "git+https://github.com/ethcore/js-precompiled.git#c9c37a8c4f83ae80c28d54a6e6b2e0d6e9c4e096" +source = "git+https://github.com/ethcore/js-precompiled.git#d9d60034533cc91d1f26afa1b21d0265c925218f" dependencies = [ "parity-dapps-glue 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", ] diff --git a/js/package.json b/js/package.json index fb6c6da7c..83d79bc8e 100644 --- a/js/package.json +++ b/js/package.json @@ -1,6 +1,6 @@ { "name": "parity.js", - "version": "1.7.14", + "version": "1.7.15", "main": "release/index.js", "jsnext:main": "src/index.js", "author": "Parity Team ", From 5f103ee33dfcb9531921b9046515a5eab9e4e5f1 Mon Sep 17 00:00:00 2001 From: Marek Kotewicz Date: Wed, 15 Mar 2017 14:03:11 +0100 Subject: [PATCH 61/71] Detect rust compiler version in Parity build script, closes 4742 (#4907) * Detect rust compiler version in Parity build script, closes #4742 * updated required compiler version message * fixed typo --- Cargo.lock | 25 +++++++++++++++++++++++++ Cargo.toml | 4 ++++ build.rs | 35 +++++++++++++++++++++++++++++++++++ 3 files changed, 64 insertions(+) create mode 100644 build.rs diff --git a/Cargo.lock b/Cargo.lock index 0249f6b84..7bfd0b20a 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -44,6 +44,7 @@ dependencies = [ "rpassword 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", "rpc-cli 1.4.0", "rustc-serialize 0.3.19 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc_version 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "semver 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", "serde 0.9.6 (registry+https://github.com/rust-lang/crates.io-index)", "serde_json 0.9.5 (registry+https://github.com/rust-lang/crates.io-index)", @@ -2017,6 +2018,14 @@ dependencies = [ "semver 0.1.20 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "rustc_version" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "semver 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "schannel" version = "0.1.1" @@ -2086,6 +2095,14 @@ dependencies = [ "semver-parser 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "semver" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "semver-parser 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "semver-parser" version = "0.6.1" @@ -2095,6 +2112,11 @@ dependencies = [ "regex 0.1.68 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "semver-parser" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "serde" version = "0.9.6" @@ -2707,6 +2729,7 @@ dependencies = [ "checksum rust-crypto 0.2.36 (registry+https://github.com/rust-lang/crates.io-index)" = "f76d05d3993fd5f4af9434e8e436db163a12a9d40e1a58a726f27a01dfd12a2a" "checksum rustc-serialize 0.3.19 (registry+https://github.com/rust-lang/crates.io-index)" = "6159e4e6e559c81bd706afe9c8fd68f547d3e851ce12e76b1de7914bab61691b" "checksum rustc_version 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)" = "c5f5376ea5e30ce23c03eb77cbe4962b988deead10910c372b226388b594c084" +"checksum rustc_version 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1e114e275f7c9b5d50bb52b28f9aac1921209f02aa6077c8b255e21eefaf8ffa" "checksum schannel 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "167852e03fcd0029c3ddebb5afb0715b2996f6e262b2c2aceaa7cd84edd4b158" "checksum scoped-tls 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f417c22df063e9450888a7561788e9bd46d3bb3c1466435b4eccb903807f147d" "checksum secur32-sys 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3f412dfa83308d893101dd59c10d6fda8283465976c28c287c5c855bf8d216bc" @@ -2715,7 +2738,9 @@ dependencies = [ "checksum semver 0.1.20 (registry+https://github.com/rust-lang/crates.io-index)" = "d4f410fedcf71af0345d7607d246e7ad15faaadd49d240ee3b24e5dc21a820ac" "checksum semver 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "2d5b7638a1f03815d94e88cb3b3c08e87f0db4d683ef499d1836aaf70a45623f" "checksum semver 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "ae2ff60ecdb19c255841c066cbfa5f8c2a4ada1eb3ae47c77ab6667128da71f5" +"checksum semver 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7a3186ec9e65071a2095434b1f5bb24838d4e8e130f584c790f6033c79943537" "checksum semver-parser 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)" = "e88e43a5a74dd2a11707f9c21dfd4a423c66bd871df813227bb0a3e78f3a1ae9" +"checksum semver-parser 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3" "checksum serde 0.9.6 (registry+https://github.com/rust-lang/crates.io-index)" = "0ae9a3c8b07c09dbe43022486d55a18c629a0618d2241e49829aaef9b6d862f9" "checksum serde_codegen_internals 0.13.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c3172bf2940b975c0e4f6ab42a511c0a4407d4f46ccef87a9d3615db5c26fa96" "checksum serde_derive 0.9.6 (registry+https://github.com/rust-lang/crates.io-index)" = "ecc6e0379ca933ece58302d2d3034443f06fbf38fd535857c1dc516195cbc3bf" diff --git a/Cargo.toml b/Cargo.toml index 7ff9b0521..099be68e5 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -4,6 +4,7 @@ name = "parity" version = "1.7.0" license = "GPL-3.0" authors = ["Parity Technologies "] +build = "build.rs" [dependencies] log = "0.3" @@ -52,6 +53,9 @@ ethcore-dapps = { path = "dapps", optional = true } clippy = { version = "0.0.103", optional = true} ethcore-secretstore = { path = "secret_store", optional = true } +[build-dependencies] +rustc_version = "0.2" + [dev-dependencies] ethcore-ipc-tests = { path = "ipc/tests" } diff --git a/build.rs b/build.rs new file mode 100644 index 000000000..0deeff37e --- /dev/null +++ b/build.rs @@ -0,0 +1,35 @@ +// Copyright 2015-2017 Parity Technologies (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 . + +extern crate rustc_version; + +const MIN_RUSTC_VERSION: &'static str = "1.15.1"; + +fn main() { + let is = rustc_version::version().unwrap(); + let required = MIN_RUSTC_VERSION.parse().unwrap(); + assert!(is >= required, format!(" + +It looks like you are compiling Parity with an old rustc compiler {}. +Parity requires version {}. Please update your compiler. +If you use rustup, try this: + + rustup update stable + +and try building Parity again. + +", is, required)); +} From 1f7fb1591d9346921832333449c1bbb4b2fa9b17 Mon Sep 17 00:00:00 2001 From: keorn Date: Wed, 15 Mar 2017 13:04:42 +0000 Subject: [PATCH 62/71] Add reseal max period (#4903) * add reseal max period * fix rpc --- ethcore/src/miner/miner.rs | 17 ++++++++++++++--- parity/cli/config.full.toml | 1 + parity/cli/config.toml | 1 + parity/cli/mod.rs | 5 +++++ parity/cli/usage.txt | 3 +++ parity/configuration.rs | 1 + rpc/src/v1/tests/eth.rs | 1 + 7 files changed, 26 insertions(+), 3 deletions(-) diff --git a/ethcore/src/miner/miner.rs b/ethcore/src/miner/miner.rs index 99c22f88e..d9df86cef 100644 --- a/ethcore/src/miner/miner.rs +++ b/ethcore/src/miner/miner.rs @@ -90,6 +90,8 @@ pub struct MinerOptions { pub reseal_on_own_tx: bool, /// Minimum period between transaction-inspired reseals. pub reseal_min_period: Duration, + /// Maximum period between blocks (enables force sealing after that). + pub reseal_max_period: Duration, /// Maximum amount of gas to bother considering for block insertion. pub tx_gas_limit: U256, /// Maximum size of the transaction queue. @@ -123,6 +125,7 @@ impl Default for MinerOptions { tx_queue_strategy: PrioritizationStrategy::GasPriceOnly, pending_set: PendingSet::AlwaysQueue, reseal_min_period: Duration::from_secs(2), + reseal_max_period: Duration::from_secs(120), work_queue_size: 20, enable_resubmission: true, tx_queue_banning: Banning::Disabled, @@ -212,6 +215,7 @@ pub struct Miner { transaction_queue: Arc>, sealing_work: Mutex, next_allowed_reseal: Mutex, + next_mandatory_reseal: RwLock, sealing_block_last_request: Mutex, // for sealing... options: MinerOptions, @@ -268,6 +272,7 @@ impl Miner { Miner { transaction_queue: Arc::new(Mutex::new(txq)), next_allowed_reseal: Mutex::new(Instant::now()), + next_mandatory_reseal: RwLock::new(Instant::now() + options.reseal_max_period), sealing_block_last_request: Mutex::new(0), sealing_work: Mutex::new(SealingWork{ queue: UsingQueue::new(options.work_queue_size), @@ -298,7 +303,9 @@ impl Miner { } fn forced_sealing(&self) -> bool { - self.options.force_sealing || !self.options.new_work_notify.is_empty() + self.options.force_sealing + || !self.options.new_work_notify.is_empty() + || Instant::now() > *self.next_mandatory_reseal.read() } /// Clear all pending block states @@ -482,6 +489,7 @@ impl Miner { // Save proposal for later seal submission and broadcast it. Seal::Proposal(seal) => { trace!(target: "miner", "Received a Proposal seal."); + *self.next_mandatory_reseal.write() = Instant::now() + self.options.reseal_max_period; { let mut sealing_work = self.sealing_work.lock(); sealing_work.queue.push(block.clone()); @@ -497,7 +505,8 @@ impl Miner { }) }, // Directly import a regular sealed block. - Seal::Regular(seal) => + Seal::Regular(seal) => { + *self.next_mandatory_reseal.write() = Instant::now() + self.options.reseal_max_period; block .lock() .seal(&*self.engine, seal) @@ -505,7 +514,8 @@ impl Miner { .unwrap_or_else(|e| { warn!("ERROR: seal failed when given internally generated seal: {}", e); false - }), + }) + }, Seal::None => false, } } else { @@ -1290,6 +1300,7 @@ mod tests { reseal_on_external_tx: false, reseal_on_own_tx: true, reseal_min_period: Duration::from_secs(5), + reseal_max_period: Duration::from_secs(120), tx_gas_limit: !U256::zero(), tx_queue_size: 1024, tx_queue_gas_limit: GasLimit::None, diff --git a/parity/cli/config.full.toml b/parity/cli/config.full.toml index 980457887..6800ec2dc 100644 --- a/parity/cli/config.full.toml +++ b/parity/cli/config.full.toml @@ -85,6 +85,7 @@ engine_signer = "0xdeadbeefcafe0000000000000000000000000001" force_sealing = true reseal_on_txs = "all" reseal_min_period = 4000 +reseal_max_period = 60000 work_queue_size = 20 relay_set = "cheap" usd_per_tx = "0.0025" diff --git a/parity/cli/config.toml b/parity/cli/config.toml index 227578b13..5c721c715 100644 --- a/parity/cli/config.toml +++ b/parity/cli/config.toml @@ -50,6 +50,7 @@ engine_signer = "0xdeadbeefcafe0000000000000000000000000001" force_sealing = true reseal_on_txs = "all" reseal_min_period = 4000 +reseal_max_period = 60000 price_update_period = "hourly" tx_queue_size = 1024 tx_queue_gas = "auto" diff --git a/parity/cli/mod.rs b/parity/cli/mod.rs index 7d35301d8..b346cb9d8 100644 --- a/parity/cli/mod.rs +++ b/parity/cli/mod.rs @@ -224,6 +224,8 @@ usage! { or |c: &Config| otry!(c.mining).reseal_on_txs.clone(), flag_reseal_min_period: u64 = 2000u64, or |c: &Config| otry!(c.mining).reseal_min_period.clone(), + flag_reseal_max_period: u64 = 120000u64, + or |c: &Config| otry!(c.mining).reseal_max_period.clone(), flag_work_queue_size: usize = 20usize, or |c: &Config| otry!(c.mining).work_queue_size.clone(), flag_tx_gas_limit: Option = None, @@ -460,6 +462,7 @@ struct Mining { force_sealing: Option, reseal_on_txs: Option, reseal_min_period: Option, + reseal_max_period: Option, work_queue_size: Option, tx_gas_limit: Option, tx_time_limit: Option, @@ -701,6 +704,7 @@ mod tests { flag_force_sealing: true, flag_reseal_on_txs: "all".into(), flag_reseal_min_period: 4000u64, + flag_reseal_max_period: 60000u64, flag_work_queue_size: 20usize, flag_tx_gas_limit: Some("6283184".into()), flag_tx_time_limit: Some(100u64), @@ -900,6 +904,7 @@ mod tests { force_sealing: Some(true), reseal_on_txs: Some("all".into()), reseal_min_period: Some(4000), + reseal_max_period: Some(60000), work_queue_size: None, relay_set: None, usd_per_tx: None, diff --git a/parity/cli/usage.txt b/parity/cli/usage.txt index da7a72db9..322543607 100644 --- a/parity/cli/usage.txt +++ b/parity/cli/usage.txt @@ -224,6 +224,9 @@ Sealing/Mining Options: --reseal-min-period MS Specify the minimum time between reseals from incoming transactions. MS is time measured in milliseconds (default: {flag_reseal_min_period}). + --reseal-max-period MS Specify the maximum time since last block to enable + force-sealing. MS is time measured in + milliseconds (default: {flag_reseal_max_period}). --work-queue-size ITEMS Specify the number of historical work packages which are kept cached lest a solution is found for them later. High values take more memory but result diff --git a/parity/configuration.rs b/parity/configuration.rs index fdbd86f3e..9b491143d 100644 --- a/parity/configuration.rs +++ b/parity/configuration.rs @@ -522,6 +522,7 @@ impl Configuration { tx_queue_strategy: to_queue_strategy(&self.args.flag_tx_queue_strategy)?, pending_set: to_pending_set(&self.args.flag_relay_set)?, reseal_min_period: Duration::from_millis(reseal_min_period), + reseal_max_period: Duration::from_millis(self.args.flag_reseal_max_period), work_queue_size: self.args.flag_work_queue_size, enable_resubmission: !self.args.flag_remove_solved, tx_queue_banning: match self.args.flag_tx_time_limit { diff --git a/rpc/src/v1/tests/eth.rs b/rpc/src/v1/tests/eth.rs index c505a2d5d..e2d866e82 100644 --- a/rpc/src/v1/tests/eth.rs +++ b/rpc/src/v1/tests/eth.rs @@ -64,6 +64,7 @@ fn miner_service(spec: &Spec, accounts: Arc) -> Arc { tx_queue_banning: Banning::Disabled, pending_set: PendingSet::SealingOrElseQueue, reseal_min_period: Duration::from_secs(0), + reseal_max_period: Duration::from_secs(120), work_queue_size: 50, enable_resubmission: true, refuse_service_transactions: false, From f8aec7571ff7de692befa581c72b6d0039fdb01f Mon Sep 17 00:00:00 2001 From: Nicolas Gotchac Date: Wed, 15 Mar 2017 16:49:26 +0100 Subject: [PATCH 63/71] Use the registry fee in Token Deployment dapp (#4915) --- .../Deploy/Deployment/deployment.js | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) diff --git a/js/src/dapps/tokendeploy/Deploy/Deployment/deployment.js b/js/src/dapps/tokendeploy/Deploy/Deployment/deployment.js index 0872c992f..51dcd2f5b 100644 --- a/js/src/dapps/tokendeploy/Deploy/Deployment/deployment.js +++ b/js/src/dapps/tokendeploy/Deploy/Deployment/deployment.js @@ -253,23 +253,28 @@ export default class Deployment extends Component { onDeploy = () => { const { managerInstance, registryInstance, tokenregInstance } = this.context; - const { base, deployBusy, globalReg, globalFee, name, nameError, tla, tlaError, totalSupply, totalSupplyError } = this.state; + const { base, deployBusy, globalReg, name, nameError, tla, tlaError, totalSupply, totalSupplyError } = this.state; const hasError = !!(nameError || tlaError || totalSupplyError); if (hasError || deployBusy) { return; } - const tokenreg = (globalReg ? tokenregInstance : registryInstance).address; + const registry = globalReg ? tokenregInstance : registryInstance; + const tokenreg = registry.address; + const values = [base.mul(totalSupply), tla, name, tokenreg]; - const options = { - value: globalReg ? globalFee : 0 - }; + const options = {}; this.setState({ deployBusy: true, deployState: 'Estimating gas for the transaction' }); - return api.parity - .defaultAccount() + return registry.fee.call({}, []) + .then((fee) => { + console.log('deploying with fee of', fee.toFixed()); + options.value = fee; + + return api.parity.defaultAccount(); + }) .then((defaultAddress) => { options.from = defaultAddress; From a25d935a1d74a0cbb7364cbf0566765fb9085ee9 Mon Sep 17 00:00:00 2001 From: Nicolas Gotchac Date: Wed, 15 Mar 2017 16:49:47 +0100 Subject: [PATCH 64/71] Add Token image from URL (#4916) --- .../dapps/tokenreg/Tokens/Token/add-meta.js | 28 +++++++- .../tokenreg/Tokens/Token/tokenContainer.js | 4 +- js/src/dapps/tokenreg/Tokens/actions.js | 70 +++++++++++++------ js/src/dapps/tokenreg/constants.js | 4 +- js/src/dapps/tokenreg/parity.js | 2 +- js/src/dapps/tokenreg/utils.js | 39 +++++++++++ js/src/views/Dapps/builtin.json | 3 +- 7 files changed, 118 insertions(+), 32 deletions(-) diff --git a/js/src/dapps/tokenreg/Tokens/Token/add-meta.js b/js/src/dapps/tokenreg/Tokens/Token/add-meta.js index 89da76701..0f73179d9 100644 --- a/js/src/dapps/tokenreg/Tokens/Token/add-meta.js +++ b/js/src/dapps/tokenreg/Tokens/Token/add-meta.js @@ -19,7 +19,7 @@ import { Dialog, RaisedButton, FlatButton, SelectField, MenuItem } from 'materia import AddIcon from 'material-ui/svg-icons/content/add'; import InputText from '../../Inputs/Text'; -import { ADDRESS_TYPE } from '../../Inputs/validation'; +import { ADDRESS_TYPE, URL_TYPE } from '../../Inputs/validation'; import styles from './token.css'; @@ -128,6 +128,22 @@ export default class AddMeta extends Component { renderForm () { const selectedMeta = metaDataKeys[this.state.metaKeyIndex]; + const metaLabel = selectedMeta.label.toLowerCase(); + let metaType; + + switch (selectedMeta.validation) { + case ADDRESS_TYPE: + metaType = 'Address'; + break; + + case URL_TYPE: + metaType = 'URL'; + break; + + default: + metaType = 'URL Hint'; + break; + } return (

@@ -145,7 +161,7 @@ export default class AddMeta extends Component { { const { index } = this.props; + const { form, metaKeyIndex } = this.state; + + const selectedMeta = metaDataKeys[metaKeyIndex]; const keyIndex = this.state.metaKeyIndex; const key = metaDataKeys[keyIndex].value; + const value = form.value; + const validationType = selectedMeta.validation; this.props.handleAddMeta( index, key, - this.state.form.value + value, + validationType ); this.setState({ complete: true }); diff --git a/js/src/dapps/tokenreg/Tokens/Token/tokenContainer.js b/js/src/dapps/tokenreg/Tokens/Token/tokenContainer.js index 2de03fe9e..dc15f68d9 100644 --- a/js/src/dapps/tokenreg/Tokens/Token/tokenContainer.js +++ b/js/src/dapps/tokenreg/Tokens/Token/tokenContainer.js @@ -61,8 +61,8 @@ const mapDispatchToProps = (dispatch) => { dispatch(unregisterToken(index)); }, - handleAddMeta: (index, key, value) => { - dispatch(addTokenMeta(index, key, value)); + handleAddMeta: (index, key, value, validationType) => { + dispatch(addTokenMeta(index, key, value, validationType)); } }; }; diff --git a/js/src/dapps/tokenreg/Tokens/actions.js b/js/src/dapps/tokenreg/Tokens/actions.js index b32b86905..6b7983b0d 100644 --- a/js/src/dapps/tokenreg/Tokens/actions.js +++ b/js/src/dapps/tokenreg/Tokens/actions.js @@ -14,7 +14,8 @@ // You should have received a copy of the GNU General Public License // along with Parity. If not, see . -import { getTokenTotalSupply } from '../utils'; +import { URL_TYPE } from '../Inputs/validation'; +import { getTokenTotalSupply, urlToHash } from '../utils'; const { bytesToHex } = window.parity.api.util; @@ -178,40 +179,63 @@ export const queryTokenMeta = (index, query) => (dispatch, getState) => { }); }; -export const addTokenMeta = (index, key, value) => (dispatch, getState) => { +export const addTokenMeta = (index, key, value, validationType) => (dispatch, getState) => { const state = getState(); + const contractInstance = state.status.contract.instance; + const ghhInstance = state.status.githubhint.instance; + const token = state.tokens.tokens.find(t => t.index === index); const options = { from: token.owner }; - const values = [ index, key, value ]; + let valuesPromise; - contractInstance - .setMeta - .estimateGas(options, values) - .then((gasEstimate) => { - options.gas = gasEstimate.mul(1.2).toFixed(0); - return contractInstance.setMeta.postTransaction(options, values); + // Get the right values (could be a hashed URL from GHH) + if (validationType === URL_TYPE) { + valuesPromise = addGithubhintURL(ghhInstance, options, value) + .then((hash) => [ index, key, hash ]); + } else { + valuesPromise = Promise.resolve([ index, key, value ]); + } + + return valuesPromise + .then((values) => { + return contractInstance + .setMeta + .estimateGas(options, values) + .then((gasEstimate) => { + options.gas = gasEstimate.mul(1.2).toFixed(0); + return contractInstance.setMeta.postTransaction(options, values); + }); }) .catch((e) => { console.error(`addTokenMeta: #${index} error`, e); }); }; -export const addGithubhintURL = (from, key, url) => (dispatch, getState) => { - const state = getState(); - const contractInstance = state.status.githubhint.instance; - const options = { from }; - const values = [ key, url ]; +export const addGithubhintURL = (ghhInstance, _options, url) => { + return urlToHash(ghhInstance, url) + .then((result) => { + const { hash, registered } = result; - contractInstance - .hintURL - .estimateGas(options, values) - .then((gasEstimate) => { - options.gas = gasEstimate.mul(1.2).toFixed(0); - return contractInstance.hintURL.postTransaction(options, values); - }) - .catch((e) => { - console.error('addGithubhintURL error', e); + if (registered) { + return hash; + } + + const options = { from: _options.from }; + const values = [ hash, url ]; + + ghhInstance + .hintURL + .estimateGas(options, values) + .then((gasEstimate) => { + options.gas = gasEstimate.mul(1.2).toFixed(0); + return ghhInstance.hintURL.postTransaction(options, values); + }) + .catch((error) => { + console.error(`registering "${url}" to GHH`, error); + }); + + return hash; }); }; diff --git a/js/src/dapps/tokenreg/constants.js b/js/src/dapps/tokenreg/constants.js index 3d56545bd..a4d2e3938 100644 --- a/js/src/dapps/tokenreg/constants.js +++ b/js/src/dapps/tokenreg/constants.js @@ -14,13 +14,13 @@ // You should have received a copy of the GNU General Public License // along with Parity. If not, see . -import { HEX_TYPE, ADDRESS_TYPE } from './Inputs/validation'; +import { URL_TYPE, ADDRESS_TYPE } from './Inputs/validation'; export const metaDataKeys = [ { label: 'Image', value: 'IMG', - validation: HEX_TYPE + validation: URL_TYPE }, { label: 'Address', diff --git a/js/src/dapps/tokenreg/parity.js b/js/src/dapps/tokenreg/parity.js index 6c861780a..7118ce087 100644 --- a/js/src/dapps/tokenreg/parity.js +++ b/js/src/dapps/tokenreg/parity.js @@ -14,7 +14,7 @@ // You should have received a copy of the GNU General Public License // along with Parity. If not, see . -const { api } = window.parity; +const api = window.parent.secureApi; export { api diff --git a/js/src/dapps/tokenreg/utils.js b/js/src/dapps/tokenreg/utils.js index 1dbd67687..82d71a6d0 100644 --- a/js/src/dapps/tokenreg/utils.js +++ b/js/src/dapps/tokenreg/utils.js @@ -18,6 +18,45 @@ import { api } from './parity'; import { eip20 as eip20Abi } from '~/contracts/abi'; +export const INVALID_URL_HASH = '0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470'; +export const ZERO_ADDRESS = '0x0000000000000000000000000000000000000000'; + +/** + * Convert the given URL to a content hash, + * and checks if it is already registered in GHH + */ +export const urlToHash = (ghhInstance, url) => { + if (!url || !url.length) { + return Promise.resolve(null); + } + + return api.parity + .hashContent(url) + .catch((error) => { + const message = error.text || error.message || error.toString(); + + throw new Error(`${message} (${url})`); + }) + .then((contentHash) => { + console.log('lookupHash', url, contentHash); + + if (contentHash === INVALID_URL_HASH) { + throw new Error(`"${url}" is not a valid URL`); + } + + return ghhInstance.entries + .call({}, [contentHash]) + .then(([accountSlashRepo, commit, contentHashOwner]) => { + const registered = (contentHashOwner !== ZERO_ADDRESS); + + return { + hash: contentHash, + registered + }; + }); + }); +}; + export const getTokenTotalSupply = (tokenAddress) => { return api .eth diff --git a/js/src/views/Dapps/builtin.json b/js/src/views/Dapps/builtin.json index 97ebcc0cc..673b4acd3 100644 --- a/js/src/views/Dapps/builtin.json +++ b/js/src/views/Dapps/builtin.json @@ -32,7 +32,8 @@ "description": "A registry of transactable tokens on the network", "author": "Parity Team ", "version": "1.0.0", - "visible": true + "visible": true, + "secure": true }, { "id": "0xf49089046f53f5d2e5f3513c1c32f5ff57d986e46309a42d2b249070e4e72c46", From 8d16cdf12facb25e0e935e644177c344b68c4f67 Mon Sep 17 00:00:00 2001 From: GitLab Build Bot Date: Wed, 15 Mar 2017 16:00:18 +0000 Subject: [PATCH 65/71] [ci skip] js-precompiled 20170315-155713 --- Cargo.lock | 2 +- js/package.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 7bfd0b20a..ada7ee439 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1699,7 +1699,7 @@ dependencies = [ [[package]] name = "parity-ui-precompiled" version = "1.4.0" -source = "git+https://github.com/ethcore/js-precompiled.git#d9d60034533cc91d1f26afa1b21d0265c925218f" +source = "git+https://github.com/ethcore/js-precompiled.git#6f3318f065b2c813b37344f44cfd56b363555e13" dependencies = [ "parity-dapps-glue 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", ] diff --git a/js/package.json b/js/package.json index 83d79bc8e..a34d8f960 100644 --- a/js/package.json +++ b/js/package.json @@ -1,6 +1,6 @@ { "name": "parity.js", - "version": "1.7.15", + "version": "1.7.16", "main": "release/index.js", "jsnext:main": "src/index.js", "author": "Parity Team ", From ba07c32300c300dfa9324cf7cf5a233976b8241c Mon Sep 17 00:00:00 2001 From: Nicolas Gotchac Date: Wed, 15 Mar 2017 19:15:05 +0100 Subject: [PATCH 66/71] Add ability to configure Secure API (for #4885) (#4922) --- js/src/secureApi.js | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/js/src/secureApi.js b/js/src/secureApi.js index fcd7f5fe2..60983fce1 100644 --- a/js/src/secureApi.js +++ b/js/src/secureApi.js @@ -92,6 +92,26 @@ export default class SecureApi extends Api { return this._transport.token; } + /** + * Configure the current API with the given values + * (`signerPort`, `dappsInterface`, `dappsPort`, ...) + */ + configure (configuration) { + const { dappsInterface, dappsPort, signerPort } = configuration; + + if (dappsInterface) { + this._dappsInterface = dappsInterface; + } + + if (dappsPort) { + this._dappsPort = dappsPort; + } + + if (signerPort) { + this._signerPort = signerPort; + } + } + connect () { if (this._isConnecting) { return; From 790bd87bc343d2d5318d3b169a5d822e5350f6c1 Mon Sep 17 00:00:00 2001 From: GitLab Build Bot Date: Wed, 15 Mar 2017 18:27:17 +0000 Subject: [PATCH 67/71] [ci skip] js-precompiled 20170315-182430 --- Cargo.lock | 2 +- js/package.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index ada7ee439..14087830c 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1699,7 +1699,7 @@ dependencies = [ [[package]] name = "parity-ui-precompiled" version = "1.4.0" -source = "git+https://github.com/ethcore/js-precompiled.git#6f3318f065b2c813b37344f44cfd56b363555e13" +source = "git+https://github.com/ethcore/js-precompiled.git#f413546f0ac11b51e1dd9abdc1b03f87818defb4" dependencies = [ "parity-dapps-glue 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", ] diff --git a/js/package.json b/js/package.json index a34d8f960..5c20370c1 100644 --- a/js/package.json +++ b/js/package.json @@ -1,6 +1,6 @@ { "name": "parity.js", - "version": "1.7.16", + "version": "1.7.17", "main": "release/index.js", "jsnext:main": "src/index.js", "author": "Parity Team ", From cb79859c0ed67b9e3c839540f5fc0442aecff673 Mon Sep 17 00:00:00 2001 From: "Denis S. Soldatov aka General-Beck" Date: Thu, 16 Mar 2017 01:21:58 +0300 Subject: [PATCH 68/71] Update cov.sh update coverage for RUST&JS [ci skip] --- scripts/cov.sh | 19 +++++++++++++------ 1 file changed, 13 insertions(+), 6 deletions(-) diff --git a/scripts/cov.sh b/scripts/cov.sh index 7f21e9804..13ab792c7 100755 --- a/scripts/cov.sh +++ b/scripts/cov.sh @@ -1,4 +1,4 @@ -#!/bin/sh +#!/bin/bash # Installing KCOV under ubuntu # https://users.rust-lang.org/t/tutorial-how-to-collect-test-coverages-for-rust-project/650# ### Install deps @@ -24,8 +24,7 @@ fi cargo test $TARGETS --no-run || exit $? - -KCOV_TARGET="target/kcov" +KCOV_TARGET="target/cov" KCOV_FLAGS="--verify" EXCLUDE="/usr/lib,\ /usr/include,\ @@ -39,17 +38,25 @@ util/src/network/tests,\ ethcore/src/evm/tests,\ ethstore/tests,\ target/debug/build,\ -target/release/build\ +target/release/build,\ +*.db " rm -rf $KCOV_TARGET mkdir -p $KCOV_TARGET - +echo "Cover RUST" for FILE in `find target/debug/deps ! -name "*.*"` do $KCOV --exclude-pattern $EXCLUDE $KCOV_FLAGS $KCOV_TARGET $FILE done -$KCOV --coveralls-id=${CI_BUILD_ID} --exclude-pattern $EXCLUDE $KCOV_FLAGS $KCOV_TARGET target/debug/parity-* +$KCOV --exclude-pattern $EXCLUDE $KCOV_FLAGS $KCOV_TARGET target/debug/parity-* +echo "Cover JS" +cd js +npm install&&npm run test:coverage +cd .. +codecov +bash <(curl -s https://codecov.io/bash)&& +echo "Uploaded code coverage" exit 0 From 57d718fde151268e81c9342e984684afe8c12cf4 Mon Sep 17 00:00:00 2001 From: "Denis S. Soldatov aka General-Beck" Date: Thu, 16 Mar 2017 01:24:23 +0300 Subject: [PATCH 69/71] add coverage to master --- .gitlab-ci.yml | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 49f967761..c92fdca83 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -503,18 +503,19 @@ docker-build: - sh scripts/docker-build.sh $DOCKER_TAG tags: - docker -test-coverage: +test-coverage: stage: test only: - - coverage + - master script: - git submodule update --init --recursive + - rm -rf target/* + - rm -rf js/.coverage - scripts/cov.sh - - COVERAGE=$(grep -Po 'covered":.*?[^\\]"' target/kcov/index.json | grep "[0-9]*\.[0-9]" -o) - - echo "Coverage:" $COVERAGE + # - COVERAGE=$(grep -Po 'covered":.*?[^\\]"' target/cov/index.json | grep "[0-9]*\.[0-9]" -o) + # - echo "Coverage:" $COVERAGE tags: - kcov - allow_failure: true test-darwin: stage: test only: From 7846544c1b627bed384d50c473836843183d5362 Mon Sep 17 00:00:00 2001 From: Nicolas Gotchac Date: Thu, 16 Mar 2017 13:18:28 +0100 Subject: [PATCH 70/71] Edit ETH value, gas and gas price in Contract Deployment (#4919) * Fix typo * Add Value capabilities to Contract Deployment * Add Extras settings for Contract Deployment (#4483) * Fix deploy in API --- js/src/api/contract/contract.js | 24 ++- .../DeployContract/DetailsStep/detailsStep.js | 84 +++++++- .../modals/DeployContract/deployContract.js | 193 ++++++++++++++---- js/src/modals/Transfer/Details/details.js | 2 +- js/src/modals/Transfer/Extras/extras.js | 13 +- js/src/ui/Form/Input/input.js | 4 +- js/src/ui/MethodDecoding/methodDecoding.js | 26 ++- js/src/util/tx.js | 25 ++- js/src/views/WriteContract/writeContract.js | 2 +- 9 files changed, 300 insertions(+), 73 deletions(-) diff --git a/js/src/api/contract/contract.js b/js/src/api/contract/contract.js index dd36afead..2156b8af1 100644 --- a/js/src/api/contract/contract.js +++ b/js/src/api/contract/contract.js @@ -107,13 +107,25 @@ export default class Contract { }); } - deploy (options, values, statecb = () => {}) { - statecb(null, { state: 'estimateGas' }); + deploy (options, values, statecb = () => {}, skipGasEstimate = false) { + let gasEstPromise; - return this - .deployEstimateGas(options, values) - .then(([gasEst, gas]) => { - options.gas = gas.toFixed(0); + if (skipGasEstimate) { + gasEstPromise = Promise.resolve(null); + } else { + statecb(null, { state: 'estimateGas' }); + + gasEstPromise = this.deployEstimateGas(options, values) + .then(([gasEst, gas]) => gas); + } + + return gasEstPromise + .then((_gas) => { + if (_gas) { + options.gas = _gas.toFixed(0); + } + + const gas = _gas || options.gas; statecb(null, { state: 'postTransaction', gas }); diff --git a/js/src/modals/DeployContract/DetailsStep/detailsStep.js b/js/src/modals/DeployContract/DetailsStep/detailsStep.js index 3600c13dd..4086b08a3 100644 --- a/js/src/modals/DeployContract/DetailsStep/detailsStep.js +++ b/js/src/modals/DeployContract/DetailsStep/detailsStep.js @@ -16,12 +16,16 @@ import React, { Component, PropTypes } from 'react'; import { FormattedMessage } from 'react-intl'; -import { MenuItem } from 'material-ui'; +import { Checkbox, MenuItem } from 'material-ui'; import { AddressSelect, Form, Input, Select } from '~/ui'; import { validateAbi } from '~/util/validation'; import { parseAbiType } from '~/util/abi'; +const CHECK_STYLE = { + marginTop: '1em' +}; + export default class DetailsStep extends Component { static contextTypes = { api: PropTypes.object.isRequired @@ -30,8 +34,10 @@ export default class DetailsStep extends Component { static propTypes = { accounts: PropTypes.object.isRequired, onAbiChange: PropTypes.func.isRequired, + onAmountChange: PropTypes.func.isRequired, onCodeChange: PropTypes.func.isRequired, onDescriptionChange: PropTypes.func.isRequired, + onExtrasChange: PropTypes.func.isRequired, onFromAddressChange: PropTypes.func.isRequired, onInputsChange: PropTypes.func.isRequired, onNameChange: PropTypes.func.isRequired, @@ -39,11 +45,14 @@ export default class DetailsStep extends Component { abi: PropTypes.string, abiError: PropTypes.string, + amount: PropTypes.string, + amountError: PropTypes.string, balances: PropTypes.object, code: PropTypes.string, codeError: PropTypes.string, description: PropTypes.string, descriptionError: PropTypes.string, + extras: PropTypes.bool, fromAddress: PropTypes.string, fromAddressError: PropTypes.string, name: PropTypes.string, @@ -52,6 +61,7 @@ export default class DetailsStep extends Component { }; static defaultProps = { + extras: false, readOnly: false }; @@ -83,7 +93,7 @@ export default class DetailsStep extends Component { fromAddress, fromAddressError, name, nameError, description, descriptionError, - abiError, + abiError, extras, code, codeError } = this.props; @@ -189,10 +199,70 @@ export default class DetailsStep extends Component { value={ code } /> + { this.renderValueInput() } + +
+ + } + onCheck={ this.onCheckExtras } + style={ CHECK_STYLE } + /> +
+ ); } + renderValueInput () { + const { abi, amount, amountError } = this.props; + + let payable = false; + + try { + const parsedAbi = JSON.parse(abi); + + payable = parsedAbi.find((method) => method.type === 'constructor' && method.payable); + } catch (error) { + return null; + } + + if (!payable) { + return null; + } + + return ( + + } + label={ + + } + min={ 0 } + step={ 0.1 } + type='number' + onChange={ this.onAmountChange } + value={ amount } + /> + ); + } + renderContractSelect () { const { contracts } = this.state; @@ -295,6 +365,16 @@ export default class DetailsStep extends Component { onDescriptionChange(description); } + onAmountChange = (event, value) => { + const { onAmountChange } = this.props; + + onAmountChange(value); + } + + onCheckExtras = () => { + this.props.onExtrasChange(!this.props.extras); + } + onAbiChange = (abi) => { const { api } = this.context; const { onAbiChange, onParamsChange, onInputsChange } = this.props; diff --git a/js/src/modals/DeployContract/deployContract.js b/js/src/modals/DeployContract/deployContract.js index 802de64fb..3e7c83d6d 100644 --- a/js/src/modals/DeployContract/deployContract.js +++ b/js/src/modals/DeployContract/deployContract.js @@ -14,6 +14,7 @@ // You should have received a copy of the GNU General Public License // along with Parity. If not, see . +import BigNumber from 'bignumber.js'; import { pick } from 'lodash'; import { observer } from 'mobx-react'; import React, { Component, PropTypes } from 'react'; @@ -22,12 +23,13 @@ import { connect } from 'react-redux'; import { BusyStep, Button, CompletedStep, CopyToClipboard, GasPriceEditor, IdentityIcon, Portal, TxHash, Warning } from '~/ui'; import { CancelIcon, DoneIcon } from '~/ui/Icons'; -import { ERRORS, validateAbi, validateCode, validateName } from '~/util/validation'; +import { ERRORS, validateAbi, validateCode, validateName, validatePositiveNumber } from '~/util/validation'; import { deploy, deployEstimateGas } from '~/util/tx'; import DetailsStep from './DetailsStep'; import ParametersStep from './ParametersStep'; import ErrorStep from './ErrorStep'; +import Extras from '../Transfer/Extras'; import styles from './deployContract.css'; @@ -50,6 +52,14 @@ const STEPS = { /> ) }, + EXTRAS: { + title: ( + + ) + }, DEPLOYMENT: { waiting: true, title: ( @@ -97,12 +107,16 @@ class DeployContract extends Component { state = { abi: '', abiError: ERRORS.invalidAbi, + amount: '0', + amountValue: new BigNumber(0), + amountError: '', code: '', codeError: ERRORS.invalidCode, deployState: '', deployError: null, description: '', descriptionError: null, + extras: false, fromAddress: Object.keys(this.props.accounts)[0], fromAddressError: null, name: '', @@ -144,7 +158,19 @@ class DeployContract extends Component { const realStepKeys = deployError || rejected ? [] - : Object.keys(STEPS).filter((k) => k !== 'CONTRACT_PARAMETERS' || inputs.length > 0); + : Object.keys(STEPS) + .filter((k) => { + if (k === 'CONTRACT_PARAMETERS') { + return inputs.length > 0; + } + + if (k === 'EXTRAS') { + return this.state.extras; + } + + return true; + }); + const realStep = realStepKeys.findIndex((k) => k === step); const realSteps = realStepKeys.length ? realStepKeys.map((k) => STEPS[k]) @@ -207,8 +233,8 @@ class DeployContract extends Component { } renderDialogActions () { - const { deployError, abiError, codeError, nameError, descriptionError, fromAddressError, fromAddress, step } = this.state; - const isValid = !nameError && !fromAddressError && !descriptionError && !abiError && !codeError; + const { deployError, abiError, amountError, codeError, nameError, descriptionError, fromAddressError, fromAddress, step } = this.state; + const isValid = !nameError && !fromAddressError && !descriptionError && !abiError && !codeError && !amountError; const cancelBtn = (