dg_xch_core 2.1.1

Core library containing type/error definitions, CLVM tools, Consensus and Pool definitions
Documentation
use crate::blockchain::coin::Coin;
use crate::blockchain::condition_opcode::ConditionOpcode;
use crate::blockchain::condition_with_args::{ConditionWithArgs, Message};
use crate::blockchain::sized_bytes::{Bytes32, Bytes48};
use crate::clvm::condition_utils::{
    agg_sig_additional_data, conditions_dict_for_solution, created_outputs_for_conditions_dict,
    ConditionsDict,
};
use crate::clvm::program::SerializedProgram;
use crate::traits::SizedBytes;
use log::warn;
use num_bigint::BigInt;
use std::hash::RandomState;
use std::io::{Error, ErrorKind};

pub fn additions_for_solution(
    coin_name: Bytes32,
    puzzle_reveal: &SerializedProgram,
    solution: &SerializedProgram,
    max_cost: u64,
) -> Result<Vec<Coin>, Error> {
    let (map, _cost) =
        conditions_dict_for_solution::<RandomState>(puzzle_reveal, solution, max_cost)?;
    created_outputs_for_conditions_dict(&map, coin_name)
}

#[must_use]
pub fn fee_for_solution(
    puzzle_reveal: &SerializedProgram,
    solution: &SerializedProgram,
    max_cost: u64,
) -> BigInt {
    match conditions_dict_for_solution::<RandomState>(puzzle_reveal, solution, max_cost) {
        Ok((conditions, _cost)) => {
            let mut total: BigInt = 0.into();
            match conditions.get(&ConditionOpcode::ReserveFee) {
                Some(conditions) => {
                    for cond in conditions {
                        if let ConditionWithArgs::ReserveFee(fee) = cond {
                            total += *fee;
                        } else {
                            warn!("Found Invalid Condition in Conditions Dict")
                        }
                    }
                }
                None => {
                    total = 0.into();
                }
            }
            total
        }
        Err(_error) => 0.into(),
    }
}

pub fn pkm_pairs_for_conditions_dict<S: std::hash::BuildHasher + Default>(
    conditions_dict: &ConditionsDict<S>,
    coin: Coin,
    additional_data: &[u8],
) -> Result<Vec<(Bytes48, Message)>, Error> {
    let mut ret = vec![];
    if let Some(v) = conditions_dict.get(&ConditionOpcode::AggSigUnsafe) {
        for cwa in v {
            if let ConditionWithArgs::AggSigUnsafe(key, msg) = *cwa {
                if msg.data().ends_with(additional_data) {
                    return Err(Error::new(ErrorKind::Other, "Invalid Condition"));
                }
                ret.push((key, msg));
            } else {
                return Err(Error::new(ErrorKind::Other, "Invalid Condition"));
            }
        }
    }
    if let Some(v) = conditions_dict.get(&ConditionOpcode::AggSigMe) {
        for cwa in v {
            if let ConditionWithArgs::AggSigMe(key, msg) = *cwa {
                let mut buf = msg.data().to_vec();
                buf.extend(coin.name());
                buf.extend(additional_data);
                ret.push((key, Message::new(buf)?));
            } else {
                return Err(Error::new(ErrorKind::Other, "Invalid Condition"));
            }
        }
    }
    if let Some(v) = conditions_dict.get(&ConditionOpcode::AggSigPuzzle) {
        let agg_sig_map = agg_sig_additional_data::<S>(Bytes32::parse(additional_data)?);
        let additional_data = agg_sig_map
            .get(&ConditionOpcode::AggSigPuzzle)
            .copied()
            .unwrap_or_default();
        for cwa in v {
            if let ConditionWithArgs::AggSigPuzzle(key, msg) = *cwa {
                let mut buf = msg.data().to_vec();
                buf.extend(coin.puzzle_hash);
                buf.extend(additional_data);
                ret.push((key, Message::new(buf)?));
            } else {
                return Err(Error::new(ErrorKind::Other, "Invalid Condition"));
            }
        }
    }
    Ok(ret)
}