fluxture
fluxture copied to clipboard
A crawling framework for blockchains and peer-to-peer systems
Fluxture
Fluxture is a lightweight crawler for peer-to-peer networks like Blockchains. It currently supports the latest version of the Bitcoin protocol: 70015. It implements the minimum amount of the Bitcoin protocol necessary to collect geographic and topological information.
Quickstart
pip3 install fluxture
Or, to install from source (e.g., for development):
$ git clone https://github.com/trailofbits/fluxture
$ cd fluxture
$ pip3 install -e '.[dev]'
Usage
To crawl the Bitcoin network, run:
fluxture crawl bitcoin --database crawl.db
The crawl database is a SQLite database that can be reused between crawls.
Geolocation
Fluxture uses the MaxMind GeoLite2 City database for geolocating nodes based upon their IP address. Various Fluxture commands will either require a path to the database, or a MaxMind license key (which will be used to automatically download the database). You can sign up for a free MaxMind license key, here.
A KML file (which can be imported to Google Maps or Google Earth) can be generated from a crawl using:
fluxture kml --group-by ip crawl.db output.kml
The geolocation database can be updated from MaxMind by running:
fluxture update-geo-db
An existing crawl database can be re-analyzed for missing or updated geolocations (e.g., from an updated MaxMind database) by running:
fluxture geolocate crawl.db
Topological Analysis
Fluxture can calculate topological statistics about the centrality of a crawled network by running:
fluxture topology crawl.db
Programmatic Interface
from fluxture.crawl_schema import CrawlDatabase
with CrawlDatabase("crawl.db") as db:
for node in db.nodes:
print(f"Node {node.ip}:{node.port} {node.state!s}")
location = node.get_location()
if location is not None:
print(f"\tLocation:\t{location.continent_code}\t{location.country_code}\t{location.city}")
else:
print("\tLocation:\t?")
version = node.get_version()
if version is not None:
print(f"\tVersion:\t{version.version!s}")
else:
print("\tVersion:\t?")
print(f"\tOut-Edges:\t{', '.join(str(neighbor.ip) for neighbor in node.get_latest_edges())}")
License and Acknowledgements
This research was developed by Trail of Bits based upon work supported by DARPA under Contract No. HR001120C0084. Any opinions, findings and conclusions or recommendations expressed in this material are those of the authors and do not necessarily reflect the views of the United States Government or DARPA. It is licensed under the Apache 2.0 license. © 2020–2021, Trail of Bits.