pub fn extract_hints(
    tx_ctx: &TransactionContext<Transaction>,
    state_context: &ErgoStateContext,
    real_secrets_to_extract: Vec<SigmaBoolean>,
    simulated_secrets_to_extract: Vec<SigmaBoolean>,
) -> Result<TransactionHintsBag, TxSigningError> {
    let mut hints_bag = TransactionHintsBag::empty();
    for (i, input) in tx_ctx.spending_tx.inputs.iter().enumerate() {
        let input_box = tx_ctx
            .get_boxes_to_spend()
            .find(|b| b.box_id() == input.box_id)
            .ok_or(TxSigningError::InputBoxNotFound(i))?;
        let height = state_context.pre_header.height;
        let self_box = tx_ctx
            .get_boxes_to_spend()
            .find(|b| b.box_id() == tx_ctx.spending_tx.inputs.as_vec()[i].box_id)
            .cloned()
            .ok_or_else(|| {
                TxSigningError::ContextError("self_index is out of bounds".to_string())
            })?;
        let outputs = tx_ctx
            .spending_tx
            .output_candidates
            .iter()
            .enumerate()
            .map(|(idx, b)| ErgoBox::from_box_candidate(b, tx_ctx.spending_tx.id(), idx as u16))
            .collect::<Result<Vec<ErgoBox>, SigmaSerializationError>>()?;
        let outputs_ir = outputs.into_iter().map(Rc::new).collect();
        let data_inputs_ir = if let Some(data_inputs) = tx_ctx.spending_tx.data_inputs.as_ref() {
            Some(data_inputs.clone().enumerated().try_mapped(|(idx, di)| {
                tx_ctx
                    .data_boxes
                    .as_ref()
                    .ok_or(TxSigningError::DataInputBoxNotFound(idx))?
                    .iter()
                    .find(|b| di.box_id == b.box_id())
                    .map(|b| Rc::new(b.clone()))
                    .ok_or(TxSigningError::DataInputBoxNotFound(idx))
            })?)
        } else {
            None
        };
        let inputs_ir = tx_ctx
            .spending_tx
            .inputs_ids()
            .enumerated()
            .try_mapped(|(idx, u)| {
                tx_ctx
                    .boxes_to_spend
                    .iter()
                    .find(|b| u == b.box_id())
                    .map(|b| Rc::new(b.clone()))
                    .ok_or(TxSigningError::InputBoxNotFound(idx))
            })?;
        let extension = tx_ctx
            .spending_tx
            .inputs
            .get(i)
            .ok_or_else(|| {
                TxSigningError::ContextError(
                    "self_index not found in spending transaction inputs".to_string(),
                )
            })?
            .spending_proof
            .extension
            .clone();
        let ctx = Rc::new(Context {
            height,
            self_box: Rc::new(self_box),
            outputs: outputs_ir,
            data_inputs: data_inputs_ir,
            inputs: inputs_ir,
            pre_header: state_context.pre_header.clone(),
            headers: state_context.headers.clone(),
            extension,
        });
        let tree = input_box.ergo_tree.clone();
        let proof: ProofBytes = tx_ctx
            .spending_tx
            .inputs
            .get(i)
            .unwrap()
            .clone()
            .spending_proof
            .proof;
        let proof: Vec<u8> = Vec::from(proof);
        let exp = tree
            .proposition()
            .map_err(ProverError::ErgoTreeError)
            .map_err(|e| TxSigningError::ProverError(e, i))?;
        let reduction_result = reduce_to_crypto(&exp, &Env::empty(), ctx)
            .map_err(ProverError::EvalError)
            .map_err(|e| TxSigningError::ProverError(e, i))?;
        let sigma_tree = reduction_result.sigma_prop;
        let bag = bag_for_multi_sig(
            sigma_tree,
            real_secrets_to_extract.as_slice(),
            simulated_secrets_to_extract.as_slice(),
            proof.as_slice(),
        )
        .map_err(|_e| {
            TxSigningError::ProverError(Unexpected("Unexpected Sigma tree Value".to_string()), i)
        })?;
        hints_bag.add_hints_for_input(i, bag);
    }

    Ok(hints_bag)
}
/// Extracting hints from a transaction and outputs it's corresponding TransactionHintsBag
Extracting hints from a transaction and outputs it's corresponding TransactionHintsBag
Extracting hints from a transaction and outputs it ' s corresponding TransactionHintsBag
pub fn extract_hints(
    tx_ctx: &TransactionContext<Transaction>,
    state_context: &ErgoStateContext,
    real_secrets_to_extract: Vec<SigmaBoolean>,
    simulated_secrets_to_extract: Vec<SigmaBoolean>,
) -> Result<TransactionHintsBag, TxSigningError> {
    let mut hints_bag = TransactionHintsBag::empty();
    for (i, input) in tx_ctx.spending_tx.inputs.iter().enumerate() {
        let input_box = tx_ctx
            .get_boxes_to_spend()
            .find(|b| b.box_id() == input.box_id)
            .ok_or(TxSigningError::InputBoxNotFound(i))?;
        let height = state_context.pre_header.height;
        let self_box = tx_ctx
            .get_boxes_to_spend()
            .find(|b| b.box_id() == tx_ctx.spending_tx.inputs.as_vec()[i].box_id)
            .cloned()
            .ok_or_else(|| {
                TxSigningError::ContextError("self_index is out of bounds".to_string())
            })?;
        let outputs = tx_ctx
            .spending_tx
            .output_candidates
            .iter()
            .enumerate()
            .map(|(idx, b)| ErgoBox::from_box_candidate(b, tx_ctx.spending_tx.id(), idx as u16))
            .collect::<Result<Vec<ErgoBox>, SigmaSerializationError>>()?;
        let outputs_ir = outputs.into_iter().map(Rc::new).collect();
        let data_inputs_ir = if let Some(data_inputs) = tx_ctx.spending_tx.data_inputs.as_ref() {
            Some(data_inputs.clone().enumerated().try_mapped(|(idx, di)| {
                tx_ctx
                    .data_boxes
                    .as_ref()
                    .ok_or(TxSigningError::DataInputBoxNotFound(idx))?
                    .iter()
                    .find(|b| di.box_id == b.box_id())
                    .map(|b| Rc::new(b.clone()))
                    .ok_or(TxSigningError::DataInputBoxNotFound(idx))
            })?)
        } else {
            None
        };
        let inputs_ir = tx_ctx
            .spending_tx
            .inputs_ids()
            .enumerated()
            .try_mapped(|(idx, u)| {
                tx_ctx
                    .boxes_to_spend
                    .iter()
                    .find(|b| u == b.box_id())
                    .map(|b| Rc::new(b.clone()))
                    .ok_or(TxSigningError::InputBoxNotFound(idx))
            })?;
        let extension = tx_ctx
            .spending_tx
            .inputs
            .get(i)
            .ok_or_else(|| {
                TxSigningError::ContextError(
                    "self_index not found in spending transaction inputs".to_string(),
                )
            })?
            .spending_proof
            .extension
            .clone();
        let ctx = Rc::new(Context {
            height,
            self_box: Rc::new(self_box),
            outputs: outputs_ir,
            data_inputs: data_inputs_ir,
            inputs: inputs_ir,
            pre_header: state_context.pre_header.clone(),
            headers: state_context.headers.clone(),
            extension,
        });
        let tree = input_box.ergo_tree.clone();
        let proof: ProofBytes = tx_ctx
            .spending_tx
            .inputs
            .get(i)
            .unwrap()
            .clone()
            .spending_proof
            .proof;
        let proof: Vec<u8> = Vec::from(proof);
        let exp = tree
            .proposition()
            .map_err(ProverError::ErgoTreeError)
            .map_err(|e| TxSigningError::ProverError(e, i))?;
        let reduction_result = reduce_to_crypto(&exp, &Env::empty(), ctx)
            .map_err(ProverError::EvalError)
            .map_err(|e| TxSigningError::ProverError(e, i))?;
        let sigma_tree = reduction_result.sigma_prop;
        let bag = bag_for_multi_sig(
            sigma_tree,
            real_secrets_to_extract.as_slice(),
            simulated_secrets_to_extract.as_slice(),
            proof.as_slice(),
        )
        .map_err(|_e| {
            TxSigningError::ProverError(Unexpected("Unexpected Sigma tree Value".to_string()), i)
        })?;
        hints_bag.add_hints_for_input(i, bag);
    }
    Ok(hints_bag)
}
pub fn extract_hints ( tx_ctx : & TransactionContext < Transaction > , state_context : & ErgoStateContext , real_secrets_to_extract : Vec < SigmaBoolean > , simulated_secrets_to_extract : Vec < SigmaBoolean > , ) -> Result < TransactionHintsBag , TxSigningError > { let mut hints_bag = TransactionHintsBag :: empty ( ) ; for ( i , input ) in tx_ctx . spending_tx . inputs . iter ( ) . enumerate ( ) { let input_box = tx_ctx . get_boxes_to_spend ( ) . find ( | b | b . box_id ( ) == input . box_id ) . ok_or ( TxSigningError :: InputBoxNotFound ( i ) ) ? ; let height = state_context . pre_header . height ; let self_box = tx_ctx . get_boxes_to_spend ( ) . find ( | b | b . box_id ( ) == tx_ctx . spending_tx . inputs . as_vec ( ) [ i ] . box_id ) . cloned ( ) . ok_or_else ( | | { TxSigningError :: ContextError ( " " . to_string ( ) ) } ) ? ; let outputs = tx_ctx . spending_tx . output_candidates . iter ( ) . enumerate ( ) . map ( | ( idx , b ) | ErgoBox :: from_box_candidate ( b , tx_ctx . spending_tx . id ( ) , idx as u16 ) ) . collect :: < Result < Vec < ErgoBox > , SigmaSerializationError > > ( ) ? ; let outputs_ir = outputs . into_iter ( ) . map ( Rc :: new ) . collect ( ) ; let data_inputs_ir = if let Some ( data_inputs ) = tx_ctx . spending_tx . data_inputs . as_ref ( ) { Some ( data_inputs . clone ( ) . enumerated ( ) . try_mapped ( | ( idx , di ) | { tx_ctx . data_boxes . as_ref ( ) . ok_or ( TxSigningError :: DataInputBoxNotFound ( idx ) ) ? . iter ( ) . find ( | b | di . box_id == b . box_id ( ) ) . map ( | b | Rc :: new ( b . clone ( ) ) ) . ok_or ( TxSigningError :: DataInputBoxNotFound ( idx ) ) } ) ? ) } else { None } ; let inputs_ir = tx_ctx . spending_tx . inputs_ids ( ) . enumerated ( ) . try_mapped ( | ( idx , u ) | { tx_ctx . boxes_to_spend . iter ( ) . find ( | b | u == b . box_id ( ) ) . map ( | b | Rc :: new ( b . clone ( ) ) ) . ok_or ( TxSigningError :: InputBoxNotFound ( idx ) ) } ) ? ; let extension = tx_ctx . spending_tx . inputs . get ( i ) . ok_or_else ( | | { TxSigningError :: ContextError ( " " . to_string ( ) , ) } ) ? . spending_proof . extension . clone ( ) ; let ctx = Rc :: new ( Context { height , self_box : Rc :: new ( self_box ) , outputs : outputs_ir , data_inputs : data_inputs_ir , inputs : inputs_ir , pre_header : state_context . pre_header . clone ( ) , headers : state_context . headers . clone ( ) , extension , } ) ; let tree = input_box . ergo_tree . clone ( ) ; let proof : ProofBytes = tx_ctx . spending_tx . inputs . get ( i ) . unwrap ( ) . clone ( ) . spending_proof . proof ; let proof : Vec < u8 > = Vec :: from ( proof ) ; let exp = tree . proposition ( ) . map_err ( ProverError :: ErgoTreeError ) . map_err ( | e | TxSigningError :: ProverError ( e , i ) ) ? ; let reduction_result = reduce_to_crypto ( & exp , & Env :: empty ( ) , ctx ) . map_err ( ProverError :: EvalError ) . map_err ( | e | TxSigningError :: ProverError ( e , i ) ) ? ; let sigma_tree = reduction_result . sigma_prop ; let bag = bag_for_multi_sig ( sigma_tree , real_secrets_to_extract . as_slice ( ) , simulated_secrets_to_extract . as_slice ( ) , proof . as_slice ( ) , ) . map_err ( | _e | { TxSigningError :: ProverError ( Unexpected ( " " . to_string ( ) ) , i ) } ) ? ; hints_bag . add_hints_for_input ( i , bag ) ; } Ok ( hints_bag ) }
Extracting hints from a transaction and outputs it's corresponding TransactionHintsBag
Extracting hints from a transaction and outputs it ' s corresponding TransactionHintsBag
tx_ctx
&TransactionContext<Transaction>
state_context
&ErgoStateContext
real_secrets_to_extract
Vec<SigmaBoolean>
simulated_secrets_to_extract
Vec<SigmaBoolean>
tx_ctx
&TransactionContext<Transaction>
state_context
&ErgoStateContext
real_secrets_to_extract
Vec<SigmaBoolean>
simulated_secrets_to_extract
Vec<SigmaBoolean>