diff --git a/src/components/finutils/src/bins/fn.rs b/src/components/finutils/src/bins/fn.rs index 1da5e8ed2..d63a7b026 100644 --- a/src/components/finutils/src/bins/fn.rs +++ b/src/components/finutils/src/bins/fn.rs @@ -483,12 +483,7 @@ fn run() -> Result<()> { wallet::public_key_from_bech32(addr).c(d!("invalid wallet address")) }) })?; - let fee_xfr_seckey = match m.value_of("fee-xfr-seckey") { - Some(path) => { - Some(fs::read_to_string(path).c(d!("Failed to read seckey file"))?) - } - None => None, - }; + let fee_randomizer = m.value_of("fee-randomizer"); if randomizer.is_none() { println!("{}", m.usage()); @@ -498,7 +493,7 @@ fn run() -> Result<()> { randomizer.unwrap(), dec_key, &to, - fee_xfr_seckey.as_deref(), + fee_randomizer.unwrap(), m.is_present("confidential-amount"), m.is_present("confidential-type"), ) diff --git a/src/components/finutils/src/bins/fn.yml b/src/components/finutils/src/bins/fn.yml index 1c24c9dc5..3d4e1e75c 100644 --- a/src/components/finutils/src/bins/fn.yml +++ b/src/components/finutils/src/bins/fn.yml @@ -555,6 +555,13 @@ subcommands: takes_value: true value_name: RANDOMIZER required: true + - fee-randomizer: + help: Randomizer for the FRA ABAR to pay fee + short: F + long: fee-randomizer + takes_value: true + value_name: FEE RANDOMIZER + required: true - to-pubkey: help: base64-formated `XfrPublicKey` of the receiver short: t @@ -568,12 +575,6 @@ subcommands: takes_value: true value_name: XFR WALLET ADDRESS required: true - - fee-xfr-seckey: - help: Xfr secret key for fee payment - long: fee-xfr-seckey - takes_value: true - value_name: XFR SECRET KEY - required: false - confidential-amount: help: mask the amount sent on the transaction log long: confidential-amount diff --git a/src/components/finutils/src/common/mod.rs b/src/components/finutils/src/common/mod.rs index 4d254f07f..044ca6390 100644 --- a/src/components/finutils/src/common/mod.rs +++ b/src/components/finutils/src/common/mod.rs @@ -37,6 +37,7 @@ use { parse_td_validator_keys, }, zei::anon_xfr::{ + anon_fee::ANON_FEE_MIN, keys::{AXfrKeyPair, AXfrPubKey}, nullifier, structs::{AnonBlindAssetRecord, MTLeafInfo, OpenAnonBlindAssetRecordBuilder}, @@ -804,18 +805,19 @@ pub fn convert_bar2abar( let oar = utils::get_oar(&from, TxoSID(sid)).c(d!("error fetching open asset record"))?; - let r = utils::generate_bar2abar_op(&from, &to, TxoSID(sid), &oar, &enc_key)?; + let r = utils::generate_bar2abar_op(&from, &to, TxoSID(sid), &oar, &enc_key) + .c(d!("Bar to abar failed"))?; Ok(r) } -/// Convert an ABAR to a BLind Asset Record +/// Convert an ABAR to a Blind Asset Record pub fn convert_abar2bar( axfr_secret_key: String, r: &str, dec_key: String, to: &XfrPublicKey, - fee_xfr_seckey: Option<&str>, + fr: &str, confidential_am: bool, confidential_ty: bool, ) -> Result<()> { @@ -823,7 +825,7 @@ pub fn convert_abar2bar( .c(d!("invalid 'from-axfr-secret-key'"))?; let from_secret_key = wallet::x_secret_key_from_base64(dec_key.as_str()).c(d!("invalid dec_key"))?; - let fee_secret_key = restore_keypair_from_str_with_default(fee_xfr_seckey)?; + let from_public_key = XPublicKey::from(&from_secret_key); let r = wallet::randomizer_from_base58(r).c(d!())?; let randomized_from_pub_key = from.pub_key().randomize(&r); @@ -860,6 +862,35 @@ pub fn convert_abar2bar( )); } + let fr = wallet::randomizer_from_base58(fr).c(d!())?; + let fee_randomized_key = from.pub_key().randomize(&fr); + let fee_axtxo_abar = utils::get_owned_abars(&fee_randomized_key).c(d!())?; + let fee_owner_memo = utils::get_abar_memo(&fee_axtxo_abar[0].0).c(d!())?.unwrap(); + let fee_mt_leaf_info = utils::get_abar_proof(&fee_axtxo_abar[0].0) + .c(d!())? + .unwrap(); + + let fee_oabar = OpenAnonBlindAssetRecordBuilder::from_abar( + &fee_axtxo_abar[0].1, + fee_owner_memo, + &from, + &from_secret_key, + ) + .unwrap() + .mt_leaf_info(fee_mt_leaf_info) + .build() + .unwrap(); + + let mut prng = ChaChaRng::from_entropy(); + let out_fee_oabar = OpenAnonBlindAssetRecordBuilder::new() + .amount(fee_oabar.get_amount() - ANON_FEE_MIN) + .asset_type(fee_oabar.get_asset_type()) + .pub_key(from.pub_key()) + .finalize(&mut prng, &from_public_key) + .unwrap() + .build() + .unwrap(); + let art = match (confidential_am, confidential_ty) { (true, true) => AssetRecordType::ConfidentialAmount_ConfidentialAssetType, (true, false) => AssetRecordType::ConfidentialAmount_NonConfidentialAssetType, @@ -867,7 +898,25 @@ pub fn convert_abar2bar( _ => AssetRecordType::NonConfidentialAmount_NonConfidentialAssetType, }; - utils::generate_abar2bar_op(&oabar_in, &from, to, art, &fee_secret_key).c(d!())?; + utils::generate_abar2bar_op(&oabar_in, &fee_oabar, &out_fee_oabar, &from, to, art) + .c(d!())?; + + println!( + "\x1b[31;01m Fee Remainder Randomizer: {}\x1b[00m", + wallet::randomizer_to_base58(&out_fee_oabar.get_key_rand_factor()) + ); + let mut file = fs::OpenOptions::new() + .append(true) + .create(true) + .open("owned_randomizers") + .expect("cannot open randomizers file"); + std::io::Write::write_all( + &mut file, + ("\n".to_owned() + + &wallet::randomizer_to_base58(&out_fee_oabar.get_key_rand_factor())) + .as_bytes(), + ) + .expect("randomizer write failed"); Ok(()) } diff --git a/src/components/finutils/src/common/utils.rs b/src/components/finutils/src/common/utils.rs index b4ca0197f..379b288cc 100644 --- a/src/components/finutils/src/common/utils.rs +++ b/src/components/finutils/src/common/utils.rs @@ -726,12 +726,13 @@ pub fn generate_bar2abar_op( input_record, enc_key, ) - .c(d!())?; + .c(d!("Failed to generate operation bar to abar"))?; - let feeop = gen_fee_bar_to_abar(auth_key_pair, txo_sid).c(d!())?; + let feeop = + gen_fee_bar_to_abar(auth_key_pair, txo_sid).c(d!("Failed to generate fee"))?; builder.add_operation(feeop); - send_tx(&builder.take_transaction()).c(d!())?; + send_tx(&builder.take_transaction()).c(d!("Failed to submit Bar to Abar txn"))?; Ok(r) } @@ -739,18 +740,22 @@ pub fn generate_bar2abar_op( #[allow(missing_docs)] pub fn generate_abar2bar_op( oabar_in: &OpenAnonBlindAssetRecord, + fee_oabar: &OpenAnonBlindAssetRecord, + out_fee_oabar: &OpenAnonBlindAssetRecord, from: &AXfrKeyPair, to: &XfrPublicKey, art: AssetRecordType, - fee_keypair: &XfrKeyPair, ) -> Result<()> { let mut builder: TransactionBuilder = new_tx_builder().c(d!())?; builder .add_operation_abar_to_bar(oabar_in, from, to, art) .c(d!())?; - let feeop = gen_fee_op(fee_keypair).c(d!())?; - builder.add_operation(feeop); + /* let feeop = gen_fee_op(fee_keypair).c(d!())?; + builder.add_operation(feeop); */ + builder + .add_operation_anon_fee(fee_oabar, out_fee_oabar, from) + .c(d!())?; send_tx(&builder.take_transaction()).c(d!())?; Ok(()) diff --git a/src/components/finutils/src/txn_builder/mod.rs b/src/components/finutils/src/txn_builder/mod.rs index 68da4cb91..25c85a9ac 100644 --- a/src/components/finutils/src/txn_builder/mod.rs +++ b/src/components/finutils/src/txn_builder/mod.rs @@ -7,7 +7,6 @@ mod amount; -use ledger::data_model::AbarToBarOps; use { credentials::CredUserSecretKey, crypto::basics::hybrid_encryption::XPublicKey, @@ -17,9 +16,10 @@ use { ledger::{ converter::ConvertAccount, data_model::{ - AnonTransferOps, AssetRules, AssetTypeCode, BarToAbarOps, ConfidentialMemo, - DefineAsset, DefineAssetBody, IndexedSignature, IssueAsset, IssueAssetBody, - IssuerKeyPair, IssuerPublicKey, Memo, NoReplayToken, Operation, Transaction, + AbarToBarOps, AnonFeeOps, AnonTransferOps, AssetRules, AssetTypeCode, + BarToAbarOps, ConfidentialMemo, DefineAsset, DefineAssetBody, + IndexedSignature, IssueAsset, IssueAssetBody, IssuerKeyPair, + IssuerPublicKey, Memo, NoReplayToken, Operation, Transaction, TransactionBody, TransferAsset, TransferAssetBody, TransferType, TxOutput, TxoRef, TxoSID, UpdateMemo, UpdateMemoBody, ASSET_TYPE_FRA, BLACK_HOLE_PUBKEY, TX_FEE_MIN, @@ -51,6 +51,7 @@ use { zei::{ anon_xfr::{ abar_to_bar::gen_abar_to_bar_note, + anon_fee::{gen_anon_fee_body, AnonFeeNote}, bar_to_abar::gen_bar_to_abar_body, config::FEE_CALCULATING_FUNC, gen_anon_xfr_body, @@ -562,6 +563,27 @@ impl TransactionBuilder { Ok(self) } + /// Add an operation to charge fee anonymously for ABAR to BAR transfer + #[allow(dead_code)] + pub fn add_operation_anon_fee( + &mut self, + input: &OpenAnonBlindAssetRecord, + output: &OpenAnonBlindAssetRecord, + input_keypair: &AXfrKeyPair, + ) -> Result<(&mut Self, AnonFeeNote)> { + let mut prng = ChaChaRng::from_entropy(); + let user_params = UserParams::anon_fee_params(MERKLE_TREE_DEPTH)?; + + let (body, keypairs) = + gen_anon_fee_body(&mut prng, &user_params, input, output, input_keypair) + .c(d!())?; + let note = AnonFeeNote::generate_note_from_body(body, keypairs).c(d!())?; + let inp = AnonFeeOps::new(note.clone(), self.no_replay_token).c(d!())?; + let op = Operation::AnonymousFee(Box::new(inp)); + self.txn.add_operation(op); + Ok((self, note)) + } + /// Add an operation to transfer assets held in Anonymous Blind Asset Record. #[allow(dead_code)] pub fn add_operation_anon_transfer( @@ -1426,17 +1448,14 @@ impl AnonTransferOperationBuilder { let fra_excess = fra_input_sum - fra_output_sum; - let boolean = estimated_fees > fra_excess; - - let outcome = match boolean { - true => FEE_CALCULATING_FUNC( + if estimated_fees > fra_excess { + FEE_CALCULATING_FUNC( self.inputs.len() as u32 + 1, self.outputs.len() as u32 + 1, - ) as u64, - false => 0u64, - }; - - outcome + ) as u64 + } else { + 0u64 + } } /// get_randomizers fetches the randomizers for the different outputs. diff --git a/src/components/wasm/src/wasm.rs b/src/components/wasm/src/wasm.rs index 3a0e331ce..292da33ab 100644 --- a/src/components/wasm/src/wasm.rs +++ b/src/components/wasm/src/wasm.rs @@ -66,6 +66,7 @@ use { wasm_bindgen::prelude::*, zei::{ anon_xfr::{ + anon_fee::ANON_FEE_MIN, keys::{AXfrKeyPair, AXfrPubKey}, nullifier, structs::{ @@ -160,16 +161,6 @@ pub fn get_null_pk() -> XfrPublicKey { pub struct RandomizerStringArray { randomizers: Vec, } -/* -#[wasm_bindgen] -pub struct OBlindAssetRecord{ - oabar: OpenAnonBlindAssetRecord, -} - -impl OBlindAssetRecord{ - pub fn get_oabar(&self) -> &OpenAnonBlindAssetRecord{&self.oabar} -} - */ #[wasm_bindgen] /// Structure that allows users to construct arbitrary transactions. @@ -560,6 +551,57 @@ impl TransactionBuilder { Ok(self) } + /// Adds an anon fee operation to transaction builder for abar to a bar. + /// + /// @param {AnonBlindAssetRecord} input - the ABAR to be used for fee + /// @param {OwnerMemo} owner_memo - the corresponding owner_memo of the fee ABAR + /// @param {MTLeafInfo} mt_leaf_info - the Merkle Proof of the ABAR + /// @param {AXfrKeyPair} from_keypair - the owners Anon Key pair + /// @param {XSecretKey} from_dec_key - the owners decryption key + pub fn add_operation_anon_fee( + mut self, + input: AnonBlindAssetRecord, + owner_memo: OwnerMemo, + mt_leaf_info: MTLeafInfo, + from_keypair: AXfrKeyPair, + from_dec_key: XSecretKey, + ) -> Result { + let fee_oabar = OpenAnonBlindAssetRecordBuilder::from_abar( + &input, + owner_memo.memo, + &from_keypair, + &from_dec_key, + ) + .c(d!()) + .map_err(|e| JsValue::from_str(&format!("Could not add operation: {}", e)))? + .mt_leaf_info(mt_leaf_info.get_zei_mt_leaf_info().clone()) + .build() + .c(d!()) + .map_err(|e| JsValue::from_str(&format!("Could not add operation: {}", e)))?; + + let mut prng = ChaChaRng::from_entropy(); + let from_public_key = XPublicKey::from(&from_dec_key); + let rem_oabar = OpenAnonBlindAssetRecordBuilder::new() + .amount(fee_oabar.get_amount() - ANON_FEE_MIN) + .asset_type(fee_oabar.get_asset_type()) + .pub_key(from_keypair.pub_key()) + .finalize(&mut prng, &from_public_key) + .unwrap() + .build() + .unwrap(); + + self.get_builder_mut() + .add_operation_anon_fee(&fee_oabar, &rem_oabar, &from_keypair) + .c(d!()) + .map_err(|e| { + JsValue::from_str(&format!("Could not add operation: {}", e)) + })?; + + let r = rem_oabar.get_key_rand_factor(); + self.randomizers.push(r); + Ok(self) + } + /// Returns a list of randomizer base58 strings as json pub fn get_randomizers(&self) -> JsValue { let r = RandomizerStringArray { @@ -1732,9 +1774,6 @@ use rand_core::{CryptoRng, RngCore}; use ring::pbkdf2; use std::num::NonZeroU32; use std::str; -use zei::anon_xfr::config::FEE_CALCULATING_FUNC; -use zei::xfr::structs::AssetType; -//use ledger::store::LedgerState; #[wasm_bindgen] /// Returns bech32 encoded representation of an XfrPublicKey. @@ -2114,9 +2153,8 @@ mod test { fn gen_oabar_and_keys( prng: &mut R, - //amount: u64, amount: u64, - asset_type: AssetType, + asset_type: ZeiAssetType, ) -> ( OpenAnonBlindAssetRecord, AXfrKeyPair, diff --git a/src/ledger/src/data_model/effects.rs b/src/ledger/src/data_model/effects.rs index 01155d171..f4bf80c74 100644 --- a/src/ledger/src/data_model/effects.rs +++ b/src/ledger/src/data_model/effects.rs @@ -3,10 +3,10 @@ use zei::anon_xfr::abar_to_bar::AbarToBarBody; use { crate::{ data_model::{ - AnonTransferOps, AssetType, AssetTypeCode, BarToAbarOps, DefineAsset, - IssueAsset, IssuerPublicKey, Memo, NoReplayToken, Operation, Transaction, - TransferAsset, TransferType, TxOutput, TxnTempSID, TxoRef, TxoSID, - UpdateMemo, + AnonFeeOps, AnonTransferOps, AssetType, AssetTypeCode, BarToAbarOps, + DefineAsset, IssueAsset, IssuerPublicKey, Memo, NoReplayToken, Operation, + Transaction, TransferAsset, TransferType, TxOutput, TxnTempSID, TxoRef, + TxoSID, UpdateMemo, }, staking::{ self, @@ -31,6 +31,7 @@ use { }, zei::{ anon_xfr::{ + anon_fee::AnonFeeBody, bar_to_abar::verify_bar_to_abar_note, structs::{AXfrBody, AnonBlindAssetRecord, Nullifier}, }, @@ -103,6 +104,8 @@ pub struct TxnEffect { pub abar_conv_inputs: Vec, /// New anon transfer bodies pub axfr_bodies: Vec, + /// New anon fee bodies + pub anon_fee_bodies: Vec, } impl TxnEffect { @@ -214,6 +217,10 @@ impl TxnEffect { check_nonce!(i); te.add_anon_transfer(i).c(d!())?; } + Operation::AnonymousFee(i) => { + check_nonce!(i); + te.add_anon_fee_op(i).c(d!())?; + } } } @@ -634,6 +641,16 @@ impl TxnEffect { Ok(()) } + + fn add_anon_fee_op(&mut self, anon_fee: &AnonFeeOps) -> Result<()> { + // verify anon_fee_note signatures + anon_fee.note.verify_signatures().c(d!())?; + + // push + self.anon_fee_bodies.push(anon_fee.note.body.clone()); + + Ok(()) + } } /// Check tx in the context of a block, partially. @@ -734,6 +751,14 @@ impl BlockEffect { current_txn_abars.push(abar) } } + + for anon_fee_body in txn_effect.anon_fee_bodies { + let (n, _) = anon_fee_body.input; + self.new_nullifiers.push(n); + + let op_abar = anon_fee_body.output; + current_txn_abars.push(op_abar) + } self.output_abars.push(current_txn_abars); Ok(temp_sid) @@ -759,6 +784,17 @@ impl BlockEffect { if self.new_nullifiers.contains(&inputs.input.0) { return Err(eg!()); } + if txn_effect.anon_fee_bodies.is_empty() { + return Err(eg!()); + } + } + + // Check that no nullifier are created twice in same block + for anon_fee_body in txn_effect.anon_fee_bodies.iter() { + let (nullifier, _) = anon_fee_body.input; + if self.new_nullifiers.contains(&nullifier) { + return Err(eg!()); + } } // Check that no AssetType is affected by both the block so far and diff --git a/src/ledger/src/data_model/mod.rs b/src/ledger/src/data_model/mod.rs index dc0be67f9..0e1bfb39e 100644 --- a/src/ledger/src/data_model/mod.rs +++ b/src/ledger/src/data_model/mod.rs @@ -46,6 +46,7 @@ use { unicode_normalization::UnicodeNormalization, zei::{ anon_xfr::{ + anon_fee::AnonFeeNote, bar_to_abar::{BarToAbarBody, BarToAbarNote}, keys::AXfrPubKey, structs::AXfrNote, @@ -1363,6 +1364,31 @@ impl AnonTransferOps { } } +/// A struct to hold the anon fee used for abar to bar conversion +#[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)] +pub struct AnonFeeOps { + /// The note which holds the signatures, the ZKF and memo + pub note: AnonFeeNote, + nonce: NoReplayToken, +} +impl AnonFeeOps { + /// Generates the anon fee note + pub fn new(note: AnonFeeNote, nonce: NoReplayToken) -> Result { + Ok(AnonFeeOps { note, nonce }) + } + + #[inline(always)] + #[allow(dead_code)] + fn set_nonce(&mut self, nonce: NoReplayToken) { + self.nonce = nonce; + } + + #[inline(always)] + fn get_nonce(&self) -> NoReplayToken { + self.nonce + } +} + /// Operation list supported in findora network #[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)] pub enum Operation { @@ -1398,6 +1424,8 @@ pub enum Operation { AbarToBar(Box), /// Anonymous transfer operation TransferAnonAsset(Box), + /// Anonymous fee operation for abar to bar xfr + AnonymousFee(Box), } fn set_no_replay_token(op: &mut Operation, no_replay_token: NoReplayToken) { @@ -1428,6 +1456,7 @@ fn set_no_replay_token(op: &mut Operation, no_replay_token: NoReplayToken) { Operation::BarToAbar(i) => i.set_nonce(no_replay_token), Operation::AbarToBar(i) => i.set_nonce(no_replay_token), Operation::TransferAnonAsset(i) => i.set_nonce(no_replay_token), + Operation::AnonymousFee(i) => i.set_nonce(no_replay_token), _ => {} } } diff --git a/src/ledger/src/store/api_cache.rs b/src/ledger/src/store/api_cache.rs index a98230d18..a3f23d3b4 100644 --- a/src/ledger/src/store/api_cache.rs +++ b/src/ledger/src/store/api_cache.rs @@ -281,6 +281,9 @@ where Operation::TransferAnonAsset(_) => { // Anon } + Operation::AnonymousFee(_) => { + // Anon Fee + } Operation::ConvertAccount(i) => { related_addresses.insert(XfrAddress { key: i.get_related_address(), diff --git a/src/ledger/src/store/mod.rs b/src/ledger/src/store/mod.rs index 279dc8722..930f4e62a 100644 --- a/src/ledger/src/store/mod.rs +++ b/src/ledger/src/store/mod.rs @@ -57,6 +57,7 @@ use { zei::{ anon_xfr::{ abar_to_bar::verify_abar_to_bar_body, + anon_fee::verify_anon_fee_body, hash_abar, keys::AXfrPubKey, structs::{AnonBlindAssetRecord, MTLeafInfo, MTNode, MTPath, Nullifier}, @@ -1682,7 +1683,24 @@ impl LedgerStatus { .c(d!())?; } + // An anon_fee_body requires abar merkle root hash for AnonFeeNote verification. This is done + // here with LedgerStatus available. + for anon_fee_body in txn_effect.anon_fee_bodies.iter() { + let node_params = NodeParams::anon_fee_params()?; + let abar_version = anon_fee_body.proof.merkle_root_version; + verify_anon_fee_body( + &node_params, + anon_fee_body, + &self.get_versioned_abar_hash(abar_version as usize).unwrap(), + ) + .c(d!())?; + } + for abar_conv in &txn_effect.abar_conv_inputs { + if txn_effect.anon_fee_bodies.is_empty() { + return Err(eg!("Abar to Bar conversion missing anon fee")); + } + let node_params = NodeParams::abar_to_bar_params()?; let abar_version: usize = abar_conv.proof.get_merkle_root_version(); diff --git a/tools/triple_masking/abar_to_bar_convert.sh b/tools/triple_masking/abar_to_bar_convert.sh index 49eba756a..042bf0486 100755 --- a/tools/triple_masking/abar_to_bar_convert.sh +++ b/tools/triple_masking/abar_to_bar_convert.sh @@ -1,18 +1,41 @@ set -e ./tools/triple_masking/bar_to_abar_convert.sh - sleep 10 echo "BAR Balance:" target/release/fn wallet --show +set +e +rm anon-keys-temp2.keys +echo " +{ + \"axfr_secret_key\": \"MwdsbYhTp4Io062nV7E2HkJfsnaTCZpkdjr6aijv2Aem3KjuGWqf4TLB_-20b305Ja3Pop8NS8tgMNUOVXUL5Q==\", + \"axfr_public_key\": \"ptyo7hlqn-Eywf_ttG99OSWtz6KfDUvLYDDVDlV1C-U=\", + \"enc_key\": \"SAmB7Oji4sAgENLaLb4PFclxQL_DRrEkXcYp6eXuXwI=\", + \"dec_key\": \"AEq1ZUFk_fB__YaNjQ3D2taGOnMZAx4adpB6RbnPj24=\" +}" > anon-keys-temp2.keys +sleep 5 +set -e + +target/release/fn owned-utxos +echo "\n\n\n Bar To Abar Conversion for fee ABAR" +sleep 10 +target/release/fn convert-bar-to-abar --anon-keys ./anon-keys-temp.keys --txo-sid 9 2> /dev/null -randomiser=$(tail -n 1 owned_randomizers) -echo "\n\n Owned Abars after Bar to Abar conversion" -sleep 20 #Do not remove/decrease +tail -n 2 owned_randomizers > randomizer_file +randomiser=$(awk 'FNR>=1 && FNR<=1' randomizer_file) +echo "\n\n Owned Abars after Bar to Abar conversion 1" +sleep 20 target/release/fn owned-abars -p zQa8j0mGYUXM6JxjWN_pqfOi1lvEyenJYq35OIJNN08= -r $randomiser +fee_randomiser=$(awk 'FNR>=2 && FNR<=2' randomizer_file) +echo "\n\n Owned Abars after Bar to Abar conversion 2" +sleep 20 +target/release/fn owned-abars -p zQa8j0mGYUXM6JxjWN_pqfOi1lvEyenJYq35OIJNN08= -r $fee_randomiser -target/release/fn convert-abar-to-bar --anon-keys ./anon-keys-temp.keys -r $randomiser --to-wallet-address fra1ck6mu4fgmh7n3g0y5jm0zjrq6hwgckut9q2tf5fpwhrdgkhgdp9qhla5t5 +echo "\n\n\n ABAR To BAR Conversion" +echo "------------------------------------------------------------------------------" +sleep 5 +target/release/fn convert-abar-to-bar --anon-keys ./anon-keys-temp.keys -r $randomiser -F $fee_randomiser --to-wallet-address fra1ck6mu4fgmh7n3g0y5jm0zjrq6hwgckut9q2tf5fpwhrdgkhgdp9qhla5t5 sleep 10