Skip to content

Commit 0fe9284

Browse files
committed
feat: testnet4 is supported with the latest rust-bitcoin
1 parent ebc9312 commit 0fe9284

File tree

12 files changed

+965
-381
lines changed

12 files changed

+965
-381
lines changed

Cargo.lock

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

Cargo.toml

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -22,14 +22,15 @@ arraydeque = "0.5.1"
2222
arrayref = "0.3.6"
2323
base64 = "0.22"
2424
bincode = "1.3.1"
25-
bitcoin = { version = "0.31", features = ["serde"] }
25+
bitcoin = { version = "0.32.5", features = [ "serde" ] }
26+
bitcoin-io = "0.1.2"
2627
clap = "2.33.3"
2728
crossbeam-channel = "0.5.0"
2829
dirs = "5.0.1"
29-
elements = { version = "0.24", features = ["serde"], optional = true }
30+
elements = { version = "0.25.1", features = ["serde"], optional = true }
3031
error-chain = "0.12.4"
3132
glob = "0.3"
32-
hex = { package = "hex-conservative", version = "0.1.1" }
33+
hex = { package = "hex-conservative", version = "0.2.1" }
3334
itertools = "0.12"
3435
lazy_static = "1.3.0"
3536
libc = "0.2.81"

src/bin/tx-fingerprint-stats.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ fn main() {
1212
use bitcoin::blockdata::script::ScriptBuf;
1313
use bitcoin::consensus::encode::deserialize;
1414
use electrs::{
15-
chain::Transaction,
15+
chain::{Transaction, TxOperations},
1616
config::Config,
1717
daemon::Daemon,
1818
metrics::Metrics,
@@ -62,7 +62,7 @@ fn main() {
6262
}
6363

6464
let tx: Transaction = deserialize(&value).expect("failed to parse Transaction");
65-
let txid = tx.txid();
65+
let txid = TxOperations::txid(&tx);
6666

6767
iter.next();
6868

src/chain.rs

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,8 @@ pub enum Network {
2929
#[cfg(not(feature = "liquid"))]
3030
Testnet,
3131
#[cfg(not(feature = "liquid"))]
32+
Testnet4,
33+
#[cfg(not(feature = "liquid"))]
3234
Regtest,
3335
#[cfg(not(feature = "liquid"))]
3436
Signet,
@@ -97,6 +99,7 @@ impl Network {
9799
return vec![
98100
"mainnet".to_string(),
99101
"testnet".to_string(),
102+
"testnet4".to_string(),
100103
"regtest".to_string(),
101104
"signet".to_string(),
102105
];
@@ -110,6 +113,27 @@ impl Network {
110113
}
111114
}
112115

116+
/// Because `rust-bitcoin` uses the `txid` function will cause a warning,
117+
/// Need to use `compute_txid` instead,
118+
/// So abstract a trait to handle the access of `txid`
119+
pub trait TxOperations {
120+
fn txid(&self) -> Txid;
121+
}
122+
123+
#[cfg(not(feature = "liquid"))]
124+
impl TxOperations for Transaction {
125+
fn txid(&self) -> Txid {
126+
self.compute_txid()
127+
}
128+
}
129+
130+
#[cfg(feature = "liquid")]
131+
impl TxOperations for Transaction {
132+
fn txid(&self) -> Txid {
133+
Transaction::txid(self)
134+
}
135+
}
136+
113137
pub fn genesis_hash(network: Network) -> BlockHash {
114138
#[cfg(not(feature = "liquid"))]
115139
return bitcoin_genesis_hash(network.into());
@@ -121,8 +145,12 @@ pub fn bitcoin_genesis_hash(network: BNetwork) -> bitcoin::BlockHash {
121145
lazy_static! {
122146
static ref BITCOIN_GENESIS: bitcoin::BlockHash =
123147
genesis_block(BNetwork::Bitcoin).block_hash();
148+
// TESTNET_GENESIS is BlockHash of testnet3
124149
static ref TESTNET_GENESIS: bitcoin::BlockHash =
125150
genesis_block(BNetwork::Testnet).block_hash();
151+
// TESTNET4_GENESIS is BlockHash of testnet4
152+
static ref TESTNET4_GENESIS: bitcoin::BlockHash =
153+
genesis_block(BNetwork::Testnet4).block_hash();
126154
static ref REGTEST_GENESIS: bitcoin::BlockHash =
127155
genesis_block(BNetwork::Regtest).block_hash();
128156
static ref SIGNET_GENESIS: bitcoin::BlockHash =
@@ -131,6 +159,7 @@ pub fn bitcoin_genesis_hash(network: BNetwork) -> bitcoin::BlockHash {
131159
match network {
132160
BNetwork::Bitcoin => *BITCOIN_GENESIS,
133161
BNetwork::Testnet => *TESTNET_GENESIS,
162+
BNetwork::Testnet4 => *TESTNET4_GENESIS,
134163
BNetwork::Regtest => *REGTEST_GENESIS,
135164
BNetwork::Signet => *SIGNET_GENESIS,
136165
_ => panic!("unknown network {:?}", network),
@@ -165,6 +194,8 @@ impl From<&str> for Network {
165194
#[cfg(not(feature = "liquid"))]
166195
"testnet" => Network::Testnet,
167196
#[cfg(not(feature = "liquid"))]
197+
"testnet4" => Network::Testnet4,
198+
#[cfg(not(feature = "liquid"))]
168199
"regtest" => Network::Regtest,
169200
#[cfg(not(feature = "liquid"))]
170201
"signet" => Network::Signet,
@@ -187,6 +218,7 @@ impl From<Network> for BNetwork {
187218
match network {
188219
Network::Bitcoin => BNetwork::Bitcoin,
189220
Network::Testnet => BNetwork::Testnet,
221+
Network::Testnet4 => BNetwork::Testnet4,
190222
Network::Regtest => BNetwork::Regtest,
191223
Network::Signet => BNetwork::Signet,
192224
}
@@ -199,9 +231,23 @@ impl From<BNetwork> for Network {
199231
match network {
200232
BNetwork::Bitcoin => Network::Bitcoin,
201233
BNetwork::Testnet => Network::Testnet,
234+
BNetwork::Testnet4 => Network::Testnet4,
202235
BNetwork::Regtest => Network::Regtest,
203236
BNetwork::Signet => Network::Signet,
204237
_ => panic!("unknown network {:?}", network),
205238
}
206239
}
207240
}
241+
242+
#[cfg(not(feature = "liquid"))]
243+
impl From<Network> for &'static bitcoin::params::Params {
244+
fn from(network: Network) -> Self {
245+
match network {
246+
Network::Bitcoin => &bitcoin::params::MAINNET,
247+
Network::Testnet => &bitcoin::params::TESTNET3,
248+
Network::Testnet4 => &bitcoin::params::TESTNET4,
249+
Network::Regtest => &bitcoin::params::REGTEST,
250+
Network::Signet => &bitcoin::params::SIGNET,
251+
}
252+
}
253+
}

src/config.rs

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -125,19 +125,19 @@ impl Config {
125125
.arg(
126126
Arg::with_name("electrum_rpc_addr")
127127
.long("electrum-rpc-addr")
128-
.help("Electrum server JSONRPC 'addr:port' to listen on (default: '127.0.0.1:50001' for mainnet, '127.0.0.1:60001' for testnet and '127.0.0.1:60401' for regtest)")
128+
.help("Electrum server JSONRPC 'addr:port' to listen on (default: '127.0.0.1:50001' for mainnet, '127.0.0.1:60001' for testnet3 and '127.0.0.1:40001' for testnet4 and '127.0.0.1:60401' for regtest)")
129129
.takes_value(true),
130130
)
131131
.arg(
132132
Arg::with_name("http_addr")
133133
.long("http-addr")
134-
.help("HTTP server 'addr:port' to listen on (default: '127.0.0.1:3000' for mainnet, '127.0.0.1:3001' for testnet and '127.0.0.1:3002' for regtest)")
134+
.help("HTTP server 'addr:port' to listen on (default: '127.0.0.1:3000' for mainnet, '127.0.0.1:3001' for testnet3 and '127.0.0.1:3004' for testnet4 and '127.0.0.1:3002' for regtest)")
135135
.takes_value(true),
136136
)
137137
.arg(
138138
Arg::with_name("daemon_rpc_addr")
139139
.long("daemon-rpc-addr")
140-
.help("Bitcoin daemon JSONRPC 'addr:port' to connect (default: 127.0.0.1:8332 for mainnet, 127.0.0.1:18332 for testnet and 127.0.0.1:18443 for regtest)")
140+
.help("Bitcoin daemon JSONRPC 'addr:port' to connect (default: 127.0.0.1:8332 for mainnet, 127.0.0.1:18332 for testnet3 and 127.0.0.1:48332 for testnet4 and 127.0.0.1:18443 for regtest)")
141141
.takes_value(true),
142142
)
143143
.arg(
@@ -149,7 +149,7 @@ impl Config {
149149
.arg(
150150
Arg::with_name("monitoring_addr")
151151
.long("monitoring-addr")
152-
.help("Prometheus monitoring 'addr:port' to listen on (default: 127.0.0.1:4224 for mainnet, 127.0.0.1:14224 for testnet and 127.0.0.1:24224 for regtest)")
152+
.help("Prometheus monitoring 'addr:port' to listen on (default: 127.0.0.1:4224 for mainnet, 127.0.0.1:14224 for testnet3 and 127.0.0.1:44224 for testnet4 and 127.0.0.1:24224 for regtest)")
153153
.takes_value(true),
154154
)
155155
.arg(
@@ -282,6 +282,8 @@ impl Config {
282282
#[cfg(not(feature = "liquid"))]
283283
Network::Testnet => 18332,
284284
#[cfg(not(feature = "liquid"))]
285+
Network::Testnet4 => 48332,
286+
#[cfg(not(feature = "liquid"))]
285287
Network::Regtest => 18443,
286288
#[cfg(not(feature = "liquid"))]
287289
Network::Signet => 38332,
@@ -297,6 +299,8 @@ impl Config {
297299
#[cfg(not(feature = "liquid"))]
298300
Network::Testnet => 60001,
299301
#[cfg(not(feature = "liquid"))]
302+
Network::Testnet4 => 40001,
303+
#[cfg(not(feature = "liquid"))]
300304
Network::Regtest => 60401,
301305
#[cfg(not(feature = "liquid"))]
302306
Network::Signet => 60601,
@@ -314,6 +318,8 @@ impl Config {
314318
#[cfg(not(feature = "liquid"))]
315319
Network::Testnet => 3001,
316320
#[cfg(not(feature = "liquid"))]
321+
Network::Testnet4 => 3004,
322+
#[cfg(not(feature = "liquid"))]
317323
Network::Regtest => 3002,
318324
#[cfg(not(feature = "liquid"))]
319325
Network::Signet => 3003,
@@ -331,6 +337,8 @@ impl Config {
331337
#[cfg(not(feature = "liquid"))]
332338
Network::Testnet => 14224,
333339
#[cfg(not(feature = "liquid"))]
340+
Network::Testnet4 => 44224,
341+
#[cfg(not(feature = "liquid"))]
334342
Network::Regtest => 24224,
335343
#[cfg(not(feature = "liquid"))]
336344
Network::Signet => 54224,
@@ -492,6 +500,8 @@ pub fn get_network_subdir(network: Network) -> Option<&'static str> {
492500
#[cfg(not(feature = "liquid"))]
493501
Network::Testnet => Some("testnet3"),
494502
#[cfg(not(feature = "liquid"))]
503+
Network::Testnet4 => Some("testnet4"),
504+
#[cfg(not(feature = "liquid"))]
495505
Network::Regtest => Some("regtest"),
496506
#[cfg(not(feature = "liquid"))]
497507
Network::Signet => Some("signet"),

src/new_index/fetch.rs

Lines changed: 101 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,6 @@ use elements::encode::{deserialize, Decodable};
99

1010
use std::collections::HashMap;
1111
use std::fs;
12-
use std::io::Cursor;
1312
use std::path::PathBuf;
1413
use std::sync::mpsc::Receiver;
1514
use std::thread;
@@ -201,7 +200,7 @@ fn blkfiles_parser(blobs: Fetcher<Vec<u8>>, magic: u32) -> Fetcher<Vec<SizedBloc
201200
}
202201

203202
fn parse_blocks(blob: Vec<u8>, magic: u32) -> Result<Vec<SizedBlock>> {
204-
let mut cursor = Cursor::new(&blob);
203+
let mut cursor = cursor::Cursor::new(&blob);
205204
let mut slices = vec![];
206205
let max_pos = blob.len() as u64;
207206

@@ -249,3 +248,103 @@ fn parse_blocks(blob: Vec<u8>, magic: u32) -> Result<Vec<SizedBlock>> {
249248
.collect()
250249
}))
251250
}
251+
252+
mod cursor {
253+
use std::convert::TryInto;
254+
255+
pub struct Cursor<T> {
256+
inner: T,
257+
pos: u64,
258+
}
259+
260+
impl<T: AsRef<[u8]>> Cursor<T> {
261+
/// Creates a `Cursor` by wrapping `inner`.
262+
#[inline]
263+
pub fn new(inner: T) -> Self {
264+
Cursor { inner, pos: 0 }
265+
}
266+
267+
/// Returns the position read up to thus far.
268+
#[inline]
269+
pub fn position(&self) -> u64 {
270+
self.pos
271+
}
272+
273+
/// Sets the position to `pos`.
274+
#[inline]
275+
pub fn set_position(&mut self, pos: u64) {
276+
self.pos = pos;
277+
}
278+
279+
/// Returns the inner buffer.
280+
///
281+
/// This is the whole wrapped buffer, including the bytes already read.
282+
#[inline]
283+
#[allow(dead_code)]
284+
pub fn into_inner(self) -> T {
285+
self.inner
286+
}
287+
}
288+
289+
#[cfg(not(feature = "liquid"))]
290+
impl<T: AsRef<[u8]>> bitcoin_io::Read for Cursor<T> {
291+
#[inline]
292+
fn read(&mut self, buf: &mut [u8]) -> Result<usize, bitcoin_io::Error> {
293+
let inner: &[u8] = self.inner.as_ref();
294+
let start_pos = self.pos.try_into().unwrap_or(inner.len());
295+
let read = core::cmp::min(inner.len().saturating_sub(start_pos), buf.len());
296+
buf[..read].copy_from_slice(&inner[start_pos..start_pos + read]);
297+
self.pos = self.pos.saturating_add(
298+
read.try_into()
299+
.unwrap_or(u64::max_value() /* unreachable */),
300+
);
301+
Ok(read)
302+
}
303+
}
304+
305+
#[cfg(not(feature = "liquid"))]
306+
impl<T: AsRef<[u8]>> bitcoin_io::BufRead for Cursor<T> {
307+
#[inline]
308+
fn fill_buf(&mut self) -> Result<&[u8], bitcoin_io::Error> {
309+
let inner: &[u8] = self.inner.as_ref();
310+
Ok(&inner[self.pos as usize..])
311+
}
312+
313+
#[inline]
314+
fn consume(&mut self, amount: usize) {
315+
assert!(amount <= self.inner.as_ref().len());
316+
self.pos += amount as u64;
317+
}
318+
}
319+
320+
#[cfg(feature = "liquid")]
321+
impl<T: AsRef<[u8]>> std::io::Read for Cursor<T> {
322+
#[inline]
323+
fn read(&mut self, buf: &mut [u8]) -> Result<usize, std::io::Error> {
324+
let inner: &[u8] = self.inner.as_ref();
325+
let start_pos = self.pos.try_into().unwrap_or(inner.len());
326+
let read = core::cmp::min(inner.len().saturating_sub(start_pos), buf.len());
327+
buf[..read].copy_from_slice(&inner[start_pos..start_pos + read]);
328+
self.pos = self.pos.saturating_add(
329+
read.try_into()
330+
.unwrap_or(u64::max_value() /* unreachable */),
331+
);
332+
Ok(read)
333+
}
334+
}
335+
336+
#[cfg(feature = "liquid")]
337+
impl<T: AsRef<[u8]>> std::io::BufRead for Cursor<T> {
338+
#[inline]
339+
fn fill_buf(&mut self) -> Result<&[u8], std::io::Error> {
340+
let inner: &[u8] = self.inner.as_ref();
341+
Ok(&inner[self.pos as usize..])
342+
}
343+
344+
#[inline]
345+
fn consume(&mut self, amount: usize) {
346+
assert!(amount <= self.inner.as_ref().len());
347+
self.pos += amount as u64;
348+
}
349+
}
350+
}

src/new_index/query.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ use std::collections::{BTreeSet, HashMap};
44
use std::sync::{Arc, RwLock, RwLockReadGuard};
55
use std::time::{Duration, Instant};
66

7-
use crate::chain::{Network, OutPoint, Transaction, TxOut, Txid};
7+
use crate::chain::{Network, OutPoint, Transaction, TxOperations, TxOut, Txid};
88
use crate::config::Config;
99
use crate::daemon::Daemon;
1010
use crate::errors::*;
@@ -133,7 +133,7 @@ impl Query {
133133
}
134134

135135
pub fn lookup_tx_spends(&self, tx: Transaction) -> Vec<Option<SpendingInput>> {
136-
let txid = tx.txid();
136+
let txid = TxOperations::txid(&tx);
137137

138138
tx.output
139139
.par_iter()

0 commit comments

Comments
 (0)