mirror of
https://github.com/sigp/lighthouse.git
synced 2026-03-06 10:11:44 +00:00
Merge remote-tracking branch 'origin/stable' into back-merge-6.0.1
This commit is contained in:
4
.github/workflows/docker.yml
vendored
4
.github/workflows/docker.yml
vendored
@@ -13,8 +13,8 @@ concurrency:
|
|||||||
cancel-in-progress: true
|
cancel-in-progress: true
|
||||||
|
|
||||||
env:
|
env:
|
||||||
DOCKER_PASSWORD: ${{ secrets.DOCKER_PASSWORD }}
|
DOCKER_PASSWORD: ${{ secrets.DH_KEY }}
|
||||||
DOCKER_USERNAME: ${{ secrets.DOCKER_USERNAME }}
|
DOCKER_USERNAME: ${{ secrets.DH_ORG }}
|
||||||
# Enable self-hosted runners for the sigp repo only.
|
# Enable self-hosted runners for the sigp repo only.
|
||||||
SELF_HOSTED_RUNNERS: ${{ github.repository == 'sigp/lighthouse' }}
|
SELF_HOSTED_RUNNERS: ${{ github.repository == 'sigp/lighthouse' }}
|
||||||
|
|
||||||
|
|||||||
4
.github/workflows/release.yml
vendored
4
.github/workflows/release.yml
vendored
@@ -10,8 +10,8 @@ concurrency:
|
|||||||
cancel-in-progress: true
|
cancel-in-progress: true
|
||||||
|
|
||||||
env:
|
env:
|
||||||
DOCKER_PASSWORD: ${{ secrets.DOCKER_PASSWORD }}
|
DOCKER_PASSWORD: ${{ secrets.DH_KEY }}
|
||||||
DOCKER_USERNAME: ${{ secrets.DOCKER_USERNAME }}
|
DOCKER_USERNAME: ${{ secrets.DH_ORG }}
|
||||||
REPO_NAME: ${{ github.repository_owner }}/lighthouse
|
REPO_NAME: ${{ github.repository_owner }}/lighthouse
|
||||||
IMAGE_NAME: ${{ github.repository_owner }}/lighthouse
|
IMAGE_NAME: ${{ github.repository_owner }}/lighthouse
|
||||||
# Enable self-hosted runners for the sigp repo only.
|
# Enable self-hosted runners for the sigp repo only.
|
||||||
|
|||||||
8
Cargo.lock
generated
8
Cargo.lock
generated
@@ -834,7 +834,7 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "beacon_node"
|
name = "beacon_node"
|
||||||
version = "6.0.0"
|
version = "6.0.1"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"account_utils",
|
"account_utils",
|
||||||
"beacon_chain",
|
"beacon_chain",
|
||||||
@@ -1079,7 +1079,7 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "boot_node"
|
name = "boot_node"
|
||||||
version = "6.0.0"
|
version = "6.0.1"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"beacon_node",
|
"beacon_node",
|
||||||
"bytes",
|
"bytes",
|
||||||
@@ -4677,7 +4677,7 @@ checksum = "830d08ce1d1d941e6b30645f1a0eb5643013d835ce3779a5fc208261dbe10f55"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "lcli"
|
name = "lcli"
|
||||||
version = "6.0.0"
|
version = "6.0.1"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"account_utils",
|
"account_utils",
|
||||||
"beacon_chain",
|
"beacon_chain",
|
||||||
@@ -5247,7 +5247,7 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "lighthouse"
|
name = "lighthouse"
|
||||||
version = "6.0.0"
|
version = "6.0.1"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"account_manager",
|
"account_manager",
|
||||||
"account_utils",
|
"account_utils",
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "beacon_node"
|
name = "beacon_node"
|
||||||
version = "6.0.0"
|
version = "6.0.1"
|
||||||
authors = [
|
authors = [
|
||||||
"Paul Hauner <paul@paulhauner.com>",
|
"Paul Hauner <paul@paulhauner.com>",
|
||||||
"Age Manning <Age@AgeManning.com",
|
"Age Manning <Age@AgeManning.com",
|
||||||
|
|||||||
@@ -1037,7 +1037,9 @@ where
|
|||||||
);
|
);
|
||||||
|
|
||||||
// Check for states to reconstruct (in the background).
|
// Check for states to reconstruct (in the background).
|
||||||
if beacon_chain.config.reconstruct_historic_states {
|
if beacon_chain.config.reconstruct_historic_states
|
||||||
|
&& beacon_chain.store.get_oldest_block_slot() == 0
|
||||||
|
{
|
||||||
beacon_chain.store_migrator.process_reconstruction();
|
beacon_chain.store_migrator.process_reconstruction();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -26,8 +26,10 @@ const MIN_COMPACTION_PERIOD_SECONDS: u64 = 7200;
|
|||||||
const COMPACTION_FINALITY_DISTANCE: u64 = 1024;
|
const COMPACTION_FINALITY_DISTANCE: u64 = 1024;
|
||||||
/// Maximum number of blocks applied in each reconstruction burst.
|
/// Maximum number of blocks applied in each reconstruction burst.
|
||||||
///
|
///
|
||||||
/// This limits the amount of time that the finalization migration is paused for.
|
/// This limits the amount of time that the finalization migration is paused for. We set this
|
||||||
const BLOCKS_PER_RECONSTRUCTION: usize = 8192 * 4;
|
/// conservatively because pausing the finalization migration for too long can cause hot state
|
||||||
|
/// cache misses and excessive disk use.
|
||||||
|
const BLOCKS_PER_RECONSTRUCTION: usize = 1024;
|
||||||
|
|
||||||
/// Default number of epochs to wait between finalization migrations.
|
/// Default number of epochs to wait between finalization migrations.
|
||||||
pub const DEFAULT_EPOCHS_PER_MIGRATION: u64 = 1;
|
pub const DEFAULT_EPOCHS_PER_MIGRATION: u64 = 1;
|
||||||
|
|||||||
@@ -152,7 +152,7 @@ pub fn delete_old_schema_freezer_data<T: BeaconChainTypes>(
|
|||||||
db.cold_db.do_atomically(cold_ops)?;
|
db.cold_db.do_atomically(cold_ops)?;
|
||||||
|
|
||||||
// In order to reclaim space, we need to compact the freezer DB as well.
|
// In order to reclaim space, we need to compact the freezer DB as well.
|
||||||
db.cold_db.compact()?;
|
db.compact_freezer()?;
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -141,10 +141,6 @@ impl<E: EthSpec> NetworkBehaviour for PeerManager<E> {
|
|||||||
debug!(self.log, "Failed to dial peer"; "peer_id"=> ?peer_id, "error" => %ClearDialError(error));
|
debug!(self.log, "Failed to dial peer"; "peer_id"=> ?peer_id, "error" => %ClearDialError(error));
|
||||||
self.on_dial_failure(peer_id);
|
self.on_dial_failure(peer_id);
|
||||||
}
|
}
|
||||||
FromSwarm::ExternalAddrConfirmed(_) => {
|
|
||||||
// We have an external address confirmed, means we are able to do NAT traversal.
|
|
||||||
metrics::set_gauge_vec(&metrics::NAT_OPEN, &["libp2p"], 1);
|
|
||||||
}
|
|
||||||
_ => {
|
_ => {
|
||||||
// NOTE: FromSwarm is a non exhaustive enum so updates should be based on release
|
// NOTE: FromSwarm is a non exhaustive enum so updates should be based on release
|
||||||
// notes more than compiler feedback
|
// notes more than compiler feedback
|
||||||
|
|||||||
@@ -86,7 +86,7 @@ pub struct SubnetService<T: BeaconChainTypes> {
|
|||||||
subscriptions: HashSetDelay<Subnet>,
|
subscriptions: HashSetDelay<Subnet>,
|
||||||
|
|
||||||
/// Subscriptions that need to be executed in the future.
|
/// Subscriptions that need to be executed in the future.
|
||||||
scheduled_subscriptions: HashSetDelay<Subnet>,
|
scheduled_subscriptions: HashSetDelay<ExactSubnet>,
|
||||||
|
|
||||||
/// A list of permanent subnets that this node is subscribed to.
|
/// A list of permanent subnets that this node is subscribed to.
|
||||||
// TODO: Shift this to a dynamic bitfield
|
// TODO: Shift this to a dynamic bitfield
|
||||||
@@ -484,8 +484,10 @@ impl<T: BeaconChainTypes> SubnetService<T> {
|
|||||||
self.subscribe_to_subnet_immediately(subnet, slot + 1)?;
|
self.subscribe_to_subnet_immediately(subnet, slot + 1)?;
|
||||||
} else {
|
} else {
|
||||||
// This is a future slot, schedule subscribing.
|
// This is a future slot, schedule subscribing.
|
||||||
|
// We need to include the slot to make the key unique to prevent overwriting the entry
|
||||||
|
// for the same subnet.
|
||||||
self.scheduled_subscriptions
|
self.scheduled_subscriptions
|
||||||
.insert_at(subnet, time_to_subscription_start);
|
.insert_at(ExactSubnet { subnet, slot }, time_to_subscription_start);
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
@@ -626,7 +628,8 @@ impl<T: BeaconChainTypes> Stream for SubnetService<T> {
|
|||||||
// Process scheduled subscriptions that might be ready, since those can extend a soon to
|
// Process scheduled subscriptions that might be ready, since those can extend a soon to
|
||||||
// expire subscription.
|
// expire subscription.
|
||||||
match self.scheduled_subscriptions.poll_next_unpin(cx) {
|
match self.scheduled_subscriptions.poll_next_unpin(cx) {
|
||||||
Poll::Ready(Some(Ok(subnet))) => {
|
Poll::Ready(Some(Ok(exact_subnet))) => {
|
||||||
|
let ExactSubnet { subnet, .. } = exact_subnet;
|
||||||
let current_slot = self.beacon_chain.slot_clock.now().unwrap_or_default();
|
let current_slot = self.beacon_chain.slot_clock.now().unwrap_or_default();
|
||||||
if let Err(e) = self.subscribe_to_subnet_immediately(subnet, current_slot + 1) {
|
if let Err(e) = self.subscribe_to_subnet_immediately(subnet, current_slot + 1) {
|
||||||
debug!(self.log, "Failed to subscribe to short lived subnet"; "subnet" => ?subnet, "err" => e);
|
debug!(self.log, "Failed to subscribe to short lived subnet"; "subnet" => ?subnet, "err" => e);
|
||||||
|
|||||||
@@ -500,12 +500,15 @@ mod test {
|
|||||||
// subscription config
|
// subscription config
|
||||||
let committee_count = 1;
|
let committee_count = 1;
|
||||||
|
|
||||||
// Makes 2 validator subscriptions to the same subnet but at different slots.
|
// Makes 3 validator subscriptions to the same subnet but at different slots.
|
||||||
// There should be just 1 unsubscription event for the later slot subscription (subscription_slot2).
|
// There should be just 1 unsubscription event for each of the later slots subscriptions
|
||||||
|
// (subscription_slot2 and subscription_slot3).
|
||||||
let subscription_slot1 = 0;
|
let subscription_slot1 = 0;
|
||||||
let subscription_slot2 = MIN_PEER_DISCOVERY_SLOT_LOOK_AHEAD + 4;
|
let subscription_slot2 = MIN_PEER_DISCOVERY_SLOT_LOOK_AHEAD + 4;
|
||||||
|
let subscription_slot3 = subscription_slot2 * 2;
|
||||||
let com1 = MIN_PEER_DISCOVERY_SLOT_LOOK_AHEAD + 4;
|
let com1 = MIN_PEER_DISCOVERY_SLOT_LOOK_AHEAD + 4;
|
||||||
let com2 = 0;
|
let com2 = 0;
|
||||||
|
let com3 = CHAIN.chain.spec.attestation_subnet_count - com1;
|
||||||
|
|
||||||
// create the attestation service and subscriptions
|
// create the attestation service and subscriptions
|
||||||
let mut subnet_service = get_subnet_service();
|
let mut subnet_service = get_subnet_service();
|
||||||
@@ -532,6 +535,13 @@ mod test {
|
|||||||
true,
|
true,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
let sub3 = get_subscription(
|
||||||
|
com3,
|
||||||
|
current_slot + Slot::new(subscription_slot3),
|
||||||
|
committee_count,
|
||||||
|
true,
|
||||||
|
);
|
||||||
|
|
||||||
let subnet_id1 = SubnetId::compute_subnet::<MainnetEthSpec>(
|
let subnet_id1 = SubnetId::compute_subnet::<MainnetEthSpec>(
|
||||||
current_slot + Slot::new(subscription_slot1),
|
current_slot + Slot::new(subscription_slot1),
|
||||||
com1,
|
com1,
|
||||||
@@ -548,12 +558,23 @@ mod test {
|
|||||||
)
|
)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
|
let subnet_id3 = SubnetId::compute_subnet::<MainnetEthSpec>(
|
||||||
|
current_slot + Slot::new(subscription_slot3),
|
||||||
|
com3,
|
||||||
|
committee_count,
|
||||||
|
&subnet_service.beacon_chain.spec,
|
||||||
|
)
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
// Assert that subscriptions are different but their subnet is the same
|
// Assert that subscriptions are different but their subnet is the same
|
||||||
assert_ne!(sub1, sub2);
|
assert_ne!(sub1, sub2);
|
||||||
|
assert_ne!(sub1, sub3);
|
||||||
|
assert_ne!(sub2, sub3);
|
||||||
assert_eq!(subnet_id1, subnet_id2);
|
assert_eq!(subnet_id1, subnet_id2);
|
||||||
|
assert_eq!(subnet_id1, subnet_id3);
|
||||||
|
|
||||||
// submit the subscriptions
|
// submit the subscriptions
|
||||||
subnet_service.validator_subscriptions(vec![sub1, sub2].into_iter());
|
subnet_service.validator_subscriptions(vec![sub1, sub2, sub3].into_iter());
|
||||||
|
|
||||||
// Unsubscription event should happen at the end of the slot.
|
// Unsubscription event should happen at the end of the slot.
|
||||||
// We wait for 2 slots, to avoid timeout issues
|
// We wait for 2 slots, to avoid timeout issues
|
||||||
@@ -590,10 +611,36 @@ mod test {
|
|||||||
// If the permanent and short lived subnets are different, we should get an unsubscription event.
|
// If the permanent and short lived subnets are different, we should get an unsubscription event.
|
||||||
if !subnet_service.is_subscribed(&Subnet::Attestation(subnet_id1)) {
|
if !subnet_service.is_subscribed(&Subnet::Attestation(subnet_id1)) {
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
[expected_subscription, expected_unsubscription],
|
[
|
||||||
|
expected_subscription.clone(),
|
||||||
|
expected_unsubscription.clone(),
|
||||||
|
],
|
||||||
second_subscribe_event[..]
|
second_subscribe_event[..]
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let subscription_slot = current_slot + subscription_slot3 - 1;
|
||||||
|
|
||||||
|
let wait_slots = subnet_service
|
||||||
|
.beacon_chain
|
||||||
|
.slot_clock
|
||||||
|
.duration_to_slot(subscription_slot)
|
||||||
|
.unwrap()
|
||||||
|
.as_millis() as u64
|
||||||
|
/ SLOT_DURATION_MILLIS;
|
||||||
|
|
||||||
|
let no_events = dbg!(get_events(&mut subnet_service, None, wait_slots as u32).await);
|
||||||
|
|
||||||
|
assert_eq!(no_events, []);
|
||||||
|
|
||||||
|
let third_subscribe_event = get_events(&mut subnet_service, None, 2).await;
|
||||||
|
|
||||||
|
if !subnet_service.is_subscribed(&Subnet::Attestation(subnet_id1)) {
|
||||||
|
assert_eq!(
|
||||||
|
[expected_subscription, expected_unsubscription],
|
||||||
|
third_subscribe_event[..]
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[tokio::test]
|
#[tokio::test]
|
||||||
|
|||||||
@@ -171,7 +171,10 @@ impl<T: BeaconChainTypes> SingleBlockLookup<T> {
|
|||||||
self.awaiting_parent.is_some()
|
self.awaiting_parent.is_some()
|
||||||
|| self.block_request_state.state.is_awaiting_event()
|
|| self.block_request_state.state.is_awaiting_event()
|
||||||
|| match &self.component_requests {
|
|| match &self.component_requests {
|
||||||
ComponentRequests::WaitingForBlock => true,
|
// If components are waiting for the block request to complete, here we should
|
||||||
|
// check if the`block_request_state.state.is_awaiting_event(). However we already
|
||||||
|
// checked that above, so `WaitingForBlock => false` is equivalent.
|
||||||
|
ComponentRequests::WaitingForBlock => false,
|
||||||
ComponentRequests::ActiveBlobRequest(request, _) => {
|
ComponentRequests::ActiveBlobRequest(request, _) => {
|
||||||
request.state.is_awaiting_event()
|
request.state.is_awaiting_event()
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2484,6 +2484,45 @@ impl<E: EthSpec, Hot: ItemStore<E>, Cold: ItemStore<E>> HotColdDB<E, Hot, Cold>
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Run a compaction pass on the freezer DB to free up space used by deleted states.
|
||||||
|
pub fn compact_freezer(&self) -> Result<(), Error> {
|
||||||
|
let current_schema_columns = vec![
|
||||||
|
DBColumn::BeaconColdStateSummary,
|
||||||
|
DBColumn::BeaconStateSnapshot,
|
||||||
|
DBColumn::BeaconStateDiff,
|
||||||
|
DBColumn::BeaconStateRoots,
|
||||||
|
];
|
||||||
|
|
||||||
|
// We can remove this once schema V21 has been gone for a while.
|
||||||
|
let previous_schema_columns = vec![
|
||||||
|
DBColumn::BeaconState,
|
||||||
|
DBColumn::BeaconStateSummary,
|
||||||
|
DBColumn::BeaconBlockRootsChunked,
|
||||||
|
DBColumn::BeaconStateRootsChunked,
|
||||||
|
DBColumn::BeaconRestorePoint,
|
||||||
|
DBColumn::BeaconHistoricalRoots,
|
||||||
|
DBColumn::BeaconRandaoMixes,
|
||||||
|
DBColumn::BeaconHistoricalSummaries,
|
||||||
|
];
|
||||||
|
let mut columns = current_schema_columns;
|
||||||
|
columns.extend(previous_schema_columns);
|
||||||
|
|
||||||
|
for column in columns {
|
||||||
|
info!(
|
||||||
|
self.log,
|
||||||
|
"Starting compaction";
|
||||||
|
"column" => ?column
|
||||||
|
);
|
||||||
|
self.cold_db.compact_column(column)?;
|
||||||
|
info!(
|
||||||
|
self.log,
|
||||||
|
"Finishing compaction";
|
||||||
|
"column" => ?column
|
||||||
|
);
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
/// Return `true` if compaction on finalization/pruning is enabled.
|
/// Return `true` if compaction on finalization/pruning is enabled.
|
||||||
pub fn compact_on_prune(&self) -> bool {
|
pub fn compact_on_prune(&self) -> bool {
|
||||||
self.config.compact_on_prune
|
self.config.compact_on_prune
|
||||||
@@ -2875,6 +2914,7 @@ impl<E: EthSpec, Hot: ItemStore<E>, Cold: ItemStore<E>> HotColdDB<E, Hot, Cold>
|
|||||||
//
|
//
|
||||||
// We can remove this once schema V21 has been gone for a while.
|
// We can remove this once schema V21 has been gone for a while.
|
||||||
let previous_schema_columns = vec![
|
let previous_schema_columns = vec![
|
||||||
|
DBColumn::BeaconState,
|
||||||
DBColumn::BeaconStateSummary,
|
DBColumn::BeaconStateSummary,
|
||||||
DBColumn::BeaconBlockRootsChunked,
|
DBColumn::BeaconBlockRootsChunked,
|
||||||
DBColumn::BeaconStateRootsChunked,
|
DBColumn::BeaconStateRootsChunked,
|
||||||
@@ -2916,7 +2956,7 @@ impl<E: EthSpec, Hot: ItemStore<E>, Cold: ItemStore<E>> HotColdDB<E, Hot, Cold>
|
|||||||
self.cold_db.do_atomically(cold_ops)?;
|
self.cold_db.do_atomically(cold_ops)?;
|
||||||
|
|
||||||
// In order to reclaim space, we need to compact the freezer DB as well.
|
// In order to reclaim space, we need to compact the freezer DB as well.
|
||||||
self.cold_db.compact()?;
|
self.compact_freezer()?;
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "boot_node"
|
name = "boot_node"
|
||||||
version = "6.0.0"
|
version = "6.0.1"
|
||||||
authors = ["Sigma Prime <contact@sigmaprime.io>"]
|
authors = ["Sigma Prime <contact@sigmaprime.io>"]
|
||||||
edition = { workspace = true }
|
edition = { workspace = true }
|
||||||
|
|
||||||
|
|||||||
@@ -17,8 +17,8 @@ pub const VERSION: &str = git_version!(
|
|||||||
// NOTE: using --match instead of --exclude for compatibility with old Git
|
// NOTE: using --match instead of --exclude for compatibility with old Git
|
||||||
"--match=thiswillnevermatchlol"
|
"--match=thiswillnevermatchlol"
|
||||||
],
|
],
|
||||||
prefix = "Lighthouse/v6.0.0-",
|
prefix = "Lighthouse/v6.0.1-",
|
||||||
fallback = "Lighthouse/v6.0.0"
|
fallback = "Lighthouse/v6.0.1"
|
||||||
);
|
);
|
||||||
|
|
||||||
/// Returns the first eight characters of the latest commit hash for this build.
|
/// Returns the first eight characters of the latest commit hash for this build.
|
||||||
|
|||||||
@@ -235,14 +235,14 @@ pub fn observe_nat() -> NatState {
|
|||||||
|
|
||||||
let libp2p_ipv4 = lighthouse_network::metrics::get_int_gauge(
|
let libp2p_ipv4 = lighthouse_network::metrics::get_int_gauge(
|
||||||
&lighthouse_network::metrics::NAT_OPEN,
|
&lighthouse_network::metrics::NAT_OPEN,
|
||||||
&["libp2p"],
|
&["libp2p_ipv4"],
|
||||||
)
|
)
|
||||||
.map(|g| g.get() == 1)
|
.map(|g| g.get() == 1)
|
||||||
.unwrap_or_default();
|
.unwrap_or_default();
|
||||||
|
|
||||||
let libp2p_ipv6 = lighthouse_network::metrics::get_int_gauge(
|
let libp2p_ipv6 = lighthouse_network::metrics::get_int_gauge(
|
||||||
&lighthouse_network::metrics::NAT_OPEN,
|
&lighthouse_network::metrics::NAT_OPEN,
|
||||||
&["libp2p"],
|
&["libp2p_ipv6"],
|
||||||
)
|
)
|
||||||
.map(|g| g.get() == 1)
|
.map(|g| g.get() == 1)
|
||||||
.unwrap_or_default();
|
.unwrap_or_default();
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "lcli"
|
name = "lcli"
|
||||||
description = "Lighthouse CLI (modeled after zcli)"
|
description = "Lighthouse CLI (modeled after zcli)"
|
||||||
version = "6.0.0"
|
version = "6.0.1"
|
||||||
authors = ["Paul Hauner <paul@paulhauner.com>"]
|
authors = ["Paul Hauner <paul@paulhauner.com>"]
|
||||||
edition = { workspace = true }
|
edition = { workspace = true }
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "lighthouse"
|
name = "lighthouse"
|
||||||
version = "6.0.0"
|
version = "6.0.1"
|
||||||
authors = ["Sigma Prime <contact@sigmaprime.io>"]
|
authors = ["Sigma Prime <contact@sigmaprime.io>"]
|
||||||
edition = { workspace = true }
|
edition = { workspace = true }
|
||||||
autotests = false
|
autotests = false
|
||||||
|
|||||||
Reference in New Issue
Block a user