pub mod prover_result;
use ergotree_interpreter::sigma_protocol::prover::ContextExtension;
use ergotree_interpreter::sigma_protocol::prover::ProofBytes;
use ergotree_ir::chain::ergo_box::BoxId;
use ergotree_ir::serialization::sigma_byte_reader::SigmaByteRead;
use ergotree_ir::serialization::sigma_byte_writer::SigmaByteWrite;
use ergotree_ir::serialization::SigmaParsingError;
use ergotree_ir::serialization::SigmaSerializable;
use ergotree_ir::serialization::SigmaSerializeResult;
#[cfg(feature = "json")]
use crate::chain::json::context_extension::ContextExtensionSerde;
use crate::wallet::box_selector::ErgoBoxId;
#[cfg(feature = "json")]
use serde::ser::SerializeStruct;
#[cfg(feature = "json")]
use serde::{Deserialize, Serialize};
use self::prover_result::ProverResult;
#[derive(PartialEq, Eq, Debug, Clone)]
#[cfg_attr(feature = "arbitrary", derive(proptest_derive::Arbitrary))]
#[cfg_attr(feature = "json", derive(Deserialize))]
pub struct UnsignedInput {
#[cfg_attr(feature = "json", serde(rename = "boxId"))]
pub box_id: BoxId,
#[cfg_attr(
feature = "json",
serde(rename = "extension",),
serde(with = "crate::chain::json::context_extension::ContextExtensionSerde")
)]
pub extension: ContextExtension,
}
#[cfg(feature = "json")]
impl Serialize for UnsignedInput {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: serde::Serializer,
{
let mut s = serializer.serialize_struct("UnsignedInput", 2)?;
s.serialize_field("boxId", &self.box_id)?;
s.serialize_field(
"extension",
&ContextExtensionSerde::from(self.extension.clone()),
)?;
s.end()
}
}
impl UnsignedInput {
pub fn new(box_id: BoxId, extension: ContextExtension) -> Self {
UnsignedInput { box_id, extension }
}
}
impl<T: ErgoBoxId> From<T> for UnsignedInput {
fn from(b: T) -> Self {
UnsignedInput::new(b.box_id(), ContextExtension::empty())
}
}
#[derive(PartialEq, Eq, Debug, Clone)]
#[cfg_attr(feature = "arbitrary", derive(proptest_derive::Arbitrary))]
#[cfg_attr(feature = "json", derive(Serialize, Deserialize))]
pub struct Input {
#[cfg_attr(feature = "json", serde(rename = "boxId", alias = "id"))]
pub box_id: BoxId,
#[cfg_attr(feature = "json", serde(rename = "spendingProof",))]
pub spending_proof: ProverResult,
}
impl Input {
pub fn new(box_id: BoxId, spending_proof: ProverResult) -> Self {
Self {
box_id,
spending_proof,
}
}
pub fn from_unsigned_input(unsigned_input: UnsignedInput, proof_bytes: ProofBytes) -> Self {
Self::new(
unsigned_input.box_id,
ProverResult {
proof: proof_bytes,
extension: unsigned_input.extension,
},
)
}
pub fn input_to_sign(&self) -> Input {
Input {
box_id: self.box_id,
spending_proof: ProverResult {
proof: ProofBytes::Empty,
extension: self.spending_proof.extension.clone(),
},
}
}
}
impl SigmaSerializable for Input {
fn sigma_serialize<W: SigmaByteWrite>(&self, w: &mut W) -> SigmaSerializeResult {
self.box_id.sigma_serialize(w)?;
self.spending_proof.sigma_serialize(w)?;
Ok(())
}
fn sigma_parse<R: SigmaByteRead>(r: &mut R) -> Result<Self, SigmaParsingError> {
let box_id = BoxId::sigma_parse(r)?;
let spending_proof = ProverResult::sigma_parse(r)?;
Ok(Input {
box_id,
spending_proof,
})
}
}
#[cfg(test)]
#[allow(clippy::panic)]
mod tests {
use super::*;
use ergotree_ir::serialization::sigma_serialize_roundtrip;
use proptest::prelude::*;
proptest! {
#[test]
fn ser_roundtrip(v in any::<Input>()) {
prop_assert_eq![sigma_serialize_roundtrip(&v), v];
}
}
}