tidied up logging for demo recording

This commit is contained in:
mfahampshire
2023-07-14 15:52:36 +02:00
parent de16ca2bd5
commit f6b200d25e
6 changed files with 88 additions and 49 deletions
+12 -8
View File
@@ -1,11 +1,10 @@
TODO FOR DEMO
- clippy
- pass mnemonic as file
- nicer logging - show sequence response etc
- pass tx hash back to client nicely & remove from service
- flags for cli
- single parse_incoming fn in lib and call from everywhere
- pass mnemonic as file (otherwise pass as env var)
- create signer in main.rs and pass to commands (client/src)
### Nym mixnet cosmos tx broadcaster demo
A demo showing how to:
* sign a cosmos tx (simple token transfer) offline
* broadcast this tx from a service on the other side of the mixnet
@@ -21,15 +20,20 @@ Built using:
# compile
cargo build --release
example 1: sign & send @ same time
example 1: sign & send in one call
# start service
../../target/release/service
# sign tx - when prompted enter 'y'
../../target/release/client offline-sign-tx "<MNEMONIC>" "<RECIPIENT_NYX_ADDRESS>
../../target/release/client offline-sign-tx ${SENDER_MNEMONIC} ${RECIPIENT_NYX_ADDRESS}
example 2: sign first, send later
example 2: create signed tx
# start service
../../target/release/service
# sign tx - when prompted enter 'n' and copy encoded tx bytes from terminal
../../target/release/client offline-sign-tx ${SENDER_MNEMONIC} ${RECIPIENT_NYX_ADDRESS}
# send tx using encoded bytes as arg
../../target/release/client send-tx ${}
```
+11 -10
View File
@@ -2,6 +2,7 @@ use clap::{Parser, Subcommand, Args};
use nym_sdk::mixnet::Recipient;
use nym_validator_client::nyxd::AccountId;
use rust_cosmos_broadcaster::{client::{offline_sign, send_tx}, create_client};
use nym_bin_common::logging::setup_logging;
#[derive(Debug, Parser)]
#[clap(name = "nym cosmos tx signer ")]
@@ -39,17 +40,16 @@ async fn main() {
let cli = Cli::parse();
let mut client = create_client("/tmp/cosmos-broadcaster-mixnet-client-2".into()).await;
let our_address = client.nym_address();
println!("\nour client nym address is: {our_address}");
println!("\nclient's nym address: {our_address}\n");
// TODO take from args as Option otherwise set as default this logic moves to src/client and remove this from here
let sp_address = Recipient::try_from_base58_string("HfbesQm2pRYCN4BAdYXhkqXBbV1Pp929mtKsESVeWXh8.8AgoUPUQbXNBCPaqAaWd3vnxhc9484qwfgrrQwBngQk2@Ck8zpXTSXMtS9YZ7k7a5BiaoLZfffWuqGWLndujh4Lw4").unwrap();
match &cli.command {
Some(Commands::OfflineSignTx(OfflineSignTx { mnemonic, nyx_token_receipient} )) => {
println!("sending offline sign info");
println!("sending offline sign info to broadcaster via the mixnet: getting signing account sequence and chain ID");
let base58_tx_bytes = offline_sign(mnemonic.clone(), nyx_token_receipient.clone(), &mut client, sp_address).await;
println!("base58 encoded signed tx payload: \n\n{}\n\n", &base58_tx_bytes);
println!("Encoded response (signed tx data) as base58 for tx broadcast: \n\n{}\n", &base58_tx_bytes);
println!("do you wish to send the tx? y/n");
let mut input = String::new();
@@ -58,19 +58,20 @@ async fn main() {
if input.starts_with('y') {
println!("\nsending tx thru the mixnet to broadcaster service");
let tx_hash = send_tx(base58_tx_bytes, sp_address, &mut client).await;
println!("the response from the broadcaster: {:#?}", tx_hash);
let (tx_hash, success) = send_tx(base58_tx_bytes, sp_address, &mut client).await;
println!("tx hash returned from the broadcaster: {}\ntx was successful: {}", tx_hash, success);
} else if input.starts_with('n') {
println!("\nok, you can send the signed tx at a later date by passing the base58 string above as the argument for send-tx")
println!("\nok, you can send the signed tx at a later date by passing the base58 string above as the argument for send-tx");
} else {
println!("\nunrecognised user input");
}
}
Some(Commands::SendTx(SendTx { base58_payload } )) => {
let tx_hash = send_tx(base58_payload.clone(), sp_address, &mut client).await;
println!("the response from the broadcaster: {:#?}", tx_hash);
println!("response from the broadcaster (tx hash) {:#?}", tx_hash);
}
None => {println!("no command specified - nothing to do")}
None => {println!("\nno command specified - nothing to do")}
}
println!("\nend")
println!("\ndisconnecting client");
println!("end")
}
+10 -15
View File
@@ -1,5 +1,5 @@
use nym_sdk::mixnet::ReconstructedMessage;
use nym_bin_common::logging::setup_logging;
use nym_sphinx_anonymous_replies::{self, requests::AnonymousSenderTag};
use rust_cosmos_broadcaster::{RequestTypes, SequenceRequestResponse, BroadcastResponse, service::{get_sequence, broadcast, create_broadcaster}, create_client};
@@ -8,16 +8,12 @@ async fn main() {
// setup_logging();
let mut client = create_client("/tmp/cosmos-broadcaster-mixnet-server-2".into()).await;
let our_address = client.nym_address();
println!("\nour client nym address is: {our_address}");
println!("\nservice's nym address: {our_address}");
// the httpclient we will use to broadcast our signed tx to the Nyx blockchain
let broadcaster = create_broadcaster().await;
/*
TODO
* add threads - loop just to check everything works quickly
*/
loop {
println!("\nWaiting for message");
println!("\nWaiting for new message");
// check incoming is empty - SURB requests also send data ( empty vec ) along
let mut received: Vec<ReconstructedMessage> = Vec::new();
// get the actual message - discard the empty vec sent along with the SURB request
@@ -26,28 +22,27 @@ async fn main() {
continue;
}
received = new_message;
println!("recieved: {:#?}", &received);
break
}
for r in received.iter() {
// convert incoming vec<u8> -> String
let s = String::from_utf8(r.message.clone());
println!("{:#?}", &s);
// println!("{:#?}", &s);
if s.is_ok() {
let p = s.unwrap();
println!("{:#?}", &p);
// println!("{:#?}", &p);
// parse JSON string -> request type & match
let request: RequestTypes = serde_json::from_str(&p).unwrap();
println!("incoming request: {:#?}", &request);
// println!("\nincoming request: {:#?}", &request);
match request {
RequestTypes::Sequence(request) => {
println!("\nincoming sequence request details:\nsigner address: {}\n", request.signer_address);
println!("\nincoming sequence request details:\nsigner address: {}", request.signer_address);
let sequence: SequenceRequestResponse = get_sequence(broadcaster.clone(), request.signer_address).await;
if Some(r.sender_tag).is_some() {
let return_recipient: AnonymousSenderTag = r.sender_tag.unwrap();
let return_recipient: AnonymousSenderTag = r.sender_tag.unwrap();
println!("replying to sender with sequence response from Nyx chain");
println!("return recipient surb bucket: {}", &return_recipient);
// todo actually return sequence serialised as json
client.send_str_reply(return_recipient, &serde_json::to_string(&sequence).unwrap()).await;
} else {
// TODO replace with actual error type to return
@@ -55,7 +50,7 @@ async fn main() {
}
},
RequestTypes::Broadcast(request) => {
println!("\nincoming sequence request details: {}\n", request.base58_tx_bytes);
println!("\nincoming broadcast request: {}\n", request.base58_tx_bytes);
let tx_hash: BroadcastResponse = broadcast(request.base58_tx_bytes, broadcaster.clone()).await;
if Some(r.sender_tag).is_some() {
let return_recipient: AnonymousSenderTag = r.sender_tag.unwrap();
+40 -7
View File
@@ -5,7 +5,7 @@ use nym_validator_client::signing::SignerData;
use nym_validator_client::nyxd::cosmwasm_client::types;
use cosmrs::bank::MsgSend;
use cosmrs::tx::Msg;
use cosmrs::{tx, AccountId, Coin, Denom};
use cosmrs::{tx, AccountId, Coin, Denom, ErrorReport};
use bip39;
use bs58;
use nym_sdk::mixnet::{self, MixnetClient, ReconstructedMessage};
@@ -36,7 +36,7 @@ pub async fn offline_sign(mnemonic: bip39::Mnemonic, to: AccountId, client: &mut
while let Some(new_message) = client.wait_for_messages().await {
if new_message.is_empty() {
continue;
} println!("got a response");
}
message = new_message;
break
}
@@ -104,7 +104,7 @@ pub async fn offline_sign(mnemonic: bip39::Mnemonic, to: AccountId, client: &mut
}
pub async fn send_tx(base58_tx: String, sp_address: Recipient, client: &mut MixnetClient) -> Option<Vec<mixnet::ReconstructedMessage>> {
pub async fn send_tx(base58_tx: String, sp_address: Recipient, client: &mut MixnetClient) -> (String, bool) {
let broadcast_request = crate::BroadcastRequest {
base58_tx_bytes: base58_tx
@@ -112,8 +112,41 @@ pub async fn send_tx(base58_tx: String, sp_address: Recipient, client: &mut Mixn
client.send_str(sp_address, &serde_json::to_string(&broadcast_request).unwrap()).await;
println!("\nWaiting for reply\n");
println!("Waiting for reply");
// handle incoming message - we presume its a reply from the SP
let mut message: Vec<ReconstructedMessage> = Vec::new();
// get the actual message - discard the empty vec sent along with the SURB topup request
while let Some(new_message) = client.wait_for_messages().await {
if new_message.is_empty() {
continue;
}
message = new_message;
break
}
// parse vec<u8> -> JSON String
let mut parsed = String::new();
for r in message.iter() {
parsed = String::from_utf8(r.message.clone()).unwrap();
break
};
let sp_response: crate::ResponseTypes = serde_json::from_str(&parsed).unwrap();
let res = match sp_response {
crate::ResponseTypes::Broadcast(response) => {
let broadcast_response = crate::BroadcastResponse {
tx_hash: response.tx_hash,
success: response.success
};
(broadcast_response.tx_hash, broadcast_response.success)
},
// TODO make this a proper error
_ => { println!("weird response"); (String::from("placeholder error"), false) }
};
res
client.wait_for_messages().await
}
}
+2 -2
View File
@@ -8,7 +8,6 @@ pub mod service;
pub const DEFAULT_VALIDATOR_RPC: &str = "https://qwerty-validator.qa.nymte.ch";
pub const DEFAULT_DENOM: &str = "unym";
pub const DEFAULT_PREFIX: &str = "n";
// pub const DEFAULT_SERVICE_NYM_ADDRESS: &str = "HfbesQm2pRYCN4BAdYXhkqXBbV1Pp929mtKsESVeWXh8.8AgoUPUQbXNBCPaqAaWd3vnxhc9484qwfgrrQwBngQk2@Ck8zpXTSXMtS9YZ7k7a5BiaoLZfffWuqGWLndujh4Lw4";
#[derive(Deserialize, Serialize, Debug)]
pub struct SequenceRequest {
@@ -29,7 +28,8 @@ pub struct BroadcastRequest {
#[derive(Deserialize, Serialize, Debug)]
pub struct BroadcastResponse{
pub tx_hash: String
pub tx_hash: String,
pub success: bool
}
#[derive(Debug, Deserialize, Serialize)]
+13 -7
View File
@@ -13,14 +13,12 @@ pub async fn get_sequence(broadcaster: HttpClient, signer_address: AccountId) ->
// get signer information
let sequence = broadcaster.get_sequence(&signer_address).await.unwrap();
let chain_id: tendermint::chain::Id = broadcaster.get_chain_id().await.unwrap();
crate::SequenceRequestResponse { account_number: sequence.account_number, sequence: sequence.sequence, chain_id }
}
pub async fn broadcast(base58_tx_bytes: String, broadcaster: HttpClient) -> crate::BroadcastResponse {
// decode the base58 tx to vec<u8>
let tx_bytes = bs58::decode(base58_tx_bytes).into_vec().unwrap();
println!("decoded tx bytes: {:#?}", tx_bytes);
// this is our sender address hardcoded for ease of the demo logging
let from_address: AccountId = "n1p8ayfmdash352gh6yy8zlxk24dm6yzc9mdq0p6".parse().unwrap();
@@ -33,6 +31,7 @@ pub async fn broadcast(base58_tx_bytes: String, broadcaster: HttpClient) -> crat
.unwrap();
// broadcast the tx
println!("broadcasting the tx to Nyx blockchain");
let broadcast_res = Client::broadcast_tx_commit(&broadcaster, tx_bytes.into())
.await
.unwrap();
@@ -43,12 +42,19 @@ pub async fn broadcast(base58_tx_bytes: String, broadcaster: HttpClient) -> crat
.unwrap()
.unwrap();
println!("{:#?}", broadcast_res.hash);
println!("balance before: {before}");
println!("balance after: {after}");
println!("returned transaction hash: {:#?}", broadcast_res.hash.to_string());
println!("balance before transaction: {before}");
println!("balance after transaction: {after}");
println!("returning tx hash to sender");
let success: bool = if after.amount < before.amount {
true
} else {
false
};
crate::BroadcastResponse {
tx_hash: serde_json::to_string(&broadcast_res.hash).unwrap()
tx_hash: serde_json::to_string(&broadcast_res.hash).unwrap(),
success,
}
}