Page Menu
Home
Phabricator
Search
Configure Global Search
Log In
Files
F14864477
D13829.id40105.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Award Token
Flag For Later
Size
4 KB
Subscribers
None
D13829.id40105.diff
View Options
diff --git a/chronik/chronik-http/src/server.rs b/chronik/chronik-http/src/server.rs
--- a/chronik/chronik-http/src/server.rs
+++ b/chronik/chronik-http/src/server.rs
@@ -111,6 +111,7 @@
fn make_router(indexer: ChronikIndexerRef) -> Router {
Router::new()
+ .route("/blockchain-info", routing::get(handle_blockchain_info))
.route("/block/:hash_or_height", routing::get(handle_block))
.route("/tx/:txid", routing::get(handle_tx))
.route(
@@ -135,6 +136,14 @@
}
}
+async fn handle_blockchain_info(
+ Extension(indexer): Extension<ChronikIndexerRef>,
+) -> Result<Protobuf<proto::BlockchainInfo>, ReportError> {
+ let indexer = indexer.read().await;
+ let blocks = indexer.blocks();
+ Ok(Protobuf(blocks.blockchain_info()?))
+}
+
async fn handle_block(
Path(hash_or_height): Path<String>,
Extension(indexer): Extension<ChronikIndexerRef>,
diff --git a/chronik/chronik-indexer/src/query/blocks.rs b/chronik/chronik-indexer/src/query/blocks.rs
--- a/chronik/chronik-indexer/src/query/blocks.rs
+++ b/chronik/chronik-indexer/src/query/blocks.rs
@@ -71,4 +71,19 @@
}),
})
}
+
+ /// Query some info about the blockchain, e.g. the tip hash and height.
+ pub fn blockchain_info(&self) -> Result<proto::BlockchainInfo> {
+ let block_reader = BlockReader::new(self.db)?;
+ match block_reader.tip()? {
+ Some(block) => Ok(proto::BlockchainInfo {
+ tip_hash: block.hash.to_vec(),
+ tip_height: block.height,
+ }),
+ None => Ok(proto::BlockchainInfo {
+ tip_hash: vec![0; 32],
+ tip_height: -1,
+ }),
+ }
+ }
}
diff --git a/chronik/chronik-proto/proto/chronik.proto b/chronik/chronik-proto/proto/chronik.proto
--- a/chronik/chronik-proto/proto/chronik.proto
+++ b/chronik/chronik-proto/proto/chronik.proto
@@ -12,6 +12,14 @@
BlockInfo block_info = 1;
}
+// Info about the state of the blockchain.
+message BlockchainInfo {
+ // Hash (little-endian) of the current tip
+ bytes tip_hash = 1;
+ // Height of the current tip (genesis has height = 0)
+ int32 tip_height = 2;
+}
+
// Info about a block
message BlockInfo {
// Hash (little-endian)
diff --git a/test/functional/chronik_blockchain_info.py b/test/functional/chronik_blockchain_info.py
new file mode 100644
--- /dev/null
+++ b/test/functional/chronik_blockchain_info.py
@@ -0,0 +1,51 @@
+#!/usr/bin/env python3
+# Copyright (c) 2023 The Bitcoin developers
+# Distributed under the MIT software license, see the accompanying
+# file COPYING or http://www.opensource.org/licenses/mit-license.php.
+"""
+Test Chronik's /blockchain-info endpoint.
+"""
+
+from test_framework.address import ADDRESS_ECREG_UNSPENDABLE
+from test_framework.blocktools import GENESIS_BLOCK_HASH
+from test_framework.test_framework import BitcoinTestFramework
+from test_framework.util import assert_equal
+
+
+class ChronikBlockchainInfoTest(BitcoinTestFramework):
+ def set_test_params(self):
+ self.setup_clean_chain = True
+ self.num_nodes = 1
+ self.extra_args = [['-chronik']]
+
+ def skip_test_if_missing_module(self):
+ self.skip_if_no_chronik()
+
+ def run_test(self):
+ from test_framework.chronik.client import ChronikClient, pb
+
+ node = self.nodes[0]
+ chronik = ChronikClient('127.0.0.1', node.chronik_port)
+
+ assert_equal(chronik.blockchain_info().ok(), pb.BlockchainInfo(
+ tip_hash=bytes.fromhex(GENESIS_BLOCK_HASH)[::-1],
+ tip_height=0,
+ ))
+
+ block_hashes = self.generatetoaddress(node, 12, ADDRESS_ECREG_UNSPENDABLE)
+
+ assert_equal(chronik.blockchain_info().ok(), pb.BlockchainInfo(
+ tip_hash=bytes.fromhex(block_hashes[11])[::-1],
+ tip_height=12,
+ ))
+
+ node.invalidateblock(block_hashes[6])
+
+ assert_equal(chronik.blockchain_info().ok(), pb.BlockchainInfo(
+ tip_hash=bytes.fromhex(block_hashes[5])[::-1],
+ tip_height=6,
+ ))
+
+
+if __name__ == '__main__':
+ ChronikBlockchainInfoTest().main()
diff --git a/test/functional/test_framework/chronik/client.py b/test/functional/test_framework/chronik/client.py
--- a/test/functional/test_framework/chronik/client.py
+++ b/test/functional/test_framework/chronik/client.py
@@ -139,6 +139,9 @@
ok_proto.ParseFromString(body)
return ChronikResponse(response.status, ok_proto=ok_proto)
+ def blockchain_info(self) -> ChronikResponse:
+ return self._request_get('/blockchain-info', pb.BlockchainInfo)
+
def block(self, hash_or_height: Union[str, int]) -> ChronikResponse:
return self._request_get(f'/block/{hash_or_height}', pb.Block)
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Tue, May 20, 19:58 (4 h, 3 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
5865603
Default Alt Text
D13829.id40105.diff (4 KB)
Attached To
D13829: [Chronik] Add `/blockchain-info` HTTP endpoint
Event Timeline
Log In to Comment