Skip to content

Commit 1df7af7

Browse files
committed
electrum: serve the indexed genesis hash in server.features
Addresses review on Blockstream#265. server.features now reports the genesis block hash actually indexed at height 0 instead of the hardcoded genesis_hash(config.network_type). The latter returns an all-zero placeholder on Liquid testnet/regtest and can't reflect configurable Elements regtest genesis blocks. RPC::start runs after the initial sync, so height 0 is already indexed; fall back to genesis_hash() only if it somehow isn't. Also strengthens the test to assert the returned genesis_hash equals the daemon's height-0 block hash (reversed, per the Electrum wire format), rather than only checking it is a string.
1 parent e8e2e6c commit 1df7af7

2 files changed

Lines changed: 26 additions & 3 deletions

File tree

‎src/electrum/server.rs‎

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1249,10 +1249,19 @@ impl RPC {
12491249

12501250
let server_features = {
12511251
use crate::chain::genesis_hash;
1252+
// Prefer the genesis block hash actually indexed at height 0 over the
1253+
// hardcoded genesis_hash(): on Liquid testnet/regtest the latter is an
1254+
// all-zero placeholder, and Elements regtest genesis is configurable.
1255+
// `start` runs after the initial sync, so height 0 is already indexed;
1256+
// fall back to genesis_hash() only if it somehow isn't.
1257+
let genesis_hash = query
1258+
.chain()
1259+
.hash_by_height(0)
1260+
.unwrap_or_else(|| genesis_hash(config.network_type));
12521261
Arc::new(ServerFeatures {
12531262
hosts: config.electrum_public_hosts.clone().unwrap_or_default(),
12541263
server_version: format!("electrs-esplora {}", ELECTRS_VERSION),
1255-
genesis_hash: genesis_hash(config.network_type),
1264+
genesis_hash,
12561265
protocol_min: PROTOCOL_VERSION,
12571266
protocol_max: PROTOCOL_VERSION,
12581267
hash_function: "sha256".into(),

‎tests/electrum.rs‎

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -216,7 +216,7 @@ fn test_electrum_raw() {
216216
fn test_electrum_server_features_without_public_hosts() {
217217
// Electrum >= 4.7.0 calls server.features on connect, so it must answer
218218
// even when peer discovery is off (no --electrum-public-hosts). See #229.
219-
let (_electrum_server, electrum_addr, mut _tester) = common::init_electrum_tester().unwrap();
219+
let (_electrum_server, electrum_addr, tester) = common::init_electrum_tester().unwrap();
220220

221221
let mut stream = TcpStream::connect(electrum_addr).unwrap();
222222
let s = write_and_read(
@@ -230,7 +230,21 @@ fn test_electrum_server_features_without_public_hosts() {
230230
let features = &reply["result"];
231231
assert_eq!(features["server_version"], "electrs-esplora 0.4.1");
232232
assert_eq!(features["hash_function"], "sha256");
233-
assert!(features["genesis_hash"].is_string(), "missing genesis_hash: {}", s);
233+
234+
// The genesis hash must be the actual genesis block hash indexed at height 0,
235+
// not the hardcoded genesis_hash() (which is an all-zero placeholder on
236+
// Liquid testnet/regtest). The Electrum protocol serializes hashes reversed.
237+
use bitcoin::hashes::Hash;
238+
use bitcoin::hex::DisplayHex;
239+
let mut genesis_bytes = tester.get_block_hash(0).unwrap().to_raw_hash().to_byte_array();
240+
genesis_bytes.reverse();
241+
let expected = genesis_bytes.to_lower_hex_string();
242+
assert_eq!(
243+
features["genesis_hash"].as_str(),
244+
Some(expected.as_str()),
245+
"genesis_hash must be the indexed height-0 block hash: {}",
246+
s
247+
);
234248
}
235249

236250
#[cfg_attr(not(feature = "liquid"), test)]

0 commit comments

Comments
 (0)