1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
pub mod error;
pub mod miner;
pub mod params;
pub mod traits;
use crate::params::{ClientParam, PoolParam};
use crate::traits::{PoolParams, StratumParams};
pub use error::Error;
pub use miner::MinerInfo;
use serde::{Deserialize, Deserializer, Serialize, Serializer};

pub type Result<T> = std::result::Result<T, Error>;

//There is definitely a better way to do this where request and response are generalized, and then
//when used in the pool we set params = PoolParams, and response sets ClientParams.
//@todo P1 Priority small, can be done later.
//
//
//@todo clean up all the params we hard-defined.

#[derive(Serialize, Deserialize)]
#[serde(untagged)]
pub enum PoolPacket<PP, SP>
where
    PP: PoolParams,
    SP: StratumParams,
{
    Request(PoolRequest<PP, SP>),
    Response(PoolResponse<PP, SP>),
}

#[derive(Serialize, Deserialize)]
#[serde(untagged)]
pub enum ClientPacket<PP, SP>
where
    PP: PoolParams,
    SP: StratumParams,
{
    Request(ClientRequest<PP, SP>),
    Response(ClientResponse<PP, SP>),
}

//Request Base Object
#[derive(Serialize, Deserialize)]
pub struct PoolRequest<PP, SP>
where
    PP: PoolParams,
    SP: StratumParams,
{
    pub id: String,
    pub method: StratumMethod,
    pub params: PoolParam<PP, SP>,
}

#[derive(Serialize, Deserialize)]
pub struct PoolResponse<PP, SP>
where
    PP: PoolParams,
    SP: StratumParams,
{
    pub id: String,
    pub method: StratumMethod,
    pub result: PoolParam<PP, SP>,
    pub error: Option<StratumError>,
}

#[derive(Serialize, Deserialize)]
pub struct ClientRequest<PP, SP>
where
    PP: PoolParams,
    SP: StratumParams,
{
    pub id: String,
    pub method: StratumMethod,
    pub params: ClientParam<PP, SP>,
}

#[derive(Serialize, Deserialize)]
pub struct ClientResponse<PP, SP>
where
    PP: PoolParams,
    SP: StratumParams,
{
    pub id: String,
    pub method: StratumMethod,
    //@todo lets see if there is a simple way of deserializing this based on the stratum method
    //above. https://github.com/serde-rs/json/issues/181
    pub result: ClientParam<PP, SP>,
    pub error: Option<StratumError>,
}

//@todo this should just be an ENUM.
#[derive(Serialize, Deserialize, Debug)]
pub struct StratumError {
    //@todo I hate the fact that the error codes are negative - if there isn't a vlaid reason
    //That this is the case, then move this back to u32, and let's just use positive numbers.
    pub code: i32,
    pub message: String,
}

#[derive(Debug)]
pub enum StratumMethod {
    //Sending and receiving
    Authorize,
    Submit,
    Subscribe,
    Notify,
    SetDifficulty,

    //Future methods potentially not implemented yet.
    Unknown(String),
}

impl Serialize for StratumMethod {
    fn serialize<S>(&self, serializer: S) -> std::result::Result<S::Ok, S::Error>
    where
        S: Serializer,
    {
        serializer.serialize_str(match *self {
            StratumMethod::Authorize => "authorize",
            StratumMethod::Submit => "submit",
            StratumMethod::Subscribe => "subscribe",
            StratumMethod::Notify => "notify",
            StratumMethod::SetDifficulty => "set_difficulty",
            StratumMethod::Unknown(ref s) => s,
        })
    }
}

impl<'de> Deserialize<'de> for StratumMethod {
    fn deserialize<D>(deserializer: D) -> std::result::Result<Self, D::Error>
    where
        D: Deserializer<'de>,
    {
        let s = String::deserialize(deserializer)?;
        Ok(match s.as_str() {
            "authorize" => StratumMethod::Authorize,
            "submit" => StratumMethod::Submit,
            "subscribe" => StratumMethod::Subscribe,
            "notify" => StratumMethod::Notify,
            "set_difficulty" => StratumMethod::SetDifficulty,
            _ => StratumMethod::Unknown(s),
        })
    }
}