Merge remote-tracking branch 'origin/master' into check-updates

This commit is contained in:
Gav Wood 2016-11-22 10:25:34 +01:00
commit bf9ed2d444
No known key found for this signature in database
GPG Key ID: C49C1ACA1CC9B252
25 changed files with 142 additions and 104 deletions

2
Cargo.lock generated
View File

@ -1265,7 +1265,7 @@ dependencies = [
[[package]] [[package]]
name = "parity-ui-precompiled" name = "parity-ui-precompiled"
version = "1.4.0" version = "1.4.0"
source = "git+https://github.com/ethcore/js-precompiled.git#587684374a12bf715151dd987a552a3d61e42972" source = "git+https://github.com/ethcore/js-precompiled.git#f46188126257e03c775e76a3cea82b5f70549400"
dependencies = [ dependencies = [
"parity-dapps-glue 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "parity-dapps-glue 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
] ]

View File

@ -21,8 +21,8 @@
"genesis": { "genesis": {
"seal": { "seal": {
"generic": { "generic": {
"fields": 1, "fields": 2,
"rlp": "0x11bbe8db4e347b4e8c937c1c8370e4b5ed33adb3db69cbdb7a38e1e50b1b82fa" "rlp": "0x200"
} }
}, },
"difficulty": "0x20000", "difficulty": "0x20000",

View File

@ -11,9 +11,9 @@
}, },
"genesis": { "genesis": {
"seal": { "seal": {
"ethereum": { "generic": {
"nonce": "0x00006d6f7264656e", "fields": 0,
"mixHash": "0x00000000000000000000000000000000000000647572616c65787365646c6578" "rlp": "0x0"
} }
}, },
"difficulty": "0x20000", "difficulty": "0x20000",

View File

@ -417,13 +417,13 @@ mod tests {
let engine = Spec::new_test_round().engine; let engine = Spec::new_test_round().engine;
let signature = tap.sign(addr, Some("0".into()), header.bare_hash()).unwrap(); let signature = tap.sign(addr, Some("0".into()), header.bare_hash()).unwrap();
let mut step = UNIX_EPOCH.elapsed().unwrap().as_secs(); let time = UNIX_EPOCH.elapsed().unwrap().as_secs();
// Two authorities.
let mut step = time - time % 2;
header.set_seal(vec![encode(&step).to_vec(), encode(&(&*signature as &[u8])).to_vec()]); header.set_seal(vec![encode(&step).to_vec(), encode(&(&*signature as &[u8])).to_vec()]);
let first_ok = engine.verify_block_seal(&header).is_ok(); assert!(engine.verify_block_seal(&header).is_err());
step = step + 1; step = step + 1;
header.set_seal(vec![encode(&step).to_vec(), encode(&(&*signature as &[u8])).to_vec()]); header.set_seal(vec![encode(&step).to_vec(), encode(&(&*signature as &[u8])).to_vec()]);
let second_ok = engine.verify_block_seal(&header).is_ok(); assert!(engine.verify_block_seal(&header).is_ok());
assert!(first_ok ^ second_ok);
} }
} }

View File

