Skip to content

Commit bfb45b9

Browse files
0.1.10
1 parent ea5948f commit bfb45b9

File tree

12 files changed

+636
-279
lines changed

12 files changed

+636
-279
lines changed

README.md

Lines changed: 79 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -177,7 +177,15 @@ Shuts down the pool and disconnects all peers.
177177

178178
##### `getConnectedPeers(): Promise<string[]>`
179179

180-
Returns a list of connected peer IDs.
180+
Gets the list of currently connected peer IDs.
181+
182+
**Returns:** Array of peer ID strings (format: "host:port")
183+
184+
##### `getPeakHeight(): Promise<number | null>`
185+
186+
Gets the highest blockchain peak height seen across all connected peers.
187+
188+
**Returns:** The highest peak height as a number, or null if no peaks have been received yet
181189

182190
##### `on(event, callback): void`
183191

@@ -232,6 +240,12 @@ Fired when a peer is removed from the pool or disconnects.
232240

233241
**Callback:** `(event: PeerDisconnectedEvent) => void`
234242

243+
#### `newPeakHeight`
244+
245+
Fired when a new highest blockchain peak is discovered.
246+
247+
**Callback:** `(event: NewPeakHeightEvent) => void`
248+
235249
### Event Data Types
236250

237251
#### `BlockReceivedEvent`
@@ -273,6 +287,16 @@ interface PeerDisconnectedEvent {
273287
}
274288
```
275289

290+
#### `NewPeakHeightEvent`
291+
292+
```typescript
293+
interface NewPeakHeightEvent {
294+
oldPeak: number | null // Previous highest peak (null if first peak)
295+
newPeak: number // New highest peak height
296+
peerId: string // Peer that discovered this peak
297+
}
298+
```
299+
276300
#### `CoinRecord`
277301

278302
```typescript
@@ -319,6 +343,13 @@ async function main() {
319343
console.log(`Peer disconnected from pool: ${event.peerId}`)
320344
})
321345

346+
pool.on('newPeakHeight', (event) => {
347+
console.log(`New blockchain peak detected!`)
348+
console.log(` Previous: ${event.oldPeak || 'None'}`)
349+
console.log(` New: ${event.newPeak}`)
350+
console.log(` Discovered by: ${event.peerId}`)
351+
})
352+
322353
// Add multiple peers
323354
await pool.addPeer('node1.chia.net', 8444, 'mainnet')
324355
await pool.addPeer('node2.chia.net', 8444, 'mainnet')
@@ -396,6 +427,46 @@ try {
396427
}
397428
```
398429

430+
#### Peak Height Tracking
431+
432+
```javascript
433+
// Monitor blockchain sync progress
434+
const pool = new ChiaPeerPool()
435+
436+
// Track peak changes
437+
let currentPeak = null
438+
pool.on('newPeakHeight', (event) => {
439+
currentPeak = event.newPeak
440+
const progress = event.oldPeak
441+
? `+${event.newPeak - event.oldPeak} blocks`
442+
: 'Initial peak'
443+
console.log(`Peak update: ${event.newPeak} (${progress})`)
444+
})
445+
446+
// Add peers
447+
await pool.addPeer('node1.chia.net', 8444, 'mainnet')
448+
await pool.addPeer('node2.chia.net', 8444, 'mainnet')
449+
450+
// Check current peak
451+
const peak = await pool.getPeakHeight()
452+
console.log(`Current highest peak: ${peak || 'None yet'}`)
453+
454+
// Fetch some blocks to trigger peak updates
455+
await pool.getBlockByHeight(5000000)
456+
await pool.getBlockByHeight(5100000)
457+
await pool.getBlockByHeight(5200000)
458+
459+
// Monitor sync status
460+
setInterval(async () => {
461+
const peak = await pool.getPeakHeight()
462+
if (peak) {
463+
const estimatedCurrent = 5200000 + Math.floor((Date.now() / 1000 - 1700000000) / 18.75)
464+
const syncPercentage = (peak / estimatedCurrent * 100).toFixed(2)
465+
console.log(`Sync status: ${syncPercentage}% (peak: ${peak})`)
466+
}
467+
}, 60000) // Check every minute
468+
```
469+
399470
### When to Use ChiaPeerPool vs ChiaBlockListener
400471

401472
- **Use ChiaPeerPool when:**
@@ -421,6 +492,7 @@ import {
421492
BlockReceivedEvent,
422493
PeerConnectedEvent,
423494
PeerDisconnectedEvent,
495+
NewPeakHeightEvent,
424496
CoinRecord,
425497
CoinSpend,
426498
initTracing,
@@ -490,13 +562,19 @@ pool.on('peerConnected', (event: PeerConnectedEvent) => {
490562
console.log(`Pool peer connected: ${event.peerId}`)
491563
})
492564

565+
pool.on('newPeakHeight', (event: NewPeakHeightEvent) => {
566+
console.log(`New peak: ${event.oldPeak} → ${event.newPeak}`)
567+
})
568+
493569
// Async/await with proper typing
494570
async function fetchHistoricalData() {
495571
const block: BlockReceivedEvent = await pool.getBlockByHeight(5000000)
496572
const peers: string[] = await pool.getConnectedPeers()
573+
const peak: number | null = await pool.getPeakHeight()
497574

498575
console.log(`Block ${block.height} has ${block.coinSpends.length} spends`)
499576
console.log(`Pool has ${peers.length} active peers`)
577+
console.log(`Current peak: ${peak || 'No peak yet'}`)
500578
}
501579
```
502580

