Skip to content

Commit 66ee0e1

Browse files
committed
chore: Implement DB read for /v3/signer/ endpoint
1 parent 32e74fb commit 66ee0e1

File tree

2 files changed

+39
-80
lines changed

2 files changed

+39
-80
lines changed

stackslib/src/chainstate/nakamoto/mod.rs

Lines changed: 28 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ use lazy_static::{__Deref, lazy_static};
3030
use rusqlite::blob::Blob;
3131
use rusqlite::types::{FromSql, FromSqlError, FromSqlResult, ToSql, ToSqlOutput};
3232
use rusqlite::{params, Connection, OpenFlags, OptionalExtension};
33+
use sha2::digest::typenum::Integer;
3334
use sha2::{Digest as Sha2Digest, Sha512_256};
3435
use stacks_common::bitvec::BitVec;
3536
use stacks_common::codec::{
@@ -3287,12 +3288,37 @@ impl NakamotoChainState {
32873288
StacksPublicKey::recover_to_pubkey(signer_sighash.bits(), &signer_signature)
32883289
.map_err(|e| ChainstateError::InvalidStacksBlock(e.to_string()))?;
32893290
let sql = "INSERT INTO signer_stats(public_key,reward_cycle) VALUES(?1,?2) ON CONFLICT(public_key,reward_cycle) DO UPDATE SET blocks_signed=blocks_signed+1";
3290-
let args = params![serde_json::to_string(&signer_pubkey).unwrap(), reward_cycle];
3291-
tx.execute(sql, args)?;
3291+
let params = params![serde_json::to_string(&signer_pubkey).unwrap(), reward_cycle];
3292+
tx.execute(sql, params)?;
32923293
}
32933294
Ok(())
32943295
}
32953296

3297+
/// Fetch number of blocks signed for a given signer and reward cycle
3298+
/// This is the data tracked by `record_block_signers()`
3299+
pub fn get_signer_block_count(
3300+
chainstate_db: &Connection,
3301+
signer_pubkey: &Secp256k1PublicKey,
3302+
reward_cycle: u64,
3303+
) -> Result<Option<u64>, ChainstateError> {
3304+
let sql =
3305+
"SELECT blocks_signed FROM signer_stats WHERE public_key = ?1 AND reward_cycle = ?2";
3306+
let params = params![serde_json::to_string(&signer_pubkey).unwrap(), reward_cycle];
3307+
chainstate_db
3308+
.query_row(sql, params, |row| {
3309+
let value: String = row.get(2)?;
3310+
value.parse::<u64>().map_err(|e| {
3311+
rusqlite::Error::FromSqlConversionFailure(
3312+
size_of::<u64>(),
3313+
rusqlite::types::Type::Integer,
3314+
e.into(),
3315+
)
3316+
})
3317+
})
3318+
.optional()
3319+
.map_err(ChainstateError::from)
3320+
}
3321+
32963322
/// Begin block-processing and return all of the pre-processed state within a
32973323
/// `SetupBlockResult`.
32983324
///

stackslib/src/net/api/getsigner.rs

Lines changed: 11 additions & 78 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ use stacks_common::util::hash::Sha256Sum;
2222
use crate::burnchains::Burnchain;
2323
use crate::chainstate::burn::db::sortdb::SortitionDB;
2424
use crate::chainstate::coordinator::OnChainRewardSetProvider;
25+
use crate::chainstate::nakamoto::NakamotoChainState;
2526
use crate::chainstate::stacks::boot::{
2627
PoxVersions, RewardSet, POX_1_NAME, POX_2_NAME, POX_3_NAME, POX_4_NAME,
2728
};
@@ -53,38 +54,6 @@ pub struct GetSignerResponse {
5354
pub blocks_signed: u64,
5455
}
5556

