109 lines
4.0 KiB
Rust
109 lines
4.0 KiB
Rust
use crate::blocks::collateral::CollateralClaimTransaction;
|
|
use crate::blocks::loans::LoanContractTransaction;
|
|
use crate::common::network_paths_and_settings::block_extension_and_paths;
|
|
use crate::decode;
|
|
use crate::records::balance_sheet::operations::balance_sheet_operation_with_db;
|
|
use crate::records::record_chain::nft_provenance::remove_nft_history_entry;
|
|
use crate::rpc::commands::transaction_by_txid::request_transaction_by_txid;
|
|
use crate::rpc::responses::RpcResponse;
|
|
use crate::sled::Db;
|
|
|
|
pub async fn undo_collateral_transaction(
|
|
transaction: CollateralClaimTransaction,
|
|
mining_receiver: &str,
|
|
db: &Db,
|
|
) -> Result<(), String> {
|
|
// restore balances and contract state for a collateral
|
|
// claim that is being removed during orphan rollback
|
|
let operand_subtraction = "subtraction";
|
|
let operand_addition = "addition";
|
|
let (
|
|
_network_name,
|
|
_padded_base_coin,
|
|
type_str,
|
|
_torrentpath,
|
|
_wallet_path,
|
|
_blockpath,
|
|
_db_path,
|
|
_balance_path,
|
|
_log_path,
|
|
) = block_extension_and_paths();
|
|
|
|
// reload the original loan contract so the collateral
|
|
// asset and amount can be restored correctly
|
|
let contract_hash = decode(&transaction.unsigned_collateral_claim.contract_hash)
|
|
.map_err(|e| format!("Error decoding contract hash: {e}"))?;
|
|
let contract = request_transaction_by_txid(db, contract_hash.clone()).await;
|
|
|
|
let loan_txtype = 7;
|
|
let loan_tx = match contract {
|
|
RpcResponse::Binary(contract_bytes) => {
|
|
if contract_bytes.is_empty() {
|
|
return Err("Invalid loan contract: empty transaction bytes".to_string());
|
|
}
|
|
if contract_bytes[0] != loan_txtype {
|
|
return Err(
|
|
"Invalid loan contract: referenced transaction is not a loan contract"
|
|
.to_string(),
|
|
);
|
|
}
|
|
LoanContractTransaction::from_bytes(loan_txtype, &contract_bytes[1..])
|
|
.await
|
|
.map_err(|e| e.to_string())?
|
|
}
|
|
};
|
|
|
|
let collateral = loan_tx.unsigned_loan_contract.collateral;
|
|
let collateral_amount = loan_tx.unsigned_loan_contract.collateral_amount;
|
|
let collateral_holding = format!(
|
|
"collateral_{}",
|
|
transaction.unsigned_collateral_claim.contract_hash
|
|
);
|
|
let claimer = &transaction.unsigned_collateral_claim.address;
|
|
let txfee = transaction.unsigned_collateral_claim.txfee;
|
|
|
|
// reverse the fee and move the collateral back into the
|
|
// contract holding wallet until the claim exists again
|
|
let _ =
|
|
balance_sheet_operation_with_db(db, mining_receiver, txfee, &type_str, operand_subtraction);
|
|
let _ = balance_sheet_operation_with_db(db, claimer, txfee, &type_str, operand_addition);
|
|
let _ = balance_sheet_operation_with_db(
|
|
db,
|
|
claimer,
|
|
collateral_amount,
|
|
&collateral,
|
|
operand_subtraction,
|
|
);
|
|
let _ = balance_sheet_operation_with_db(
|
|
db,
|
|
&collateral_holding,
|
|
collateral_amount,
|
|
&collateral,
|
|
operand_addition,
|
|
);
|
|
|
|
// Remove the collateral-claim transaction lookup from the txid tree.
|
|
let txid_tree = db.open_tree("txid").unwrap();
|
|
let tx_hash = transaction.unsigned_collateral_claim.hash().await;
|
|
txid_tree
|
|
.remove(decode(&tx_hash).map_err(|e| format!("Error decoding txid: {e}"))?)
|
|
.unwrap();
|
|
|
|
// NFT collateral claims write provenance for the collateral asset.
|
|
let nft_tree = db.open_tree("nfts").unwrap();
|
|
let tx_hash_bytes = decode(&tx_hash).map_err(|e| format!("Error decoding txid: {e}"))?;
|
|
if nft_tree
|
|
.contains_key(collateral.as_bytes())
|
|
.unwrap_or(false)
|
|
{
|
|
let _ = remove_nft_history_entry(db, &collateral, &tx_hash_bytes);
|
|
}
|
|
|
|
// Mark the loan contract active again because the collateral claim no
|
|
// longer exists after rollback.
|
|
let loan_tree = db.open_tree("loan").unwrap();
|
|
loan_tree.insert(contract_hash, "true".as_bytes()).unwrap();
|
|
|
|
Ok(())
|
|
}
|