Skip to content

Commit a4f65b6

Browse files
author
CodeSandwich
committed
Move JCLI weighted pool IDs to separate module
1 parent fcf2686 commit a4f65b6

File tree

3 files changed

+82
-62
lines changed

3 files changed

+82
-62
lines changed

jcli/src/jcli_app/certificate/mod.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ mod get_stake_pool_id;
1010
mod new_stake_delegation;
1111
mod new_stake_pool_registration;
1212
mod sign;
13+
mod weighted_pool_ids;
1314

1415
pub(crate) use self::sign::{pool_owner_sign, stake_delegation_account_binding_sign};
1516

Lines changed: 6 additions & 62 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,12 @@
1-
use crate::jcli_app::certificate::{write_cert, Error};
1+
use crate::jcli_app::certificate::{weighted_pool_ids::WeightedPoolIds, write_cert, Error};
22
use crate::jcli_app::utils::key_parser::parse_pub_key;
3-
use chain_crypto::{Blake2b256, Ed25519, PublicKey};
4-
use chain_impl_mockchain::account::{DelegationRatio, DelegationType};
5-
use chain_impl_mockchain::accounting::account::DELEGATION_RATIO_MAX_DECLS;
3+
use chain_crypto::{Ed25519, PublicKey};
64
use chain_impl_mockchain::certificate::{Certificate, StakeDelegation as Delegation};
75
use chain_impl_mockchain::transaction::UnspecifiedAccountIdentifier;
86
use jormungandr_lib::interfaces::Certificate as CertificateType;
9-
use std::convert::TryFrom;
10-
use std::error::Error as StdError;
7+
use std::convert::TryInto;
118
use std::ops::Deref;
129
use std::path::PathBuf;
13-
use std::str::FromStr;
1410
use structopt::StructOpt;
1511

1612
#[derive(StructOpt)]
@@ -19,42 +15,19 @@ pub struct StakeDelegation {
1915
#[structopt(name = "STAKE_KEY", parse(try_from_str = "parse_pub_key"))]
2016
stake_id: PublicKey<Ed25519>,
2117

22-
/// hex-encoded stake pool IDs and their numeric weights in format "pool_id:weight".
23-
/// If weight is not provided, it defaults to 1.
24-
#[structopt(name = "STAKE_POOL_IDS", raw(required = "true"))]
25-
pool_ids: Vec<WeightedPoolId>,
18+
#[structopt(flatten)]
19+
pool_ids: WeightedPoolIds,
2620

2721
/// write the output to the given file or print it to the standard output if not defined
2822
#[structopt(short = "o", long = "output")]
2923
output: Option<PathBuf>,
3024
}
3125