@ -1,6 +1,6 @@
{ {
"name": "parity.js", "name": "parity.js",
"version": "0.2.58", "version": "0.2.61",
"main": "release/index.js", "main": "release/index.js",
"jsnext:main": "src/index.js", "jsnext:main": "src/index.js",
"author": "Parity Team <admin@parity.io>", "author": "Parity Team <admin@parity.io>",

View File

@ -14,9 +14,10 @@
// You should have received a copy of the GNU General Public License // You should have received a copy of the GNU General Public License
// along with Parity. If not, see <http://www.gnu.org/licenses/>. // along with Parity. If not, see <http://www.gnu.org/licenses/>.
import { stringify } from 'querystring';
import React from 'react'; import React from 'react';
export default ( export const termsOfService = (
<ul> <ul>
<li>This privacy notice relates to your use of the Parity SMS verification service. We take your privacy seriously and deal in an honest, direct and transparent way when it comes to your data.</li> <li>This privacy notice relates to your use of the Parity SMS verification service. We take your privacy seriously and deal in an honest, direct and transparent way when it comes to your data.</li>
<li>We collect your phone number when you use this service. This is temporarily kept in memory, and then encrypted and stored in our EU servers. We only retain the cryptographic hash of the number to prevent duplicated accounts. You consent to this use.</li> <li>We collect your phone number when you use this service. This is temporarily kept in memory, and then encrypted and stored in our EU servers. We only retain the cryptographic hash of the number to prevent duplicated accounts. You consent to this use.</li>
@ -25,3 +26,18 @@ export default (
<li><i>Parity Technology Limited</i> is registered in England and Wales under company number <code>09760015</code> and complies with the Data Protection Act 1998 (UK). You may contact us via email at <a href={ 'mailto:admin@parity.io' }>admin@parity.io</a>. Our general privacy policy can be found here: <a href={ 'https://ethcore.io/legal.html' }>https://ethcore.io/legal.html</a>.</li> <li><i>Parity Technology Limited</i> is registered in England and Wales under company number <code>09760015</code> and complies with the Data Protection Act 1998 (UK). You may contact us via email at <a href={ 'mailto:admin@parity.io' }>admin@parity.io</a>. Our general privacy policy can be found here: <a href={ 'https://ethcore.io/legal.html' }>https://ethcore.io/legal.html</a>.</li>
</ul> </ul>
); );
export const postToServer = (query) => {
query = stringify(query);
return fetch('https://sms-verification.parity.io/?' + query, {
method: 'POST', mode: 'cors', cache: 'no-store'
})
.then((res) => {
return res.json().then((data) => {
if (res.ok) {
return data.message;
}
throw new Error(data.message || 'unknown error');
});
});
};

View File

@ -14,8 +14,6 @@
// You should have received a copy of the GNU General Public License // You should have received a copy of the GNU General Public License
// along with Parity. If not, see <http://www.gnu.org/licenses/>. // along with Parity. If not, see <http://www.gnu.org/licenses/>.
import { stringify } from 'querystring';
export const checkIfVerified = (contract, account) => { export const checkIfVerified = (contract, account) => {
return contract.instance.certified.call({}, [account]); return contract.instance.certified.call({}, [account]);
}; };
@ -35,18 +33,3 @@ export const checkIfRequested = (contract, account) => {
}); });
}); });
}; };
export const postToServer = (query) => {
query = stringify(query);
return fetch('https://sms-verification.parity.io/?' + query, {
method: 'POST', mode: 'cors', cache: 'no-store'
})
.then((res) => {
return res.json().then((data) => {
if (res.ok) {
return data.message;
}
throw new Error(data.message || 'unknown error');
});
});
};

View File

