1
//! Support for the `v1` proof of work scheme's intro payload extension
2

            
3
use crate::relaycell::hs::pow::ProofOfWorkType;
4
use tor_bytes::{EncodeResult, Reader, Result, Writeable, Writer};
5
use tor_hscrypto::pow::v1::{Effort, Nonce, SeedHead, SolutionByteArray};
6

            
7
/// Proof of work using the `v1` scheme
8
///
9
/// Specified as part of <https://spec.torproject.org/rend-spec/introduction-protocol.html#INTRO1_POW_EXT>
10
#[derive(derive_more::Constructor, amplify::Getters, Debug, Clone, PartialEq)]
11
pub struct ProofOfWorkV1 {
12
    /// Nonce value chosen by the client
13
    #[getter(as_ref)]
14
    nonce: Nonce,
15
    /// Effort chosen by the client
16
    #[getter(as_copy)]
17
    effort: Effort,
18
    /// Header with which to identify the applicable service-provided seed
19
    #[getter(as_copy)]
20
    seed_head: SeedHead,
21
    /// Proposed solution proof, not validated
22
    ///
23
    /// This byte array still needs to be validated first as a well-formed
24
    /// Equix solution, and then as a proof for a particular puzzle.
25
    #[getter(as_ref)]
26
    solution: SolutionByteArray,
27
}
28

            
29
impl ProofOfWorkV1 {
30
    /// Construct by reading the scheme-specific data, if the scheme ID is correct for [`ProofOfWorkV1`]
31
    pub(super) fn try_take_body_from(scheme: u8, b: &mut Reader<'_>) -> Result<Option<Self>> {
32
        if scheme == ProofOfWorkType::V1.get() {
33
            Ok(Some(Self {
34
                nonce: b.extract()?,
35
                effort: b.extract()?,
36
                seed_head: b.extract()?,
37
                solution: b.extract()?,
38
            }))
39
        } else {
40
            Ok(None)
41
        }
42
    }
43

            
44
    /// Write the scheme and scheme-specific portion the v1 Proof Of Work
45
    pub(super) fn write_onto<B: Writer + ?Sized>(&self, b: &mut B) -> EncodeResult<()> {
46
        b.write_u8(ProofOfWorkType::V1.get());
47
        self.nonce.write_onto(b)?;
48
        self.effort.write_onto(b)?;
49
        self.seed_head.write_onto(b)?;
50
        self.solution.write_onto(b)?;
51
        Ok(())
52
    }
53
}