32-
struct WeightedPoolId {
33-
pool_id: Blake2b256,
34-
weight: u8,
35-
}
36-
37-
impl FromStr for WeightedPoolId {
38-
type Err = Box<dyn StdError>;
39-
40-
fn from_str(s: &str) -> Result<Self, Self::Err> {
41-
let mut split = s.splitn(2, ':');
42-
Ok(WeightedPoolId {
43-
pool_id: split.next().unwrap().parse()?,
44-
weight: split.next().map_or(Ok(1), str::parse)?,
45-
})
46-
}
47-
}
48-
4926
impl StakeDelegation {
5027
pub fn exec(self) -> Result<(), Error> {
51-
let delegation = match self.pool_ids.len() {
52-
1 => DelegationType::Full(self.pool_ids[0].pool_id.into()),
53-
_ => DelegationType::Ratio(delegation_ratio(&self.pool_ids)?),
54-
};
5528
let content = Delegation {
5629
account_id: UnspecifiedAccountIdentifier::from_single_account(self.stake_id.into()),
57-
delegation,
30+
delegation: (&self.pool_ids).try_into()?,
5831
};
5932
let cert = Certificate::StakeDelegation(content);
6033
write_cert(
@@ -63,32 +36,3 @@ impl StakeDelegation {
6336
)
6437
}
6538
}
66-
67-
fn delegation_ratio(pool_ids: &[WeightedPoolId]) -> Result<DelegationRatio, Error> {
68-
if pool_ids.len() > DELEGATION_RATIO_MAX_DECLS {
69-
return Err(Error::TooManyPoolDelegations {
70-
actual: pool_ids.len(),
71-
max: DELEGATION_RATIO_MAX_DECLS,
72-
});
73-
}
74-
let parts = delegation_ratio_sum(pool_ids)?;
75-
let pools = pool_ids
76-
.iter()
77-
.map(|pool_id| (pool_id.pool_id.into(), pool_id.weight))
78-
.collect();
79-
DelegationRatio::new(parts, pools).ok_or_else(|| Error::InvalidPoolDelegation)
80-
}
81-
82-
fn delegation_ratio_sum(pool_ids: &[WeightedPoolId]) -> Result<u8, Error> {
83-
let parts = pool_ids
84-
.iter()
85-
.map(|pool_id| match pool_id.weight {
86-
0 => Err(Error::PoolDelegationWithZeroWeight),
87-
weight => Ok(weight as u64),
88-
})
89-
.sum::<Result<_, _>>()?;
90-
u8::try_from(parts).map_err(|_| Error::InvalidPoolDelegationWeights {
91-
actual: parts,
92-
max: u8::max_value() as u64,
93-
})
94-
}
Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
use crate::jcli_app::certificate::Error;
2+
use chain_crypto::Blake2b256;
3+
use chain_impl_mockchain::account::{DelegationRatio, DelegationType};
4+
use chain_impl_mockchain::accounting::account::DELEGATION_RATIO_MAX_DECLS;
5+
use std::convert::TryFrom;
6+
use std::error::Error as StdError;
7+
use std::str::FromStr;
8+
use structopt::StructOpt;
9+
10+
#[derive(StructOpt)]
11+
pub struct WeightedPoolIds {
12+
/// hex-encoded stake pool IDs and their numeric weights in format "pool_id:weight".
13+
/// If weight is not provided, it defaults to 1.
14+
#[structopt(name = "STAKE_POOL_IDS", raw(required = "true"))]
15+
pool_ids: Vec<WeightedPoolId>,
16+
}
17+
18+
struct WeightedPoolId {
19+
pool_id: Blake2b256,
20+
weight: u8,
21+
}
22+
23+
impl<'a> TryFrom<&'a WeightedPoolIds> for DelegationType {
24+
type Error = Error;
25+
26+
fn try_from(pool_ids: &'a WeightedPoolIds) -> Result<Self, Self::Error> {
27+
let pool_ids = &pool_ids.pool_ids;
28+
let delegation = match pool_ids.len() {
29+
1 => DelegationType::Full(pool_ids[0].pool_id.into()),
30+
_ => DelegationType::Ratio(delegation_ratio(pool_ids)?),
31+
};
32+
Ok(delegation)
33+
}
34+
}
35+
36+
fn delegation_ratio(pool_ids: &[WeightedPoolId]) -> Result<DelegationRatio, Error> {
37+
if pool_ids.len() > DELEGATION_RATIO_MAX_DECLS {
38+
return Err(Error::TooManyPoolDelegations {
39+
actual: pool_ids.len(),
40+
max: DELEGATION_RATIO_MAX_DECLS,
41+
});
42+
}
43+
let parts = delegation_ratio_sum(pool_ids)?;
44+
let pools = pool_ids
45+
.iter()
46+
.map(|pool_id| (pool_id.pool_id.into(), pool_id.weight))
47+
.collect();
48+
DelegationRatio::new(parts, pools).ok_or_else(|| Error::InvalidPoolDelegation)
49+
}
50+
51+
fn delegation_ratio_sum(pool_ids: &[WeightedPoolId]) -> Result<u8, Error> {
52+
let parts = pool_ids
53+
.iter()
54+
.map(|pool_id| match pool_id.weight {
55+
0 => Err(Error::PoolDelegationWithZeroWeight),
56+
weight => Ok(weight as u64),
57+
})
58+
.sum::<Result<_, _>>()?;
59+
u8::try_from(parts).map_err(|_| Error::InvalidPoolDelegationWeights {
60+
actual: parts,
61+
max: u8::max_value() as u64,
62+
})
63+
}
64+
65+
impl FromStr for WeightedPoolId {
66+
type Err = Box<dyn StdError>;
67+
68+
fn from_str(s: &str) -> Result<Self, Self::Err> {
69+
let mut split = s.splitn(2, ':');
70+
Ok(WeightedPoolId {
71+
pool_id: split.next().unwrap().parse()?,
72+
weight: split.next().map_or(Ok(1), str::parse)?,
73+
})
74+
}
75+
}

0 commit comments

Comments
 (0)