Chain-selection from UI (#4859)
* First little bits for chain-selection. * Provide RPCs and get settings through to user defaults. * Hasty stash. * Fix updater accidentally redownloading. * Finish up. * Add JS tests. * Hypervisor should never run a binary modified before itself. * Style. * Help tweak. * Fix test compile. * Fix JS test * Build fix for tests. * Revert default chain name * Another test * Use spec name via client. * Fix mock up. * whitespace [ci:skip] * whitespace [ci:skip] * remove exit/restart endpoints.
This commit is contained in:
parent
8a67a0a80a
commit
3041c95408
2
Cargo.lock
generated
2
Cargo.lock
generated
@ -1,6 +1,6 @@
|
|||||||
[root]
|
[root]
|
||||||
name = "parity"
|
name = "parity"
|
||||||
version = "1.6.0"
|
version = "1.7.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"ansi_term 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
"ansi_term 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"app_dirs 1.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
"app_dirs 1.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
[package]
|
[package]
|
||||||
description = "Parity Ethereum client"
|
description = "Parity Ethereum client"
|
||||||
name = "parity"
|
name = "parity"
|
||||||
version = "1.6.0"
|
version = "1.7.0"
|
||||||
license = "GPL-3.0"
|
license = "GPL-3.0"
|
||||||
authors = ["Parity Technologies <admin@parity.io>"]
|
authors = ["Parity Technologies <admin@parity.io>"]
|
||||||
|
|
||||||
|
@ -151,8 +151,9 @@ pub struct Client {
|
|||||||
factories: Factories,
|
factories: Factories,
|
||||||
history: u64,
|
history: u64,
|
||||||
rng: Mutex<OsRng>,
|
rng: Mutex<OsRng>,
|
||||||
on_mode_change: Mutex<Option<Box<FnMut(&Mode) + 'static + Send>>>,
|
on_user_defaults_change: Mutex<Option<Box<FnMut(Option<Mode>) + 'static + Send>>>,
|
||||||
registrar: Mutex<Option<Registry>>,
|
registrar: Mutex<Option<Registry>>,
|
||||||
|
exit_handler: Mutex<Option<Box<Fn(bool, Option<String>) + 'static + Send>>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Client {
|
impl Client {
|
||||||
@ -240,8 +241,9 @@ impl Client {
|
|||||||
factories: factories,
|
factories: factories,
|
||||||
history: history,
|
history: history,
|
||||||
rng: Mutex::new(OsRng::new().map_err(::util::UtilError::StdIo)?),
|
rng: Mutex::new(OsRng::new().map_err(::util::UtilError::StdIo)?),
|
||||||
on_mode_change: Mutex::new(None),
|
on_user_defaults_change: Mutex::new(None),
|
||||||
registrar: Mutex::new(None),
|
registrar: Mutex::new(None),
|
||||||
|
exit_handler: Mutex::new(None),
|
||||||
});
|
});
|
||||||
|
|
||||||
{
|
{
|
||||||
@ -276,6 +278,11 @@ impl Client {
|
|||||||
self.notify.write().push(Arc::downgrade(&target));
|
self.notify.write().push(Arc::downgrade(&target));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Set a closure to call when we want to restart the client
|
||||||
|
pub fn set_exit_handler<F>(&self, f: F) where F: Fn(bool, Option<String>) + 'static + Send {
|
||||||
|
*self.exit_handler.lock() = Some(Box::new(f));
|
||||||
|
}
|
||||||
|
|
||||||
/// Returns engine reference.
|
/// Returns engine reference.
|
||||||
pub fn engine(&self) -> &Engine {
|
pub fn engine(&self) -> &Engine {
|
||||||
&*self.engine
|
&*self.engine
|
||||||
@ -294,9 +301,9 @@ impl Client {
|
|||||||
self.registrar.lock()
|
self.registrar.lock()
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Register an action to be done if a mode change happens.
|
/// Register an action to be done if a mode/spec_name change happens.
|
||||||
pub fn on_mode_change<F>(&self, f: F) where F: 'static + FnMut(&Mode) + Send {
|
pub fn on_user_defaults_change<F>(&self, f: F) where F: 'static + FnMut(Option<Mode>) + Send {
|
||||||
*self.on_mode_change.lock() = Some(Box::new(f));
|
*self.on_user_defaults_change.lock() = Some(Box::new(f));
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Flush the block import queue.
|
/// Flush the block import queue.
|
||||||
@ -651,7 +658,6 @@ impl Client {
|
|||||||
self.miner.clone()
|
self.miner.clone()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/// Replace io channel. Useful for testing.
|
/// Replace io channel. Useful for testing.
|
||||||
pub fn set_io_channel(&self, io_channel: IoChannel<ClientIoMessage>) {
|
pub fn set_io_channel(&self, io_channel: IoChannel<ClientIoMessage>) {
|
||||||
*self.io_channel.lock() = io_channel;
|
*self.io_channel.lock() = io_channel;
|
||||||
@ -1030,9 +1036,9 @@ impl BlockChainClient for Client {
|
|||||||
let mut mode = self.mode.lock();
|
let mut mode = self.mode.lock();
|
||||||
*mode = new_mode.clone().into();
|
*mode = new_mode.clone().into();
|
||||||
trace!(target: "mode", "Mode now {:?}", &*mode);
|
trace!(target: "mode", "Mode now {:?}", &*mode);
|
||||||
if let Some(ref mut f) = *self.on_mode_change.lock() {
|
if let Some(ref mut f) = *self.on_user_defaults_change.lock() {
|
||||||
trace!(target: "mode", "Making callback...");
|
trace!(target: "mode", "Making callback...");
|
||||||
f(&*mode)
|
f(Some((&*mode).clone()))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
match new_mode {
|
match new_mode {
|
||||||
@ -1042,6 +1048,22 @@ impl BlockChainClient for Client {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn spec_name(&self) -> String {
|
||||||
|
self.config.spec_name.clone()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn set_spec_name(&self, new_spec_name: String) {
|
||||||
|
trace!(target: "mode", "Client::set_spec_name({:?})", new_spec_name);
|
||||||
|
if !self.enabled.load(AtomicOrdering::Relaxed) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if let Some(ref h) = *self.exit_handler.lock() {
|
||||||
|
(*h)(true, Some(new_spec_name));
|
||||||
|
} else {
|
||||||
|
warn!("Not hypervised; cannot change chain.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn best_block_header(&self) -> encoded::Header {
|
fn best_block_header(&self) -> encoded::Header {
|
||||||
self.chain.read().best_block_header()
|
self.chain.read().best_block_header()
|
||||||
}
|
}
|
||||||
|
@ -123,6 +123,8 @@ pub struct ClientConfig {
|
|||||||
pub db_wal: bool,
|
pub db_wal: bool,
|
||||||
/// Operating mode
|
/// Operating mode
|
||||||
pub mode: Mode,
|
pub mode: Mode,
|
||||||
|
/// The chain spec name
|
||||||
|
pub spec_name: String,
|
||||||
/// Type of block verifier used by client.
|
/// Type of block verifier used by client.
|
||||||
pub verifier_type: VerifierType,
|
pub verifier_type: VerifierType,
|
||||||
/// State db cache-size.
|
/// State db cache-size.
|
||||||
|
@ -721,6 +721,10 @@ impl BlockChainClient for TestBlockChainClient {
|
|||||||
|
|
||||||
fn set_mode(&self, _: Mode) { unimplemented!(); }
|
fn set_mode(&self, _: Mode) { unimplemented!(); }
|
||||||
|
|
||||||
|
fn spec_name(&self) -> String { "foundation".into() }
|
||||||
|
|
||||||
|
fn set_spec_name(&self, _: String) { unimplemented!(); }
|
||||||
|
|
||||||
fn disable(&self) { unimplemented!(); }
|
fn disable(&self) { unimplemented!(); }
|
||||||
|
|
||||||
fn pruning_info(&self) -> PruningInfo {
|
fn pruning_info(&self) -> PruningInfo {
|
||||||
|
@ -241,6 +241,12 @@ pub trait BlockChainClient : Sync + Send {
|
|||||||
/// Set the mode.
|
/// Set the mode.
|
||||||
fn set_mode(&self, mode: Mode);
|
fn set_mode(&self, mode: Mode);
|
||||||
|
|
||||||
|
/// Get the chain spec name.
|
||||||
|
fn spec_name(&self) -> String;
|
||||||
|
|
||||||
|
/// Set the chain via a spec name.
|
||||||
|
fn set_spec_name(&self, spec_name: String);
|
||||||
|
|
||||||
/// Disable the client from importing blocks. This cannot be undone in this session and indicates
|
/// Disable the client from importing blocks. This cannot be undone in this session and indicates
|
||||||
/// that a subsystem has reason to believe this executable incapable of syncing the chain.
|
/// that a subsystem has reason to believe this executable incapable of syncing the chain.
|
||||||
fn disable(&self);
|
fn disable(&self);
|
||||||
|
@ -284,9 +284,15 @@ export default class Parity {
|
|||||||
.execute('parity_mode');
|
.execute('parity_mode');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// DEPRECATED - use chain instead.
|
||||||
netChain () {
|
netChain () {
|
||||||
return this._transport
|
return this._transport
|
||||||
.execute('parity_netChain');
|
.execute('parity_chain');
|
||||||
|
}
|
||||||
|
|
||||||
|
chain () {
|
||||||
|
return this._transport
|
||||||
|
.execute('parity_chain');
|
||||||
}
|
}
|
||||||
|
|
||||||
netPeers () {
|
netPeers () {
|
||||||
@ -454,6 +460,11 @@ export default class Parity {
|
|||||||
.execute('parity_setMode', mode);
|
.execute('parity_setMode', mode);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
setChain (specName) {
|
||||||
|
return this._transport
|
||||||
|
.execute('parity_setChain', specName);
|
||||||
|
}
|
||||||
|
|
||||||
setNewDappsAddresses (addresses) {
|
setNewDappsAddresses (addresses) {
|
||||||
return this._transport
|
return this._transport
|
||||||
.execute('parity_setNewDappsAddresses', addresses ? inAddresses(addresses) : null);
|
.execute('parity_setNewDappsAddresses', addresses ? inAddresses(addresses) : null);
|
||||||
|
@ -199,7 +199,7 @@ export default {
|
|||||||
'2017-01-20 18:14:19 Configured for DevelopmentChain using InstantSeal engine',
|
'2017-01-20 18:14:19 Configured for DevelopmentChain using InstantSeal engine',
|
||||||
'2017-01-20 18:14:19 Operating mode: active',
|
'2017-01-20 18:14:19 Operating mode: active',
|
||||||
'2017-01-20 18:14:19 State DB configuration: fast',
|
'2017-01-20 18:14:19 State DB configuration: fast',
|
||||||
'2017-01-20 18:14:19 Starting Parity/v1.6.0-unstable-2ae8b4c-20170120/x86_64-linux-gnu/rustc1.14.0'
|
'2017-01-20 18:14:19 Starting Parity/v1.7.0-unstable-2ae8b4c-20170120/x86_64-linux-gnu/rustc1.14.0'
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
@ -35,6 +35,7 @@ export default class Parity extends Component {
|
|||||||
features = FeaturesStore.get();
|
features = FeaturesStore.get();
|
||||||
|
|
||||||
componentWillMount () {
|
componentWillMount () {
|
||||||
|
this.store.loadChain();
|
||||||
return this.store.loadMode();
|
return this.store.loadMode();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -50,11 +51,12 @@ export default class Parity extends Component {
|
|||||||
<div>
|
<div>
|
||||||
<FormattedMessage
|
<FormattedMessage
|
||||||
id='settings.parity.overview_0'
|
id='settings.parity.overview_0'
|
||||||
defaultMessage='Control the Parity node settings and mode of operation via this interface.'
|
defaultMessage='Control the Parity node settings and nature of syncing via this interface.'
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div className={ layout.details }>
|
<div className={ layout.details }>
|
||||||
|
{ this.renderChains() }
|
||||||
{ this.renderModes() }
|
{ this.renderModes() }
|
||||||
<Features />
|
<Features />
|
||||||
<LanguageSelector />
|
<LanguageSelector />
|
||||||
@ -65,12 +67,12 @@ export default class Parity extends Component {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
renderItem (mode, label) {
|
renderItem (name, label) {
|
||||||
return (
|
return (
|
||||||
<MenuItem
|
<MenuItem
|
||||||
key={ mode }
|
key={ name }
|
||||||
label={ label }
|
label={ label }
|
||||||
value={ mode }
|
value={ name }
|
||||||
>
|
>
|
||||||
{ label }
|
{ label }
|
||||||
</MenuItem>
|
</MenuItem>
|
||||||
@ -134,7 +136,7 @@ export default class Parity extends Component {
|
|||||||
hint={
|
hint={
|
||||||
<FormattedMessage
|
<FormattedMessage
|
||||||
id='settings.parity.modes.hint'
|
id='settings.parity.modes.hint'
|
||||||
defaultMessage='the syning mode for the Parity node'
|
defaultMessage='the syncing mode for the Parity node'
|
||||||
/>
|
/>
|
||||||
}
|
}
|
||||||
label={
|
label={
|
||||||
@ -182,7 +184,100 @@ export default class Parity extends Component {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
renderChains () {
|
||||||
|
const { chain } = this.store;
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Select
|
||||||
|
id='parityChainSelect'
|
||||||
|
hint={
|
||||||
|
<FormattedMessage
|
||||||
|
id='settings.parity.chains.hint'
|
||||||
|
defaultMessage='the chain for the Parity node to sync to'
|
||||||
|
/>
|
||||||
|
}
|
||||||
|
label={
|
||||||
|
<FormattedMessage
|
||||||
|
id='settings.parity.chains.label'
|
||||||
|
defaultMessage='chain/network to sync'
|
||||||
|
/>
|
||||||
|
}
|
||||||
|
onChange={ this.onChangeChain }
|
||||||
|
value={ chain }
|
||||||
|
>
|
||||||
|
{
|
||||||
|
this.renderItem('foundation', (
|
||||||
|
<FormattedMessage
|
||||||
|
id='settings.parity.chains.chain_foundation'
|
||||||
|
defaultMessage='Parity syncs to the Ethereum network launched by the Ethereum Foundation'
|
||||||
|
/>
|
||||||
|
))
|
||||||
|
}
|
||||||
|
{
|
||||||
|
this.renderItem('kovan', (
|
||||||
|
<FormattedMessage
|
||||||
|
id='settings.parity.chains.chain_kovan'
|
||||||
|
defaultMessage='Parity syncs to the Kovan test network'
|
||||||
|
/>
|
||||||
|
))
|
||||||
|
}
|
||||||
|
{
|
||||||
|
this.renderItem('olympic', (
|
||||||
|
<FormattedMessage
|
||||||
|
id='settings.parity.chains.chain_olympic'
|
||||||
|
defaultMessage='Parity syncs to the Olympic test network'
|
||||||
|
/>
|
||||||
|
))
|
||||||
|
}
|
||||||
|
{
|
||||||
|
this.renderItem('morden', (
|
||||||
|
<FormattedMessage
|
||||||
|
id='settings.parity.chains.cmorden_kovan'
|
||||||
|
defaultMessage='Parity syncs to Morden (Classic) test network'
|
||||||
|
/>
|
||||||
|
))
|
||||||
|
}
|
||||||
|
{
|
||||||
|
this.renderItem('ropsten', (
|
||||||
|
<FormattedMessage
|
||||||
|
id='settings.parity.chains.chain_ropsten'
|
||||||
|
defaultMessage='Parity syncs to the Ropsten test network'
|
||||||
|
/>
|
||||||
|
))
|
||||||
|
}
|
||||||
|
{
|
||||||
|
this.renderItem('classic', (
|
||||||
|
<FormattedMessage
|
||||||
|
id='settings.parity.chains.chain_classic'
|
||||||
|
defaultMessage='Parity syncs to the Ethereum Classic network'
|
||||||
|
/>
|
||||||
|
))
|
||||||
|
}
|
||||||
|
{
|
||||||
|
this.renderItem('expanse', (
|
||||||
|
<FormattedMessage
|
||||||
|
id='settings.parity.chains.chain_expanse'
|
||||||
|
defaultMessage='Parity syncs to the Expanse network'
|
||||||
|
/>
|
||||||
|
))
|
||||||
|
}
|
||||||
|
{
|
||||||
|
this.renderItem('dev', (
|
||||||
|
<FormattedMessage
|
||||||
|
id='settings.parity.chains.chain_dev'
|
||||||
|
defaultMessage='Parity uses a local development chain'
|
||||||
|
/>
|
||||||
|
))
|
||||||
|
}
|
||||||
|
</Select>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
onChangeMode = (event, index, mode) => {
|
onChangeMode = (event, index, mode) => {
|
||||||
this.store.changeMode(mode || event.target.value);
|
this.store.changeMode(mode || event.target.value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
onChangeChain = (event, index, chain) => {
|
||||||
|
this.store.changeChain(chain || event.target.value);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -38,10 +38,12 @@ describe('views/Settings/Parity', () => {
|
|||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
render();
|
render();
|
||||||
sinon.spy(instance.store, 'loadMode');
|
sinon.spy(instance.store, 'loadMode');
|
||||||
|
sinon.spy(instance.store, 'loadChain');
|
||||||
});
|
});
|
||||||
|
|
||||||
afterEach(() => {
|
afterEach(() => {
|
||||||
instance.store.loadMode.restore();
|
instance.store.loadMode.restore();
|
||||||
|
instance.store.loadChain.restore();
|
||||||
});
|
});
|
||||||
|
|
||||||
it('renders defaults', () => {
|
it('renders defaults', () => {
|
||||||
@ -56,6 +58,10 @@ describe('views/Settings/Parity', () => {
|
|||||||
it('loads the mode in the store', () => {
|
it('loads the mode in the store', () => {
|
||||||
expect(instance.store.loadMode).to.have.been.called;
|
expect(instance.store.loadMode).to.have.been.called;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('loads the chain in the store', () => {
|
||||||
|
expect(instance.store.loadChain).to.have.been.called;
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('components', () => {
|
describe('components', () => {
|
||||||
@ -94,5 +100,27 @@ describe('views/Settings/Parity', () => {
|
|||||||
expect(instance.store.changeMode).to.have.been.calledWith('dark');
|
expect(instance.store.changeMode).to.have.been.calledWith('dark');
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
describe('chain selector', () => {
|
||||||
|
let select;
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
select = component.find('Select[id="parityChainSelect"]');
|
||||||
|
sinon.spy(instance.store, 'changeChain');
|
||||||
|
});
|
||||||
|
|
||||||
|
afterEach(() => {
|
||||||
|
instance.store.changeChain.restore();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('renders a chain selector', () => {
|
||||||
|
expect(select).to.have.length(1);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('changes the chain on the store when changed', () => {
|
||||||
|
select.simulate('change', { target: { value: 'dark' } });
|
||||||
|
expect(instance.store.changeChain).to.have.been.calledWith('dark');
|
||||||
|
});
|
||||||
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
@ -20,7 +20,9 @@ function createApi () {
|
|||||||
return {
|
return {
|
||||||
parity: {
|
parity: {
|
||||||
mode: sinon.stub().resolves('passive'),
|
mode: sinon.stub().resolves('passive'),
|
||||||
setMode: sinon.stub().resolves(true)
|
setMode: sinon.stub().resolves(true),
|
||||||
|
chain: sinon.stub().resolves('foundation'),
|
||||||
|
setChain: sinon.stub().resolves(true)
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -20,6 +20,7 @@ import { action, observable } from 'mobx';
|
|||||||
import { LOG_KEYS } from '~/config';
|
import { LOG_KEYS } from '~/config';
|
||||||
|
|
||||||
const DEFAULT_MODE = 'active';
|
const DEFAULT_MODE = 'active';
|
||||||
|
const DEFAULT_CHAIN = 'foundation';
|
||||||
const LOGLEVEL_OPTIONS = Object
|
const LOGLEVEL_OPTIONS = Object
|
||||||
.keys(LogLevel.levels)
|
.keys(LogLevel.levels)
|
||||||
.map((name) => {
|
.map((name) => {
|
||||||
@ -32,6 +33,7 @@ const LOGLEVEL_OPTIONS = Object
|
|||||||
export default class Store {
|
export default class Store {
|
||||||
@observable logLevels = {};
|
@observable logLevels = {};
|
||||||
@observable mode = DEFAULT_MODE;
|
@observable mode = DEFAULT_MODE;
|
||||||
|
@observable chain = DEFAULT_CHAIN;
|
||||||
|
|
||||||
constructor (api) {
|
constructor (api) {
|
||||||
this._api = api;
|
this._api = api;
|
||||||
@ -51,6 +53,10 @@ export default class Store {
|
|||||||
this.mode = mode;
|
this.mode = mode;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@action setChain = (chain) => {
|
||||||
|
this.chain = chain;
|
||||||
|
}
|
||||||
|
|
||||||
changeMode (mode) {
|
changeMode (mode) {
|
||||||
return this._api.parity
|
return this._api.parity
|
||||||
.setMode(mode)
|
.setMode(mode)
|
||||||
@ -64,6 +70,19 @@ export default class Store {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
changeChain (chain) {
|
||||||
|
return this._api.parity
|
||||||
|
.setChain(chain)
|
||||||
|
.then((result) => {
|
||||||
|
if (result) {
|
||||||
|
this.setChain(chain);
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.catch((error) => {
|
||||||
|
console.warn('changeChain', error);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
loadLogLevels () {
|
loadLogLevels () {
|
||||||
this.setLogLevels(
|
this.setLogLevels(
|
||||||
Object
|
Object
|
||||||
@ -98,6 +117,17 @@ export default class Store {
|
|||||||
console.warn('loadMode', error);
|
console.warn('loadMode', error);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
loadChain () {
|
||||||
|
return this._api.parity
|
||||||
|
.chain()
|
||||||
|
.then((chain) => {
|
||||||
|
this.setChain(chain);
|
||||||
|
})
|
||||||
|
.catch((error) => {
|
||||||
|
console.warn('loadChain', error);
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export {
|
export {
|
||||||
|
@ -33,16 +33,22 @@ describe('views/Settings/Parity/Store', () => {
|
|||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
createStore();
|
createStore();
|
||||||
sinon.spy(store, 'setMode');
|
sinon.spy(store, 'setMode');
|
||||||
|
sinon.spy(store, 'setChain');
|
||||||
});
|
});
|
||||||
|
|
||||||
afterEach(() => {
|
afterEach(() => {
|
||||||
store.setMode.restore();
|
store.setMode.restore();
|
||||||
|
store.setChain.restore();
|
||||||
});
|
});
|
||||||
|
|
||||||
it('defaults to mode === active', () => {
|
it('defaults to mode === active', () => {
|
||||||
expect(store.mode).to.equal('active');
|
expect(store.mode).to.equal('active');
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('defaults to chain === foundation', () => {
|
||||||
|
expect(store.chain).to.equal('foundation');
|
||||||
|
});
|
||||||
|
|
||||||
describe('@action', () => {
|
describe('@action', () => {
|
||||||
describe('setMode', () => {
|
describe('setMode', () => {
|
||||||
it('sets the mode', () => {
|
it('sets the mode', () => {
|
||||||
@ -50,6 +56,13 @@ describe('views/Settings/Parity/Store', () => {
|
|||||||
expect(store.mode).to.equal('offline');
|
expect(store.mode).to.equal('offline');
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
describe('setChain', () => {
|
||||||
|
it('sets the chain', () => {
|
||||||
|
store.setChain('dev');
|
||||||
|
expect(store.chain).to.equal('dev');
|
||||||
|
});
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('operations', () => {
|
describe('operations', () => {
|
||||||
@ -80,5 +93,33 @@ describe('views/Settings/Parity/Store', () => {
|
|||||||
expect(store.setMode).to.have.been.calledWith('passive');
|
expect(store.setMode).to.have.been.calledWith('passive');
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
describe('changeChain', () => {
|
||||||
|
beforeEach(() => {
|
||||||
|
return store.changeChain('dev');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('calls parity.setChain', () => {
|
||||||
|
expect(api.parity.setChain).to.have.been.calledWith('dev');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('sets the chain as provided', () => {
|
||||||
|
expect(store.setChain).to.have.been.calledWith('dev');
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('loadChain', () => {
|
||||||
|
beforeEach(() => {
|
||||||
|
return store.loadChain();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('calls parity.chain', () => {
|
||||||
|
expect(api.parity.chain).to.have.been.called;
|
||||||
|
});
|
||||||
|
|
||||||
|
it('sets the chain as retrieved', () => {
|
||||||
|
expect(store.setChain).to.have.been.calledWith('foundation');
|
||||||
|
});
|
||||||
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
@ -190,6 +190,7 @@ fn execute_import(cmd: ImportBlockchain) -> Result<(), String> {
|
|||||||
// prepare client config
|
// prepare client config
|
||||||
let mut client_config = to_client_config(
|
let mut client_config = to_client_config(
|
||||||
&cmd.cache_config,
|
&cmd.cache_config,
|
||||||
|
spec.name.to_lowercase(),
|
||||||
Mode::Active,
|
Mode::Active,
|
||||||
tracing,
|
tracing,
|
||||||
fat_db,
|
fat_db,
|
||||||
@ -361,6 +362,7 @@ fn start_client(
|
|||||||
// prepare client config
|
// prepare client config
|
||||||
let client_config = to_client_config(
|
let client_config = to_client_config(
|
||||||
&cache_config,
|
&cache_config,
|
||||||
|
spec.name.to_lowercase(),
|
||||||
Mode::Active,
|
Mode::Active,
|
||||||
tracing,
|
tracing,
|
||||||
fat_db,
|
fat_db,
|
||||||
|
@ -90,7 +90,7 @@ usage! {
|
|||||||
flag_release_track: String = "current", or |c: &Config| otry!(c.parity).release_track.clone(),
|
flag_release_track: String = "current", or |c: &Config| otry!(c.parity).release_track.clone(),
|
||||||
flag_no_download: bool = false, or |c: &Config| otry!(c.parity).no_download.clone(),
|
flag_no_download: bool = false, or |c: &Config| otry!(c.parity).no_download.clone(),
|
||||||
flag_no_consensus: bool = false, or |c: &Config| otry!(c.parity).no_consensus.clone(),
|
flag_no_consensus: bool = false, or |c: &Config| otry!(c.parity).no_consensus.clone(),
|
||||||
flag_chain: String = "homestead", or |c: &Config| otry!(c.parity).chain.clone(),
|
flag_chain: String = "foundation", or |c: &Config| otry!(c.parity).chain.clone(),
|
||||||
flag_keys_path: String = "$BASE/keys", or |c: &Config| otry!(c.parity).keys_path.clone(),
|
flag_keys_path: String = "$BASE/keys", or |c: &Config| otry!(c.parity).keys_path.clone(),
|
||||||
flag_identity: String = "", or |c: &Config| otry!(c.parity).identity.clone(),
|
flag_identity: String = "", or |c: &Config| otry!(c.parity).identity.clone(),
|
||||||
|
|
||||||
|
@ -85,14 +85,16 @@ pub struct Execute {
|
|||||||
#[derive(Debug, PartialEq)]
|
#[derive(Debug, PartialEq)]
|
||||||
pub struct Configuration {
|
pub struct Configuration {
|
||||||
pub args: Args,
|
pub args: Args,
|
||||||
|
pub spec_name_override: Option<String>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Configuration {
|
impl Configuration {
|
||||||
pub fn parse<S: AsRef<str>>(command: &[S]) -> Result<Self, ArgsError> {
|
pub fn parse<S: AsRef<str>>(command: &[S], spec_name_override: Option<String>) -> Result<Self, ArgsError> {
|
||||||
let args = Args::parse(command)?;
|
let args = Args::parse(command)?;
|
||||||
|
|
||||||
let config = Configuration {
|
let config = Configuration {
|
||||||
args: args,
|
args: args,
|
||||||
|
spec_name_override: spec_name_override,
|
||||||
};
|
};
|
||||||
|
|
||||||
Ok(config)
|
Ok(config)
|
||||||
@ -103,7 +105,11 @@ impl Configuration {
|
|||||||
let pruning = self.args.flag_pruning.parse()?;
|
let pruning = self.args.flag_pruning.parse()?;
|
||||||
let pruning_history = self.args.flag_pruning_history;
|
let pruning_history = self.args.flag_pruning_history;
|
||||||
let vm_type = self.vm_type()?;
|
let vm_type = self.vm_type()?;
|
||||||
let mode = match self.args.flag_mode.as_ref() { "last" => None, mode => Some(to_mode(&mode, self.args.flag_mode_timeout, self.args.flag_mode_alarm)?), };
|
let spec = self.chain().parse()?;
|
||||||
|
let mode = match self.args.flag_mode.as_ref() {
|
||||||
|
"last" => None,
|
||||||
|
mode => Some(to_mode(&mode, self.args.flag_mode_timeout, self.args.flag_mode_alarm)?),
|
||||||
|
};
|
||||||
let update_policy = self.update_policy()?;
|
let update_policy = self.update_policy()?;
|
||||||
let logger_config = self.logger_config();
|
let logger_config = self.logger_config();
|
||||||
let http_conf = self.http_config()?;
|
let http_conf = self.http_config()?;
|
||||||
@ -111,7 +117,6 @@ impl Configuration {
|
|||||||
let net_conf = self.net_config()?;
|
let net_conf = self.net_config()?;
|
||||||
let network_id = self.network_id();
|
let network_id = self.network_id();
|
||||||
let cache_config = self.cache_config();
|
let cache_config = self.cache_config();
|
||||||
let spec = self.chain().parse()?;
|
|
||||||
let tracing = self.args.flag_tracing.parse()?;
|
let tracing = self.args.flag_tracing.parse()?;
|
||||||
let fat_db = self.args.flag_fat_db.parse()?;
|
let fat_db = self.args.flag_fat_db.parse()?;
|
||||||
let compaction = self.args.flag_db_compaction.parse()?;
|
let compaction = self.args.flag_db_compaction.parse()?;
|
||||||
@ -437,7 +442,10 @@ impl Configuration {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn chain(&self) -> String {
|
fn chain(&self) -> String {
|
||||||
if self.args.flag_testnet {
|
if let Some(ref s) = self.spec_name_override {
|
||||||
|
s.clone()
|
||||||
|
}
|
||||||
|
else if self.args.flag_testnet {
|
||||||
"testnet".to_owned()
|
"testnet".to_owned()
|
||||||
} else {
|
} else {
|
||||||
self.args.flag_chain.clone()
|
self.args.flag_chain.clone()
|
||||||
@ -972,6 +980,7 @@ mod tests {
|
|||||||
fn parse(args: &[&str]) -> Configuration {
|
fn parse(args: &[&str]) -> Configuration {
|
||||||
Configuration {
|
Configuration {
|
||||||
args: Args::parse_without_config(args).unwrap(),
|
args: Args::parse_without_config(args).unwrap(),
|
||||||
|
spec_name_override: None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1429,7 +1438,7 @@ mod tests {
|
|||||||
let filename = temp.as_str().to_owned() + "/peers";
|
let filename = temp.as_str().to_owned() + "/peers";
|
||||||
File::create(filename.clone()).unwrap().write_all(b" \n\t\n").unwrap();
|
File::create(filename.clone()).unwrap().write_all(b" \n\t\n").unwrap();
|
||||||
let args = vec!["parity", "--reserved-peers", &filename];
|
let args = vec!["parity", "--reserved-peers", &filename];
|
||||||
let conf = Configuration::parse(&args).unwrap();
|
let conf = Configuration::parse(&args, None).unwrap();
|
||||||
assert!(conf.init_reserved_nodes().is_ok());
|
assert!(conf.init_reserved_nodes().is_ok());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -215,6 +215,7 @@ pub fn default_network_config() -> ::ethsync::NetworkConfiguration {
|
|||||||
#[cfg_attr(feature = "dev", allow(too_many_arguments))]
|
#[cfg_attr(feature = "dev", allow(too_many_arguments))]
|
||||||
pub fn to_client_config(
|
pub fn to_client_config(
|
||||||
cache_config: &CacheConfig,
|
cache_config: &CacheConfig,
|
||||||
|
spec_name: String,
|
||||||
mode: Mode,
|
mode: Mode,
|
||||||
tracing: bool,
|
tracing: bool,
|
||||||
fat_db: bool,
|
fat_db: bool,
|
||||||
@ -261,6 +262,7 @@ pub fn to_client_config(
|
|||||||
client_config.vm_type = vm_type;
|
client_config.vm_type = vm_type;
|
||||||
client_config.name = name;
|
client_config.name = name;
|
||||||
client_config.verifier_type = if check_seal { VerifierType::Canon } else { VerifierType::CanonNoSeal };
|
client_config.verifier_type = if check_seal { VerifierType::Canon } else { VerifierType::CanonNoSeal };
|
||||||
|
client_config.spec_name = spec_name;
|
||||||
client_config
|
client_config
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -479,4 +481,3 @@ but the first password is trimmed
|
|||||||
assert_eq!(to_bootnodes(&Some(two_bootnodes.into())), Ok(vec![one_bootnode.into(), one_bootnode.into()]));
|
assert_eq!(to_bootnodes(&Some(two_bootnodes.into())), Ok(vec![one_bootnode.into(), one_bootnode.into()]));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -122,7 +122,7 @@ mod stratum;
|
|||||||
use std::{process, env};
|
use std::{process, env};
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
use std::io::{self as stdio, BufReader, Read, Write};
|
use std::io::{self as stdio, BufReader, Read, Write};
|
||||||
use std::fs::{metadata, File};
|
use std::fs::{remove_file, metadata, File};
|
||||||
use std::path::PathBuf;
|
use std::path::PathBuf;
|
||||||
use util::sha3::sha3;
|
use util::sha3::sha3;
|
||||||
use cli::Args;
|
use cli::Args;
|
||||||
@ -143,7 +143,7 @@ fn print_hash_of(maybe_file: Option<String>) -> Result<String, String> {
|
|||||||
|
|
||||||
enum PostExecutionAction {
|
enum PostExecutionAction {
|
||||||
Print(String),
|
Print(String),
|
||||||
Restart,
|
Restart(Option<String>),
|
||||||
Quit,
|
Quit,
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -152,8 +152,8 @@ fn execute(command: Execute, can_restart: bool) -> Result<PostExecutionAction, S
|
|||||||
|
|
||||||
match command.cmd {
|
match command.cmd {
|
||||||
Cmd::Run(run_cmd) => {
|
Cmd::Run(run_cmd) => {
|
||||||
let restart = run::execute(run_cmd, can_restart, logger)?;
|
let (restart, spec_name) = run::execute(run_cmd, can_restart, logger)?;
|
||||||
Ok(if restart { PostExecutionAction::Restart } else { PostExecutionAction::Quit })
|
Ok(if restart { PostExecutionAction::Restart(spec_name) } else { PostExecutionAction::Quit })
|
||||||
},
|
},
|
||||||
Cmd::Version => Ok(PostExecutionAction::Print(Args::print_version())),
|
Cmd::Version => Ok(PostExecutionAction::Print(Args::print_version())),
|
||||||
Cmd::Hash(maybe_file) => print_hash_of(maybe_file).map(|s| PostExecutionAction::Print(s)),
|
Cmd::Hash(maybe_file) => print_hash_of(maybe_file).map(|s| PostExecutionAction::Print(s)),
|
||||||
@ -170,7 +170,7 @@ fn execute(command: Execute, can_restart: bool) -> Result<PostExecutionAction, S
|
|||||||
|
|
||||||
fn start(can_restart: bool) -> Result<PostExecutionAction, String> {
|
fn start(can_restart: bool) -> Result<PostExecutionAction, String> {
|
||||||
let args: Vec<String> = env::args().collect();
|
let args: Vec<String> = env::args().collect();
|
||||||
let conf = Configuration::parse(&args).unwrap_or_else(|e| e.exit());
|
let conf = Configuration::parse(&args, take_spec_name_override()).unwrap_or_else(|e| e.exit());
|
||||||
|
|
||||||
let deprecated = find_deprecated(&conf.args);
|
let deprecated = find_deprecated(&conf.args);
|
||||||
for d in deprecated {
|
for d in deprecated {
|
||||||
@ -208,6 +208,22 @@ fn latest_exe_path() -> Option<PathBuf> {
|
|||||||
.and_then(|mut f| { let mut exe = String::new(); f.read_to_string(&mut exe).ok().map(|_| updates_path(&exe)) })
|
.and_then(|mut f| { let mut exe = String::new(); f.read_to_string(&mut exe).ok().map(|_| updates_path(&exe)) })
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn set_spec_name_override(spec_name: String) {
|
||||||
|
if let Err(e) = File::create(updates_path("spec_name_overide"))
|
||||||
|
.and_then(|mut f| f.write_all(spec_name.as_bytes()))
|
||||||
|
{
|
||||||
|
warn!("Couldn't override chain spec: {}", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn take_spec_name_override() -> Option<String> {
|
||||||
|
let p = updates_path("spec_name_overide");
|
||||||
|
let r = File::open(p.clone()).ok()
|
||||||
|
.and_then(|mut f| { let mut spec_name = String::new(); f.read_to_string(&mut spec_name).ok().map(|_| spec_name) });
|
||||||
|
let _ = remove_file(p);
|
||||||
|
r
|
||||||
|
}
|
||||||
|
|
||||||
#[cfg(windows)]
|
#[cfg(windows)]
|
||||||
fn global_cleanup() {
|
fn global_cleanup() {
|
||||||
extern "system" { pub fn WSACleanup() -> i32; }
|
extern "system" { pub fn WSACleanup() -> i32; }
|
||||||
@ -250,7 +266,12 @@ fn main_direct(can_restart: bool) -> i32 {
|
|||||||
match start(can_restart) {
|
match start(can_restart) {
|
||||||
Ok(result) => match result {
|
Ok(result) => match result {
|
||||||
PostExecutionAction::Print(s) => { println!("{}", s); 0 },
|
PostExecutionAction::Print(s) => { println!("{}", s); 0 },
|
||||||
PostExecutionAction::Restart => PLEASE_RESTART_EXIT_CODE,
|
PostExecutionAction::Restart(spec_name_override) => {
|
||||||
|
if let Some(spec_name) = spec_name_override {
|
||||||
|
set_spec_name_override(spec_name);
|
||||||
|
}
|
||||||
|
PLEASE_RESTART_EXIT_CODE
|
||||||
|
},
|
||||||
PostExecutionAction::Quit => 0,
|
PostExecutionAction::Quit => 0,
|
||||||
},
|
},
|
||||||
Err(err) => {
|
Err(err) => {
|
||||||
@ -303,7 +324,7 @@ fn main() {
|
|||||||
(Some(latest_exe_time), Some(this_exe_time)) if latest_exe_time > this_exe_time => true,
|
(Some(latest_exe_time), Some(this_exe_time)) if latest_exe_time > this_exe_time => true,
|
||||||
_ => false,
|
_ => false,
|
||||||
};
|
};
|
||||||
trace_main!("Starting... (have-update: {}, non-updated-current: {})", have_update, is_non_updated_current); trace_main!("Starting... (have-update: {}, non-updated-current: {})", have_update, is_non_updated_current);
|
trace_main!("Starting... (have-update: {}, non-updated-current: {}, update-is-newer: {})", have_update, is_non_updated_current, update_is_newer);
|
||||||
let exit_code = if have_update && is_non_updated_current && update_is_newer {
|
let exit_code = if have_update && is_non_updated_current && update_is_newer {
|
||||||
trace_main!("Attempting to run latest update ({})...", latest_exe.as_ref().expect("guarded by have_update; latest_exe must exist for have_update; qed").display());
|
trace_main!("Attempting to run latest update ({})...", latest_exe.as_ref().expect("guarded by have_update; latest_exe must exist for have_update; qed").display());
|
||||||
run_parity().unwrap_or_else(|| { trace_main!("Falling back to local..."); main_direct(true) })
|
run_parity().unwrap_or_else(|| { trace_main!("Falling back to local..."); main_direct(true) })
|
||||||
|
@ -24,7 +24,7 @@ use util::{Colour, version, RotatingLogger, Mutex, Condvar};
|
|||||||
use io::{MayPanic, ForwardPanic, PanicHandler};
|
use io::{MayPanic, ForwardPanic, PanicHandler};
|
||||||
use ethcore_logger::{Config as LogConfig};
|
use ethcore_logger::{Config as LogConfig};
|
||||||
use ethcore::miner::{StratumOptions, Stratum};
|
use ethcore::miner::{StratumOptions, Stratum};
|
||||||
use ethcore::client::{Mode, DatabaseCompactionProfile, VMType, BlockChainClient};
|
use ethcore::client::{Client, Mode, DatabaseCompactionProfile, VMType, BlockChainClient};
|
||||||
use ethcore::service::ClientService;
|
use ethcore::service::ClientService;
|
||||||
use ethcore::account_provider::{AccountProvider, AccountProviderSettings};
|
use ethcore::account_provider::{AccountProvider, AccountProviderSettings};
|
||||||
use ethcore::miner::{Miner, MinerService, ExternalMiner, MinerOptions};
|
use ethcore::miner::{Miner, MinerService, ExternalMiner, MinerOptions};
|
||||||
@ -152,12 +152,12 @@ impl ::local_store::NodeInfo for FullNodeInfo {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn execute(cmd: RunCmd, can_restart: bool, logger: Arc<RotatingLogger>) -> Result<bool, String> {
|
pub fn execute(cmd: RunCmd, can_restart: bool, logger: Arc<RotatingLogger>) -> Result<(bool, Option<String>), String> {
|
||||||
if cmd.ui && cmd.dapps_conf.enabled {
|
if cmd.ui && cmd.dapps_conf.enabled {
|
||||||
// Check if Parity is already running
|
// Check if Parity is already running
|
||||||
let addr = format!("{}:{}", cmd.dapps_conf.interface, cmd.dapps_conf.port);
|
let addr = format!("{}:{}", cmd.dapps_conf.interface, cmd.dapps_conf.port);
|
||||||
if !TcpListener::bind(&addr as &str).is_ok() {
|
if !TcpListener::bind(&addr as &str).is_ok() {
|
||||||
return open_ui(&cmd.dapps_conf, &cmd.signer_conf).map(|_| false);
|
return open_ui(&cmd.dapps_conf, &cmd.signer_conf).map(|_| (false, None));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -286,6 +286,7 @@ pub fn execute(cmd: RunCmd, can_restart: bool, logger: Arc<RotatingLogger>) -> R
|
|||||||
// create client config
|
// create client config
|
||||||
let mut client_config = to_client_config(
|
let mut client_config = to_client_config(
|
||||||
&cmd.cache_config,
|
&cmd.cache_config,
|
||||||
|
spec.name.to_lowercase(),
|
||||||
mode.clone(),
|
mode.clone(),
|
||||||
tracing,
|
tracing,
|
||||||
fat_db,
|
fat_db,
|
||||||
@ -493,8 +494,10 @@ pub fn execute(cmd: RunCmd, can_restart: bool, logger: Arc<RotatingLogger>) -> R
|
|||||||
user_defaults.save(&user_defaults_path)?;
|
user_defaults.save(&user_defaults_path)?;
|
||||||
|
|
||||||
// tell client how to save the default mode if it gets changed.
|
// tell client how to save the default mode if it gets changed.
|
||||||
client.on_mode_change(move |mode: &Mode| {
|
client.on_user_defaults_change(move |mode: Option<Mode>| {
|
||||||
user_defaults.mode = mode.clone();
|
if let Some(mode) = mode {
|
||||||
|
user_defaults.mode = mode;
|
||||||
|
}
|
||||||
let _ = user_defaults.save(&user_defaults_path); // discard failures - there's nothing we can do
|
let _ = user_defaults.save(&user_defaults_path); // discard failures - there's nothing we can do
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -503,6 +506,7 @@ pub fn execute(cmd: RunCmd, can_restart: bool, logger: Arc<RotatingLogger>) -> R
|
|||||||
true => None,
|
true => None,
|
||||||
false => {
|
false => {
|
||||||
let sync = sync_provider.clone();
|
let sync = sync_provider.clone();
|
||||||
|
let client = client.clone();
|
||||||
let watcher = Arc::new(snapshot::Watcher::new(
|
let watcher = Arc::new(snapshot::Watcher::new(
|
||||||
service.client(),
|
service.client(),
|
||||||
move || is_major_importing(Some(sync.status().state), client.queue_info()),
|
move || is_major_importing(Some(sync.status().state), client.queue_info()),
|
||||||
@ -526,7 +530,7 @@ pub fn execute(cmd: RunCmd, can_restart: bool, logger: Arc<RotatingLogger>) -> R
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Handle exit
|
// Handle exit
|
||||||
let restart = wait_for_exit(panic_handler, Some(updater), can_restart);
|
let restart = wait_for_exit(panic_handler, Some(updater), Some(client), can_restart);
|
||||||
|
|
||||||
// drop this stuff as soon as exit detected.
|
// drop this stuff as soon as exit detected.
|
||||||
drop((http_server, ipc_server, dapps_server, signer_server, secretstore_key_server, ipfs_server, event_loop));
|
drop((http_server, ipc_server, dapps_server, signer_server, secretstore_key_server, ipfs_server, event_loop));
|
||||||
@ -604,9 +608,10 @@ fn build_create_account_hint(spec: &SpecType, keys: &str) -> String {
|
|||||||
fn wait_for_exit(
|
fn wait_for_exit(
|
||||||
panic_handler: Arc<PanicHandler>,
|
panic_handler: Arc<PanicHandler>,
|
||||||
updater: Option<Arc<Updater>>,
|
updater: Option<Arc<Updater>>,
|
||||||
|
client: Option<Arc<Client>>,
|
||||||
can_restart: bool
|
can_restart: bool
|
||||||
) -> bool {
|
) -> (bool, Option<String>) {
|
||||||
let exit = Arc::new((Mutex::new(false), Condvar::new()));
|
let exit = Arc::new((Mutex::new((false, None)), Condvar::new()));
|
||||||
|
|
||||||
// Handle possible exits
|
// Handle possible exits
|
||||||
let e = exit.clone();
|
let e = exit.clone();
|
||||||
@ -616,18 +621,24 @@ fn wait_for_exit(
|
|||||||
let e = exit.clone();
|
let e = exit.clone();
|
||||||
panic_handler.on_panic(move |_reason| { e.1.notify_all(); });
|
panic_handler.on_panic(move |_reason| { e.1.notify_all(); });
|
||||||
|
|
||||||
|
if can_restart {
|
||||||
if let Some(updater) = updater {
|
if let Some(updater) = updater {
|
||||||
// Handle updater wanting to restart us
|
// Handle updater wanting to restart us
|
||||||
if can_restart {
|
|
||||||
let e = exit.clone();
|
let e = exit.clone();
|
||||||
updater.set_exit_handler(move || { *e.0.lock() = true; e.1.notify_all(); });
|
updater.set_exit_handler(move || { *e.0.lock() = (true, None); e.1.notify_all(); });
|
||||||
} else {
|
|
||||||
updater.set_exit_handler(|| info!("Update installed; ready for restart."));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if let Some(client) = client {
|
||||||
|
// Handle updater wanting to restart us
|
||||||
|
let e = exit.clone();
|
||||||
|
client.set_exit_handler(move |restart, new_chain: Option<String>| { *e.0.lock() = (restart, new_chain); e.1.notify_all(); });
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
trace!(target: "mode", "Not hypervised: not setting exit handlers.");
|
||||||
}
|
}
|
||||||
|
|
||||||
// Wait for signal
|
// Wait for signal
|
||||||
let mut l = exit.0.lock();
|
let mut l = exit.0.lock();
|
||||||
let _ = exit.1.wait(&mut l);
|
let _ = exit.1.wait(&mut l);
|
||||||
*l
|
l.clone()
|
||||||
}
|
}
|
||||||
|
@ -173,6 +173,7 @@ impl SnapshotCommand {
|
|||||||
// prepare client config
|
// prepare client config
|
||||||
let client_config = to_client_config(
|
let client_config = to_client_config(
|
||||||
&self.cache_config,
|
&self.cache_config,
|
||||||
|
spec.name.to_lowercase(),
|
||||||
Mode::Active,
|
Mode::Active,
|
||||||
tracing,
|
tracing,
|
||||||
fat_db,
|
fat_db,
|
||||||
|
@ -36,7 +36,7 @@ impl Default for NetworkSettings {
|
|||||||
fn default() -> Self {
|
fn default() -> Self {
|
||||||
NetworkSettings {
|
NetworkSettings {
|
||||||
name: "".into(),
|
name: "".into(),
|
||||||
chain: "homestead".into(),
|
chain: "foundation".into(),
|
||||||
network_port: 30303,
|
network_port: 30303,
|
||||||
rpc_enabled: true,
|
rpc_enabled: true,
|
||||||
rpc_interface: "local".into(),
|
rpc_interface: "local".into(),
|
||||||
|
@ -303,6 +303,10 @@ impl Parity for ParityClient {
|
|||||||
Err(errors::light_unimplemented(None))
|
Err(errors::light_unimplemented(None))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn chain(&self) -> Result<String, Error> {
|
||||||
|
Ok(self.settings.chain.clone())
|
||||||
|
}
|
||||||
|
|
||||||
fn enode(&self) -> Result<String, Error> {
|
fn enode(&self) -> Result<String, Error> {
|
||||||
self.light_dispatch.sync.enode().ok_or_else(errors::network_disabled)
|
self.light_dispatch.sync.enode().ok_or_else(errors::network_disabled)
|
||||||
}
|
}
|
||||||
|
@ -117,6 +117,10 @@ impl<F: Fetch> ParitySet for ParitySetClient<F> {
|
|||||||
Err(errors::light_unimplemented(None))
|
Err(errors::light_unimplemented(None))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn set_spec_name(&self, _spec_name: String) -> Result<bool, Error> {
|
||||||
|
Err(errors::light_unimplemented(None))
|
||||||
|
}
|
||||||
|
|
||||||
fn hash_content(&self, url: String) -> BoxFuture<H256, Error> {
|
fn hash_content(&self, url: String) -> BoxFuture<H256, Error> {
|
||||||
self.fetch.process(self.fetch.fetch(&url).then(move |result| {
|
self.fetch.process(self.fetch.fetch(&url).then(move |result| {
|
||||||
result
|
result
|
||||||
|
@ -188,6 +188,10 @@ impl<C, M, S: ?Sized, U> Parity for ParityClient<C, M, S, U> where
|
|||||||
Ok(self.settings.chain.clone())
|
Ok(self.settings.chain.clone())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn chain(&self) -> Result<String, Error> {
|
||||||
|
Ok(take_weak!(self.client).spec_name())
|
||||||
|
}
|
||||||
|
|
||||||
fn net_peers(&self) -> Result<Peers, Error> {
|
fn net_peers(&self) -> Result<Peers, Error> {
|
||||||
let sync = take_weak!(self.sync);
|
let sync = take_weak!(self.sync);
|
||||||
let sync_status = sync.status();
|
let sync_status = sync.status();
|
||||||
|
@ -156,6 +156,11 @@ impl<C, M, U, F> ParitySet for ParitySetClient<C, M, U, F> where
|
|||||||
Ok(true)
|
Ok(true)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn set_spec_name(&self, spec_name: String) -> Result<bool, Error> {
|
||||||
|
take_weak!(self.client).set_spec_name(spec_name);
|
||||||
|
Ok(true)
|
||||||
|
}
|
||||||
|
|
||||||
fn hash_content(&self, url: String) -> BoxFuture<H256, Error> {
|
fn hash_content(&self, url: String) -> BoxFuture<H256, Error> {
|
||||||
self.fetch.process(self.fetch.fetch(&url).then(move |result| {
|
self.fetch.process(self.fetch.fetch(&url).then(move |result| {
|
||||||
result
|
result
|
||||||
|
@ -285,6 +285,17 @@ fn rpc_parity_net_chain() {
|
|||||||
assert_eq!(io.handle_request_sync(request), Some(response.to_owned()));
|
assert_eq!(io.handle_request_sync(request), Some(response.to_owned()));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn rpc_parity_chain() {
|
||||||
|
let deps = Dependencies::new();
|
||||||
|
let io = deps.default_client();
|
||||||
|
|
||||||
|
let request = r#"{"jsonrpc": "2.0", "method": "parity_chain", "params":[], "id": 1}"#;
|
||||||
|
let response = r#"{"jsonrpc":"2.0","result":"foundation","id":1}"#;
|
||||||
|
|
||||||
|
assert_eq!(io.handle_request_sync(request), Some(response.to_owned()));
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn rpc_parity_net_peers() {
|
fn rpc_parity_net_peers() {
|
||||||
let deps = Dependencies::new();
|
let deps = Dependencies::new();
|
||||||
|
@ -76,7 +76,7 @@ build_rpc_trait! {
|
|||||||
#[rpc(name = "parity_devLogsLevels")]
|
#[rpc(name = "parity_devLogsLevels")]
|
||||||
fn dev_logs_levels(&self) -> Result<String, Error>;
|
fn dev_logs_levels(&self) -> Result<String, Error>;
|
||||||
|
|
||||||
/// Returns chain name
|
/// Returns chain name - DEPRECATED. Use `parity_chainName` instead.
|
||||||
#[rpc(name = "parity_netChain")]
|
#[rpc(name = "parity_netChain")]
|
||||||
fn net_chain(&self) -> Result<String, Error>;
|
fn net_chain(&self) -> Result<String, Error>;
|
||||||
|
|
||||||
@ -167,10 +167,14 @@ build_rpc_trait! {
|
|||||||
#[rpc(async, name = "parity_nextNonce")]
|
#[rpc(async, name = "parity_nextNonce")]
|
||||||
fn next_nonce(&self, H160) -> BoxFuture<U256, Error>;
|
fn next_nonce(&self, H160) -> BoxFuture<U256, Error>;
|
||||||
|
|
||||||
/// Get the mode. Results one of: "active", "passive", "dark", "offline".
|
/// Get the mode. Returns one of: "active", "passive", "dark", "offline".
|
||||||
#[rpc(name = "parity_mode")]
|
#[rpc(name = "parity_mode")]
|
||||||
fn mode(&self) -> Result<String, Error>;
|
fn mode(&self) -> Result<String, Error>;
|
||||||
|
|
||||||
|
/// Get the chain name. Returns one of: "foundation", "kovan", &c. of a filename.
|
||||||
|
#[rpc(name = "parity_chain")]
|
||||||
|
fn chain(&self) -> Result<String, Error>;
|
||||||
|
|
||||||
/// Get the enode of this node.
|
/// Get the enode of this node.
|
||||||
#[rpc(name = "parity_enode")]
|
#[rpc(name = "parity_enode")]
|
||||||
fn enode(&self) -> Result<String, Error>;
|
fn enode(&self) -> Result<String, Error>;
|
||||||
|
@ -88,6 +88,10 @@ build_rpc_trait! {
|
|||||||
#[rpc(name = "parity_setMode")]
|
#[rpc(name = "parity_setMode")]
|
||||||
fn set_mode(&self, String) -> Result<bool, Error>;
|
fn set_mode(&self, String) -> Result<bool, Error>;
|
||||||
|
|
||||||
|
/// Set the network spec. Argument must be one of: "foundation", "ropsten", "morden", "kovan", "olympic", "classic", "dev", "expanse" or a filename.
|
||||||
|
#[rpc(name = "parity_setChain")]
|
||||||
|
fn set_spec_name(&self, String) -> Result<bool, Error>;
|
||||||
|
|
||||||
/// Hash a file content under given URL.
|
/// Hash a file content under given URL.
|
||||||
#[rpc(async, name = "parity_hashContent")]
|
#[rpc(async, name = "parity_hashContent")]
|
||||||
fn hash_content(&self, String) -> BoxFuture<H256, Error>;
|
fn hash_content(&self, String) -> BoxFuture<H256, Error>;
|
||||||
|
Loading…
Reference in New Issue
Block a user