Merge branch 'master' into engine-password
This commit is contained in:
commit
81a756394a
2
Cargo.lock
generated
2
Cargo.lock
generated
@ -1270,7 +1270,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#d6232885df4b43c91291d31c769e48f107246d73"
|
source = "git+https://github.com/ethcore/js-precompiled.git#7700411d2b0ba1372e0d6cf72a84ecf873a181f3"
|
||||||
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)",
|
||||||
]
|
]
|
||||||
|
@ -21,8 +21,7 @@
|
|||||||
"genesis": {
|
"genesis": {
|
||||||
"seal": {
|
"seal": {
|
||||||
"generic": {
|
"generic": {
|
||||||
"fields": 2,
|
"rlp": "0xc28080"
|
||||||
"rlp": "0x200"
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"difficulty": "0x20000",
|
"difficulty": "0x20000",
|
||||||
|
@ -12,7 +12,6 @@
|
|||||||
"genesis": {
|
"genesis": {
|
||||||
"seal": {
|
"seal": {
|
||||||
"generic": {
|
"generic": {
|
||||||
"fields": 0,
|
|
||||||
"rlp": "0x0"
|
"rlp": "0x0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
@ -1272,7 +1272,7 @@ impl BlockChainClient for Client {
|
|||||||
self.miner.pending_transactions(self.chain.read().best_block_number())
|
self.miner.pending_transactions(self.chain.read().best_block_number())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn signing_network_id(&self) -> Option<u8> {
|
fn signing_network_id(&self) -> Option<u64> {
|
||||||
self.engine.signing_network_id(&self.latest_env_info())
|
self.engine.signing_network_id(&self.latest_env_info())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -662,7 +662,7 @@ impl BlockChainClient for TestBlockChainClient {
|
|||||||
self.miner.pending_transactions(self.chain_info().best_block_number)
|
self.miner.pending_transactions(self.chain_info().best_block_number)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn signing_network_id(&self) -> Option<u8> { None }
|
fn signing_network_id(&self) -> Option<u64> { None }
|
||||||
|
|
||||||
fn mode(&self) -> Mode { Mode::Active }
|
fn mode(&self) -> Mode { Mode::Active }
|
||||||
|
|
||||||
|
@ -237,7 +237,7 @@ pub trait BlockChainClient : Sync + Send {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Get the preferred network ID to sign on
|
/// Get the preferred network ID to sign on
|
||||||
fn signing_network_id(&self) -> Option<u8>;
|
fn signing_network_id(&self) -> Option<u64>;
|
||||||
|
|
||||||
/// Get the mode.
|
/// Get the mode.
|
||||||
fn mode(&self) -> Mode;
|
fn mode(&self) -> Mode;
|
||||||
|
@ -116,7 +116,7 @@ pub trait Engine : Sync + Send {
|
|||||||
fn verify_transaction(&self, _t: &SignedTransaction, _header: &Header) -> Result<(), Error> { Ok(()) }
|
fn verify_transaction(&self, _t: &SignedTransaction, _header: &Header) -> Result<(), Error> { Ok(()) }
|
||||||
|
|
||||||
/// The network ID that transactions should be signed with.
|
/// The network ID that transactions should be signed with.
|
||||||
fn signing_network_id(&self, _env_info: &EnvInfo) -> Option<u8> { None }
|
fn signing_network_id(&self, _env_info: &EnvInfo) -> Option<u64> { None }
|
||||||
|
|
||||||
/// Verify the seal of a block. This is an auxilliary method that actually just calls other `verify_` methods
|
/// Verify the seal of a block. This is an auxilliary method that actually just calls other `verify_` methods
|
||||||
/// to get the job done. By default it must pass `verify_basic` and `verify_block_unordered`. If more or fewer
|
/// to get the job done. By default it must pass `verify_basic` and `verify_block_unordered`. If more or fewer
|
||||||
|
@ -165,9 +165,9 @@ impl Engine for Ethash {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn signing_network_id(&self, env_info: &EnvInfo) -> Option<u8> {
|
fn signing_network_id(&self, env_info: &EnvInfo) -> Option<u64> {
|
||||||
if env_info.number >= self.ethash_params.eip155_transition && self.params().network_id < 127 {
|
if env_info.number >= self.ethash_params.eip155_transition {
|
||||||
Some(self.params().network_id as u8)
|
Some(self.params().network_id)
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
@ -316,7 +316,7 @@ impl Engine for Ethash {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if let Some(n) = t.network_id() {
|
if let Some(n) = t.network_id() {
|
||||||
if header.number() < self.ethash_params.eip155_transition || n as usize != self.params().network_id {
|
if header.number() < self.ethash_params.eip155_transition || n != self.params().network_id {
|
||||||
return Err(TransactionError::InvalidNetworkId.into())
|
return Err(TransactionError::InvalidNetworkId.into())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -30,11 +30,9 @@ pub struct Ethereum {
|
|||||||
|
|
||||||
impl Into<Generic> for Ethereum {
|
impl Into<Generic> for Ethereum {
|
||||||
fn into(self) -> Generic {
|
fn into(self) -> Generic {
|
||||||
let mut s = RlpStream::new();
|
let mut s = RlpStream::new_list(2);
|
||||||
s.append(&self.mix_hash);
|
s.append(&self.mix_hash).append(&self.nonce);
|
||||||
s.append(&self.nonce);
|
|
||||||
Generic {
|
Generic {
|
||||||
fields: 2,
|
|
||||||
rlp: s.out()
|
rlp: s.out()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -42,8 +40,6 @@ impl Into<Generic> for Ethereum {
|
|||||||
|
|
||||||
/// Generic seal.
|
/// Generic seal.
|
||||||
pub struct Generic {
|
pub struct Generic {
|
||||||
/// Number of seal fields.
|
|
||||||
pub fields: usize,
|
|
||||||
/// Seal rlp.
|
/// Seal rlp.
|
||||||
pub rlp: Vec<u8>,
|
pub rlp: Vec<u8>,
|
||||||
}
|
}
|
||||||
@ -64,7 +60,6 @@ impl From<ethjson::spec::Seal> for Seal {
|
|||||||
mix_hash: eth.mix_hash.into()
|
mix_hash: eth.mix_hash.into()
|
||||||
}),
|
}),
|
||||||
ethjson::spec::Seal::Generic(g) => Seal::Generic(Generic {
|
ethjson::spec::Seal::Generic(g) => Seal::Generic(Generic {
|
||||||
fields: g.fields,
|
|
||||||
rlp: g.rlp.into()
|
rlp: g.rlp.into()
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
@ -37,7 +37,7 @@ pub struct CommonParams {
|
|||||||
/// Maximum size of extra data.
|
/// Maximum size of extra data.
|
||||||
pub maximum_extra_data_size: usize,
|
pub maximum_extra_data_size: usize,
|
||||||
/// Network id.
|
/// Network id.
|
||||||
pub network_id: usize,
|
pub network_id: u64,
|
||||||
/// Main subprotocol name.
|
/// Main subprotocol name.
|
||||||
pub subprotocol_name: String,
|
pub subprotocol_name: String,
|
||||||
/// Minimum gas limit.
|
/// Minimum gas limit.
|
||||||
@ -93,8 +93,6 @@ pub struct Spec {
|
|||||||
pub receipts_root: H256,
|
pub receipts_root: H256,
|
||||||
/// The genesis block's extra data field.
|
/// The genesis block's extra data field.
|
||||||
pub extra_data: Bytes,
|
pub extra_data: Bytes,
|
||||||
/// The number of seal fields in the genesis block.
|
|
||||||
pub seal_fields: usize,
|
|
||||||
/// Each seal field, expressed as RLP, concatenated.
|
/// Each seal field, expressed as RLP, concatenated.
|
||||||
pub seal_rlp: Bytes,
|
pub seal_rlp: Bytes,
|
||||||
|
|
||||||
@ -126,7 +124,6 @@ impl From<ethjson::spec::Spec> for Spec {
|
|||||||
gas_used: g.gas_used,
|
gas_used: g.gas_used,
|
||||||
timestamp: g.timestamp,
|
timestamp: g.timestamp,
|
||||||
extra_data: g.extra_data,
|
extra_data: g.extra_data,
|
||||||
seal_fields: seal.fields,
|
|
||||||
seal_rlp: seal.rlp,
|
seal_rlp: seal.rlp,
|
||||||
state_root_memo: RwLock::new(g.state_root),
|
state_root_memo: RwLock::new(g.state_root),
|
||||||
genesis_state: From::from(s.accounts),
|
genesis_state: From::from(s.accounts),
|
||||||
@ -166,7 +163,7 @@ impl Spec {
|
|||||||
pub fn nodes(&self) -> &[String] { &self.nodes }
|
pub fn nodes(&self) -> &[String] { &self.nodes }
|
||||||
|
|
||||||
/// Get the configured Network ID.
|
/// Get the configured Network ID.
|
||||||
pub fn network_id(&self) -> usize { self.params.network_id }
|
pub fn network_id(&self) -> u64 { self.params.network_id }
|
||||||
|
|
||||||
/// Get the configured subprotocol name.
|
/// Get the configured subprotocol name.
|
||||||
pub fn subprotocol_name(&self) -> String { self.params.subprotocol_name.clone() }
|
pub fn subprotocol_name(&self) -> String { self.params.subprotocol_name.clone() }
|
||||||
@ -191,13 +188,8 @@ impl Spec {
|
|||||||
header.set_gas_limit(self.gas_limit.clone());
|
header.set_gas_limit(self.gas_limit.clone());
|
||||||
header.set_difficulty(self.difficulty.clone());
|
header.set_difficulty(self.difficulty.clone());
|
||||||
header.set_seal({
|
header.set_seal({
|
||||||
let seal = {
|
let r = Rlp::new(&self.seal_rlp);
|
||||||
let mut s = RlpStream::new_list(self.seal_fields);
|
r.iter().map(|f| f.as_raw().to_vec()).collect()
|
||||||
s.append_raw(&self.seal_rlp, self.seal_fields);
|
|
||||||
s.out()
|
|
||||||
};
|
|
||||||
let r = Rlp::new(&seal);
|
|
||||||
(0..self.seal_fields).map(|i| r.at(i).as_raw().to_vec()).collect()
|
|
||||||
});
|
});
|
||||||
trace!(target: "spec", "Header hash is {}", header.hash());
|
trace!(target: "spec", "Header hash is {}", header.hash());
|
||||||
header
|
header
|
||||||
@ -226,7 +218,6 @@ impl Spec {
|
|||||||
self.gas_used = g.gas_used;
|
self.gas_used = g.gas_used;
|
||||||
self.timestamp = g.timestamp;
|
self.timestamp = g.timestamp;
|
||||||
self.extra_data = g.extra_data;
|
self.extra_data = g.extra_data;
|
||||||
self.seal_fields = seal.fields;
|
|
||||||
self.seal_rlp = seal.rlp;
|
self.seal_rlp = seal.rlp;
|
||||||
self.state_root_memo = RwLock::new(g.state_root);
|
self.state_root_memo = RwLock::new(g.state_root);
|
||||||
}
|
}
|
||||||
|
@ -72,7 +72,7 @@ pub struct Transaction {
|
|||||||
|
|
||||||
impl Transaction {
|
impl Transaction {
|
||||||
/// Append object with a without signature into RLP stream
|
/// Append object with a without signature into RLP stream
|
||||||
pub fn rlp_append_unsigned_transaction(&self, s: &mut RlpStream, network_id: Option<u8>) {
|
pub fn rlp_append_unsigned_transaction(&self, s: &mut RlpStream, network_id: Option<u64>) {
|
||||||
s.begin_list(if network_id.is_none() { 6 } else { 9 });
|
s.begin_list(if network_id.is_none() { 6 } else { 9 });
|
||||||
s.append(&self.nonce);
|
s.append(&self.nonce);
|
||||||
s.append(&self.gas_price);
|
s.append(&self.gas_price);
|
||||||
@ -140,26 +140,26 @@ impl From<ethjson::transaction::Transaction> for SignedTransaction {
|
|||||||
|
|
||||||
impl Transaction {
|
impl Transaction {
|
||||||
/// The message hash of the transaction.
|
/// The message hash of the transaction.
|
||||||
pub fn hash(&self, network_id: Option<u8>) -> H256 {
|
pub fn hash(&self, network_id: Option<u64>) -> H256 {
|
||||||
let mut stream = RlpStream::new();
|
let mut stream = RlpStream::new();
|
||||||
self.rlp_append_unsigned_transaction(&mut stream, network_id);
|
self.rlp_append_unsigned_transaction(&mut stream, network_id);
|
||||||
stream.out().sha3()
|
stream.out().sha3()
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Signs the transaction as coming from `sender`.
|
/// Signs the transaction as coming from `sender`.
|
||||||
pub fn sign(self, secret: &Secret, network_id: Option<u8>) -> SignedTransaction {
|
pub fn sign(self, secret: &Secret, network_id: Option<u64>) -> SignedTransaction {
|
||||||
let sig = ::ethkey::sign(secret, &self.hash(network_id))
|
let sig = ::ethkey::sign(secret, &self.hash(network_id))
|
||||||
.expect("data is valid and context has signing capabilities; qed");
|
.expect("data is valid and context has signing capabilities; qed");
|
||||||
self.with_signature(sig, network_id)
|
self.with_signature(sig, network_id)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Signs the transaction with signature.
|
/// Signs the transaction with signature.
|
||||||
pub fn with_signature(self, sig: Signature, network_id: Option<u8>) -> SignedTransaction {
|
pub fn with_signature(self, sig: Signature, network_id: Option<u64>) -> SignedTransaction {
|
||||||
SignedTransaction {
|
SignedTransaction {
|
||||||
unsigned: self,
|
unsigned: self,
|
||||||
r: sig.r().into(),
|
r: sig.r().into(),
|
||||||
s: sig.s().into(),
|
s: sig.s().into(),
|
||||||
v: sig.v() + if let Some(n) = network_id { 35 + n * 2 } else { 27 },
|
v: sig.v() as u64 + if let Some(n) = network_id { 35 + n * 2 } else { 27 },
|
||||||
hash: Cell::new(None),
|
hash: Cell::new(None),
|
||||||
sender: Cell::new(None),
|
sender: Cell::new(None),
|
||||||
}
|
}
|
||||||
@ -211,7 +211,7 @@ pub struct SignedTransaction {
|
|||||||
unsigned: Transaction,
|
unsigned: Transaction,
|
||||||
/// The V field of the signature; the LS bit described which half of the curve our point falls
|
/// The V field of the signature; the LS bit described which half of the curve our point falls
|
||||||
/// in. The MS bits describe which network this transaction is for. If 27/28, its for all networks.
|
/// in. The MS bits describe which network this transaction is for. If 27/28, its for all networks.
|
||||||
v: u8,
|
v: u64,
|
||||||
/// The R field of the signature; helps describe the point on the curve.
|
/// The R field of the signature; helps describe the point on the curve.
|
||||||
r: U256,
|
r: U256,
|
||||||
/// The S field of the signature; helps describe the point on the curve.
|
/// The S field of the signature; helps describe the point on the curve.
|
||||||
@ -302,10 +302,10 @@ impl SignedTransaction {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// 0 if `v` would have been 27 under "Electrum" notation, 1 if 28 or 4 if invalid.
|
/// 0 if `v` would have been 27 under "Electrum" notation, 1 if 28 or 4 if invalid.
|
||||||
pub fn standard_v(&self) -> u8 { match self.v { v if v == 27 || v == 28 || v > 36 => (v - 1) % 2, _ => 4 } }
|
pub fn standard_v(&self) -> u8 { match self.v { v if v == 27 || v == 28 || v > 36 => ((v - 1) % 2) as u8, _ => 4 } }
|
||||||
|
|
||||||
/// The network ID, or `None` if this is a global transaction.
|
/// The network ID, or `None` if this is a global transaction.
|
||||||
pub fn network_id(&self) -> Option<u8> {
|
pub fn network_id(&self) -> Option<u64> {
|
||||||
match self.v {
|
match self.v {
|
||||||
v if v > 36 => Some((v - 35) / 2),
|
v if v > 36 => Some((v - 35) / 2),
|
||||||
_ => None,
|
_ => None,
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "parity.js",
|
"name": "parity.js",
|
||||||
"version": "0.2.90",
|
"version": "0.2.91",
|
||||||
"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>",
|
||||||
|
@ -32,9 +32,7 @@ pub struct Ethereum {
|
|||||||
/// Generic seal.
|
/// Generic seal.
|
||||||
#[derive(Debug, PartialEq, Deserialize)]
|
#[derive(Debug, PartialEq, Deserialize)]
|
||||||
pub struct Generic {
|
pub struct Generic {
|
||||||
/// Number of fields.
|
/// Seal rlp.
|
||||||
pub fields: usize,
|
|
||||||
/// Their rlp.
|
|
||||||
pub rlp: Bytes,
|
pub rlp: Bytes,
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -63,8 +61,7 @@ mod tests {
|
|||||||
}
|
}
|
||||||
},{
|
},{
|
||||||
"generic": {
|
"generic": {
|
||||||
"fields": 1,
|
"rlp": "0xe011bbe8db4e347b4e8c937c1c8370e4b5ed33adb3db69cbdb7a38e1e50b1b82fa"
|
||||||
"rlp": "0x11bbe8db4e347b4e8c937c1c8370e4b5ed33adb3db69cbdb7a38e1e50b1b82fa"
|
|
||||||
}
|
}
|
||||||
}]"#;
|
}]"#;
|
||||||
let _deserialized: Vec<Seal> = serde_json::from_str(s).unwrap();
|
let _deserialized: Vec<Seal> = serde_json::from_str(s).unwrap();
|
||||||
|
@ -48,7 +48,7 @@ usage! {
|
|||||||
flag_testnet: bool,
|
flag_testnet: bool,
|
||||||
flag_import_geth_keys: bool,
|
flag_import_geth_keys: bool,
|
||||||
flag_datadir: Option<String>,
|
flag_datadir: Option<String>,
|
||||||
flag_networkid: Option<usize>,
|
flag_networkid: Option<u64>,
|
||||||
flag_peers: Option<u16>,
|
flag_peers: Option<u16>,
|
||||||
flag_nodekey: Option<String>,
|
flag_nodekey: Option<String>,
|
||||||
flag_nodiscover: bool,
|
flag_nodiscover: bool,
|
||||||
@ -122,7 +122,7 @@ usage! {
|
|||||||
or |c: &Config| otry!(c.network).nat.clone(),
|
or |c: &Config| otry!(c.network).nat.clone(),
|
||||||
flag_allow_ips: String = "all",
|
flag_allow_ips: String = "all",
|
||||||
or |c: &Config| otry!(c.network).allow_ips.clone(),
|
or |c: &Config| otry!(c.network).allow_ips.clone(),
|
||||||
flag_network_id: Option<usize> = None,
|
flag_network_id: Option<u64> = None,
|
||||||
or |c: &Config| otry!(c.network).id.clone().map(Some),
|
or |c: &Config| otry!(c.network).id.clone().map(Some),
|
||||||
flag_bootnodes: Option<String> = None,
|
flag_bootnodes: Option<String> = None,
|
||||||
or |c: &Config| otry!(c.network).bootnodes.clone().map(|vec| Some(vec.join(","))),
|
or |c: &Config| otry!(c.network).bootnodes.clone().map(|vec| Some(vec.join(","))),
|
||||||
@ -328,7 +328,7 @@ struct Network {
|
|||||||
max_pending_peers: Option<u16>,
|
max_pending_peers: Option<u16>,
|
||||||
nat: Option<String>,
|
nat: Option<String>,
|
||||||
allow_ips: Option<String>,
|
allow_ips: Option<String>,
|
||||||
id: Option<usize>,
|
id: Option<u64>,
|
||||||
bootnodes: Option<Vec<String>>,
|
bootnodes: Option<Vec<String>>,
|
||||||
discovery: Option<bool>,
|
discovery: Option<bool>,
|
||||||
node_key: Option<String>,
|
node_key: Option<String>,
|
||||||
|
@ -527,7 +527,7 @@ impl Configuration {
|
|||||||
Ok(ret)
|
Ok(ret)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn network_id(&self) -> Option<usize> {
|
fn network_id(&self) -> Option<u64> {
|
||||||
self.args.flag_network_id.or(self.args.flag_networkid)
|
self.args.flag_network_id.or(self.args.flag_networkid)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -44,7 +44,7 @@ pub struct SyncConfig {
|
|||||||
/// Enable ancient block download.
|
/// Enable ancient block download.
|
||||||
pub download_old_blocks: bool,
|
pub download_old_blocks: bool,
|
||||||
/// Network ID
|
/// Network ID
|
||||||
pub network_id: usize,
|
pub network_id: u64,
|
||||||
/// Main "eth" subprotocol name.
|
/// Main "eth" subprotocol name.
|
||||||
pub subprotocol_name: [u8; 3],
|
pub subprotocol_name: [u8; 3],
|
||||||
/// Fork block to check
|
/// Fork block to check
|
||||||
|
@ -192,7 +192,7 @@ pub struct SyncStatus {
|
|||||||
/// Syncing protocol version. That's the maximum protocol version we connect to.
|
/// Syncing protocol version. That's the maximum protocol version we connect to.
|
||||||
pub protocol_version: u8,
|
pub protocol_version: u8,
|
||||||
/// The underlying p2p network version.
|
/// The underlying p2p network version.
|
||||||
pub network_id: usize,
|
pub network_id: u64,
|
||||||
/// `BlockChain` height for the moment the sync started.
|
/// `BlockChain` height for the moment the sync started.
|
||||||
pub start_block_number: BlockNumber,
|
pub start_block_number: BlockNumber,
|
||||||
/// Last fully downloaded and imported block number (if any).
|
/// Last fully downloaded and imported block number (if any).
|
||||||
@ -273,7 +273,7 @@ struct PeerInfo {
|
|||||||
/// Peer chain genesis hash
|
/// Peer chain genesis hash
|
||||||
genesis: H256,
|
genesis: H256,
|
||||||
/// Peer network id
|
/// Peer network id
|
||||||
network_id: usize,
|
network_id: u64,
|
||||||
/// Peer best block hash
|
/// Peer best block hash
|
||||||
latest_hash: H256,
|
latest_hash: H256,
|
||||||
/// Peer total difficulty if known
|
/// Peer total difficulty if known
|
||||||
@ -341,7 +341,7 @@ pub struct ChainSync {
|
|||||||
/// Last propagated block number
|
/// Last propagated block number
|
||||||
last_sent_block_number: BlockNumber,
|
last_sent_block_number: BlockNumber,
|
||||||
/// Network ID
|
/// Network ID
|
||||||
network_id: usize,
|
network_id: u64,
|
||||||
/// Optional fork block to check
|
/// Optional fork block to check
|
||||||
fork_block: Option<(BlockNumber, H256)>,
|
fork_block: Option<(BlockNumber, H256)>,
|
||||||
/// Snapshot downloader.
|
/// Snapshot downloader.
|
||||||
|
Loading…
Reference in New Issue
Block a user