Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: add various new nakamoto block fields to /new_block ingestion and StacksPayload #659

Merged
merged 3 commits into from
Oct 22, 2024
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
use crate::scan::stacks::{Record, RecordKind};
use crate::service::tests::helpers::mock_bitcoin_rpc::TipData;
use chainhook_sdk::indexer::bitcoin::NewBitcoinBlock;
use chainhook_sdk::indexer::stacks::{NewBlock, NewEvent, NewTransaction};
use chainhook_sdk::indexer::stacks::{NewBlock, NewEvent, NewTransaction, RewardSet, RewardSetSigner};
use chainhook_sdk::types::{
FTBurnEventData, FTMintEventData, FTTransferEventData, NFTBurnEventData, NFTMintEventData,
NFTTransferEventData, STXBurnEventData, STXLockEventData, STXMintEventData,
Expand Down Expand Up @@ -260,6 +260,26 @@ pub fn create_stacks_new_block(
transactions: (0..4).map(create_stacks_new_transaction).collect(),
events,
matured_miner_rewards: vec![],
block_time: Some(12345),
signer_bitvec: Some("000800000001ff".to_owned()),
signer_signature: Some(vec!["1234".to_owned(), "2345".to_owned()]),
cycle_number: Some(1),
reward_set: Some(RewardSet {
pox_ustx_threshold: "50000".to_owned(),
rewarded_addresses: vec![],
signers: Some(vec![
RewardSetSigner {
signing_key: "0123".to_owned(),
weight: 123,
stacked_amt: "555555".to_owned(),
},
RewardSetSigner {
signing_key: "2345".to_owned(),
weight: 234,
stacked_amt: "6677777".to_owned(),
},
]),
}),
}
}

Expand Down
53 changes: 53 additions & 0 deletions components/chainhook-sdk/src/indexer/stacks/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,36 @@ pub struct NewBlock {
pub transactions: Vec<NewTransaction>,
pub events: Vec<NewEvent>,
pub matured_miner_rewards: Vec<MaturedMinerReward>,

#[serde(skip_serializing_if = "Option::is_none")]
pub block_time: Option<u64>,

#[serde(skip_serializing_if = "Option::is_none")]
pub signer_bitvec: Option<String>,

#[serde(skip_serializing_if = "Option::is_none")]
pub signer_signature: Option<Vec<String>>,

#[serde(skip_serializing_if = "Option::is_none")]
pub cycle_number: Option<u64>,

#[serde(skip_serializing_if = "Option::is_none")]
pub reward_set: Option<RewardSet>,
Comment on lines +39 to +52
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

stacks-core isn't very consistent with some of these fields being optional (undefined) vs nullable. So goal here is to just support either case during deserialization.

}

#[derive(Deserialize, Serialize)]
pub struct RewardSet {
pub pox_ustx_threshold: String,
pub rewarded_addresses: Vec<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub signers: Option<Vec<RewardSetSigner>>,
}

#[derive(Deserialize, Serialize)]
pub struct RewardSetSigner {
pub signing_key: String,
pub weight: u32,
pub stacked_amt: String,
}

#[derive(Deserialize, Serialize, Default, Clone)]
Expand Down Expand Up @@ -432,6 +462,29 @@ pub fn standardize_stacks_block(
pox_cycle_length: pox_cycle_length.try_into().unwrap(),
confirm_microblock_identifier,
stacks_block_hash: block.block_hash.clone(),

block_time: block.block_time,
// TODO: decode `signer_bitvec` into an easy to use bit string representation (e.g. "01010101")
signer_bitvec: block.signer_bitvec.clone(),
Comment on lines +467 to +468
Copy link
Member Author

@zone117x zone117x Oct 22, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@rafaelcr we get these from /new_block in consesus-serialize format, e.g. 0x000800000001ff. Is there existing code I can call to decode this? We should deliver it in the payloads in a more typical (and easier to use) bitfield format (a string of 1 and/or 0).

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, I believe so, it's probably included in the update we did to the stacks-codec here hirosystems/clarinet#1524

signer_signature: block.signer_signature.clone(),

cycle_number: block.cycle_number,
reward_set: block.reward_set.as_ref().and_then(|r| {
Some(StacksBlockMetadataRewardSet {
pox_ustx_threshold: r.pox_ustx_threshold.clone(),
rewarded_addresses: r.rewarded_addresses.clone(),
signers: r.signers.as_ref().map(|signers| {
signers
.into_iter()
.map(|signer| StacksBlockMetadataRewardSetSigner {
signing_key: signer.signing_key.clone(),
weight: signer.weight,
stacked_amt: signer.stacked_amt.clone(),
})
.collect()
}),
})
}),
},
transactions,
};
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use super::BlockEvent;
use chainhook_types::{
BlockIdentifier, StacksBlockData, StacksBlockMetadata, StacksTransactionData,
BlockIdentifier, StacksBlockData, StacksBlockMetadata, StacksBlockMetadataRewardSet, StacksBlockMetadataRewardSetSigner, StacksTransactionData
};

