Skip to content

Commit 2efe18b

Browse files
Merge branch 'develop' into feat/clarity-cli-serialized-output
2 parents f4ce327 + 02ecae6 commit 2efe18b

File tree

22 files changed

+428
-431
lines changed

22 files changed

+428
-431
lines changed

Cargo.lock

Lines changed: 0 additions & 7 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,6 @@ name = "block_limits"
4343
harness = false
4444

4545
[dependencies]
46-
tini = "0.2"
4746
rand = "=0.7.2"
4847
rand_chacha = "=0.2.2"
4948
serde = "1"

docs/event-dispatcher.md

Lines changed: 68 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,9 @@ These events are sent to the configured endpoint at two URLs:
2727
This payload includes data related to a newly processed block,
2828
and any events emitted from Stacks transactions during the block.
2929

30+
If the transaction originally comes from the parent microblock stream
31+
preceding this block, the microblock related fields will be filled in.
32+
3033
Example:
3134

3235
```json
@@ -58,15 +61,21 @@ Example:
5861
"raw_tx": "0x808000000004008bc5147525b8f477f0bc4522a88c8339b2494db50000000000000002000000000000000001015814daf929d8700af344987681f44e913890a12e38550abe8e40f149ef5269f40f4008083a0f2e0ddf65dcd05ecfc151c7ff8a5308ad04c77c0e87b5aeadad31010200000000040000000000000000000000000000000000000000000000000000000000000000",
5962
"status": "success",
6063
"tx_index": 0,
61-
"txid": "0x3e04ada5426332bfef446ba0a06d124aace4ade5c11840f541bf88e2e919faf6"
64+
"txid": "0x3e04ada5426332bfef446ba0a06d124aace4ade5c11840f541bf88e2e919faf6",
65+
"microblock_sequence": "None",
66+
"microblock_hash": "None",
67+
"microblock_parent_hash": "None"
6268
},
6369
{
6470
"contract_abi": null,
6571
"raw_result": "0x03",
6672
"raw_tx": "0x80800000000400f942874ce525e87f21bbe8c121b12fac831d02f4000000000000000000000000000003e800006ae29867aec4b0e4f776bebdcea7f6d9a24eeff370c8c739defadfcbb52659b30736ad4af021e8fb741520a6c65da419fdec01989fdf0032fc1838f427a9a36102010000000000051ac2d519faccba2e435f3272ff042b89435fd160ff00000000000003e800000000000000000000000000000000000000000000000000000000000000000000",
6773
"status": "success",
6874
"tx_index": 1,
69-
"txid": "0x738e4d44636023efa08374033428e44eca490582bd39a6e61f3b6cf749b4214c"
75+
"txid": "0x738e4d44636023efa08374033428e44eca490582bd39a6e61f3b6cf749b4214c",
76+
"microblock_sequence": "3",
77+
"microblock_hash": "0x9304fcbcc6daf5ac3f264522e0df50eddb5be85df6ee8a9fc2384c54274daaac",
78+
"microblock_parent_hash": "0x4893ab44636023efa08374033428e44eca490582bd39a6e61f3b6cf749b474bd"
7079
}
7180
],
7281
"matured_miner_rewards": [
@@ -116,6 +125,63 @@ Example:
116125
PoX commitments during this block. These addresses may not actually receive rewards during
117126
this block if the block is faster than miners have an opportunity to commit.
118127

128+
### `POST /new_microblocks`
129+
130+
This payload includes data related to one or more microblocks that are either emmitted by the
131+
node itself, or received through the network.
132+
133+
Example:
134+
135+
```json
136+
{
137+
"parent_index_block_hash": "0x999b38d44d6af72703a476dde4cea683ec965346d9e9a7ded2d773fb4f257a3b",
138+
"events": [
139+
{
140+
"event_index": 1,
141+
"committed": true,
142+
"stx_transfer_event": {
143+
"amount": "1000",
144+
"recipient": "ST31DA6FTSJX2WGTZ69SFY11BH51NZMB0ZZ239N96",
145+
"sender": "ST3WM51TCWMJYGZS1QFMC28DH5YP86782YGR113C1"
146+
},
147+
"txid": "0x738e4d44636023efa08374033428e44eca490582bd39a6e61f3b6cf749b4214c",
148+
"type": "stx_transfer_event"
149+
}
150+
],
151+
"transactions": [
152+
{
153+
"contract_abi": null,
154+
"raw_result": "0x03",
155+
"raw_tx": "0x808000000004008bc5147525b8f477f0bc4522a88c8339b2494db50000000000000002000000000000000001015814daf929d8700af344987681f44e913890a12e38550abe8e40f149ef5269f40f4008083a0f2e0ddf65dcd05ecfc151c7ff8a5308ad04c77c0e87b5aeadad31010200000000040000000000000000000000000000000000000000000000000000000000000000",
156+
"status": "success",
157+
"tx_index": 0,
158+
"txid": "0x3e04ada5426332bfef446ba0a06d124aace4ade5c11840f541bf88e2e919faf6",
159+
"microblock_sequence": "3",
160+
"microblock_hash": "0x9304fcbcc6daf5ac3f264522e0df50eddb5be85df6ee8a9fc2384c54274daaac",
161+
"microblock_parent_hash": "0x4893ab44636023efa08374033428e44eca490582bd39a6e61f3b6cf749b474bd"
162+
},
163+
{
164+
"contract_abi": null,
165+
"raw_result": "0x03",
166+
"raw_tx": "0x80800000000400f942874ce525e87f21bbe8c121b12fac831d02f4000000000000000000000000000003e800006ae29867aec4b0e4f776bebdcea7f6d9a24eeff370c8c739defadfcbb52659b30736ad4af021e8fb741520a6c65da419fdec01989fdf0032fc1838f427a9a36102010000000000051ac2d519faccba2e435f3272ff042b89435fd160ff00000000000003e800000000000000000000000000000000000000000000000000000000000000000000",
167+
"status": "success",
168+
"tx_index": 1,
169+
"txid": "0x738e4d44636023efa08374033428e44eca490582bd39a6e61f3b6cf749b4214c",
170+
"microblock_sequence": "4",
171+
"microblock_hash": "0xfcd4fc34c6daf5ac3f264522e0df50eddb5be85df6ee8a9fc2384c5427459e43",
172+
"microblock_parent_hash": "0x9304fcbcc6daf5ac3f264522e0df50eddb5be85df6ee8a9fc2384c54274daaac"
173+
}
174+
],
175+
"burn_block_hash": "0x4eaabcd105865e471f697eff5dd5bd85d47ecb5a26a3379d74fae0ae87c40904",
176+
"burn_block_height": 331,
177+
"burn_block_timestamp": 1651301734
178+
}
179+
```
180+
181+
* `burn_block_{}` are the stats related to the burn block that is associated with the stacks
182+
block that precedes this microblock stream.
183+
* Each transaction json object includes information about the microblock the transaction was packaged into.
184+
119185
### `POST /new_mempool_tx`
120186

121187
This payload includes raw transactions newly received in the

src/burnchains/bitcoin/indexer.rs

Lines changed: 0 additions & 224 deletions
Original file line numberDiff line numberDiff line change
@@ -25,8 +25,6 @@ use std::path::PathBuf;
2525
use std::time;
2626
use std::time::Duration;
2727

28-
use tini::Ini;
29-
3028
use burnchains::bitcoin::blocks::BitcoinHeaderIPC;
3129
use burnchains::bitcoin::messages::BitcoinMessageHandler;
3230
use burnchains::bitcoin::spv::*;
@@ -137,165 +135,6 @@ impl BitcoinIndexerConfig {
137135
magic_bytes: BLOCKSTACK_MAGIC_MAINNET.clone(),
138136
}
139137
}
140-
141-
pub fn to_file(&self, path: &String) -> Result<(), btc_error> {
142-
let username = self.username.clone().unwrap_or("".to_string());
143-
let password = self.password.clone().unwrap_or("".to_string());
144-
145-
let conf = Ini::new()
146-
.section("bitcoin")
147-
.item("server", self.peer_host.as_str())
148-
.item("p2p_port", format!("{}", self.peer_port).as_str())
149-
.item("rpc_port", format!("{}", self.rpc_port).as_str())
150-
.item("rpc_ssl", format!("{}", self.rpc_ssl).as_str())
151-
.item("username", username.as_str())
152-
.item("password", password.as_str())
153-
.item("timeout", format!("{}", self.timeout).as_str())
154-
.item("spv_path", self.spv_headers_path.as_str())
155-
.item("first_block", format!("{}", self.first_block).as_str())
156-
.section("blockstack")
157-
.item(
158-
"network_id",
159-
format!(
160-
"{}{}",
161-
self.magic_bytes.as_bytes()[0] as char,
162-
self.magic_bytes.as_bytes()[1] as char
163-
)
164-
.as_str(),
165-
);
166-
167-
conf.to_file(&path).map_err(|e| btc_error::Io(e))
168-
}
169-
170-
pub fn from_file(path: &String) -> Result<BitcoinIndexerConfig, btc_error> {
171-
let conf_path = PathBuf::from(path);
172-
if !conf_path.is_file() {
173-
return Err(btc_error::ConfigError(
174-
"Failed to load BitcoinIndexerConfig file: No such file or directory".to_string(),
175-
));
176-
}
177-
178-
let default_config = BitcoinIndexerConfig::default(0);
179-
180-
match Ini::from_file(path) {
181-
Ok(ini_file) => {
182-
// [bitcoin]
183-
let peer_host = ini_file
184-
.get("bitcoin", "server")
185-
.unwrap_or(default_config.peer_host);
186-
187-
let peer_port = ini_file
188-
.get("bitcoin", "p2p_port")
189-
.unwrap_or(format!("{}", default_config.peer_port))
190-
.trim()
191-
.parse()
192-
.map_err(|_e| {
193-
btc_error::ConfigError("Invalid bitcoin:p2p_port value".to_string())
194-
})?;
195-
196-
if peer_port <= 1024 || peer_port == 65535 {
197-
return Err(btc_error::ConfigError("Invalid p2p_port".to_string()));
198-
}
199-
200-
let rpc_port = ini_file
201-
.get("bitcoin", "rpc_port")
202-
.unwrap_or(format!("{}", default_config.rpc_port))
203-
.trim()
204-
.parse()
205-
.map_err(|_e| {
206-
btc_error::ConfigError("Invalid bitcoin:port value".to_string())
207-
})?;
208-
209-
if rpc_port <= 1024 || rpc_port == 65535 {
210-
return Err(btc_error::ConfigError("Invalid rpc_port".to_string()));
211-
}
212-
213-
let username: Option<String> =
214-
ini_file.get("bitcoin", "username").and_then(|s| Some(s));
215-
let password: Option<String> =
216-
ini_file.get("bitcoin", "password").and_then(|s| Some(s));
217-
218-
let timeout = ini_file
219-
.get("bitcoin", "timeout")
220-
.unwrap_or(format!("{}", default_config.timeout))
221-
.trim()
222-
.parse()
223-
.map_err(|_e| {
224-
btc_error::ConfigError("Invalid bitcoin:timeout value".to_string())
225-
})?;
226-
227-
let spv_headers_path_cfg = ini_file
228-
.get("bitcoin", "spv_path")
229-
.unwrap_or(default_config.spv_headers_path);
230-
231-
let spv_headers_path =
232-
if path::is_separator(spv_headers_path_cfg.chars().next().ok_or(
233-
btc_error::ConfigError("Invalid bitcoin:spv_path value".to_string()),
234-
)?) {
235-
// absolute
236-
spv_headers_path_cfg
237-
} else {
238-
// relative to config file
239-
let mut p = PathBuf::from(path);
240-
p.pop();
241-
let s = p.join(&spv_headers_path_cfg);
242-
s.to_str().unwrap().to_string()
243-
};
244-
245-
let first_block = ini_file
246-
.get("bitcoin", "first_block")
247-
.unwrap_or(format!("{}", 0))
248-
.trim()
249-
.parse()
250-
.map_err(|_e| {
251-
btc_error::ConfigError("Invalid bitcoin:first_block value".to_string())
252-
})?;
253-
254-
let rpc_ssl_str = ini_file
255-
.get("bitcoin", "ssl")
256-
.unwrap_or(format!("{}", default_config.rpc_ssl));
257-
258-
let rpc_ssl = rpc_ssl_str == "1" || rpc_ssl_str == "true";
259-
260-
// [blockstack]
261-
let blockstack_magic_str =
262-
ini_file.get("blockstack", "network_id").unwrap_or(format!(
263-
"{}{}",
264-
BLOCKSTACK_MAGIC_MAINNET.as_bytes()[0] as char,
265-
BLOCKSTACK_MAGIC_MAINNET.as_bytes()[1] as char
266-
));
267-
268-
if blockstack_magic_str.len() != 2 {
269-
return Err(btc_error::ConfigError(
270-
"Invalid blockstack:network_id value: must be two bytes".to_string(),
271-
));
272-
}
273-
274-
let blockstack_magic = MagicBytes([
275-
blockstack_magic_str.as_bytes()[0] as u8,
276-
blockstack_magic_str.as_bytes()[1] as u8,
277-
]);
278-
279-
let cfg = BitcoinIndexerConfig {
280-
peer_host: peer_host,
281-
peer_port: peer_port,
282-
rpc_port: rpc_port,
283-
rpc_ssl: rpc_ssl,
284-
username: username,
285-
password: password,
286-
timeout: timeout,
287-
spv_headers_path: spv_headers_path,
288-
first_block: first_block,
289-
magic_bytes: blockstack_magic,
290-
};
291-
292-
Ok(cfg)
293-
}
294-
Err(_) => Err(btc_error::ConfigError(
295-
"Failed to parse BitcoinConfigIndexer config file".to_string(),
296-
)),
297-
}
298-
}
299138
}
300139

301140
impl BitcoinIndexerRuntime {
@@ -323,18 +162,6 @@ impl BitcoinIndexer {
323162
}
324163
}
325164

326-
pub fn from_file(
327-
network_id: BitcoinNetworkType,
328-
config_file: &String,
329-
) -> Result<BitcoinIndexer, btc_error> {
330-
let config = BitcoinIndexerConfig::from_file(config_file)?;
331-
let runtime = BitcoinIndexerRuntime::new(network_id);
332-
Ok(BitcoinIndexer {
333-
config: config,
334-
runtime: runtime,
335-
})
336-
}
337-
338165
pub fn dup(&self) -> BitcoinIndexer {
339166
BitcoinIndexer {
340167
config: self.config.clone(),
@@ -775,57 +602,6 @@ impl Drop for BitcoinIndexer {
775602
impl BurnchainIndexer for BitcoinIndexer {
776603
type P = BitcoinBlockParser;
777604

778-
/// Instantiate the Bitcoin indexer, and connect to the peer network.
779-
/// Instead, load our configuration state and sanity-check it.
780-
///
781-
/// Pass a directory (working_dir) that contains a "bitcoin.ini" file.
782-
fn init(
783-
working_dir: &String,
784-
network_name: &String,
785-
first_block_height: u64,
786-
) -> Result<BitcoinIndexer, burnchain_error> {
787-
let conf_path_str =
788-
Burnchain::get_chainstate_config_path(working_dir, &"bitcoin".to_string());
789-
790-
let network_id_opt = match network_name.as_ref() {
791-
BITCOIN_MAINNET_NAME => Some(BitcoinNetworkType::Mainnet),
792-
BITCOIN_TESTNET_NAME => Some(BitcoinNetworkType::Testnet),
793-
BITCOIN_REGTEST_NAME => Some(BitcoinNetworkType::Regtest),
794-
_ => None,
795-
};
796-
797-
if network_id_opt.is_none() {
798-
return Err(burnchain_error::Bitcoin(btc_error::ConfigError(format!(
799-
"Unrecognized network name '{}'",
800-
network_name
801-
))));
802-
}
803-
let bitcoin_network_id = network_id_opt.unwrap();
804-
805-
if !PathBuf::from(&conf_path_str).exists() {
806-
let default_config = BitcoinIndexerConfig::default(first_block_height);
807-
default_config
808-
.to_file(&conf_path_str)
809-
.map_err(burnchain_error::Bitcoin)?;
810-
}
811-
812-
let mut indexer = BitcoinIndexer::from_file(bitcoin_network_id, &conf_path_str)
813-
.map_err(burnchain_error::Bitcoin)?;
814-
815-
SpvClient::new(
816-
&indexer.config.spv_headers_path,
817-
0,
818-
None,
819-
indexer.runtime.network_id,
820-
true,
821-
false,
822-
)
823-
.map_err(burnchain_error::Bitcoin)?;
824-
825-
indexer.connect()?;
826-
Ok(indexer)
827-
}
828-
829605
/// Connect to the Bitcoin peer network.
830606
/// Use the peer host and peer port given in the config file,
831607
/// and loaded in on setup. Don't call this before init().

0 commit comments

Comments
 (0)