Skip to content

Commit 41681ea

Browse files
committed
Refactor: Introduce type-safe Hash conversion utilities, replace manual conversions across modules, and adjust types for stronger consistency. Update tests and documentation accordingly.
1 parent fe2b0d6 commit 41681ea

File tree

16 files changed

+171
-121
lines changed

16 files changed

+171
-121
lines changed

codec/src/map_parameters.rs

Lines changed: 71 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -29,16 +29,50 @@ pub fn map_network(network: addresses::Network) -> Result<NetworkId> {
2929
}
3030
}
3131

32-
/// Convert from Pallas Hash to Acropolis Hash
33-
pub fn pallas_hash_to_acropolis<const N: usize>(
34-
pallas_hash: &pallas_primitives::Hash<N>,
32+
/// Convert a Pallas Hash reference to an Acropolis Hash (owned)
33+
/// Works for any hash size N
34+
pub fn to_hash<const N: usize>(pallas_hash: &pallas_primitives::Hash<N>) -> Hash<N> {
35+
Hash::try_from(pallas_hash.as_ref()).unwrap()
36+
}
37+
38+
/// Convert a Pallas Hash reference to an Acropolis Hash (owned)
39+
/// Works for any hash size N
40+
pub fn genesis_to_hash<const N: usize>(pallas_hash: &pallas_primitives::Genesishash) -> Hash<N> {
41+
Hash::try_from(pallas_hash.as_ref()).unwrap()
42+
}
43+
44+
/// Convert a Pallas Hash reference to an Acropolis Hash (owned)
45+
/// Works for any hash size N
46+
pub fn genesis_delegate_to_hash<const N: usize>(
47+
pallas_hash: &pallas_primitives::GenesisDelegateHash,
3548
) -> Hash<N> {
36-
Hash::new(**pallas_hash)
49+
Hash::try_from(pallas_hash.as_ref()).unwrap()
3750
}
3851

39-
/// Convert from Acropolis Hash to Pallas Hash
40-
pub fn acropolis_hash_to_pallas<const N: usize>(our_hash: &Hash<N>) -> pallas_primitives::Hash<N> {
41-
pallas_primitives::Hash::new(**our_hash)
52+
/// Convert an optional Pallas Hash reference to an optional Acropolis Hash
53+
pub fn to_hash_opt<const N: usize>(
54+
pallas_hash: Option<&pallas_primitives::Hash<N>>,
55+
) -> Option<Hash<N>> {
56+
pallas_hash.map(|h| to_hash(h))
57+
}
58+
59+
/// Convert a Pallas Hash<28> reference to an Acropolis PoolId
60+
pub fn to_pool_id(pallas_hash: &pallas_primitives::Hash<28>) -> PoolId {
61+
PoolId::from(to_hash(pallas_hash))
62+
}
63+
64+
/// Convert a Pallas Hash<32> reference to an Acropolis VRFKey
65+
pub fn to_vrf_key(pallas_hash: &pallas_primitives::Hash<32>) -> VRFKey {
66+
VRFKey::try_from(pallas_hash.as_ref()).unwrap()
67+
}
68+
69+
/// Convert a Pallas Bytes reference to an Acropolis Hash<N>
70+
/// Useful for genesis hash fields that might be stored as Bytes
71+
pub fn bytes_to_hash<const N: usize>(bytes: &pallas_primitives::Bytes) -> Hash<N> {
72+
let slice: &[u8] = bytes.as_ref();
73+
let mut array = [0u8; N];
74+
array.copy_from_slice(&slice[..N]);
75+
Hash::from(array)
4276
}
4377

4478
/// Derive our Address from a Pallas address
@@ -83,12 +117,8 @@ pub fn map_address(address: &addresses::Address) -> Result<Address> {
83117
addresses::Address::Stake(stake_address) => Ok(Address::Stake(StakeAddress {
84118
network: map_network(stake_address.network())?,
85119
credential: match stake_address.payload() {
86-
addresses::StakePayload::Stake(hash) => {
87-
StakeCredential::AddrKeyHash(pallas_hash_to_acropolis(hash))
88-
}
89-
addresses::StakePayload::Script(hash) => {
90-
StakeCredential::ScriptHash(pallas_hash_to_acropolis(hash))
91-
}
120+
addresses::StakePayload::Stake(hash) => StakeCredential::AddrKeyHash(to_hash(hash)),
121+
addresses::StakePayload::Script(hash) => StakeCredential::ScriptHash(to_hash(hash)),
92122
},
93123
})),
94124
}
@@ -98,10 +128,10 @@ pub fn map_address(address: &addresses::Address) -> Result<Address> {
98128
pub fn map_stake_credential(cred: &PallasStakeCredential) -> StakeCredential {
99129
match cred {
100130
PallasStakeCredential::AddrKeyhash(key_hash) => {
101-
StakeCredential::AddrKeyHash(KeyHash::try_from(key_hash.to_vec()).unwrap())
131+
StakeCredential::AddrKeyHash(to_hash(key_hash))
102132
}
103133
PallasStakeCredential::ScriptHash(script_hash) => {
104-
StakeCredential::ScriptHash(KeyHash::try_from(script_hash.to_vec()).unwrap())
134+
StakeCredential::ScriptHash(to_hash(script_hash))
105135
}
106136
}
107137
}
@@ -110,10 +140,10 @@ pub fn map_stake_credential(cred: &PallasStakeCredential) -> StakeCredential {
110140
pub fn map_stake_address(cred: &PallasStakeCredential, network_id: NetworkId) -> StakeAddress {
111141
let payload = match cred {
112142
PallasStakeCredential::AddrKeyhash(key_hash) => {
113-
StakeCredential::AddrKeyHash(KeyHash::try_from(key_hash.to_vec()).unwrap())
143+
StakeCredential::AddrKeyHash(to_hash(key_hash))
114144
}
115145
PallasStakeCredential::ScriptHash(script_hash) => {
116-
StakeCredential::ScriptHash(KeyHash::try_from(script_hash.to_vec()).unwrap())
146+
StakeCredential::ScriptHash(to_hash(script_hash))
117147
}
118148
};
119149

@@ -123,10 +153,8 @@ pub fn map_stake_address(cred: &PallasStakeCredential, network_id: NetworkId) ->
123153
/// Map a Pallas DRep to our DRepChoice
124154
pub fn map_drep(drep: &conway::DRep) -> DRepChoice {
125155
match drep {
126-
conway::DRep::Key(key_hash) => DRepChoice::Key(pallas_hash_to_acropolis(key_hash)),
127-
conway::DRep::Script(script_hash) => {
128-
DRepChoice::Script(pallas_hash_to_acropolis(script_hash))
129-
}
156+
conway::DRep::Key(key_hash) => DRepChoice::Key(to_hash(key_hash)),
157+
conway::DRep::Script(script_hash) => DRepChoice::Script(to_hash(script_hash)),
130158
conway::DRep::Abstain => DRepChoice::Abstain,
131159
conway::DRep::NoConfidence => DRepChoice::NoConfidence,
132160
}
@@ -188,7 +216,7 @@ pub fn map_nullable_gov_action_id(
188216
fn map_constitution(constitution: &conway::Constitution) -> Constitution {
189217
Constitution {
190218
anchor: map_anchor(&constitution.anchor),
191-
guardrail_script: map_nullable(|x| x, &constitution.guardrail_script),
219+
guardrail_script: map_nullable(|x| to_hash(x), &constitution.guardrail_script),
192220
}
193221
}
194222

@@ -251,7 +279,7 @@ pub fn map_certificate(
251279
alonzo::Certificate::StakeDelegation(cred, pool_key_hash) => {
252280
Ok(TxCertificate::StakeDelegation(StakeDelegation {
253281
stake_address: map_stake_address(cred, network_id),
254-
operator: PoolId::from(pallas_hash_to_acropolis(pool_key_hash)),
282+
operator: to_pool_id(pool_key_hash),
255283
}))
256284
}
257285
alonzo::Certificate::PoolRegistration {
@@ -267,8 +295,8 @@ pub fn map_certificate(
267295
} => Ok(TxCertificate::PoolRegistrationWithPos(
268296
PoolRegistrationWithPos {
269297
reg: PoolRegistration {
270-
operator: pallas_hash_to_acropolis(operator),
271-
vrf_key_hash: VRFKey::from(pallas_hash_to_acropolis(vrf_keyhash)),
298+
operator: to_pool_id(operator),
299+
vrf_key_hash: to_vrf_key(vrf_keyhash),
272300
pledge: *pledge,
273301
cost: *cost,
274302
margin: Ratio {
@@ -280,7 +308,7 @@ pub fn map_certificate(
280308
.iter()
281309
.map(|v| {
282310
StakeAddress::new(
283-
StakeCredential::AddrKeyHash(v),
311+
StakeCredential::AddrKeyHash(to_hash(v)),
284312
network_id.clone().into(),
285313
)
286314
})
@@ -301,7 +329,7 @@ pub fn map_certificate(
301329
alonzo::Certificate::PoolRetirement(pool_key_hash, epoch) => Ok(
302330
TxCertificate::PoolRetirementWithPos(PoolRetirementWithPos {
303331
ret: PoolRetirement {
304-
operator: pallas_hash_to_acropolis(pool_key_hash),
332+
operator: to_pool_id(pool_key_hash),
305333
epoch: *epoch,
306334
},
307335
tx_hash,
@@ -313,9 +341,9 @@ pub fn map_certificate(
313341
genesis_delegate_hash,
314342
vrf_key_hash,
315343
) => Ok(TxCertificate::GenesisKeyDelegation(GenesisKeyDelegation {
316-
genesis_hash: pallas_hash_to_acropolis(genesis_hash),
317-
genesis_delegate_hash: pallas_hash_to_acropolis(genesis_delegate_hash),
318-
vrf_key_hash: vrf_key_hash,
344+
genesis_hash: genesis_to_hash(genesis_hash),
345+
genesis_delegate_hash: genesis_delegate_to_hash(genesis_delegate_hash),
346+
vrf_key_hash: to_vrf_key(vrf_key_hash),
319347
})),
320348
alonzo::Certificate::MoveInstantaneousRewardsCert(mir) => Ok(
321349
TxCertificate::MoveInstantaneousReward(MoveInstantaneousReward {
@@ -360,7 +388,7 @@ pub fn map_certificate(
360388
conway::Certificate::StakeDelegation(cred, pool_key_hash) => {
361389
Ok(TxCertificate::StakeDelegation(StakeDelegation {
362390
stake_address: map_stake_address(cred, network_id),
363-
operator: PoolId::from(pool_key_hash),
391+
operator: to_pool_id(pool_key_hash),
364392
}))
365393
}
366394
conway::Certificate::PoolRegistration {
@@ -377,8 +405,8 @@ pub fn map_certificate(
377405
} => Ok(TxCertificate::PoolRegistrationWithPos(
378406
PoolRegistrationWithPos {
379407
reg: PoolRegistration {
380-
operator: operator,
381-
vrf_key_hash: vrf_keyhash,
408+
operator: to_pool_id(operator),
409+
vrf_key_hash: to_vrf_key(vrf_keyhash),
382410
pledge: *pledge,
383411
cost: *cost,
384412
margin: Ratio {
@@ -390,7 +418,7 @@ pub fn map_certificate(
390418
.into_iter()
391419
.map(|v| {
392420
StakeAddress::new(
393-
StakeCredential::AddrKeyHash(v),
421+
StakeCredential::AddrKeyHash(to_hash(v)),
394422
network_id.clone().into(),
395423
)
396424
})
@@ -411,7 +439,7 @@ pub fn map_certificate(
411439
conway::Certificate::PoolRetirement(pool_key_hash, epoch) => Ok(
412440
TxCertificate::PoolRetirementWithPos(PoolRetirementWithPos {
413441
ret: PoolRetirement {
414-
operator: pool_key_hash.into(),
442+
operator: to_pool_id(pool_key_hash),
415443
epoch: *epoch,
416444
},
417445
tx_hash,
@@ -443,15 +471,15 @@ pub fn map_certificate(
443471
conway::Certificate::StakeVoteDeleg(cred, pool_key_hash, drep) => Ok(
444472
TxCertificate::StakeAndVoteDelegation(StakeAndVoteDelegation {
445473
stake_address: map_stake_address(cred, network_id),
446-
operator: pool_key_hash,
474+
operator: to_pool_id(pool_key_hash),
447475
drep: map_drep(drep),
448476
}),
449477
),
450478

451479
conway::Certificate::StakeRegDeleg(cred, pool_key_hash, coin) => Ok(
452480
TxCertificate::StakeRegistrationAndDelegation(StakeRegistrationAndDelegation {
453481
stake_address: map_stake_address(cred, network_id),
454-
operator: pool_key_hash,
482+
operator: to_pool_id(pool_key_hash),
455483
deposit: *coin,
456484
}),
457485
),
@@ -470,7 +498,7 @@ pub fn map_certificate(
470498
Ok(TxCertificate::StakeRegistrationAndStakeAndVoteDelegation(
471499
StakeRegistrationAndStakeAndVoteDelegation {
472500
stake_address: map_stake_address(cred, network_id),
473-
operator: pool_key_hash,
501+
operator: to_pool_id(pool_key_hash),
474502
drep: map_drep(drep),
475503
deposit: *coin,
476504
},
@@ -860,14 +888,14 @@ pub fn map_governance_proposals_procedures(
860888
fn map_voter(voter: &conway::Voter) -> Voter {
861889
match voter {
862890
conway::Voter::ConstitutionalCommitteeKey(key_hash) => {
863-
Voter::ConstitutionalCommitteeKey(key_hash)
891+
Voter::ConstitutionalCommitteeKey(to_hash(key_hash))
864892
}
865893
conway::Voter::ConstitutionalCommitteeScript(script_hash) => {
866-
Voter::ConstitutionalCommitteeScript(script_hash)
894+
Voter::ConstitutionalCommitteeScript(to_hash(script_hash))
867895
}
868-
conway::Voter::DRepKey(addr_key_hash) => Voter::DRepKey(addr_key_hash),
869-
conway::Voter::DRepScript(script_hash) => Voter::DRepScript(script_hash),
870-
conway::Voter::StakePoolKey(key_hash) => Voter::StakePoolKey(key_hash),
896+
conway::Voter::DRepKey(addr_key_hash) => Voter::DRepKey(to_hash(addr_key_hash)),
897+
conway::Voter::DRepScript(script_hash) => Voter::DRepScript(to_hash(script_hash)),
898+
conway::Voter::StakePoolKey(key_hash) => Voter::StakePoolKey(to_pool_id(key_hash)),
871899
}
872900
}
873901

common/src/address.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -437,7 +437,7 @@ impl StakeAddress {
437437
}
438438

439439
/// Convert to binary format (29 bytes)
440-
pub fn to_binary(&self) -> Result<KeyHash> {
440+
pub fn to_binary(&self) -> Result<Vec<u8>> {
441441
let network_bits = match self.network {
442442
NetworkId::Mainnet => 0b1u8,
443443
NetworkId::Testnet => 0b0u8,

common/src/hash.rs

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ use std::{fmt, ops::Deref, str::FromStr};
1616
///
1717
/// # Examples
1818
///
19-
/// ```
19+
/// ```ignore
2020
/// use your_crate::Hash;
2121
///
2222
/// // Parse from hex string
@@ -67,7 +67,7 @@ impl<const BYTES: usize> Hash<BYTES> {
6767
///
6868
/// # Examples
6969
///
70-
/// ```
70+
/// ```ignore
7171
/// use your_crate::Hash;
7272
///
7373
/// const MY_HASH: Hash<32> = Hash::new([0u8; 32]);
@@ -81,7 +81,7 @@ impl<const BYTES: usize> Hash<BYTES> {
8181
///
8282
/// # Examples
8383
///
84-
/// ```
84+
/// ```ignore
8585
/// use your_crate::Hash;
8686
///
8787
/// let hash = Hash::new([1u8; 28]);
@@ -97,7 +97,7 @@ impl<const BYTES: usize> Hash<BYTES> {
9797
///
9898
/// # Examples
9999
///
100-
/// ```
100+
/// ```ignore
101101
/// use your_crate::Hash;
102102
///
103103
/// let hash = Hash::new([1u8; 28]);
@@ -204,7 +204,7 @@ impl<const BYTES: usize> FromStr for Hash<BYTES> {
204204
///
205205
/// # Examples
206206
///
207-
/// ```
207+
/// ```ignore
208208
/// use your_crate::Hash;
209209
///
210210
/// let hash: Hash<28> = "276fd18711931e2c0e21430192dbeac0e458093cd9d1fcd7210f64b3"
@@ -273,7 +273,7 @@ pub type AddrKeyhash = Hash<28>;
273273
///
274274
/// # Examples
275275
///
276-
/// ```
276+
/// ```ignore
277277
/// declare_hash_type!(BlockHash, 32);
278278
/// declare_hash_type!(TxHash, 32);
279279
/// ```
@@ -300,7 +300,7 @@ macro_rules! declare_hash_type {
300300
///
301301
/// # Examples
302302
///
303-
/// ```
303+
/// ```ignore
304304
/// declare_hash_type_with_bech32!(VRFKey, 32, "vrf_vk");
305305
///
306306
/// let key: VRFKey = // ... get key
@@ -360,7 +360,7 @@ macro_rules! declare_hash_type_with_bech32 {
360360
///
361361
/// # Examples
362362
///
363-
/// ```
363+
/// ```ignore
364364
/// // Both are 28 bytes but have different Bech32 encodings
365365
/// declare_hash_newtype_with_bech32!(PoolId, 28, "pool");
366366
/// declare_hash_newtype_with_bech32!(DrepId, 28, "drep");

0 commit comments

Comments
 (0)