backports for stable 2.2.7 (#10163)
* version: bump stable to 2.2.7 * version: mark 2.2 track stable * version: mark update critical on all networks * version: commit cargo lock * Ping nodes from discovery (#10167) * snap: fix path in script (#10157) * snap: fix path in script * debug, revert me * fix * necromancer awk magic * awk necromancy and path fixing * working track selection * Fix _cannot recursively call into `Core`_ issue (#10144) * Change igd to github:maufl/rust-igd * Run `igd::search_gateway_from_timeout` from own thread * Handle the case for contract creation on an empty but exist account with storage items (#10065) * Add is_base_storage_root_unchanged * Fix compile, use a shortcut for check, and remove ignored tests * Add a warn! * Update ethereum/tests to v6.0.0-beta.2 * grumble: use {:#x} instead of 0x{:x} Co-Authored-By: sorpaas <accounts@that.world> * version: bump fork blocks for kovan and foundation (#10186) * pull constantinople on ethereum network (#10189) * ethcore: pull constantinople on ethereum network * version: mark update as critical * ethcore: remove constantinople alltogether from chain spec * version: revert fork block for ethereum
This commit is contained in:
parent
e9396e158b
commit
b00a21f39a
12
Cargo.lock
generated
12
Cargo.lock
generated
@ -2210,7 +2210,7 @@ version = "1.12.0"
|
||||
dependencies = [
|
||||
"jni 0.10.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"panic_hook 0.1.0",
|
||||
"parity-ethereum 2.2.6",
|
||||
"parity-ethereum 2.2.7",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -2226,7 +2226,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "parity-ethereum"
|
||||
version = "2.2.6"
|
||||
version = "2.2.7"
|
||||
dependencies = [
|
||||
"ansi_term 0.10.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"atty 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
@ -2275,7 +2275,7 @@ dependencies = [
|
||||
"parity-rpc-client 1.4.0",
|
||||
"parity-runtime 0.1.0",
|
||||
"parity-updater 1.12.0",
|
||||
"parity-version 2.2.6",
|
||||
"parity-version 2.2.7",
|
||||
"parity-whisper 0.1.0",
|
||||
"parking_lot 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"pretty_assertions 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
@ -2430,7 +2430,7 @@ dependencies = [
|
||||
"parity-crypto 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"parity-runtime 0.1.0",
|
||||
"parity-updater 1.12.0",
|
||||
"parity-version 2.2.6",
|
||||
"parity-version 2.2.7",
|
||||
"parking_lot 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"patricia-trie 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"pretty_assertions 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
@ -2527,7 +2527,7 @@ dependencies = [
|
||||
"parity-bytes 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"parity-hash-fetch 1.12.0",
|
||||
"parity-path 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"parity-version 2.2.6",
|
||||
"parity-version 2.2.7",
|
||||
"parking_lot 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"rand 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"semver 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
@ -2537,7 +2537,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "parity-version"
|
||||
version = "2.2.6"
|
||||
version = "2.2.7"
|
||||
dependencies = [
|
||||
"parity-bytes 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"rlp 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
|
@ -2,7 +2,7 @@
|
||||
description = "Parity Ethereum client"
|
||||
name = "parity-ethereum"
|
||||
# NOTE Make sure to update util/version/Cargo.toml as well
|
||||
version = "2.2.6"
|
||||
version = "2.2.7"
|
||||
license = "GPL-3.0"
|
||||
authors = ["Parity Technologies <admin@parity.io>"]
|
||||
|
||||
|
@ -9,8 +9,7 @@
|
||||
"durationLimit": "0xd",
|
||||
"blockReward": {
|
||||
"0x0": "0x4563918244f40000",
|
||||
"0x42ae50": "0x29a2241af62c0000",
|
||||
"0x6c0840": "0x1bc16d674ec80000"
|
||||
"0x42ae50": "0x29a2241af62c0000"
|
||||
},
|
||||
"homesteadTransition": "0x118c30",
|
||||
"daoHardforkTransition": "0x1d4c00",
|
||||
@ -135,8 +134,7 @@
|
||||
],
|
||||
"eip100bTransition": "0x42ae50",
|
||||
"difficultyBombDelays": {
|
||||
"0x42ae50": "0x2dc6c0",
|
||||
"0x6c0840": "0x1e8480"
|
||||
"0x42ae50": "0x2dc6c0"
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -161,11 +159,7 @@
|
||||
"eip140Transition": "0x42ae50",
|
||||
"eip211Transition": "0x42ae50",
|
||||
"eip214Transition": "0x42ae50",
|
||||
"eip658Transition": "0x42ae50",
|
||||
"eip145Transition": "0x6c0840",
|
||||
"eip1014Transition": "0x6c0840",
|
||||
"eip1052Transition": "0x6c0840",
|
||||
"eip1283Transition": "0x6c0840"
|
||||
"eip658Transition": "0x42ae50"
|
||||
},
|
||||
"genesis": {
|
||||
"seal": {
|
||||
|
@ -1 +1 @@
|
||||
Subproject commit 2cd62aeec11da29766b30d500f2b9a96f1f28cf0
|
||||
Subproject commit 420f443477caa8516f1f9ee8122fafc3415c0f34
|
@ -1,42 +1,4 @@
|
||||
{ "block":
|
||||
[
|
||||
{
|
||||
"reference": "None",
|
||||
"comment": "This failing test is deemed skippable. Could not happen on a mainnet.",
|
||||
"failing": "GeneralStateTest_stCreate2",
|
||||
"subtests": ["RevertInCreateInInitCreate2_d0g0v0_Constantinople"]
|
||||
},
|
||||
{
|
||||
"reference": "None",
|
||||
"comment": "This failing test is deemed skippable. Could not happen on a mainnet.",
|
||||
"failing": "GeneralStateTest_stRevertTest",
|
||||
"subtests": ["RevertInCreateInInit_d0g0v0_Constantinople"]
|
||||
}
|
||||
],
|
||||
"state":
|
||||
[
|
||||
{
|
||||
"reference": "None",
|
||||
"comment": "This failing test is deemed skippable. Could not happen on a mainnet.",
|
||||
"failing": "stCreate2Test",
|
||||
"subtests": {
|
||||
"RevertInCreateInInitCreate2": {
|
||||
"subnumbers": ["1"],
|
||||
"chain": "Constantinople (test)"
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"reference": "None",
|
||||
"comment": "This failing test is deemed skippable. Could not happen on a mainnet.",
|
||||
"failing": "stRevertTest",
|
||||
"subtests": {
|
||||
"RevertInCreateInInit": {
|
||||
"subnumbers": ["1"],
|
||||
"chain": "Constantinople (test)"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
]
|
||||
"block": [],
|
||||
"state": []
|
||||
}
|
||||
|
@ -116,7 +116,12 @@ impl<'a, T: 'a, V: 'a, B: 'a> Ext for Externalities<'a, T, V, B>
|
||||
where T: Tracer, V: VMTracer, B: StateBackend
|
||||
{
|
||||
fn initial_storage_at(&self, key: &H256) -> vm::Result<H256> {
|
||||
if self.state.is_base_storage_root_unchanged(&self.origin_info.address)? {
|
||||
self.state.checkpoint_storage_at(0, &self.origin_info.address, key).map(|v| v.unwrap_or(H256::zero())).map_err(Into::into)
|
||||
} else {
|
||||
warn!(target: "externalities", "Detected existing account {:#x} where a forced contract creation happened.", self.origin_info.address);
|
||||
Ok(H256::zero())
|
||||
}
|
||||
}
|
||||
|
||||
fn storage_at(&self, key: &H256) -> vm::Result<H256> {
|
||||
|
@ -447,6 +447,11 @@ impl Account {
|
||||
}
|
||||
}
|
||||
|
||||
/// Whether the base storage root of this account is unchanged.
|
||||
pub fn is_base_storage_root_unchanged(&self) -> bool {
|
||||
self.original_storage_cache.is_none()
|
||||
}
|
||||
|
||||
/// Storage root where the account changes are based upon.
|
||||
pub fn base_storage_root(&self) -> H256 {
|
||||
self.storage_root
|
||||
|
@ -539,6 +539,13 @@ impl<B: Backend> State<B> {
|
||||
|a| a.as_ref().map_or(self.account_start_nonce, |account| *account.nonce()))
|
||||
}
|
||||
|
||||
/// Whether the base storage root of an account remains unchanged.
|
||||
pub fn is_base_storage_root_unchanged(&self, a: &Address) -> TrieResult<bool> {
|
||||
Ok(self.ensure_cached(a, RequireCache::None, true,
|
||||
|a| a.as_ref().map(|account| account.is_base_storage_root_unchanged()))?
|
||||
.unwrap_or(true))
|
||||
}
|
||||
|
||||
/// Get the storage root of account `a`.
|
||||
pub fn storage_root(&self, a: &Address) -> TrieResult<Option<H256>> {
|
||||
self.ensure_cached(a, RequireCache::None, true,
|
||||
|
@ -3,13 +3,17 @@
|
||||
set -e # fail on any error
|
||||
set -u # treat unset variables as error
|
||||
|
||||
TRACK=`awk -F '=' '/^track/ {print $2}' ./util/version/Cargo.toml`
|
||||
# some necromancy:
|
||||
# gsub(/"/, "", $2) deletes "qoutes"
|
||||
# gsub(/ /, "", $2) deletes whitespaces
|
||||
TRACK=`awk -F '=' '/^track/ {gsub(/"/, "", $2); gsub(/ /, "", $2); print $2}' ./util/version/Cargo.toml`
|
||||
echo Track is: $TRACK
|
||||
|
||||
case ${TRACK} in
|
||||
nightly) export GRADE="devel" CHANNEL="edge";;
|
||||
beta) export GRADE="stable" CHANNEL="beta";;
|
||||
stable) export GRADE="stable" CHANNEL="stable";;
|
||||
*) echo "No release" exit 0;;
|
||||
*) echo "No release" && exit 0;;
|
||||
esac
|
||||
|
||||
SNAP_PACKAGE="parity_"$VERSION"_"$BUILD_ARCH".snap"
|
||||
|
@ -53,12 +53,15 @@ const REQUEST_BACKOFF: [Duration; 4] = [
|
||||
Duration::from_secs(64)
|
||||
];
|
||||
|
||||
const NODE_LAST_SEEN_TIMEOUT: Duration = Duration::from_secs(24*60*60);
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct NodeEntry {
|
||||
pub id: NodeId,
|
||||
pub endpoint: NodeEndpoint,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct BucketEntry {
|
||||
pub address: NodeEntry,
|
||||
pub id_hash: H256,
|
||||
@ -89,6 +92,12 @@ struct FindNodeRequest {
|
||||
answered: bool,
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy)]
|
||||
enum PingReason {
|
||||
Default,
|
||||
FromDiscoveryRequest(NodeId)
|
||||
}
|
||||
|
||||
struct PingRequest {
|
||||
// Time when the request was sent
|
||||
sent_at: Instant,
|
||||
@ -99,8 +108,10 @@ struct PingRequest {
|
||||
// The hash Parity used to respond with (until rev 01f825b0e1f1c4c420197b51fc801cbe89284b29)
|
||||
#[deprecated()]
|
||||
deprecated_echo_hash: H256,
|
||||
reason: PingReason
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct NodeBucket {
|
||||
nodes: VecDeque<BucketEntry>, //sorted by last active
|
||||
}
|
||||
@ -178,7 +189,7 @@ impl<'a> Discovery<'a> {
|
||||
if self.node_buckets[dist].nodes.iter().any(|n| n.id_hash == id_hash) {
|
||||
return;
|
||||
}
|
||||
self.try_ping(e);
|
||||
self.try_ping(e, PingReason::Default);
|
||||
}
|
||||
}
|
||||
|
||||
@ -221,7 +232,7 @@ impl<'a> Discovery<'a> {
|
||||
} else { None }
|
||||
};
|
||||
if let Some(node) = ping {
|
||||
self.try_ping(node);
|
||||
self.try_ping(node, PingReason::Default);
|
||||
}
|
||||
Some(TableUpdates { added: added_map, removed: HashSet::new() })
|
||||
}
|
||||
@ -244,7 +255,7 @@ impl<'a> Discovery<'a> {
|
||||
fn update_new_nodes(&mut self) {
|
||||
while self.in_flight_pings.len() < MAX_NODES_PING {
|
||||
match self.adding_nodes.pop() {
|
||||
Some(next) => self.try_ping(next),
|
||||
Some(next) => self.try_ping(next, PingReason::Default),
|
||||
None => break,
|
||||
}
|
||||
}
|
||||
@ -298,7 +309,7 @@ impl<'a> Discovery<'a> {
|
||||
None // a and b are equal, so log distance is -inf
|
||||
}
|
||||
|
||||
fn try_ping(&mut self, node: NodeEntry) {
|
||||
fn try_ping(&mut self, node: NodeEntry, reason: PingReason) {
|
||||
if !self.is_allowed(&node) {
|
||||
trace!(target: "discovery", "Node {:?} not allowed", node);
|
||||
return;
|
||||
@ -313,7 +324,7 @@ impl<'a> Discovery<'a> {
|
||||
}
|
||||
|
||||
if self.in_flight_pings.len() < MAX_NODES_PING {
|
||||
self.ping(&node)
|
||||
self.ping(&node, reason)
|
||||
.unwrap_or_else(|e| {
|
||||
warn!(target: "discovery", "Error sending Ping packet: {:?}", e);
|
||||
});
|
||||
@ -322,7 +333,7 @@ impl<'a> Discovery<'a> {
|
||||
}
|
||||
}
|
||||
|
||||
fn ping(&mut self, node: &NodeEntry) -> Result<(), Error> {
|
||||
fn ping(&mut self, node: &NodeEntry, reason: PingReason) -> Result<(), Error> {
|
||||
let mut rlp = RlpStream::new_list(4);
|
||||
rlp.append(&PROTOCOL_VERSION);
|
||||
self.public_endpoint.to_rlp_list(&mut rlp);
|
||||
@ -336,6 +347,7 @@ impl<'a> Discovery<'a> {
|
||||
node: node.clone(),
|
||||
echo_hash: hash,
|
||||
deprecated_echo_hash: old_parity_hash,
|
||||
reason: reason
|
||||
});
|
||||
|
||||
trace!(target: "discovery", "Sent Ping to {:?} ; node_id={:#x}", &node.endpoint, node.id);
|
||||
@ -515,7 +527,7 @@ impl<'a> Discovery<'a> {
|
||||
if request.deprecated_echo_hash == echo_hash {
|
||||
trace!(target: "discovery", "Got Pong from an old parity-ethereum version.");
|
||||
}
|
||||
Some(request.node.clone())
|
||||
Some((request.node.clone(), request.reason.clone()))
|
||||
}
|
||||
};
|
||||
|
||||
@ -529,7 +541,10 @@ impl<'a> Discovery<'a> {
|
||||
},
|
||||
};
|
||||
|
||||
if let Some(node) = expected_node {
|
||||
if let Some((node, ping_reason)) = expected_node {
|
||||
if let PingReason::FromDiscoveryRequest(target) = ping_reason {
|
||||
self.respond_with_discovery(target, &node)?;
|
||||
}
|
||||
Ok(self.update_node(node))
|
||||
} else {
|
||||
debug!(target: "discovery", "Got unexpected Pong from {:?} ; request not found", &from);
|
||||
@ -537,21 +552,59 @@ impl<'a> Discovery<'a> {
|
||||
}
|
||||
}
|
||||
|
||||
fn on_find_node(&mut self, rlp: &Rlp, _node: &NodeId, from: &SocketAddr) -> Result<Option<TableUpdates>, Error> {
|
||||
fn on_find_node(&mut self, rlp: &Rlp, node_id: &NodeId, from: &SocketAddr) -> Result<Option<TableUpdates>, Error> {
|
||||
trace!(target: "discovery", "Got FindNode from {:?}", &from);
|
||||
let target: NodeId = rlp.val_at(0)?;
|
||||
let timestamp: u64 = rlp.val_at(1)?;
|
||||
self.check_timestamp(timestamp)?;
|
||||
|
||||
let node = NodeEntry {
|
||||
id: node_id.clone(),
|
||||
endpoint: NodeEndpoint {
|
||||
address: *from,
|
||||
udp_port: from.port()
|
||||
}
|
||||
};
|
||||
|
||||
if self.is_a_valid_known_node(&node) {
|
||||
self.respond_with_discovery(target, &node)?;
|
||||
} else {
|
||||
// Make sure the request source is actually there and responds to pings before actually responding
|
||||
self.try_ping(node, PingReason::FromDiscoveryRequest(target));
|
||||
}
|
||||
Ok(None)
|
||||
}
|
||||
|
||||
fn is_a_valid_known_node(&self, node: &NodeEntry) -> bool {
|
||||
let id_hash = keccak(node.id);
|
||||
let dist = match Discovery::distance(&self.id_hash, &id_hash) {
|
||||
Some(dist) => dist,
|
||||
None => {
|
||||
debug!(target: "discovery", "Got an incoming discovery request from self: {:?}", node);
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
let bucket = &self.node_buckets[dist];
|
||||
if let Some(known_node) = bucket.nodes.iter().find(|n| n.address.id == node.id) {
|
||||
debug!(target: "discovery", "Found a known node in a bucket when processing discovery: {:?}/{:?}", known_node, node);
|
||||
(known_node.address.endpoint == node.endpoint) && (known_node.last_seen.elapsed() < NODE_LAST_SEEN_TIMEOUT)
|
||||
} else {
|
||||
false
|
||||
}
|
||||
}
|
||||
|
||||
fn respond_with_discovery(&mut self, target: NodeId, node: &NodeEntry) -> Result<(), Error> {
|
||||
let nearest = self.nearest_node_entries(&target);
|
||||
if nearest.is_empty() {
|
||||
return Ok(None);
|
||||
return Ok(());
|
||||
}
|
||||
let mut packets = Discovery::prepare_neighbours_packets(&nearest);
|
||||
for p in packets.drain(..) {
|
||||
self.send_packet(PACKET_NEIGHBOURS, from, &p)?;
|
||||
self.send_packet(PACKET_NEIGHBOURS, &node.endpoint.address, &p)?;
|
||||
}
|
||||
trace!(target: "discovery", "Sent {} Neighbours to {:?}", nearest.len(), &from);
|
||||
Ok(None)
|
||||
trace!(target: "discovery", "Sent {} Neighbours to {:?}", nearest.len(), &node.endpoint);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn prepare_neighbours_packets(nearest: &[NodeEntry]) -> Vec<Bytes> {
|
||||
@ -827,7 +880,7 @@ mod tests {
|
||||
}
|
||||
|
||||
// After 4 discovery rounds, the first one should have learned about the rest.
|
||||
for _round in 0 .. 4 {
|
||||
for _round in 0 .. 5 {
|
||||
discovery_handlers[0].round();
|
||||
|
||||
let mut continue_loop = true;
|
||||
@ -835,9 +888,9 @@ mod tests {
|
||||
continue_loop = false;
|
||||
|
||||
// Process all queued messages.
|
||||
for i in 0 .. 5 {
|
||||
let src = discovery_handlers[i].public_endpoint.address.clone();
|
||||
while let Some(datagram) = discovery_handlers[i].dequeue_send() {
|
||||
for i in 0 .. 20 {
|
||||
let src = discovery_handlers[i%5].public_endpoint.address.clone();
|
||||
while let Some(datagram) = discovery_handlers[i%5].dequeue_send() {
|
||||
let dest = discovery_handlers.iter_mut()
|
||||
.find(|disc| datagram.address == disc.public_endpoint.address)
|
||||
.unwrap();
|
||||
@ -929,14 +982,14 @@ mod tests {
|
||||
let mut discovery = Discovery { request_backoff: &request_backoff, ..discovery };
|
||||
|
||||
for _ in 0..2 {
|
||||
discovery.ping(&node_entries[101]).unwrap();
|
||||
discovery.ping(&node_entries[101], PingReason::Default).unwrap();
|
||||
let num_nodes = total_bucket_nodes(&discovery.node_buckets);
|
||||
discovery.check_expired(Instant::now() + PING_TIMEOUT);
|
||||
let removed = num_nodes - total_bucket_nodes(&discovery.node_buckets);
|
||||
assert_eq!(removed, 0);
|
||||
}
|
||||
|
||||
discovery.ping(&node_entries[101]).unwrap();
|
||||
discovery.ping(&node_entries[101], PingReason::Default).unwrap();
|
||||
let num_nodes = total_bucket_nodes(&discovery.node_buckets);
|
||||
discovery.check_expired(Instant::now() + PING_TIMEOUT);
|
||||
let removed = num_nodes - total_bucket_nodes(&discovery.node_buckets);
|
||||
@ -1123,7 +1176,7 @@ mod tests {
|
||||
let mut discovery1 = Discovery::new(&key1, ep1.clone(), IpFilter::default());
|
||||
let mut discovery2 = Discovery::new(&key2, ep2.clone(), IpFilter::default());
|
||||
|
||||
discovery1.ping(&NodeEntry { id: discovery2.id, endpoint: ep2.clone() }).unwrap();
|
||||
discovery1.ping(&NodeEntry { id: discovery2.id, endpoint: ep2.clone() }, PingReason::Default).unwrap();
|
||||
let ping_data = discovery1.dequeue_send().unwrap();
|
||||
assert!(!discovery1.any_sends_queued());
|
||||
let data = &ping_data.payload[(32 + 65)..];
|
||||
|
@ -308,7 +308,15 @@ pub fn select_public_address(port: u16) -> SocketAddr {
|
||||
|
||||
pub fn map_external_address(local: &NodeEndpoint) -> Option<NodeEndpoint> {
|
||||
if let SocketAddr::V4(ref local_addr) = local.address {
|
||||
match search_gateway_from_timeout(*local_addr.ip(), Duration::new(5, 0)) {
|
||||
let local_ip = *local_addr.ip();
|
||||
let search_gateway_child = ::std::thread::spawn(move || {
|
||||
search_gateway_from_timeout(local_ip, Duration::new(5, 0))
|
||||
});
|
||||
let gateway_result = match search_gateway_child.join() {
|
||||
Err(_) => return None,
|
||||
Ok(gateway_result) => gateway_result,
|
||||
};
|
||||
match gateway_result {
|
||||
Err(ref err) => debug!("Gateway search error: {}", err),
|
||||
Ok(gateway) => {
|
||||
match gateway.get_external_ip() {
|
||||
|
@ -3,22 +3,22 @@
|
||||
[package]
|
||||
name = "parity-version"
|
||||
# NOTE: this value is used for Parity Ethereum version string (via env CARGO_PKG_VERSION)
|
||||
version = "2.2.6"
|
||||
version = "2.2.7"
|
||||
authors = ["Parity Technologies <admin@parity.io>"]
|
||||
build = "build.rs"
|
||||
|
||||
[package.metadata]
|
||||
# This versions track. Should be changed to `stable` or `beta` when on respective branches.
|
||||
# Used by auto-updater and for Parity version string.
|
||||
track = "beta"
|
||||
track = "stable"
|
||||
|
||||
# Network specific settings, used ONLY by auto-updater.
|
||||
# Latest supported fork blocks.
|
||||
# Indicates a critical release in this track (i.e. consensus issue).
|
||||
[package.metadata.networks]
|
||||
foundation = { forkBlock = 4370000, critical = false }
|
||||
foundation = { forkBlock = 4370000, critical = true }
|
||||
ropsten = { forkBlock = 4230000, critical = false }
|
||||
kovan = { forkBlock = 6600000, critical = true }
|
||||
kovan = { forkBlock = 9200000, critical = true }
|
||||
|
||||
[dependencies]
|
||||
parity-bytes = "0.1"
|
||||
|
Loading…
Reference in New Issue
Block a user