Skip to content

Commit f557107

Browse files
authored
Merge branch 'develop' into chore/3.1.0.0.12_develop
2 parents ae969ca + c457f41 commit f557107

File tree

296 files changed

+3568
-4540
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

296 files changed

+3568
-4540
lines changed

.cargo/config.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
[alias]
22
stacks-node = "run --package stacks-node --"
33
fmt-stacks = "fmt -- --config group_imports=StdExternalCrate,imports_granularity=Module"
4-
clippy-stacks = "clippy -p libstackerdb -p stacks-signer -p pox-locking -p clarity -p libsigner -p stacks-common --no-deps --tests --all-features -- -D warnings"
4+
clippy-stacks = "clippy -p stx-genesis -p libstackerdb -p stacks-signer -p pox-locking -p clarity -p libsigner -p stacks-common --no-deps --tests --all-features -- -D warnings"
55

66
# Uncomment to improve performance slightly, at the cost of portability
77
# * Note that native binaries may not run on CPUs that are different from the build machine

CHANGELOG.md

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,12 @@ All notable changes to this project will be documented in this file.
55
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
66
and this project adheres to the versioning scheme outlined in the [README.md](README.md).
77

8+
## Unreleased
9+
10+
### Added
11+
12+
- Added a new RPC endpoint `/v3/health` to query the node's health status. The endpoint returns a 200 status code with relevant synchronization information (including the node's current Stacks tip height, the maximum Stacks tip height among its neighbors, and the difference between these two). A user can use the `difference_from_max_peer` value to decide what is a good threshold for them before considering the node out of sync. The endpoint returns a 500 status code if the query cannot retrieve viable data.
13+
814
## [3.1.0.0.12]
915