crate/chia-generator-parser/src/parser.rs

Lines changed: 52 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,6 @@
11
use crate::{
22
error::{GeneratorParserError, Result},
3-
types::{
4-
BlockHeightInfo, CoinInfo, CoinSpendInfo, GeneratorAnalysis, GeneratorBlockInfo,
5-
ParsedBlock, ParsedGenerator,
6-
},
3+
types::{BlockHeightInfo, CoinInfo, CoinSpendInfo, GeneratorBlockInfo, ParsedBlock},
74
};
85
use chia_bls::Signature;
96
use chia_consensus::{
@@ -14,7 +11,7 @@ use chia_consensus::{
1411
run_block_generator::{run_block_generator2, setup_generator_args},
1512
validation_error::{atom, first, next, rest, ErrorCode},
1613
};
17-
use chia_protocol::{Bytes32, FullBlock};
14+
use chia_protocol::FullBlock;
1815
use chia_traits::streamable::Streamable;
1916
use clvm_utils::tree_hash;
2017
use clvmr::{
@@ -63,7 +60,7 @@ impl BlockParser {
6360
.map(|g| g.len() as u32);
6461

6562
// Extract generator info
66-
let generator_info = block
63+
let _generator_info = block
6764
.transactions_generator
6865
.as_ref()
6966
.map(|gen| GeneratorBlockInfo {
@@ -101,7 +98,6 @@ impl BlockParser {
10198
coin_creations,
10299
has_transactions_generator,
103100
generator_size,
104-
generator_info,
105101
})
106102
}
107103

@@ -373,15 +369,15 @@ impl BlockParser {
373369
// Get created coins from conditions
374370
let created_coins = self.extract_created_coins(spend_index, spend_bundle_conditions);
375371

376-
Some(CoinSpendInfo {
377-
coin: coin_info,
378-
puzzle_reveal,
379-
solution: solution_bytes,
380-
real_data: true,
381-
parsing_method: "clvm_execution".to_string(),
382-
offset: 0,
372+
Some(CoinSpendInfo::new(
373+
coin_info,
374+
hex::encode(puzzle_reveal),
375+
hex::encode(solution_bytes),
376+
true,
377+
"From transaction generator".to_string(),
378+
0,
383379
created_coins,
384-
})
380+
))
385381
}
386382

387383
/// Extract parent coin info from a coin spend node
@@ -464,42 +460,62 @@ impl BlockParser {
464460
})
465461
}
466462

463+
/*
467464
/// Parse generator from hex string
468465
pub fn parse_generator_from_hex(&self, generator_hex: &str) -> Result<ParsedGenerator> {
469466
let generator_bytes =
470-
hex::decode(generator_hex).map_err(|e| GeneratorParserError::HexDecodingError(e))?;
467+
hex::decode(generator_hex).map_err(|e| ParseError::HexDecodingError(e))?;
471468
self.parse_generator_from_bytes(&generator_bytes)
472469
}
473470
474471
/// Parse generator from bytes
475472
pub fn parse_generator_from_bytes(&self, generator_bytes: &[u8]) -> Result<ParsedGenerator> {
476-
let analysis = self.analyze_generator(generator_bytes)?;
477-
473+
// Create a dummy GeneratorBlockInfo for now
478474
Ok(ParsedGenerator {
479-
block_info: GeneratorBlockInfo {
480-
prev_header_hash: Bytes32::default(),
481-
transactions_generator: Some(generator_bytes.to_vec()),
482-
transactions_generator_ref_list: Vec::new(),
483-
},
475+
block_info: GeneratorBlockInfo::new(
476+
[0u8; 32].into(),
477+
Some(generator_bytes.to_vec()),
478+
vec![],
479+
),
484480
generator_hex: Some(hex::encode(generator_bytes)),
485-
analysis,
481+
analysis: self.analyze_generator(generator_bytes)?,
486482
})
487483
}
488484
489485
/// Analyze generator bytecode
490486
pub fn analyze_generator(&self, generator_bytes: &[u8]) -> Result<GeneratorAnalysis> {
491487
let size_bytes = generator_bytes.len();
492-
let is_empty = size_bytes == 0;
493-
494-
// Check for CLVM patterns
495-
let contains_clvm_patterns = generator_bytes
496-
.windows(2)
497-
.any(|w| matches!(w, [0xff, _] | [_, 0xff]));
498-
499-
// Check for coin patterns (CREATE_COIN opcode)
500-
let contains_coin_patterns = generator_bytes.windows(1).any(|w| w[0] == 0x33);
488+
let is_empty = generator_bytes.is_empty();
489+
490+
// Check for common CLVM patterns
491+
let contains_clvm_patterns = generator_bytes.windows(2).any(|w| {
492+
w == [0x01, 0x00] || // pair
493+
w == [0x02, 0x00] || // cons
494+
w == [0x03, 0x00] || // first
495+
w == [0x04, 0x00] // rest
496+
});
497+
498+
// Check for coin patterns (32-byte sequences)
499+
let contains_coin_patterns = generator_bytes.len() >= 32;
500+
501+
// Calculate simple entropy
502+
let mut byte_counts = [0u64; 256];
503+
for &byte in generator_bytes {
504+
byte_counts[byte as usize] += 1;
505+
}
501506
502-
let entropy = self.calculate_entropy(generator_bytes);
507+
let total = generator_bytes.len() as f64;
508+
let entropy = if total > 0.0 {
509+
byte_counts.iter()
510+
.filter(|&&count| count > 0)
511+
.map(|&count| {
512+
let p = count as f64 / total;
513+
-p * p.log2()
514+
})
515+
.sum()
516+
} else {
517+
0.0
518+
};
503519
504520
Ok(GeneratorAnalysis {
505521
size_bytes,
@@ -509,8 +525,10 @@ impl BlockParser {
509525
entropy,
510526
})
511527
}
528+
*/
512529

513530
/// Calculate Shannon entropy of data
531+
#[allow(dead_code)]
514532
fn calculate_entropy(&self, data: &[u8]) -> f64 {
515533
if data.is_empty() {
516534
return 0.0;

0 commit comments

Comments
 (0)