@ -77,7 +77,7 @@ export default class Lookup extends Component {
label='Lookup' label='Lookup'
primary primary
icon={ <SearchIcon /> } icon={ <SearchIcon /> }
onClick={ this.onLookupClick } onTouchTap={ this.onLookupClick }
/> />
</div> </div>
<CardText>{ output }</CardText> <CardText>{ output }</CardText>

View File

@ -14,7 +14,7 @@
// You should have received a copy of the GNU General Public License // You should have received a copy of the GNU General Public License
// along with Parity. If not, see <http://www.gnu.org/licenses/>. // along with Parity. If not, see <http://www.gnu.org/licenses/>.
import { sha3 } from '../parity.js'; import { sha3, api } from '../parity.js';
const alreadyQueued = (queue, action, name) => const alreadyQueued = (queue, action, name) =>
!!queue.find((entry) => entry.action === action && entry.name === name); !!queue.find((entry) => entry.action === action && entry.name === name);
@ -43,14 +43,23 @@ export const reserve = (name) => (dispatch, getState) => {
const values = [ sha3(name) ]; const values = [ sha3(name) ];
dispatch(reserveStart(name)); dispatch(reserveStart(name));
reserve.estimateGas(options, values) reserve.estimateGas(options, values)
.then((gas) => { .then((gas) => {
options.gas = gas.mul(1.2).toFixed(0); options.gas = gas.mul(1.2).toFixed(0);
return reserve.postTransaction(options, values); return reserve.postTransaction(options, values);
}) })
.then((data) => { .then((requestId) => {
return api.pollMethod('parity_checkRequest', requestId);
})
.then((txhash) => {
dispatch(reserveSuccess(name)); dispatch(reserveSuccess(name));
}).catch((err) => { })
.catch((err) => {
if (err && err.type === 'REQUEST_REJECTED') {
return dispatch(reserveFail(name));
}
console.error(`could not reserve ${name}`); console.error(`could not reserve ${name}`);
if (err) console.error(err.stack); if (err) console.error(err.stack);
dispatch(reserveFail(name)); dispatch(reserveFail(name));
@ -81,9 +90,17 @@ export const drop = (name) => (dispatch, getState) => {
options.gas = gas.mul(1.2).toFixed(0); options.gas = gas.mul(1.2).toFixed(0);
return drop.postTransaction(options, values); return drop.postTransaction(options, values);
}) })
.then((data) => { .then((requestId) => {
return api.pollMethod('parity_checkRequest', requestId);
})
.then((txhash) => {
dispatch(dropSuccess(name)); dispatch(dropSuccess(name));
}).catch((err) => { })
.catch((err) => {
if (err && err.type === 'REQUEST_REJECTED') {
dispatch(reserveFail(name));
}
console.error(`could not drop ${name}`); console.error(`could not drop ${name}`);
if (err) console.error(err.stack); if (err) console.error(err.stack);
dispatch(reserveFail(name)); dispatch(reserveFail(name));

View File

@ -86,6 +86,22 @@ export default class Names extends Component {
name: '' name: ''
}; };
componentWillReceiveProps (nextProps) {
const nextQueue = nextProps.queue;
const prevQueue = this.props.queue;
if (nextQueue.length > prevQueue.length) {
const newQueued = nextQueue[nextQueue.length - 1];
const newName = newQueued.name;
if (newName !== this.state.name) {
return;
}
this.setState({ name: '' });
}
}
render () { render () {
const { action, name } = this.state; const { action, name } = this.state;
const { fee, pending, queue } = this.props; const { fee, pending, queue } = this.props;
@ -120,7 +136,7 @@ export default class Names extends Component {
label={ action === 'reserve' ? 'Reserve' : 'Drop' } label={ action === 'reserve' ? 'Reserve' : 'Drop' }
primary primary
icon={ <CheckIcon /> } icon={ <CheckIcon /> }
onClick={ this.onSubmitClick } onTouchTap={ this.onSubmitClick }
/> />
{ queue.length > 0 { queue.length > 0
? (<div>{ useSignerText }{ renderQueue(queue) }</div>) ? (<div>{ useSignerText }{ renderQueue(queue) }</div>)

View File

@ -52,7 +52,7 @@ export default class Records extends Component {
label='Save' label='Save'
primary primary
icon={ <SaveIcon /> } icon={ <SaveIcon /> }
onClick={ this.onSaveClick } onTouchTap={ this.onSaveClick }
/> />
</CardText> </CardText>
</Card> </Card>

View File

@ -174,7 +174,7 @@ export default class LoadContract extends Component {
const secondaryText = description || `Saved ${moment(timestamp).fromNow()}`; const secondaryText = description || `Saved ${moment(timestamp).fromNow()}`;
const remove = removable const remove = removable
? ( ? (
<IconButton onClick={ onDelete }> <IconButton onTouchTap={ onDelete }>
<DeleteIcon /> <DeleteIcon />
</IconButton> </IconButton>
) )

View File

@ -25,7 +25,7 @@ import ErrorIcon from 'material-ui/svg-icons/navigation/close';
import { fromWei } from '../../../api/util/wei'; import { fromWei } from '../../../api/util/wei';
import { Form, Input } from '../../../ui'; import { Form, Input } from '../../../ui';
import terms from '../terms-of-service'; import { termsOfService } from '../../../3rdparty/sms-verification';
import styles from './gatherData.css'; import styles from './gatherData.css';
export default class GatherData extends Component { export default class GatherData extends Component {
@ -66,7 +66,7 @@ export default class GatherData extends Component {
disabled={ isVerified } disabled={ isVerified }
onCheck={ this.consentOnChange } onCheck={ this.consentOnChange }
/> />
<div className={ styles.terms }>{ terms }</div> <div className={ styles.terms }>{ termsOfService }</div>
</Form> </Form>
); );
} }
@ -123,8 +123,7 @@ export default class GatherData extends Component {
<p className={ styles.message }>You already requested verification.</p> <p className={ styles.message }>You already requested verification.</p>
</div> </div>
); );
} } else if (hasRequested === false) {
if (hasRequested === false) {
return ( return (
<div className={ styles.container }> <div className={ styles.container }>
<SuccessIcon /> <SuccessIcon />

View File

@ -16,8 +16,8 @@
import React, { Component, PropTypes } from 'react'; import React, { Component, PropTypes } from 'react';
import { observer } from 'mobx-react'; import { observer } from 'mobx-react';
import ActionDoneAll from 'material-ui/svg-icons/action/done-all'; import DoneIcon from 'material-ui/svg-icons/action/done-all';
import ContentClear from 'material-ui/svg-icons/content/clear'; import CancelIcon from 'material-ui/svg-icons/content/clear';
import { Button, IdentityIcon, Modal } from '../../ui'; import { Button, IdentityIcon, Modal } from '../../ui';
@ -77,7 +77,7 @@ export default class SMSVerification extends Component {
const cancel = ( const cancel = (
<Button <Button
key='cancel' label='Cancel' key='cancel' label='Cancel'
icon={ <ContentClear /> } icon={ <CancelIcon /> }
onClick={ onClose } onClick={ onClose }
/> />
); );
@ -92,7 +92,7 @@ export default class SMSVerification extends Component {
<Button <Button
key='done' label='Done' key='done' label='Done'
disabled={ !isStepValid } disabled={ !isStepValid }
icon={ <ActionDoneAll /> } icon={ <DoneIcon /> }
onClick={ onClose } onClick={ onClose }
/> />
</div> </div>
@ -140,24 +140,13 @@ export default class SMSVerification extends Component {
setNumber, setConsentGiven, setCode setNumber, setConsentGiven, setCode
} = this.props.store; } = this.props.store;
if (phase === 5) { switch (phase) {
return (<Done />); case 0:
}
if (phase === 4) {
return (<SendConfirmation step={ step } tx={ confirmationTx } />);
}
if (phase === 3) {
return ( return (
<QueryCode <p>Loading SMS Verification.</p>
number={ number } fee={ fee } isCodeValid={ isCodeValid }
setCode={ setCode }
/>
); );
}
if (phase === 2) { case 1:
return (<SendRequest step={ step } tx={ requestTx } />);
}
if (phase === 1) {
const { setNumber, setConsentGiven } = this.props.store; const { setNumber, setConsentGiven } = this.props.store;
return ( return (
<GatherData <GatherData
@ -166,11 +155,32 @@ export default class SMSVerification extends Component {
setNumber={ setNumber } setConsentGiven={ setConsentGiven } setNumber={ setNumber } setConsentGiven={ setConsentGiven }
/> />
); );
}
if (phase === 0) {
return (<p>Preparing awesomeness!</p>);
}
case 2:
return (
<SendRequest step={ step } tx={ requestTx } />
);
case 3:
return (
<QueryCode
number={ number } fee={ fee } isCodeValid={ isCodeValid }
setCode={ setCode }
/>
);
case 4:
return (
<SendConfirmation step={ step } tx={ confirmationTx } />
);
case 5:
return (
<Done />
);
default:
return null; return null;
} }
}
} }

View File

@ -20,7 +20,8 @@ import { sha3 } from '../../api/util/sha3';
import Contracts from '../../contracts'; import Contracts from '../../contracts';
import { checkIfVerified, checkIfRequested, postToServer } from '../../contracts/sms-verification'; import { checkIfVerified, checkIfRequested } from '../../contracts/sms-verification';
import { postToServer } from '../../3rdparty/sms-verification';
import checkIfTxFailed from '../../util/check-if-tx-failed'; import checkIfTxFailed from '../../util/check-if-tx-failed';
import waitForConfirmations from '../../util/wait-for-block-confirmations'; import waitForConfirmations from '../../util/wait-for-block-confirmations';
@ -87,7 +88,7 @@ export default class VerificationStore {
this.account = account; this.account = account;
this.step = LOADING; this.step = LOADING;
Contracts.create(api).registry.getContract('smsVerification') Contracts.create(api).registry.getContract('smsverification')
.then((contract) => { .then((contract) => {
this.contract = contract; this.contract = contract;
this.load(); this.load();

View File

@ -155,24 +155,20 @@ export default class Status {
const { refreshStatus } = this._store.getState().nodeStatus; const { refreshStatus } = this._store.getState().nodeStatus;
const statusPromises = [ this._api.eth.syncing() ]; const statusPromises = [ this._api.eth.syncing(), this._api.parity.netPeers() ];
if (refreshStatus) { if (refreshStatus) {
statusPromises.push(this._api.eth.hashrate()); statusPromises.push(this._api.eth.hashrate());
statusPromises.push(this._api.parity.netPeers());
} }
Promise Promise
.all(statusPromises) .all(statusPromises)
.then((statusResults) => { .then(([ syncing, netPeers, ...statusResults ]) => {
const status = statusResults.length === 1 const status = statusResults.length === 0
? { ? { syncing, netPeers }
syncing: statusResults[0]
}
: { : {
syncing: statusResults[0], syncing, netPeers,
hashrate: statusResults[1], hashrate: statusResults[0]
netPeers: statusResults[2]
}; };
if (!isEqual(status, this._status)) { if (!isEqual(status, this._status)) {

View File

@ -96,7 +96,7 @@ export default class TypedInput extends Component {
<IconButton <IconButton
iconStyle={ iconStyle } iconStyle={ iconStyle }
style={ style } style={ style }
onClick={ this.onAddField } onTouchTap={ this.onAddField }
> >
<AddIcon /> <AddIcon />
</IconButton> </IconButton>
@ -104,7 +104,7 @@ export default class TypedInput extends Component {
<IconButton <IconButton
iconStyle={ iconStyle } iconStyle={ iconStyle }
style={ style } style={ style }
onClick={ this.onRemoveField } onTouchTap={ this.onRemoveField }
> >
<RemoveIcon /> <RemoveIcon />
</IconButton> </IconButton>

View File

@ -67,7 +67,7 @@ export default class Dapps extends Component {
label='edit' label='edit'
key='edit' key='edit'
icon={ <EyeIcon /> } icon={ <EyeIcon /> }
onClick={ this.store.openModal } onTouchTap={ this.store.openModal }
/> />
] } ] }
/> />

View File

@ -74,7 +74,7 @@ class TransactionPendingFormConfirm extends Component {
data-effect='solid' data-effect='solid'
> >
<RaisedButton <RaisedButton
onClick={ this.onConfirm } onTouchTap={ this.onConfirm }
className={ styles.confirmButton } className={ styles.confirmButton }
fullWidth fullWidth
primary primary

View File

@ -37,7 +37,7 @@ export default class TransactionPendingFormReject extends Component {
<strong>This cannot be undone</strong> <strong>This cannot be undone</strong>
</div> </div>
<RaisedButton <RaisedButton
onClick={ onReject } onTouchTap={ onReject }
className={ styles.rejectButton } className={ styles.rejectButton }
fullWidth fullWidth
label={ 'Reject Transaction' } label={ 'Reject Transaction' }

View File

@ -57,7 +57,7 @@ export default class CallsToolbar extends Component {
<div className={ styles.callActions } { ...this._test('button-container') }> <div className={ styles.callActions } { ...this._test('button-container') }>
<IconButton <IconButton
className={ styles.callAction } className={ styles.callAction }
onClick={ this.setCall } onTouchTap={ this.setCall }
tooltip='Set' tooltip='Set'
tooltipPosition='top-left' tooltipPosition='top-left'
{ ...this._test('button-setCall') } { ...this._test('button-setCall') }
@ -66,7 +66,7 @@ export default class CallsToolbar extends Component {
</IconButton> </IconButton>
<IconButton <IconButton
className={ styles.callAction } className={ styles.callAction }
onClick={ this.makeCall } onTouchTap={ this.makeCall }
tooltip='Fire again' tooltip='Fire again'
tooltipPosition='top-left' tooltipPosition='top-left'
{ ...this._test('button-makeCall') } { ...this._test('button-makeCall') }

View File

@ -45,7 +45,7 @@ export default class ScrollTopButton extends Component {
return ( return (
<IconButton <IconButton
className={ `${styles.scrollButton} ${hiddenClass}` } className={ `${styles.scrollButton} ${hiddenClass}` }
onClick={ this._scrollToTop }> onTouchTap={ this._scrollToTop }>
<ArrowUpwardIcon /> <ArrowUpwardIcon />
</IconButton> </IconButton>
); );

View File

@ -102,7 +102,7 @@ fn import(i: ImportAccounts) -> Result<String, String> {
let from = DiskDirectory::at(path); let from = DiskDirectory::at(path);
imported += try!(import_accounts(&from, &to).map_err(|_| "Importing accounts failed.")).len(); imported += try!(import_accounts(&from, &to).map_err(|_| "Importing accounts failed.")).len();
} }
Ok(format!("{}", imported)) Ok(format!("{} account(s) imported", imported))
} }
fn import_geth(i: ImportFromGethAccounts) -> Result<String, String> { fn import_geth(i: ImportFromGethAccounts) -> Result<String, String> {

View File

@ -40,7 +40,7 @@ Operating Options:
(default: {flag_mode_alarm}). (default: {flag_mode_alarm}).
--chain CHAIN Specify the blockchain type. CHAIN may be either a --chain CHAIN Specify the blockchain type. CHAIN may be either a
JSON chain specification file or olympic, frontier, JSON chain specification file or olympic, frontier,
homestead, mainnet, morden, classic, expanse, homestead, mainnet, morden, ropsten, classic, expanse,
testnet or dev (default: {flag_chain}). testnet or dev (default: {flag_chain}).
-d --db-path PATH Specify the database & configuration directory path -d --db-path PATH Specify the database & configuration directory path
(default: {flag_db_path}). (default: {flag_db_path}).

View File

@ -313,7 +313,7 @@ impl Configuration {
fn chain(&self) -> String { fn chain(&self) -> String {
if self.args.flag_testnet { if self.args.flag_testnet {
"morden".to_owned() "ropsten".to_owned()
} else { } else {
self.args.flag_chain.clone() self.args.flag_chain.clone()
} }
@ -905,7 +905,7 @@ mod tests {
// then // then
assert_eq!(conf.network_settings(), NetworkSettings { assert_eq!(conf.network_settings(), NetworkSettings {
name: "testname".to_owned(), name: "testname".to_owned(),
chain: "morden".to_owned(), chain: "ropsten".to_owned(),
network_port: 30303, network_port: 30303,
rpc_enabled: true, rpc_enabled: true,
rpc_interface: "local".to_owned(), rpc_interface: "local".to_owned(),