-
Notifications
You must be signed in to change notification settings - Fork 316
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
mock-consensus: 🌱 a genesis validator can be generated (#3902)
fixes #3816. see #3588. this also addresses part of #3934. this provides extension facilities to the mock consensus test node builder, which allows penumbra-app tests to define a single validator, and subsequently retrieve it from the chain state. see `mock_consensus_can_define_a_genesis_validator`. when run with `--no-capture` enabled, these logs will be visible: ``` 2024-02-28T23:00:43.751036Z DEBUG penumbra_stake::component::stake: adding validator identity to consensus set index, validator: penumbravalid172v76yyqwngcln2dxrs8ht0sjgswer3569yyhezgsz6aj97ecvqqyf3h9h at crates/core/component/stake/src/component/stake.rs:533 in penumbra_stake::component::stake::staking [...] 2024-02-28T23:00:43.776880Z INFO penumbra_app::server::consensus: genesis state is a full configuration at crates/core/app/src/server/consensus.rs:145 2024-02-28T23:00:43.780436Z DEBUG penumbra_app::app: finished committing state, jmt_root: RootHash("46dc0e9561f17eee61a2c13f517036d4d0a4c77c60362cb6cc165083675dcaf7") at crates/core/app/src/app/mod.rs:592 ``` logging facilities are provided so that helper warnings should be given to users that forget to call `with_penumbra_single_validator`, or provide an `AppState` object whose validator list would be overwritten. the `serde_json` dependency is removed from the mock consensus library, it is no longer used. a warning is added to the mock consensus library to note to future contributors that other penumbra dependencies should be avoided in that library. * #3588 * #3816 --------- Co-authored-by: Henry de Valence <hdevalence@penumbralabs.xyz>
- Loading branch information
1 parent
d6679fc
commit 60e2bd6
Showing
11 changed files
with
304 additions
and
39 deletions.
There are no files selected for viewing
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,118 @@ | ||
use { | ||
penumbra_genesis::AppState, | ||
penumbra_mock_consensus::builder::Builder, | ||
penumbra_proto::{ | ||
core::keys::v1::{GovernanceKey, IdentityKey}, | ||
penumbra::core::component::stake::v1::Validator as PenumbraValidator, | ||
}, | ||
}; | ||
|
||
/// Penumbra-specific extensions to the mock consensus builder. | ||
pub trait BuilderExt: Sized { | ||
/// The error thrown by [`with_penumbra_auto_app_state`] | ||
type Error; | ||
/// Add the provided Penumbra [`AppState`] to the builder. | ||
/// | ||
/// This will inject any configured validators into the state before serializing it into bytes. | ||
fn with_penumbra_auto_app_state(self, app_state: AppState) -> Result<Self, Self::Error>; | ||
} | ||
|
||
impl BuilderExt for Builder { | ||
type Error = anyhow::Error; | ||
fn with_penumbra_auto_app_state(self, app_state: AppState) -> Result<Self, Self::Error> { | ||
let Self { keyring, .. } = &self; | ||
|
||
let app_state = if keyring.is_empty() { | ||
// If there are no consensus keys to inject, pass along the provided app state. | ||
app_state | ||
} else { | ||
// Otherwise, generate a penumbra validator for each entry in the keyring... | ||
let validators = keyring | ||
.verification_keys() | ||
.cloned() | ||
.map(generate_penumbra_validator) | ||
.inspect(log_validator) | ||
.collect::<Vec<_>>(); | ||
// ...and then inject these validators into the app state. | ||
inject_penumbra_validators(app_state, validators)? | ||
}; | ||
|
||
// Serialize the app state into bytes, and add it to the builder. | ||
serde_json::to_vec(&app_state) | ||
.map_err(Self::Error::from) | ||
.map(|s| self.app_state(s)) | ||
} | ||
} | ||
|
||
/// Injects the given collection of [`Validator`s][PenumbraValidator] into the app state. | ||
fn inject_penumbra_validators( | ||
app_state: AppState, | ||
validators: Vec<PenumbraValidator>, | ||
) -> Result<AppState, anyhow::Error> { | ||
use AppState::{Checkpoint, Content}; | ||
match app_state { | ||
Checkpoint(_) => anyhow::bail!("checkpoint app state isn't supported"), | ||
Content(mut content) => { | ||
// Inject the builder's validators into the staking component's genesis state... | ||
let overwritten = std::mem::replace(&mut content.stake_content.validators, validators); | ||
// ...and log a warning if this overwrote any validators already in the app state. | ||
if !overwritten.is_empty() { | ||
tracing::warn!( | ||
?overwritten, | ||
"`with_penumbra_auto_app_state` overwrote validators in the given AppState" | ||
) | ||
} | ||
Ok(Content(content)) | ||
} | ||
} | ||
} | ||
|
||
/// Generates a [`Validator`][PenumbraValidator] given a consensus verification key. | ||
fn generate_penumbra_validator( | ||
consensus_key: ed25519_consensus::VerificationKey, | ||
) -> PenumbraValidator { | ||
/// A temporary stub for validator keys. | ||
/// | ||
/// An invalid key is intentionally provided here, until we have test coverage exercising the | ||
/// use of these keys. Once we need it we will: | ||
/// - generate a random signing key | ||
/// - get its verification key | ||
/// - use that for the identity key | ||
/// - throw the signing key away | ||
/// | ||
/// NB: for now, we will use the same key for governance. See the documentation of | ||
/// `GovernanceKey` for more information about cold storage of validator keys. | ||
const INVALID_KEY_BYTES: [u8; 32] = [0; 32]; | ||
|
||
PenumbraValidator { | ||
identity_key: Some(IdentityKey { | ||
ik: INVALID_KEY_BYTES.to_vec().clone(), | ||
}), | ||
governance_key: Some(GovernanceKey { | ||
gk: INVALID_KEY_BYTES.to_vec().clone(), | ||
}), | ||
consensus_key: consensus_key.as_bytes().to_vec(), | ||
enabled: true, | ||
sequence_number: 0, | ||
name: String::default(), | ||
website: String::default(), | ||
description: String::default(), | ||
funding_streams: Vec::default(), | ||
} | ||
} | ||
|
||
fn log_validator( | ||
PenumbraValidator { | ||
name, | ||
enabled, | ||
sequence_number, | ||
.. | ||
}: &PenumbraValidator, | ||
) { | ||
tracing::trace!( | ||
%name, | ||
%enabled, | ||
%sequence_number, | ||
"injecting validator into app state" | ||
) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.