Skip to content

Commit

Permalink
add UpdateVote jcli command
Browse files Browse the repository at this point in the history
  • Loading branch information
Mr-Leshiy committed Oct 26, 2021
1 parent 3ac0eb3 commit 5f8d43f
Show file tree
Hide file tree
Showing 5 changed files with 99 additions and 15 deletions.
16 changes: 2 additions & 14 deletions jcli/src/jcli_lib/transaction/simplified.rs
Expand Up @@ -2,7 +2,7 @@ use crate::jcli_lib::rest::RestArgs;
use crate::jcli_lib::transaction::{common, Error};
use crate::transaction::mk_witness::WitnessType;
use crate::transaction::staging::Staging;
use crate::utils::key_parser::{parse_ed25519_secret_key, read_ed25519_secret_key_from_file};
use crate::utils::key_parser::read_secret_key;
use crate::utils::AccountId;
use crate::{rest, transaction};
use chain_addr::Kind;
Expand Down Expand Up @@ -123,18 +123,6 @@ fn create_receiver_secret_key_and_address(
Ok((sk, address))
}

fn read_secret_key(secret_key_path: Option<PathBuf>) -> Result<EitherEd25519SecretKey, Error> {
match secret_key_path {
Some(path) => read_ed25519_secret_key_from_file(&Some(path)),
None => {
let key =
rpassword::prompt_password_stdout("Introduce the bech32 format secret key:\n")?;
parse_ed25519_secret_key(&key)
}
}
.map_err(Error::SecretKeyReadFailed)
}

fn common_fee_from_settings(settings: &SettingsDto) -> CommonFees {
let fees = settings.fees;
CommonFees {
Expand Down Expand Up @@ -189,7 +177,7 @@ pub fn make_transaction(
"Total value to transfer (including fees): {}",
transfer_value
);
if !ask_yes_or_no(true).map_err(Error::UserInputError)? {
if !ask_yes_or_no(true)? {
return Err(Error::CancelByUser);
}
}
Expand Down
13 changes: 13 additions & 0 deletions jcli/src/jcli_lib/utils/key_parser.rs
Expand Up @@ -21,6 +21,8 @@ pub enum Error {
},
#[error("could not decode secretkey: {0}")]
SecretKeyMalformed(#[from] bech32::Error),
#[error("error requesting user input")]
UserInputError(#[from] std::io::Error),
}

pub fn parse_pub_key<A: AsymmetricPublicKey>(
Expand All @@ -46,6 +48,17 @@ where
})
}

pub fn read_secret_key(secret_key_path: Option<PathBuf>) -> Result<EitherEd25519SecretKey, Error> {
match secret_key_path {
Some(path) => read_ed25519_secret_key_from_file(&Some(path)),
None => {
let key =
rpassword::prompt_password_stdout("Introduce the bech32 format secret key:\n")?;
parse_ed25519_secret_key(&key)
}
}
}

pub fn read_ed25519_secret_key_from_file<P: AsRef<Path>>(
path: &Option<P>,
) -> Result<EitherEd25519SecretKey, Error> {
Expand Down
18 changes: 17 additions & 1 deletion jcli/src/jcli_lib/vote/mod.rs
@@ -1,9 +1,15 @@
use crate::jcli_lib::utils::output_file::{self, OutputFile};
use crate::jcli_lib::utils::vote::{SharesError, VotePlanError};
use crate::jcli_lib::utils::{
key_parser,
vote::{SharesError, VotePlanError},
};
use crate::rest;

mod committee;
mod election_public_key;
mod tally;
mod update_proposal;
mod update_vote;

use structopt::StructOpt;
use thiserror::Error;
Expand Down Expand Up @@ -53,6 +59,10 @@ pub enum Error {
VotePlanError(#[from] VotePlanError),
#[error(transparent)]
SharesError(#[from] SharesError),
#[error("could not process secret file '{0}'")]
SecretKeyReadFailed(#[from] key_parser::Error),
#[error(transparent)]
RestError(#[from] rest::Error),
}

#[derive(StructOpt)]
Expand All @@ -64,6 +74,10 @@ pub enum Vote {
ElectionKey(election_public_key::ElectionPublicKey),
/// Perform decryption of private voting tally
Tally(tally::Tally),
/// Create proposal for the updating chain config
UpdateProposal(update_proposal::UpdateProposal),
/// Vote for the update proposal
UpdateVote(update_vote::UpdateVote),
}

impl Vote {
Expand All @@ -72,6 +86,8 @@ impl Vote {
Vote::Committee(cmd) => cmd.exec(),
Vote::ElectionKey(cmd) => cmd.exec(),
Vote::Tally(cmd) => cmd.exec(),
Vote::UpdateProposal(cmd) => cmd.exec(),
Vote::UpdateVote(cmd) => cmd.exec(),
}
}
}
Expand Down
12 changes: 12 additions & 0 deletions jcli/src/jcli_lib/vote/update_proposal.rs
@@ -0,0 +1,12 @@
use crate::jcli_lib::vote::Error;
use structopt::StructOpt;

#[derive(StructOpt)]
#[structopt(rename_all = "kebab-case")]
pub struct UpdateProposal {}

impl UpdateProposal {
pub fn exec(&self) -> Result<(), Error> {
Ok(())
}
}
55 changes: 55 additions & 0 deletions jcli/src/jcli_lib/vote/update_vote.rs
@@ -0,0 +1,55 @@
use crate::{
jcli_lib::vote::Error,
rest::{v0::message::post_fragment, RestArgs},
utils::key_parser::read_secret_key,
};
use chain_core::property::Serialize;
use chain_impl_mockchain::{
fragment::Fragment,
key::{BftLeaderId, EitherEd25519SecretKey},
update::{SignedUpdateVote, UpdateProposalId, UpdateVote as UpdateVoteLib},
};
use std::path::PathBuf;
use structopt::StructOpt;

#[derive(StructOpt)]
#[structopt(rename_all = "kebab-case")]
pub struct UpdateVote {
/// the Proposal ID of the proposal.
#[structopt(name = "PROPOSAL_ID")]
proposal_id: UpdateProposalId,

/// the file path to the file to read the signing key from.
/// If omitted it will be read from the standard input.
#[structopt(long)]
pub secret: Option<PathBuf>,

#[structopt(flatten)]
rest_args: RestArgs,
}

impl UpdateVote {
pub fn exec(self) -> Result<(), Error> {
let secret_key = read_secret_key(self.secret)?;

let fragment = build_fragment(secret_key, self.proposal_id);

let fragment_id = post_fragment(self.rest_args, fragment)?;
println!("Posted fragment id: {}", fragment_id);

Ok(())
}
}

fn build_fragment(secret_key: EitherEd25519SecretKey, proposal_id: UpdateProposalId) -> Fragment {
let voter_id = secret_key.to_public();

let update_vote = UpdateVoteLib::new(proposal_id, BftLeaderId::from(voter_id));

let bytes = update_vote.serialize_as_vec().unwrap();

let signed_update_vote =
SignedUpdateVote::new(secret_key.sign_slice(bytes.as_slice()), update_vote);

Fragment::UpdateVote(signed_update_vote)
}

0 comments on commit 5f8d43f

Please sign in to comment.