Skip to content

Commit e373202

Browse files
Merge pull request #3230 from danielSanchezQ/jcli-simplified-transaction
2 parents 6df83f3 + 4d82704 commit e373202

File tree

22 files changed

+675
-90
lines changed

22 files changed

+675
-90
lines changed

Cargo.lock

+11
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

jcli/Cargo.toml

+1
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ gtmpl = "0.6.0"
3535
ed25519-bip32 = "0.3"
3636
thiserror = "1.0"
3737
bytes = "1.0"
38+
rpassword = "5.0"
3839

3940
[dependencies.clap]
4041
version = "2.33"

jcli/src/jcli_lib/block/mod.rs

+13-5
Original file line numberDiff line numberDiff line change
@@ -116,18 +116,26 @@ pub struct Input {
116116

117117
impl Input {
118118
pub fn open(&self) -> Result<impl BufRead, Error> {
119-
io::open_file_read(&self.input_file).map_err(|source| Error::InputInvalid {
120-
source,
121-
path: self.input_file.clone().unwrap_or_default(),
122-
})
119+
open_block_file(&self.input_file)
123120
}
124121

125122
pub fn load_block(&self) -> Result<Block, Error> {
126123
let reader = self.open()?;
127-
Block::deserialize(reader).map_err(Error::BlockFileCorrupted)
124+
load_block(reader)
128125
}
129126
}
130127

128+
pub fn open_block_file(input_file: &Option<PathBuf>) -> Result<impl BufRead, Error> {
129+
io::open_file_read(input_file).map_err(|source| Error::InputInvalid {
130+
source,
131+
path: input_file.clone().unwrap_or_default(),
132+
})
133+
}
134+
135+
pub fn load_block(block_reader: impl BufRead) -> Result<Block, Error> {
136+
Block::deserialize(block_reader).map_err(Error::BlockFileCorrupted)
137+
}
138+
131139
#[derive(StructOpt)]
132140
pub struct Common {
133141
#[structopt(flatten)]

jcli/src/jcli_lib/key.rs

+1
Original file line numberDiff line numberDiff line change
@@ -418,6 +418,7 @@ fn bytes_to_priv_key<K: AsymmetricKey>(bytes: &[u8]) -> Result<String, Error> {
418418

419419
#[derive(Debug)]
420420
struct Seed([u8; 32]);
421+
421422
impl std::str::FromStr for Seed {
422423
type Err = Error;
423424
fn from_str(s: &str) -> Result<Self, Self::Err> {

jcli/src/jcli_lib/rest/config.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -7,12 +7,12 @@ use std::path::PathBuf;
77
use structopt::StructOpt;
88
use thiserror::Error;
99

10-
#[derive(StructOpt)]
10+
#[derive(StructOpt, Clone)]
1111
pub struct RestArgs {
1212
/// node API address. Must always have `http://` or `https://` prefix.
1313
/// E.g. `-h http://127.0.0.1`, `--host https://node.com:8443/cardano/api`
1414
#[structopt(short, long, env = "JORMUNGANDR_RESTAPI_URL")]
15-
host: Url,
15+
pub host: Url,
1616
/// print additional debug information to stderr.
1717
/// The output format is intentionally undocumented and unstable
1818
#[structopt(long)]

jcli/src/jcli_lib/rest/mod.rs

+4-2
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
mod config;
2-
mod v0;
2+
pub mod v0;
33

44
use crate::jcli_lib::utils::{io::ReadYamlError, output_format};
5-
use config::RestArgs;
5+
pub use config::RestArgs;
66
use hex::FromHexError;
77
use structopt::StructOpt;
88
use thiserror::Error;
@@ -29,6 +29,8 @@ pub enum Error {
2929
InputHexMalformed(#[from] FromHexError),
3030
#[error("error when trying to perform an HTTP request")]
3131
RequestError(#[from] config::Error),
32+
#[error("error loading data from response")]
33+
SerdeError(#[from] serde_json::Error),
3234
}
3335

3436
impl From<ReadYamlError> for Error {

jcli/src/jcli_lib/rest/v0/account/mod.rs

+14-6
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
use crate::jcli_lib::rest::{Error, RestArgs};
22
use crate::jcli_lib::utils::{AccountId, OutputFormat};
3+
use jormungandr_lib::interfaces::AccountState;
34
use structopt::StructOpt;
45

56
#[derive(StructOpt)]
@@ -24,13 +25,20 @@ impl Account {
2425
output_format,
2526
account_id,
2627
} = self;
27-
let state = args
28-
.client()?
29-
.get(&["v0", "account", &account_id.to_url_arg()])
30-
.execute()?
31-
.json()?;
32-
let formatted = output_format.format_json(state)?;
28+
let state = request_account_information(args, account_id)?;
29+
let formatted = output_format.format_json(serde_json::to_value(state)?)?;
3330
println!("{}", formatted);
3431
Ok(())
3532
}
3633
}
34+
35+
pub fn request_account_information(
36+
args: RestArgs,
37+
account_id: AccountId,
38+
) -> Result<AccountState, Error> {
39+
args.client()?
40+
.get(&["v0", "account", &account_id.to_url_arg()])
41+
.execute()?
42+
.json()
43+
.map_err(Into::into)
44+
}

jcli/src/jcli_lib/rest/v0/message/mod.rs

+10-5
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ use crate::jcli_lib::{
22
rest::{Error, RestArgs},
33
utils::{io, OutputFormat},
44
};
5-
use chain_core::property::Deserialize;
5+
use chain_core::property::{Deserialize, Serialize};
66
use chain_impl_mockchain::fragment::Fragment;
77
use std::path::PathBuf;
88
use structopt::StructOpt;
@@ -57,14 +57,19 @@ fn get_logs(args: RestArgs, output_format: OutputFormat) -> Result<(), Error> {
5757
fn post_message(args: RestArgs, file: Option<PathBuf>) -> Result<(), Error> {
5858
let msg_hex = io::read_line(&file)?;
5959
let msg_bin = hex::decode(&msg_hex)?;
60-
let _fragment =
60+
let fragment =
6161
Fragment::deserialize(msg_bin.as_slice()).map_err(Error::InputFragmentMalformed)?;
62+
let fragment_id = post_fragment(args, fragment)?;
63+
println!("{}", fragment_id);
64+
Ok(())
65+
}
66+
67+
pub fn post_fragment(args: RestArgs, fragment: Fragment) -> Result<String, Error> {
6268
let fragment_id = args
6369
.client()?
6470
.post(&["v0", "message"])
65-
.body(msg_bin)
71+
.body(fragment.serialize_as_vec()?)
6672
.execute()?
6773
.text()?;
68-
println!("{}", fragment_id);
69-
Ok(())
74+
Ok(fragment_id)
7075
}

jcli/src/jcli_lib/rest/v0/mod.rs

+3-3
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,12 @@
1-
mod account;
1+
pub mod account;
22
mod block;
33
mod diagnostic;
44
mod leaders;
5-
mod message;
5+
pub mod message;
66
mod network;
77
mod node;
88
mod rewards;
9-
mod settings;
9+
pub mod settings;
1010
mod shutdown;
1111
mod stake;
1212
mod stake_pool;

jcli/src/jcli_lib/rest/v0/settings/mod.rs

+9-2
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
use crate::jcli_lib::rest::{Error, RestArgs};
22
use crate::jcli_lib::utils::OutputFormat;
3+
use jormungandr_lib::interfaces::SettingsDto;
4+
35
use structopt::StructOpt;
46

57
#[derive(StructOpt)]
@@ -20,9 +22,14 @@ impl Settings {
2022
args,
2123
output_format,
2224
} = self;
23-
let response = args.client()?.get(&["v0", "settings"]).execute()?.json()?;
24-
let formatted = output_format.format_json(response)?;
25+
let settings = request_settings(args)?;
26+
let formatted = output_format.format_json(serde_json::to_value(&settings)?)?;
2527
println!("{}", formatted);
2628
Ok(())
2729
}
2830
}
31+
32+
pub fn request_settings(args: RestArgs) -> Result<SettingsDto, Error> {
33+
serde_json::from_str(&(args.client()?.get(&["v0", "settings"]).execute()?.text()?))
34+
.map_err(Error::SerdeError)
35+
}
+1-18
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,4 @@
11
use crate::jcli_lib::transaction::{common, Error};
2-
use chain_addr::{Address, Kind};
3-
use chain_impl_mockchain::transaction::UnspecifiedAccountIdentifier;
42
use jormungandr_lib::interfaces;
53
use structopt::StructOpt;
64

@@ -22,22 +20,7 @@ pub struct AddAccount {
2220
impl AddAccount {
2321
pub fn exec(self) -> Result<(), Error> {
2422
let mut transaction = self.common.load()?;
25-
26-
let account_id = match Address::from(self.account).kind() {
27-
Kind::Account(key) => {
28-
UnspecifiedAccountIdentifier::from_single_account(key.clone().into())
29-
}
30-
Kind::Multisig(key) => UnspecifiedAccountIdentifier::from_multi_account((*key).into()),
31-
Kind::Single(_) => return Err(Error::AccountAddressSingle),
32-
Kind::Group(_, _) => return Err(Error::AccountAddressGroup),
33-
Kind::Script(_) => return Err(Error::AccountAddressScript),
34-
};
35-
36-
transaction.add_input(interfaces::TransactionInput {
37-
input: interfaces::TransactionInputType::Account(account_id.into()),
38-
value: self.value,
39-
})?;
40-
23+
transaction.add_account(self.account, self.value)?;
4124
self.common.store(&transaction)
4225
}
4326
}

jcli/src/jcli_lib/transaction/finalize.rs

+16-7
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
use crate::jcli_lib::transaction::{common, Error};
2+
use crate::transaction::staging::Staging;
23
use chain_impl_mockchain::transaction::OutputPolicy;
34
use jormungandr_lib::interfaces;
45
use structopt::StructOpt;
@@ -20,15 +21,23 @@ impl Finalize {
2021
pub fn exec(self) -> Result<(), Error> {
2122
let mut transaction = self.common.load()?;
2223

23-
let fee_algo = self.fee.linear_fee();
24-
let output_policy = match self.change {
25-
None => OutputPolicy::Forget,
26-
Some(change) => OutputPolicy::One(change.into()),
27-
};
28-
29-
let _balance = transaction.balance_inputs_outputs(&fee_algo, output_policy)?;
24+
finalize(self.fee, self.change, &mut transaction)?;
3025

3126
self.common.store(&transaction)?;
3227
Ok(())
3328
}
3429
}
30+
31+
pub fn finalize(
32+
fee: common::CommonFees,
33+
change: Option<interfaces::Address>,
34+
transaction: &mut Staging,
35+
) -> Result<(), Error> {
36+
let fee_algo = fee.linear_fee();
37+
let output_policy = match change {
38+
None => OutputPolicy::Forget,
39+
Some(change) => OutputPolicy::One(change.into()),
40+
};
41+
let _balance = transaction.balance_inputs_outputs(&fee_algo, output_policy)?;
42+
Ok(())
43+
}

jcli/src/jcli_lib/transaction/mk_witness.rs

+36-32
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ use crate::jcli_lib::{
44
};
55
use bech32::{self, ToBase32 as _};
66
use chain_core::property::Serialize as _;
7+
use chain_impl_mockchain::key::EitherEd25519SecretKey;
78
use chain_impl_mockchain::{
89
account::SpendingCounter,
910
header::HeaderId,
@@ -62,38 +63,14 @@ impl std::str::FromStr for WitnessType {
6263

6364
impl MkWitness {
6465
pub fn exec(self) -> Result<(), Error> {
65-
let witness = match self.witness_type {
66-
WitnessType::UTxO => {
67-
let secret_key = read_ed25519_secret_key_from_file(&self.secret)?;
68-
Witness::new_utxo(&self.genesis_block_hash, &self.sign_data_hash, |d| {
69-
secret_key.sign(d)
70-
})
71-
}
72-
WitnessType::OldUTxO => {
73-
let secret_key = read_ed25519_secret_key_from_file(&self.secret)?;
74-
Witness::new_old_utxo(
75-
&self.genesis_block_hash,
76-
&self.sign_data_hash,
77-
|d| (secret_key.to_public(), secret_key.sign(d)),
78-
&[0; 32],
79-
)
80-
}
81-
WitnessType::Account => {
82-
let account_spending_counter = self
83-
.account_spending_counter
84-
.ok_or(Error::MakeWitnessAccountCounterMissing)
85-
.map(SpendingCounter::from)?;
86-
87-
let secret_key = read_ed25519_secret_key_from_file(&self.secret)?;
88-
Witness::new_account(
89-
&self.genesis_block_hash,
90-
&self.sign_data_hash,
91-
account_spending_counter,
92-
|d| secret_key.sign(d),
93-
)
94-
}
95-
};
96-
66+
let secret_key = read_ed25519_secret_key_from_file(&self.secret)?;
67+
let witness = make_witness(
68+
&self.witness_type,
69+
&self.genesis_block_hash,
70+
&self.sign_data_hash,
71+
self.account_spending_counter.map(SpendingCounter::from),
72+
&secret_key,
73+
)?;
9774
self.write_witness(&witness)
9875
}
9976

@@ -115,3 +92,30 @@ impl MkWitness {
11592
})
11693
}
11794
}
95+
96+
pub fn make_witness(
97+
witness_type: &WitnessType,
98+
genesis_block_hash: &HeaderId,
99+
sign_data_hash: &TransactionSignDataHash,
100+
account_spending_counter: Option<SpendingCounter>,
101+
secret_key: &EitherEd25519SecretKey,
102+
) -> Result<Witness, Error> {
103+
let witness = match witness_type {
104+
WitnessType::UTxO => {
105+
Witness::new_utxo(genesis_block_hash, sign_data_hash, |d| secret_key.sign(d))
106+
}
107+
WitnessType::OldUTxO => Witness::new_old_utxo(
108+
genesis_block_hash,
109+
sign_data_hash,
110+
|d| (secret_key.to_public(), secret_key.sign(d)),
111+
&[0; 32],
112+
),
113+
WitnessType::Account => Witness::new_account(
114+
genesis_block_hash,
115+
sign_data_hash,
116+
account_spending_counter.ok_or(Error::MakeWitnessAccountCounterMissing)?,
117+
|d| secret_key.sign(d),
118+
),
119+
};
120+
Ok(witness)
121+
}

0 commit comments

Comments
 (0)