1
//! Implement parsing for the `pow-params v1` scheme
2

            
3
use crate::doc::hsdesc::inner::HsInnerKwd;
4
use crate::parse::tokenize::Item;
5
use crate::types::misc::{B64, Iso8601TimeNoSp};
6
use crate::{KeywordEncodable, NetdocErrorKind, Result};
7
use std::time::SystemTime;
8
use tor_checkable::timed::TimerangeBound;
9
use tor_hscrypto::pow::v1::{Effort, Seed};
10

            
11
/// The contents of a `pow-params v1` line
12
///
13
/// These parameters are defined in the specifications for the `v1` proof of work scheme:
14
/// <https://spec.torproject.org/hspow-spec/v1-equix.html#parameter-descriptor>
15
///
16
/// In addition to the scheme identifier itself, this type of
17
/// `pow-params` line includes a 32-byte seed with its own expiration
18
/// timestamp, and a suggested effort value that clients may use for
19
/// their initial request.
20
#[derive(Debug, Clone, derive_more::Constructor, amplify::Getters)]
21
pub struct PowParamsV1 {
22
    /// Time limited [`Seed`]
23
    #[getter(as_ref)]
24
    seed: TimerangeBound<Seed>,
25
    /// Last known suggested [`Effort`]
26
    ///
27
    /// This can be [`Effort::zero()`] if the puzzle is available but the
28
    /// service doesn't recommend using it for an initial connection attempt.
29
    #[getter(as_copy)]
30
    suggested_effort: Effort,
31
}
32

            
33
impl PowParamsV1 {
34
    /// Parse a single `pow-params v1` line from an `Item`
35
10
    pub(super) fn from_item(item: &Item<'_, HsInnerKwd>) -> Result<Self> {
36
10
        if item.has_obj() {
37
2
            return Err(NetdocErrorKind::UnexpectedObject
38
2
                .with_msg(item.kwd().to_str())
39
2
                .at_pos(item.pos()));
40
8
        }
41
8
        let seed = item.required_arg(1)?.parse::<B64>()?.into_array()?.into();
42
8
        let suggested_effort = item.required_arg(2)?.parse::<u32>()?.into();
43
8
        let expires: SystemTime = item.required_arg(3)?.parse::<Iso8601TimeNoSp>()?.into();
44
8
        Ok(Self {
45
8
            seed: TimerangeBound::new(seed, ..expires),
46
8
            suggested_effort,
47
8
        })
48
10
    }
49
}