Skip to content

Commit aeb3a09

Browse files
committed
Refactor: Simplify Bech32 encoding for StakeAddress in governance and epochs handlers
1 parent 4caab30 commit aeb3a09

File tree

4 files changed

+62
-60
lines changed

4 files changed

+62
-60
lines changed

modules/accounts_state/src/spo_distribution_store.rs

Lines changed: 20 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
use acropolis_common::{PoolId, StakeAddress};
2-
use anyhow::Result;
2+
use anyhow::{anyhow, Context, Result};
33
use fjall::{Config, Keyspace, PartitionCreateOptions};
44
use std::collections::HashMap;
55

@@ -30,19 +30,27 @@ fn encode_epoch_pool_prefix(epoch: u64, pool_id: &PoolId) -> Vec<u8> {
3030
}
3131

3232
fn decode_key(key: &[u8]) -> Result<(u64, PoolId, StakeAddress)> {
33-
if key.len() != TOTAL_KEY_LEN {
34-
anyhow::bail!(
35-
"Invalid key length: expected {}, got {}",
36-
TOTAL_KEY_LEN,
37-
key.len()
38-
);
39-
}
40-
41-
let epoch = u64::from_be_bytes(key[..EPOCH_LEN].try_into()?);
42-
let pool_id = key[EPOCH_LEN..EPOCH_LEN + POOL_ID_LENGTH].try_into()?;
33+
let epoch_bytes: [u8; EPOCH_LEN] = key[..EPOCH_LEN]
34+
.try_into()
35+
.map_err(|_| anyhow!("Failed to extract epoch bytes (offset 0-{})", EPOCH_LEN))?;
36+
let epoch = u64::from_be_bytes(epoch_bytes);
37+
38+
let pool_id: PoolId = key[EPOCH_LEN..EPOCH_LEN + POOL_ID_LENGTH].try_into().map_err(|_| {
39+
anyhow!(
40+
"Failed to extract pool ID bytes (offset {}-{})",
41+
EPOCH_LEN,
42+
EPOCH_LEN + POOL_ID_LENGTH
43+
)
44+
})?;
4345

4446
let stake_address_bytes = &key[EPOCH_LEN + POOL_ID_LENGTH..];
45-
let stake_address = StakeAddress::from_binary(stake_address_bytes)?;
47+
let stake_address = StakeAddress::from_binary(stake_address_bytes).with_context(|| {
48+
format!(
49+
"Failed to decode stake address from {} bytes at offset {}",
50+
stake_address_bytes.len(),
51+
EPOCH_LEN + POOL_ID_LENGTH
52+
)
53+
})?;
4654

4755
Ok((epoch, pool_id, stake_address))
4856
}