56-
pub enum GetSignerErrors {
57-
NotAvailableYet(crate::chainstate::coordinator::Error),
58-
Other(String),
59-
}
60-
61-
impl GetSignerErrors {
62-
pub const NOT_AVAILABLE_ERR_TYPE: &'static str = "not_available_try_again";
63-
pub const OTHER_ERR_TYPE: &'static str = "other";
64-
65-
pub fn error_type_string(&self) -> &'static str {
66-
match self {
67-
Self::NotAvailableYet(_) => Self::NOT_AVAILABLE_ERR_TYPE,
68-
Self::Other(_) => Self::OTHER_ERR_TYPE,
69-
}
70-
}
71-
}
72-
73-
impl From<&str> for GetSignerErrors {
74-
fn from(value: &str) -> Self {
75-
GetSignerErrors::Other(value.into())
76-
}
77-
}
78-
79-
impl std::fmt::Display for GetSignerErrors {
80-
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
81-
match self {
82-
GetSignerErrors::NotAvailableYet(e) => write!(f, "Could not read reward set. Prepare phase may not have started for this cycle yet. Err = {e:?}"),
83-
GetSignerErrors::Other(msg) => write!(f, "{msg}")
84-
}
85-
}
86-
}
87-
8857
/// Decode the HTTP request
8958
impl HttpRequest for GetSignerRequestHandler {
9059
fn verb(&self) -> &'static str {
@@ -128,12 +97,12 @@ impl HttpRequest for GetSignerRequestHandler {
12897
));
12998
};
13099

131-
let cycle_num = u64::from_str_radix(cycle_num_str.into(), 10)
132-
.map_err(|e| Error::DecodeError(format!("Failed to parse cycle number: {e}")))?;
133-
134100
let signer_pubkey = Secp256k1PublicKey::from_hex(signer_pubkey_str.into())
135101
.map_err(|e| Error::DecodeError(format!("Failed to signer public key: {e}")))?;
136102

103+
let cycle_num = u64::from_str_radix(cycle_num_str.into(), 10)
104+
.map_err(|e| Error::DecodeError(format!("Failed to parse cycle number: {e}")))?;
105+
137106
self.signer_pubkey = Some(signer_pubkey);
138107
self.reward_cycle = Some(cycle_num);
139108

@@ -152,16 +121,9 @@ impl RPCRequestHandler for GetSignerRequestHandler {
152121
fn try_handle_request(
153122
&mut self,
154123
preamble: HttpRequestPreamble,
155-
contents: HttpRequestContents,
124+
_contents: HttpRequestContents,
156125
node: &mut StacksNodeState,
157126
) -> Result<(HttpResponsePreamble, HttpResponseContents), NetError> {
158-
let tip = match node.load_stacks_chain_tip(&preamble, &contents) {
159-
Ok(tip) => tip,
160-
Err(error_resp) => {
161-
return error_resp.try_into_contents().map_err(NetError::from);
162-
}
163-
};
164-
165127
let signer_pubkey = self
166128
.signer_pubkey
167129
.take()
@@ -172,13 +134,12 @@ impl RPCRequestHandler for GetSignerRequestHandler {
172134
.take()
173135
.ok_or(NetError::SendError("Missing `reward_cycle`".into()))?;
174136

175-
let result = node.with_node_state(|_network, _sortdb, _chainstate, _mempool, _rpc_args| {
176-
// TODO
177-
if true {
178-
Ok(0u64)
179-
} else {
180-
Err("Something went wrong")
181-
}
137+
let result = node.with_node_state(|_network, _sortdb, chainstate, _mempool, _rpc_args| {
138+
NakamotoChainState::get_signer_block_count(
139+
&chainstate.index_conn(),
140+
&signer_pubkey,
141+
reward_cycle,
142+
)
182143
});
183144

184145
let response = match result {
@@ -238,31 +199,3 @@ impl StacksHttpResponse {
238199
Ok(response)
239200
}
240201
}
241-
242-
#[cfg(test)]
243-
mod test {
244-
use super::GetSignerErrors;
245-
246-
#[test]
247-
// Test the formatting and error type strings of GetSignerErrors
248-
fn get_signer_errors() {
249-
let not_available_err = GetSignerErrors::NotAvailableYet(
250-
crate::chainstate::coordinator::Error::PoXNotProcessedYet,
251-
);
252-
let other_err = GetSignerErrors::Other("foo".into());
253-
254-
assert_eq!(
255-
not_available_err.error_type_string(),
256-
GetSignerErrors::NOT_AVAILABLE_ERR_TYPE
257-
);
258-
assert_eq!(
259-
other_err.error_type_string(),
260-
GetSignerErrors::OTHER_ERR_TYPE
261-
);
262-
263-
assert!(not_available_err
264-
.to_string()
265-
.starts_with("Could not read reward set"));
266-
assert_eq!(other_err.to_string(), "foo".to_string());
267-
}
268-
}

0 commit comments

Comments
 (0)