1016
### Added
@@ -33,6 +39,7 @@ and this project adheres to the versioning scheme outlined in the [README.md](RE
3339
## [3.1.0.0.10]
3440

3541
### Added
42+
3643
- Persisted tracking of StackerDB slot versions for mining. This improves miner p2p performance.
3744

3845
## [3.1.0.0.9]

docs/rpc-endpoints.md

Lines changed: 16 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -129,7 +129,7 @@ non-canonical headers will be returned instead.
129129
### GET /v2/accounts/[Principal]
130130

131131
Get the account data for the provided principal.
132-
The principal string is either a Stacks address or a Contract identifier (e.g.,
132+
The principal string is either a Stacks address or a Contract identifier (e.g.,
133133
`SP31DA6FTSJX2WGTZ69SFY11BH51NZMB0ZW97B5P0.get-info`
134134

135135
Returns JSON data in the form:
@@ -157,7 +157,7 @@ JSON object _without_ the `balance_proof` or `nonce_proof` fields.
157157

158158
Attempt to vetch a data var from a contract. The contract is identified with [Stacks Address] and
159159
[Contract Name] in the URL path. The variable is identified with [Var Name].
160-
160+
161161
Returns JSON data in the form:
162162

163163
```json
@@ -202,7 +202,7 @@ Returns JSON data in the form:
202202
Where data is the metadata formatted as a JSON string.
203203

204204
### GET /v2/constant_val/[Stacks Address]/[Contract Name]/[Constant Name]
205-
Attempt to fetch a constant from a contract. The contract is identified with [Stacks Address] and
205+
Attempt to fetch a constant from a contract. The contract is identified with [Stacks Address] and
206206
[Contract Name] in the URL path. The constant is identified with [Constant Name].
207207

208208
Returns JSON data in the form:
@@ -219,7 +219,7 @@ Where data is the hex serialization of the constant value.
219219

220220
Attempt to fetch data from a contract data map. The contract is identified with [Stacks Address] and
221221
[Contract Name] in the URL path. The map is identified with [Map Name].
222-
222+
223223
The _key_ to lookup in the map is supplied via the POST body. This should be supplied as the hex string
224224
serialization of the key (which should be a Clarity value). Note, this is a _JSON_ string atom.
225225

@@ -539,8 +539,8 @@ data.
539539

540540
This will return 404 if the block does not exist.
541541

542-
This endpoint also accepts a querystring parameter `?tip=` which when supplied
543-
will return the block relative to the specified tip allowing the querying of
542+
This endpoint also accepts a querystring parameter `?tip=` which when supplied
543+
will return the block relative to the specified tip allowing the querying of
544544
sibling blocks (same height, different tip) too.
545545

546546
### GET /v3/tenures/[Block ID]
@@ -595,3 +595,13 @@ This feature requires enabling of transaction indexing by setting the `txindex`
595595

596596
This will return 404 if the transaction does not exist and 501 (Not Implemented) if
597597
transaction indexing is not enabled.
598+
599+
600+
### GET /v3/health
601+
602+
Determine node's synchronization health, comparing the node's current Stacks tip height
603+
with the maximum Stacks tip height observed among its connected peers.
604+
If there are no valid initial peers or data for the node to determine this information, this endpoint returns an error. The endpoint returns the node's current Stacks tip height, the maximum Stacks tip height observed among its connected peers, and the difference between these two heights.
605+
A user can utilize the `difference_from_max_peer` to establish their own criteria for determining if a node is out of sync.
606+
607+
See OpenAPI [spec](./rpc/openapi.yaml) for details.
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
{
2+
"error": "No viable bootstrap peers found, unable to determine health"
3+
}
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
{
2+
"$schema": "http://json-schema.org/draft-07/schema#",
3+
"description": "Error response when GET request to query node health fails",
4+
"title": "ServerError",
5+
"type": "object",
6+
"additionalProperties": false,
7+
"required": [
8+
"error"
9+
],
10+
"properties": {
11+
"error": {
12+
"type": "string"
13+
}
14+
}
15+
}
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
{
2+
"difference_from_max_peer": 0,
3+
"max_stacks_height_of_neighbors": 12345,
4+
"node_stacks_tip_height": 12345
5+
}
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
{
2+
"$schema": "http://json-schema.org/draft-07/schema#",
3+
"description": "GET request to query node health",
4+
"title": "GetHealthResponse",
5+
"type": "object",
6+
"additionalProperties": false,
7+
"required": [
8+
"difference_from_max_peer",
9+
"max_stacks_height_of_neighbors",
10+
"node_stacks_tip_height"
11+
],
12+
"properties": {
13+
"difference_from_max_peer": {
14+
"type": "integer",
15+
"description": "The difference in height between the node and its most advanced neighbor."
16+
},
17+
"max_stacks_height_of_neighbors": {
18+
"type": "integer",
19+
"description": "The max Stacks height of the node's most advanced neighbor."
20+
},
21+
"node_stacks_tip_height": {
22+
"type": "integer",
23+
"description": "The Stacks height of this node."
24+
}
25+
}
26+
}

docs/rpc/openapi.yaml

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -895,3 +895,36 @@ paths:
895895
description: Transaction indexing not enabled
896896
content:
897897
application/text-plain: {}
898+
899+
/v3/health:
900+
get:
901+
summary: Query the health of the node.
902+
description: |
903+
Get node health information.
904+
A node is considered healthy if its Stacks tip height matches the maximum Stacks tip height observed among its connected peers.
905+
This endpoint returns:
906+
- `difference_from_max_peer`: The difference in Stacks height between this node and its most advanced peer.
907+
- `max_stacks_height_of_neighbors`: The maximum Stacks height observed among the node's connected peers.
908+
- `node_stacks_tip_height`: The current Stacks tip height of this node.
909+
tags:
910+
- Info
911+
operationId: get_health
912+
responses:
913+
200:
914+
description: Success
915+
content:
916+
application/json:
917+
schema:
918+
$ref: ./api/core-node/get-health.schema.json
919+
example:
920+
$ref: ./api/core-node/get-health.example.json
921+
500:
922+
description: |
923+
Failed to query for health (e.g., no data or no valid peers to query from).
924+
Only the `error` field will be set in this case, providing a message about the failure.
925+
content:
926+
application/json:
927+
schema:
928+
$ref: ./api/core-node/get-health-error.schema.json
929+
example:
930+
$ref: ./api/core-node/get-health-error.example.json

libsigner/src/events.rs

Lines changed: 63 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -45,8 +45,8 @@ pub use stacks_common::consts::SIGNER_SLOTS_PER_USER;
4545
use stacks_common::types::chainstate::{
4646
BlockHeaderHash, BurnchainHeaderHash, ConsensusHash, SortitionId, StacksPublicKey,
4747
};
48-
use stacks_common::util::hash::{Hash160, Sha512Trunc256Sum};
49-
use stacks_common::util::serde_serializers::{prefix_hex, prefix_opt_hex};
48+
use stacks_common::util::hash::{hex_bytes, Hash160, Sha512Trunc256Sum};
49+
use stacks_common::util::serde_serializers::{prefix_hex, prefix_opt_hex, prefix_string_0x};
5050
use stacks_common::util::HexError;
5151
use stacks_common::versions::STACKS_NODE_VERSION;
5252
use tiny_http::{
@@ -229,6 +229,8 @@ pub enum SignerEvent<T: SignerEventTrait> {
229229
signer_sighash: Option<Sha512Trunc256Sum>,
230230
/// The block height for the newly processed stacks block
231231
block_height: u64,
232+
/// The transactions included in the block
233+
transactions: Vec<StacksTransaction>,
232234
},
233235
}
234236

@@ -577,18 +579,26 @@ impl<T: SignerEventTrait> TryFrom<BlockValidateResponse> for SignerEvent<T> {
577579
}
578580
}
579581

580-
#[derive(Debug, Deserialize)]
581-
struct BurnBlockEvent {
582+
/// Burn block JSON payload from the event receiver
583+
#[derive(Debug, Deserialize, Clone)]
584+
pub struct BurnBlockEvent {
585+
/// The hash of the burn block
582586
#[serde(with = "prefix_hex")]
583-
burn_block_hash: BurnchainHeaderHash,
584-
burn_block_height: u64,
585-
reward_recipients: Vec<serde_json::Value>,
586-
reward_slot_holders: Vec<String>,
587-
burn_amount: u64,
587+
pub burn_block_hash: BurnchainHeaderHash,
588+
/// The height of the burn block
589+
pub burn_block_height: u64,
590+
/// The reward recipients
591+
pub reward_recipients: Vec<serde_json::Value>,
592+
/// The reward slot holders
593+
pub reward_slot_holders: Vec<String>,
594+
/// The amount of burn
595+
pub burn_amount: u64,
596+
/// The consensus hash of the burn block
588597
#[serde(with = "prefix_hex")]
589-
consensus_hash: ConsensusHash,
598+
pub consensus_hash: ConsensusHash,
599+
/// The parent burn block hash
590600
#[serde(with = "prefix_hex")]
591-
parent_burn_block_hash: BurnchainHeaderHash,
601+
pub parent_burn_block_hash: BurnchainHeaderHash,
592602
}
593603

594604
impl<T: SignerEventTrait> TryFrom<BurnBlockEvent> for SignerEvent<T> {
@@ -605,6 +615,45 @@ impl<T: SignerEventTrait> TryFrom<BurnBlockEvent> for SignerEvent<T> {
605615
}
606616
}
607617

618+
/// A subset of `TransactionEventPayload`, received from the event
619+
/// dispatcher.
620+
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
621+
pub struct NewBlockTransaction {
622+
/// The raw transaction bytes. If this is a burn operation,
623+
/// this will be "00".
624+
#[serde(with = "prefix_string_0x")]
625+
raw_tx: String,
626+
}
627+
628+
impl NewBlockTransaction {
629+
pub fn get_stacks_transaction(&self) -> Result<Option<StacksTransaction>, CodecError> {
630+
if self.raw_tx == "00" {
631+
Ok(None)
632+
} else {
633+
let tx_bytes = hex_bytes(&self.raw_tx).map_err(|e| {
634+
CodecError::DeserializeError(format!("Failed to deserialize raw tx: {}", e))
635+
})?;
636+
let tx = StacksTransaction::consensus_deserialize(&mut &tx_bytes[..])?;
637+
Ok(Some(tx))
638+
}
639+
}
640+
}
641+
642+
/// "Special" deserializer to turn `{ tx_raw: "0x..." }` into `StacksTransaction`.
643+
fn deserialize_raw_tx_hex<'de, D: serde::Deserializer<'de>>(
644+
d: D,
645+
) -> Result<Vec<StacksTransaction>, D::Error> {
646+
let tx_objs: Vec<NewBlockTransaction> = serde::Deserialize::deserialize(d)?;
647+
Ok(tx_objs
648+
.iter()
649+
.map(|tx| tx.get_stacks_transaction())
650+
.collect::<Result<Vec<_>, _>>()
651+
.map_err(serde::de::Error::custom)?
652+
.into_iter()
653+
.flatten()
654+
.collect::<Vec<_>>())
655+
}
656+
608657
#[derive(Debug, Deserialize)]
609658
struct BlockEvent {
610659
#[serde(with = "prefix_hex")]
@@ -617,6 +666,8 @@ struct BlockEvent {
617666
#[serde(with = "prefix_hex")]
618667
block_hash: BlockHeaderHash,
619668
block_height: u64,
669+
#[serde(deserialize_with = "deserialize_raw_tx_hex")]
670+
transactions: Vec<StacksTransaction>,
620671
}
621672

622673
impl<T: SignerEventTrait> TryFrom<BlockEvent> for SignerEvent<T> {
@@ -628,6 +679,7 @@ impl<T: SignerEventTrait> TryFrom<BlockEvent> for SignerEvent<T> {
628679
block_id: block_event.index_block_hash,
629680
consensus_hash: block_event.consensus_hash,
630681
block_height: block_event.block_height,
682+
transactions: block_event.transactions,
631683
})
632684
}
633685
}

libsigner/src/libsigner.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -57,8 +57,8 @@ use stacks_common::versions::STACKS_SIGNER_VERSION;
5757

5858
pub use crate::error::{EventError, RPCError};
5959
pub use crate::events::{
60-
BlockProposal, BlockProposalData, EventReceiver, EventStopSignaler, SignerEvent,
61-
SignerEventReceiver, SignerEventTrait, SignerStopSignaler,
60+
BlockProposal, BlockProposalData, BurnBlockEvent, EventReceiver, EventStopSignaler,
61+
SignerEvent, SignerEventReceiver, SignerEventTrait, SignerStopSignaler,
6262
};
6363
pub use crate::runloop::{RunningSigner, Signer, SignerRunLoop};
6464
pub use crate::session::{SignerSession, StackerDBSession};

0 commit comments

Comments
 (0)