modules/accounts_state/src/state.rs

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -15,9 +15,8 @@ use acropolis_common::{
1515
protocol_params::ProtocolParams,
1616
stake_addresses::{StakeAddressMap, StakeAddressState},
1717
BlockInfo, DRepChoice, DRepCredential, DelegatedStake, InstantaneousRewardSource,
18-
InstantaneousRewardTarget, Lovelace, MoveInstantaneousReward, PoolId,
19-
PoolLiveStakeInfo, PoolRegistration, Pot, SPORewards, StakeAddress, StakeRewardDelta,
20-
TxCertificate,
18+
InstantaneousRewardTarget, Lovelace, MoveInstantaneousReward, PoolId, PoolLiveStakeInfo,
19+
PoolRegistration, Pot, SPORewards, StakeAddress, StakeRewardDelta, TxCertificate,
2120
};
2221
use anyhow::Result;
2322
use imbl::OrdMap;
@@ -962,7 +961,14 @@ impl State {
962961
mod tests {
963962
use super::*;
964963
use acropolis_common::crypto::{keyhash_224, keyhash_256};
965-
use acropolis_common::{protocol_params::ConwayParams, rational_number::RationalNumber, Anchor, Committee, Constitution, CostModel, DRepVotingThresholds, KeyHash, NetworkId, PoolVotingThresholds, Pot, PotDelta, Ratio, Registration, StakeAddress, StakeAddressDelta, StakeAndVoteDelegation, StakeCredential, StakeRegistrationAndStakeAndVoteDelegation, StakeRegistrationAndVoteDelegation, TxCertificateWithPos, TxIdentifier, VoteDelegation, VrfKeyHash, Withdrawal};
964+
use acropolis_common::{
965+
protocol_params::ConwayParams, rational_number::RationalNumber, Anchor, Committee,
966+
Constitution, CostModel, DRepVotingThresholds, KeyHash, NetworkId, PoolVotingThresholds,
967+
Pot, PotDelta, Ratio, Registration, StakeAddress, StakeAddressDelta,
968+
StakeAndVoteDelegation, StakeCredential, StakeRegistrationAndStakeAndVoteDelegation,
969+
StakeRegistrationAndVoteDelegation, TxCertificateWithPos, TxIdentifier, VoteDelegation,
970+
VrfKeyHash, Withdrawal,
971+
};
966972

967973
// Helper to create a StakeAddress from a byte slice
968974
fn create_address(hash: &[u8]) -> StakeAddress {

modules/rest_blockfrost/src/handlers/epochs.rs

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -456,9 +456,12 @@ pub async fn handle_epoch_total_stakes_blockfrost(
456456
let spdd_response = spdd
457457
.into_iter()
458458
.map(|(pool_id, stake_address, amount)| {
459+
let bech32 = stake_address
460+
.to_string()
461+
.map_err(|e| anyhow::anyhow!("Failed to convert stake address to string {}", e))?;
459462
Ok(SPDDByEpochItemRest {
460463
pool_id,
461-
stake_address: stake_address.to_string().unwrap(),
464+
stake_address: bech32,
462465
amount,
463466
})
464467
})
@@ -556,8 +559,11 @@ pub async fn handle_epoch_pool_stakes_blockfrost(
556559
let spdd_response = spdd
557560
.into_iter()
558561
.map(|(stake_address, amount)| {
562+
let bech32 = stake_address
563+
.to_string()
564+
.map_err(|e| anyhow::anyhow!("Failed to convert stake address to string {}", e))?;
559565
Ok(SPDDByEpochAndPoolItemRest {
560-
stake_address: stake_address.to_string().unwrap(),
566+
stake_address: bech32,
561567
amount,
562568
})
563569
})

modules/rest_blockfrost/src/handlers/governance.rs

Lines changed: 24 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -10,13 +10,13 @@ use acropolis_common::{
1010
accounts::{AccountsStateQuery, AccountsStateQueryResponse},
1111
governance::{GovernanceStateQuery, GovernanceStateQueryResponse},
1212
},
13-
Credential, GovActionId, StakeAddress, TxHash, Voter,
13+
Credential, GovActionId, TxHash, Voter,
1414
};
1515
use anyhow::{anyhow, Result};
1616
use caryatid_sdk::Context;
1717
use reqwest::Client;
1818
use serde_json::Value;
19-
use std::{collections::HashMap, sync::Arc};
19+
use std::sync::Arc;
2020

2121
pub async fn handle_dreps_list_blockfrost(
2222
context: Arc<Context<Message>>,
@@ -191,27 +191,6 @@ pub async fn handle_drep_delegators_blockfrost(
191191
Message::StateQueryResponse(StateQueryResponse::Governance(
192192
GovernanceStateQueryResponse::DRepDelegators(delegators),
193193
)) => {
194-
let stake_address_to_bech32: HashMap<StakeAddress, String> = match delegators
195-
.addresses
196-
.iter()
197-
.map(|addr| {
198-
let credential = addr.get_credential();
199-
let bech32 = credential
200-
.to_stake_bech32()
201-
.map_err(|_| anyhow!("Failed to encode stake address"))?;
202-
Ok((addr.clone(), bech32))
203-
})
204-
.collect::<Result<HashMap<_, _>>>()
205-
{
206-
Ok(map) => map,
207-
Err(e) => {
208-
return Ok(RESTResponse::with_text(
209-
500,
210-
&format!("Internal error: {e}"),
211-
));
212-
}
213-
};
214-
215194
let msg = Arc::new(Message::StateQuery(StateQuery::Accounts(
216195
AccountsStateQuery::GetAccountsUtxoValuesMap {
217196
stake_addresses: delegators.addresses.clone(),
@@ -226,27 +205,31 @@ pub async fn handle_drep_delegators_blockfrost(
226205
Message::StateQueryResponse(StateQueryResponse::Accounts(
227206
AccountsStateQueryResponse::AccountsUtxoValuesMap(map),
228207
)) => {
229-
let mut response = Vec::new();
230-
231-
for (stake_address, amount) in map {
232-
let Some(bech32) = stake_address_to_bech32.get(&stake_address) else {
233-
return Ok(RESTResponse::with_text(
208+
let response: Result<Vec<_>> = map
209+
.into_iter()
210+
.map(|(stake_address, amount)| {
211+
let bech32 = stake_address
212+
.to_string()
213+
.map_err(|e| anyhow!("Failed to encode stake address {}", e))?;
214+
215+
Ok(serde_json::json!({
216+
"address": bech32,
217+
"amount": amount.to_string(),
218+
}))
219+
})
220+
.collect();
221+
222+
match response {
223+
Ok(response) => match serde_json::to_string_pretty(&response) {
224+
Ok(json) => Ok(RESTResponse::with_json(200, &json)),
225+
Err(e) => Ok(RESTResponse::with_text(
234226
500,
235-
"Internal error: missing Bech32 for stake key",
236-
));
237-
};
238-
239-
response.push(serde_json::json!({
240-
"address": bech32,
241-
"amount": amount.to_string(),
242-
}));
243-
}
244-
245-
match serde_json::to_string_pretty(&response) {
246-
Ok(json) => Ok(RESTResponse::with_json(200, &json)),
227+
&format!("Failed to serialize DRep delegators: {e}"),
228+
)),
229+
},
247230
Err(e) => Ok(RESTResponse::with_text(
248231
500,
249-
&format!("Failed to serialize DRep delegators: {e}"),
232+
&format!("Internal error: {e}"),
250233
)),
251234
}
252235
}
@@ -279,7 +262,6 @@ pub async fn handle_drep_delegators_blockfrost(
279262
_ => Ok(RESTResponse::with_text(500, "Unexpected message type")),
280263
}
281264
}
282-
283265
pub async fn handle_drep_metadata_blockfrost(
284266
context: Arc<Context<Message>>,
285267
params: Vec<String>,

0 commit comments

Comments
 (0)