Skip to content

Commit

Permalink
Rename TransactionAuthorizationData back to just AuthorizationData
Browse files Browse the repository at this point in the history
We don't need the differentiation because we can use SigningRequest and
SigningResponse, which are specific to only the threshold backend and do
not need to leak.
  • Loading branch information
plaidfinch committed Mar 23, 2024
1 parent a93178d commit 2c06897
Show file tree
Hide file tree
Showing 19 changed files with 135 additions and 244 deletions.
6 changes: 2 additions & 4 deletions crates/core/app/src/action_handler/actions/submit.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,9 +24,7 @@ use penumbra_proto::{DomainType, StateWriteProto as _};
use penumbra_sct::component::clock::EpochRead;
use penumbra_sct::component::tree::SctRead;
use penumbra_shielded_pool::component::AssetRegistry;
use penumbra_transaction::{
Transaction, TransactionAuthorizationData, TransactionPlan, WitnessData,
};
use penumbra_transaction::{AuthorizationData, Transaction, TransactionPlan, WitnessData};

use crate::action_handler::AppActionHandler;
use crate::community_pool_ext::CommunityPoolStateWriteExt;
Expand Down Expand Up @@ -372,7 +370,7 @@ async fn build_community_pool_transaction(
anchor: penumbra_tct::Tree::new().root(),
state_commitment_proofs: Default::default(),
},
&TransactionAuthorizationData {
&AuthorizationData {
effect_hash: Some(effect_hash),
spend_auths: Default::default(),
delegator_vote_auths: Default::default(),
Expand Down
122 changes: 22 additions & 100 deletions crates/core/transaction/src/auth_data.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,22 +3,10 @@ use decaf377_rdsa::{Signature, SpendAuth};
use penumbra_proto::{core::transaction::v1 as pb, DomainType};
use penumbra_txhash::EffectHash;

/// Authorization data returned in response to some signing request, which may be a request to
/// authorize a transaction, a validator definition, or a validator vote.
#[derive(Clone, Debug)]
pub enum AuthorizationData {
/// Authorization data for a transaction.
Transaction(TransactionAuthorizationData),
/// Authorization signature for a validator definition.
ValidatorDefinition(Signature<SpendAuth>),
/// Authorization signature for a validator vote.
ValidatorVote(Signature<SpendAuth>),
}

/// Authorization data returned in response to a
/// [`TransactionDescription`](crate::TransactionDescription).
#[derive(Clone, Debug)]
pub struct TransactionAuthorizationData {
pub struct AuthorizationData {
/// The computed authorization hash for the approved transaction.
pub effect_hash: Option<EffectHash>,
/// The required spend authorization signatures, returned in the same order as the Spend actions
Expand All @@ -33,101 +21,35 @@ impl DomainType for AuthorizationData {
type Proto = pb::AuthorizationData;
}

impl From<TransactionAuthorizationData> for AuthorizationData {
fn from(msg: TransactionAuthorizationData) -> Self {
Self::Transaction(msg)
}
}

impl From<TransactionAuthorizationData> for pb::AuthorizationData {
fn from(msg: TransactionAuthorizationData) -> Self {
AuthorizationData::from(msg).into()
}
}

impl From<AuthorizationData> for pb::AuthorizationData {
fn from(msg: AuthorizationData) -> Self {
match msg {
AuthorizationData::Transaction(TransactionAuthorizationData {
effect_hash,
spend_auths,
delegator_vote_auths,
}) => Self {
effect_hash: effect_hash.map(Into::into),
spend_auths: spend_auths.into_iter().map(Into::into).collect(),
delegator_vote_auths: delegator_vote_auths.into_iter().map(Into::into).collect(),
validator_definition_auth: None,
validator_vote_auth: None,
},
AuthorizationData::ValidatorDefinition(sig) => Self {
effect_hash: None,
spend_auths: vec![],
delegator_vote_auths: vec![],
validator_definition_auth: Some(sig.into()),
validator_vote_auth: None,
},
AuthorizationData::ValidatorVote(sig) => Self {
effect_hash: None,
spend_auths: vec![],
delegator_vote_auths: vec![],
validator_definition_auth: None,
validator_vote_auth: Some(sig.into()),
},
Self {
effect_hash: msg.effect_hash.map(Into::into),
spend_auths: msg.spend_auths.into_iter().map(Into::into).collect(),
delegator_vote_auths: msg
.delegator_vote_auths
.into_iter()
.map(Into::into)
.collect(),
}
}
}

impl TryFrom<pb::AuthorizationData> for TransactionAuthorizationData {
type Error = anyhow::Error;
fn try_from(value: pb::AuthorizationData) -> Result<Self, Self::Error> {
let data = value.try_into()?;
let kind = match data {
AuthorizationData::Transaction(_) => "transaction",
AuthorizationData::ValidatorDefinition(_) => "validator definition",
AuthorizationData::ValidatorVote(_) => "validator vote",
};
let AuthorizationData::Transaction(data) = data else {
anyhow::bail!(
"expected transaction authorization data but got {kind} authorization data"
);
};
Ok(data)
}
}

impl TryFrom<pb::AuthorizationData> for AuthorizationData {
type Error = anyhow::Error;
fn try_from(value: pb::AuthorizationData) -> Result<Self, Self::Error> {
if let Some(sig) = value.validator_definition_auth {
if value.effect_hash.is_some()
|| !value.spend_auths.is_empty()
|| !value.delegator_vote_auths.is_empty()
{
anyhow::bail!("unexpected fields in validator definition authorization");
}
Ok(Self::ValidatorDefinition(TryInto::try_into(sig)?))
} else if let Some(sig) = value.validator_vote_auth {
if value.effect_hash.is_some()
|| !value.spend_auths.is_empty()
|| !value.delegator_vote_auths.is_empty()
{
anyhow::bail!("unexpected fields in validator vote authorization");
}
Ok(Self::ValidatorVote(TryInto::try_into(sig)?))
} else {
Ok(Self::Transaction(TransactionAuthorizationData {
effect_hash: value.effect_hash.map(TryInto::try_into).transpose()?,
spend_auths: value
.spend_auths
.into_iter()
.map(TryInto::try_into)
.collect::<Result<_, _>>()?,
delegator_vote_auths: value
.delegator_vote_auths
.into_iter()
.map(TryInto::try_into)
.collect::<Result<_, _>>()?,
}))
}
Ok(Self {
effect_hash: value.effect_hash.map(TryInto::try_into).transpose()?,
spend_auths: value
.spend_auths
.into_iter()
.map(TryInto::try_into)
.collect::<Result<_, _>>()?,
delegator_vote_auths: value
.delegator_vote_auths
.into_iter()
.map(TryInto::try_into)
.collect::<Result<_, _>>()?,
})
}
}
2 changes: 1 addition & 1 deletion crates/core/transaction/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ pub mod plan;
pub mod view;

pub use action::Action;
pub use auth_data::{AuthorizationData, TransactionAuthorizationData};
pub use auth_data::AuthorizationData;
pub use detection_data::DetectionData;
pub use error::Error;
pub use is_action::IsAction;
Expand Down
6 changes: 3 additions & 3 deletions crates/core/transaction/src/plan/auth.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ use rand::{CryptoRng, RngCore};

use penumbra_keys::keys::SpendKey;

use crate::{TransactionAuthorizationData, TransactionPlan};
use crate::{AuthorizationData, TransactionPlan};

impl TransactionPlan {
/// Authorize this [`TransactionPlan`] with the provided [`SpendKey`].
Expand All @@ -13,7 +13,7 @@ impl TransactionPlan {
&self,
mut rng: R,
sk: &SpendKey,
) -> Result<TransactionAuthorizationData> {
) -> Result<AuthorizationData> {
let effect_hash = self.effect_hash(sk.full_viewing_key())?;
let mut spend_auths = Vec::new();
let mut delegator_vote_auths = Vec::new();
Expand All @@ -30,7 +30,7 @@ impl TransactionPlan {
let auth_sig = rsk.sign(&mut rng, effect_hash.as_ref());
delegator_vote_auths.push(auth_sig);
}
Ok(TransactionAuthorizationData {
Ok(AuthorizationData {
effect_hash: Some(effect_hash),
spend_auths,
delegator_vote_auths,
Expand Down
10 changes: 4 additions & 6 deletions crates/core/transaction/src/plan/build.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,7 @@ use penumbra_txhash::AuthorizingData;

use super::TransactionPlan;
use crate::ActionPlan;
use crate::{
action::Action, Transaction, TransactionAuthorizationData, TransactionBody, WitnessData,
};
use crate::{action::Action, AuthorizationData, Transaction, TransactionBody, WitnessData};

impl TransactionPlan {
/// Builds a [`TransactionPlan`] by slotting in the
Expand Down Expand Up @@ -48,7 +46,7 @@ impl TransactionPlan {
/// and assemble the transaction.
pub fn apply_auth_data(
&self,
auth_data: &TransactionAuthorizationData,
auth_data: &AuthorizationData,
mut transaction: Transaction,
) -> Result<Transaction> {
// Do some basic input sanity-checking.
Expand Down Expand Up @@ -119,7 +117,7 @@ impl TransactionPlan {
self,
full_viewing_key: &FullViewingKey,
witness_data: &WitnessData,
auth_data: &TransactionAuthorizationData,
auth_data: &AuthorizationData,
) -> Result<Transaction> {
// TODO: stream progress updates
// 1. Build each action.
Expand Down Expand Up @@ -155,7 +153,7 @@ impl TransactionPlan {
self,
full_viewing_key: &FullViewingKey,
witness_data: &WitnessData,
auth_data: &TransactionAuthorizationData,
auth_data: &AuthorizationData,
) -> Result<Transaction> {
// Clone the witness data into an Arc so it can be shared between tasks.
let witness_data = std::sync::Arc::new(witness_data.clone());
Expand Down
12 changes: 6 additions & 6 deletions crates/custody/src/soft_kms.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ use penumbra_proto::{
custody::v1::{self as pb, AuthorizeResponse},
Message as _,
};
use penumbra_transaction::{AuthorizationData, TransactionAuthorizationData};
use penumbra_transaction::AuthorizationData;
use rand_core::OsRng;
use tonic::{async_trait, Request, Response, Status};

Expand All @@ -37,7 +37,7 @@ impl SoftKms {

/// Attempt to authorize the requested [`TransactionPlan`](penumbra_transaction::TransactionPlan).
#[tracing::instrument(skip(self, request), name = "softhsm_sign")]
pub fn sign(&self, request: &AuthorizeRequest) -> anyhow::Result<TransactionAuthorizationData> {
pub fn sign(&self, request: &AuthorizeRequest) -> anyhow::Result<AuthorizationData> {
tracing::debug!(?request.plan);

for policy in &self.config.auth_policy {
Expand Down Expand Up @@ -123,12 +123,12 @@ impl pb::custody_service_server::CustodyService for SoftKms {
.try_into()
.map_err(|e: anyhow::Error| Status::invalid_argument(e.to_string()))?;

let signature = self
let validator_definition_auth = self
.sign_validator_definition(&request)
.map_err(|e| Status::unauthenticated(format!("{e:#}")))?;

let authorization_response = pb::AuthorizeValidatorDefinitionResponse {
data: Some(AuthorizationData::ValidatorDefinition(signature).into()),
validator_definition_auth: Some(validator_definition_auth.into()),
};

Ok(Response::new(authorization_response))
Expand All @@ -143,12 +143,12 @@ impl pb::custody_service_server::CustodyService for SoftKms {
.try_into()
.map_err(|e: anyhow::Error| Status::invalid_argument(e.to_string()))?;

let signature = self
let validator_vote_auth = self
.sign_validator_vote(&request)
.map_err(|e| Status::unauthenticated(format!("{e:#}")))?;

let authorization_response = pb::AuthorizeValidatorVoteResponse {
data: Some(AuthorizationData::ValidatorVote(signature).into()),
validator_vote_auth: Some(validator_vote_auth.into()),
};

Ok(Response::new(authorization_response))
Expand Down
25 changes: 20 additions & 5 deletions crates/custody/src/threshold.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,11 @@ use tonic::{async_trait, Request, Response, Status};

use penumbra_keys::{keys::AddressIndex, Address, FullViewingKey};
use penumbra_proto::{custody::v1 as pb, DomainType};
use penumbra_transaction::AuthorizationData;

use crate::{AuthorizeRequest, AuthorizeValidatorDefinitionRequest, AuthorizeValidatorVoteRequest};

pub use self::config::Config;
pub use self::sign::SigningRequest;
pub use self::sign::{SigningRequest, SigningResponse};

mod config;
mod dkg;
Expand Down Expand Up @@ -190,7 +189,7 @@ impl<T> Threshold<T> {

impl<T: Terminal> Threshold<T> {
/// Try and create the necessary signatures to authorize the transaction plan.
async fn authorize(&self, request: SigningRequest) -> Result<AuthorizationData> {
async fn authorize(&self, request: SigningRequest) -> Result<SigningResponse> {
// Round 1
let (round1_message, state1) = sign::coordinator_round1(&mut OsRng, &self.config, request)?;
self.terminal
Expand Down Expand Up @@ -280,6 +279,12 @@ impl<T: Terminal + Sync + Send + 'static> pb::custody_service_server::CustodySer
"Failed to process transaction authorization request: {e}"
))
})?;
let SigningResponse::Transaction(data) = data else {
return Err(Status::internal(
"expected transaction authorization but custody service returned another kind of authorization data"
.to_string()
));
};
Ok(Response::new(pb::AuthorizeResponse {
data: Some(data.into()),
}))
Expand All @@ -303,8 +308,13 @@ impl<T: Terminal + Sync + Send + 'static> pb::custody_service_server::CustodySer
"Failed to process validator definition authorization request: {e}"
))
})?;
let SigningResponse::ValidatorDefinition(validator_definition_auth) = data else {
return Err(Status::internal(
"expected validator definition authorization but custody service returned another kind of authorization data".to_string()
));
};
Ok(Response::new(pb::AuthorizeValidatorDefinitionResponse {
data: Some(data.into()),
validator_definition_auth: Some(validator_definition_auth.into()),
}))
}

Expand All @@ -324,8 +334,13 @@ impl<T: Terminal + Sync + Send + 'static> pb::custody_service_server::CustodySer
"Failed to process validator vote authorization request: {e}"
))
})?;
let SigningResponse::ValidatorVote(validator_vote_auth) = data else {
return Err(Status::internal(
"expected validator vote authorization but custody service returned another kind of authorization data".to_string()
));
};
Ok(Response::new(pb::AuthorizeValidatorVoteResponse {
data: Some(data.into()),
validator_vote_auth: Some(validator_vote_auth.into()),
}))
}

Expand Down
Loading

0 comments on commit 2c06897

Please sign in to comment.