pub fn generate_test_stacks_block(
Expand Down Expand Up @@ -72,6 +72,26 @@ pub fn generate_test_stacks_block(
pox_cycle_length: 100,
confirm_microblock_identifier,
stacks_block_hash: String::new(),
block_time: Some(12345),
signer_bitvec: Some("1010101010101".to_owned()),
signer_signature: Some(vec!["1234".to_owned(), "2345".to_owned()]),
cycle_number: Some(1),
reward_set: Some(StacksBlockMetadataRewardSet {
pox_ustx_threshold: "50000".to_owned(),
rewarded_addresses: vec![],
signers: Some(vec![
StacksBlockMetadataRewardSetSigner {
signing_key: "0123".to_owned(),
weight: 123,
stacked_amt: "555555".to_owned(),
},
StacksBlockMetadataRewardSetSigner {
signing_key: "2345".to_owned(),
weight: 234,
stacked_amt: "6677777".to_owned(),
},
]),
}),
},
})
}
Expand Down
17 changes: 17 additions & 0 deletions components/chainhook-types-js/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -694,6 +694,23 @@ export interface StacksBlockMetadata {
* @memberof StacksBlockMetadata
*/
pox_cycle_length: number;

block_time?: number | null;
signer_bitvec?: string | null;
signer_signature?: string[] | null;
cycle_number?: number | null;
reward_set?: {
pox_ustx_threshold: string;
rewarded_addresses: string[];
signers?: {
signing_key: string;
weight: number;
stacked_amt: string;
}[] | null;
start_cycle_state: {
missed_reward_slots: [];
};
} | null;
}

/**
Expand Down
23 changes: 23 additions & 0 deletions components/chainhook-types-rs/src/rosetta.rs
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,29 @@ pub struct StacksBlockMetadata {
pub pox_cycle_length: u32,
pub confirm_microblock_identifier: Option<BlockIdentifier>,
pub stacks_block_hash: String,

// Fields included in Nakamoto block headers
pub block_time: Option<u64>,
pub signer_bitvec: Option<String>,
pub signer_signature: Option<Vec<String>>,

// Available starting in epoch3, only included in blocks where the pox cycle rewards are first calculated
pub cycle_number: Option<u64>,
pub reward_set: Option<StacksBlockMetadataRewardSet>,
}

#[derive(Debug, Clone, PartialEq, Deserialize, Serialize)]
pub struct StacksBlockMetadataRewardSet {
pub pox_ustx_threshold: String,
pub rewarded_addresses: Vec<String>,
pub signers: Option<Vec<StacksBlockMetadataRewardSetSigner>>,
}

#[derive(Debug, Clone, PartialEq, Deserialize, Serialize)]
pub struct StacksBlockMetadataRewardSetSigner {
pub signing_key: String,
pub weight: u32,
pub stacked_amt: String,
Comment on lines +117 to +139
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm simply re-using the same structure as the /new_block event for this payload so for now it looks like code duplication, however, it gives us room to restructure/rename/re-type these as needed.

}

/// BitcoinBlock contain an array of Transactions that occurred at a particular
Expand Down
23 changes: 23 additions & 0 deletions components/client/typescript/src/schemas/stacks/payload.ts
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,29 @@ export const StacksEventMetadataSchema = Type.Object({
pox_cycle_length: Type.Integer(),
pox_cycle_position: Type.Integer(),
stacks_block_hash: Type.String(),

// Fields included in Nakamoto block headers
block_time: Nullable(Type.Integer()),
signer_bitvec: Nullable(Type.String()),
signer_signature: Nullable(Type.Array(Type.String())),

// Available starting in epoch3, only included in blocks where the pox cycle rewards are first calculated
cycle_number: Nullable(Type.Integer()),
reward_set: Nullable(
Type.Object({
pox_ustx_threshold: Type.String(),
rewarded_addresses: Type.Array(Type.String()),
signers: Nullable(
Type.Array(
Type.Object({
signing_key: Type.String(),
weight: Type.Integer(),
stacked_amt: Type.String(),
})
)
),
})
),
});
export type StacksEventMetadata = Static<typeof StacksEventMetadataSchema>;

Expand Down
Loading