Compare commits
6 Commits
wot
...
username-s
Author | SHA1 | Date | |
---|---|---|---|
|
4b7b408d60 | ||
|
cb17270512 | ||
|
74db4d2d9d | ||
|
f74fd0d03d | ||
|
df292afe69 | ||
|
d247c1eee8 |
@ -1,6 +1,3 @@
|
||||
onionr/data/**/*
|
||||
onionr/data
|
||||
MY-RUN.sh
|
||||
Dockerfile
|
||||
.dockerignore
|
||||
.git
|
||||
|
12
AUTHORS.MD
Normal file
12
AUTHORS.MD
Normal file
@ -0,0 +1,12 @@
|
||||
# Incomplete List of Contributors
|
||||
|
||||
Onionr is created by a team of hard working volunteers.
|
||||
|
||||
In no order of importance, these people make Onionr happen:
|
||||
|
||||
* [Beardog (Kevin Froman)](https://www.chaoswebs.net/) - Project founder, owner and core developer
|
||||
* [InvisaMage](https://invisamage.com/) - Web UI Bulma design
|
||||
* [Arinerron](https://arinerron.com/) - Logger and config modules, testing and other contributions
|
||||
* [Anhar Ismail](https://github.com/anharismail) - Created Onionr's logo
|
||||
|
||||
+ Other contributors and testers
|
11
Dockerfile
11
Dockerfile
@ -1,12 +1,12 @@
|
||||
FROM python:3.10
|
||||
EXPOSE 8080
|
||||
FROM python:3.7
|
||||
|
||||
USER root
|
||||
|
||||
RUN mkdir /app
|
||||
WORKDIR /app
|
||||
|
||||
ENV ONIONR_DOCKER=true
|
||||
ENV PORT=8080
|
||||
EXPOSE 8080
|
||||
|
||||
#Install needed packages
|
||||
RUN apt-get update && apt-get install -y tor locales
|
||||
@ -15,7 +15,7 @@ RUN sed -i -e 's/# en_US.UTF-8 UTF-8/en_US.UTF-8 UTF-8/' /etc/locale.gen && \
|
||||
locale-gen
|
||||
ENV LANG=en_US.UTF-8 LANGUAGE=en_US:en LC_ALL=en_US.UTF-8
|
||||
|
||||
ADD ./requirements-x86-all-plugins.txt /app/requirements.txt
|
||||
ADD ./requirements.txt /app/requirements.txt
|
||||
RUN pip3 install --require-hashes -r requirements.txt
|
||||
|
||||
#Add Onionr source
|
||||
@ -26,6 +26,5 @@ VOLUME /app/data/
|
||||
#Default to running as nonprivileged user
|
||||
RUN chmod g=u -R /app
|
||||
USER 1000
|
||||
ENV HOME=/app
|
||||
|
||||
CMD ["bash", "./onionr.sh", "start"]
|
||||
CMD ["bash", "./onionr.sh"]
|
||||
|
97
README.md
97
README.md
@ -8,73 +8,85 @@
|
||||
Privacy Respecting Communication Network 📡
|
||||
</p>
|
||||
<p align="center">
|
||||
WIP anonymous social platform, mail, file sharing and marketplace
|
||||
Anonymous social platform, mail, file sharing.
|
||||
</p>
|
||||
|
||||
<img src="https://img.shields.io/badge/License-aGPLv3-yellow"> <img src='https://img.shields.io/badge/python%20version%20%F0%9F%90%8D-3.10+-blue'>
|
||||
<img src='https://img.shields.io/github/license/beardog108/onionr'> <img src="https://img.shields.io/github/repo-size/beardog108/onionr"> <img src='https://img.shields.io/badge/python%20version%20%F0%9F%90%8D-3.7+-blue'> <img src='https://img.shields.io/github/commit-activity/m/beardog108/onionr'>
|
||||
|
||||
<a href='https://twitter.com/onionrnet'><img src='https://img.shields.io/twitter/follow/onionrnet?style=social'></a> - [Discord](https://discord.gg/DVF2bEAzrt) - Matrix: #onionr:amorgan.xyz
|
||||
<a href='https://www.reddit.com/r/onionr'><img src = 'https://img.shields.io/reddit/subreddit-subscribers/onionr?style=social'></a> <a href='https://twitter.com/onionrnet'><img src='https://img.shields.io/twitter/follow/onionrnet?style=social'></a> - [Discord](https://discord.gg/DVF2bEAzrt) - Matrix: #onionr:amorgan.xyz
|
||||
|
||||
| | | |
|
||||
| ----------- | ----------- | ----------- |
|
||||
| [Install](#install-and-run-on-linux) | [Features](#main-features) | [Screenshots](#screenshots)|
|
||||
| [Docs](#documentation) | [Get involved](#help-out) | [Onionr.net](https://onionr.net/)/[.onion](http://onionrbak72t5zhbzuey2fdkpczlvhowgcpqc6uoyrd3uxztzxwz5cyd.onion/) |
|
||||
| [Docs](#documentation)/[web copy](https://beardog108.github.io/onionr/) | [Get involved](#help-out) | [Onionr.net](https://onionr.net/)/[.onion](http://onionrbak72t5zhbzuey2fdkpczlvhowgcpqc6uoyrd3uxztzxwz5cyd.onion/) |
|
||||
|
||||
|
||||
---
|
||||
<hr>
|
||||
|
||||
**The main repository for this software is at https://gitlab.com/beardog/onionr/**
|
||||
**The main repository for this software is at https://git.VoidNet.tech/kev/onionr/**
|
||||
|
||||
***Note that this README reflects the state of the rewrite, and not the original alpha network***
|
||||
|
||||
Mirrors [Gitea](https://git.voidnet.tech/kev/onionr)
|
||||
Mirrors: [Github](https://github.com/beardog108/onionr), [Gitlab](https://gitlab.com/beardog/onionr)
|
||||
|
||||
|
||||
Onionr ("Onion Relay") is a decentralized/distributed peer-to-peer communication network, designed to be anonymous and resistant to (meta)data analysis, spam, and corruption.
|
||||
|
||||
Onionr stores data in independent packages referred to as 'blocks'. The blocks are distributed to all interested nodes. Blocks and user IDs cannot be easily proven to have been created by a particular user. Even if there is enough evidence to believe that a specific user created a block, nodes still operate behind Tor and as such cannot be trivially unmasked. Anonymity is achieved by a stateless network, with no given indication of what node a block originates from. In fact, since one is not required to participate in routing or storage to insert a message, blocks often do not originate from any identifiable node.
|
||||
|
||||
Through message mixing and key privacy, it is intended to be nigh impossible to discover the identity of a message creator or recipient. Via long-term traffic analysis, a well funded adversary may discover the most probable node(s) to be creating a set of related blocks, however doing so would only lead them to a node behind Tor. As the first node that a block appears on is almost always not the creator of the block, there is plausible deniability regarding the true creator of the block.
|
||||
|
||||
Onionr gives the individual the ability to speak freely, without fear of surveillance and censorship.
|
||||
|
||||
---
|
||||
|
||||
# Onionr internals
|
||||
|
||||
## Blocks
|
||||
|
||||
At the core, Onionr is an anonymous Distributed Hash Table (DHT) syncing prepackaged blocks using a simple Gossip protocol with Dandelion++ as an overlay network on top of Tor and I2P.
|
||||
|
||||
Onionr stores data in independent packages referred to as 'blocks'. The blocks are distributed to all nodes, but are not required to be stored. Blocks and user IDs cannot be easily proven to have been created by a particular user. Even if Dandelion++ is defeated and there is enough evidence to believe that a specific node is linked to a block's creation, nodes still operate behind Tor or I2P and as such cannot be trivially unmasked. Anonymity is achieved by a stateless network, with no given indication of what node a block originates from. In fact, since one is not required to participate in routing or storage to insert a message, blocks often do not originate from any identifiable node, similar to how Bitcoin transactions do not necessarily originate from a wallet directly associated with a node.
|
||||
|
||||
## Onionr Gossip
|
||||
|
||||
Onionr works via epidemic/gossip style routing, with message delivery taking roughly log<sub>C</sub>(N) cycles where C is the number of nodes to send a message to each cycle and N is the number of connected nodes. So a network of 100 million nodes can deliver messages in a few minutes even with high packet loss and malfunctioning nodes.
|
||||
|
||||
Through Dandelion++ message forwarding and key privacy, it is intended to be nigh impossible to discover the identity of a message creator or recipient. Via long-term traffic analysis, a well funded adversary may discover the most probable node(s) to be creating a set of related blocks, however doing so would only lead them to a node behind Tor. As the first node that a block appears on is almost always not the creator of the block, there is plausible deniability regarding the true creator of the block.
|
||||
|
||||
Users are identified by ed25519/curve25519 public keys, which can be used to sign blocks or send encrypted data.
|
||||
|
||||
Onionr can be used for mail, as a social network, instant messenger, file sharing software, or for encrypted group discussion.
|
||||
|
||||
Since Onionr is technically just a data format, any routing scheme can technically be used to pass messages.
|
||||
Due to the nature of anonymity, the graph as implemented in this reference network is dense, undirected, cyclic and can be disconnected. As a result, current scalability is poor but sufficient for high latency communications. As the need arises isolated stream solutions may be implemented (in a manner similar to described in the Bitmessage whitepaper). Since Onionr is technically just a data format, any routing scheme can be used to pass messages.
|
||||
|
||||
The whitepaper is available [here](docs/whitepaper.md).
|
||||
|
||||
---
|
||||
|
||||
# Main Features
|
||||
## Main Features
|
||||
|
||||
* [X] 🌐 Fully p2p/decentralized, no trackers or other single points of failure
|
||||
* [X] 🔒 End to end encryption of user data
|
||||
* [X] 📢 Optional non-encrypted blocks, useful for blog posts or public file sharing
|
||||
* [X] 💻 Easy HTTP API for integration to websites
|
||||
* [X] 🕵️ Metadata analysis resistance and anonymity
|
||||
* [X] 📡 Transport agnosticism (no internet required)
|
||||
|
||||
Onionr ships with various application plugins ready for use out of the box:
|
||||
|
||||
# Roadmap
|
||||
Currently usable:
|
||||
|
||||
See [ROADMAP.md](ROADMAP.md)
|
||||
* Mail
|
||||
* Public anonymous chat/message board
|
||||
* Simple webpage hosting - Will be greatly extended
|
||||
* File sharing (Work in progress)
|
||||
|
||||
Not yet usable:
|
||||
|
||||
* Instant messaging
|
||||
|
||||
|
||||
# Screenshots
|
||||
|
||||
<img alt='Node statistics page screenshot' src='docs/onionr-1.png' width=600>
|
||||
|
||||
Home screen
|
||||
|
||||
<img alt='Friend/contact manager screenshot' src='docs/onionr-2.png' width=600>
|
||||
|
||||
Friend/contact manager
|
||||
|
||||
<img alt='Encrypted, metadata-masking mail application screenshot' src='docs/onionr-3.png' width=600>
|
||||
|
||||
Encrypted, metadata-masking mail application. One of the first distributed mail systems to have basic forward secrecy.
|
||||
|
||||
# Documentation
|
||||
|
||||
More docs coming soon.
|
||||
|
||||
* [Block specification](docs/dev/specs/block-spec.md)
|
||||
* [HTTP API](docs/dev/http-api.md)
|
||||
|
||||
# Install and Run on Linux
|
||||
|
||||
@ -84,27 +96,30 @@ Master may be unstable, you should use the latest release tag. (checkout via git
|
||||
|
||||
`$ sudo apt install python3-pip python3-dev tor`
|
||||
|
||||
* Have python3.10, python3-pip, Tor (daemon, not browser) installed. python3-dev is recommended.
|
||||
* Have python3.7+, python3-pip, Tor (daemon, not browser) installed. python3-dev is recommended.
|
||||
* You may need build-essentials or the equivalent of your platform
|
||||
* Clone the git repo: `$ git clone https://gitlab.com/beardog/onionr --tags`
|
||||
* cd into install direction: `$ cd onionr/`
|
||||
* Install the Python dependencies ([virtualenv strongly recommended](https://virtualenv.pypa.io/en/stable/userguide/)): `$ pip3 install --require-hashes -r requirements-x86-all-plugins.txt`
|
||||
* Install the Python dependencies ([virtualenv strongly recommended](https://virtualenv.pypa.io/en/stable/userguide/)): `$ pip3 install --require-hashes -r requirements.txt` (on ARM64 devices like Raspberry Pi 4's use requirements-ARM.txt instead.)
|
||||
* (Optional): Install desktop notification dependencies: `$ pip3 install --require-hashes -r requirements-notifications.txt`
|
||||
|
||||
Require-hashes is suggested for supply-chain security but is optional. The hashes are not correct for ARM machines. If you are just running a node or want a bare-bones install you can use requirements-base-x86.txt and selectively install the requirements.txt files in static-data/official-plugins/ subdirectories
|
||||
(--require-hashes is intended to prevent exploitation via compromise of PyPi/CA certificates)
|
||||
|
||||
## Run Onionr
|
||||
|
||||
* Run Onionr normally: `$ ./onionr.sh start`
|
||||
* Run Onionr in background as daemon: `$ ./start-daemon.sh`
|
||||
* Open Onionr web interface `$ ./onionr.sh openhome`
|
||||
* Gracefully stop Onionr from CLI `$ ./onionr.sh stop`
|
||||
|
||||
|
||||
# Contact/Community
|
||||
|
||||
* Email: onionr [ at ] voidnet.tech
|
||||
* Email: beardog [ at ] mailbox.org
|
||||
* Twitter: [@onionrnet](https://twitter.com/onionrnet)
|
||||
* Onionr Mail: decentralized-fiery-freehearted-skimmer-yodling-topstitch-divorceable-ojibwa-resettlement-infracted-lessor-noninstinctual-leaseholder-counterpoised-couture-skinful
|
||||
* Matrix: #onionr:amorgan.xyz
|
||||
* Discord: https://discord.gg/DVF2bEAzrt (Discord is bad for freedom and privacy, this is only provided for convenience)
|
||||
* Discord: https://discord.gg/DVF2bEAzrt (Discord is bad for freedom and privacy, this is only provided for convienience)
|
||||
|
||||
# Help out
|
||||
|
||||
@ -113,7 +128,7 @@ Everyone is welcome to contribute. Help is wanted for the following:
|
||||
* Development (Get in touch first)
|
||||
* Creation of a shared lib for use from other languages and faster proof-of-work
|
||||
* Android and IOS development
|
||||
* Mac support (testers needed)
|
||||
* Mac support (already partially supported, testers needed)
|
||||
* Bug fixes and development of new features
|
||||
* Testing
|
||||
* Translations/localizations
|
||||
@ -135,15 +150,15 @@ Donating at least $3 gets you cool Onionr stickers. Get in touch if you want the
|
||||
![sticker](docs/sticker.png)
|
||||
|
||||
|
||||
* Bitcoin: [bc1qpayme9rlpkch0qp3r79lvm5racr7t6llauwfmg](bitcoin:bc1qpayme9rlpkch0qp3r79lvm5racr7t6llauwfmg) (Contact us for a unique address or for other coins)
|
||||
* Bitcoin: [1onion55FXzm6h8KQw3zFw2igpHcV7LPq](bitcoin:1onion55FXzm6h8KQw3zFw2igpHcV7LPq) (Contact us for a unique address or for other coins)
|
||||
|
||||
* Monero: 4B5BA24d1P3R5aWEpkGY5TP7buJJcn2aSGBVRQCHhpiahxeB4aWsu15XwmuTjC6VF62NApZeJGTS248RMVECP8aW73Uj2ax
|
||||
|
||||
* USD (Card/Paypal (no account required)): [Ko-Fi](https://www.ko-fi.com/beardogkf)
|
||||
* USD (Card/Paypal): [Ko-Fi](https://www.ko-fi.com/beardogkf)
|
||||
|
||||
* Sign up for [privacy.com (refferal link)](https://privacy.com/join/FNNDF) to protect your personal information when contributing or shopping elsewhere, we both get $5 USD.
|
||||
* [Indiegogo](https://igg.me/at/onionr/x#/)
|
||||
|
||||
Note: not tax deductible
|
||||
Note: probably not tax deductible
|
||||
|
||||
# Security
|
||||
|
||||
|
46
ROADMAP.md
46
ROADMAP.md
@ -1,46 +0,0 @@
|
||||
# Onionr Roadmap
|
||||
|
||||
|
||||
## Taraxacum Release (9.0)
|
||||
|
||||
|
||||
* [ X ] Implement new block format with verifiable delay function
|
||||
|
||||
* [ X ] Implement overhauled gossip system with dandelion++
|
||||
|
||||
The new system is separated from the underlying networks used and makes it much easier to implement new transport methods. Dandelion++ is also better than the old block mixing we did.
|
||||
|
||||
|
||||
## Misc
|
||||
|
||||
* [ ] Spruce up documentation
|
||||
* [ ] Restore LAN transport
|
||||
* [ ] Restore webUI as a plugin
|
||||
* [ ] Restore static site/file sharing plugin
|
||||
* [ ] Restore/reimplement mail plugin
|
||||
* [ ] Restore/reimplement friends plugin
|
||||
* [ ] Refresh test suite
|
||||
* [ ] Revamped key/encrypted messaging (encrypted blocks)
|
||||
|
||||
|
||||
|
||||
## Web of trust release (~10.0)
|
||||
|
||||
To facilitate the below market plugin/application, Onionr will need a web of trust system.
|
||||
|
||||
* [ ] Web of trust plugin or module
|
||||
|
||||
|
||||
## Market Plugin Release (~10.1)
|
||||
|
||||
The Onionr team believes the Monero community is currently lacking a good p2p market, and as such we hope to build a solution using Onionr as a transport. This may be a separate project and as opposed to a plugin.
|
||||
|
||||
|
||||
* A new marketplace plugin will be developed with the following *tenative* features:
|
||||
|
||||
* [ ] Account management
|
||||
* [ ] Monero management
|
||||
* [ ] Store front discovery and search
|
||||
* [ ] Product listing search
|
||||
* [ ] User reviews
|
||||
|
@ -22,13 +22,13 @@ The following exploits are of particular interest:
|
||||
* Cryptography/protocol issues
|
||||
* Denying nodes access to the network by segmenting them out with Sybil nodes
|
||||
|
||||
We do not consider non-network based same-machine attacks to be very significant, but we are still willing to listen.
|
||||
We do not consider OS user-level side channel attacks on a shared machine to be very significant, but we are still willing to listen.
|
||||
|
||||
# Rewards
|
||||
|
||||
Onionr is a student-owned hobby project, resources are not available for large rewards.
|
||||
Onionr is a hobbyist project, resources are not available for monetary rewards.
|
||||
|
||||
Stickers or other small rewards are available. We reserve the right to refuse rewards for any reason.
|
||||
Shirts/stickers or other small rewards are available. We reserve the right to refuse rewards for any reason.
|
||||
|
||||
Public recognition can be given upon request.
|
||||
|
||||
@ -36,4 +36,4 @@ Public recognition can be given upon request.
|
||||
|
||||
Email: beardog [ at ] mailbox.org
|
||||
|
||||
PGP (optional): F61A 4DBB 0B3D F172 1F65 0EDF 0D41 4D0F E405 B63B
|
||||
Keybase: beardog
|
||||
|
@ -1,8 +0,0 @@
|
||||
PyNaCl==1.5.0
|
||||
psutil==5.9.1
|
||||
filenuke==0.0.0
|
||||
ujson==5.4.0
|
||||
cffi==1.15.1
|
||||
onionrblocks==7.0.0
|
||||
ordered-set==4.1.0
|
||||
json-rpc==1.13.0
|
18
docs/TODO.txt
Normal file
18
docs/TODO.txt
Normal file
@ -0,0 +1,18 @@
|
||||
* add GUI config editor
|
||||
* add multi-device forward secrecy
|
||||
|
||||
* document anonymity & security theory
|
||||
* document usage
|
||||
|
||||
* ensure accessibility for Onionr web UI
|
||||
* make forward secrecy compatible with multiple devices
|
||||
* add way to mark key as dead
|
||||
* add hashable set password for web ui
|
||||
* add edits to circles posts
|
||||
* make node "speed" setting such as when ui is open to reduce bandwidth usage
|
||||
* localization support
|
||||
|
||||
* add BCC support to mail
|
||||
|
||||
|
||||
* truncate last N blocks when sharing list
|
124
docs/dev/http-api.md
Executable file
124
docs/dev/http-api.md
Executable file
@ -0,0 +1,124 @@
|
||||
# Onionr HTTP API
|
||||
|
||||
All HTTP interfaces in the Onionr reference client use the [Flask](http://flask.pocoo.org/) web framework with the [gevent](http://www.gevent.org/) WSGI server.
|
||||
|
||||
## Client & Public difference
|
||||
|
||||
The client API server is a locked down interface intended for authenticated local communication.
|
||||
|
||||
The public API server is available only remotely from Tor & I2P. It is the interface in which peers use to communicate with one another.
|
||||
|
||||
# Client API
|
||||
|
||||
Please note: endpoints that simply provide static web app files are not documented here.
|
||||
|
||||
* /serviceactive/pubkey
|
||||
- Methods: GET
|
||||
- Returns true or false based on if a given public key has an active direct connection service.
|
||||
* /queueResponseAdd/key (DEPRECATED)
|
||||
- Methods: POST
|
||||
- Accepts form key 'data' to set queue response information from a plugin
|
||||
- Returns success if no error occurs
|
||||
* /queueResponse/key (DEPRECATED)
|
||||
- Methods: GET
|
||||
- Returns the queue response for a key. Returns failure with a 404 code if a code is not set.
|
||||
* /ping
|
||||
- Methods: GET
|
||||
- Returns "pong!"
|
||||
* /getblocksbytype/type
|
||||
- Methods: GET
|
||||
- Returns a list of stored blocks by a given type
|
||||
* /getblockbody/hash
|
||||
- Methods: GET
|
||||
- Returns the main data section of a block
|
||||
* /getblockdata/hash
|
||||
- Methods: GET
|
||||
- Returns the entire data contents of a block, including metadata.
|
||||
* /getblockheader/hash
|
||||
- Methods: GET
|
||||
- Returns the header (metadata section) of a block.
|
||||
* /gethidden/
|
||||
- Methods: GET
|
||||
- Returns line separated list of hidden blocks
|
||||
* /hitcount
|
||||
- Methods: GET
|
||||
- Return the amount of requests the public api server has received this session
|
||||
* /lastconnect
|
||||
- Methods: GET
|
||||
- Returns the epoch timestamp of when the last incoming connection to the public API server was logged
|
||||
* /site/hash
|
||||
- Methods: GET
|
||||
- Returns HTML content out of a block
|
||||
* /waitforshare/hash
|
||||
- Methods: POST
|
||||
- Prevents the public API server from listing or sharing a block until it has been uploaded to at least 1 peer.
|
||||
* /shutdown
|
||||
- Methods: GET
|
||||
- Shutdown Onionr. You should probably use /shutdownclean instead.
|
||||
* /shutdownclean
|
||||
- Methods: GET
|
||||
- Tells the communicator daemon to shutdown Onionr. Slower but cleaner.
|
||||
* /getstats
|
||||
- Methods: GET
|
||||
- Returns some JSON serialized statistics
|
||||
* /getuptime
|
||||
- Methods: GET
|
||||
- Returns uptime in seconds
|
||||
* /getActivePubkey
|
||||
- Methods: GET
|
||||
- Returns the current active public key in base32 format
|
||||
* /getHumanReadable/pubkey
|
||||
- Methods: GET
|
||||
- Echos the specified public key in mnemonic format
|
||||
* /insertblock
|
||||
- Methods: POST
|
||||
- Accepts JSON data for creating a new block. 'message' contains the block data, 'to' specifies the peer's public key to encrypt the data to, 'sign' is a boolean for signing the message.
|
||||
* /torready
|
||||
- Methods: POST
|
||||
- Returns boolean if Tor is started or not
|
||||
|
||||
# Public API
|
||||
|
||||
v0
|
||||
|
||||
* /
|
||||
- Methods: GET
|
||||
- Returns a basic HTML informational banner describing Onionr.
|
||||
* /getblocklist
|
||||
- Methods: GET
|
||||
- URI Parameters:
|
||||
- date: unix epoch timestamp for offset
|
||||
- Returns a list of block hashes stored on the node since an offset (all blocks if no timestamp is specified)
|
||||
* /getdata/block-hash
|
||||
- Methods: GET
|
||||
- Returns data for a block based on a provided hash
|
||||
* /www/file-path
|
||||
- Methods: GET
|
||||
- Returns file data. Intended for manually sharing file data directly from an Onionr node.
|
||||
* /ping
|
||||
- Methods: GET
|
||||
- Returns 'pong!'
|
||||
* /pex
|
||||
- Methods: GET
|
||||
- Returns a list of peer addresses reached within recent time
|
||||
* /announce
|
||||
- Methods: POST
|
||||
- Accepts form data for 'node' (valid node address) and 'random' which is a nonce when hashed (blake2b_256) in the format `hash(peerAddress+serverAddress+nonce)`, begins with at least 5 zeros.
|
||||
- Returns 200 with 'Success' if no error occurs. If the post is invalid, 'failure' with code 406 is returned.
|
||||
* /upload
|
||||
- Methods: POST
|
||||
- Accepts form data for 'block' as a 'file' upload.
|
||||
- Returns 200 with 'success' if no error occurs. If the block cannot be accepted, 'failure' with 400 is returned.
|
||||
|
||||
# Direct Connection API
|
||||
|
||||
These are constant endpoints available on direct connection servers. Plugin endpoints for direct connections are not documented here.
|
||||
|
||||
* /ping
|
||||
- Methods: GET
|
||||
- Returns 200 with 'pong!'
|
||||
|
||||
* /close
|
||||
- Methods: GET
|
||||
- Kills the direct connection server, destroying the onion address.
|
||||
- Returns 200 with 'goodbye'
|
@ -1,9 +0,0 @@
|
||||
# Interesting papers related to Onionr development
|
||||
|
||||
A paper being listed here is not end-all-be-all endorsement of every detail inside.
|
||||
|
||||
* [Epidemic Routing for Partially-Connected Ad Hoc Networks](https://web.archive.org/web/20200208074703/http://issg.cs.duke.edu/epidemic/epidemic.pdf)
|
||||
* [Freenet: A distibuted decentralized information storage and retrieval system](https://freenetproject.org/assets/papers/ddisrs.pdf)
|
||||
* [Protecting Free Expression Online with Freenet](https://freenetproject.org/assets/papers/ddisrs.pdf)
|
||||
* [Bitmessage: A Peer‐to‐Peer Message Authentication and Delivery System](https://archive.org/details/BitmessageWhitepaper/)
|
||||
* [MuON: Epidemic based Mutual Anonymity](https://web.archive.org/web/20060901153544/http://www.csl.mtu.edu/cs6461/www/Reading/MuON_ICNP2005.pdf)
|
@ -1,28 +0,0 @@
|
||||
# Running Onionr in Docker
|
||||
|
||||
A Dockerfile is included in the root directory of Onionr.
|
||||
|
||||
In Docker version 20.10 (and probably others), there is a strange bug where Onionr must be run with -it or stdout will be garbled and it may hang.
|
||||
|
||||
## Clone and build the image
|
||||
|
||||
`$ git clone https://git.voidnet.tech/kev/onionr/`
|
||||
`$ cd onionr`
|
||||
`$ sudo docker build -t onionr .`
|
||||
|
||||
|
||||
## Run Onionr
|
||||
|
||||
`$ sudo docker run -it -p 8080:8080 onionr`
|
||||
|
||||
Onionr will be accessible over any network interface by default, so make sure to either change the entry point bind-address argument or set a firewall rule.
|
||||
|
||||
That said, Onionr does protect it's interface by default with a web token, which will be shown in stdout.
|
||||
|
||||
**However, anyone who can access the port may be able to see what Onionr sites you have saved and potentially deanonymize your node**
|
||||
|
||||
## View the UI
|
||||
|
||||
Visit the address and port for the machine Onionr is running on, for example: http://192.168.1.5:8080/#<long-token-taken-from-stdout>
|
||||
|
||||
If you want a secure connection to the interface, either use a proxy such as nginx or caddy, or use [SSH tunneling](./vps-cloud-guide.md).
|
@ -1,18 +0,0 @@
|
||||
# Cloud/Server Hosting Onionr
|
||||
|
||||
Cloud hosting is not the recommended way to run Onionr, as it gives the cloud provider control over your data.
|
||||
|
||||
That said, it is quite useful and by running a 24/7 Onionr node you contribute to the network's health.
|
||||
|
||||
![https://cock.li/img/cockbox.png](https://cockbox.org/?r=12)
|
||||
|
||||
[Cockbox](https://cockbox.org/?r=12) is the recommended provider, as they do not demand personal information and accept Monero. This is an affiliate link, which gives us a commission at no expense or complication to you.
|
||||
|
||||
|
||||
1. [Install Onionr like normal](./basic-onionr-user-guide.pdf) or [from Docker](./docker.md)
|
||||
2. Run with specific host and port to bind to: `$ ./run-onionr-node.py --bind-address 0.0.0.0 --port 8080`
|
||||
3. Get the web security token: `$ ./onionr.sh get-web` (the long string at the end of the URL)
|
||||
4. [Configure Firefox for SSH tunneling](https://web.archive.org/web/20210123034529/https://gist.github.com/brentjanderson/6ed800376e53746d2d28ba7b6bdcdc12). `Set network.proxy.allow_hijacking_localhost` to true in about:config
|
||||
|
||||
|
||||
Disable random host binding in config (general.security.random_bind_ip = false) if you have Onionr auto start. You may also want to disable deniable block inserts.
|
@ -1,9 +1,6 @@
|
||||
#!/bin/sh
|
||||
ORIG_ONIONR_RUN_DIR=`pwd`
|
||||
export ORIG_ONIONR_RUN_DIR
|
||||
export PYTHONDONTWRITEBYTECODE=1
|
||||
export PYTHONUNBUFFERED=1
|
||||
export PYTHONOPTIMIZE="true"
|
||||
cd "$(dirname "$0")"
|
||||
cd src
|
||||
./__init__.py "$@"
|
392
requirements-ARM.txt
Normal file
392
requirements-ARM.txt
Normal file
@ -0,0 +1,392 @@
|
||||
#
|
||||
# This file is autogenerated by pip-compile
|
||||
# To update, run:
|
||||
#
|
||||
# pip-compile --generate-hashes --output-file=requirements-ARM.txt requirements.in
|
||||
#
|
||||
--extra-index-url https://www.piwheels.org/simple
|
||||
|
||||
certifi==2020.12.5 \
|
||||
--hash=sha256:1a4995114262bffbc2413b159f2a1a480c969de6e6eb13ee966d470af86af59c \
|
||||
--hash=sha256:719a74fb9e33b9bd44cc7f3a8d94bc35e4049deebe19ba7d8e108280cfd59830
|
||||
# via requests
|
||||
cffi==1.14.4 \
|
||||
--hash=sha256:00a1ba5e2e95684448de9b89888ccd02c98d512064b4cb987d48f4b40aa0421e \
|
||||
--hash=sha256:00e28066507bfc3fe865a31f325c8391a1ac2916219340f87dfad602c3e48e5d \
|
||||
--hash=sha256:045d792900a75e8b1e1b0ab6787dd733a8190ffcf80e8c8ceb2fb10a29ff238a \
|
||||
--hash=sha256:0638c3ae1a0edfb77c6765d487fee624d2b1ee1bdfeffc1f0b58c64d149e7eec \
|
||||
--hash=sha256:105abaf8a6075dc96c1fe5ae7aae073f4696f2905fde6aeada4c9d2926752362 \
|
||||
--hash=sha256:155136b51fd733fa94e1c2ea5211dcd4c8879869008fc811648f16541bf99668 \
|
||||
--hash=sha256:1a465cbe98a7fd391d47dce4b8f7e5b921e6cd805ef421d04f5f66ba8f06086c \
|
||||
--hash=sha256:1d2c4994f515e5b485fd6d3a73d05526aa0fcf248eb135996b088d25dfa1865b \
|
||||
--hash=sha256:2c24d61263f511551f740d1a065eb0212db1dbbbbd241db758f5244281590c06 \
|
||||
--hash=sha256:51a8b381b16ddd370178a65360ebe15fbc1c71cf6f584613a7ea08bfad946698 \
|
||||
--hash=sha256:594234691ac0e9b770aee9fcdb8fa02c22e43e5c619456efd0d6c2bf276f3eb2 \
|
||||
--hash=sha256:5cf4be6c304ad0b6602f5c4e90e2f59b47653ac1ed9c662ed379fe48a8f26b0c \
|
||||
--hash=sha256:64081b3f8f6f3c3de6191ec89d7dc6c86a8a43911f7ecb422c60e90c70be41c7 \
|
||||
--hash=sha256:6bc25fc545a6b3d57b5f8618e59fc13d3a3a68431e8ca5fd4c13241cd70d0009 \
|
||||
--hash=sha256:798caa2a2384b1cbe8a2a139d80734c9db54f9cc155c99d7cc92441a23871c03 \
|
||||
--hash=sha256:7c6b1dece89874d9541fc974917b631406233ea0440d0bdfbb8e03bf39a49b3b \
|
||||
--hash=sha256:840793c68105fe031f34d6a086eaea153a0cd5c491cde82a74b420edd0a2b909 \
|
||||
--hash=sha256:8d6603078baf4e11edc4168a514c5ce5b3ba6e3e9c374298cb88437957960a53 \
|
||||
--hash=sha256:9cc46bc107224ff5b6d04369e7c595acb700c3613ad7bcf2e2012f62ece80c35 \
|
||||
--hash=sha256:9f7a31251289b2ab6d4012f6e83e58bc3b96bd151f5b5262467f4bb6b34a7c26 \
|
||||
--hash=sha256:9ffb888f19d54a4d4dfd4b3f29bc2c16aa4972f1c2ab9c4ab09b8ab8685b9c2b \
|
||||
--hash=sha256:a5ed8c05548b54b998b9498753fb9cadbfd92ee88e884641377d8a8b291bcc01 \
|
||||
--hash=sha256:a7711edca4dcef1a75257b50a2fbfe92a65187c47dab5a0f1b9b332c5919a3fb \
|
||||
--hash=sha256:af5c59122a011049aad5dd87424b8e65a80e4a6477419c0c1015f73fb5ea0293 \
|
||||
--hash=sha256:b18e0a9ef57d2b41f5c68beefa32317d286c3d6ac0484efd10d6e07491bb95dd \
|
||||
--hash=sha256:b4e248d1087abf9f4c10f3c398896c87ce82a9856494a7155823eb45a892395d \
|
||||
--hash=sha256:ba4e9e0ae13fc41c6b23299545e5ef73055213e466bd107953e4a013a5ddd7e3 \
|
||||
--hash=sha256:c6332685306b6417a91b1ff9fae889b3ba65c2292d64bd9245c093b1b284809d \
|
||||
--hash=sha256:d5ff0621c88ce83a28a10d2ce719b2ee85635e85c515f12bac99a95306da4b2e \
|
||||
--hash=sha256:d9efd8b7a3ef378dd61a1e77367f1924375befc2eba06168b6ebfa903a5e59ca \
|
||||
--hash=sha256:df5169c4396adc04f9b0a05f13c074df878b6052430e03f50e68adf3a57aa28d \
|
||||
--hash=sha256:ebb253464a5d0482b191274f1c8bf00e33f7e0b9c66405fbffc61ed2c839c775 \
|
||||
--hash=sha256:ec80dc47f54e6e9a78181ce05feb71a0353854cc26999db963695f950b5fb375 \
|
||||
--hash=sha256:f032b34669220030f905152045dfa27741ce1a6db3324a5bc0b96b6c7420c87b \
|
||||
--hash=sha256:f60567825f791c6f8a592f3c6e3bd93dd2934e3f9dac189308426bd76b00ef3b \
|
||||
--hash=sha256:f803eaa94c2fcda012c047e62bc7a51b0bdabda1cad7a92a522694ea2d76e49f
|
||||
# via
|
||||
# -r requirements.in
|
||||
# pynacl
|
||||
chardet==4.0.0 \
|
||||
--hash=sha256:0d6f53a15db4120f2b08c94f11e7d93d2c911ee118b6b30a04ec3ee8310179fa \
|
||||
--hash=sha256:f864054d66fd9118f2e67044ac8981a54775ec5b67aed0441892edb553d21da5
|
||||
# via requests
|
||||
click==7.1.2 \
|
||||
--hash=sha256:d2b5255c7c6349bc1bd1e59e08cd12acbbd63ce649f2588755783aa94dfb6b1a \
|
||||
--hash=sha256:dacca89f4bfadd5de3d7489b7c8a566eee0d3676333fbb50030263894c38c0dc
|
||||
# via flask
|
||||
deadsimplekv==0.3.2 \
|
||||
--hash=sha256:a725f4a9d1156ebb66b7535ac150006881e0365b715e34e3709214827b8b0c4c \
|
||||
--hash=sha256:df00262d26c3dcfecb710425a7413059480d8cf026216042d7cbffb8514818b2
|
||||
# via -r requirements.in
|
||||
filenuke==0.0.0 \
|
||||
--hash=sha256:147011c0125121469cae0a8a7f4df399f470e54aa29a08f2d2c099bf0118dcee \
|
||||
--hash=sha256:c55535dcecfdb27c5f4ce664d46e115950b5429763b5db75c198053646177f8f
|
||||
# via -r requirements.in
|
||||
flask==1.1.2 \
|
||||
--hash=sha256:4efa1ae2d7c9865af48986de8aeb8504bf32c7f3d6fdc9353d34b21f4b127060 \
|
||||
--hash=sha256:8a4fdd8936eba2512e9c85df320a37e694c93945b33ef33c89946a340a238557
|
||||
# via -r requirements.in
|
||||
gevent==20.9.0 \
|
||||
--hash=sha256:10110d4881aec04f218c316cb796b18c8b2cac67ae0eb5b0c5780056757268a2 \
|
||||
--hash=sha256:1628a403fc9c3ea9b35924638a4d4fbe236f60ecdf4e22ed133fbbaf0bc7cb6b \
|
||||
--hash=sha256:1cfa3674866294623e324fa5b76eba7b96744d1956a605cfe24d26c5cd890f91 \
|
||||
--hash=sha256:2269574444113cb4ca1c1808ab9460a87fe25e1c34a6e36d975d4af46e4afff9 \
|
||||
--hash=sha256:283a021a2e14adfad718346f18982b80569d9c3a59e97cfae1b7d4c5b017941a \
|
||||
--hash=sha256:2aa70726ad1883fe7c17774e5ccc91ac6e30334efa29bafb9b8fe8ca6091b219 \
|
||||
--hash=sha256:315a63a35068183dfb9bc0331c7bb3c265ee7db8a11797cbe98dadbdb45b5d35 \
|
||||
--hash=sha256:324808a8558c733f7a9734525483795d52ca3bbd5662b24b361d81c075414b1f \
|
||||
--hash=sha256:33a63f230755c6813fca39d9cea2a8894df32df2ee58fd69d8bf8fcc1d8e018e \
|
||||
--hash=sha256:5f6d48051d336561ec08995431ee4d265ac723a64bba99cc58c3eb1a4d4f5c8d \
|
||||
--hash=sha256:8d338cd6d040fe2607e5305dd7991b5960b3780ae01f804c2ac5760d31d3b2c6 \
|
||||
--hash=sha256:906175e3fb25f377a0b581e79d3ed5a7d925c136ff92fd022bb3013e25f5f3a9 \
|
||||
--hash=sha256:93980e51dd2e5f81899d644a0b6ef4a73008c679fcedd50e3b21cc3451ba2424 \
|
||||
--hash=sha256:9bb477f514cf39dc20651b479bf1ad4f38b9a679be2bfa3e162ec0c3785dfa2a \
|
||||
--hash=sha256:a8733a01974433d91308f8c44fa6cc13428b15bb39d46540657e260ff8852cb1 \
|
||||
--hash=sha256:adbb267067f56696b2babced3d0856aa39dcf14b8ccd2dffa1fab587b00c6f80 \
|
||||
--hash=sha256:afc177c37de41ce9c27d351ac84cbaf34407effcab5d6641645838f39d365be1 \
|
||||
--hash=sha256:b07fcbca3e819296979d82fac3d8b44f0d5ced57b9a04dffcfd194da99c8eb2d \
|
||||
--hash=sha256:b2948566003a1030e47507755fe1f446995e8671c0c67571091539e01faf94cc \
|
||||
--hash=sha256:db208e74a32cff7f55f5aa1ba5d7d1c1a086a6325c8702ae78a5c741155552ff \
|
||||
--hash=sha256:dd4c6b2f540b25c3d0f277a725bc1a900ce30a681b90a081216e31f814be453b \
|
||||
--hash=sha256:e11de4b4d107ca2f35000eb08e9c4c4621c153103b400f48a9ea95b96d8c7e0b \
|
||||
--hash=sha256:eba19bae532d0c48d489fa16815b242ce074b1f4b63e8a8e663232cbe311ead9 \
|
||||
--hash=sha256:fb33dc1ab27557bccd64ad4bf81e68c8b0d780fe937b1e2c0814558798137229
|
||||
# via -r requirements.in
|
||||
greenlet==1.0.0 \
|
||||
--hash=sha256:0a77691f0080c9da8dfc81e23f4e3cffa5accf0f5b56478951016d7cfead9196 \
|
||||
--hash=sha256:0ddd77586553e3daf439aa88b6642c5f252f7ef79a39271c25b1d4bf1b7cbb85 \
|
||||
--hash=sha256:111cfd92d78f2af0bc7317452bd93a477128af6327332ebf3c2be7df99566683 \
|
||||
--hash=sha256:122c63ba795fdba4fc19c744df6277d9cfd913ed53d1a286f12189a0265316dd \
|
||||
--hash=sha256:181300f826625b7fd1182205b830642926f52bd8cdb08b34574c9d5b2b1813f7 \
|
||||
--hash=sha256:1a1ada42a1fd2607d232ae11a7b3195735edaa49ea787a6d9e6a53afaf6f3476 \
|
||||
--hash=sha256:1bb80c71de788b36cefb0c3bb6bfab306ba75073dbde2829c858dc3ad70f867c \
|
||||
--hash=sha256:1d1d4473ecb1c1d31ce8fd8d91e4da1b1f64d425c1dc965edc4ed2a63cfa67b2 \
|
||||
--hash=sha256:292e801fcb3a0b3a12d8c603c7cf340659ea27fd73c98683e75800d9fd8f704c \
|
||||
--hash=sha256:2c65320774a8cd5fdb6e117c13afa91c4707548282464a18cf80243cf976b3e6 \
|
||||
--hash=sha256:4365eccd68e72564c776418c53ce3c5af402bc526fe0653722bc89efd85bf12d \
|
||||
--hash=sha256:5352c15c1d91d22902582e891f27728d8dac3bd5e0ee565b6a9f575355e6d92f \
|
||||
--hash=sha256:58ca0f078d1c135ecf1879d50711f925ee238fe773dfe44e206d7d126f5bc664 \
|
||||
--hash=sha256:5d4030b04061fdf4cbc446008e238e44936d77a04b2b32f804688ad64197953c \
|
||||
--hash=sha256:5d69bbd9547d3bc49f8a545db7a0bd69f407badd2ff0f6e1a163680b5841d2b0 \
|
||||
--hash=sha256:5f297cb343114b33a13755032ecf7109b07b9a0020e841d1c3cedff6602cc139 \
|
||||
--hash=sha256:62afad6e5fd70f34d773ffcbb7c22657e1d46d7fd7c95a43361de979f0a45aef \
|
||||
--hash=sha256:647ba1df86d025f5a34043451d7c4a9f05f240bee06277a524daad11f997d1e7 \
|
||||
--hash=sha256:719e169c79255816cdcf6dccd9ed2d089a72a9f6c42273aae12d55e8d35bdcf8 \
|
||||
--hash=sha256:7cd5a237f241f2764324396e06298b5dee0df580cf06ef4ada0ff9bff851286c \
|
||||
--hash=sha256:875d4c60a6299f55df1c3bb870ebe6dcb7db28c165ab9ea6cdc5d5af36bb33ce \
|
||||
--hash=sha256:90b6a25841488cf2cb1c8623a53e6879573010a669455046df5f029d93db51b7 \
|
||||
--hash=sha256:94620ed996a7632723a424bccb84b07e7b861ab7bb06a5aeb041c111dd723d36 \
|
||||
--hash=sha256:b5f1b333015d53d4b381745f5de842f19fe59728b65f0fbb662dafbe2018c3a5 \
|
||||
--hash=sha256:c5b22b31c947ad8b6964d4ed66776bcae986f73669ba50620162ba7c832a6b6a \
|
||||
--hash=sha256:c93d1a71c3fe222308939b2e516c07f35a849c5047f0197442a4d6fbcb4128ee \
|
||||
--hash=sha256:cdb90267650c1edb54459cdb51dab865f6c6594c3a47ebd441bc493360c7af70 \
|
||||
--hash=sha256:cfd06e0f0cc8db2a854137bd79154b61ecd940dce96fad0cba23fe31de0b793c \
|
||||
--hash=sha256:d3789c1c394944084b5e57c192889985a9f23bd985f6d15728c745d380318128 \
|
||||
--hash=sha256:da7d09ad0f24270b20f77d56934e196e982af0d0a2446120cb772be4e060e1a2 \
|
||||
--hash=sha256:df3e83323268594fa9755480a442cabfe8d82b21aba815a71acf1bb6c1776218 \
|
||||
--hash=sha256:df8053867c831b2643b2c489fe1d62049a98566b1646b194cc815f13e27b90df \
|
||||
--hash=sha256:e1128e022d8dce375362e063754e129750323b67454cac5600008aad9f54139e \
|
||||
--hash=sha256:e6e9fdaf6c90d02b95e6b0709aeb1aba5affbbb9ccaea5502f8638e4323206be \
|
||||
--hash=sha256:eac8803c9ad1817ce3d8d15d1bb82c2da3feda6bee1153eec5c58fa6e5d3f770 \
|
||||
--hash=sha256:eb333b90036358a0e2c57373f72e7648d7207b76ef0bd00a4f7daad1f79f5203 \
|
||||
--hash=sha256:ed1d1351f05e795a527abc04a0d82e9aecd3bdf9f46662c36ff47b0b00ecaf06 \
|
||||
--hash=sha256:f3dc68272990849132d6698f7dc6df2ab62a88b0d36e54702a8fd16c0490e44f \
|
||||
--hash=sha256:f59eded163d9752fd49978e0bab7a1ff21b1b8d25c05f0995d140cc08ac83379 \
|
||||
--hash=sha256:f5e2d36c86c7b03c94b8459c3bd2c9fe2c7dab4b258b8885617d44a22e453fb7 \
|
||||
--hash=sha256:f6f65bf54215e4ebf6b01e4bb94c49180a589573df643735107056f7a910275b \
|
||||
--hash=sha256:f8450d5ef759dbe59f84f2c9f77491bb3d3c44bc1a573746daf086e70b14c243 \
|
||||
--hash=sha256:f97d83049715fd9dec7911860ecf0e17b48d8725de01e45de07d8ac0bd5bc378
|
||||
# via gevent
|
||||
idna==2.10 \
|
||||
--hash=sha256:b307872f855b18632ce0c21c5e45be78c0ea7ae4c15c828c20788b26921eb3f6 \
|
||||
--hash=sha256:b97d804b1e9b523befed77c48dacec60e6dcb0b5391d57af6a65a312a90648c0
|
||||
# via requests
|
||||
itsdangerous==1.1.0 \
|
||||
--hash=sha256:321b033d07f2a4136d3ec762eac9f16a10ccd60f53c0c91af90217ace7ba1f19 \
|
||||
--hash=sha256:b12271b2047cb23eeb98c8b5622e2e5c5e9abd9784a153e9d8ef9cb4dd09d749
|
||||
# via flask
|
||||
jinja2==2.11.2 \
|
||||
--hash=sha256:89aab215427ef59c34ad58735269eb58b1a5808103067f7bb9d5836c651b3bb0 \
|
||||
--hash=sha256:f0a4641d3cf955324a89c04f3d94663aa4d638abe8f733ecd3582848e1c37035
|
||||
# via flask
|
||||
markupsafe==1.1.1 \
|
||||
--hash=sha256:00bc623926325b26bb9605ae9eae8a215691f33cae5df11ca5424f06f2d1f473 \
|
||||
--hash=sha256:09027a7803a62ca78792ad89403b1b7a73a01c8cb65909cd876f7fcebd79b161 \
|
||||
--hash=sha256:09c4b7f37d6c648cb13f9230d847adf22f8171b1ccc4d5682398e77f40309235 \
|
||||
--hash=sha256:1027c282dad077d0bae18be6794e6b6b8c91d58ed8a8d89a89d59693b9131db5 \
|
||||
--hash=sha256:13d3144e1e340870b25e7b10b98d779608c02016d5184cfb9927a9f10c689f42 \
|
||||
--hash=sha256:24982cc2533820871eba85ba648cd53d8623687ff11cbb805be4ff7b4c971aff \
|
||||
--hash=sha256:29872e92839765e546828bb7754a68c418d927cd064fd4708fab9fe9c8bb116b \
|
||||
--hash=sha256:43a55c2930bbc139570ac2452adf3d70cdbb3cfe5912c71cdce1c2c6bbd9c5d1 \
|
||||
--hash=sha256:46c99d2de99945ec5cb54f23c8cd5689f6d7177305ebff350a58ce5f8de1669e \
|
||||
--hash=sha256:500d4957e52ddc3351cabf489e79c91c17f6e0899158447047588650b5e69183 \
|
||||
--hash=sha256:535f6fc4d397c1563d08b88e485c3496cf5784e927af890fb3c3aac7f933ec66 \
|
||||
--hash=sha256:596510de112c685489095da617b5bcbbac7dd6384aeebeda4df6025d0256a81b \
|
||||
--hash=sha256:62fe6c95e3ec8a7fad637b7f3d372c15ec1caa01ab47926cfdf7a75b40e0eac1 \
|
||||
--hash=sha256:6788b695d50a51edb699cb55e35487e430fa21f1ed838122d722e0ff0ac5ba15 \
|
||||
--hash=sha256:6dd73240d2af64df90aa7c4e7481e23825ea70af4b4922f8ede5b9e35f78a3b1 \
|
||||
--hash=sha256:717ba8fe3ae9cc0006d7c451f0bb265ee07739daf76355d06366154ee68d221e \
|
||||
--hash=sha256:79855e1c5b8da654cf486b830bd42c06e8780cea587384cf6545b7d9ac013a0b \
|
||||
--hash=sha256:7c1699dfe0cf8ff607dbdcc1e9b9af1755371f92a68f706051cc8c37d447c905 \
|
||||
--hash=sha256:88e5fcfb52ee7b911e8bb6d6aa2fd21fbecc674eadd44118a9cc3863f938e735 \
|
||||
--hash=sha256:8defac2f2ccd6805ebf65f5eeb132adcf2ab57aa11fdf4c0dd5169a004710e7d \
|
||||
--hash=sha256:98c7086708b163d425c67c7a91bad6e466bb99d797aa64f965e9d25c12111a5e \
|
||||
--hash=sha256:9add70b36c5666a2ed02b43b335fe19002ee5235efd4b8a89bfcf9005bebac0d \
|
||||
--hash=sha256:9bf40443012702a1d2070043cb6291650a0841ece432556f784f004937f0f32c \
|
||||
--hash=sha256:ade5e387d2ad0d7ebf59146cc00c8044acbd863725f887353a10df825fc8ae21 \
|
||||
--hash=sha256:b00c1de48212e4cc9603895652c5c410df699856a2853135b3967591e4beebc2 \
|
||||
--hash=sha256:b1282f8c00509d99fef04d8ba936b156d419be841854fe901d8ae224c59f0be5 \
|
||||
--hash=sha256:b2051432115498d3562c084a49bba65d97cf251f5a331c64a12ee7e04dacc51b \
|
||||
--hash=sha256:ba59edeaa2fc6114428f1637ffff42da1e311e29382d81b339c1817d37ec93c6 \
|
||||
--hash=sha256:c8716a48d94b06bb3b2524c2b77e055fb313aeb4ea620c8dd03a105574ba704f \
|
||||
--hash=sha256:cd5df75523866410809ca100dc9681e301e3c27567cf498077e8551b6d20e42f \
|
||||
--hash=sha256:cdb132fc825c38e1aeec2c8aa9338310d29d337bebbd7baa06889d09a60a1fa2 \
|
||||
--hash=sha256:e249096428b3ae81b08327a63a485ad0878de3fb939049038579ac0ef61e17e7 \
|
||||
--hash=sha256:e8313f01ba26fbbe36c7be1966a7b7424942f670f38e666995b88d012765b9be
|
||||
# via jinja2
|
||||
niceware==0.2.1 \
|
||||
--hash=sha256:0f8b192f2a1e800e068474f6e208be9c7e2857664b33a96f4045340de4e5c69c \
|
||||
--hash=sha256:cf2dc0e1567d36d067c61b32fed0f1b9c4534ed511f9eeead4ba548d03b5c9eb
|
||||
# via -r requirements.in
|
||||
psutil==5.8.0 \
|
||||
--hash=sha256:0066a82f7b1b37d334e68697faba68e5ad5e858279fd6351c8ca6024e8d6ba64 \
|
||||
--hash=sha256:02b8292609b1f7fcb34173b25e48d0da8667bc85f81d7476584d889c6e0f2131 \
|
||||
--hash=sha256:0ae6f386d8d297177fd288be6e8d1afc05966878704dad9847719650e44fc49c \
|
||||
--hash=sha256:0c9ccb99ab76025f2f0bbecf341d4656e9c1351db8cc8a03ccd62e318ab4b5c6 \
|
||||
--hash=sha256:0dd4465a039d343925cdc29023bb6960ccf4e74a65ad53e768403746a9207023 \
|
||||
--hash=sha256:12d844996d6c2b1d3881cfa6fa201fd635971869a9da945cf6756105af73d2df \
|
||||
--hash=sha256:1bff0d07e76114ec24ee32e7f7f8d0c4b0514b3fae93e3d2aaafd65d22502394 \
|
||||
--hash=sha256:245b5509968ac0bd179287d91210cd3f37add77dad385ef238b275bad35fa1c4 \
|
||||
--hash=sha256:28ff7c95293ae74bf1ca1a79e8805fcde005c18a122ca983abf676ea3466362b \
|
||||
--hash=sha256:36b3b6c9e2a34b7d7fbae330a85bf72c30b1c827a4366a07443fc4b6270449e2 \
|
||||
--hash=sha256:52de075468cd394ac98c66f9ca33b2f54ae1d9bff1ef6b67a212ee8f639ec06d \
|
||||
--hash=sha256:5da29e394bdedd9144c7331192e20c1f79283fb03b06e6abd3a8ae45ffecee65 \
|
||||
--hash=sha256:61f05864b42fedc0771d6d8e49c35f07efd209ade09a5afe6a5059e7bb7bf83d \
|
||||
--hash=sha256:6223d07a1ae93f86451d0198a0c361032c4c93ebd4bf6d25e2fb3edfad9571ef \
|
||||
--hash=sha256:6323d5d845c2785efb20aded4726636546b26d3b577aded22492908f7c1bdda7 \
|
||||
--hash=sha256:6ffe81843131ee0ffa02c317186ed1e759a145267d54fdef1bc4ea5f5931ab60 \
|
||||
--hash=sha256:74f2d0be88db96ada78756cb3a3e1b107ce8ab79f65aa885f76d7664e56928f6 \
|
||||
--hash=sha256:74fb2557d1430fff18ff0d72613c5ca30c45cdbfcddd6a5773e9fc1fe9364be8 \
|
||||
--hash=sha256:90d4091c2d30ddd0a03e0b97e6a33a48628469b99585e2ad6bf21f17423b112b \
|
||||
--hash=sha256:90f31c34d25b1b3ed6c40cdd34ff122b1887a825297c017e4cbd6796dd8b672d \
|
||||
--hash=sha256:99de3e8739258b3c3e8669cb9757c9a861b2a25ad0955f8e53ac662d66de61ac \
|
||||
--hash=sha256:c6a5fd10ce6b6344e616cf01cc5b849fa8103fbb5ba507b6b2dee4c11e84c935 \
|
||||
--hash=sha256:ce8b867423291cb65cfc6d9c4955ee9bfc1e21fe03bb50e177f2b957f1c2469d \
|
||||
--hash=sha256:d225cd8319aa1d3c85bf195c4e07d17d3cd68636b8fc97e6cf198f782f99af28 \
|
||||
--hash=sha256:ea313bb02e5e25224e518e4352af4bf5e062755160f77e4b1767dd5ccb65f876 \
|
||||
--hash=sha256:ea372bcc129394485824ae3e3ddabe67dc0b118d262c568b4d2602a7070afdb0 \
|
||||
--hash=sha256:f4634b033faf0d968bb9220dd1c793b897ab7f1189956e1aa9eae752527127d3 \
|
||||
--hash=sha256:fcc01e900c1d7bee2a37e5d6e4f9194760a93597c97fee89c4ae51701de03563
|
||||
# via -r requirements.in
|
||||
pycparser==2.20 \
|
||||
--hash=sha256:2d475327684562c3a96cc71adf7dc8c4f0565175cf86b6d7a404ff4c771f15f0 \
|
||||
--hash=sha256:7582ad22678f0fcd81102833f60ef8d0e57288b6b5fb00323d101be910e35705
|
||||
# via cffi
|
||||
pynacl==1.4.0 \
|
||||
--hash=sha256:06cbb4d9b2c4bd3c8dc0d267416aaed79906e7b33f114ddbf0911969794b1cc4 \
|
||||
--hash=sha256:11335f09060af52c97137d4ac54285bcb7df0cef29014a1a4efe64ac065434c4 \
|
||||
--hash=sha256:2fe0fc5a2480361dcaf4e6e7cea00e078fcda07ba45f811b167e3f99e8cff574 \
|
||||
--hash=sha256:30f9b96db44e09b3304f9ea95079b1b7316b2b4f3744fe3aaecccd95d547063d \
|
||||
--hash=sha256:4e10569f8cbed81cb7526ae137049759d2a8d57726d52c1a000a3ce366779634 \
|
||||
--hash=sha256:511d269ee845037b95c9781aa702f90ccc36036f95d0f31373a6a79bd8242e25 \
|
||||
--hash=sha256:537a7ccbea22905a0ab36ea58577b39d1fa9b1884869d173b5cf111f006f689f \
|
||||
--hash=sha256:54e9a2c849c742006516ad56a88f5c74bf2ce92c9f67435187c3c5953b346505 \
|
||||
--hash=sha256:757250ddb3bff1eecd7e41e65f7f833a8405fede0194319f87899690624f2122 \
|
||||
--hash=sha256:7757ae33dae81c300487591c68790dfb5145c7d03324000433d9a2c141f82af7 \
|
||||
--hash=sha256:7c6092102219f59ff29788860ccb021e80fffd953920c4a8653889c029b2d420 \
|
||||
--hash=sha256:8122ba5f2a2169ca5da936b2e5a511740ffb73979381b4229d9188f6dcb22f1f \
|
||||
--hash=sha256:9c4a7ea4fb81536c1b1f5cc44d54a296f96ae78c1ebd2311bd0b60be45a48d96 \
|
||||
--hash=sha256:c914f78da4953b33d4685e3cdc7ce63401247a21425c16a39760e282075ac4a6 \
|
||||
--hash=sha256:cd401ccbc2a249a47a3a1724c2918fcd04be1f7b54eb2a5a71ff915db0ac51c6 \
|
||||
--hash=sha256:d452a6746f0a7e11121e64625109bc4468fc3100452817001dbe018bb8b08514 \
|
||||
--hash=sha256:ea6841bc3a76fa4942ce00f3bda7d436fda21e2d91602b9e21b7ca9ecab8f3ff \
|
||||
--hash=sha256:f8851ab9041756003119368c1e6cd0b9c631f46d686b3904b18c0139f4419f80
|
||||
# via -r requirements.in
|
||||
pysocks==1.7.1 \
|
||||
--hash=sha256:08e69f092cc6dbe92a0fdd16eeb9b9ffbc13cadfe5ca4c7bd92ffb078b293299 \
|
||||
--hash=sha256:2725bd0a9925919b9b51739eea5f9e2bae91e83288108a9ad338b2e3a4435ee5 \
|
||||
--hash=sha256:3f8804571ebe159c380ac6de37643bb4685970655d3bba243530d6558b799aa0
|
||||
# via -r requirements.in
|
||||
requests==2.25.1 \
|
||||
--hash=sha256:27973dd4a904a4f13b263a19c866c13b92a39ed1c964655f025f3f8d3d75b804 \
|
||||
--hash=sha256:c210084e36a42ae6b9219e00e48287def368a26d03a048ddad7bfee44f75871e
|
||||
# via
|
||||
# -r requirements.in
|
||||
# streamedrequests
|
||||
six==1.15.0 \
|
||||
--hash=sha256:30639c035cdb23534cd4aa2dd52c3bf48f06e5f4a941509c8bafd8ce11080259 \
|
||||
--hash=sha256:8b74bedcbbbaca38ff6d7491d76f2b06b3592611af620f8426e82dddb04a5ced
|
||||
# via pynacl
|
||||
stem==1.8.0 \
|
||||
--hash=sha256:a0b48ea6224e95f22aa34c0bc3415f0eb4667ddeae3dfb5e32a6920c185568c2
|
||||
# via -r requirements.in
|
||||
streamedrequests==1.0.3 \
|
||||
--hash=sha256:4388ffc0ee94dda719dafc4324b8ddd108cb2231ec59871de79e2592bf4eef0a \
|
||||
--hash=sha256:ee68417a1522e75c35b1b2d5f3b6f7e76a3a1a6c0ef5e0c573d08307910079d8
|
||||
# via -r requirements.in
|
||||
toomanyobjs==1.1.0 \
|
||||
--hash=sha256:99e27468f9dad19127be9e2fb086b42acd69aed9ad7e63cef74d6e4389be0534
|
||||
# via -r requirements.in
|
||||
ujson==4.0.1 \
|
||||
--hash=sha256:078808c385036cba73cad96f498310c61e9b5ae5ac9ea01e7c3996ece544b556 \
|
||||
--hash=sha256:0a2e1b211714eb1ec0772a013ec9967f8f95f21c84e8f46382e9f8a32ae781fe \
|
||||
--hash=sha256:0f412c3f59b1ab0f40018235224ca0cf29232d0201ff5085618565a8a9c810ed \
|
||||
--hash=sha256:26cf6241b36ff5ce4539ae687b6b02673109c5e3efc96148806a7873eaa229d3 \
|
||||
--hash=sha256:2b2d9264ac76aeb11f590f7a1ccff0689ba1313adacbb6d38d3b15f21a392897 \
|
||||
--hash=sha256:4f12b0b4e235b35d49f15227b0a827e614c52dda903c58a8f5523936c233dfc7 \
|
||||
--hash=sha256:4fe8c6112b732cba5a722f7cbe22f18d405f6f44415794a5b46473a477635233 \
|
||||
--hash=sha256:51480048373cf97a6b97fcd70c3586ca0a31f27e22ab680fb14c1f22bedbf743 \
|
||||
--hash=sha256:568bb3e7f035006147af4ce3a9ced7d126c92e1a8607c7b2266007b1c1162c53 \
|
||||
--hash=sha256:5fe1536465b1c86e32a47113abd3178001b7c2dcd61f95f336fe2febf4661e74 \
|
||||
--hash=sha256:71703a269f074ff65b9d7746662e4b3e76a4af443e532218af1e8ce15d9b1e7b \
|
||||
--hash=sha256:7a1545ac2476db4cc1f0f236603ccbb50991fc1bba480cda1bc06348cc2a2bf0 \
|
||||
--hash=sha256:a5200a68f1dcf3ce275e1cefbcfa3914b70c2b5e2f71c2e31556aa1f7244c845 \
|
||||
--hash=sha256:a618af22407baeadb3f046f81e7a5ee5e9f8b0b716d2b564f92276a54d26a823 \
|
||||
--hash=sha256:a79bca47eafb31c74b38e68623bc9b2bb930cb48fab1af31c8f2cb68cf473421 \
|
||||
--hash=sha256:b87379a3f8046d6d111762d81f3384bf38ab24b1535c841fe867a4a097d84523 \
|
||||
--hash=sha256:bd4c77aee3ffb920e2dbc21a9e0c7945a400557ce671cfd57dbd569f5ebc619d \
|
||||
--hash=sha256:c354c1617b0a4378b6279d0cd511b769500cf3fa7c42e8e004cbbbb6b4c2a875 \
|
||||
--hash=sha256:c604024bd853b5df6be7d933e934da8dd139e6159564db7c55b92a9937678093 \
|
||||
--hash=sha256:e7ab24942b2d57920d75b817b8eead293026db003247e26f99506bdad86c61b4 \
|
||||
--hash=sha256:f8a60928737a9a47e692fcd661ef2b5d75ba22c7c930025bd95e338f2a6e15bc
|
||||
# via -r requirements.in
|
||||
unpaddedbase32==0.2.0 \
|
||||
--hash=sha256:4aacee75f8fd6c8cf129842ecba45ca59c11bfb13dae19d86f32b48fa3715403 \
|
||||
--hash=sha256:b7b780c31d27d55e66abf6c221216a35690ee8892c2daacff7f2528e229bd9c3
|
||||
# via -r requirements.in
|
||||
urllib3==1.25.11 \
|
||||
--hash=sha256:8d7eaa5a82a1cac232164990f04874c594c9453ec55eef02eab885aa02fc17a2 \
|
||||
--hash=sha256:f5321fbe4bf3fefa0efd0bfe7fb14e90909eb62a48ccda331726b4319897dd5e
|
||||
# via
|
||||
# -r requirements.in
|
||||
# requests
|
||||
watchdog==1.0.2 \
|
||||
--hash=sha256:016b01495b9c55b5d4126ed8ae75d93ea0d99377084107c33162df52887cee18 \
|
||||
--hash=sha256:101532b8db506559e52a9b5d75a308729b3f68264d930670e6155c976d0e52a0 \
|
||||
--hash=sha256:27d9b4666938d5d40afdcdf2c751781e9ce36320788b70208d0f87f7401caf93 \
|
||||
--hash=sha256:2f1ade0d0802503fda4340374d333408831cff23da66d7e711e279ba50fe6c4a \
|
||||
--hash=sha256:376cbc2a35c0392b0fe7ff16fbc1b303fd99d4dd9911ab5581ee9d69adc88982 \
|
||||
--hash=sha256:57f05e55aa603c3b053eed7e679f0a83873c540255b88d58c6223c7493833bac \
|
||||
--hash=sha256:5f1f3b65142175366ba94c64d8d4c8f4015825e0beaacee1c301823266b47b9b \
|
||||
--hash=sha256:602dbd9498592eacc42e0632c19781c3df1728ef9cbab555fab6778effc29eeb \
|
||||
--hash=sha256:68744de2003a5ea2dfbb104f9a74192cf381334a9e2c0ed2bbe1581828d50b61 \
|
||||
--hash=sha256:85e6574395aa6c1e14e0f030d9d7f35c2340a6cf95d5671354ce876ac3ffdd4d \
|
||||
--hash=sha256:b1d723852ce90a14abf0ec0ca9e80689d9509ee4c9ee27163118d87b564a12ac \
|
||||
--hash=sha256:d948ad9ab9aba705f9836625b32e965b9ae607284811cd98334423f659ea537a \
|
||||
--hash=sha256:e2a531e71be7b5cc3499ae2d1494d51b6a26684bcc7c3146f63c810c00e8a3cc \
|
||||
--hash=sha256:e7c73edef48f4ceeebb987317a67e0080e5c9228601ff67b3c4062fa020403c7 \
|
||||
--hash=sha256:ee21aeebe6b3e51e4ba64564c94cee8dbe7438b9cb60f0bb350c4fa70d1b52c2 \
|
||||
--hash=sha256:f1d0e878fd69129d0d68b87cee5d9543f20d8018e82998efb79f7e412d42154a \
|
||||
--hash=sha256:f84146f7864339c8addf2c2b9903271df21d18d2c721e9a77f779493234a82b5
|
||||
# via -r requirements.in
|
||||
werkzeug==1.0.1 \
|
||||
--hash=sha256:2de2a5db0baeae7b2d2664949077c2ac63fbd16d98da0ff71837f7d1dea3fd43 \
|
||||
--hash=sha256:6c80b1e5ad3665290ea39320b91e1be1e0d5f60652b964a3070216de83d2e47c
|
||||
# via flask
|
||||
zope.event==4.5.0 \
|
||||
--hash=sha256:2666401939cdaa5f4e0c08cf7f20c9b21423b95e88f4675b1443973bdb080c42 \
|
||||
--hash=sha256:5e76517f5b9b119acf37ca8819781db6c16ea433f7e2062c4afc2b6fbedb1330
|
||||
# via gevent
|
||||
zope.interface==5.2.0 \
|
||||
--hash=sha256:05a97ba92c1c7c26f25c9f671aa1ef85ffead6cdad13770e5b689cf983adc7e1 \
|
||||
--hash=sha256:07d61722dd7d85547b7c6b0f5486b4338001fab349f2ac5cabc0b7182eb3425d \
|
||||
--hash=sha256:0a990dcc97806e5980bbb54b2e46b9cde9e48932d8e6984daf71ef1745516123 \
|
||||
--hash=sha256:150e8bcb7253a34a4535aeea3de36c0bb3b1a6a47a183a95d65a194b3e07f232 \
|
||||
--hash=sha256:1743bcfe45af8846b775086471c28258f4c6e9ee8ef37484de4495f15a98b549 \
|
||||
--hash=sha256:1b5f6c8fff4ed32aa2dd43e84061bc8346f32d3ba6ad6e58f088fe109608f102 \
|
||||
--hash=sha256:21e49123f375703cf824214939d39df0af62c47d122d955b2a8d9153ea08cfd5 \
|
||||
--hash=sha256:21f579134a47083ffb5ddd1307f0405c91aa8b61ad4be6fd5af0171474fe0c45 \
|
||||
--hash=sha256:27c267dc38a0f0079e96a2945ee65786d38ef111e413c702fbaaacbab6361d00 \
|
||||
--hash=sha256:299bde0ab9e5c4a92f01a152b7fbabb460f31343f1416f9b7b983167ab1e33bc \
|
||||
--hash=sha256:2ab88d8f228f803fcb8cb7d222c579d13dab2d3622c51e8cf321280da01102a7 \
|
||||
--hash=sha256:2ced4c35061eea623bc84c7711eedce8ecc3c2c51cd9c6afa6290df3bae9e104 \
|
||||
--hash=sha256:2dcab01c660983ba5e5a612e0c935141ccbee67d2e2e14b833e01c2354bd8034 \
|
||||
--hash=sha256:32546af61a9a9b141ca38d971aa6eb9800450fa6620ce6323cc30eec447861f3 \
|
||||
--hash=sha256:32b40a4c46d199827d79c86bb8cb88b1bbb764f127876f2cb6f3a47f63dbada3 \
|
||||
--hash=sha256:3cc94c69f6bd48ed86e8e24f358cb75095c8129827df1298518ab860115269a4 \
|
||||
--hash=sha256:42b278ac0989d6f5cf58d7e0828ea6b5951464e3cf2ff229dd09a96cb6ba0c86 \
|
||||
--hash=sha256:495b63fd0302f282ee6c1e6ea0f1c12cb3d1a49c8292d27287f01845ff252a96 \
|
||||
--hash=sha256:4af87cdc0d4b14e600e6d3d09793dce3b7171348a094ba818e2a68ae7ee67546 \
|
||||
--hash=sha256:4b94df9f2fdde7b9314321bab8448e6ad5a23b80542dcab53e329527d4099dcb \
|
||||
--hash=sha256:4c48ddb63e2b20fba4c6a2bf81b4d49e99b6d4587fb67a6cd33a2c1f003af3e3 \
|
||||
--hash=sha256:4df9afd17bd5477e9f8c8b6bb8507e18dd0f8b4efe73bb99729ff203279e9e3b \
|
||||
--hash=sha256:518950fe6a5d56f94ba125107895f938a4f34f704c658986eae8255edb41163b \
|
||||
--hash=sha256:538298e4e113ccb8b41658d5a4b605bebe75e46a30ceca22a5a289cf02c80bec \
|
||||
--hash=sha256:55465121e72e208a7b69b53de791402affe6165083b2ea71b892728bd19ba9ae \
|
||||
--hash=sha256:588384d70a0f19b47409cfdb10e0c27c20e4293b74fc891df3d8eb47782b8b3e \
|
||||
--hash=sha256:6278c080d4afffc9016e14325f8734456831124e8c12caa754fd544435c08386 \
|
||||
--hash=sha256:64ea6c221aeee4796860405e1aedec63424cda4202a7ad27a5066876db5b0fd2 \
|
||||
--hash=sha256:681dbb33e2b40262b33fd383bae63c36d33fd79fa1a8e4092945430744ffd34a \
|
||||
--hash=sha256:6936aa9da390402d646a32a6a38d5409c2d2afb2950f045a7d02ab25a4e7d08d \
|
||||
--hash=sha256:778d0ec38bbd288b150a3ae363c8ffd88d2207a756842495e9bffd8a8afbc89a \
|
||||
--hash=sha256:8251f06a77985a2729a8bdbefbae79ee78567dddc3acbd499b87e705ca59fe24 \
|
||||
--hash=sha256:83b4aa5344cce005a9cff5d0321b2e318e871cc1dfc793b66c32dd4f59e9770d \
|
||||
--hash=sha256:844fad925ac5c2ad4faaceb3b2520ad016b5280105c6e16e79838cf951903a7b \
|
||||
--hash=sha256:8ceb3667dd13b8133f2e4d637b5b00f240f066448e2aa89a41f4c2d78a26ce50 \
|
||||
--hash=sha256:92dc0fb79675882d0b6138be4bf0cec7ea7c7eede60aaca78303d8e8dbdaa523 \
|
||||
--hash=sha256:9789bd945e9f5bd026ed3f5b453d640befb8b1fc33a779c1fe8d3eb21fe3fb4a \
|
||||
--hash=sha256:a2b6d6eb693bc2fc6c484f2e5d93bd0b0da803fa77bf974f160533e555e4d095 \
|
||||
--hash=sha256:aab9f1e34d810feb00bf841993552b8fcc6ae71d473c505381627143d0018a6a \
|
||||
--hash=sha256:abb61afd84f23099ac6099d804cdba9bd3b902aaaded3ffff47e490b0a495520 \
|
||||
--hash=sha256:adf9ee115ae8ff8b6da4b854b4152f253b390ba64407a22d75456fe07dcbda65 \
|
||||
--hash=sha256:aedc6c672b351afe6dfe17ff83ee5e7eb6ed44718f879a9328a68bdb20b57e11 \
|
||||
--hash=sha256:b7a00ecb1434f8183395fac5366a21ee73d14900082ca37cf74993cf46baa56c \
|
||||
--hash=sha256:ba32f4a91c1cb7314c429b03afbf87b1fff4fb1c8db32260e7310104bd77f0c7 \
|
||||
--hash=sha256:cbd0f2cbd8689861209cd89141371d3a22a11613304d1f0736492590aa0ab332 \
|
||||
--hash=sha256:e4bc372b953bf6cec65a8d48482ba574f6e051621d157cf224227dbb55486b1e \
|
||||
--hash=sha256:eccac3d9aadc68e994b6d228cb0c8919fc47a5350d85a1b4d3d81d1e98baf40c \
|
||||
--hash=sha256:efd550b3da28195746bb43bd1d815058181a7ca6d9d6aa89dd37f5eefe2cacb7 \
|
||||
--hash=sha256:efef581c8ba4d990770875e1a2218e856849d32ada2680e53aebc5d154a17e20 \
|
||||
--hash=sha256:f057897711a630a0b7a6a03f1acf379b6ba25d37dc5dc217a97191984ba7f2fc \
|
||||
--hash=sha256:f37d45fab14ffef9d33a0dc3bc59ce0c5313e2253323312d47739192da94f5fd \
|
||||
--hash=sha256:f44906f70205d456d503105023041f1e63aece7623b31c390a0103db4de17537
|
||||
# via gevent
|
||||
|
||||
# WARNING: The following packages were not pinned, but pip requires them to be
|
||||
# pinned when the requirements file includes hashes. Consider using the --allow-unsafe flag.
|
||||
# setuptools
|
||||
|
@ -1,270 +0,0 @@
|
||||
#
|
||||
# This file is autogenerated by pip-compile with python 3.10
|
||||
# To update, run:
|
||||
#
|
||||
# pip-compile --generate-hashes --output-file=requirements-base-x86.txt requirements-base.in
|
||||
#
|
||||
cffi==1.15.1 \
|
||||
--hash=sha256:00a9ed42e88df81ffae7a8ab6d9356b371399b91dbdf0c3cb1e84c03a13aceb5 \
|
||||
--hash=sha256:03425bdae262c76aad70202debd780501fabeaca237cdfddc008987c0e0f59ef \
|
||||
--hash=sha256:04ed324bda3cda42b9b695d51bb7d54b680b9719cfab04227cdd1e04e5de3104 \
|
||||
--hash=sha256:0e2642fe3142e4cc4af0799748233ad6da94c62a8bec3a6648bf8ee68b1c7426 \
|
||||
--hash=sha256:173379135477dc8cac4bc58f45db08ab45d228b3363adb7af79436135d028405 \
|
||||
--hash=sha256:198caafb44239b60e252492445da556afafc7d1e3ab7a1fb3f0584ef6d742375 \
|
||||
--hash=sha256:1e74c6b51a9ed6589199c787bf5f9875612ca4a8a0785fb2d4a84429badaf22a \
|
||||
--hash=sha256:2012c72d854c2d03e45d06ae57f40d78e5770d252f195b93f581acf3ba44496e \
|
||||
--hash=sha256:21157295583fe8943475029ed5abdcf71eb3911894724e360acff1d61c1d54bc \
|
||||
--hash=sha256:2470043b93ff09bf8fb1d46d1cb756ce6132c54826661a32d4e4d132e1977adf \
|
||||
--hash=sha256:285d29981935eb726a4399badae8f0ffdff4f5050eaa6d0cfc3f64b857b77185 \
|
||||
--hash=sha256:30d78fbc8ebf9c92c9b7823ee18eb92f2e6ef79b45ac84db507f52fbe3ec4497 \
|
||||
--hash=sha256:320dab6e7cb2eacdf0e658569d2575c4dad258c0fcc794f46215e1e39f90f2c3 \
|
||||
--hash=sha256:33ab79603146aace82c2427da5ca6e58f2b3f2fb5da893ceac0c42218a40be35 \
|
||||
--hash=sha256:3548db281cd7d2561c9ad9984681c95f7b0e38881201e157833a2342c30d5e8c \
|
||||
--hash=sha256:3799aecf2e17cf585d977b780ce79ff0dc9b78d799fc694221ce814c2c19db83 \
|
||||
--hash=sha256:39d39875251ca8f612b6f33e6b1195af86d1b3e60086068be9cc053aa4376e21 \
|
||||
--hash=sha256:3b926aa83d1edb5aa5b427b4053dc420ec295a08e40911296b9eb1b6170f6cca \
|
||||
--hash=sha256:3bcde07039e586f91b45c88f8583ea7cf7a0770df3a1649627bf598332cb6984 \
|
||||
--hash=sha256:3d08afd128ddaa624a48cf2b859afef385b720bb4b43df214f85616922e6a5ac \
|
||||
--hash=sha256:3eb6971dcff08619f8d91607cfc726518b6fa2a9eba42856be181c6d0d9515fd \
|
||||
--hash=sha256:40f4774f5a9d4f5e344f31a32b5096977b5d48560c5592e2f3d2c4374bd543ee \
|
||||
--hash=sha256:4289fc34b2f5316fbb762d75362931e351941fa95fa18789191b33fc4cf9504a \
|
||||
--hash=sha256:470c103ae716238bbe698d67ad020e1db9d9dba34fa5a899b5e21577e6d52ed2 \
|
||||
--hash=sha256:4f2c9f67e9821cad2e5f480bc8d83b8742896f1242dba247911072d4fa94c192 \
|
||||
--hash=sha256:50a74364d85fd319352182ef59c5c790484a336f6db772c1a9231f1c3ed0cbd7 \
|
||||
--hash=sha256:54a2db7b78338edd780e7ef7f9f6c442500fb0d41a5a4ea24fff1c929d5af585 \
|
||||
--hash=sha256:5635bd9cb9731e6d4a1132a498dd34f764034a8ce60cef4f5319c0541159392f \
|
||||
--hash=sha256:59c0b02d0a6c384d453fece7566d1c7e6b7bae4fc5874ef2ef46d56776d61c9e \
|
||||
--hash=sha256:5d598b938678ebf3c67377cdd45e09d431369c3b1a5b331058c338e201f12b27 \
|
||||
--hash=sha256:5df2768244d19ab7f60546d0c7c63ce1581f7af8b5de3eb3004b9b6fc8a9f84b \
|
||||
--hash=sha256:5ef34d190326c3b1f822a5b7a45f6c4535e2f47ed06fec77d3d799c450b2651e \
|
||||
--hash=sha256:6975a3fac6bc83c4a65c9f9fcab9e47019a11d3d2cf7f3c0d03431bf145a941e \
|
||||
--hash=sha256:6c9a799e985904922a4d207a94eae35c78ebae90e128f0c4e521ce339396be9d \
|
||||
--hash=sha256:70df4e3b545a17496c9b3f41f5115e69a4f2e77e94e1d2a8e1070bc0c38c8a3c \
|
||||
--hash=sha256:7473e861101c9e72452f9bf8acb984947aa1661a7704553a9f6e4baa5ba64415 \
|
||||
--hash=sha256:8102eaf27e1e448db915d08afa8b41d6c7ca7a04b7d73af6514df10a3e74bd82 \
|
||||
--hash=sha256:87c450779d0914f2861b8526e035c5e6da0a3199d8f1add1a665e1cbc6fc6d02 \
|
||||
--hash=sha256:8b7ee99e510d7b66cdb6c593f21c043c248537a32e0bedf02e01e9553a172314 \
|
||||
--hash=sha256:91fc98adde3d7881af9b59ed0294046f3806221863722ba7d8d120c575314325 \
|
||||
--hash=sha256:94411f22c3985acaec6f83c6df553f2dbe17b698cc7f8ae751ff2237d96b9e3c \
|
||||
--hash=sha256:98d85c6a2bef81588d9227dde12db8a7f47f639f4a17c9ae08e773aa9c697bf3 \
|
||||
--hash=sha256:9ad5db27f9cabae298d151c85cf2bad1d359a1b9c686a275df03385758e2f914 \
|
||||
--hash=sha256:a0b71b1b8fbf2b96e41c4d990244165e2c9be83d54962a9a1d118fd8657d2045 \
|
||||
--hash=sha256:a0f100c8912c114ff53e1202d0078b425bee3649ae34d7b070e9697f93c5d52d \
|
||||
--hash=sha256:a591fe9e525846e4d154205572a029f653ada1a78b93697f3b5a8f1f2bc055b9 \
|
||||
--hash=sha256:a5c84c68147988265e60416b57fc83425a78058853509c1b0629c180094904a5 \
|
||||
--hash=sha256:a66d3508133af6e8548451b25058d5812812ec3798c886bf38ed24a98216fab2 \
|
||||
--hash=sha256:a8c4917bd7ad33e8eb21e9a5bbba979b49d9a97acb3a803092cbc1133e20343c \
|
||||
--hash=sha256:b3bbeb01c2b273cca1e1e0c5df57f12dce9a4dd331b4fa1635b8bec26350bde3 \
|
||||
--hash=sha256:cba9d6b9a7d64d4bd46167096fc9d2f835e25d7e4c121fb2ddfc6528fb0413b2 \
|
||||
--hash=sha256:cc4d65aeeaa04136a12677d3dd0b1c0c94dc43abac5860ab33cceb42b801c1e8 \
|
||||
--hash=sha256:ce4bcc037df4fc5e3d184794f27bdaab018943698f4ca31630bc7f84a7b69c6d \
|
||||
--hash=sha256:cec7d9412a9102bdc577382c3929b337320c4c4c4849f2c5cdd14d7368c5562d \
|
||||
--hash=sha256:d400bfb9a37b1351253cb402671cea7e89bdecc294e8016a707f6d1d8ac934f9 \
|
||||
--hash=sha256:d61f4695e6c866a23a21acab0509af1cdfd2c013cf256bbf5b6b5e2695827162 \
|
||||
--hash=sha256:db0fbb9c62743ce59a9ff687eb5f4afbe77e5e8403d6697f7446e5f609976f76 \
|
||||
--hash=sha256:dd86c085fae2efd48ac91dd7ccffcfc0571387fe1193d33b6394db7ef31fe2a4 \
|
||||
--hash=sha256:e00b098126fd45523dd056d2efba6c5a63b71ffe9f2bbe1a4fe1716e1d0c331e \
|
||||
--hash=sha256:e229a521186c75c8ad9490854fd8bbdd9a0c9aa3a524326b55be83b54d4e0ad9 \
|
||||
--hash=sha256:e263d77ee3dd201c3a142934a086a4450861778baaeeb45db4591ef65550b0a6 \
|
||||
--hash=sha256:ed9cb427ba5504c1dc15ede7d516b84757c3e3d7868ccc85121d9310d27eed0b \
|
||||
--hash=sha256:fa6693661a4c91757f4412306191b6dc88c1703f780c8234035eac011922bc01 \
|
||||
--hash=sha256:fcd131dd944808b5bdb38e6f5b53013c5aa4f334c5cad0c72742f6eba4b73db0
|
||||
# via pynacl
|
||||
filenuke==0.0.0 \
|
||||
--hash=sha256:147011c0125121469cae0a8a7f4df399f470e54aa29a08f2d2c099bf0118dcee \
|
||||
--hash=sha256:c55535dcecfdb27c5f4ce664d46e115950b5429763b5db75c198053646177f8f
|
||||
# via -r requirements-base.in
|
||||
kasten==3.0.0 \
|
||||
--hash=sha256:52894af46d6e1339f0d5fa8961892b292f99176848bce11877fe4a435b6782e5 \
|
||||
--hash=sha256:b22ebdc5f475c2ef9ab74abc36552add0b37732a7ce2be6bd7977ee41b2163b4
|
||||
# via onionrblocks
|
||||
mimcvdf==1.2.1 \
|
||||
--hash=sha256:7c837c46cfb9dce4ba895bc706a69646d4d5185c66aeaa333b5cfaa9a7d06dc4
|
||||
# via kasten
|
||||
msgpack==1.0.4 \
|
||||
--hash=sha256:002b5c72b6cd9b4bafd790f364b8480e859b4712e91f43014fe01e4f957b8467 \
|
||||
--hash=sha256:0a68d3ac0104e2d3510de90a1091720157c319ceeb90d74f7b5295a6bee51bae \
|
||||
--hash=sha256:0df96d6eaf45ceca04b3f3b4b111b86b33785683d682c655063ef8057d61fd92 \
|
||||
--hash=sha256:0dfe3947db5fb9ce52aaea6ca28112a170db9eae75adf9339a1aec434dc954ef \
|
||||
--hash=sha256:0e3590f9fb9f7fbc36df366267870e77269c03172d086fa76bb4eba8b2b46624 \
|
||||
--hash=sha256:11184bc7e56fd74c00ead4f9cc9a3091d62ecb96e97653add7a879a14b003227 \
|
||||
--hash=sha256:112b0f93202d7c0fef0b7810d465fde23c746a2d482e1e2de2aafd2ce1492c88 \
|
||||
--hash=sha256:1276e8f34e139aeff1c77a3cefb295598b504ac5314d32c8c3d54d24fadb94c9 \
|
||||
--hash=sha256:1576bd97527a93c44fa856770197dec00d223b0b9f36ef03f65bac60197cedf8 \
|
||||
--hash=sha256:1e91d641d2bfe91ba4c52039adc5bccf27c335356055825c7f88742c8bb900dd \
|
||||
--hash=sha256:26b8feaca40a90cbe031b03d82b2898bf560027160d3eae1423f4a67654ec5d6 \
|
||||
--hash=sha256:2999623886c5c02deefe156e8f869c3b0aaeba14bfc50aa2486a0415178fce55 \
|
||||
--hash=sha256:2a2df1b55a78eb5f5b7d2a4bb221cd8363913830145fad05374a80bf0877cb1e \
|
||||
--hash=sha256:2bb8cdf50dd623392fa75525cce44a65a12a00c98e1e37bf0fb08ddce2ff60d2 \
|
||||
--hash=sha256:2cc5ca2712ac0003bcb625c96368fd08a0f86bbc1a5578802512d87bc592fe44 \
|
||||
--hash=sha256:35bc0faa494b0f1d851fd29129b2575b2e26d41d177caacd4206d81502d4c6a6 \
|
||||
--hash=sha256:3c11a48cf5e59026ad7cb0dc29e29a01b5a66a3e333dc11c04f7e991fc5510a9 \
|
||||
--hash=sha256:449e57cc1ff18d3b444eb554e44613cffcccb32805d16726a5494038c3b93dab \
|
||||
--hash=sha256:462497af5fd4e0edbb1559c352ad84f6c577ffbbb708566a0abaaa84acd9f3ae \
|
||||
--hash=sha256:4733359808c56d5d7756628736061c432ded018e7a1dff2d35a02439043321aa \
|
||||
--hash=sha256:48f5d88c99f64c456413d74a975bd605a9b0526293218a3b77220a2c15458ba9 \
|
||||
--hash=sha256:49565b0e3d7896d9ea71d9095df15b7f75a035c49be733051c34762ca95bbf7e \
|
||||
--hash=sha256:4ab251d229d10498e9a2f3b1e68ef64cb393394ec477e3370c457f9430ce9250 \
|
||||
--hash=sha256:4d5834a2a48965a349da1c5a79760d94a1a0172fbb5ab6b5b33cbf8447e109ce \
|
||||
--hash=sha256:4dea20515f660aa6b7e964433b1808d098dcfcabbebeaaad240d11f909298075 \
|
||||
--hash=sha256:545e3cf0cf74f3e48b470f68ed19551ae6f9722814ea969305794645da091236 \
|
||||
--hash=sha256:63e29d6e8c9ca22b21846234913c3466b7e4ee6e422f205a2988083de3b08cae \
|
||||
--hash=sha256:6916c78f33602ecf0509cc40379271ba0f9ab572b066bd4bdafd7434dee4bc6e \
|
||||
--hash=sha256:6a4192b1ab40f8dca3f2877b70e63799d95c62c068c84dc028b40a6cb03ccd0f \
|
||||
--hash=sha256:6c9566f2c39ccced0a38d37c26cc3570983b97833c365a6044edef3574a00c08 \
|
||||
--hash=sha256:76ee788122de3a68a02ed6f3a16bbcd97bc7c2e39bd4d94be2f1821e7c4a64e6 \
|
||||
--hash=sha256:7760f85956c415578c17edb39eed99f9181a48375b0d4a94076d84148cf67b2d \
|
||||
--hash=sha256:77ccd2af37f3db0ea59fb280fa2165bf1b096510ba9fe0cc2bf8fa92a22fdb43 \
|
||||
--hash=sha256:81fc7ba725464651190b196f3cd848e8553d4d510114a954681fd0b9c479d7e1 \
|
||||
--hash=sha256:85f279d88d8e833ec015650fd15ae5eddce0791e1e8a59165318f371158efec6 \
|
||||
--hash=sha256:9667bdfdf523c40d2511f0e98a6c9d3603be6b371ae9a238b7ef2dc4e7a427b0 \
|
||||
--hash=sha256:a75dfb03f8b06f4ab093dafe3ddcc2d633259e6c3f74bb1b01996f5d8aa5868c \
|
||||
--hash=sha256:ac5bd7901487c4a1dd51a8c58f2632b15d838d07ceedaa5e4c080f7190925bff \
|
||||
--hash=sha256:aca0f1644d6b5a73eb3e74d4d64d5d8c6c3d577e753a04c9e9c87d07692c58db \
|
||||
--hash=sha256:b17be2478b622939e39b816e0aa8242611cc8d3583d1cd8ec31b249f04623243 \
|
||||
--hash=sha256:c1683841cd4fa45ac427c18854c3ec3cd9b681694caf5bff04edb9387602d661 \
|
||||
--hash=sha256:c23080fdeec4716aede32b4e0ef7e213c7b1093eede9ee010949f2a418ced6ba \
|
||||
--hash=sha256:d5b5b962221fa2c5d3a7f8133f9abffc114fe218eb4365e40f17732ade576c8e \
|
||||
--hash=sha256:d603de2b8d2ea3f3bcb2efe286849aa7a81531abc52d8454da12f46235092bcb \
|
||||
--hash=sha256:e83f80a7fec1a62cf4e6c9a660e39c7f878f603737a0cdac8c13131d11d97f52 \
|
||||
--hash=sha256:eb514ad14edf07a1dbe63761fd30f89ae79b42625731e1ccf5e1f1092950eaa6 \
|
||||
--hash=sha256:eba96145051ccec0ec86611fe9cf693ce55f2a3ce89c06ed307de0e085730ec1 \
|
||||
--hash=sha256:ed6f7b854a823ea44cf94919ba3f727e230da29feb4a99711433f25800cf747f \
|
||||
--hash=sha256:f0029245c51fd9473dc1aede1160b0a29f4a912e6b1dd353fa6d317085b219da \
|
||||
--hash=sha256:f5d869c18f030202eb412f08b28d2afeea553d6613aee89e200d7aca7ef01f5f \
|
||||
--hash=sha256:fb62ea4b62bfcb0b380d5680f9a4b3f9a2d166d9394e9bbd9666c0ee09a3645c \
|
||||
--hash=sha256:fcb8a47f43acc113e24e910399376f7277cf8508b27e5b88499f053de6b115a8
|
||||
# via kasten
|
||||
onionrblocks==7.0.0 \
|
||||
--hash=sha256:53e90964371076d9daf2ed0790b21f174ef3321f4f1808209cc6dd9b7ff6d8ff \
|
||||
--hash=sha256:54af28d0be856209525646c4ef9f977f95f0ae1329b2cc023b351317c9d0eef7
|
||||
# via -r requirements-base.in
|
||||
ordered-set==4.1.0 \
|
||||
--hash=sha256:046e1132c71fcf3330438a539928932caf51ddbc582496833e23de611de14562 \
|
||||
--hash=sha256:694a8e44c87657c59292ede72891eb91d34131f6531463aab3009191c77364a8
|
||||
# via -r requirements-base.in
|
||||
psutil==5.9.3 \
|
||||
--hash=sha256:07d880053c6461c9b89cd5d4808f3b8336665fa3acdefd6777662c5ed73a851a \
|
||||
--hash=sha256:12500d761ac091f2426567f19f95fd3f15a197d96befb44a5c1e3cbe6db5752c \
|
||||
--hash=sha256:1b540599481c73408f6b392cdffef5b01e8ff7a2ac8caae0a91b8222e88e8f1e \
|
||||
--hash=sha256:35feafe232d1aaf35d51bd42790cbccb882456f9f18cdc411532902370d660df \
|
||||
--hash=sha256:3a7826e68b0cf4ce2c1ee385d64eab7d70e3133171376cac53d7c1790357ec8f \
|
||||
--hash=sha256:46907fa62acaac364fff0b8a9da7b360265d217e4fdeaca0a2397a6883dffba2 \
|
||||
--hash=sha256:4bd4854f0c83aa84a5a40d3b5d0eb1f3c128f4146371e03baed4589fe4f3c931 \
|
||||
--hash=sha256:538fcf6ae856b5e12d13d7da25ad67f02113c96f5989e6ad44422cb5994ca7fc \
|
||||
--hash=sha256:547ebb02031fdada635452250ff39942db8310b5c4a8102dfe9384ee5791e650 \
|
||||
--hash=sha256:5e8b50241dd3c2ed498507f87a6602825073c07f3b7e9560c58411c14fe1e1c9 \
|
||||
--hash=sha256:5fa88e3d5d0b480602553d362c4b33a63e0c40bfea7312a7bf78799e01e0810b \
|
||||
--hash=sha256:68fa227c32240c52982cb931801c5707a7f96dd8927f9102d6c7771ea1ff5698 \
|
||||
--hash=sha256:6ced1ad823ecfa7d3ce26fe8aa4996e2e53fb49b7fed8ad81c80958501ec0619 \
|
||||
--hash=sha256:71b1206e7909792d16933a0d2c1c7f04ae196186c51ba8567abae1d041f06dcb \
|
||||
--hash=sha256:767ef4fa33acda16703725c0473a91e1832d296c37c63896c7153ba81698f1ab \
|
||||
--hash=sha256:7ccfcdfea4fc4b0a02ca2c31de7fcd186beb9cff8207800e14ab66f79c773af6 \
|
||||
--hash=sha256:7e4939ff75149b67aef77980409f156f0082fa36accc475d45c705bb00c6c16a \
|
||||
--hash=sha256:828c9dc9478b34ab96be75c81942d8df0c2bb49edbb481f597314d92b6441d89 \
|
||||
--hash=sha256:8a4e07611997acf178ad13b842377e3d8e9d0a5bac43ece9bfc22a96735d9a4f \
|
||||
--hash=sha256:941a6c2c591da455d760121b44097781bc970be40e0e43081b9139da485ad5b7 \
|
||||
--hash=sha256:9a4af6ed1094f867834f5f07acd1250605a0874169a5fcadbcec864aec2496a6 \
|
||||
--hash=sha256:9ec296f565191f89c48f33d9544d8d82b0d2af7dd7d2d4e6319f27a818f8d1cc \
|
||||
--hash=sha256:9ec95df684583b5596c82bb380c53a603bb051cf019d5c849c47e117c5064395 \
|
||||
--hash=sha256:a04a1836894c8279e5e0a0127c0db8e198ca133d28be8a2a72b4db16f6cf99c1 \
|
||||
--hash=sha256:a3d81165b8474087bb90ec4f333a638ccfd1d69d34a9b4a1a7eaac06648f9fbe \
|
||||
--hash=sha256:b4a247cd3feaae39bb6085fcebf35b3b8ecd9b022db796d89c8f05067ca28e71 \
|
||||
--hash=sha256:ba38cf9984d5462b506e239cf4bc24e84ead4b1d71a3be35e66dad0d13ded7c1 \
|
||||
--hash=sha256:beb57d8a1ca0ae0eb3d08ccaceb77e1a6d93606f0e1754f0d60a6ebd5c288837 \
|
||||
--hash=sha256:d266cd05bd4a95ca1c2b9b5aac50d249cf7c94a542f47e0b22928ddf8b80d1ef \
|
||||
--hash=sha256:d8c3cc6bb76492133474e130a12351a325336c01c96a24aae731abf5a47fe088 \
|
||||
--hash=sha256:db8e62016add2235cc87fb7ea000ede9e4ca0aa1f221b40cef049d02d5d2593d \
|
||||
--hash=sha256:e7507f6c7b0262d3e7b0eeda15045bf5881f4ada70473b87bc7b7c93b992a7d7 \
|
||||
--hash=sha256:ed15edb14f52925869250b1375f0ff58ca5c4fa8adefe4883cfb0737d32f5c02 \
|
||||
--hash=sha256:f57d63a2b5beaf797b87024d018772439f9d3103a395627b77d17a8d72009543 \
|
||||
--hash=sha256:fa5e32c7d9b60b2528108ade2929b115167fe98d59f89555574715054f50fa31 \
|
||||
--hash=sha256:fe79b4ad4836e3da6c4650cb85a663b3a51aef22e1a829c384e18fae87e5e727
|
||||
# via -r requirements-base.in
|
||||
pycparser==2.21 \
|
||||
--hash=sha256:8ee45429555515e1f6b185e78100aea234072576aa43ab53aefcae078162fca9 \
|
||||
--hash=sha256:e644fdec12f7872f86c58ff790da456218b10f863970249516d60a5eaca77206
|
||||
# via cffi
|
||||
pynacl==1.5.0 \
|
||||
--hash=sha256:06b8f6fa7f5de8d5d2f7573fe8c863c051225a27b61e6860fd047b1775807858 \
|
||||
--hash=sha256:0c84947a22519e013607c9be43706dd42513f9e6ae5d39d3613ca1e142fba44d \
|
||||
--hash=sha256:20f42270d27e1b6a29f54032090b972d97f0a1b0948cc52392041ef7831fee93 \
|
||||
--hash=sha256:401002a4aaa07c9414132aaed7f6836ff98f59277a234704ff66878c2ee4a0d1 \
|
||||
--hash=sha256:52cb72a79269189d4e0dc537556f4740f7f0a9ec41c1322598799b0bdad4ef92 \
|
||||
--hash=sha256:61f642bf2378713e2c2e1de73444a3778e5f0a38be6fee0fe532fe30060282ff \
|
||||
--hash=sha256:8ac7448f09ab85811607bdd21ec2464495ac8b7c66d146bf545b0f08fb9220ba \
|
||||
--hash=sha256:a36d4a9dda1f19ce6e03c9a784a2921a4b726b02e1c736600ca9c22029474394 \
|
||||
--hash=sha256:a422368fc821589c228f4c49438a368831cb5bbc0eab5ebe1d7fac9dded6567b \
|
||||
--hash=sha256:e46dae94e34b085175f8abb3b0aaa7da40767865ac82c928eeb9e57e1ea8a543
|
||||
# via onionrblocks
|
||||
result==0.8.0 \
|
||||
--hash=sha256:c48c909e92181a075ba358228a3fe161e26d205dad416ad81f27f23515a5626d \
|
||||
--hash=sha256:d6a6258f32c057a4e0478999c6ce43dcadaf8ea435f58ac601ae2768f93ef243
|
||||
# via -r requirements-base.in
|
||||
ujson==5.5.0 \
|
||||
--hash=sha256:0762a4fdf86e01f3f8d8b6b7158d01fdd870799ff3f402b676e358fcd879e7eb \
|
||||
--hash=sha256:10095160dbe6bba8059ad6677a01da251431f4c68041bf796dcac0956b34f8f7 \
|
||||
--hash=sha256:1a485117f97312bef45f5d79d2ff97eff4da503b8a04f3691f59d31141686459 \
|
||||
--hash=sha256:1cef44ea4973344baed3d50a5da4a8843de3a6af7dea7fadf0a594e53ce5892f \
|
||||
--hash=sha256:1dc2f46c31ef22b0aaa28cd71be897bea271e700636658d573df9c43c49ebbd0 \
|
||||
--hash=sha256:21678d7e068707e4d54bdfeb8c250ebc548b51e499aed778b22112ca31a79669 \
|
||||
--hash=sha256:278aa9d7cb56435c96d19f5d702e026bcf69f824e24b41e9b52706abd3565837 \
|
||||
--hash=sha256:2ab011e3556a9a1d9461bd686870c527327765ed02fe53550531d6609a8a33ff \
|
||||
--hash=sha256:2d90414e3b4b44b39825049185959488e084ea7fcaf6124afd5c00893938b09d \
|
||||
--hash=sha256:2e506ecf89b6b9d304362ccef770831ec242a52c89dab1b4aabf1ab0eb1d5ed6 \
|
||||
--hash=sha256:33cd9084fefc74cbacf88c92fd260b61211e00bcde38d640c369e5dc34a2b4e1 \
|
||||
--hash=sha256:3b74467564814fbce322427a5664e6bcc7dae6dbc8acbef76300fe43ca4072ab \
|
||||
--hash=sha256:3f3f4240d99d55eb97cb012e9adf401f5ed9cd827af0341ac44603832202b0d2 \
|
||||
--hash=sha256:3fe1aea596f9539fc20cd9e52f098c842afc090168824fd4ca9744fe13151a03 \
|
||||
--hash=sha256:4a8cb3c8637006c5bd8237ebb5992a76ba06e39988ad5cff2096227443e8fd6a \
|
||||
--hash=sha256:4ef4ab8352861b99bd7fedb1fc6df3ea7f7d5216c789ba6d859e4ea06f1a4c45 \
|
||||
--hash=sha256:5035bb997d163f346c22abcec75190e7e756a5349e7c708bd3d5fd7066a9a854 \
|
||||
--hash=sha256:593a0f6fb0e186c5ba65465ed6f6215a30d1efa898c25e74de1c8577a1bff6d0 \
|
||||
--hash=sha256:59cdcd934385f36e8bd76aedc234371cc75c848d95bdce804ac8aa8744cfeffa \
|
||||
--hash=sha256:5a9b1320d8363a42d857fae8065a2174d38217cdd58cd8dc4f48d54e0591271e \
|
||||
--hash=sha256:5f9681ec4c60d0da590552427d770636d9079038c30b265f507ccde23caa7823 \
|
||||
--hash=sha256:5fd797a4837ba10671954e7c09010cec7aca67e09d193f4920a16beea5f66f65 \
|
||||
--hash=sha256:6019e3480d933d3698f2ecb4b46d64bfadd64e718f04fac36e681f3254b49a93 \
|
||||
--hash=sha256:603607f56a0ee84d9cd2c7e9b1d29b18a70684b94ee34f07b9ffe8dc9c8a9f81 \
|
||||
--hash=sha256:60a4b481978ea2aad8fe8af1ecc271624d01b3cf4b09e9b643dd2fe19c07634c \
|
||||
--hash=sha256:6b9812638d7aa8ecda2e8e1513fb4da999249603bffab7439a5f8f0bb362b0db \
|
||||
--hash=sha256:6c7ae6e0778ab9610f5e80e0595957d101ab8de18c32a8c053a19943ef4831d0 \
|
||||
--hash=sha256:6f83be8257b2f2dd6dea5ee62cd28db90584da7a7af1fba77a2102fc7943638a \
|
||||
--hash=sha256:701e81e047f5c0cffd4ac828efca68b0bd270c616654966a051e9a5f836b385e \
|
||||
--hash=sha256:703fd69d9cb21d6ec2086789df9be2cf8140a76ff127050c24007ea8940dcd3b \
|
||||
--hash=sha256:7471d4486f23518cff343f1eec6c68d1b977ed74c3e6cc3e1ac896b9b7d68645 \
|
||||
--hash=sha256:765d46f3d5e7a1d48075035e2d1a9164f683e3fccde834ca04602e6c588835bc \
|
||||
--hash=sha256:7a09d203983104918c62f2eef9406f24c355511f9217967df23e70fa7f5b54ff \
|
||||
--hash=sha256:7c20cc83b0df47129ec6ed8a47fa7dcfc309c5bad029464004162738502568bb \
|
||||
--hash=sha256:7d7cfac2547c93389fa303fc0c0eb6698825564e8389c41c9b60009c746207b6 \
|
||||
--hash=sha256:7d87c817b292efb748f1974f37e8bb8a8772ef92f05f84e507159360814bcc3f \
|
||||
--hash=sha256:8141f654432cf75144d6103bfac2286b8adf23467201590b173a74535d6be22d \
|
||||
--hash=sha256:849f2ff40264152f25589cb48ddb4a43d14db811f841ec73989bfc0c8c4853fa \
|
||||
--hash=sha256:880c84ce59f49776cf120f77e7ca04877c97c6887917078dbc369eb47004d7cf \
|
||||
--hash=sha256:94874584b733a18b310b0e954d53168e62cd4a0fd9db85b1903f0902a7eb33e8 \
|
||||
--hash=sha256:95603eff711b8f3b9596e1c961dbeb745a792ba1904141612f194e07edd71e5f \
|
||||
--hash=sha256:9585892091ae86045135d6a6129a644142d6a51b23e1428bb5de6d10bc0ce0c7 \
|
||||
--hash=sha256:977bf5be704a88d46bf5b228df8b44521b1f3119d741062191608b3a6a38f224 \
|
||||
--hash=sha256:9cdc46859024501c20ab74ad542cdf2f08b94b5ce384f2f569483fa3ed926d04 \
|
||||
--hash=sha256:a34a5f034b339f69ef7f6a134c22d04b92e07b6ddc1dd65382e7e4ec65d6437d \
|
||||
--hash=sha256:a655f7b755cfc5c07f2116b6dcf0ba148c89adef9a6d40c1b0f1fada878c4345 \
|
||||
--hash=sha256:a7d12f2d2df195c8c4e49d2cdbad640353a856c62ca2c624d8b47aa33b65a2a2 \
|
||||
--hash=sha256:abfe83e082c9208891e2158c1b5044a650ecec408b823bf6bf16cd7f8085cafa \
|
||||
--hash=sha256:b25077a971c7da47bd6846a912a747f6963776d90720c88603b1b55d81790780 \
|
||||
--hash=sha256:bf416a93e1331820c77e3429df26946dbd4fe105e9b487cd2d1b7298b75784a8 \
|
||||
--hash=sha256:c04ae27e076d81a3839047d8eed57c1e17e361640616fd520d752375e3ba8f0c \
|
||||
--hash=sha256:d5bea13c73f36c4346808df3fa806596163a7962b6d28001ca2a391cab856089 \
|
||||
--hash=sha256:d75bef34e69e7effb7b4849e3f830e3174d2cc6ec7273503fdde111c222dc9b3 \
|
||||
--hash=sha256:d93940664a5ccfd79f72dcb939b0c31a3479889f14f0eb95ec52976f8c0cae7d \
|
||||
--hash=sha256:d9c89c521dc90c7564358e525f849b93ad1d710553c1491f66b8cce8113bc901 \
|
||||
--hash=sha256:e0b36257dc90194784531c3b922d8d31fb2b4d8e5adfd27aff4eee7174176365 \
|
||||
--hash=sha256:e1135264bcd40965cd35b0869e36952f54825024befdc7a923df9a7d83cfd800 \
|
||||
--hash=sha256:e510d288e613d6927796dfb728e13e4530fc83b9ccac5888a21f7860486eab21 \
|
||||
--hash=sha256:ee9a2c9a4b2421e77f8fe33ed0621dea03c66c710707553020b1e32f3afb6240 \
|
||||
--hash=sha256:f19f11055ba2961eb39bdb1ff15763a53fca4fa0b5b624da3c7a528e83cdd09c \
|
||||
--hash=sha256:f26544bc10c83a2ff9aa2e093500c1b473f327faae31fb468d591e5823333376 \
|
||||
--hash=sha256:f4875cafc9a6482c04c7df52a725d1c41beb74913c0ff4ec8f189f1954a2afe9 \
|
||||
--hash=sha256:f5179088ef6487c475604b7898731a6ddeeada7702cfb2162155b016703a8475 \
|
||||
--hash=sha256:f63d1ae1ca17bb2c847e298c7bcf084a73d56d434b4c50509fb93a4b4300b0b2 \
|
||||
--hash=sha256:ff4928dc1e9704b567171c16787238201fdbf023665573c12c02146fe1e02eec
|
||||
# via -r requirements-base.in
|
@ -1,7 +0,0 @@
|
||||
psutil==5.9.3
|
||||
ujson==5.5.0
|
||||
ordered-set==4.1.0
|
||||
result==0.8.0
|
||||
# These two are also by Kevin
|
||||
filenuke==0.0.0
|
||||
onionrblocks==7.0.0
|
@ -1,2 +1,3 @@
|
||||
pip-tools==6.4.0
|
||||
pdoc3==0.9.2
|
||||
pip-tools==5.5.0
|
||||
helium==3.0.5
|
||||
|
@ -1,40 +1,73 @@
|
||||
#
|
||||
# This file is autogenerated by pip-compile with python 3.10
|
||||
# This file is autogenerated by pip-compile
|
||||
# To update, run:
|
||||
#
|
||||
# pip-compile --generate-hashes --output-file=requirements-dev.txt requirements-dev.in
|
||||
#
|
||||
click==7.0 \
|
||||
--hash=sha256:2335065e6395b9e67ca716de5f7526736bfa6ceead690adf616d925bdc622b13 \
|
||||
--hash=sha256:5b94b49521f6456670fdb30cd82a4eca9412788a93fa6dd6df72c94d5a8ff2d7
|
||||
--hash=sha256:5b94b49521f6456670fdb30cd82a4eca9412788a93fa6dd6df72c94d5a8ff2d7 \
|
||||
# via pip-tools
|
||||
helium==3.0.5 \
|
||||
--hash=sha256:74b074fbdc2ddc485a9e0e792b2d0ac3d52a8fcaf4a8ab855b690633590a0104
|
||||
--hash=sha256:74b074fbdc2ddc485a9e0e792b2d0ac3d52a8fcaf4a8ab855b690633590a0104 \
|
||||
# via -r requirements-dev.in
|
||||
pep517==0.12.0 \
|
||||
--hash=sha256:931378d93d11b298cf511dd634cf5ea4cb249a28ef84160b3247ee9afb4e8ab0 \
|
||||
--hash=sha256:dd884c326898e2c6e11f9e0b64940606a93eb10ea022a2e067959f3a110cf161
|
||||
# via pip-tools
|
||||
pip-tools==6.4.0 \
|
||||
--hash=sha256:65553a15b1ba34be5e43889345062e38fb9b219ffa23b084ca0d4c4039b6f53b \
|
||||
--hash=sha256:bb2c3272bc229b4a6d25230ebe255823aba1aa466a0d698c48ab7eb5ab7efdc9
|
||||
mako==1.1.1 \
|
||||
--hash=sha256:2984a6733e1d472796ceef37ad48c26f4a984bb18119bb2dbc37a44d8f6e75a4 \
|
||||
# via pdoc3
|
||||
markdown==3.1.1 \
|
||||
--hash=sha256:2e50876bcdd74517e7b71f3e7a76102050edec255b3983403f1a63e7c8a41e7a \
|
||||
--hash=sha256:56a46ac655704b91e5b7e6326ce43d5ef72411376588afa1dd90e881b83c7e8c \
|
||||
# via pdoc3
|
||||
markupsafe==1.1.1 \
|
||||
--hash=sha256:00bc623926325b26bb9605ae9eae8a215691f33cae5df11ca5424f06f2d1f473 \
|
||||
--hash=sha256:09027a7803a62ca78792ad89403b1b7a73a01c8cb65909cd876f7fcebd79b161 \
|
||||
--hash=sha256:09c4b7f37d6c648cb13f9230d847adf22f8171b1ccc4d5682398e77f40309235 \
|
||||
--hash=sha256:1027c282dad077d0bae18be6794e6b6b8c91d58ed8a8d89a89d59693b9131db5 \
|
||||
--hash=sha256:13d3144e1e340870b25e7b10b98d779608c02016d5184cfb9927a9f10c689f42 \
|
||||
--hash=sha256:24982cc2533820871eba85ba648cd53d8623687ff11cbb805be4ff7b4c971aff \
|
||||
--hash=sha256:29872e92839765e546828bb7754a68c418d927cd064fd4708fab9fe9c8bb116b \
|
||||
--hash=sha256:43a55c2930bbc139570ac2452adf3d70cdbb3cfe5912c71cdce1c2c6bbd9c5d1 \
|
||||
--hash=sha256:46c99d2de99945ec5cb54f23c8cd5689f6d7177305ebff350a58ce5f8de1669e \
|
||||
--hash=sha256:500d4957e52ddc3351cabf489e79c91c17f6e0899158447047588650b5e69183 \
|
||||
--hash=sha256:535f6fc4d397c1563d08b88e485c3496cf5784e927af890fb3c3aac7f933ec66 \
|
||||
--hash=sha256:596510de112c685489095da617b5bcbbac7dd6384aeebeda4df6025d0256a81b \
|
||||
--hash=sha256:62fe6c95e3ec8a7fad637b7f3d372c15ec1caa01ab47926cfdf7a75b40e0eac1 \
|
||||
--hash=sha256:6788b695d50a51edb699cb55e35487e430fa21f1ed838122d722e0ff0ac5ba15 \
|
||||
--hash=sha256:6dd73240d2af64df90aa7c4e7481e23825ea70af4b4922f8ede5b9e35f78a3b1 \
|
||||
--hash=sha256:717ba8fe3ae9cc0006d7c451f0bb265ee07739daf76355d06366154ee68d221e \
|
||||
--hash=sha256:79855e1c5b8da654cf486b830bd42c06e8780cea587384cf6545b7d9ac013a0b \
|
||||
--hash=sha256:7c1699dfe0cf8ff607dbdcc1e9b9af1755371f92a68f706051cc8c37d447c905 \
|
||||
--hash=sha256:88e5fcfb52ee7b911e8bb6d6aa2fd21fbecc674eadd44118a9cc3863f938e735 \
|
||||
--hash=sha256:8defac2f2ccd6805ebf65f5eeb132adcf2ab57aa11fdf4c0dd5169a004710e7d \
|
||||
--hash=sha256:98c7086708b163d425c67c7a91bad6e466bb99d797aa64f965e9d25c12111a5e \
|
||||
--hash=sha256:9add70b36c5666a2ed02b43b335fe19002ee5235efd4b8a89bfcf9005bebac0d \
|
||||
--hash=sha256:9bf40443012702a1d2070043cb6291650a0841ece432556f784f004937f0f32c \
|
||||
--hash=sha256:ade5e387d2ad0d7ebf59146cc00c8044acbd863725f887353a10df825fc8ae21 \
|
||||
--hash=sha256:b00c1de48212e4cc9603895652c5c410df699856a2853135b3967591e4beebc2 \
|
||||
--hash=sha256:b1282f8c00509d99fef04d8ba936b156d419be841854fe901d8ae224c59f0be5 \
|
||||
--hash=sha256:b2051432115498d3562c084a49bba65d97cf251f5a331c64a12ee7e04dacc51b \
|
||||
--hash=sha256:ba59edeaa2fc6114428f1637ffff42da1e311e29382d81b339c1817d37ec93c6 \
|
||||
--hash=sha256:c8716a48d94b06bb3b2524c2b77e055fb313aeb4ea620c8dd03a105574ba704f \
|
||||
--hash=sha256:cd5df75523866410809ca100dc9681e301e3c27567cf498077e8551b6d20e42f \
|
||||
--hash=sha256:cdb132fc825c38e1aeec2c8aa9338310d29d337bebbd7baa06889d09a60a1fa2 \
|
||||
--hash=sha256:e249096428b3ae81b08327a63a485ad0878de3fb939049038579ac0ef61e17e7 \
|
||||
--hash=sha256:e8313f01ba26fbbe36c7be1966a7b7424942f670f38e666995b88d012765b9be \
|
||||
# via mako
|
||||
pdoc3==0.9.2 \
|
||||
--hash=sha256:9df5d931f25f353c69c46819a3bd03ef96dd286f2a70bb1b93a23a781f91faa1 \
|
||||
# via -r requirements-dev.in
|
||||
pip-tools==5.5.0 \
|
||||
--hash=sha256:10841c1e56c234d610d0466447685b9ea4ee4a2c274f858c0ef3c33d9bd0d985 \
|
||||
--hash=sha256:cb0108391366b3ef336185097b3c2c0f3fa115b15098dafbda5e78aef70ea114 \
|
||||
# via -r requirements-dev.in
|
||||
selenium==3.141.0 \
|
||||
--hash=sha256:2d7131d7bc5a5b99a2d9b04aaf2612c411b03b8ca1b1ee8d3de5845a9be2cb3c \
|
||||
--hash=sha256:deaf32b60ad91a4611b98d8002757f29e6f2c2d5fcaf202e1c9ad06d6772300d
|
||||
--hash=sha256:deaf32b60ad91a4611b98d8002757f29e6f2c2d5fcaf202e1c9ad06d6772300d \
|
||||
# via helium
|
||||
tomli==2.0.0 \
|
||||
--hash=sha256:b5bde28da1fed24b9bd1d4d2b8cba62300bfb4ec9a6187a957e8ddb9434c5224 \
|
||||
--hash=sha256:c292c34f58502a1eb2bbb9f5bbc9a5ebc37bee10ffb8c2d6bbdfa8eb13cc14e1
|
||||
# via pep517
|
||||
urllib3==1.25.9 \
|
||||
--hash=sha256:3018294ebefce6572a474f0604c2021e33b3fd8006ecd11d62107a5d2a963527 \
|
||||
--hash=sha256:88206b0eb87e6d677d424843ac5209e3fb9d0190d0ee169599165ec25e9d9115
|
||||
--hash=sha256:88206b0eb87e6d677d424843ac5209e3fb9d0190d0ee169599165ec25e9d9115 \
|
||||
# via selenium
|
||||
wheel==0.37.1 \
|
||||
--hash=sha256:4bdcd7d840138086126cd09254dc6195fb4fc6f01c050a1d7236f2630db1d22a \
|
||||
--hash=sha256:e9a504e793efbca1b8e0e9cb979a249cf4a0a7b5b8c9e8b65a5e39d49529c1c4
|
||||
# via pip-tools
|
||||
|
||||
# WARNING: The following packages were not pinned, but pip requires them to be
|
||||
# pinned when the requirements file includes hashes. Consider using the --allow-unsafe flag.
|
||||
|
1
requirements-notifications.in
Normal file
1
requirements-notifications.in
Normal file
@ -0,0 +1 @@
|
||||
simplenotifications==0.2.18
|
8
requirements-notifications.txt
Normal file
8
requirements-notifications.txt
Normal file
@ -0,0 +1,8 @@
|
||||
#
|
||||
# This file is autogenerated by pip-compile
|
||||
# To update, run:
|
||||
#
|
||||
# pip-compile --generate-hashes --output-file=requirements-notifications.txt requirements-notifications.in
|
||||
#
|
||||
simplenotifications==0.2.18 \
|
||||
--hash=sha256:b7efd3d834b1922a3279287913d87fe4ef6fad181ca7edf54bfb8f1d973941e0
|
@ -1,445 +0,0 @@
|
||||
#
|
||||
# This file is autogenerated by pip-compile with python 3.10
|
||||
# To update, run:
|
||||
#
|
||||
# pip-compile --generate-hashes --output-file=requirements-x86-all-plugins.txt requirements-base.in static-data/official-plugins/rpc/requirements.in static-data/official-plugins/tor/requirements.in static-data/official-plugins/wot/requirements.in
|
||||
#
|
||||
autocommand==2.2.1 \
|
||||
--hash=sha256:85d03044c2a1fc1c7844ac41545045927aecde0cbaf8ea28b88e0cd8588ce5d3 \
|
||||
--hash=sha256:fed420e9d02745821a782971b583c6970259ee0b229be2a0a401e1467a4f170f
|
||||
# via jaraco-text
|
||||
cffi==1.15.1 \
|
||||
--hash=sha256:00a9ed42e88df81ffae7a8ab6d9356b371399b91dbdf0c3cb1e84c03a13aceb5 \
|
||||
--hash=sha256:03425bdae262c76aad70202debd780501fabeaca237cdfddc008987c0e0f59ef \
|
||||
--hash=sha256:04ed324bda3cda42b9b695d51bb7d54b680b9719cfab04227cdd1e04e5de3104 \
|
||||
--hash=sha256:0e2642fe3142e4cc4af0799748233ad6da94c62a8bec3a6648bf8ee68b1c7426 \
|
||||
--hash=sha256:173379135477dc8cac4bc58f45db08ab45d228b3363adb7af79436135d028405 \
|
||||
--hash=sha256:198caafb44239b60e252492445da556afafc7d1e3ab7a1fb3f0584ef6d742375 \
|
||||
--hash=sha256:1e74c6b51a9ed6589199c787bf5f9875612ca4a8a0785fb2d4a84429badaf22a \
|
||||
--hash=sha256:2012c72d854c2d03e45d06ae57f40d78e5770d252f195b93f581acf3ba44496e \
|
||||
--hash=sha256:21157295583fe8943475029ed5abdcf71eb3911894724e360acff1d61c1d54bc \
|
||||
--hash=sha256:2470043b93ff09bf8fb1d46d1cb756ce6132c54826661a32d4e4d132e1977adf \
|
||||
--hash=sha256:285d29981935eb726a4399badae8f0ffdff4f5050eaa6d0cfc3f64b857b77185 \
|
||||
--hash=sha256:30d78fbc8ebf9c92c9b7823ee18eb92f2e6ef79b45ac84db507f52fbe3ec4497 \
|
||||
--hash=sha256:320dab6e7cb2eacdf0e658569d2575c4dad258c0fcc794f46215e1e39f90f2c3 \
|
||||
--hash=sha256:33ab79603146aace82c2427da5ca6e58f2b3f2fb5da893ceac0c42218a40be35 \
|
||||
--hash=sha256:3548db281cd7d2561c9ad9984681c95f7b0e38881201e157833a2342c30d5e8c \
|
||||
--hash=sha256:3799aecf2e17cf585d977b780ce79ff0dc9b78d799fc694221ce814c2c19db83 \
|
||||
--hash=sha256:39d39875251ca8f612b6f33e6b1195af86d1b3e60086068be9cc053aa4376e21 \
|
||||
--hash=sha256:3b926aa83d1edb5aa5b427b4053dc420ec295a08e40911296b9eb1b6170f6cca \
|
||||
--hash=sha256:3bcde07039e586f91b45c88f8583ea7cf7a0770df3a1649627bf598332cb6984 \
|
||||
--hash=sha256:3d08afd128ddaa624a48cf2b859afef385b720bb4b43df214f85616922e6a5ac \
|
||||
--hash=sha256:3eb6971dcff08619f8d91607cfc726518b6fa2a9eba42856be181c6d0d9515fd \
|
||||
--hash=sha256:40f4774f5a9d4f5e344f31a32b5096977b5d48560c5592e2f3d2c4374bd543ee \
|
||||
--hash=sha256:4289fc34b2f5316fbb762d75362931e351941fa95fa18789191b33fc4cf9504a \
|
||||
--hash=sha256:470c103ae716238bbe698d67ad020e1db9d9dba34fa5a899b5e21577e6d52ed2 \
|
||||
--hash=sha256:4f2c9f67e9821cad2e5f480bc8d83b8742896f1242dba247911072d4fa94c192 \
|
||||
--hash=sha256:50a74364d85fd319352182ef59c5c790484a336f6db772c1a9231f1c3ed0cbd7 \
|
||||
--hash=sha256:54a2db7b78338edd780e7ef7f9f6c442500fb0d41a5a4ea24fff1c929d5af585 \
|
||||
--hash=sha256:5635bd9cb9731e6d4a1132a498dd34f764034a8ce60cef4f5319c0541159392f \
|
||||
--hash=sha256:59c0b02d0a6c384d453fece7566d1c7e6b7bae4fc5874ef2ef46d56776d61c9e \
|
||||
--hash=sha256:5d598b938678ebf3c67377cdd45e09d431369c3b1a5b331058c338e201f12b27 \
|
||||
--hash=sha256:5df2768244d19ab7f60546d0c7c63ce1581f7af8b5de3eb3004b9b6fc8a9f84b \
|
||||
--hash=sha256:5ef34d190326c3b1f822a5b7a45f6c4535e2f47ed06fec77d3d799c450b2651e \
|
||||
--hash=sha256:6975a3fac6bc83c4a65c9f9fcab9e47019a11d3d2cf7f3c0d03431bf145a941e \
|
||||
--hash=sha256:6c9a799e985904922a4d207a94eae35c78ebae90e128f0c4e521ce339396be9d \
|
||||
--hash=sha256:70df4e3b545a17496c9b3f41f5115e69a4f2e77e94e1d2a8e1070bc0c38c8a3c \
|
||||
--hash=sha256:7473e861101c9e72452f9bf8acb984947aa1661a7704553a9f6e4baa5ba64415 \
|
||||
--hash=sha256:8102eaf27e1e448db915d08afa8b41d6c7ca7a04b7d73af6514df10a3e74bd82 \
|
||||
--hash=sha256:87c450779d0914f2861b8526e035c5e6da0a3199d8f1add1a665e1cbc6fc6d02 \
|
||||
--hash=sha256:8b7ee99e510d7b66cdb6c593f21c043c248537a32e0bedf02e01e9553a172314 \
|
||||
--hash=sha256:91fc98adde3d7881af9b59ed0294046f3806221863722ba7d8d120c575314325 \
|
||||
--hash=sha256:94411f22c3985acaec6f83c6df553f2dbe17b698cc7f8ae751ff2237d96b9e3c \
|
||||
--hash=sha256:98d85c6a2bef81588d9227dde12db8a7f47f639f4a17c9ae08e773aa9c697bf3 \
|
||||
--hash=sha256:9ad5db27f9cabae298d151c85cf2bad1d359a1b9c686a275df03385758e2f914 \
|
||||
--hash=sha256:a0b71b1b8fbf2b96e41c4d990244165e2c9be83d54962a9a1d118fd8657d2045 \
|
||||
--hash=sha256:a0f100c8912c114ff53e1202d0078b425bee3649ae34d7b070e9697f93c5d52d \
|
||||
--hash=sha256:a591fe9e525846e4d154205572a029f653ada1a78b93697f3b5a8f1f2bc055b9 \
|
||||
--hash=sha256:a5c84c68147988265e60416b57fc83425a78058853509c1b0629c180094904a5 \
|
||||
--hash=sha256:a66d3508133af6e8548451b25058d5812812ec3798c886bf38ed24a98216fab2 \
|
||||
--hash=sha256:a8c4917bd7ad33e8eb21e9a5bbba979b49d9a97acb3a803092cbc1133e20343c \
|
||||
--hash=sha256:b3bbeb01c2b273cca1e1e0c5df57f12dce9a4dd331b4fa1635b8bec26350bde3 \
|
||||
--hash=sha256:cba9d6b9a7d64d4bd46167096fc9d2f835e25d7e4c121fb2ddfc6528fb0413b2 \
|
||||
--hash=sha256:cc4d65aeeaa04136a12677d3dd0b1c0c94dc43abac5860ab33cceb42b801c1e8 \
|
||||
--hash=sha256:ce4bcc037df4fc5e3d184794f27bdaab018943698f4ca31630bc7f84a7b69c6d \
|
||||
--hash=sha256:cec7d9412a9102bdc577382c3929b337320c4c4c4849f2c5cdd14d7368c5562d \
|
||||
--hash=sha256:d400bfb9a37b1351253cb402671cea7e89bdecc294e8016a707f6d1d8ac934f9 \
|
||||
--hash=sha256:d61f4695e6c866a23a21acab0509af1cdfd2c013cf256bbf5b6b5e2695827162 \
|
||||
--hash=sha256:db0fbb9c62743ce59a9ff687eb5f4afbe77e5e8403d6697f7446e5f609976f76 \
|
||||
--hash=sha256:dd86c085fae2efd48ac91dd7ccffcfc0571387fe1193d33b6394db7ef31fe2a4 \
|
||||
--hash=sha256:e00b098126fd45523dd056d2efba6c5a63b71ffe9f2bbe1a4fe1716e1d0c331e \
|
||||
--hash=sha256:e229a521186c75c8ad9490854fd8bbdd9a0c9aa3a524326b55be83b54d4e0ad9 \
|
||||
--hash=sha256:e263d77ee3dd201c3a142934a086a4450861778baaeeb45db4591ef65550b0a6 \
|
||||
--hash=sha256:ed9cb427ba5504c1dc15ede7d516b84757c3e3d7868ccc85121d9310d27eed0b \
|
||||
--hash=sha256:fa6693661a4c91757f4412306191b6dc88c1703f780c8234035eac011922bc01 \
|
||||
--hash=sha256:fcd131dd944808b5bdb38e6f5b53013c5aa4f334c5cad0c72742f6eba4b73db0
|
||||
# via
|
||||
# -r static-data/official-plugins/wot/requirements.in
|
||||
# cryptography
|
||||
# pynacl
|
||||
cheroot==8.6.0 \
|
||||
--hash=sha256:366adf6e7cac9555486c2d1be6297993022eff6f8c4655c1443268cca3f08e25 \
|
||||
--hash=sha256:62cbced16f07e8aaf512673987cd6b1fc5ad00073345e9ed6c4e2a5cc2a3a22d
|
||||
# via cherrypy
|
||||
cherrypy==18.8.0 \
|
||||
--hash=sha256:9b48cfba8a2f16d5b6419cc657e6d51db005ba35c5e3824e4728bb03bbc7ef9b \
|
||||
--hash=sha256:b56097025dc78a76a59db551b3a82871c6b3a0107b80b12ff759e4c0b3b947ce
|
||||
# via -r static-data/official-plugins/rpc/requirements.in
|
||||
cryptography==38.0.1 \
|
||||
--hash=sha256:0297ffc478bdd237f5ca3a7dc96fc0d315670bfa099c04dc3a4a2172008a405a \
|
||||
--hash=sha256:10d1f29d6292fc95acb597bacefd5b9e812099d75a6469004fd38ba5471a977f \
|
||||
--hash=sha256:16fa61e7481f4b77ef53991075de29fc5bacb582a1244046d2e8b4bb72ef66d0 \
|
||||
--hash=sha256:194044c6b89a2f9f169df475cc167f6157eb9151cc69af8a2a163481d45cc407 \
|
||||
--hash=sha256:1db3d807a14931fa317f96435695d9ec386be7b84b618cc61cfa5d08b0ae33d7 \
|
||||
--hash=sha256:3261725c0ef84e7592597606f6583385fed2a5ec3909f43bc475ade9729a41d6 \
|
||||
--hash=sha256:3b72c360427889b40f36dc214630e688c2fe03e16c162ef0aa41da7ab1455153 \
|
||||
--hash=sha256:3e3a2599e640927089f932295a9a247fc40a5bdf69b0484532f530471a382750 \
|
||||
--hash=sha256:3fc26e22840b77326a764ceb5f02ca2d342305fba08f002a8c1f139540cdfaad \
|
||||
--hash=sha256:5067ee7f2bce36b11d0e334abcd1ccf8c541fc0bbdaf57cdd511fdee53e879b6 \
|
||||
--hash=sha256:52e7bee800ec869b4031093875279f1ff2ed12c1e2f74923e8f49c916afd1d3b \
|
||||
--hash=sha256:64760ba5331e3f1794d0bcaabc0d0c39e8c60bf67d09c93dc0e54189dfd7cfe5 \
|
||||
--hash=sha256:765fa194a0f3372d83005ab83ab35d7c5526c4e22951e46059b8ac678b44fa5a \
|
||||
--hash=sha256:79473cf8a5cbc471979bd9378c9f425384980fcf2ab6534b18ed7d0d9843987d \
|
||||
--hash=sha256:896dd3a66959d3a5ddcfc140a53391f69ff1e8f25d93f0e2e7830c6de90ceb9d \
|
||||
--hash=sha256:89ed49784ba88c221756ff4d4755dbc03b3c8d2c5103f6d6b4f83a0fb1e85294 \
|
||||
--hash=sha256:ac7e48f7e7261207d750fa7e55eac2d45f720027d5703cd9007e9b37bbb59ac0 \
|
||||
--hash=sha256:ad7353f6ddf285aeadfaf79e5a6829110106ff8189391704c1d8801aa0bae45a \
|
||||
--hash=sha256:b0163a849b6f315bf52815e238bc2b2346604413fa7c1601eea84bcddb5fb9ac \
|
||||
--hash=sha256:b6c9b706316d7b5a137c35e14f4103e2115b088c412140fdbd5f87c73284df61 \
|
||||
--hash=sha256:c2e5856248a416767322c8668ef1845ad46ee62629266f84a8f007a317141013 \
|
||||
--hash=sha256:ca9f6784ea96b55ff41708b92c3f6aeaebde4c560308e5fbbd3173fbc466e94e \
|
||||
--hash=sha256:d1a5bd52d684e49a36582193e0b89ff267704cd4025abefb9e26803adeb3e5fb \
|
||||
--hash=sha256:d3971e2749a723e9084dd507584e2a2761f78ad2c638aa31e80bc7a15c9db4f9 \
|
||||
--hash=sha256:d4ef6cc305394ed669d4d9eebf10d3a101059bdcf2669c366ec1d14e4fb227bd \
|
||||
--hash=sha256:d9e69ae01f99abe6ad646947bba8941e896cb3aa805be2597a0400e0764b5818
|
||||
# via secretstorage
|
||||
filenuke==0.0.0 \
|
||||
--hash=sha256:147011c0125121469cae0a8a7f4df399f470e54aa29a08f2d2c099bf0118dcee \
|
||||
--hash=sha256:c55535dcecfdb27c5f4ce664d46e115950b5429763b5db75c198053646177f8f
|
||||
# via -r requirements-base.in
|
||||
inflect==6.0.0 \
|
||||
--hash=sha256:0bc1516ec2725e2d8221707a612245093cb6f1cea209cfd8cbd4fc5e96fa6365 \
|
||||
--hash=sha256:e3b85d65a296843268f35f4136283ad7c012a129375db1529d49b4b01ecb400b
|
||||
# via jaraco-text
|
||||
jaraco-classes==3.2.2 \
|
||||
--hash=sha256:6745f113b0b588239ceb49532aa09c3ebb947433ce311ef2f8e3ad64ebb74594 \
|
||||
--hash=sha256:e6ef6fd3fcf4579a7a019d87d1e56a883f4e4c35cfe925f86731abc58804e647
|
||||
# via
|
||||
# jaraco-collections
|
||||
# keyring
|
||||
jaraco-collections==3.5.2 \
|
||||
--hash=sha256:072b93eb35f9e48508485755534e66a34ef1cc84af291fd27f39b44d4c0dd2c3 \
|
||||
--hash=sha256:1ca12fa4b7067dfc8d7f791c1a8660d970a2bf2f80536ba0aa5cbb71fe1261f1
|
||||
# via cherrypy
|
||||
jaraco-context==4.1.2 \
|
||||
--hash=sha256:9327d3e6901923e5a7097aa2df4b9c2bc13f845c7672692e3827ebd1b3d67606 \
|
||||
--hash=sha256:a58e94dd67871639abc091b57d32842449b230777570ef2bcec3dc16b912613e
|
||||
# via jaraco-text
|
||||
jaraco-functools==3.5.1 \
|
||||
--hash=sha256:c8774f73323de42250a659934215da1d899b02c66a6133f1cb79f02a5aff4f38 \
|
||||
--hash=sha256:d0adcf91710a0853efe9f23a78fad586bf67df572f0d6d8e0fa36d289ae1c1d9
|
||||
# via
|
||||
# cheroot
|
||||
# jaraco-text
|
||||
# tempora
|
||||
jaraco-text==3.9.1 \
|
||||
--hash=sha256:3ca615c4135e151d21206075ec4aface8a2fbc3e68437fe709a6541428a635f9 \
|
||||
--hash=sha256:d57cd4448a588020318425e04194e897f96fc23b92b82ff9308a24d5cbf2b3fb
|
||||
# via jaraco-collections
|
||||
jeepney==0.8.0 \
|
||||
--hash=sha256:5efe48d255973902f6badc3ce55e2aa6c5c3b3bc642059ef3a91247bcfcc5806 \
|
||||
--hash=sha256:c0a454ad016ca575060802ee4d590dd912e35c122fa04e70306de3d076cce755
|
||||
# via
|
||||
# keyring
|
||||
# secretstorage
|
||||
json-rpc==1.13.0 \
|
||||
--hash=sha256:84b45058e5ba95f49c7b6afcf7e03ab86bee89bf2c01f3ad8dd41fe114fc1f84 \
|
||||
--hash=sha256:def0dbcf5b7084fc31d677f2f5990d988d06497f2f47f13024274cfb2d5d7589
|
||||
# via -r static-data/official-plugins/rpc/requirements.in
|
||||
kasten==3.0.0 \
|
||||
--hash=sha256:52894af46d6e1339f0d5fa8961892b292f99176848bce11877fe4a435b6782e5 \
|
||||
--hash=sha256:b22ebdc5f475c2ef9ab74abc36552add0b37732a7ce2be6bd7977ee41b2163b4
|
||||
# via onionrblocks
|
||||
keyring==23.9.3 \
|
||||
--hash=sha256:69732a15cb1433bdfbc3b980a8a36a04878a6cfd7cb99f497b573f31618001c0 \
|
||||
--hash=sha256:69b01dd83c42f590250fe7a1f503fc229b14de83857314b1933a3ddbf595c4a5
|
||||
# via -r static-data/official-plugins/wot/requirements.in
|
||||
mimcvdf==1.2.1 \
|
||||
--hash=sha256:7c837c46cfb9dce4ba895bc706a69646d4d5185c66aeaa333b5cfaa9a7d06dc4
|
||||
# via kasten
|
||||
more-itertools==8.14.0 \
|
||||
--hash=sha256:1bc4f91ee5b1b31ac7ceacc17c09befe6a40a503907baf9c839c229b5095cfd2 \
|
||||
--hash=sha256:c09443cd3d5438b8dafccd867a6bc1cb0894389e90cb53d227456b0b0bccb750
|
||||
# via
|
||||
# cheroot
|
||||
# cherrypy
|
||||
# jaraco-classes
|
||||
# jaraco-functools
|
||||
# jaraco-text
|
||||
msgpack==1.0.4 \
|
||||
--hash=sha256:002b5c72b6cd9b4bafd790f364b8480e859b4712e91f43014fe01e4f957b8467 \
|
||||
--hash=sha256:0a68d3ac0104e2d3510de90a1091720157c319ceeb90d74f7b5295a6bee51bae \
|
||||
--hash=sha256:0df96d6eaf45ceca04b3f3b4b111b86b33785683d682c655063ef8057d61fd92 \
|
||||
--hash=sha256:0dfe3947db5fb9ce52aaea6ca28112a170db9eae75adf9339a1aec434dc954ef \
|
||||
--hash=sha256:0e3590f9fb9f7fbc36df366267870e77269c03172d086fa76bb4eba8b2b46624 \
|
||||
--hash=sha256:11184bc7e56fd74c00ead4f9cc9a3091d62ecb96e97653add7a879a14b003227 \
|
||||
--hash=sha256:112b0f93202d7c0fef0b7810d465fde23c746a2d482e1e2de2aafd2ce1492c88 \
|
||||
--hash=sha256:1276e8f34e139aeff1c77a3cefb295598b504ac5314d32c8c3d54d24fadb94c9 \
|
||||
--hash=sha256:1576bd97527a93c44fa856770197dec00d223b0b9f36ef03f65bac60197cedf8 \
|
||||
--hash=sha256:1e91d641d2bfe91ba4c52039adc5bccf27c335356055825c7f88742c8bb900dd \
|
||||
--hash=sha256:26b8feaca40a90cbe031b03d82b2898bf560027160d3eae1423f4a67654ec5d6 \
|
||||
--hash=sha256:2999623886c5c02deefe156e8f869c3b0aaeba14bfc50aa2486a0415178fce55 \
|
||||
--hash=sha256:2a2df1b55a78eb5f5b7d2a4bb221cd8363913830145fad05374a80bf0877cb1e \
|
||||
--hash=sha256:2bb8cdf50dd623392fa75525cce44a65a12a00c98e1e37bf0fb08ddce2ff60d2 \
|
||||
--hash=sha256:2cc5ca2712ac0003bcb625c96368fd08a0f86bbc1a5578802512d87bc592fe44 \
|
||||
--hash=sha256:35bc0faa494b0f1d851fd29129b2575b2e26d41d177caacd4206d81502d4c6a6 \
|
||||
--hash=sha256:3c11a48cf5e59026ad7cb0dc29e29a01b5a66a3e333dc11c04f7e991fc5510a9 \
|
||||
--hash=sha256:449e57cc1ff18d3b444eb554e44613cffcccb32805d16726a5494038c3b93dab \
|
||||
--hash=sha256:462497af5fd4e0edbb1559c352ad84f6c577ffbbb708566a0abaaa84acd9f3ae \
|
||||
--hash=sha256:4733359808c56d5d7756628736061c432ded018e7a1dff2d35a02439043321aa \
|
||||
--hash=sha256:48f5d88c99f64c456413d74a975bd605a9b0526293218a3b77220a2c15458ba9 \
|
||||
--hash=sha256:49565b0e3d7896d9ea71d9095df15b7f75a035c49be733051c34762ca95bbf7e \
|
||||
--hash=sha256:4ab251d229d10498e9a2f3b1e68ef64cb393394ec477e3370c457f9430ce9250 \
|
||||
--hash=sha256:4d5834a2a48965a349da1c5a79760d94a1a0172fbb5ab6b5b33cbf8447e109ce \
|
||||
--hash=sha256:4dea20515f660aa6b7e964433b1808d098dcfcabbebeaaad240d11f909298075 \
|
||||
--hash=sha256:545e3cf0cf74f3e48b470f68ed19551ae6f9722814ea969305794645da091236 \
|
||||
--hash=sha256:63e29d6e8c9ca22b21846234913c3466b7e4ee6e422f205a2988083de3b08cae \
|
||||
--hash=sha256:6916c78f33602ecf0509cc40379271ba0f9ab572b066bd4bdafd7434dee4bc6e \
|
||||
--hash=sha256:6a4192b1ab40f8dca3f2877b70e63799d95c62c068c84dc028b40a6cb03ccd0f \
|
||||
--hash=sha256:6c9566f2c39ccced0a38d37c26cc3570983b97833c365a6044edef3574a00c08 \
|
||||
--hash=sha256:76ee788122de3a68a02ed6f3a16bbcd97bc7c2e39bd4d94be2f1821e7c4a64e6 \
|
||||
--hash=sha256:7760f85956c415578c17edb39eed99f9181a48375b0d4a94076d84148cf67b2d \
|
||||
--hash=sha256:77ccd2af37f3db0ea59fb280fa2165bf1b096510ba9fe0cc2bf8fa92a22fdb43 \
|
||||
--hash=sha256:81fc7ba725464651190b196f3cd848e8553d4d510114a954681fd0b9c479d7e1 \
|
||||
--hash=sha256:85f279d88d8e833ec015650fd15ae5eddce0791e1e8a59165318f371158efec6 \
|
||||
--hash=sha256:9667bdfdf523c40d2511f0e98a6c9d3603be6b371ae9a238b7ef2dc4e7a427b0 \
|
||||
--hash=sha256:a75dfb03f8b06f4ab093dafe3ddcc2d633259e6c3f74bb1b01996f5d8aa5868c \
|
||||
--hash=sha256:ac5bd7901487c4a1dd51a8c58f2632b15d838d07ceedaa5e4c080f7190925bff \
|
||||
--hash=sha256:aca0f1644d6b5a73eb3e74d4d64d5d8c6c3d577e753a04c9e9c87d07692c58db \
|
||||
--hash=sha256:b17be2478b622939e39b816e0aa8242611cc8d3583d1cd8ec31b249f04623243 \
|
||||
--hash=sha256:c1683841cd4fa45ac427c18854c3ec3cd9b681694caf5bff04edb9387602d661 \
|
||||
--hash=sha256:c23080fdeec4716aede32b4e0ef7e213c7b1093eede9ee010949f2a418ced6ba \
|
||||
--hash=sha256:d5b5b962221fa2c5d3a7f8133f9abffc114fe218eb4365e40f17732ade576c8e \
|
||||
--hash=sha256:d603de2b8d2ea3f3bcb2efe286849aa7a81531abc52d8454da12f46235092bcb \
|
||||
--hash=sha256:e83f80a7fec1a62cf4e6c9a660e39c7f878f603737a0cdac8c13131d11d97f52 \
|
||||
--hash=sha256:eb514ad14edf07a1dbe63761fd30f89ae79b42625731e1ccf5e1f1092950eaa6 \
|
||||
--hash=sha256:eba96145051ccec0ec86611fe9cf693ce55f2a3ce89c06ed307de0e085730ec1 \
|
||||
--hash=sha256:ed6f7b854a823ea44cf94919ba3f727e230da29feb4a99711433f25800cf747f \
|
||||
--hash=sha256:f0029245c51fd9473dc1aede1160b0a29f4a912e6b1dd353fa6d317085b219da \
|
||||
--hash=sha256:f5d869c18f030202eb412f08b28d2afeea553d6613aee89e200d7aca7ef01f5f \
|
||||
--hash=sha256:fb62ea4b62bfcb0b380d5680f9a4b3f9a2d166d9394e9bbd9666c0ee09a3645c \
|
||||
--hash=sha256:fcb8a47f43acc113e24e910399376f7277cf8508b27e5b88499f053de6b115a8
|
||||
# via kasten
|
||||
onionrblocks==7.0.0 \
|
||||
--hash=sha256:53e90964371076d9daf2ed0790b21f174ef3321f4f1808209cc6dd9b7ff6d8ff \
|
||||
--hash=sha256:54af28d0be856209525646c4ef9f977f95f0ae1329b2cc023b351317c9d0eef7
|
||||
# via -r requirements-base.in
|
||||
ordered-set==4.1.0 \
|
||||
--hash=sha256:046e1132c71fcf3330438a539928932caf51ddbc582496833e23de611de14562 \
|
||||
--hash=sha256:694a8e44c87657c59292ede72891eb91d34131f6531463aab3009191c77364a8
|
||||
# via -r requirements-base.in
|
||||
portend==3.1.0 \
|
||||
--hash=sha256:239e3116045ea823f6df87d6168107ad75ccc0590e37242af0cc1e98c5d224e4 \
|
||||
--hash=sha256:9e735cee3a5c1961f09e3f3ba6dc498198c2d70b473d98d0d1504b8d1e7a3d61
|
||||
# via cherrypy
|
||||
psutil==5.9.3 \
|
||||
--hash=sha256:07d880053c6461c9b89cd5d4808f3b8336665fa3acdefd6777662c5ed73a851a \
|
||||
--hash=sha256:12500d761ac091f2426567f19f95fd3f15a197d96befb44a5c1e3cbe6db5752c \
|
||||
--hash=sha256:1b540599481c73408f6b392cdffef5b01e8ff7a2ac8caae0a91b8222e88e8f1e \
|
||||
--hash=sha256:35feafe232d1aaf35d51bd42790cbccb882456f9f18cdc411532902370d660df \
|
||||
--hash=sha256:3a7826e68b0cf4ce2c1ee385d64eab7d70e3133171376cac53d7c1790357ec8f \
|
||||
--hash=sha256:46907fa62acaac364fff0b8a9da7b360265d217e4fdeaca0a2397a6883dffba2 \
|
||||
--hash=sha256:4bd4854f0c83aa84a5a40d3b5d0eb1f3c128f4146371e03baed4589fe4f3c931 \
|
||||
--hash=sha256:538fcf6ae856b5e12d13d7da25ad67f02113c96f5989e6ad44422cb5994ca7fc \
|
||||
--hash=sha256:547ebb02031fdada635452250ff39942db8310b5c4a8102dfe9384ee5791e650 \
|
||||
--hash=sha256:5e8b50241dd3c2ed498507f87a6602825073c07f3b7e9560c58411c14fe1e1c9 \
|
||||
--hash=sha256:5fa88e3d5d0b480602553d362c4b33a63e0c40bfea7312a7bf78799e01e0810b \
|
||||
--hash=sha256:68fa227c32240c52982cb931801c5707a7f96dd8927f9102d6c7771ea1ff5698 \
|
||||
--hash=sha256:6ced1ad823ecfa7d3ce26fe8aa4996e2e53fb49b7fed8ad81c80958501ec0619 \
|
||||
--hash=sha256:71b1206e7909792d16933a0d2c1c7f04ae196186c51ba8567abae1d041f06dcb \
|
||||
--hash=sha256:767ef4fa33acda16703725c0473a91e1832d296c37c63896c7153ba81698f1ab \
|
||||
--hash=sha256:7ccfcdfea4fc4b0a02ca2c31de7fcd186beb9cff8207800e14ab66f79c773af6 \
|
||||
--hash=sha256:7e4939ff75149b67aef77980409f156f0082fa36accc475d45c705bb00c6c16a \
|
||||
--hash=sha256:828c9dc9478b34ab96be75c81942d8df0c2bb49edbb481f597314d92b6441d89 \
|
||||
--hash=sha256:8a4e07611997acf178ad13b842377e3d8e9d0a5bac43ece9bfc22a96735d9a4f \
|
||||
--hash=sha256:941a6c2c591da455d760121b44097781bc970be40e0e43081b9139da485ad5b7 \
|
||||
--hash=sha256:9a4af6ed1094f867834f5f07acd1250605a0874169a5fcadbcec864aec2496a6 \
|
||||
--hash=sha256:9ec296f565191f89c48f33d9544d8d82b0d2af7dd7d2d4e6319f27a818f8d1cc \
|
||||
--hash=sha256:9ec95df684583b5596c82bb380c53a603bb051cf019d5c849c47e117c5064395 \
|
||||
--hash=sha256:a04a1836894c8279e5e0a0127c0db8e198ca133d28be8a2a72b4db16f6cf99c1 \
|
||||
--hash=sha256:a3d81165b8474087bb90ec4f333a638ccfd1d69d34a9b4a1a7eaac06648f9fbe \
|
||||
--hash=sha256:b4a247cd3feaae39bb6085fcebf35b3b8ecd9b022db796d89c8f05067ca28e71 \
|
||||
--hash=sha256:ba38cf9984d5462b506e239cf4bc24e84ead4b1d71a3be35e66dad0d13ded7c1 \
|
||||
--hash=sha256:beb57d8a1ca0ae0eb3d08ccaceb77e1a6d93606f0e1754f0d60a6ebd5c288837 \
|
||||
--hash=sha256:d266cd05bd4a95ca1c2b9b5aac50d249cf7c94a542f47e0b22928ddf8b80d1ef \
|
||||
--hash=sha256:d8c3cc6bb76492133474e130a12351a325336c01c96a24aae731abf5a47fe088 \
|
||||
--hash=sha256:db8e62016add2235cc87fb7ea000ede9e4ca0aa1f221b40cef049d02d5d2593d \
|
||||
--hash=sha256:e7507f6c7b0262d3e7b0eeda15045bf5881f4ada70473b87bc7b7c93b992a7d7 \
|
||||
--hash=sha256:ed15edb14f52925869250b1375f0ff58ca5c4fa8adefe4883cfb0737d32f5c02 \
|
||||
--hash=sha256:f57d63a2b5beaf797b87024d018772439f9d3103a395627b77d17a8d72009543 \
|
||||
--hash=sha256:fa5e32c7d9b60b2528108ade2929b115167fe98d59f89555574715054f50fa31 \
|
||||
--hash=sha256:fe79b4ad4836e3da6c4650cb85a663b3a51aef22e1a829c384e18fae87e5e727
|
||||
# via -r requirements-base.in
|
||||
pycparser==2.21 \
|
||||
--hash=sha256:8ee45429555515e1f6b185e78100aea234072576aa43ab53aefcae078162fca9 \
|
||||
--hash=sha256:e644fdec12f7872f86c58ff790da456218b10f863970249516d60a5eaca77206
|
||||
# via cffi
|
||||
pydantic==1.10.2 \
|
||||
--hash=sha256:05e00dbebbe810b33c7a7362f231893183bcc4251f3f2ff991c31d5c08240c42 \
|
||||
--hash=sha256:06094d18dd5e6f2bbf93efa54991c3240964bb663b87729ac340eb5014310624 \
|
||||
--hash=sha256:0b959f4d8211fc964772b595ebb25f7652da3f22322c007b6fed26846a40685e \
|
||||
--hash=sha256:19b3b9ccf97af2b7519c42032441a891a5e05c68368f40865a90eb88833c2559 \
|
||||
--hash=sha256:1b6ee725bd6e83ec78b1aa32c5b1fa67a3a65badddde3976bca5fe4568f27709 \
|
||||
--hash=sha256:1ee433e274268a4b0c8fde7ad9d58ecba12b069a033ecc4645bb6303c062d2e9 \
|
||||
--hash=sha256:216f3bcbf19c726b1cc22b099dd409aa371f55c08800bcea4c44c8f74b73478d \
|
||||
--hash=sha256:2d0567e60eb01bccda3a4df01df677adf6b437958d35c12a3ac3e0f078b0ee52 \
|
||||
--hash=sha256:2e05aed07fa02231dbf03d0adb1be1d79cabb09025dd45aa094aa8b4e7b9dcda \
|
||||
--hash=sha256:352aedb1d71b8b0736c6d56ad2bd34c6982720644b0624462059ab29bd6e5912 \
|
||||
--hash=sha256:355639d9afc76bcb9b0c3000ddcd08472ae75318a6eb67a15866b87e2efa168c \
|
||||
--hash=sha256:37c90345ec7dd2f1bcef82ce49b6235b40f282b94d3eec47e801baf864d15525 \
|
||||
--hash=sha256:4b8795290deaae348c4eba0cebb196e1c6b98bdbe7f50b2d0d9a4a99716342fe \
|
||||
--hash=sha256:5760e164b807a48a8f25f8aa1a6d857e6ce62e7ec83ea5d5c5a802eac81bad41 \
|
||||
--hash=sha256:6eb843dcc411b6a2237a694f5e1d649fc66c6064d02b204a7e9d194dff81eb4b \
|
||||
--hash=sha256:7b5ba54d026c2bd2cb769d3468885f23f43710f651688e91f5fb1edcf0ee9283 \
|
||||
--hash=sha256:7c2abc4393dea97a4ccbb4ec7d8658d4e22c4765b7b9b9445588f16c71ad9965 \
|
||||
--hash=sha256:81a7b66c3f499108b448f3f004801fcd7d7165fb4200acb03f1c2402da73ce4c \
|
||||
--hash=sha256:91b8e218852ef6007c2b98cd861601c6a09f1aa32bbbb74fab5b1c33d4a1e410 \
|
||||
--hash=sha256:9300fcbebf85f6339a02c6994b2eb3ff1b9c8c14f502058b5bf349d42447dcf5 \
|
||||
--hash=sha256:9cabf4a7f05a776e7793e72793cd92cc865ea0e83a819f9ae4ecccb1b8aa6116 \
|
||||
--hash=sha256:a1f5a63a6dfe19d719b1b6e6106561869d2efaca6167f84f5ab9347887d78b98 \
|
||||
--hash=sha256:a4c805731c33a8db4b6ace45ce440c4ef5336e712508b4d9e1aafa617dc9907f \
|
||||
--hash=sha256:ae544c47bec47a86bc7d350f965d8b15540e27e5aa4f55170ac6a75e5f73b644 \
|
||||
--hash=sha256:b97890e56a694486f772d36efd2ba31612739bc6f3caeee50e9e7e3ebd2fdd13 \
|
||||
--hash=sha256:bb6ad4489af1bac6955d38ebcb95079a836af31e4c4f74aba1ca05bb9f6027bd \
|
||||
--hash=sha256:bedf309630209e78582ffacda64a21f96f3ed2e51fbf3962d4d488e503420254 \
|
||||
--hash=sha256:c1ba1afb396148bbc70e9eaa8c06c1716fdddabaf86e7027c5988bae2a829ab6 \
|
||||
--hash=sha256:c33602f93bfb67779f9c507e4d69451664524389546bacfe1bee13cae6dc7488 \
|
||||
--hash=sha256:c4aac8e7103bf598373208f6299fa9a5cfd1fc571f2d40bf1dd1955a63d6eeb5 \
|
||||
--hash=sha256:c6f981882aea41e021f72779ce2a4e87267458cc4d39ea990729e21ef18f0f8c \
|
||||
--hash=sha256:cc78cc83110d2f275ec1970e7a831f4e371ee92405332ebfe9860a715f8336e1 \
|
||||
--hash=sha256:d49f3db871575e0426b12e2f32fdb25e579dea16486a26e5a0474af87cb1ab0a \
|
||||
--hash=sha256:dd3f9a40c16daf323cf913593083698caee97df2804aa36c4b3175d5ac1b92a2 \
|
||||
--hash=sha256:e0bedafe4bc165ad0a56ac0bd7695df25c50f76961da29c050712596cf092d6d \
|
||||
--hash=sha256:e9069e1b01525a96e6ff49e25876d90d5a563bc31c658289a8772ae186552236
|
||||
# via inflect
|
||||
pynacl==1.5.0 \
|
||||
--hash=sha256:06b8f6fa7f5de8d5d2f7573fe8c863c051225a27b61e6860fd047b1775807858 \
|
||||
--hash=sha256:0c84947a22519e013607c9be43706dd42513f9e6ae5d39d3613ca1e142fba44d \
|
||||
--hash=sha256:20f42270d27e1b6a29f54032090b972d97f0a1b0948cc52392041ef7831fee93 \
|
||||
--hash=sha256:401002a4aaa07c9414132aaed7f6836ff98f59277a234704ff66878c2ee4a0d1 \
|
||||
--hash=sha256:52cb72a79269189d4e0dc537556f4740f7f0a9ec41c1322598799b0bdad4ef92 \
|
||||
--hash=sha256:61f642bf2378713e2c2e1de73444a3778e5f0a38be6fee0fe532fe30060282ff \
|
||||
--hash=sha256:8ac7448f09ab85811607bdd21ec2464495ac8b7c66d146bf545b0f08fb9220ba \
|
||||
--hash=sha256:a36d4a9dda1f19ce6e03c9a784a2921a4b726b02e1c736600ca9c22029474394 \
|
||||
--hash=sha256:a422368fc821589c228f4c49438a368831cb5bbc0eab5ebe1d7fac9dded6567b \
|
||||
--hash=sha256:e46dae94e34b085175f8abb3b0aaa7da40767865ac82c928eeb9e57e1ea8a543
|
||||
# via
|
||||
# -r static-data/official-plugins/wot/requirements.in
|
||||
# onionrblocks
|
||||
pysocks==1.7.1 \
|
||||
--hash=sha256:08e69f092cc6dbe92a0fdd16eeb9b9ffbc13cadfe5ca4c7bd92ffb078b293299 \
|
||||
--hash=sha256:2725bd0a9925919b9b51739eea5f9e2bae91e83288108a9ad338b2e3a4435ee5 \
|
||||
--hash=sha256:3f8804571ebe159c380ac6de37643bb4685970655d3bba243530d6558b799aa0
|
||||
# via -r static-data/official-plugins/tor/requirements.in
|
||||
pytz==2022.2.1 \
|
||||
--hash=sha256:220f481bdafa09c3955dfbdddb7b57780e9a94f5127e35456a48589b9e0c0197 \
|
||||
--hash=sha256:cea221417204f2d1a2aa03ddae3e867921971d0d76f14d87abb4414415bbdcf5
|
||||
# via tempora
|
||||
result==0.8.0 \
|
||||
--hash=sha256:c48c909e92181a075ba358228a3fe161e26d205dad416ad81f27f23515a5626d \
|
||||
--hash=sha256:d6a6258f32c057a4e0478999c6ce43dcadaf8ea435f58ac601ae2768f93ef243
|
||||
# via -r requirements-base.in
|
||||
secretstorage==3.3.3 \
|
||||
--hash=sha256:2403533ef369eca6d2ba81718576c5e0f564d5cca1b58f73a8b23e7d4eeebd77 \
|
||||
--hash=sha256:f356e6628222568e3af06f2eba8df495efa13b3b63081dafd4f7d9a7b7bc9f99
|
||||
# via keyring
|
||||
six==1.16.0 \
|
||||
--hash=sha256:1e61c37477a1626458e36f7b1d82aa5c9b094fa4802892072e49de9c60c4c926 \
|
||||
--hash=sha256:8abb2f1d86890a2dfb989f9a77cfcfd3e47c2a354b01111771326f8aa26e0254
|
||||
# via cheroot
|
||||
stem==1.8.1 \
|
||||
--hash=sha256:81d43a7c668ba9d7bc1103b2e7a911e9d148294b373d27a59ae8da79ef7a3e2f
|
||||
# via -r static-data/official-plugins/tor/requirements.in
|
||||
tempora==5.0.2 \
|
||||
--hash=sha256:31fa5bb33b2641026211f23e808eb8bd351901988b167d45f323c8f450ecf211 \
|
||||
--hash=sha256:e65d32ae68ad772ee738d802689f689b3f883e165e8dadd39aa89ef317b12b99
|
||||
# via portend
|
||||
typing-extensions==4.3.0 \
|
||||
--hash=sha256:25642c956049920a5aa49edcdd6ab1e06d7e5d467fc00e0506c44ac86fbfca02 \
|
||||
--hash=sha256:e6d2677a32f47fc7eb2795db1dd15c1f34eff616bcaf2cfb5e997f854fa1c4a6
|
||||
# via pydantic
|
||||
ujson==5.5.0 \
|
||||
--hash=sha256:0762a4fdf86e01f3f8d8b6b7158d01fdd870799ff3f402b676e358fcd879e7eb \
|
||||
--hash=sha256:10095160dbe6bba8059ad6677a01da251431f4c68041bf796dcac0956b34f8f7 \
|
||||
--hash=sha256:1a485117f97312bef45f5d79d2ff97eff4da503b8a04f3691f59d31141686459 \
|
||||
--hash=sha256:1cef44ea4973344baed3d50a5da4a8843de3a6af7dea7fadf0a594e53ce5892f \
|
||||
--hash=sha256:1dc2f46c31ef22b0aaa28cd71be897bea271e700636658d573df9c43c49ebbd0 \
|
||||
--hash=sha256:21678d7e068707e4d54bdfeb8c250ebc548b51e499aed778b22112ca31a79669 \
|
||||
--hash=sha256:278aa9d7cb56435c96d19f5d702e026bcf69f824e24b41e9b52706abd3565837 \
|
||||
--hash=sha256:2ab011e3556a9a1d9461bd686870c527327765ed02fe53550531d6609a8a33ff \
|
||||
--hash=sha256:2d90414e3b4b44b39825049185959488e084ea7fcaf6124afd5c00893938b09d \
|
||||
--hash=sha256:2e506ecf89b6b9d304362ccef770831ec242a52c89dab1b4aabf1ab0eb1d5ed6 \
|
||||
--hash=sha256:33cd9084fefc74cbacf88c92fd260b61211e00bcde38d640c369e5dc34a2b4e1 \
|
||||
--hash=sha256:3b74467564814fbce322427a5664e6bcc7dae6dbc8acbef76300fe43ca4072ab \
|
||||
--hash=sha256:3f3f4240d99d55eb97cb012e9adf401f5ed9cd827af0341ac44603832202b0d2 \
|
||||
--hash=sha256:3fe1aea596f9539fc20cd9e52f098c842afc090168824fd4ca9744fe13151a03 \
|
||||
--hash=sha256:4a8cb3c8637006c5bd8237ebb5992a76ba06e39988ad5cff2096227443e8fd6a \
|
||||
--hash=sha256:4ef4ab8352861b99bd7fedb1fc6df3ea7f7d5216c789ba6d859e4ea06f1a4c45 \
|
||||
--hash=sha256:5035bb997d163f346c22abcec75190e7e756a5349e7c708bd3d5fd7066a9a854 \
|
||||
--hash=sha256:593a0f6fb0e186c5ba65465ed6f6215a30d1efa898c25e74de1c8577a1bff6d0 \
|
||||
--hash=sha256:59cdcd934385f36e8bd76aedc234371cc75c848d95bdce804ac8aa8744cfeffa \
|
||||
--hash=sha256:5a9b1320d8363a42d857fae8065a2174d38217cdd58cd8dc4f48d54e0591271e \
|
||||
--hash=sha256:5f9681ec4c60d0da590552427d770636d9079038c30b265f507ccde23caa7823 \
|
||||
--hash=sha256:5fd797a4837ba10671954e7c09010cec7aca67e09d193f4920a16beea5f66f65 \
|
||||
--hash=sha256:6019e3480d933d3698f2ecb4b46d64bfadd64e718f04fac36e681f3254b49a93 \
|
||||
--hash=sha256:603607f56a0ee84d9cd2c7e9b1d29b18a70684b94ee34f07b9ffe8dc9c8a9f81 \
|
||||
--hash=sha256:60a4b481978ea2aad8fe8af1ecc271624d01b3cf4b09e9b643dd2fe19c07634c \
|
||||
--hash=sha256:6b9812638d7aa8ecda2e8e1513fb4da999249603bffab7439a5f8f0bb362b0db \
|
||||
--hash=sha256:6c7ae6e0778ab9610f5e80e0595957d101ab8de18c32a8c053a19943ef4831d0 \
|
||||
--hash=sha256:6f83be8257b2f2dd6dea5ee62cd28db90584da7a7af1fba77a2102fc7943638a \
|
||||
--hash=sha256:701e81e047f5c0cffd4ac828efca68b0bd270c616654966a051e9a5f836b385e \
|
||||
--hash=sha256:703fd69d9cb21d6ec2086789df9be2cf8140a76ff127050c24007ea8940dcd3b \
|
||||
--hash=sha256:7471d4486f23518cff343f1eec6c68d1b977ed74c3e6cc3e1ac896b9b7d68645 \
|
||||
--hash=sha256:765d46f3d5e7a1d48075035e2d1a9164f683e3fccde834ca04602e6c588835bc \
|
||||
--hash=sha256:7a09d203983104918c62f2eef9406f24c355511f9217967df23e70fa7f5b54ff \
|
||||
--hash=sha256:7c20cc83b0df47129ec6ed8a47fa7dcfc309c5bad029464004162738502568bb \
|
||||
--hash=sha256:7d7cfac2547c93389fa303fc0c0eb6698825564e8389c41c9b60009c746207b6 \
|
||||
--hash=sha256:7d87c817b292efb748f1974f37e8bb8a8772ef92f05f84e507159360814bcc3f \
|
||||
--hash=sha256:8141f654432cf75144d6103bfac2286b8adf23467201590b173a74535d6be22d \
|
||||
--hash=sha256:849f2ff40264152f25589cb48ddb4a43d14db811f841ec73989bfc0c8c4853fa \
|
||||
--hash=sha256:880c84ce59f49776cf120f77e7ca04877c97c6887917078dbc369eb47004d7cf \
|
||||
--hash=sha256:94874584b733a18b310b0e954d53168e62cd4a0fd9db85b1903f0902a7eb33e8 \
|
||||
--hash=sha256:95603eff711b8f3b9596e1c961dbeb745a792ba1904141612f194e07edd71e5f \
|
||||
--hash=sha256:9585892091ae86045135d6a6129a644142d6a51b23e1428bb5de6d10bc0ce0c7 \
|
||||
--hash=sha256:977bf5be704a88d46bf5b228df8b44521b1f3119d741062191608b3a6a38f224 \
|
||||
--hash=sha256:9cdc46859024501c20ab74ad542cdf2f08b94b5ce384f2f569483fa3ed926d04 \
|
||||
--hash=sha256:a34a5f034b339f69ef7f6a134c22d04b92e07b6ddc1dd65382e7e4ec65d6437d \
|
||||
--hash=sha256:a655f7b755cfc5c07f2116b6dcf0ba148c89adef9a6d40c1b0f1fada878c4345 \
|
||||
--hash=sha256:a7d12f2d2df195c8c4e49d2cdbad640353a856c62ca2c624d8b47aa33b65a2a2 \
|
||||
--hash=sha256:abfe83e082c9208891e2158c1b5044a650ecec408b823bf6bf16cd7f8085cafa \
|
||||
--hash=sha256:b25077a971c7da47bd6846a912a747f6963776d90720c88603b1b55d81790780 \
|
||||
--hash=sha256:bf416a93e1331820c77e3429df26946dbd4fe105e9b487cd2d1b7298b75784a8 \
|
||||
--hash=sha256:c04ae27e076d81a3839047d8eed57c1e17e361640616fd520d752375e3ba8f0c \
|
||||
--hash=sha256:d5bea13c73f36c4346808df3fa806596163a7962b6d28001ca2a391cab856089 \
|
||||
--hash=sha256:d75bef34e69e7effb7b4849e3f830e3174d2cc6ec7273503fdde111c222dc9b3 \
|
||||
--hash=sha256:d93940664a5ccfd79f72dcb939b0c31a3479889f14f0eb95ec52976f8c0cae7d \
|
||||
--hash=sha256:d9c89c521dc90c7564358e525f849b93ad1d710553c1491f66b8cce8113bc901 \
|
||||
--hash=sha256:e0b36257dc90194784531c3b922d8d31fb2b4d8e5adfd27aff4eee7174176365 \
|
||||
--hash=sha256:e1135264bcd40965cd35b0869e36952f54825024befdc7a923df9a7d83cfd800 \
|
||||
--hash=sha256:e510d288e613d6927796dfb728e13e4530fc83b9ccac5888a21f7860486eab21 \
|
||||
--hash=sha256:ee9a2c9a4b2421e77f8fe33ed0621dea03c66c710707553020b1e32f3afb6240 \
|
||||
--hash=sha256:f19f11055ba2961eb39bdb1ff15763a53fca4fa0b5b624da3c7a528e83cdd09c \
|
||||
--hash=sha256:f26544bc10c83a2ff9aa2e093500c1b473f327faae31fb468d591e5823333376 \
|
||||
--hash=sha256:f4875cafc9a6482c04c7df52a725d1c41beb74913c0ff4ec8f189f1954a2afe9 \
|
||||
--hash=sha256:f5179088ef6487c475604b7898731a6ddeeada7702cfb2162155b016703a8475 \
|
||||
--hash=sha256:f63d1ae1ca17bb2c847e298c7bcf084a73d56d434b4c50509fb93a4b4300b0b2 \
|
||||
--hash=sha256:ff4928dc1e9704b567171c16787238201fdbf023665573c12c02146fe1e02eec
|
||||
# via -r requirements-base.in
|
||||
zc-lockfile==2.0 \
|
||||
--hash=sha256:307ad78227e48be260e64896ec8886edc7eae22d8ec53e4d528ab5537a83203b \
|
||||
--hash=sha256:cc33599b549f0c8a248cb72f3bf32d77712de1ff7ee8814312eb6456b42c015f
|
||||
# via cherrypy
|
||||
|
||||
# WARNING: The following packages were not pinned, but pip requires them to be
|
||||
# pinned when the requirements file includes hashes. Consider using the --allow-unsafe flag.
|
||||
# setuptools
|
17
requirements.in
Normal file
17
requirements.in
Normal file
@ -0,0 +1,17 @@
|
||||
urllib3==1.25.11
|
||||
requests==2.25.1
|
||||
PyNaCl==1.4.0
|
||||
gevent==20.9.0
|
||||
Flask==1.1.2
|
||||
PySocks==1.7.1
|
||||
stem==1.8.0
|
||||
deadsimplekv==0.3.2
|
||||
unpaddedbase32==0.2.0
|
||||
streamedrequests==1.0.3
|
||||
toomanyobjs==1.1.0
|
||||
niceware==0.2.1
|
||||
psutil==5.8.0
|
||||
filenuke==0.0.0
|
||||
watchdog==1.0.2
|
||||
ujson==4.0.1
|
||||
cffi==1.14.4
|
329
requirements.txt
Normal file
329
requirements.txt
Normal file
@ -0,0 +1,329 @@
|
||||
#
|
||||
# This file is autogenerated by pip-compile
|
||||
# To update, run:
|
||||
#
|
||||
# pip-compile --generate-hashes requirements.in
|
||||
#
|
||||
certifi==2018.11.29 \
|
||||
--hash=sha256:47f9c83ef4c0c621eaef743f133f09fa8a74a9b75f037e8624f83bd1b6626cb7 \
|
||||
--hash=sha256:993f830721089fef441cdfeb4b2c8c9df86f0c63239f06bd025a76a7daddb033 \
|
||||
# via requests
|
||||
cffi==1.14.4 \
|
||||
--hash=sha256:00a1ba5e2e95684448de9b89888ccd02c98d512064b4cb987d48f4b40aa0421e \
|
||||
--hash=sha256:00e28066507bfc3fe865a31f325c8391a1ac2916219340f87dfad602c3e48e5d \
|
||||
--hash=sha256:045d792900a75e8b1e1b0ab6787dd733a8190ffcf80e8c8ceb2fb10a29ff238a \
|
||||
--hash=sha256:0638c3ae1a0edfb77c6765d487fee624d2b1ee1bdfeffc1f0b58c64d149e7eec \
|
||||
--hash=sha256:105abaf8a6075dc96c1fe5ae7aae073f4696f2905fde6aeada4c9d2926752362 \
|
||||
--hash=sha256:155136b51fd733fa94e1c2ea5211dcd4c8879869008fc811648f16541bf99668 \
|
||||
--hash=sha256:1a465cbe98a7fd391d47dce4b8f7e5b921e6cd805ef421d04f5f66ba8f06086c \
|
||||
--hash=sha256:1d2c4994f515e5b485fd6d3a73d05526aa0fcf248eb135996b088d25dfa1865b \
|
||||
--hash=sha256:2c24d61263f511551f740d1a065eb0212db1dbbbbd241db758f5244281590c06 \
|
||||
--hash=sha256:51a8b381b16ddd370178a65360ebe15fbc1c71cf6f584613a7ea08bfad946698 \
|
||||
--hash=sha256:594234691ac0e9b770aee9fcdb8fa02c22e43e5c619456efd0d6c2bf276f3eb2 \
|
||||
--hash=sha256:5cf4be6c304ad0b6602f5c4e90e2f59b47653ac1ed9c662ed379fe48a8f26b0c \
|
||||
--hash=sha256:64081b3f8f6f3c3de6191ec89d7dc6c86a8a43911f7ecb422c60e90c70be41c7 \
|
||||
--hash=sha256:6bc25fc545a6b3d57b5f8618e59fc13d3a3a68431e8ca5fd4c13241cd70d0009 \
|
||||
--hash=sha256:798caa2a2384b1cbe8a2a139d80734c9db54f9cc155c99d7cc92441a23871c03 \
|
||||
--hash=sha256:7c6b1dece89874d9541fc974917b631406233ea0440d0bdfbb8e03bf39a49b3b \
|
||||
--hash=sha256:840793c68105fe031f34d6a086eaea153a0cd5c491cde82a74b420edd0a2b909 \
|
||||
--hash=sha256:8d6603078baf4e11edc4168a514c5ce5b3ba6e3e9c374298cb88437957960a53 \
|
||||
--hash=sha256:9cc46bc107224ff5b6d04369e7c595acb700c3613ad7bcf2e2012f62ece80c35 \
|
||||
--hash=sha256:9f7a31251289b2ab6d4012f6e83e58bc3b96bd151f5b5262467f4bb6b34a7c26 \
|
||||
--hash=sha256:9ffb888f19d54a4d4dfd4b3f29bc2c16aa4972f1c2ab9c4ab09b8ab8685b9c2b \
|
||||
--hash=sha256:a5ed8c05548b54b998b9498753fb9cadbfd92ee88e884641377d8a8b291bcc01 \
|
||||
--hash=sha256:a7711edca4dcef1a75257b50a2fbfe92a65187c47dab5a0f1b9b332c5919a3fb \
|
||||
--hash=sha256:af5c59122a011049aad5dd87424b8e65a80e4a6477419c0c1015f73fb5ea0293 \
|
||||
--hash=sha256:b18e0a9ef57d2b41f5c68beefa32317d286c3d6ac0484efd10d6e07491bb95dd \
|
||||
--hash=sha256:b4e248d1087abf9f4c10f3c398896c87ce82a9856494a7155823eb45a892395d \
|
||||
--hash=sha256:ba4e9e0ae13fc41c6b23299545e5ef73055213e466bd107953e4a013a5ddd7e3 \
|
||||
--hash=sha256:c6332685306b6417a91b1ff9fae889b3ba65c2292d64bd9245c093b1b284809d \
|
||||
--hash=sha256:d5ff0621c88ce83a28a10d2ce719b2ee85635e85c515f12bac99a95306da4b2e \
|
||||
--hash=sha256:d9efd8b7a3ef378dd61a1e77367f1924375befc2eba06168b6ebfa903a5e59ca \
|
||||
--hash=sha256:df5169c4396adc04f9b0a05f13c074df878b6052430e03f50e68adf3a57aa28d \
|
||||
--hash=sha256:ebb253464a5d0482b191274f1c8bf00e33f7e0b9c66405fbffc61ed2c839c775 \
|
||||
--hash=sha256:ec80dc47f54e6e9a78181ce05feb71a0353854cc26999db963695f950b5fb375 \
|
||||
--hash=sha256:f032b34669220030f905152045dfa27741ce1a6db3324a5bc0b96b6c7420c87b \
|
||||
--hash=sha256:f60567825f791c6f8a592f3c6e3bd93dd2934e3f9dac189308426bd76b00ef3b \
|
||||
--hash=sha256:f803eaa94c2fcda012c047e62bc7a51b0bdabda1cad7a92a522694ea2d76e49f \
|
||||
# via -r requirements.in, pynacl
|
||||
chardet==3.0.4 \
|
||||
--hash=sha256:84ab92ed1c4d4f16916e05906b6b75a6c0fb5db821cc65e70cbd64a3e2a5eaae \
|
||||
--hash=sha256:fc323ffcaeaed0e0a02bf4d117757b98aed530d9ed4531e3e15460124c106691 \
|
||||
# via requests
|
||||
click==7.0 \
|
||||
--hash=sha256:2335065e6395b9e67ca716de5f7526736bfa6ceead690adf616d925bdc622b13 \
|
||||
--hash=sha256:5b94b49521f6456670fdb30cd82a4eca9412788a93fa6dd6df72c94d5a8ff2d7 \
|
||||
# via flask
|
||||
deadsimplekv==0.3.2 \
|
||||
--hash=sha256:a725f4a9d1156ebb66b7535ac150006881e0365b715e34e3709214827b8b0c4c \
|
||||
--hash=sha256:df00262d26c3dcfecb710425a7413059480d8cf026216042d7cbffb8514818b2 \
|
||||
# via -r requirements.in
|
||||
filenuke==0.0.0 \
|
||||
--hash=sha256:147011c0125121469cae0a8a7f4df399f470e54aa29a08f2d2c099bf0118dcee \
|
||||
--hash=sha256:c55535dcecfdb27c5f4ce664d46e115950b5429763b5db75c198053646177f8f \
|
||||
# via -r requirements.in
|
||||
flask==1.1.2 \
|
||||
--hash=sha256:4efa1ae2d7c9865af48986de8aeb8504bf32c7f3d6fdc9353d34b21f4b127060 \
|
||||
--hash=sha256:8a4fdd8936eba2512e9c85df320a37e694c93945b33ef33c89946a340a238557 \
|
||||
# via -r requirements.in
|
||||
gevent==20.9.0 \
|
||||
--hash=sha256:1628a403fc9c3ea9b35924638a4d4fbe236f60ecdf4e22ed133fbbaf0bc7cb6b \
|
||||
--hash=sha256:2269574444113cb4ca1c1808ab9460a87fe25e1c34a6e36d975d4af46e4afff9 \
|
||||
--hash=sha256:324808a8558c733f7a9734525483795d52ca3bbd5662b24b361d81c075414b1f \
|
||||
--hash=sha256:5f6d48051d336561ec08995431ee4d265ac723a64bba99cc58c3eb1a4d4f5c8d \
|
||||
--hash=sha256:a8733a01974433d91308f8c44fa6cc13428b15bb39d46540657e260ff8852cb1 \
|
||||
--hash=sha256:adbb267067f56696b2babced3d0856aa39dcf14b8ccd2dffa1fab587b00c6f80 \
|
||||
--hash=sha256:b07fcbca3e819296979d82fac3d8b44f0d5ced57b9a04dffcfd194da99c8eb2d \
|
||||
--hash=sha256:b2948566003a1030e47507755fe1f446995e8671c0c67571091539e01faf94cc \
|
||||
--hash=sha256:e11de4b4d107ca2f35000eb08e9c4c4621c153103b400f48a9ea95b96d8c7e0b \
|
||||
--hash=sha256:fb33dc1ab27557bccd64ad4bf81e68c8b0d780fe937b1e2c0814558798137229 \
|
||||
# via -r requirements.in
|
||||
greenlet==0.4.17 \
|
||||
--hash=sha256:1023d7b43ca11264ab7052cb09f5635d4afdb43df55e0854498fc63070a0b206 \
|
||||
--hash=sha256:124a3ae41215f71dc91d1a3d45cbf2f84e46b543e5d60b99ecc20e24b4c8f272 \
|
||||
--hash=sha256:13037e2d7ab2145300676852fa069235512fdeba4ed1e3bb4b0677a04223c525 \
|
||||
--hash=sha256:3af587e9813f9bd8be9212722321a5e7be23b2bc37e6323a90e592ab0c2ef117 \
|
||||
--hash=sha256:41d8835c69a78de718e466dd0e6bfd4b46125f21a67c3ff6d76d8d8059868d6b \
|
||||
--hash=sha256:4481002118b2f1588fa3d821936ffdc03db80ef21186b62b90c18db4ba5e743b \
|
||||
--hash=sha256:47825c3a109f0331b1e54c1173d4e57fa000aa6c96756b62852bfa1af91cd652 \
|
||||
--hash=sha256:5494e3baeacc371d988345fbf8aa4bd15555b3077c40afcf1994776bb6d77eaf \
|
||||
--hash=sha256:75e4c27188f28149b74e7685809f9227410fd15432a4438fc48627f518577fa5 \
|
||||
--hash=sha256:97f2b01ab622a4aa4b3724a3e1fba66f47f054c434fbaa551833fa2b41e3db51 \
|
||||
--hash=sha256:a34023b9eabb3525ee059f3bf33a417d2e437f7f17e341d334987d4091ae6072 \
|
||||
--hash=sha256:ac85db59aa43d78547f95fc7b6fd2913e02b9e9b09e2490dfb7bbdf47b2a4914 \
|
||||
--hash=sha256:be7a79988b8fdc5bbbeaed69e79cfb373da9759242f1565668be4fb7f3f37552 \
|
||||
--hash=sha256:bee111161420f341a346731279dd976be161b465c1286f82cc0779baf7b729e8 \
|
||||
--hash=sha256:ccd62f09f90b2730150d82f2f2ffc34d73c6ce7eac234aed04d15dc8a3023994 \
|
||||
--hash=sha256:d3436110ca66fe3981031cc6aff8cc7a40d8411d173dde73ddaa5b8445385e2d \
|
||||
--hash=sha256:e495096e3e2e8f7192afb6aaeba19babc4fb2bdf543d7b7fed59e00c1df7f170 \
|
||||
--hash=sha256:e66a824f44892bc4ec66c58601a413419cafa9cec895e63d8da889c8a1a4fa4a \
|
||||
# via gevent
|
||||
idna==2.7 \
|
||||
--hash=sha256:156a6814fb5ac1fc6850fb002e0852d56c0c8d2531923a51032d1b70760e186e \
|
||||
--hash=sha256:684a38a6f903c1d71d6d5fac066b58d7768af4de2b832e426ec79c30daa94a16 \
|
||||
# via requests
|
||||
itsdangerous==1.1.0 \
|
||||
--hash=sha256:321b033d07f2a4136d3ec762eac9f16a10ccd60f53c0c91af90217ace7ba1f19 \
|
||||
--hash=sha256:b12271b2047cb23eeb98c8b5622e2e5c5e9abd9784a153e9d8ef9cb4dd09d749 \
|
||||
# via flask
|
||||
jinja2==2.11.1 \
|
||||
--hash=sha256:93187ffbc7808079673ef52771baa950426fd664d3aad1d0fa3e95644360e250 \
|
||||
--hash=sha256:b0eaf100007721b5c16c1fc1eecb87409464edc10469ddc9a22a27a99123be49 \
|
||||
# via flask
|
||||
markupsafe==1.1.1 \
|
||||
--hash=sha256:00bc623926325b26bb9605ae9eae8a215691f33cae5df11ca5424f06f2d1f473 \
|
||||
--hash=sha256:09027a7803a62ca78792ad89403b1b7a73a01c8cb65909cd876f7fcebd79b161 \
|
||||
--hash=sha256:09c4b7f37d6c648cb13f9230d847adf22f8171b1ccc4d5682398e77f40309235 \
|
||||
--hash=sha256:1027c282dad077d0bae18be6794e6b6b8c91d58ed8a8d89a89d59693b9131db5 \
|
||||
--hash=sha256:13d3144e1e340870b25e7b10b98d779608c02016d5184cfb9927a9f10c689f42 \
|
||||
--hash=sha256:24982cc2533820871eba85ba648cd53d8623687ff11cbb805be4ff7b4c971aff \
|
||||
--hash=sha256:29872e92839765e546828bb7754a68c418d927cd064fd4708fab9fe9c8bb116b \
|
||||
--hash=sha256:43a55c2930bbc139570ac2452adf3d70cdbb3cfe5912c71cdce1c2c6bbd9c5d1 \
|
||||
--hash=sha256:46c99d2de99945ec5cb54f23c8cd5689f6d7177305ebff350a58ce5f8de1669e \
|
||||
--hash=sha256:500d4957e52ddc3351cabf489e79c91c17f6e0899158447047588650b5e69183 \
|
||||
--hash=sha256:535f6fc4d397c1563d08b88e485c3496cf5784e927af890fb3c3aac7f933ec66 \
|
||||
--hash=sha256:596510de112c685489095da617b5bcbbac7dd6384aeebeda4df6025d0256a81b \
|
||||
--hash=sha256:62fe6c95e3ec8a7fad637b7f3d372c15ec1caa01ab47926cfdf7a75b40e0eac1 \
|
||||
--hash=sha256:6788b695d50a51edb699cb55e35487e430fa21f1ed838122d722e0ff0ac5ba15 \
|
||||
--hash=sha256:6dd73240d2af64df90aa7c4e7481e23825ea70af4b4922f8ede5b9e35f78a3b1 \
|
||||
--hash=sha256:717ba8fe3ae9cc0006d7c451f0bb265ee07739daf76355d06366154ee68d221e \
|
||||
--hash=sha256:79855e1c5b8da654cf486b830bd42c06e8780cea587384cf6545b7d9ac013a0b \
|
||||
--hash=sha256:7c1699dfe0cf8ff607dbdcc1e9b9af1755371f92a68f706051cc8c37d447c905 \
|
||||
--hash=sha256:88e5fcfb52ee7b911e8bb6d6aa2fd21fbecc674eadd44118a9cc3863f938e735 \
|
||||
--hash=sha256:8defac2f2ccd6805ebf65f5eeb132adcf2ab57aa11fdf4c0dd5169a004710e7d \
|
||||
--hash=sha256:98c7086708b163d425c67c7a91bad6e466bb99d797aa64f965e9d25c12111a5e \
|
||||
--hash=sha256:9add70b36c5666a2ed02b43b335fe19002ee5235efd4b8a89bfcf9005bebac0d \
|
||||
--hash=sha256:9bf40443012702a1d2070043cb6291650a0841ece432556f784f004937f0f32c \
|
||||
--hash=sha256:ade5e387d2ad0d7ebf59146cc00c8044acbd863725f887353a10df825fc8ae21 \
|
||||
--hash=sha256:b00c1de48212e4cc9603895652c5c410df699856a2853135b3967591e4beebc2 \
|
||||
--hash=sha256:b1282f8c00509d99fef04d8ba936b156d419be841854fe901d8ae224c59f0be5 \
|
||||
--hash=sha256:b2051432115498d3562c084a49bba65d97cf251f5a331c64a12ee7e04dacc51b \
|
||||
--hash=sha256:ba59edeaa2fc6114428f1637ffff42da1e311e29382d81b339c1817d37ec93c6 \
|
||||
--hash=sha256:c8716a48d94b06bb3b2524c2b77e055fb313aeb4ea620c8dd03a105574ba704f \
|
||||
--hash=sha256:cd5df75523866410809ca100dc9681e301e3c27567cf498077e8551b6d20e42f \
|
||||
--hash=sha256:cdb132fc825c38e1aeec2c8aa9338310d29d337bebbd7baa06889d09a60a1fa2 \
|
||||
--hash=sha256:e249096428b3ae81b08327a63a485ad0878de3fb939049038579ac0ef61e17e7 \
|
||||
--hash=sha256:e8313f01ba26fbbe36c7be1966a7b7424942f670f38e666995b88d012765b9be \
|
||||
# via jinja2
|
||||
niceware==0.2.1 \
|
||||
--hash=sha256:0f8b192f2a1e800e068474f6e208be9c7e2857664b33a96f4045340de4e5c69c \
|
||||
--hash=sha256:cf2dc0e1567d36d067c61b32fed0f1b9c4534ed511f9eeead4ba548d03b5c9eb \
|
||||
# via -r requirements.in
|
||||
psutil==5.8.0 \
|
||||
--hash=sha256:0066a82f7b1b37d334e68697faba68e5ad5e858279fd6351c8ca6024e8d6ba64 \
|
||||
--hash=sha256:02b8292609b1f7fcb34173b25e48d0da8667bc85f81d7476584d889c6e0f2131 \
|
||||
--hash=sha256:0ae6f386d8d297177fd288be6e8d1afc05966878704dad9847719650e44fc49c \
|
||||
--hash=sha256:0c9ccb99ab76025f2f0bbecf341d4656e9c1351db8cc8a03ccd62e318ab4b5c6 \
|
||||
--hash=sha256:0dd4465a039d343925cdc29023bb6960ccf4e74a65ad53e768403746a9207023 \
|
||||
--hash=sha256:12d844996d6c2b1d3881cfa6fa201fd635971869a9da945cf6756105af73d2df \
|
||||
--hash=sha256:1bff0d07e76114ec24ee32e7f7f8d0c4b0514b3fae93e3d2aaafd65d22502394 \
|
||||
--hash=sha256:245b5509968ac0bd179287d91210cd3f37add77dad385ef238b275bad35fa1c4 \
|
||||
--hash=sha256:28ff7c95293ae74bf1ca1a79e8805fcde005c18a122ca983abf676ea3466362b \
|
||||
--hash=sha256:36b3b6c9e2a34b7d7fbae330a85bf72c30b1c827a4366a07443fc4b6270449e2 \
|
||||
--hash=sha256:52de075468cd394ac98c66f9ca33b2f54ae1d9bff1ef6b67a212ee8f639ec06d \
|
||||
--hash=sha256:5da29e394bdedd9144c7331192e20c1f79283fb03b06e6abd3a8ae45ffecee65 \
|
||||
--hash=sha256:61f05864b42fedc0771d6d8e49c35f07efd209ade09a5afe6a5059e7bb7bf83d \
|
||||
--hash=sha256:6223d07a1ae93f86451d0198a0c361032c4c93ebd4bf6d25e2fb3edfad9571ef \
|
||||
--hash=sha256:6323d5d845c2785efb20aded4726636546b26d3b577aded22492908f7c1bdda7 \
|
||||
--hash=sha256:6ffe81843131ee0ffa02c317186ed1e759a145267d54fdef1bc4ea5f5931ab60 \
|
||||
--hash=sha256:74f2d0be88db96ada78756cb3a3e1b107ce8ab79f65aa885f76d7664e56928f6 \
|
||||
--hash=sha256:74fb2557d1430fff18ff0d72613c5ca30c45cdbfcddd6a5773e9fc1fe9364be8 \
|
||||
--hash=sha256:90d4091c2d30ddd0a03e0b97e6a33a48628469b99585e2ad6bf21f17423b112b \
|
||||
--hash=sha256:90f31c34d25b1b3ed6c40cdd34ff122b1887a825297c017e4cbd6796dd8b672d \
|
||||
--hash=sha256:99de3e8739258b3c3e8669cb9757c9a861b2a25ad0955f8e53ac662d66de61ac \
|
||||
--hash=sha256:c6a5fd10ce6b6344e616cf01cc5b849fa8103fbb5ba507b6b2dee4c11e84c935 \
|
||||
--hash=sha256:ce8b867423291cb65cfc6d9c4955ee9bfc1e21fe03bb50e177f2b957f1c2469d \
|
||||
--hash=sha256:d225cd8319aa1d3c85bf195c4e07d17d3cd68636b8fc97e6cf198f782f99af28 \
|
||||
--hash=sha256:ea313bb02e5e25224e518e4352af4bf5e062755160f77e4b1767dd5ccb65f876 \
|
||||
--hash=sha256:ea372bcc129394485824ae3e3ddabe67dc0b118d262c568b4d2602a7070afdb0 \
|
||||
--hash=sha256:f4634b033faf0d968bb9220dd1c793b897ab7f1189956e1aa9eae752527127d3 \
|
||||
--hash=sha256:fcc01e900c1d7bee2a37e5d6e4f9194760a93597c97fee89c4ae51701de03563 \
|
||||
# via -r requirements.in
|
||||
pycparser==2.19 \
|
||||
--hash=sha256:a988718abfad80b6b157acce7bf130a30876d27603738ac39f140993246b25b3 \
|
||||
# via cffi
|
||||
pynacl==1.4.0 \
|
||||
--hash=sha256:06cbb4d9b2c4bd3c8dc0d267416aaed79906e7b33f114ddbf0911969794b1cc4 \
|
||||
--hash=sha256:11335f09060af52c97137d4ac54285bcb7df0cef29014a1a4efe64ac065434c4 \
|
||||
--hash=sha256:2fe0fc5a2480361dcaf4e6e7cea00e078fcda07ba45f811b167e3f99e8cff574 \
|
||||
--hash=sha256:30f9b96db44e09b3304f9ea95079b1b7316b2b4f3744fe3aaecccd95d547063d \
|
||||
--hash=sha256:511d269ee845037b95c9781aa702f90ccc36036f95d0f31373a6a79bd8242e25 \
|
||||
--hash=sha256:537a7ccbea22905a0ab36ea58577b39d1fa9b1884869d173b5cf111f006f689f \
|
||||
--hash=sha256:54e9a2c849c742006516ad56a88f5c74bf2ce92c9f67435187c3c5953b346505 \
|
||||
--hash=sha256:757250ddb3bff1eecd7e41e65f7f833a8405fede0194319f87899690624f2122 \
|
||||
--hash=sha256:7757ae33dae81c300487591c68790dfb5145c7d03324000433d9a2c141f82af7 \
|
||||
--hash=sha256:7c6092102219f59ff29788860ccb021e80fffd953920c4a8653889c029b2d420 \
|
||||
--hash=sha256:8122ba5f2a2169ca5da936b2e5a511740ffb73979381b4229d9188f6dcb22f1f \
|
||||
--hash=sha256:9c4a7ea4fb81536c1b1f5cc44d54a296f96ae78c1ebd2311bd0b60be45a48d96 \
|
||||
--hash=sha256:cd401ccbc2a249a47a3a1724c2918fcd04be1f7b54eb2a5a71ff915db0ac51c6 \
|
||||
--hash=sha256:d452a6746f0a7e11121e64625109bc4468fc3100452817001dbe018bb8b08514 \
|
||||
--hash=sha256:ea6841bc3a76fa4942ce00f3bda7d436fda21e2d91602b9e21b7ca9ecab8f3ff \
|
||||
--hash=sha256:f8851ab9041756003119368c1e6cd0b9c631f46d686b3904b18c0139f4419f80 \
|
||||
# via -r requirements.in
|
||||
pysocks==1.7.1 \
|
||||
--hash=sha256:08e69f092cc6dbe92a0fdd16eeb9b9ffbc13cadfe5ca4c7bd92ffb078b293299 \
|
||||
--hash=sha256:2725bd0a9925919b9b51739eea5f9e2bae91e83288108a9ad338b2e3a4435ee5 \
|
||||
--hash=sha256:3f8804571ebe159c380ac6de37643bb4685970655d3bba243530d6558b799aa0 \
|
||||
# via -r requirements.in
|
||||
requests==2.25.1 \
|
||||
--hash=sha256:27973dd4a904a4f13b263a19c866c13b92a39ed1c964655f025f3f8d3d75b804 \
|
||||
--hash=sha256:c210084e36a42ae6b9219e00e48287def368a26d03a048ddad7bfee44f75871e \
|
||||
# via -r requirements.in, streamedrequests
|
||||
six==1.12.0 \
|
||||
--hash=sha256:3350809f0555b11f552448330d0b52d5f24c91a322ea4a15ef22629740f3761c \
|
||||
--hash=sha256:d16a0141ec1a18405cd4ce8b4613101da75da0e9a7aec5bdd4fa804d0e0eba73 \
|
||||
# via pynacl
|
||||
stem==1.8.0 \
|
||||
--hash=sha256:a0b48ea6224e95f22aa34c0bc3415f0eb4667ddeae3dfb5e32a6920c185568c2 \
|
||||
# via -r requirements.in
|
||||
streamedrequests==1.0.3 \
|
||||
--hash=sha256:4388ffc0ee94dda719dafc4324b8ddd108cb2231ec59871de79e2592bf4eef0a \
|
||||
--hash=sha256:ee68417a1522e75c35b1b2d5f3b6f7e76a3a1a6c0ef5e0c573d08307910079d8 \
|
||||
# via -r requirements.in
|
||||
toomanyobjs==1.1.0 \
|
||||
--hash=sha256:99e27468f9dad19127be9e2fb086b42acd69aed9ad7e63cef74d6e4389be0534 \
|
||||
# via -r requirements.in
|
||||
ujson==4.0.1 \
|
||||
--hash=sha256:078808c385036cba73cad96f498310c61e9b5ae5ac9ea01e7c3996ece544b556 \
|
||||
--hash=sha256:0a2e1b211714eb1ec0772a013ec9967f8f95f21c84e8f46382e9f8a32ae781fe \
|
||||
--hash=sha256:0f412c3f59b1ab0f40018235224ca0cf29232d0201ff5085618565a8a9c810ed \
|
||||
--hash=sha256:26cf6241b36ff5ce4539ae687b6b02673109c5e3efc96148806a7873eaa229d3 \
|
||||
--hash=sha256:2b2d9264ac76aeb11f590f7a1ccff0689ba1313adacbb6d38d3b15f21a392897 \
|
||||
--hash=sha256:4f12b0b4e235b35d49f15227b0a827e614c52dda903c58a8f5523936c233dfc7 \
|
||||
--hash=sha256:4fe8c6112b732cba5a722f7cbe22f18d405f6f44415794a5b46473a477635233 \
|
||||
--hash=sha256:51480048373cf97a6b97fcd70c3586ca0a31f27e22ab680fb14c1f22bedbf743 \
|
||||
--hash=sha256:568bb3e7f035006147af4ce3a9ced7d126c92e1a8607c7b2266007b1c1162c53 \
|
||||
--hash=sha256:5fe1536465b1c86e32a47113abd3178001b7c2dcd61f95f336fe2febf4661e74 \
|
||||
--hash=sha256:71703a269f074ff65b9d7746662e4b3e76a4af443e532218af1e8ce15d9b1e7b \
|
||||
--hash=sha256:7a1545ac2476db4cc1f0f236603ccbb50991fc1bba480cda1bc06348cc2a2bf0 \
|
||||
--hash=sha256:a5200a68f1dcf3ce275e1cefbcfa3914b70c2b5e2f71c2e31556aa1f7244c845 \
|
||||
--hash=sha256:a618af22407baeadb3f046f81e7a5ee5e9f8b0b716d2b564f92276a54d26a823 \
|
||||
--hash=sha256:a79bca47eafb31c74b38e68623bc9b2bb930cb48fab1af31c8f2cb68cf473421 \
|
||||
--hash=sha256:b87379a3f8046d6d111762d81f3384bf38ab24b1535c841fe867a4a097d84523 \
|
||||
--hash=sha256:bd4c77aee3ffb920e2dbc21a9e0c7945a400557ce671cfd57dbd569f5ebc619d \
|
||||
--hash=sha256:c354c1617b0a4378b6279d0cd511b769500cf3fa7c42e8e004cbbbb6b4c2a875 \
|
||||
--hash=sha256:c604024bd853b5df6be7d933e934da8dd139e6159564db7c55b92a9937678093 \
|
||||
--hash=sha256:e7ab24942b2d57920d75b817b8eead293026db003247e26f99506bdad86c61b4 \
|
||||
--hash=sha256:f8a60928737a9a47e692fcd661ef2b5d75ba22c7c930025bd95e338f2a6e15bc \
|
||||
# via -r requirements.in
|
||||
unpaddedbase32==0.2.0 \
|
||||
--hash=sha256:4aacee75f8fd6c8cf129842ecba45ca59c11bfb13dae19d86f32b48fa3715403 \
|
||||
--hash=sha256:b7b780c31d27d55e66abf6c221216a35690ee8892c2daacff7f2528e229bd9c3 \
|
||||
# via -r requirements.in
|
||||
urllib3==1.25.11 \
|
||||
--hash=sha256:8d7eaa5a82a1cac232164990f04874c594c9453ec55eef02eab885aa02fc17a2 \
|
||||
--hash=sha256:f5321fbe4bf3fefa0efd0bfe7fb14e90909eb62a48ccda331726b4319897dd5e \
|
||||
# via -r requirements.in, requests
|
||||
watchdog==1.0.2 \
|
||||
--hash=sha256:016b01495b9c55b5d4126ed8ae75d93ea0d99377084107c33162df52887cee18 \
|
||||
--hash=sha256:101532b8db506559e52a9b5d75a308729b3f68264d930670e6155c976d0e52a0 \
|
||||
--hash=sha256:27d9b4666938d5d40afdcdf2c751781e9ce36320788b70208d0f87f7401caf93 \
|
||||
--hash=sha256:2f1ade0d0802503fda4340374d333408831cff23da66d7e711e279ba50fe6c4a \
|
||||
--hash=sha256:376cbc2a35c0392b0fe7ff16fbc1b303fd99d4dd9911ab5581ee9d69adc88982 \
|
||||
--hash=sha256:57f05e55aa603c3b053eed7e679f0a83873c540255b88d58c6223c7493833bac \
|
||||
--hash=sha256:5f1f3b65142175366ba94c64d8d4c8f4015825e0beaacee1c301823266b47b9b \
|
||||
--hash=sha256:602dbd9498592eacc42e0632c19781c3df1728ef9cbab555fab6778effc29eeb \
|
||||
--hash=sha256:68744de2003a5ea2dfbb104f9a74192cf381334a9e2c0ed2bbe1581828d50b61 \
|
||||
--hash=sha256:85e6574395aa6c1e14e0f030d9d7f35c2340a6cf95d5671354ce876ac3ffdd4d \
|
||||
--hash=sha256:b1d723852ce90a14abf0ec0ca9e80689d9509ee4c9ee27163118d87b564a12ac \
|
||||
--hash=sha256:d948ad9ab9aba705f9836625b32e965b9ae607284811cd98334423f659ea537a \
|
||||
--hash=sha256:e2a531e71be7b5cc3499ae2d1494d51b6a26684bcc7c3146f63c810c00e8a3cc \
|
||||
--hash=sha256:e7c73edef48f4ceeebb987317a67e0080e5c9228601ff67b3c4062fa020403c7 \
|
||||
--hash=sha256:ee21aeebe6b3e51e4ba64564c94cee8dbe7438b9cb60f0bb350c4fa70d1b52c2 \
|
||||
--hash=sha256:f1d0e878fd69129d0d68b87cee5d9543f20d8018e82998efb79f7e412d42154a \
|
||||
--hash=sha256:f84146f7864339c8addf2c2b9903271df21d18d2c721e9a77f779493234a82b5 \
|
||||
# via -r requirements.in
|
||||
werkzeug==0.15.5 \
|
||||
--hash=sha256:87ae4e5b5366da2347eb3116c0e6c681a0e939a33b2805e2c0cbd282664932c4 \
|
||||
--hash=sha256:a13b74dd3c45f758d4ebdb224be8f1ab8ef58b3c0ffc1783a8c7d9f4f50227e6 \
|
||||
# via flask
|
||||
zope.event==4.4 \
|
||||
--hash=sha256:69c27debad9bdacd9ce9b735dad382142281ac770c4a432b533d6d65c4614bcf \
|
||||
--hash=sha256:d8e97d165fd5a0997b45f5303ae11ea3338becfe68c401dd88ffd2113fe5cae7 \
|
||||
# via gevent
|
||||
zope.interface==5.1.0 \
|
||||
--hash=sha256:0103cba5ed09f27d2e3de7e48bb320338592e2fabc5ce1432cf33808eb2dfd8b \
|
||||
--hash=sha256:14415d6979356629f1c386c8c4249b4d0082f2ea7f75871ebad2e29584bd16c5 \
|
||||
--hash=sha256:1ae4693ccee94c6e0c88a4568fb3b34af8871c60f5ba30cf9f94977ed0e53ddd \
|
||||
--hash=sha256:1b87ed2dc05cb835138f6a6e3595593fea3564d712cb2eb2de963a41fd35758c \
|
||||
--hash=sha256:269b27f60bcf45438e8683269f8ecd1235fa13e5411de93dae3b9ee4fe7f7bc7 \
|
||||
--hash=sha256:27d287e61639d692563d9dab76bafe071fbeb26818dd6a32a0022f3f7ca884b5 \
|
||||
--hash=sha256:39106649c3082972106f930766ae23d1464a73b7d30b3698c986f74bf1256a34 \
|
||||
--hash=sha256:40e4c42bd27ed3c11b2c983fecfb03356fae1209de10686d03c02c8696a1d90e \
|
||||
--hash=sha256:461d4339b3b8f3335d7e2c90ce335eb275488c587b61aca4b305196dde2ff086 \
|
||||
--hash=sha256:4f98f70328bc788c86a6a1a8a14b0ea979f81ae6015dd6c72978f1feff70ecda \
|
||||
--hash=sha256:558a20a0845d1a5dc6ff87cd0f63d7dac982d7c3be05d2ffb6322a87c17fa286 \
|
||||
--hash=sha256:562dccd37acec149458c1791da459f130c6cf8902c94c93b8d47c6337b9fb826 \
|
||||
--hash=sha256:5e86c66a6dea8ab6152e83b0facc856dc4d435fe0f872f01d66ce0a2131b7f1d \
|
||||
--hash=sha256:60a207efcd8c11d6bbeb7862e33418fba4e4ad79846d88d160d7231fcb42a5ee \
|
||||
--hash=sha256:645a7092b77fdbc3f68d3cc98f9d3e71510e419f54019d6e282328c0dd140dcd \
|
||||
--hash=sha256:6874367586c020705a44eecdad5d6b587c64b892e34305bb6ed87c9bbe22a5e9 \
|
||||
--hash=sha256:74bf0a4f9091131de09286f9a605db449840e313753949fe07c8d0fe7659ad1e \
|
||||
--hash=sha256:7b726194f938791a6691c7592c8b9e805fc6d1b9632a833b9c0640828cd49cbc \
|
||||
--hash=sha256:8149ded7f90154fdc1a40e0c8975df58041a6f693b8f7edcd9348484e9dc17fe \
|
||||
--hash=sha256:8cccf7057c7d19064a9e27660f5aec4e5c4001ffcf653a47531bde19b5aa2a8a \
|
||||
--hash=sha256:911714b08b63d155f9c948da2b5534b223a1a4fc50bb67139ab68b277c938578 \
|
||||
--hash=sha256:a5f8f85986197d1dd6444763c4a15c991bfed86d835a1f6f7d476f7198d5f56a \
|
||||
--hash=sha256:a744132d0abaa854d1aad50ba9bc64e79c6f835b3e92521db4235a1991176813 \
|
||||
--hash=sha256:af2c14efc0bb0e91af63d00080ccc067866fb8cbbaca2b0438ab4105f5e0f08d \
|
||||
--hash=sha256:b054eb0a8aa712c8e9030065a59b5e6a5cf0746ecdb5f087cca5ec7685690c19 \
|
||||
--hash=sha256:b0becb75418f8a130e9d465e718316cd17c7a8acce6fe8fe07adc72762bee425 \
|
||||
--hash=sha256:b1d2ed1cbda2ae107283befd9284e650d840f8f7568cb9060b5466d25dc48975 \
|
||||
--hash=sha256:ba4261c8ad00b49d48bbb3b5af388bb7576edfc0ca50a49c11dcb77caa1d897e \
|
||||
--hash=sha256:d1fe9d7d09bb07228650903d6a9dc48ea649e3b8c69b1d263419cc722b3938e8 \
|
||||
--hash=sha256:d7804f6a71fc2dda888ef2de266727ec2f3915373d5a785ed4ddc603bbc91e08 \
|
||||
--hash=sha256:da2844fba024dd58eaa712561da47dcd1e7ad544a257482392472eae1c86d5e5 \
|
||||
--hash=sha256:dcefc97d1daf8d55199420e9162ab584ed0893a109f45e438b9794ced44c9fd0 \
|
||||
--hash=sha256:dd98c436a1fc56f48c70882cc243df89ad036210d871c7427dc164b31500dc11 \
|
||||
--hash=sha256:e74671e43ed4569fbd7989e5eecc7d06dc134b571872ab1d5a88f4a123814e9f \
|
||||
--hash=sha256:eb9b92f456ff3ec746cd4935b73c1117538d6124b8617bc0fe6fda0b3816e345 \
|
||||
--hash=sha256:ebb4e637a1fb861c34e48a00d03cffa9234f42bef923aec44e5625ffb9a8e8f9 \
|
||||
--hash=sha256:ef739fe89e7f43fb6494a43b1878a36273e5924869ba1d866f752c5812ae8d58 \
|
||||
--hash=sha256:f40db0e02a8157d2b90857c24d89b6310f9b6c3642369852cdc3b5ac49b92afc \
|
||||
--hash=sha256:f68bf937f113b88c866d090fea0bc52a098695173fc613b055a17ff0cf9683b6 \
|
||||
--hash=sha256:fb55c182a3f7b84c1a2d6de5fa7b1a05d4660d866b91dbf8d74549c57a1499e8 \
|
||||
# via gevent
|
||||
|
||||
# WARNING: The following packages were not pinned, but pip requires them to be
|
||||
# pinned when the requirements file includes hashes. Consider using the --allow-unsafe flag.
|
||||
# setuptools
|
184
run-onionr-node.py
Executable file
184
run-onionr-node.py
Executable file
@ -0,0 +1,184 @@
|
||||
#!/usr/bin/env python3
|
||||
|
||||
import argparse
|
||||
import os
|
||||
from threading import Thread
|
||||
from time import sleep
|
||||
from subprocess import DEVNULL
|
||||
|
||||
import ujson
|
||||
from psutil import Popen
|
||||
from psutil import Process
|
||||
import psutil
|
||||
|
||||
import sys
|
||||
import curses
|
||||
|
||||
script_dir = os.path.dirname(os.path.realpath(__file__))
|
||||
sys.path.append(script_dir + '/src/')
|
||||
|
||||
from etc import onionrvalues
|
||||
|
||||
|
||||
sub_script = script_dir + '/' + onionrvalues.SCRIPT_NAME
|
||||
|
||||
|
||||
def show_info(p: Process):
|
||||
def pbar(window):
|
||||
window.addstr(8, 10, "Onionr statistics")
|
||||
window.addstr(9, 10, "-" * 17)
|
||||
curses.curs_set(0)
|
||||
while True:
|
||||
threads = p.num_threads()
|
||||
open_files = len(p.open_files())
|
||||
cpu_percent = p.cpu_percent()
|
||||
block_count = len(blockmetadb.get_block_list())
|
||||
for proc in p.children(recursive=True):
|
||||
threads += proc.num_threads()
|
||||
cpu_percent += proc.cpu_percent()
|
||||
try:
|
||||
open_files += len(proc.open_files())
|
||||
except psutil.AccessDenied:
|
||||
pass
|
||||
cpu_percent = cpu_percent * 100
|
||||
window.addstr(11, 10, f"Threads: {threads}")
|
||||
window.addstr(10, 10, f"Open files: {open_files}")
|
||||
window.addstr(12, 10, f"CPU: {cpu_percent}%")
|
||||
window.addstr(13, 10, f"Blocks: {block_count}")
|
||||
window.refresh()
|
||||
sleep(0.5)
|
||||
sleep(15)
|
||||
curses.wrapper(pbar)
|
||||
while True:
|
||||
sleep(1)
|
||||
|
||||
|
||||
parser = argparse.ArgumentParser()
|
||||
|
||||
parser.add_argument(
|
||||
"--bind-address", help="Address to bind to. Be very careful with non-loopback",
|
||||
type=str, default="")
|
||||
parser.add_argument(
|
||||
"--port", help="Port to bind to, must be available and possible",
|
||||
type=int, default=0)
|
||||
parser.add_argument(
|
||||
"--use-bootstrap-file", help="Use bootstrap node list file",
|
||||
type=int, default=1)
|
||||
parser.add_argument(
|
||||
"--show-stats", help="Display curses output of Onionr stats",
|
||||
type=int, default=0)
|
||||
parser.add_argument(
|
||||
"--onboarding", help="Use Onionr onboarding (if first load)",
|
||||
type=int, default=1)
|
||||
parser.add_argument(
|
||||
"--security-level", help="Set Onionr security level",
|
||||
type=int, default=0)
|
||||
parser.add_argument(
|
||||
'--open-ui', help='Open onionr web ui after started',
|
||||
type=int, default=1)
|
||||
parser.add_argument(
|
||||
'--random-localhost-ip', help='bind to random localhost IP for extra security',
|
||||
type=int, default=1)
|
||||
parser.add_argument(
|
||||
'--use-tor', help='Use Tor transport',
|
||||
type=int, default=1)
|
||||
parser.add_argument(
|
||||
'--private-key', help='Use existing private key',
|
||||
type=str, default=0)
|
||||
parser.add_argument(
|
||||
'--animated-background', help='Animated background on webui index. Just for looks.',
|
||||
type=int, default=0)
|
||||
parser.add_argument(
|
||||
'--keep-log-on-exit', help='Onionr can keep or delete its log file on exit',
|
||||
type=int, default=0)
|
||||
parser.add_argument(
|
||||
'--use-upload-mixing', help='Re-upload blocks uploaded to us. Slow but more secure',
|
||||
type=int, default=0)
|
||||
parser.add_argument(
|
||||
'--dev-mode',
|
||||
help='Developer mode makes restarting and testing Onionr less tedious during development',
|
||||
type=int, default=0)
|
||||
parser.add_argument(
|
||||
'--disable-plugin-list',
|
||||
help='plugins to disable by name, separate with commas',
|
||||
type=str, default='chat'
|
||||
)
|
||||
parser.add_argument(
|
||||
'--store-plaintext',
|
||||
help='store plaintext blocks or not. note that encrypted blocks may not really be encrypted, but we cannot detect that',
|
||||
type=int, default=1
|
||||
)
|
||||
|
||||
args = parser.parse_args()
|
||||
|
||||
p = Popen([sub_script, 'version'], stdout=DEVNULL)
|
||||
p.wait()
|
||||
from filepaths import config_file, keys_file
|
||||
from coredb import blockmetadb
|
||||
import onionrcrypto
|
||||
|
||||
|
||||
with open(config_file, 'r') as cf:
|
||||
config = ujson.loads(cf.read())
|
||||
|
||||
|
||||
if args.private_key:
|
||||
priv = args.private_key
|
||||
pub = onionrcrypto.cryptoutils.get_pub_key_from_priv(priv)
|
||||
with open(keys_file, "a") as f:
|
||||
f.write(',' + pub.decode() + ',' + priv)
|
||||
config['general']['public_key'] = pub
|
||||
|
||||
config['plugins']['disabled'] = args.disable_plugin_list.split(',')
|
||||
config['general']['dev_mode'] = False
|
||||
|
||||
config['general']['store_plaintext_blocks'] = True
|
||||
config['general']['use_bootstrap_list'] = True
|
||||
config['transports']['tor'] = True
|
||||
config['general']['bind_port'] = 0 # client api server port
|
||||
config['general']['bind_address'] = '' # client api server address
|
||||
|
||||
if args.bind_address:
|
||||
config['general']['bind_address'] = args.bind_address
|
||||
if args.port:
|
||||
config['client']['client']['port'] = args.port
|
||||
|
||||
if not args.use_bootstrap_file:
|
||||
config['general']['use_bootstrap_list'] = False
|
||||
if not args.store_plaintext:
|
||||
config['general']['store_plaintext_blocks'] = False
|
||||
if args.dev_mode:
|
||||
config['general']['dev_mode'] = True
|
||||
if not args.onboarding:
|
||||
config['onboarding']['done'] = True
|
||||
if not args.random_localhost_ip:
|
||||
config['general']['random_bind_ip'] = False
|
||||
if not args.use_tor:
|
||||
config['transports']['tor'] = False
|
||||
if not args.animated_background:
|
||||
config['ui']['animated_background'] = False
|
||||
if args.keep_log_on_exit:
|
||||
config['log']['file']['remove_on_exit'] = True
|
||||
else:
|
||||
config['log']['file']['remove_on_exit'] = False
|
||||
|
||||
config['general']['upload_mixing'] = False
|
||||
if args.use_upload_mixing:
|
||||
config['general']['upload_mixing'] = True
|
||||
config['general']['display_header'] = False
|
||||
config['general']['security_level'] = args.security_level
|
||||
|
||||
with open(config_file, 'w') as cf:
|
||||
cf.write(ujson.dumps(config, reject_bytes=False))
|
||||
|
||||
if args.open_ui:
|
||||
p = Popen([sub_script, 'start'], stdout=DEVNULL)
|
||||
sleep(2)
|
||||
Popen([sub_script, 'openhome'], stdout=DEVNULL)
|
||||
else:
|
||||
p = Popen([sub_script, 'start'], stdout=DEVNULL)
|
||||
|
||||
p = p.children()[0]
|
||||
if args.show_stats:
|
||||
Thread(target=show_info, args=[p], daemon=True).start()
|
||||
p.wait()
|
@ -13,10 +13,6 @@ for f in tests/*.py; do
|
||||
python3 "$f" || close # if needed
|
||||
let "ran++"
|
||||
done
|
||||
for f in tests/gossip-unittests/*.py; do
|
||||
python3 "$f" || close # if needed
|
||||
let "ran++"
|
||||
done
|
||||
echo "ran $ran unittests. Unittest Time: $SECONDS"
|
||||
ran=0;
|
||||
|
||||
|
33
sandboxed-onionr.py
Normal file
33
sandboxed-onionr.py
Normal file
@ -0,0 +1,33 @@
|
||||
#!/usr/bin/env python3
|
||||
|
||||
import os, sys
|
||||
import tempfile, shutil
|
||||
import stat
|
||||
|
||||
env_var = "firejailed-onionr"
|
||||
|
||||
def copytree(src, dst, symlinks=False, ignore=None):
|
||||
for item in os.listdir(src):
|
||||
if item in (".git", ".vscode", ".github"):
|
||||
continue
|
||||
s = os.path.join(src, item)
|
||||
d = os.path.join(dst, item)
|
||||
if os.path.isdir(s):
|
||||
shutil.copytree(s, d, symlinks, ignore)
|
||||
else:
|
||||
shutil.copy2(s, d)
|
||||
|
||||
env_var = "firejailed-onionr"
|
||||
directory = os.path.dirname(os.path.realpath(sys.argv[0]))
|
||||
|
||||
if not os.getenv(env_var):
|
||||
temp_dir = tempfile.mkdtemp()
|
||||
print(temp_dir)
|
||||
copytree(directory, temp_dir)
|
||||
os.system(f"firejail --env={env_var}={temp_dir} --private={temp_dir} python3 ./sandboxed-onionr.py")
|
||||
sys.exit(0)
|
||||
|
||||
os.system(f"python3 -m pip install -r ./requirements.txt --user")
|
||||
os.system(f"./onionr.sh start &")
|
||||
|
||||
|
@ -1 +1,7 @@
|
||||
This directory contains useful scripts and utilities that don't make sense to include as official Onionr features.
|
||||
|
||||
passphrase-generator.py: very simple utility to generate and print a strong passphrase to stdout. 256 bits of entropy by default.
|
||||
enable-dev-config.py/disable-dev-config.py: enable/disable dev default config setup
|
||||
block-spammer.py: attack tool for spamming blocks
|
||||
announce-attack.py: flood a node with false nodes
|
||||
run-unit-test-by-name: runs a unit test (no browser, runtime or intgegration test) by name
|
25
scripts/announce-attack.py
Normal file
25
scripts/announce-attack.py
Normal file
@ -0,0 +1,25 @@
|
||||
import sys
|
||||
import os
|
||||
import secrets
|
||||
import base64
|
||||
os.chdir('../')
|
||||
sys.path.append("src/")
|
||||
from onionrutils import stringvalidators
|
||||
from onionrutils import basicrequests
|
||||
|
||||
|
||||
def random_tor_generator():
|
||||
return base64.b32encode(secrets.token_bytes(35)).decode().replace("=", "").lower() + ".onion"
|
||||
|
||||
node = input("Enter node to attack. Note that you legally must use your own, and even that might lead to technical or legal issues")
|
||||
assert stringvalidators.validate_transport(node)
|
||||
|
||||
count = int(input("Attack amount: "))
|
||||
port = input("Socks:")
|
||||
for x in range(count):
|
||||
new = random_tor_generator()
|
||||
print(f"Introducing {new} to {node}")
|
||||
basicrequests.do_post_request(
|
||||
f'http://{node}/announce',
|
||||
data = {'node': new},
|
||||
port=port)
|
31
scripts/block-spammer.py
Executable file
31
scripts/block-spammer.py
Executable file
@ -0,0 +1,31 @@
|
||||
#!/usr/bin/env python3
|
||||
|
||||
"""Spam a bunch of Onionr blocks"""
|
||||
|
||||
# Please don't run this script on the real Onionr network. You wouldn't do anything but be annoying
|
||||
|
||||
print("Please don't run this script on Onionr networks that include more than you. You wouldn't do anything but be annoying, and probably violate law")
|
||||
|
||||
import sys
|
||||
import os
|
||||
if not os.path.exists('onionr.sh'):
|
||||
os.chdir('../')
|
||||
sys.path.append("src/")
|
||||
import onionrblocks
|
||||
|
||||
|
||||
amount = int(input("Number of blocks:"))
|
||||
expire = input("Expire in seconds:")
|
||||
|
||||
if not expire:
|
||||
expire = ""
|
||||
else:
|
||||
expire = int(expire)
|
||||
|
||||
for i in range(amount):
|
||||
if expire:
|
||||
print(onionrblocks.insert(data=os.urandom(32), expire=expire))
|
||||
else:
|
||||
print(onionrblocks.insert(data=os.urandom(32)))
|
||||
print(i, "done")
|
||||
|
51
scripts/client-api-request-crafter.py
Normal file
51
scripts/client-api-request-crafter.py
Normal file
@ -0,0 +1,51 @@
|
||||
#!/usr/bin/env python3
|
||||
|
||||
"""Craft and send requests to the local client API"""
|
||||
|
||||
|
||||
import sys
|
||||
import os
|
||||
if not os.path.exists('onionr.sh'):
|
||||
os.chdir('../')
|
||||
sys.path.append("src/")
|
||||
|
||||
import atexit
|
||||
import readline
|
||||
|
||||
histfile = os.path.join(os.path.expanduser("~"), ".onionr_history")
|
||||
try:
|
||||
readline.read_history_file(histfile)
|
||||
# default history len is -1 (infinite), which may grow unruly
|
||||
readline.set_history_length(1000)
|
||||
except FileNotFoundError:
|
||||
pass
|
||||
|
||||
atexit.register(readline.write_history_file, histfile)
|
||||
from onionrutils.localcommand import local_command
|
||||
from onionrutils.localcommand import get_hostname
|
||||
|
||||
try:
|
||||
print('API file found, probably running on ' + get_hostname())
|
||||
except TypeError:
|
||||
print('Onionr not running')
|
||||
sys.exit(1)
|
||||
print('1. get request (default)')
|
||||
print('2. post request')
|
||||
choice = input(">").lower().strip()
|
||||
post = False
|
||||
post_data = {}
|
||||
json = False
|
||||
endpoint = input("URL Endpoint: ")
|
||||
data = input("Data url param: ")
|
||||
if choice in ("2", "post", "post request"):
|
||||
post = True
|
||||
print("Enter post data")
|
||||
post_data = input()
|
||||
if post_data:
|
||||
print("Is this JSON?")
|
||||
json = input("y/n").lower().strip()
|
||||
if json == "y":
|
||||
json = True
|
||||
|
||||
ret = local_command(endpoint, data=data, post=post, post_data=post_data, is_json=json)
|
||||
print("Response: \n", ret)
|
21
scripts/closeness-calculator.py
Normal file
21
scripts/closeness-calculator.py
Normal file
@ -0,0 +1,21 @@
|
||||
import sys
|
||||
import os
|
||||
import subprocess
|
||||
import base64
|
||||
if not os.path.exists('onionr.sh'):
|
||||
os.chdir('../')
|
||||
sys.path.append("src/")
|
||||
from streamfill import identify_neighbors
|
||||
|
||||
onions = []
|
||||
p = subprocess.Popen(["scripts/generate-onions.py", '5'],
|
||||
stdout=subprocess.PIPE,
|
||||
stderr=subprocess.PIPE)
|
||||
for line in iter(p.stdout.readline, b''):
|
||||
line = line.decode()
|
||||
onions.append(line.strip())
|
||||
|
||||
|
||||
for onion in onions:
|
||||
print(onion, identify_neighbors(onion, onions, 3))
|
||||
|
@ -11,9 +11,12 @@ conf['tor']['existing_control_port'] = 0
|
||||
conf['tor']['existing_control_password'] = ""
|
||||
conf['tor']['existing_socks_port'] = 0
|
||||
|
||||
conf['general']['dev_mode'] = False
|
||||
conf['general']['insert_deniable_blocks'] = True
|
||||
conf['general']['random_bind_ip'] = True
|
||||
conf['general']['display_header'] = True
|
||||
conf['general']['security_level'] = 0
|
||||
conf['general']['use_bootstrap_list'] = True
|
||||
conf['onboarding']['done'] = False
|
||||
conf['general']['minimum_block_pow'] = 5
|
||||
conf['general']['minimum_send_pow'] = 5
|
||||
|
@ -10,6 +10,7 @@ conf = json.load(open('static-data/default_config.json', 'r'))
|
||||
|
||||
block_pow = int(input("Block POW level:"))
|
||||
|
||||
conf['general']['security_level'] = int(input("Security level:"))
|
||||
conf['transports']['tor'] = False
|
||||
if input('Use Tor? y/n').lower() == 'y':
|
||||
conf['transports']['tor'] = True
|
||||
@ -19,11 +20,15 @@ if input('Use Tor? y/n').lower() == 'y':
|
||||
conf['tor']['existing_control_password'] = input("Tor pass:")
|
||||
conf['tor']['existing_socks_port'] = int(input("Existing socks port:"))
|
||||
|
||||
conf['general']['dev_mode'] = True
|
||||
conf['general']['insert_deniable_blocks'] = False
|
||||
conf['general']['random_bind_ip'] = False
|
||||
conf['onboarding']['done'] = True
|
||||
conf['general']['minimum_block_pow'] = block_pow
|
||||
conf['general']['minimum_send_pow'] = block_pow
|
||||
conf['general']['use_bootstrap_list'] = False
|
||||
if input("Use bootstrap list? y/n").lower() == 'y':
|
||||
conf['general']['use_bootstrap_list'] = True
|
||||
conf['log']['file']['remove_on_exit'] = False
|
||||
conf['ui']['animated_background'] = False
|
||||
if input('Stat reporting? y/n') == 'y':
|
||||
|
33
scripts/floodfill-network-visualizer.py
Normal file
33
scripts/floodfill-network-visualizer.py
Normal file
@ -0,0 +1,33 @@
|
||||
import networkx as nx
|
||||
import matplotlib.pyplot as plt
|
||||
import sys
|
||||
import os
|
||||
import subprocess
|
||||
import base64
|
||||
if not os.path.exists('onionr.sh'):
|
||||
os.chdir('../')
|
||||
sys.path.append("src/")
|
||||
from streamfill import identify_neighbors
|
||||
|
||||
G = nx.Graph()
|
||||
size = 1000
|
||||
|
||||
onions = []
|
||||
p = subprocess.Popen(["scripts/generate-onions.py", str(size)],
|
||||
stdout=subprocess.PIPE,
|
||||
stderr=subprocess.PIPE)
|
||||
for line in iter(p.stdout.readline, b''):
|
||||
line = line.decode().strip()
|
||||
onions.append(line)
|
||||
G.add_node(line[:6])
|
||||
|
||||
for onion in onions:
|
||||
neighbors = identify_neighbors(onion, onions, 0.15 * size)
|
||||
for neighbor in neighbors:
|
||||
G.add_edge(onion[:6], neighbor[:6])
|
||||
|
||||
#nx.draw(G, with_labels=True, font_weight='bold')
|
||||
#nx.draw_shell(G, with_labels=True)
|
||||
#nx.draw_random(G, with_labels=True)
|
||||
nx.draw_kamada_kawai(G)
|
||||
plt.savefig("graph.png")
|
41
scripts/generate-onions.py
Executable file
41
scripts/generate-onions.py
Executable file
@ -0,0 +1,41 @@
|
||||
#!/usr/bin/env python3
|
||||
|
||||
import sys
|
||||
import os
|
||||
import stem
|
||||
from stem import process
|
||||
from stem.control import Controller
|
||||
if not os.path.exists('onionr.sh'):
|
||||
os.chdir('../')
|
||||
sys.path.append("src/")
|
||||
|
||||
try:
|
||||
sys.argv[1]
|
||||
except IndexError:
|
||||
sys.exit(1)
|
||||
|
||||
tor_process = process.launch_tor_with_config(
|
||||
completion_percent=0,
|
||||
config = {
|
||||
'ControlPort': '2778',
|
||||
'DisableNetwork': '1',
|
||||
'Log': [
|
||||
'NOTICE stdout',
|
||||
'ERR file /tmp/tor_error_log',
|
||||
],
|
||||
},
|
||||
)
|
||||
|
||||
with Controller.from_port('127.0.0.1', 2778) as controller:
|
||||
controller.authenticate()
|
||||
for i in range(1024, 1024 + int(sys.argv[1])):
|
||||
hs = controller.create_ephemeral_hidden_service(
|
||||
{80: i},
|
||||
key_type='NEW',
|
||||
key_content='ED25519-V3',
|
||||
await_publication=False,
|
||||
detached=True)
|
||||
print(hs.service_id + ".onion")
|
||||
controller.remove_ephemeral_hidden_service(hs.service_id)
|
||||
|
||||
tor_process.kill()
|
105
scripts/graph-simulation.py
Normal file
105
scripts/graph-simulation.py
Normal file
@ -0,0 +1,105 @@
|
||||
from typing import NamedTuple, List, Set
|
||||
|
||||
from collections import namedtuple
|
||||
from hashlib import sha3_256
|
||||
from secrets import randbelow
|
||||
from random import SystemRandom
|
||||
from threading import Thread
|
||||
from time import sleep
|
||||
import uuid
|
||||
|
||||
WeightedEdge = namedtuple("WeightedEdge", ["node", "weight"])
|
||||
|
||||
message_pool: Set["Message"] = set() # This is just to save memory for the simulation
|
||||
|
||||
def get_message(hash_id):
|
||||
for m in message_pool:
|
||||
if hash_id == m.hash_id:
|
||||
return m
|
||||
raise ValueError
|
||||
|
||||
class Node:
|
||||
def __init__(self, hidden_node: bool,
|
||||
edges: List[WeightedEdge], graph_ids=["main"]):
|
||||
self.hidden_node = hidden_node
|
||||
self.edges = edges
|
||||
self.node_id = str(uuid.uuid4())
|
||||
self._messages: List[str] = list() # hashes point to message_pool
|
||||
self._hidden_messages: List[str] = list()
|
||||
|
||||
def sharing_messages(self):
|
||||
share = list(self._messages)
|
||||
for m in self._hidden_messages:
|
||||
share.remove(m)
|
||||
return share
|
||||
|
||||
|
||||
def add_message(self, hash_id):
|
||||
if hash_id not in self._messages:
|
||||
self._messages.append(hash_id)
|
||||
|
||||
def pick_edge(self):
|
||||
selected = self.edges[0]
|
||||
alt = []
|
||||
|
||||
for weighted_edge in self.edges[1:]:
|
||||
if weighted_edge.weight[0] > selected.weight:
|
||||
selected = weighted_edge
|
||||
elif weighted_edge.weight[0] == selected.weight:
|
||||
alt.append(selected)
|
||||
alt.append(selected)
|
||||
SystemRandom().shuffle(alt)
|
||||
return alt[0]
|
||||
|
||||
|
||||
def share_to_edges(self, message_id):
|
||||
edge = self.pick_edge()
|
||||
edge.node.add_message(message_id)
|
||||
edge.weight[0] += 1
|
||||
|
||||
def lookup_messages(self):
|
||||
edge = self.pick_edge()
|
||||
for message in edge.node.sharing_messages():
|
||||
if message.hash_id not in self._messages:
|
||||
self._messages.append(message.hash_id)
|
||||
print(self.node_id, "found", message.hash_id)
|
||||
edge.weight[0] += 1
|
||||
|
||||
def make_new_connections(self):
|
||||
edge = self.pick_edge()
|
||||
for new_edge in edge.node.edges:
|
||||
if new_edge not in self.edges:
|
||||
self.edges.append(WeightedEdge(new_edge.node, [0]))
|
||||
print(self.node_id, "added peer", new_edge.node.node_id)
|
||||
edge.weight[0] += 1
|
||||
|
||||
|
||||
class Message:
|
||||
def __init__(self, data):
|
||||
def _do_hash(data):
|
||||
h = sha3_256()
|
||||
h.update(data)
|
||||
return h.digest()
|
||||
self.hash_id = _do_hash(data)
|
||||
self.data = data
|
||||
|
||||
bootstrap_node = Node(False, [])
|
||||
graph = [WeightedEdge(bootstrap_node, [0])]
|
||||
|
||||
for i in range(10):
|
||||
graph.append(WeightedEdge(Node(False, [WeightedEdge(bootstrap_node, [0])]), [0]))
|
||||
|
||||
m = Message(b"hello world")
|
||||
message_pool.add(m)
|
||||
bootstrap_node.add_message(m.hash_id)
|
||||
|
||||
def node_driver(node):
|
||||
while True:
|
||||
node.make_new_connections()
|
||||
node.lookup_messages()
|
||||
sleep(1)
|
||||
|
||||
for edge in graph:
|
||||
Thread(target=node_driver, args=[edge.node], daemon=True).start()
|
||||
input()
|
||||
|
21
scripts/passphrase-generator.py
Executable file
21
scripts/passphrase-generator.py
Executable file
@ -0,0 +1,21 @@
|
||||
#!/usr/bin/env python3
|
||||
|
||||
"""Generate a 16 word passphase with 256 bits of entropy.
|
||||
|
||||
Specify true to reduce to 128 bits"""
|
||||
|
||||
|
||||
import sys
|
||||
|
||||
import niceware
|
||||
|
||||
byte_count = 32 # 256 bits of entropy with niceware
|
||||
|
||||
arg = False
|
||||
try:
|
||||
arg = sys.argv[1].lower()
|
||||
if arg == 'true':
|
||||
byte_count = 16
|
||||
except IndexError: pass
|
||||
|
||||
print(' '.join(niceware.generate_passphrase(byte_count)))
|
16
scripts/show-blocks.py
Normal file
16
scripts/show-blocks.py
Normal file
@ -0,0 +1,16 @@
|
||||
import sys
|
||||
import os
|
||||
import stem
|
||||
|
||||
if not os.path.exists('onionr.sh'):
|
||||
os.chdir('../')
|
||||
sys.path.append("src/")
|
||||
from coredb.blockmetadb import get_block_list
|
||||
from onionrblocks.onionrblockapi import Block
|
||||
|
||||
for bl in get_block_list():
|
||||
bl_obj = Block(bl, decrypt=False)
|
||||
b_type = bl_obj.getType()
|
||||
if not b_type:
|
||||
b_type = "encrypted"
|
||||
print(bl + " - " + str(bl_obj.date) + " - " + b_type)
|
73
scripts/stats-server.py
Executable file
73
scripts/stats-server.py
Executable file
@ -0,0 +1,73 @@
|
||||
#!/usr/bin/env python3
|
||||
"""Onionr - Private P2P Communication.
|
||||
|
||||
LAN transport server thread
|
||||
"""
|
||||
import sys
|
||||
import os
|
||||
os.chdir('../')
|
||||
sys.path.append("src/")
|
||||
from gevent.pywsgi import WSGIServer
|
||||
from flask import Flask
|
||||
from flask import Response
|
||||
from flask import request
|
||||
import stem
|
||||
from stem.control import Controller
|
||||
from netcontroller import getopenport
|
||||
import json
|
||||
"""
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
"""
|
||||
|
||||
#passw = secrets.token_hex(32)
|
||||
port_num = int(input('tor control port'))
|
||||
web_port = getopenport.get_open_port()
|
||||
|
||||
|
||||
app = Flask(__name__)
|
||||
|
||||
STATS_FILE = 'stats.json'
|
||||
|
||||
@app.route('/sendstats/<node>', methods = ['POST'])
|
||||
def get_stats(node):
|
||||
try:
|
||||
with open(STATS_FILE, 'r') as f:
|
||||
try:
|
||||
data = json.loads(f.read())
|
||||
except json.decoder.JSONDecodeError:
|
||||
raise FileNotFoundError
|
||||
except FileNotFoundError:
|
||||
data = {}
|
||||
data[node] = request.get_data().decode('utf-8')
|
||||
|
||||
with open(STATS_FILE, 'w') as f:
|
||||
data = json.dumps(data)
|
||||
f.write(data)
|
||||
|
||||
return Response('ok')
|
||||
|
||||
with Controller.from_port(port = port_num) as controller:
|
||||
controller.authenticate(input('pass for tor')) # provide the password here if you set one
|
||||
hs = controller.create_ephemeral_hidden_service(
|
||||
{80: web_port},
|
||||
key_type = 'NEW',
|
||||
key_content = 'ED25519-V3',
|
||||
await_publication=True,
|
||||
detached=True)
|
||||
hs = hs.service_id
|
||||
print(f'stats server {hs}')
|
||||
|
||||
server = WSGIServer(('127.0.0.1', web_port), app, log=None)
|
||||
server.serve_forever()
|
||||
|
40
scripts/sybil-attack.py
Normal file
40
scripts/sybil-attack.py
Normal file
@ -0,0 +1,40 @@
|
||||
import sys
|
||||
import os
|
||||
import stem
|
||||
|
||||
if not os.path.exists('onionr.sh'):
|
||||
os.chdir('../')
|
||||
sys.path.append("src/")
|
||||
from onionrutils import stringvalidators
|
||||
from onionrutils import basicrequests
|
||||
|
||||
from stem.control import Controller
|
||||
|
||||
onionr_ip = input("onionr ip address: ")
|
||||
onionr_port = int(input("Enter onionr public api port: "))
|
||||
|
||||
controller = Controller.from_port('127.0.0.1', int(input("Enter tor controller port: ")))
|
||||
controller.authenticate()
|
||||
|
||||
node = input("Enter node to attack. Note that you legally must use your own, and even that might lead to technical or legal issues: ")
|
||||
assert stringvalidators.validate_transport(node)
|
||||
|
||||
socks = input("Socks:")
|
||||
|
||||
adders = set([])
|
||||
for i in range(int(input("Sybil addresses: "))):
|
||||
response = controller.create_ephemeral_hidden_service({80: f'{onionr_ip}:{onionr_port}'}, await_publication=True)
|
||||
#print(i, response.service_id)
|
||||
adders.add(response.service_id)
|
||||
|
||||
|
||||
for x in adders:
|
||||
x += '.onion'
|
||||
print(f"Introducing {x} to {node}")
|
||||
basicrequests.do_post_request(
|
||||
f'http://{node}/announce',
|
||||
data = {'node': x},
|
||||
port=socks)
|
||||
|
||||
|
||||
|
12
scripts/testblock.py
Executable file
12
scripts/testblock.py
Executable file
@ -0,0 +1,12 @@
|
||||
#!/usr/bin/env python3
|
||||
|
||||
import sys
|
||||
import os
|
||||
if not os.path.exists('onionr.sh'):
|
||||
os.chdir('../')
|
||||
sys.path.append("src/")
|
||||
import onionrblocks
|
||||
|
||||
expire = 600
|
||||
print(onionrblocks.insert(data=os.urandom(32), expire=expire))
|
||||
|
108
src/__init__.py
108
src/__init__.py
@ -5,71 +5,44 @@ This file initializes Onionr when ran to be a daemon or with commands
|
||||
|
||||
Run with 'help' for usage.
|
||||
"""
|
||||
# Enable pyjion if we can because why not
|
||||
pyjion_enabled = False
|
||||
try:
|
||||
pass
|
||||
#import pyjion
|
||||
#pyjion.enable()
|
||||
#pyjion_enabled = True
|
||||
except ImportError:
|
||||
pass
|
||||
|
||||
|
||||
import os
|
||||
import cProfile
|
||||
import threading
|
||||
|
||||
onionr_profiling = os.getenv("ONIONR_PROFILING", False)
|
||||
|
||||
|
||||
import sys
|
||||
|
||||
try:
|
||||
import sqlite3
|
||||
except ModuleNotFoundError:
|
||||
sys.stderr.write(
|
||||
'Error, Onionr requires Sqlite3-enabled Python.\n' +
|
||||
'https://stackoverflow.com/a/1875095\n')
|
||||
sys.exit(1)
|
||||
"""
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
"""
|
||||
|
||||
# Set the user's locale for encoding reasons
|
||||
import locale # noqa
|
||||
locale.setlocale(locale.LC_ALL, '') # noqa
|
||||
|
||||
import traceback
|
||||
import signal
|
||||
|
||||
def sigusr_stacktrace(signum, frame):
|
||||
"""Print stacktrace on SIGUSR1"""
|
||||
stack_trace_file = os.getenv('ONIONR_STACK_TRACE_FILE', False)
|
||||
for th in threading.enumerate():
|
||||
if stack_trace_file:
|
||||
with open(stack_trace_file, 'a') as f:
|
||||
f.write(f'Thread: {th.name}')
|
||||
f.write('-' * 44 + '')
|
||||
traceback.print_stack(sys._current_frames()[th.ident], file=f)
|
||||
else:
|
||||
print(f'Thread: {th.name}')
|
||||
print('-' * 44)
|
||||
traceback.print_stack(sys._current_frames()[th.ident])
|
||||
#print(traceback.format_stack(frame))
|
||||
|
||||
signal.signal(signal.SIGUSR1, sigusr_stacktrace)
|
||||
|
||||
# Importing initailzes logging
|
||||
from logger import log as logging
|
||||
|
||||
ran_as_script = False
|
||||
if __name__ == "__main__": ran_as_script = True
|
||||
|
||||
# Import standard libraries
|
||||
|
||||
try:
|
||||
from etc import dependencycheck # noqa
|
||||
except ModuleNotFoundError as e:
|
||||
print('Missing requirement: ' + str(e) + ' installed')
|
||||
sys.exit(1)
|
||||
|
||||
# Import 3rd party libraries
|
||||
|
||||
from filenuke import nuke # noqa
|
||||
@ -77,13 +50,10 @@ from filenuke import nuke # noqa
|
||||
# Onionr imports
|
||||
|
||||
# For different Onionr related constants such as versions
|
||||
import onionrvalues # noqa
|
||||
from etc import onionrvalues # noqa
|
||||
|
||||
import onionrexceptions # noqa
|
||||
import onionrsetup as setup # noqa
|
||||
setup.setup_config()
|
||||
|
||||
setup.setup_default_plugins()
|
||||
|
||||
min_ver = onionrvalues.MIN_PY_VERSION
|
||||
|
||||
@ -97,30 +67,36 @@ if sys.version_info[0] == 2 or sys.version_info[1] < min_ver:
|
||||
from utils import createdirs
|
||||
createdirs.create_dirs()
|
||||
|
||||
import bigbrother # noqa
|
||||
from onionrcommands import parser # noqa
|
||||
from onionrplugins import onionrevents as events # noqa
|
||||
from onionrblocks.deleteplaintext import delete_plaintext_no_blacklist # noqa
|
||||
|
||||
|
||||
setup.setup_config()
|
||||
|
||||
import config # noqa
|
||||
from utils import identifyhome # noqa
|
||||
import filepaths # noqa
|
||||
|
||||
if config.get('advanced.security_auditing', True):
|
||||
try:
|
||||
bigbrother.enable_ministries()
|
||||
except onionrexceptions.PythonVersion:
|
||||
pass
|
||||
|
||||
if not config.get('general.store_plaintext_blocks', True):
|
||||
delete_plaintext_no_blacklist()
|
||||
|
||||
setup.setup_default_plugins()
|
||||
|
||||
|
||||
def onionr_main():
|
||||
"""Onionr entrypoint, start command processor
|
||||
|
||||
Entrypoint for daemon is commands/daemonlaunch/__init__.py
|
||||
"""
|
||||
events.event('beforecmdparsing', threaded=False)
|
||||
"""Onionr entrypoint, start command processor"""
|
||||
parser.register()
|
||||
|
||||
|
||||
if ran_as_script:
|
||||
if onionr_profiling:
|
||||
cProfile.run('onionr_main()')
|
||||
else:
|
||||
onionr_main()
|
||||
onionr_main()
|
||||
|
||||
config.reload()
|
||||
|
||||
|
9
src/apiservers/README.md
Normal file
9
src/apiservers/README.md
Normal file
@ -0,0 +1,9 @@
|
||||
# API Servers
|
||||
|
||||
Contains the WSGI servers Onionr uses for remote peer communication and local daemon control
|
||||
|
||||
## Files
|
||||
|
||||
* \_\_init\_\_.py: Exposes the server classes
|
||||
* private: Contains the client API (the server used to interact with the local Onionr daemon, and view the web UI)
|
||||
* public: Contains the public API (the server used by remote peers to talk to our daemon)
|
10
src/apiservers/__init__.py
Executable file
10
src/apiservers/__init__.py
Executable file
@ -0,0 +1,10 @@
|
||||
"""Flask WSGI apps for the public and private API servers.
|
||||
|
||||
Public is net-facing server meant for other nodes
|
||||
Private is meant for controlling and accessing this node
|
||||
"""
|
||||
|
||||
from . import public, private
|
||||
|
||||
PublicAPI = public.PublicAPI
|
||||
ClientAPI = private.PrivateAPI
|
8
src/apiservers/private/README.md
Normal file
8
src/apiservers/private/README.md
Normal file
@ -0,0 +1,8 @@
|
||||
# Private API Server
|
||||
|
||||
Private API server, used to access the web interface locally and control Onionr
|
||||
|
||||
## Files
|
||||
|
||||
* \_\_init\_\_.py: Sets up the server and a few misc functions
|
||||
* register_private_blueprints.py: Adds in flask blueprints for various sub-APIs
|
119
src/apiservers/private/__init__.py
Normal file
119
src/apiservers/private/__init__.py
Normal file
@ -0,0 +1,119 @@
|
||||
"""Onionr - Private P2P Communication.
|
||||
|
||||
This file handles all incoming http requests to the client, using Flask
|
||||
"""
|
||||
from typing import Dict
|
||||
import hmac
|
||||
|
||||
import flask
|
||||
from gevent.pywsgi import WSGIServer
|
||||
|
||||
from onionrutils import epoch
|
||||
import httpapi
|
||||
from filepaths import private_API_host_file
|
||||
import logger
|
||||
|
||||
from etc import waitforsetvar
|
||||
from . import register_private_blueprints
|
||||
import config
|
||||
from .. import public
|
||||
"""
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
"""
|
||||
|
||||
|
||||
class PrivateAPI:
|
||||
"""Client HTTP api for controlling onionr and using UI."""
|
||||
|
||||
callbacks: Dict[str, Dict] = {'public': {}, 'private': {}}
|
||||
|
||||
def __init__(self):
|
||||
"""Initialize the api server, preping variables for later use.
|
||||
|
||||
This initialization defines all of the API entry points
|
||||
and handlers for the endpoints and errors
|
||||
This also saves the used host (random localhost IP address)
|
||||
to the data folder in host.txt
|
||||
"""
|
||||
self.config = config
|
||||
|
||||
self.startTime = epoch.get_epoch()
|
||||
app = flask.Flask(__name__)
|
||||
|
||||
|
||||
bind_port = int(config.get('client.client.port', 59496))
|
||||
self.bindPort = bind_port
|
||||
|
||||
self.clientToken = config.get('client.webpassword')
|
||||
|
||||
if config.get('general.bind_address'):
|
||||
with open(private_API_host_file, 'w') as bindFile:
|
||||
bindFile.write(config.get('general.bind_address'))
|
||||
self.host = config.get('general.bind_address')
|
||||
else:
|
||||
self.host = httpapi.apiutils.setbindip.set_bind_IP(
|
||||
private_API_host_file)
|
||||
logger.info('Running api on %s:%s' % (self.host, self.bindPort))
|
||||
self.httpServer = ''
|
||||
|
||||
self.queueResponse = {}
|
||||
self.get_block_data = httpapi.apiutils.GetBlockData(self)
|
||||
register_private_blueprints.register_private_blueprints(self, app)
|
||||
httpapi.load_plugin_blueprints(app)
|
||||
self.app = app
|
||||
|
||||
def start(self):
|
||||
"""Start client gevent API web server with flask client app."""
|
||||
waitforsetvar.wait_for_set_var(self, "_too_many")
|
||||
fd_handler = httpapi.fdsafehandler.FDSafeHandler
|
||||
self.publicAPI = self._too_many.get( # pylint: disable=E1101
|
||||
public.PublicAPI)
|
||||
self.httpServer = WSGIServer((self.host, self.bindPort),
|
||||
self.app, log=None,
|
||||
handler_class=fd_handler)
|
||||
self.httpServer.serve_forever()
|
||||
|
||||
def setPublicAPIInstance(self, inst):
|
||||
"""Dynamically set public API instance."""
|
||||
self.publicAPI = inst
|
||||
|
||||
def validateToken(self, token):
|
||||
"""Validate that the client token matches the given token.
|
||||
|
||||
Used to prevent CSRF and other attacks.
|
||||
"""
|
||||
if not self.clientToken:
|
||||
logger.error("client password needs to be set")
|
||||
return False
|
||||
try:
|
||||
return hmac.compare_digest(self.clientToken, token)
|
||||
except TypeError:
|
||||
return False
|
||||
|
||||
def getUptime(self) -> int:
|
||||
"""Safely wait for uptime to be set and return it."""
|
||||
while True:
|
||||
try:
|
||||
return epoch.get_epoch() - self.startTime
|
||||
except (AttributeError, NameError):
|
||||
# Don't error on race condition with startup
|
||||
pass
|
||||
|
||||
def getBlockData(self, bHash, decrypt=False, raw=False,
|
||||
headerOnly=False) -> bytes:
|
||||
"""Returns block data bytes."""
|
||||
return self.get_block_data.get_block_data(bHash,
|
||||
decrypt=decrypt,
|
||||
raw=raw,
|
||||
headerOnly=headerOnly)
|
60
src/apiservers/private/register_private_blueprints.py
Normal file
60
src/apiservers/private/register_private_blueprints.py
Normal file
@ -0,0 +1,60 @@
|
||||
"""Onionr - Private P2P Communication.
|
||||
|
||||
This file registers blueprints for the private api server
|
||||
"""
|
||||
from threading import Thread
|
||||
from gevent import sleep
|
||||
|
||||
from httpapi import security, friendsapi, configapi, insertblock
|
||||
from httpapi import miscclientapi, onionrsitesapi, apiutils
|
||||
from httpapi import themeapi
|
||||
from httpapi import fileoffsetreader
|
||||
from httpapi.sse.private import private_sse_blueprint
|
||||
|
||||
"""
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
"""
|
||||
|
||||
|
||||
def register_private_blueprints(private_api, app):
|
||||
"""Register private API plask blueprints."""
|
||||
app.register_blueprint(security.client.ClientAPISecurity(
|
||||
private_api).client_api_security_bp)
|
||||
app.register_blueprint(friendsapi.friends)
|
||||
app.register_blueprint(configapi.config_BP)
|
||||
app.register_blueprint(insertblock.ib)
|
||||
app.register_blueprint(miscclientapi.getblocks.client_get_blocks)
|
||||
app.register_blueprint(miscclientapi.endpoints.PrivateEndpoints(
|
||||
private_api).private_endpoints_bp)
|
||||
app.register_blueprint(miscclientapi.motd.bp)
|
||||
app.register_blueprint(onionrsitesapi.site_api)
|
||||
app.register_blueprint(apiutils.shutdown.shutdown_bp)
|
||||
app.register_blueprint(miscclientapi.staticfiles.static_files_bp)
|
||||
app.register_blueprint(themeapi.theme_blueprint)
|
||||
app.register_blueprint(private_sse_blueprint)
|
||||
app.register_blueprint(fileoffsetreader.offset_reader_api)
|
||||
|
||||
def _add_events_bp():
|
||||
while True:
|
||||
try:
|
||||
private_api._too_many
|
||||
break
|
||||
except AttributeError:
|
||||
sleep(0.2)
|
||||
app.register_blueprint(
|
||||
private_api._too_many.get_by_string('DaemonEventsBP').flask_bp)
|
||||
|
||||
Thread(target=_add_events_bp).start()
|
||||
|
||||
return app
|
76
src/apiservers/public/__init__.py
Normal file
76
src/apiservers/public/__init__.py
Normal file
@ -0,0 +1,76 @@
|
||||
"""Onionr - Private P2P Communication.
|
||||
|
||||
This file handles all incoming http requests
|
||||
to the public api server, using Flask
|
||||
"""
|
||||
import time
|
||||
import threading
|
||||
import flask
|
||||
from gevent.pywsgi import WSGIServer
|
||||
from httpapi import apiutils, security, fdsafehandler, miscpublicapi
|
||||
import logger
|
||||
import config
|
||||
import filepaths
|
||||
from utils import gettransports
|
||||
from etc import onionrvalues, waitforsetvar
|
||||
"""
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
"""
|
||||
|
||||
|
||||
def _get_tor_adder(pub_api):
|
||||
transports = []
|
||||
while len(transports) == 0:
|
||||
transports = gettransports.get()
|
||||
time.sleep(0.3)
|
||||
pub_api.torAdder = transports[0]
|
||||
|
||||
|
||||
class PublicAPI:
|
||||
"""The new client api server, isolated from the public api."""
|
||||
|
||||
def __init__(self):
|
||||
"""Setup the public api app."""
|
||||
app = flask.Flask('PublicAPI')
|
||||
app.config['MAX_CONTENT_LENGTH'] = 5 * 1024 * 1024
|
||||
self.i2pEnabled = config.get('i2p.host', False)
|
||||
self.hideBlocks = [] # Blocks to be denied sharing
|
||||
self.host = apiutils.setbindip.set_bind_IP(
|
||||
filepaths.public_API_host_file)
|
||||
|
||||
threading.Thread(target=_get_tor_adder,
|
||||
args=[self], daemon=True).start()
|
||||
|
||||
self.torAdder = ""
|
||||
self.bindPort = config.get('client.public.port')
|
||||
self.lastRequest = 0
|
||||
# total rec requests to public api since server started
|
||||
self.hitCount = 0
|
||||
self.config = config
|
||||
self.API_VERSION = onionrvalues.API_VERSION
|
||||
logger.info('Running public api on %s:%s' % (self.host, self.bindPort))
|
||||
|
||||
app.register_blueprint(
|
||||
security.public.PublicAPISecurity(self).public_api_security_bp)
|
||||
app.register_blueprint(
|
||||
miscpublicapi.endpoints.PublicEndpoints(self).public_endpoints_bp)
|
||||
self.app = app
|
||||
|
||||
def start(self):
|
||||
"""Start the Public API server."""
|
||||
waitforsetvar.wait_for_set_var(self, "_too_many")
|
||||
self.httpServer = WSGIServer((self.host, self.bindPort),
|
||||
self.app, log=None,
|
||||
handler_class=fdsafehandler.FDSafeHandler)
|
||||
self.httpServer.serve_forever()
|
51
src/bigbrother/__init__.py
Normal file
51
src/bigbrother/__init__.py
Normal file
@ -0,0 +1,51 @@
|
||||
"""Onionr - Private P2P Communication.
|
||||
|
||||
Processes interpreter hook events to detect security leaks
|
||||
"""
|
||||
import sys
|
||||
from typing import Iterable
|
||||
|
||||
from onionrexceptions import PythonVersion
|
||||
from . import ministry
|
||||
"""
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
"""
|
||||
|
||||
|
||||
def _auditing_supported():
|
||||
try:
|
||||
sys.audit
|
||||
sys.addaudithook
|
||||
except AttributeError:
|
||||
raise PythonVersion('Auditing not supported interpreter')
|
||||
|
||||
|
||||
def sys_hook_entrypoint(event, info):
|
||||
"""Entrypoint for big brother sys auditors."""
|
||||
if event == 'socket.connect':
|
||||
ministry.ofcommunication.detect_socket_leaks(info)
|
||||
elif event == 'exec':
|
||||
# logs and block both exec and eval
|
||||
ministry.ofexec.block_exec(event, info)
|
||||
elif event == 'system':
|
||||
ministry.ofexec.block_system(info)
|
||||
elif event == 'open':
|
||||
ministry.ofdisk.detect_disk_access(info)
|
||||
|
||||
|
||||
def enable_ministries(disable_hooks: Iterable = None):
|
||||
"""Enable auditors."""
|
||||
disable_hooks = disable_hooks or []
|
||||
_auditing_supported() # raises PythonVersion exception if <3.8
|
||||
sys.addaudithook(sys_hook_entrypoint)
|
@ -4,21 +4,21 @@ Ensure sockets don't get made to non localhost
|
||||
"""
|
||||
import ipaddress
|
||||
|
||||
from logger import log as logging
|
||||
import logger
|
||||
from onionrexceptions import NetworkLeak
|
||||
"""
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
"""
|
||||
|
||||
|
||||
@ -29,20 +29,18 @@ def detect_socket_leaks(socket_event):
|
||||
raises exception & logs if not to loopback
|
||||
"""
|
||||
ip_address = socket_event[1][0]
|
||||
if ip_address.startswith('/'):
|
||||
return
|
||||
|
||||
# validate is valid ip address (no hostname, etc)
|
||||
# raises NetworkLeak if not
|
||||
try:
|
||||
ip_address = ipaddress.ip_address(ip_address)
|
||||
except ValueError:
|
||||
logging.warn(f'Conn made to {ip_address} outside of Tor/similar')
|
||||
logger.warn(f'Conn made to {ip_address} outside of Tor/similar')
|
||||
raise \
|
||||
NetworkLeak('Conn to host/non local IP, this is a privacy issue!')
|
||||
|
||||
# Validate that the IP is localhost ipv4
|
||||
if not ip_address.is_loopback and not ip_address.is_multicast \
|
||||
and not ip_address.is_private:
|
||||
logging.warn(f'Conn made to {ip_address} outside of Tor/similar')
|
||||
logger.warn(f'Conn made to {ip_address} outside of Tor/similar')
|
||||
raise NetworkLeak('Conn to non local IP, this is a privacy concern!')
|
@ -3,7 +3,7 @@
|
||||
Log (not block) read/write of non-user data files and non-python lib files
|
||||
"""
|
||||
from utils.identifyhome import identify_home
|
||||
from logger import log as logging
|
||||
import logger
|
||||
"""
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
@ -25,7 +25,7 @@ def detect_disk_access(info):
|
||||
|
||||
if '/dev/null' == info[0]: return
|
||||
|
||||
whitelist = [identify_home(), 'onionr/src/', '/site-packages/', '/usr/lib64/', '/usr/local/lib/python']
|
||||
whitelist = [identify_home(), 'onionr/src/', '/site-packages/', '/usr/lib64/']
|
||||
|
||||
for item in whitelist:
|
||||
if item in info[0]:
|
||||
@ -33,4 +33,4 @@ def detect_disk_access(info):
|
||||
|
||||
if identify_home() not in info[0]:
|
||||
if 'proc' not in info[0]: # if it is, it is onionr stats
|
||||
logging.warn(f'[DISK MINISTRY] {info}')
|
||||
logger.warn(f'[DISK MINISTRY] {info}')
|
79
src/bigbrother/ministry/ofexec.py
Normal file
79
src/bigbrother/ministry/ofexec.py
Normal file
@ -0,0 +1,79 @@
|
||||
"""Onionr - Private P2P Communication.
|
||||
|
||||
Prevent eval/exec/os.system and log it
|
||||
"""
|
||||
import base64
|
||||
import platform
|
||||
|
||||
import logger
|
||||
from utils import identifyhome
|
||||
from onionrexceptions import ArbitraryCodeExec
|
||||
"""
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
"""
|
||||
|
||||
|
||||
def block_system(cmd):
|
||||
"""Prevent os.system except for whitelisted commands+contexts."""
|
||||
logger.warn('POSSIBLE EXPLOIT DETECTED, SEE LOGS', terminal=True)
|
||||
logger.warn(f'POSSIBLE EXPLOIT: shell command not in whitelist: {cmd}')
|
||||
raise ArbitraryCodeExec('os.system command not in whitelist')
|
||||
|
||||
|
||||
def block_exec(event, info):
|
||||
"""Prevent arbitrary code execution in eval/exec and log it."""
|
||||
# because libraries have stupid amounts of compile/exec/eval,
|
||||
# We have to use a whitelist where it can be tolerated
|
||||
# Generally better than nothing, not a silver bullet
|
||||
whitelisted_code = [
|
||||
'netrc.py',
|
||||
'shlex.py',
|
||||
'gzip.py',
|
||||
'<werkzeug routing>',
|
||||
'werkzeug/test.py',
|
||||
'multiprocessing/popen_fork.py',
|
||||
'multiprocessing/util.py',
|
||||
'multiprocessing/connection.py',
|
||||
'multiprocessing/queues.py',
|
||||
'multiprocessing/synchronize.py',
|
||||
'onionrutils/escapeansi.py',
|
||||
'stem/connection.py',
|
||||
'stem/response/add_onion.py',
|
||||
'stem/response/authchallenge.py',
|
||||
'stem/response/getinfo.py',
|
||||
'stem/response/getconf.py',
|
||||
'stem/response/mapaddress.py',
|
||||
'stem/response/protocolinfo.py',
|
||||
'apport/__init__.py',
|
||||
'apport/report.py'
|
||||
]
|
||||
whitelisted_source = []
|
||||
home = identifyhome.identify_home()
|
||||
|
||||
code_b64 = base64.b64encode(info[0].co_code).decode()
|
||||
if code_b64 in whitelisted_source:
|
||||
return
|
||||
|
||||
for source in whitelisted_code:
|
||||
if info[0].co_filename.endswith(source):
|
||||
return
|
||||
|
||||
if 'plugins/' in info[0].co_filename:
|
||||
return
|
||||
|
||||
logger.warn('POSSIBLE EXPLOIT DETECTED, SEE LOGS', terminal=True)
|
||||
logger.warn('POSSIBLE EXPLOIT DETECTED: ' + info[0].co_filename)
|
||||
logger.warn('Prevented exec/eval. Report this with the sample below')
|
||||
logger.warn(f'{event} code in base64 format: {code_b64}')
|
||||
raise ArbitraryCodeExec("Arbitrary code (eval/exec) detected.")
|
@ -1,33 +0,0 @@
|
||||
from typing import Callable, Generator, List
|
||||
|
||||
from onionrblocks import Block
|
||||
from onionrplugins import onionrevents
|
||||
|
||||
import db
|
||||
|
||||
from .dbpath import block_db_path
|
||||
from .blockcleaner import clean_block_database
|
||||
from .getblocks import get_blocks_after_timestamp, get_blocks_by_type
|
||||
from .deleteblock import delete_block
|
||||
|
||||
block_storage_observers: List[Callable] = []
|
||||
|
||||
|
||||
|
||||
|
||||
def add_block_to_db(block: Block):
|
||||
onionrevents.event('before_block_db_add', block, threaded=False)
|
||||
db.set_if_new(block_db_path, block.id, block.raw) # Raises db.DuplicateKey if dupe
|
||||
onionrevents.event('after_block_db_add', block, threaded=False)
|
||||
|
||||
|
||||
def has_block(block_hash):
|
||||
return block_hash in db.list_keys(block_db_path)
|
||||
|
||||
|
||||
def get_block(block_hash) -> Block:
|
||||
return Block(
|
||||
block_hash,
|
||||
db.get_db_obj(block_db_path, 'u').get(block_hash),
|
||||
auto_verify=False)
|
||||
|
@ -1,24 +0,0 @@
|
||||
from typing import Set
|
||||
|
||||
from onionrblocks import Block
|
||||
|
||||
from logger import log as logging
|
||||
|
||||
from .deleteblock import delete_block
|
||||
from .getblocks import get_blocks_after_timestamp
|
||||
|
||||
|
||||
def clean_block_database():
|
||||
"""Delete expired blocks from block db"""
|
||||
remove_set: Set[bytes] = set()
|
||||
block: Block
|
||||
|
||||
for block in get_blocks_after_timestamp(0):
|
||||
try:
|
||||
Block(block.id, block.raw, auto_verify=True)
|
||||
except ValueError: # block expired
|
||||
remove_set.add(block)
|
||||
|
||||
if len(remove_set):
|
||||
logging.info(f"Cleaning {len(remove_set)} blocks")
|
||||
[i for i in map(delete_block, remove_set)]
|
@ -1,4 +0,0 @@
|
||||
from utils import identifyhome
|
||||
|
||||
|
||||
block_db_path = identifyhome.identify_home() + 'blockdata'
|
@ -1,10 +0,0 @@
|
||||
from typing import TYPE_CHECKING
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from onionrblocks import Block
|
||||
|
||||
import db
|
||||
|
||||
from .dbpath import block_db_path
|
||||
|
||||
def delete_block(block: 'Block'): db.delete(block_db_path, block.id)
|
@ -1,33 +0,0 @@
|
||||
from typing import Generator
|
||||
|
||||
import db
|
||||
|
||||
from onionrblocks import Block
|
||||
|
||||
from .dbpath import block_db_path
|
||||
|
||||
|
||||
def get_blocks_by_type(block_type: str) -> "Generator[Block]":
|
||||
try:
|
||||
block_type = block_type.decode('utf-8')
|
||||
except AttributeError:
|
||||
pass
|
||||
block_db = db.get_db_obj(block_db_path, 'u')
|
||||
for block_hash in db.list_keys(block_db_path):
|
||||
block = Block(block_hash, block_db[block_hash], auto_verify=False)
|
||||
if block.type == block_type:
|
||||
yield block
|
||||
|
||||
|
||||
def get_blocks_after_timestamp(
|
||||
timestamp: int, block_type: str = '') -> "Generator[Block]":
|
||||
block_db = db.get_db_obj(block_db_path, 'u')
|
||||
|
||||
for block_hash in db.list_keys(block_db_path):
|
||||
block = Block(block_hash, block_db[block_hash], auto_verify=False)
|
||||
if block.timestamp > timestamp:
|
||||
if block_type:
|
||||
if block_type == block.type:
|
||||
yield block
|
||||
else:
|
||||
yield block
|
15
src/communicator/README.md
Normal file
15
src/communicator/README.md
Normal file
@ -0,0 +1,15 @@
|
||||
# Onionr Communicator
|
||||
|
||||
Onionr communicator is the Onionr client. It "connects" to remote Onionr peers and does things such as:
|
||||
|
||||
* Finding new peers
|
||||
* Uploading blocks
|
||||
* Downloading blocks
|
||||
* Daemon maintenance/housekeeping
|
||||
|
||||
## Files
|
||||
|
||||
* \_\_init\_\_.py: Contains the main communicator code. Inits and launches the communicator and sets up the timers
|
||||
* peeraction.py: contains a function to send commands to remote peers
|
||||
* bootstrappers.py: adds peers from the bootstrap list to the communicator to try to connect to them
|
||||
* onlinepeers: management of the online peer pool for the communicator
|
206
src/communicator/__init__.py
Executable file
206
src/communicator/__init__.py
Executable file
@ -0,0 +1,206 @@
|
||||
"""Onionr - Private P2P Communication.
|
||||
|
||||
This file contains both the OnionrCommunicate class for
|
||||
communcating with peers and code to operate as a daemon,
|
||||
getting commands from the command queue database
|
||||
"""
|
||||
import time
|
||||
|
||||
import config
|
||||
import logger
|
||||
import onionrpeers
|
||||
import onionrplugins as plugins
|
||||
from . import onlinepeers
|
||||
from . import uploadqueue
|
||||
from communicatorutils import downloadblocks
|
||||
from communicatorutils import lookupblocks
|
||||
from communicatorutils import lookupadders
|
||||
from communicatorutils import connectnewpeers
|
||||
from communicatorutils import uploadblocks
|
||||
from communicatorutils import announcenode, deniableinserts
|
||||
from communicatorutils import cooldownpeer
|
||||
from communicatorutils import housekeeping
|
||||
from communicatorutils import netcheck
|
||||
from onionrthreads import add_onionr_thread
|
||||
from onionrcommands.openwebinterface import get_url
|
||||
from netcontroller import NetController
|
||||
from . import bootstrappeers
|
||||
from . import daemoneventhooks
|
||||
"""
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
"""
|
||||
|
||||
config.reload()
|
||||
|
||||
|
||||
class OnionrCommunicatorDaemon:
|
||||
def __init__(self, shared_state, developmentMode=None):
|
||||
if developmentMode is None:
|
||||
developmentMode = config.get(
|
||||
'general.dev_mode', False)
|
||||
|
||||
# configure logger and stuff
|
||||
self.config = config
|
||||
self.shared_state = shared_state # TooManyObjects module
|
||||
shared_state.add(self)
|
||||
|
||||
# populate kv values
|
||||
self.kv = self.shared_state.get_by_string('DeadSimpleKV')
|
||||
|
||||
if config.get('general.offline_mode', False):
|
||||
self.kv.put('isOnline', False)
|
||||
|
||||
# initialize core with Tor socks port being 3rd argument
|
||||
self.proxyPort = shared_state.get(NetController).socksPort
|
||||
|
||||
self.upload_session_manager = self.shared_state.get(
|
||||
uploadblocks.sessionmanager.BlockUploadSessionManager)
|
||||
self.shared_state.share_object()
|
||||
|
||||
# loop time.sleep delay in seconds
|
||||
self.delay = 5
|
||||
|
||||
# amount of threads running by name, used to prevent too many
|
||||
self.threadCounts = {}
|
||||
|
||||
# Loads in and starts the enabled plugins
|
||||
plugins.reload()
|
||||
|
||||
# extends our upload list and saves our list when Onionr exits
|
||||
uploadqueue.UploadQueue(self)
|
||||
|
||||
add_onionr_thread(
|
||||
lookupblocks.lookup_blocks_from_communicator,
|
||||
[self.shared_state], 25, 3)
|
||||
|
||||
add_onionr_thread(
|
||||
downloadblocks.download_blocks_from_communicator,
|
||||
[self.shared_state],
|
||||
config.get('timers.getBlocks', 10), 1)
|
||||
|
||||
add_onionr_thread(onlinepeers.clear_offline_peer, [self.kv], 58)
|
||||
|
||||
add_onionr_thread(
|
||||
housekeeping.clean_old_blocks, [self.shared_state], 10, 1)
|
||||
|
||||
# Discover new peers
|
||||
add_onionr_thread(
|
||||
lookupadders.lookup_new_peer_transports_with_communicator,
|
||||
[shared_state], 60, 3)
|
||||
|
||||
# Timer for adjusting which peers
|
||||
# we actively communicate to at any given time,
|
||||
# to avoid over-using peers
|
||||
add_onionr_thread(
|
||||
cooldownpeer.cooldown_peer, [self.shared_state], 30, 60)
|
||||
|
||||
# Timer to read the upload queue and upload the entries to peers
|
||||
add_onionr_thread(
|
||||
uploadblocks.upload_blocks_from_communicator,
|
||||
[self.shared_state], 5, 1)
|
||||
|
||||
# This timer creates deniable blocks,
|
||||
# in an attempt to further obfuscate block insertion metadata
|
||||
if config.get('general.insert_deniable_blocks', True):
|
||||
add_onionr_thread(
|
||||
deniableinserts.insert_deniable_block, [], 180, 10)
|
||||
|
||||
if config.get('transports.tor', True):
|
||||
# Timer to check for connectivity,
|
||||
# through Tor to various high-profile onion services
|
||||
add_onionr_thread(netcheck.net_check, [shared_state], 500, 60)
|
||||
|
||||
# Announce the public API server transport address
|
||||
# to other nodes if security level allows
|
||||
if config.get('general.security_level', 1) == 0 \
|
||||
and config.get('general.announce_node', True):
|
||||
# Default to high security level incase config breaks
|
||||
add_onionr_thread(
|
||||
announcenode.announce_node, [self.shared_state], 600, 60)
|
||||
else:
|
||||
logger.debug('Will not announce node.')
|
||||
|
||||
add_onionr_thread(onionrpeers.peer_cleanup, [], 300, 300)
|
||||
|
||||
add_onionr_thread(housekeeping.clean_keys, [], 15, 1)
|
||||
|
||||
if config.get('general.use_bootstrap_list', True):
|
||||
bootstrappeers.add_bootstrap_list_to_peer_list(
|
||||
self.kv, [], db_only=True)
|
||||
|
||||
daemoneventhooks.daemon_event_handlers(shared_state)
|
||||
|
||||
get_url()
|
||||
if not config.get('onboarding.done', True):
|
||||
logger.info(
|
||||
'First run detected. Run openhome to get setup.',
|
||||
terminal=True)
|
||||
|
||||
while not config.get('onboarding.done', True) and \
|
||||
not self.shared_state.get_by_string(
|
||||
'DeadSimpleKV').get('shutdown'):
|
||||
try:
|
||||
time.sleep(2)
|
||||
except KeyboardInterrupt:
|
||||
self.shared_state.get_by_string(
|
||||
'DeadSimpleKV').put('shutdown', True)
|
||||
|
||||
# Main daemon loop, mainly for calling timers,
|
||||
# don't do any complex operations here to avoid locking
|
||||
try:
|
||||
while not self.shared_state.get_by_string(
|
||||
'DeadSimpleKV').get('shutdown'):
|
||||
time.sleep(self.delay)
|
||||
except KeyboardInterrupt:
|
||||
self.shared_state.get_by_string(
|
||||
'DeadSimpleKV').put('shutdown', True)
|
||||
|
||||
logger.info(
|
||||
'Goodbye. (Onionr is cleaning up, and will exit)', terminal=True)
|
||||
|
||||
def decrementThreadCount(self, threadName):
|
||||
"""Decrement amount of a thread name if more than zero.
|
||||
|
||||
called when a function meant to be run in a thread ends
|
||||
"""
|
||||
try:
|
||||
if self.threadCounts[threadName] > 0:
|
||||
self.threadCounts[threadName] -= 1
|
||||
except KeyError:
|
||||
pass
|
||||
|
||||
def peerCleanup(self):
|
||||
"""This just calls onionrpeers.cleanupPeers.
|
||||
|
||||
Remove dead or bad peers (offline too long, too slow)"""
|
||||
onionrpeers.peer_cleanup()
|
||||
self.decrementThreadCount('peerCleanup')
|
||||
|
||||
def getPeerProfileInstance(self, peer):
|
||||
"""Gets a peer profile instance from the list of profiles"""
|
||||
for i in self.kv.get('peerProfiles'):
|
||||
# if the peer's profile is already loaded, return that
|
||||
if i.address == peer:
|
||||
retData = i
|
||||
break
|
||||
else:
|
||||
# if the peer's profile is not loaded, return a new one.
|
||||
# connectNewPeer also adds it to the list on connect
|
||||
retData = onionrpeers.PeerProfiles(peer)
|
||||
self.kv.get('peerProfiles').append(retData)
|
||||
return retData
|
||||
|
||||
|
||||
def startCommunicator(shared_state):
|
||||
OnionrCommunicatorDaemon(shared_state)
|
36
src/communicator/bootstrappeers.py
Normal file
36
src/communicator/bootstrappeers.py
Normal file
@ -0,0 +1,36 @@
|
||||
"""Onionr - Private P2P Communication.
|
||||
|
||||
add bootstrap peers to the communicator peer list
|
||||
"""
|
||||
from typing import TYPE_CHECKING
|
||||
|
||||
from utils import readstatic, gettransports
|
||||
from coredb import keydb
|
||||
"""
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
"""
|
||||
|
||||
bootstrap_peers = readstatic.read_static('bootstrap-nodes.txt').split(',')
|
||||
|
||||
|
||||
def add_bootstrap_list_to_peer_list(kv, peerList, db_only=False):
|
||||
"""Add the bootstrap list to the peer list (no duplicates)."""
|
||||
for i in bootstrap_peers:
|
||||
# Add bootstrap peers to peerList (does not save them)
|
||||
# Don't add them if they're already added or in the offline list
|
||||
if i not in peerList and i not in kv.get('offlinePeers') \
|
||||
and i not in gettransports.get() and len(str(i).strip()) > 0:
|
||||
if not db_only:
|
||||
peerList.append(i)
|
||||
keydb.addkeys.add_address(i)
|
82
src/communicator/daemoneventhooks/__init__.py
Normal file
82
src/communicator/daemoneventhooks/__init__.py
Normal file
@ -0,0 +1,82 @@
|
||||
"""Onionr - Private P2P Communication.
|
||||
|
||||
Hooks to handle daemon events
|
||||
"""
|
||||
from threading import Thread
|
||||
|
||||
from .removefrominsertqueue import remove_from_insert_queue
|
||||
|
||||
from typing import TYPE_CHECKING
|
||||
|
||||
from gevent import sleep
|
||||
|
||||
from communicatorutils.uploadblocks import mixmate
|
||||
from communicatorutils import restarttor
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from toomanyobjs import TooMany
|
||||
from deadsimplekv import DeadSimpleKV
|
||||
from communicator import OnionrCommunicatorDaemon
|
||||
from httpapi.daemoneventsapi import DaemonEventsBP
|
||||
from onionrtypes import BlockHash
|
||||
from apiservers import PublicAPI
|
||||
"""
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
"""
|
||||
|
||||
|
||||
def daemon_event_handlers(shared_state: 'TooMany'):
|
||||
def _get_inst(class_name: str):
|
||||
while True:
|
||||
try:
|
||||
return shared_state.get_by_string(class_name)
|
||||
except KeyError:
|
||||
sleep(0.2)
|
||||
comm_inst = _get_inst('OnionrCommunicatorDaemon')
|
||||
public_api: 'PublicAPI' = _get_inst('PublicAPI')
|
||||
events_api: 'DaemonEventsBP' = _get_inst('DaemonEventsBP')
|
||||
kv: 'DeadSimpleKV' = _get_inst('DeadSimpleKV')
|
||||
|
||||
def remove_from_insert_queue_wrapper(block_hash: 'BlockHash'):
|
||||
remove_from_insert_queue(comm_inst, block_hash)
|
||||
return "removed"
|
||||
|
||||
def print_test(text=''):
|
||||
print("It works!", text)
|
||||
return f"It works! {text}"
|
||||
|
||||
def upload_event(block: 'BlockHash' = ''):
|
||||
if not block:
|
||||
raise ValueError
|
||||
public_api.hideBlocks.append(block)
|
||||
try:
|
||||
mixmate.block_mixer(kv.get('blocksToUpload'), block)
|
||||
except ValueError:
|
||||
pass
|
||||
return "removed"
|
||||
|
||||
def restart_tor():
|
||||
restarttor.restart(shared_state)
|
||||
kv.put('offlinePeers', [])
|
||||
kv.put('onlinePeers', [])
|
||||
|
||||
def test_runtime():
|
||||
Thread(target=comm_inst.shared_state.get_by_string(
|
||||
"OnionrRunTestManager").run_tests).start()
|
||||
|
||||
events_api.register_listener(remove_from_insert_queue_wrapper)
|
||||
events_api.register_listener(restart_tor)
|
||||
events_api.register_listener(print_test)
|
||||
events_api.register_listener(upload_event)
|
||||
events_api.register_listener(test_runtime)
|
33
src/communicator/daemoneventhooks/removefrominsertqueue.py
Normal file
33
src/communicator/daemoneventhooks/removefrominsertqueue.py
Normal file
@ -0,0 +1,33 @@
|
||||
"""Onionr - P2P Anonymous Storage Network.
|
||||
|
||||
Remove block hash from daemon's upload list.
|
||||
"""
|
||||
from typing import TYPE_CHECKING
|
||||
if TYPE_CHECKING:
|
||||
from deadsimplekv import DeadSimpleKV
|
||||
from communicator import OnionrCommunicatorDaemon
|
||||
from onionrtypes import BlockHash
|
||||
"""
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
"""
|
||||
|
||||
|
||||
def remove_from_insert_queue(comm_inst: "OnionrCommunicatorDaemon",
|
||||
b_hash: "BlockHash"):
|
||||
"""Remove block hash from daemon's upload list."""
|
||||
kv: "DeadSimpleKV" = comm_inst.shared_state.get_by_string("DeadSimpleKV")
|
||||
try:
|
||||
kv.get('generating_blocks').remove(b_hash)
|
||||
except ValueError:
|
||||
pass
|
12
src/communicator/onlinepeers/README.md
Normal file
12
src/communicator/onlinepeers/README.md
Normal file
@ -0,0 +1,12 @@
|
||||
# Online Peers
|
||||
|
||||
Manages a pool of peers to perform actions with. Since Onionr does not maintain socket connections, it holds a list of peers.
|
||||
|
||||
|
||||
## Files
|
||||
|
||||
* \_\_init\_\_.py: exposes some functions to interact with the pool
|
||||
* clearofflinepeer.py: Pop the oldest peer in the offline list
|
||||
* onlinepeers.py: communicator timer to add new peers to the pool randomly
|
||||
* pickonlinepeers.py: returns a random peer from the online pool
|
||||
* removeonlinepeer.py: removes a specified peer from the online pool
|
6
src/communicator/onlinepeers/__init__.py
Normal file
6
src/communicator/onlinepeers/__init__.py
Normal file
@ -0,0 +1,6 @@
|
||||
from . import clearofflinepeer, onlinepeers, pickonlinepeers, removeonlinepeer
|
||||
|
||||
clear_offline_peer = clearofflinepeer.clear_offline_peer
|
||||
get_online_peers = onlinepeers.get_online_peers
|
||||
pick_online_peer = pickonlinepeers.pick_online_peer
|
||||
remove_online_peer = removeonlinepeer.remove_online_peer
|
35
src/communicator/onlinepeers/clearofflinepeer.py
Normal file
35
src/communicator/onlinepeers/clearofflinepeer.py
Normal file
@ -0,0 +1,35 @@
|
||||
"""Onionr - Private P2P Communication.
|
||||
|
||||
clear offline peer in a communicator instance
|
||||
"""
|
||||
from typing import TYPE_CHECKING
|
||||
|
||||
import logger
|
||||
if TYPE_CHECKING:
|
||||
from communicator import OnionrCommunicatorDaemon
|
||||
"""
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
"""
|
||||
|
||||
|
||||
def clear_offline_peer(kv: 'DeadSimpleKV'):
|
||||
"""Remove the longest offline peer to retry later."""
|
||||
try:
|
||||
removed = kv.get('offlinePeers').pop(0)
|
||||
except IndexError:
|
||||
pass
|
||||
else:
|
||||
logger.debug('Removed ' + removed +
|
||||
' from offline list, will try them again.')
|
||||
|
63
src/communicator/onlinepeers/onlinepeers.py
Normal file
63
src/communicator/onlinepeers/onlinepeers.py
Normal file
@ -0,0 +1,63 @@
|
||||
"""Onionr - Private P2P Communication.
|
||||
|
||||
get online peers in a communicator instance
|
||||
"""
|
||||
import time
|
||||
from typing import TYPE_CHECKING
|
||||
|
||||
import config
|
||||
from etc.humanreadabletime import human_readable_time
|
||||
from communicatorutils.connectnewpeers import connect_new_peer_to_communicator
|
||||
import logger
|
||||
if TYPE_CHECKING:
|
||||
from deadsimplekv import DeadSimpleKV
|
||||
"""
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
"""
|
||||
|
||||
|
||||
def get_online_peers(shared_state):
|
||||
"""Manage the kv.get('onlinePeers') attribute list.
|
||||
|
||||
Connect to more peers if we have none connected
|
||||
"""
|
||||
kv: "DeadSimpleKV" = shared_state.get_by_string("DeadSimpleKV")
|
||||
if config.get('general.offline_mode', False):
|
||||
return
|
||||
logger.info('Refreshing peer pool...')
|
||||
max_peers = int(config.get('peers.max_connect', 10))
|
||||
needed = max_peers - len(kv.get('onlinePeers'))
|
||||
|
||||
last_seen = 'never'
|
||||
if not isinstance(kv.get('lastNodeSeen'), type(None)):
|
||||
last_seen = human_readable_time(kv.get('lastNodeSeen'))
|
||||
|
||||
for _ in range(needed):
|
||||
if len(kv.get('onlinePeers')) == 0:
|
||||
connect_new_peer_to_communicator(shared_state, useBootstrap=True)
|
||||
else:
|
||||
connect_new_peer_to_communicator(shared_state)
|
||||
|
||||
if kv.get('shutdown'):
|
||||
break
|
||||
else:
|
||||
if len(kv.get('onlinePeers')) == 0:
|
||||
logger.debug('Couldn\'t connect to any peers.' +
|
||||
f' Last node seen {last_seen} ago.')
|
||||
try:
|
||||
get_online_peers(shared_state)
|
||||
except RecursionError:
|
||||
pass
|
||||
else:
|
||||
kv.put('lastNodeSeen', time.time())
|
47
src/communicator/onlinepeers/pickonlinepeers.py
Normal file
47
src/communicator/onlinepeers/pickonlinepeers.py
Normal file
@ -0,0 +1,47 @@
|
||||
"""
|
||||
Onionr - Private P2P Communication.
|
||||
|
||||
pick online peers in a communicator instance
|
||||
"""
|
||||
import secrets
|
||||
from typing import TYPE_CHECKING
|
||||
|
||||
import onionrexceptions
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from deadsimplekv import DeadSimpleKV
|
||||
"""
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
"""
|
||||
|
||||
|
||||
def pick_online_peer(kv: 'DeadSimpleKV'):
|
||||
"""Randomly picks peer from pool without bias (using secrets module)."""
|
||||
ret_data = ''
|
||||
peer_length = len(kv.get('onlinePeers'))
|
||||
if peer_length <= 0:
|
||||
raise onionrexceptions.OnlinePeerNeeded
|
||||
|
||||
while True:
|
||||
peer_length = len(kv.get('onlinePeers'))
|
||||
|
||||
try:
|
||||
# Get a random online peer, securely.
|
||||
# May get stuck in loop if network is lost
|
||||
ret_data = kv.get('onlinePeers')[secrets.randbelow(peer_length)]
|
||||
except IndexError:
|
||||
pass
|
||||
else:
|
||||
break
|
||||
return ret_data
|
38
src/communicator/onlinepeers/removeonlinepeer.py
Normal file
38
src/communicator/onlinepeers/removeonlinepeer.py
Normal file
@ -0,0 +1,38 @@
|
||||
"""Onionr - Private P2P Communication.
|
||||
|
||||
remove an online peer from the pool in a communicator instance
|
||||
"""
|
||||
from typing import TYPE_CHECKING
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from deadsimplekv import DeadSimpleKV
|
||||
"""
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
"""
|
||||
|
||||
|
||||
def remove_online_peer(kv, peer):
|
||||
"""Remove an online peer."""
|
||||
try:
|
||||
del kv.get('connectTimes')[peer]
|
||||
except KeyError:
|
||||
pass
|
||||
try:
|
||||
del kv.get('dbTimestamps')[peer]
|
||||
except KeyError:
|
||||
pass
|
||||
try:
|
||||
kv.get('onlinePeers').remove(peer)
|
||||
except ValueError:
|
||||
pass
|
78
src/communicator/peeraction.py
Normal file
78
src/communicator/peeraction.py
Normal file
@ -0,0 +1,78 @@
|
||||
"""Onionr - Private P2P Communication.
|
||||
|
||||
This file implements logic for performing requests to Onionr peers
|
||||
"""
|
||||
from typing import TYPE_CHECKING
|
||||
|
||||
import streamedrequests
|
||||
import logger
|
||||
from onionrutils import epoch, basicrequests
|
||||
from coredb import keydb
|
||||
from . import onlinepeers
|
||||
from onionrtypes import OnionAddressString
|
||||
from onionrpeers.peerprofiles import PeerProfiles
|
||||
from etc.waitforsetvar import wait_for_set_var
|
||||
"""
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
"""
|
||||
|
||||
|
||||
def get_peer_profile(kv, address: OnionAddressString) -> 'PeerProfiles':
|
||||
profile_inst_list = kv.get('peerProfiles')
|
||||
for profile in profile_inst_list:
|
||||
if profile.address == address:
|
||||
return profile
|
||||
p = PeerProfiles(address)
|
||||
profile_inst_list.append(p)
|
||||
return p
|
||||
|
||||
|
||||
def peer_action(shared_state, peer, action,
|
||||
returnHeaders=False, max_resp_size=5242880):
|
||||
"""Perform a get request to a peer."""
|
||||
penalty_score = -10
|
||||
kv: "DeadSimpleKV" = shared_state.get_by_string("DeadSimpleKV")
|
||||
if len(peer) == 0:
|
||||
return False
|
||||
url = 'http://%s/%s' % (peer, action)
|
||||
|
||||
try:
|
||||
ret_data = basicrequests.do_get_request(url, port=kv.get('proxyPort'),
|
||||
max_size=max_resp_size)
|
||||
except streamedrequests.exceptions.ResponseLimitReached:
|
||||
logger.warn(
|
||||
'Request failed due to max response size being overflowed',
|
||||
terminal=True)
|
||||
ret_data = False
|
||||
penalty_score = -100
|
||||
# if request failed, (error), mark peer offline
|
||||
if ret_data is False:
|
||||
try:
|
||||
get_peer_profile(kv, peer).addScore(penalty_score)
|
||||
onlinepeers.remove_online_peer(kv, peer)
|
||||
keydb.transportinfo.set_address_info(
|
||||
peer, 'lastConnectAttempt', epoch.get_epoch())
|
||||
if action != 'ping' and not kv.get('shutdown'):
|
||||
logger.warn(f'Lost connection to {peer}', terminal=True)
|
||||
# Will only add a new peer to pool if needed
|
||||
onlinepeers.get_online_peers(kv)
|
||||
except ValueError:
|
||||
pass
|
||||
else:
|
||||
peer_profile = get_peer_profile(kv, peer)
|
||||
peer_profile.update_connect_time()
|
||||
peer_profile.addScore(1)
|
||||
# If returnHeaders, returns tuple of data, headers.
|
||||
# If not, just data string
|
||||
return ret_data
|
73
src/communicator/uploadqueue/__init__.py
Normal file
73
src/communicator/uploadqueue/__init__.py
Normal file
@ -0,0 +1,73 @@
|
||||
"""Onionr - Private P2P Communication.
|
||||
|
||||
Class to remember blocks that need to be uploaded
|
||||
and not shared on startup/shutdown
|
||||
"""
|
||||
import atexit
|
||||
import os
|
||||
from typing import TYPE_CHECKING
|
||||
|
||||
import deadsimplekv
|
||||
|
||||
import filepaths
|
||||
from onionrutils import localcommand
|
||||
if TYPE_CHECKING:
|
||||
from communicator import OnionrCommunicatorDaemon
|
||||
from deadsimplekv import DeadSimpleKV
|
||||
"""
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
"""
|
||||
|
||||
UPLOAD_MEMORY_FILE = filepaths.upload_list
|
||||
|
||||
|
||||
def _add_to_hidden_blocks(cache):
|
||||
for bl in cache:
|
||||
localcommand.local_command('waitforshare/' + bl, post=True)
|
||||
|
||||
|
||||
class UploadQueue:
|
||||
"""Saves and loads block upload info from json file."""
|
||||
|
||||
def __init__(self, communicator: 'OnionrCommunicatorDaemon'):
|
||||
"""Start the UploadQueue object, loading left over uploads into queue.
|
||||
|
||||
register save shutdown function
|
||||
"""
|
||||
self.communicator = communicator
|
||||
cache: deadsimplekv.DeadSimpleKV = deadsimplekv.DeadSimpleKV(
|
||||
UPLOAD_MEMORY_FILE)
|
||||
self.kv: "DeadSimpleKV" = \
|
||||
communicator.shared_state.get_by_string("DeadSimpleKV")
|
||||
self.store_obj = cache
|
||||
cache = cache.get('uploads')
|
||||
if cache is None:
|
||||
cache = []
|
||||
|
||||
_add_to_hidden_blocks(cache)
|
||||
self.kv.get('blocksToUpload').extend(cache)
|
||||
|
||||
atexit.register(self.save)
|
||||
|
||||
def save(self):
|
||||
"""Save to disk on shutdown or if called manually."""
|
||||
bl: deadsimplekv.DeadSimpleKV = self.kv.get('blocksToUpload')
|
||||
if len(bl) == 0:
|
||||
try:
|
||||
os.remove(UPLOAD_MEMORY_FILE)
|
||||
except FileNotFoundError:
|
||||
pass
|
||||
else:
|
||||
self.store_obj.put('uploads', bl)
|
||||
self.store_obj.flush()
|
33
src/communicatorutils/README.md
Executable file
33
src/communicatorutils/README.md
Executable file
@ -0,0 +1,33 @@
|
||||
# communicatorutils
|
||||
|
||||
The files in this submodule handle various subtasks and utilities for the onionr communicator.
|
||||
|
||||
## Files:
|
||||
|
||||
announcenode.py: Uses a communicator instance to announce our transport address to connected nodes
|
||||
|
||||
connectnewpeers.py: takes a communicator instance and has it connect to as many peers as needed, and/or to a new specified peer.
|
||||
|
||||
cooldownpeer.py: randomly selects a connected peer in a communicator and disconnects them for the purpose of security and network balancing.
|
||||
|
||||
daemonqueuehandler.py: checks for new commands in the daemon queue and processes them accordingly.
|
||||
|
||||
deniableinserts.py: insert fake blocks with the communicator for plausible deniability
|
||||
|
||||
downloadblocks.py: iterates a communicator instance's block download queue and attempts to download the blocks from online peers
|
||||
|
||||
housekeeping.py: cleans old blocks and forward secrecy keys
|
||||
|
||||
lookupadders.py: ask connected peers to share their list of peer transport addresses
|
||||
|
||||
lookupblocks.py: lookup new blocks from connected peers from the communicator
|
||||
|
||||
netcheck.py: check if the node is online based on communicator status and onion server ping results
|
||||
|
||||
onionrcommunicataortimers.py: create a timer for a function to be launched on an interval. Control how many possible instances of a timer may be running a function at once and control if the timer should be ran in a thread or not.
|
||||
|
||||
proxypicker.py: returns a string name for the appropriate proxy to be used with a particular peer transport address.
|
||||
|
||||
servicecreator.py: iterate connection blocks and create new direct connection servers for them.
|
||||
|
||||
uploadblocks.py: iterate a communicator's upload queue and upload the blocks to connected peers
|
0
static-data/official-plugins/tor/bootstrap.txt → src/communicatorutils/__init__.py
Normal file → Executable file
0
static-data/official-plugins/tor/bootstrap.txt → src/communicatorutils/__init__.py
Normal file → Executable file
77
src/communicatorutils/announcenode.py
Executable file
77
src/communicatorutils/announcenode.py
Executable file
@ -0,0 +1,77 @@
|
||||
"""
|
||||
Onionr - Private P2P Communication.
|
||||
|
||||
Use a communicator instance to announce
|
||||
our transport address to connected nodes
|
||||
"""
|
||||
from typing import TYPE_CHECKING
|
||||
|
||||
import logger
|
||||
from onionrutils import basicrequests
|
||||
from utils import gettransports
|
||||
from netcontroller import NetController
|
||||
from communicator import onlinepeers
|
||||
from coredb import keydb
|
||||
import onionrexceptions
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from deadsimplekv import DeadSimpleKV
|
||||
"""
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
"""
|
||||
|
||||
|
||||
def announce_node(shared_state):
|
||||
"""Announce our node to our peers."""
|
||||
ret_data = False
|
||||
kv: "DeadSimpleKV" = shared_state.get_by_string("DeadSimpleKV")
|
||||
config = shared_state.get_by_string("OnionrCommunicatorDaemon").config
|
||||
# Do not let announceCache get too large
|
||||
if len(kv.get('announceCache')) >= 10000:
|
||||
kv.get('announceCache').popitem()
|
||||
|
||||
if config.get('general.security_level', 0) == 0:
|
||||
# Announce to random online peers
|
||||
for i in kv.get('onlinePeers'):
|
||||
if i not in kv.get('announceCache'):
|
||||
peer = i
|
||||
break
|
||||
else:
|
||||
try:
|
||||
peer = onlinepeers.pick_online_peer(kv)
|
||||
except onionrexceptions.OnlinePeerNeeded:
|
||||
peer = ""
|
||||
|
||||
try:
|
||||
ourID = gettransports.get()[0]
|
||||
if not peer:
|
||||
raise onionrexceptions.OnlinePeerNeeded
|
||||
except (IndexError, onionrexceptions.OnlinePeerNeeded):
|
||||
pass
|
||||
else:
|
||||
url = 'http://' + peer + '/announce'
|
||||
data = {'node': ourID}
|
||||
|
||||
logger.info('Announcing node to ' + url)
|
||||
if basicrequests.do_post_request(
|
||||
url,
|
||||
data,
|
||||
port=shared_state.get(NetController).socksPort)\
|
||||
== 'Success':
|
||||
logger.info('Successfully introduced node to ' + peer,
|
||||
terminal=True)
|
||||
ret_data = True
|
||||
keydb.transportinfo.set_address_info(peer, 'introduced', 1)
|
||||
|
||||
return ret_data
|
117
src/communicatorutils/connectnewpeers.py
Executable file
117
src/communicatorutils/connectnewpeers.py
Executable file
@ -0,0 +1,117 @@
|
||||
"""Onionr - Private P2P Communication.
|
||||
|
||||
Connect a new peer to our communicator instance.
|
||||
Does so randomly if no peer is specified
|
||||
"""
|
||||
import time
|
||||
import secrets
|
||||
|
||||
import onionrexceptions
|
||||
import logger
|
||||
import onionrpeers
|
||||
from utils import networkmerger, gettransports
|
||||
from onionrutils import stringvalidators, epoch
|
||||
from communicator import peeraction, bootstrappeers
|
||||
from coredb import keydb
|
||||
import config
|
||||
"""
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
"""
|
||||
|
||||
|
||||
def connect_new_peer_to_communicator(shared_state, peer='', useBootstrap=False):
|
||||
retData = False
|
||||
kv: "DeadSimpleKV" = shared_state.get_by_string("DeadSimpleKV")
|
||||
tried = kv.get('offlinePeers')
|
||||
transports = gettransports.get()
|
||||
if peer != '':
|
||||
if stringvalidators.validate_transport(peer):
|
||||
peerList = [peer]
|
||||
else:
|
||||
raise onionrexceptions.InvalidAddress(
|
||||
'Will not attempt connection test to invalid address')
|
||||
else:
|
||||
peerList = keydb.listkeys.list_adders()
|
||||
|
||||
mainPeerList = keydb.listkeys.list_adders()
|
||||
if not peerList:
|
||||
peerList = onionrpeers.get_score_sorted_peer_list()
|
||||
|
||||
"""
|
||||
If we don't have enough peers connected or random chance,
|
||||
select new peers to try
|
||||
"""
|
||||
if len(peerList) < 8 or secrets.randbelow(4) == 3:
|
||||
tryingNew = []
|
||||
for x in kv.get('newPeers'):
|
||||
if x not in peerList:
|
||||
peerList.append(x)
|
||||
tryingNew.append(x)
|
||||
for i in tryingNew:
|
||||
kv.get('newPeers').remove(i)
|
||||
|
||||
if len(peerList) == 0 or useBootstrap:
|
||||
# Avoid duplicating bootstrap addresses in peerList
|
||||
if config.get('general.use_bootstrap_list', True):
|
||||
bootstrappeers.add_bootstrap_list_to_peer_list(kv, peerList)
|
||||
|
||||
for address in peerList:
|
||||
address = address.strip()
|
||||
|
||||
# Don't connect to our own address
|
||||
if address in transports:
|
||||
continue
|
||||
"""Don't connect to invalid address or
|
||||
if its already been tried/connected, or if its cooled down
|
||||
"""
|
||||
if len(address) == 0 or address in tried \
|
||||
or address in kv.get('onlinePeers') \
|
||||
or address in kv.get('cooldownPeer'):
|
||||
continue
|
||||
if kv.get('shutdown'):
|
||||
return
|
||||
# Ping a peer,
|
||||
ret = peeraction.peer_action(shared_state, address, 'ping')
|
||||
if ret == 'pong!':
|
||||
time.sleep(0.1)
|
||||
if address not in mainPeerList:
|
||||
# Add a peer to our list if it isn't already since it connected
|
||||
networkmerger.mergeAdders(address)
|
||||
if address not in kv.get('onlinePeers'):
|
||||
logger.info('Connected to ' + address, terminal=True)
|
||||
kv.get('onlinePeers').append(address)
|
||||
kv.get('connectTimes')[address] = epoch.get_epoch()
|
||||
retData = address
|
||||
|
||||
# add peer to profile list if they're not in it
|
||||
for profile in kv.get('peerProfiles'):
|
||||
if profile.address == address:
|
||||
break
|
||||
else:
|
||||
kv.get('peerProfiles').append(
|
||||
onionrpeers.PeerProfiles(address))
|
||||
try:
|
||||
del kv.get('plaintextDisabledPeers')[address]
|
||||
except KeyError:
|
||||
pass
|
||||
if peeraction.peer_action(
|
||||
shared_state, address, 'plaintext') == 'false':
|
||||
kv.get('plaintextDisabledPeers')[address] = True
|
||||
break
|
||||
|
||||
else:
|
||||
# Mark a peer as tried if they failed to respond to ping
|
||||
tried.append(address)
|
||||
logger.debug('Failed to connect to %s: %s ' % (address, ret))
|
||||
return retData
|
60
src/communicatorutils/cooldownpeer.py
Executable file
60
src/communicatorutils/cooldownpeer.py
Executable file
@ -0,0 +1,60 @@
|
||||
"""Onionr - Private P2P Communication.
|
||||
|
||||
Select random online peer in a communicator instance and have them "cool down"
|
||||
"""
|
||||
from typing import TYPE_CHECKING
|
||||
|
||||
from onionrutils import epoch
|
||||
from communicator import onlinepeers
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from deadsimplekv import DeadSimpleKV
|
||||
"""
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
"""
|
||||
|
||||
|
||||
def cooldown_peer(shared_state):
|
||||
"""Randomly add an online peer to cooldown, so we can connect a new one."""
|
||||
kv: "DeadSimpleKV" = shared_state.get_by_string("DeadSimpleKV")
|
||||
config = shared_state.get_by_string("OnionrCommunicatorDaemon").config
|
||||
online_peer_amount = len(kv.get('onlinePeers'))
|
||||
minTime = 300
|
||||
cooldown_time = 600
|
||||
to_cool = ''
|
||||
tempConnectTimes = dict(kv.get('connectTimes'))
|
||||
|
||||
# Remove peers from cooldown that have been there long enough
|
||||
tempCooldown = dict(kv.get('cooldownPeer'))
|
||||
for peer in tempCooldown:
|
||||
if (epoch.get_epoch() - tempCooldown[peer]) >= cooldown_time:
|
||||
del kv.get('cooldownPeer')[peer]
|
||||
|
||||
# Cool down a peer, if we have max connections alive for long enough
|
||||
if online_peer_amount >= config.get('peers.max_connect', 10, save=True):
|
||||
finding = True
|
||||
|
||||
while finding:
|
||||
try:
|
||||
to_cool = min(tempConnectTimes, key=tempConnectTimes.get)
|
||||
if (epoch.get_epoch() - tempConnectTimes[to_cool]) < minTime:
|
||||
del tempConnectTimes[to_cool]
|
||||
else:
|
||||
finding = False
|
||||
except ValueError:
|
||||
break
|
||||
else:
|
||||
onlinepeers.remove_online_peer(kv, to_cool)
|
||||
kv.get('cooldownPeer')[to_cool] = epoch.get_epoch()
|
||||
|
35
src/communicatorutils/deniableinserts.py
Executable file
35
src/communicatorutils/deniableinserts.py
Executable file
@ -0,0 +1,35 @@
|
||||
"""Onionr - Private P2P Communication.
|
||||
|
||||
Use the communicator to insert fake mail messages
|
||||
"""
|
||||
import secrets
|
||||
|
||||
from etc import onionrvalues
|
||||
import onionrblocks
|
||||
"""
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
"""
|
||||
|
||||
|
||||
def insert_deniable_block():
|
||||
"""Insert a fake block to make it more difficult to track real blocks."""
|
||||
fakePeer = ''
|
||||
chance = 10
|
||||
if secrets.randbelow(chance) == (chance - 1):
|
||||
# This assumes on the libsodium primitives to have key-privacy
|
||||
fakePeer = onionrvalues.DENIABLE_PEER_ADDRESS
|
||||
data = secrets.token_hex(secrets.randbelow(5120) + 1)
|
||||
onionrblocks.insert(data, header='pm', encryptType='asym',
|
||||
asymPeer=fakePeer, disableForward=True,
|
||||
meta={'subject': 'foo'})
|
173
src/communicatorutils/downloadblocks/__init__.py
Executable file
173
src/communicatorutils/downloadblocks/__init__.py
Executable file
@ -0,0 +1,173 @@
|
||||
"""Onionr - Private P2P Communication.
|
||||
|
||||
Download blocks using the communicator instance.
|
||||
"""
|
||||
from typing import TYPE_CHECKING
|
||||
from secrets import SystemRandom
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from communicator import OnionrCommunicatorDaemon
|
||||
from deadsimplekv import DeadSimpleKV
|
||||
|
||||
from gevent import spawn
|
||||
|
||||
import onionrexceptions
|
||||
import logger
|
||||
import onionrpeers
|
||||
|
||||
from communicator import peeraction
|
||||
from communicator import onlinepeers
|
||||
from onionrblocks import blockmetadata
|
||||
from onionrutils import validatemetadata
|
||||
from coredb import blockmetadb
|
||||
from onionrutils.localcommand import local_command
|
||||
import onionrcrypto
|
||||
import onionrstorage
|
||||
from onionrblocks import onionrblacklist
|
||||
from onionrblocks import storagecounter
|
||||
from . import shoulddownload
|
||||
"""
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
"""
|
||||
|
||||
storage_counter = storagecounter.StorageCounter()
|
||||
|
||||
|
||||
def download_blocks_from_communicator(shared_state: "TooMany"):
|
||||
"""Use communicator instance to download blocks in the comms's queue"""
|
||||
blacklist = onionrblacklist.OnionrBlackList()
|
||||
kv: "DeadSimpleKV" = shared_state.get_by_string("DeadSimpleKV")
|
||||
LOG_SKIP_COUNT = 50 # for how many iterations we skip logging the counter
|
||||
count: int = 0
|
||||
metadata_validation_result: bool = False
|
||||
# Iterate the block queue in the communicator
|
||||
for blockHash in list(kv.get('blockQueue')):
|
||||
count += 1
|
||||
|
||||
try:
|
||||
blockPeers = list(kv.get('blockQueue')[blockHash])
|
||||
except KeyError:
|
||||
blockPeers = []
|
||||
removeFromQueue = True
|
||||
|
||||
if not shoulddownload.should_download(shared_state, blockHash):
|
||||
continue
|
||||
|
||||
if kv.get('shutdown') or not kv.get('isOnline') or \
|
||||
storage_counter.is_full():
|
||||
# Exit loop if shutting down or offline, or disk allocation reached
|
||||
break
|
||||
# Do not download blocks being downloaded
|
||||
if blockHash in kv.get('currentDownloading'):
|
||||
continue
|
||||
|
||||
if len(kv.get('onlinePeers')) == 0:
|
||||
break
|
||||
|
||||
# So we can avoid concurrent downloading in other threads of same block
|
||||
kv.get('currentDownloading').append(blockHash)
|
||||
if len(blockPeers) == 0:
|
||||
try:
|
||||
peerUsed = onlinepeers.pick_online_peer(kv)
|
||||
except onionrexceptions.OnlinePeerNeeded:
|
||||
continue
|
||||
else:
|
||||
SystemRandom().shuffle(blockPeers)
|
||||
peerUsed = blockPeers.pop(0)
|
||||
|
||||
if not kv.get('shutdown') and peerUsed.strip() != '':
|
||||
logger.info(
|
||||
f"Attempting to download %s from {peerUsed}..." % (blockHash[:12],))
|
||||
content = peeraction.peer_action(
|
||||
shared_state, peerUsed,
|
||||
'getdata/' + blockHash,
|
||||
max_resp_size=3000000) # block content from random peer
|
||||
|
||||
if content is not False and len(content) > 0:
|
||||
try:
|
||||
content = content.encode()
|
||||
except AttributeError:
|
||||
pass
|
||||
|
||||
realHash = onionrcrypto.hashers.sha3_hash(content)
|
||||
try:
|
||||
realHash = realHash.decode() # bytes on some versions for some reason
|
||||
except AttributeError:
|
||||
pass
|
||||
if realHash == blockHash:
|
||||
#content = content.decode() # decode here because sha3Hash needs bytes above
|
||||
metas = blockmetadata.get_block_metadata_from_data(content) # returns tuple(metadata, meta), meta is also in metadata
|
||||
metadata = metas[0]
|
||||
try:
|
||||
metadata_validation_result = \
|
||||
validatemetadata.validate_metadata(metadata, metas[2])
|
||||
except onionrexceptions.PlaintextNotSupported:
|
||||
logger.debug(f"Not saving {blockHash} due to plaintext not enabled")
|
||||
removeFromQueue = True
|
||||
except onionrexceptions.DataExists:
|
||||
metadata_validation_result = False
|
||||
if metadata_validation_result: # check if metadata is valid, and verify nonce
|
||||
if onionrcrypto.cryptoutils.verify_POW(content): # check if POW is enough/correct
|
||||
logger.info('Attempting to save block %s...' % blockHash[:12])
|
||||
try:
|
||||
onionrstorage.set_data(content)
|
||||
except onionrexceptions.DataExists:
|
||||
logger.warn('Data is already set for %s ' % (blockHash,))
|
||||
except onionrexceptions.DiskAllocationReached:
|
||||
logger.error('Reached disk allocation allowance, cannot save block %s.' % (blockHash,))
|
||||
removeFromQueue = False
|
||||
else:
|
||||
blockmetadb.add_to_block_DB(blockHash, dataSaved=True) # add block to meta db
|
||||
blockmetadata.process_block_metadata(blockHash) # caches block metadata values to block database
|
||||
spawn(
|
||||
local_command,
|
||||
f'/daemon-event/upload_event',
|
||||
post=True,
|
||||
is_json=True,
|
||||
post_data={'block': blockHash}
|
||||
)
|
||||
else:
|
||||
logger.warn('POW failed for block %s.' % (blockHash,))
|
||||
else:
|
||||
if blacklist.inBlacklist(realHash):
|
||||
logger.warn('Block %s is blacklisted.' % (realHash,))
|
||||
else:
|
||||
logger.warn('Metadata for block %s is invalid.' % (blockHash,))
|
||||
blacklist.addToDB(blockHash)
|
||||
else:
|
||||
# if block didn't meet expected hash
|
||||
tempHash = onionrcrypto.hashers.sha3_hash(content) # lazy hack, TODO use var
|
||||
try:
|
||||
tempHash = tempHash.decode()
|
||||
except AttributeError:
|
||||
pass
|
||||
# Punish peer for sharing invalid block (not always malicious, but is bad regardless)
|
||||
onionrpeers.PeerProfiles(peerUsed).addScore(-50)
|
||||
if tempHash != 'ed55e34cb828232d6c14da0479709bfa10a0923dca2b380496e6b2ed4f7a0253':
|
||||
# Dumb hack for 404 response from peer. Don't log it if 404 since its likely not malicious or a critical error.
|
||||
logger.warn(
|
||||
'Block hash validation failed for ' +
|
||||
blockHash + ' got ' + tempHash)
|
||||
else:
|
||||
removeFromQueue = False # Don't remove from queue if 404
|
||||
if removeFromQueue:
|
||||
try:
|
||||
del kv.get('blockQueue')[blockHash] # remove from block queue both if success or false
|
||||
if count == LOG_SKIP_COUNT:
|
||||
logger.info('%s blocks remaining in queue' %
|
||||
[len(kv.get('blockQueue'))], terminal=True)
|
||||
count = 0
|
||||
except KeyError:
|
||||
pass
|
||||
kv.get('currentDownloading').remove(blockHash)
|
42
src/communicatorutils/downloadblocks/shoulddownload.py
Normal file
42
src/communicatorutils/downloadblocks/shoulddownload.py
Normal file
@ -0,0 +1,42 @@
|
||||
"""Onionr - Private P2P Communication.
|
||||
|
||||
Check if a block should be downloaded
|
||||
(if we already have it or its blacklisted or not)
|
||||
"""
|
||||
from coredb import blockmetadb
|
||||
from onionrblocks import onionrblacklist
|
||||
"""
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
"""
|
||||
|
||||
|
||||
def should_download(shared_state, block_hash) -> bool:
|
||||
"""Return bool for if a (assumed to exist) block should be downloaded."""
|
||||
blacklist = onionrblacklist.OnionrBlackList()
|
||||
should = True
|
||||
kv: "DeadSimpleKV" = shared_state.get_by_string("DeadSimpleKV")
|
||||
if block_hash in blockmetadb.get_block_list():
|
||||
# Don't download block we have
|
||||
should = False
|
||||
else:
|
||||
if blacklist.inBlacklist(block_hash):
|
||||
# Don't download blacklisted block
|
||||
should = False
|
||||
if should is False:
|
||||
# Remove block from communicator queue if it shouldn't be downloaded
|
||||
try:
|
||||
del kv.get('blockQueue')[block_hash]
|
||||
except KeyError:
|
||||
pass
|
||||
return should
|
108
src/communicatorutils/housekeeping.py
Executable file
108
src/communicatorutils/housekeeping.py
Executable file
@ -0,0 +1,108 @@
|
||||
"""Onionr - Private P2P Communication.
|
||||
|
||||
Cleanup old Onionr blocks and forward secrecy keys using the communicator.
|
||||
Ran from a communicator timer usually
|
||||
"""
|
||||
import sqlite3
|
||||
from typing import TYPE_CHECKING
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from deadsimplekv import DeadSimpleKV
|
||||
|
||||
import logger
|
||||
from onionrusers import onionrusers
|
||||
from onionrutils import epoch
|
||||
from coredb import blockmetadb, dbfiles
|
||||
import onionrstorage
|
||||
from onionrstorage import removeblock
|
||||
from onionrblocks import onionrblacklist
|
||||
from onionrblocks.storagecounter import StorageCounter
|
||||
from etc.onionrvalues import DATABASE_LOCK_TIMEOUT
|
||||
from onionrproofs import hashMeetsDifficulty
|
||||
"""
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
"""
|
||||
|
||||
storage_counter = StorageCounter()
|
||||
|
||||
|
||||
def __remove_from_upload(shared_state, block_hash: str):
|
||||
kv: "DeadSimpleKV" = shared_state.get_by_string("DeadSimpleKV")
|
||||
try:
|
||||
kv.get('blocksToUpload').remove(block_hash)
|
||||
except ValueError:
|
||||
pass
|
||||
|
||||
|
||||
def __purge_block(shared_state, block_hash, add_to_blacklist = True):
|
||||
blacklist = None
|
||||
|
||||
removeblock.remove_block(block_hash)
|
||||
onionrstorage.deleteBlock(block_hash)
|
||||
__remove_from_upload(shared_state, block_hash)
|
||||
|
||||
if add_to_blacklist:
|
||||
blacklist = onionrblacklist.OnionrBlackList()
|
||||
blacklist.addToDB(block_hash)
|
||||
|
||||
|
||||
def clean_old_blocks(shared_state):
|
||||
"""Delete expired blocks + old blocks if disk allocation is near full"""
|
||||
blacklist = onionrblacklist.OnionrBlackList()
|
||||
# Delete expired blocks
|
||||
for bHash in blockmetadb.expiredblocks.get_expired_blocks():
|
||||
__purge_block(shared_state, bHash, add_to_blacklist=True)
|
||||
logger.info('Deleted expired block: %s' % (bHash,))
|
||||
|
||||
while storage_counter.is_full():
|
||||
try:
|
||||
oldest = blockmetadb.get_block_list()[0]
|
||||
except IndexError:
|
||||
break
|
||||
else:
|
||||
__purge_block(shared_state, bHash, add_to_blacklist=True)
|
||||
logger.info('Deleted block because of full storage: %s' % (oldest,))
|
||||
|
||||
|
||||
def clean_keys():
|
||||
"""Delete expired forward secrecy keys"""
|
||||
conn = sqlite3.connect(dbfiles.user_id_info_db,
|
||||
timeout=DATABASE_LOCK_TIMEOUT)
|
||||
c = conn.cursor()
|
||||
time = epoch.get_epoch()
|
||||
deleteKeys = []
|
||||
|
||||
for entry in c.execute(
|
||||
"SELECT * FROM forwardKeys WHERE expire <= ?", (time,)):
|
||||
logger.debug('Forward key: %s' % entry[1])
|
||||
deleteKeys.append(entry[1])
|
||||
|
||||
for key in deleteKeys:
|
||||
logger.debug('Deleting forward key %s' % key)
|
||||
c.execute("DELETE from forwardKeys where forwardKey = ?", (key,))
|
||||
conn.commit()
|
||||
conn.close()
|
||||
|
||||
onionrusers.deleteExpiredKeys()
|
||||
|
||||
|
||||
def clean_blocks_not_meeting_pow(shared_state):
|
||||
"""Clean blocks not meeting min send/rec pow. Used if config.json POW changes"""
|
||||
block_list = blockmetadb.get_block_list()
|
||||
for block in block_list:
|
||||
if not hashMeetsDifficulty(block):
|
||||
logger.warn(
|
||||
f"Deleting block {block} because it was stored" +
|
||||
"with a POW level smaller than current.", terminal=True)
|
||||
__purge_block(shared_state, block)
|
66
src/communicatorutils/lookupadders.py
Executable file
66
src/communicatorutils/lookupadders.py
Executable file
@ -0,0 +1,66 @@
|
||||
"""Onionr - Private P2P Communication.
|
||||
|
||||
Lookup new peer transport addresses using the communicator
|
||||
"""
|
||||
from typing import TYPE_CHECKING
|
||||
import logger
|
||||
from onionrutils import stringvalidators
|
||||
from communicator import peeraction, onlinepeers
|
||||
from utils import gettransports
|
||||
import onionrexceptions
|
||||
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from deadsimplekv import DeadSimpleKV
|
||||
"""
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
"""
|
||||
|
||||
|
||||
def lookup_new_peer_transports_with_communicator(shared_state):
|
||||
logger.info('Looking up new addresses...')
|
||||
tryAmount = 1
|
||||
newPeers = []
|
||||
transports = gettransports.get()
|
||||
kv: "DeadSimpleKV" = shared_state.get_by_string("DeadSimpleKV")
|
||||
|
||||
for i in range(tryAmount):
|
||||
# Download new peer address list from random online peers
|
||||
if len(newPeers) > 10000:
|
||||
# Don't get new peers if we have too many queued up
|
||||
break
|
||||
try:
|
||||
peer = onlinepeers.pick_online_peer(kv)
|
||||
newAdders = peeraction.peer_action(shared_state, peer, action='pex')
|
||||
except onionrexceptions.OnlinePeerNeeded:
|
||||
continue
|
||||
try:
|
||||
newPeers = newAdders.split(',')
|
||||
except AttributeError:
|
||||
pass
|
||||
else:
|
||||
# Validate new peers are good format and not already in queue
|
||||
invalid = []
|
||||
for x in newPeers:
|
||||
x = x.strip()
|
||||
if not stringvalidators.validate_transport(x) \
|
||||
or x in kv.get('newPeers') or x in transports:
|
||||
# avoid adding if its our address
|
||||
invalid.append(x)
|
||||
for x in invalid:
|
||||
try:
|
||||
newPeers.remove(x)
|
||||
except ValueError:
|
||||
pass
|
||||
kv.get('newPeers').extend(newPeers)
|
126
src/communicatorutils/lookupblocks.py
Executable file
126
src/communicatorutils/lookupblocks.py
Executable file
@ -0,0 +1,126 @@
|
||||
"""Onionr - Private P2P Communication.
|
||||
|
||||
Lookup new blocks with the communicator using a random connected peer
|
||||
"""
|
||||
from typing import TYPE_CHECKING
|
||||
|
||||
from gevent import time
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from deadsimplekv import DeadSimpleKV
|
||||
|
||||
import logger
|
||||
import onionrproofs
|
||||
from onionrutils import stringvalidators, epoch
|
||||
from communicator import peeraction, onlinepeers
|
||||
from coredb.blockmetadb import get_block_list
|
||||
from utils import reconstructhash
|
||||
from onionrblocks import onionrblacklist
|
||||
import onionrexceptions
|
||||
import config
|
||||
from etc import onionrvalues
|
||||
from onionrblocks.storagecounter import StorageCounter
|
||||
"""
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
"""
|
||||
|
||||
blacklist = onionrblacklist.OnionrBlackList()
|
||||
storage_counter = StorageCounter()
|
||||
|
||||
|
||||
def lookup_blocks_from_communicator(shared_state: 'TooMany'):
|
||||
logger.info('Looking up new blocks')
|
||||
tryAmount = 2
|
||||
newBlocks = ''
|
||||
# List of existing saved blocks
|
||||
existingBlocks = get_block_list()
|
||||
triedPeers = [] # list of peers we've tried this time around
|
||||
# Max amount of *new* block hashes to have in queue
|
||||
maxBacklog = 1560
|
||||
lastLookupTime = 0 # Last time we looked up a particular peer's list
|
||||
new_block_count = 0
|
||||
kv: "DeadSimpleKV" = shared_state.get_by_string("DeadSimpleKV")
|
||||
for i in range(tryAmount):
|
||||
# Defined here to reset it each time, time offset is added later
|
||||
listLookupCommand = 'getblocklist'
|
||||
if len(kv.get('blockQueue')) >= maxBacklog:
|
||||
break
|
||||
if not kv.get('isOnline'):
|
||||
break
|
||||
# check if disk allocation is used
|
||||
if storage_counter.is_full():
|
||||
logger.debug(
|
||||
'Not looking up new blocks due to maximum amount of disk used')
|
||||
break
|
||||
try:
|
||||
# select random online peer
|
||||
peer = onlinepeers.pick_online_peer(kv)
|
||||
except onionrexceptions.OnlinePeerNeeded:
|
||||
time.sleep(1)
|
||||
continue
|
||||
# if we've already tried all the online peers this time around, stop
|
||||
if peer in triedPeers:
|
||||
if len(kv.get('onlinePeers')) == len(triedPeers):
|
||||
break
|
||||
else:
|
||||
continue
|
||||
triedPeers.append(peer)
|
||||
|
||||
# Get the last time we looked up a peer's stamp,
|
||||
# to only fetch blocks since then.
|
||||
# Saved in memory only for privacy reasons
|
||||
try:
|
||||
lastLookupTime = kv.get('dbTimestamps')[peer]
|
||||
except KeyError:
|
||||
lastLookupTime = epoch.get_epoch() - onionrvalues.DEFAULT_EXPIRE
|
||||
listLookupCommand += '?date=%s' % (lastLookupTime,)
|
||||
try:
|
||||
newBlocks = peeraction.peer_action(
|
||||
shared_state,
|
||||
peer, listLookupCommand) # get list of new block hashes
|
||||
except Exception as error:
|
||||
logger.warn(
|
||||
f'Could not get new blocks from {peer}.',
|
||||
error=error)
|
||||
newBlocks = False
|
||||
|
||||
if newBlocks != False: # noqa
|
||||
# if request was a success
|
||||
for i in newBlocks.split('\n'):
|
||||
if stringvalidators.validate_hash(i):
|
||||
i = reconstructhash.reconstruct_hash(i)
|
||||
# if newline seperated string is valid hash
|
||||
|
||||
# if block does not exist on disk + is not already in queue
|
||||
if i not in existingBlocks:
|
||||
if i not in kv.get('blockQueue'):
|
||||
if onionrproofs.hashMeetsDifficulty(i) and \
|
||||
not blacklist.inBlacklist(i):
|
||||
if len(kv.get('blockQueue')) <= 1000000:
|
||||
# add blocks to download queue
|
||||
kv.get('blockQueue')[i] = [peer]
|
||||
new_block_count += 1
|
||||
kv.get('dbTimestamps')[peer] = \
|
||||
epoch.get_rounded_epoch(roundS=60)
|
||||
else:
|
||||
if peer not in kv.get('blockQueue')[i]:
|
||||
if len(kv.get('blockQueue')[i]) < 10:
|
||||
kv.get('blockQueue')[i].append(peer)
|
||||
if new_block_count > 0:
|
||||
block_string = ""
|
||||
if new_block_count > 1:
|
||||
block_string = "s"
|
||||
logger.info(
|
||||
f'Discovered {new_block_count} new block{block_string}',
|
||||
terminal=True)
|
64
src/communicatorutils/netcheck.py
Executable file
64
src/communicatorutils/netcheck.py
Executable file
@ -0,0 +1,64 @@
|
||||
"""
|
||||
Onionr - Private P2P Communication.
|
||||
|
||||
Determine if our node is able to use Tor based
|
||||
on the status of a communicator instance
|
||||
and the result of pinging onion http servers
|
||||
"""
|
||||
import logger
|
||||
from utils import netutils
|
||||
from onionrutils import localcommand, epoch
|
||||
from . import restarttor
|
||||
|
||||
from typing import TYPE_CHECKING
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from deadsimplekv import DeadSimpleKV
|
||||
"""
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
"""
|
||||
|
||||
|
||||
def net_check(shared_state):
|
||||
"""Check if we are connected to the internet.
|
||||
|
||||
or not when we can't connect to any peers
|
||||
"""
|
||||
# for detecting if we have received incoming connections recently
|
||||
rec = False
|
||||
kv: "DeadSimpleKV" = shared_state.get_by_string("DeadSimpleKV")
|
||||
proxy_port = shared_state.get_by_string("NetController").socksPort
|
||||
|
||||
if len(kv.get('onlinePeers')) == 0:
|
||||
try:
|
||||
if (epoch.get_epoch() - int(localcommand.local_command
|
||||
('/lastconnect'))) <= 60:
|
||||
kv.put('isOnline', True)
|
||||
rec = True
|
||||
except ValueError:
|
||||
pass
|
||||
if not rec and not netutils.check_network(torPort=proxy_port):
|
||||
if not kv.get('shutdown'):
|
||||
if not shared_state.get_by_string(
|
||||
"OnionrCommunicatorDaemon").config.get(
|
||||
'general.offline_mode', False):
|
||||
logger.warn('Network check failed, are you connected to ' +
|
||||
'the Internet, and is Tor working? ' +
|
||||
'This is usually temporary, but bugs and censorship can cause this to persist, in which case you should report it to beardog [at] mailbox.org', # noqa
|
||||
terminal=True)
|
||||
restarttor.restart(shared_state)
|
||||
kv.put('offlinePeers', [])
|
||||
kv.put('isOnline', False)
|
||||
else:
|
||||
kv.put('isOnline', True)
|
28
src/communicatorutils/proxypicker.py
Executable file
28
src/communicatorutils/proxypicker.py
Executable file
@ -0,0 +1,28 @@
|
||||
"""
|
||||
Onionr - Private P2P Communication.
|
||||
|
||||
Pick a proxy to use based on a peer's address
|
||||
"""
|
||||
"""
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
"""
|
||||
|
||||
|
||||
def pick_proxy(peer_address):
|
||||
if peer_address.endswith('.onion'):
|
||||
return 'tor'
|
||||
elif peer_address.endswith('.i2p'):
|
||||
return 'i2p'
|
||||
raise ValueError(
|
||||
f"Peer address not ending with acceptable domain: {peer_address}")
|
28
src/communicatorutils/restarttor.py
Normal file
28
src/communicatorutils/restarttor.py
Normal file
@ -0,0 +1,28 @@
|
||||
"""
|
||||
Onionr - Private P2P Communication.
|
||||
|
||||
Restart Onionr managed Tor
|
||||
"""
|
||||
import netcontroller
|
||||
import config
|
||||
"""
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
"""
|
||||
|
||||
|
||||
def restart(shared_state):
|
||||
if not config.get('tor.use_existing_tor', False):
|
||||
net = shared_state.get(netcontroller.NetController)
|
||||
net.killTor()
|
||||
net.startTor()
|
148
src/communicatorutils/uploadblocks/__init__.py
Executable file
148
src/communicatorutils/uploadblocks/__init__.py
Executable file
@ -0,0 +1,148 @@
|
||||
"""Onionr - Private P2P Communication.
|
||||
|
||||
Upload blocks in the upload queue to peers from the communicator
|
||||
"""
|
||||
from typing import TYPE_CHECKING
|
||||
from time import sleep
|
||||
from threading import Thread
|
||||
from secrets import SystemRandom
|
||||
|
||||
from . import sessionmanager
|
||||
|
||||
from onionrtypes import UserID
|
||||
import logger
|
||||
from communicatorutils import proxypicker
|
||||
import onionrexceptions
|
||||
from onionrblocks import onionrblockapi as block
|
||||
from onionrblocks.blockmetadata.fromdata import get_block_metadata_from_data
|
||||
from onionrutils import stringvalidators, basicrequests
|
||||
from onionrutils.validatemetadata import validate_metadata
|
||||
from communicator import onlinepeers
|
||||
if TYPE_CHECKING:
|
||||
from deadsimplekv import DeadSimpleKV
|
||||
from communicator import OnionrCommunicatorDaemon
|
||||
"""
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
"""
|
||||
|
||||
|
||||
def upload_blocks_from_communicator(shared_state: 'OnionrCommunicatorDaemon'):
|
||||
"""Accept a communicator instance + upload blocks from its upload queue."""
|
||||
"""when inserting a block, we try to upload
|
||||
it to a few peers to add some deniability & increase functionality"""
|
||||
kv: "DeadSimpleKV" = shared_state.get_by_string("DeadSimpleKV")
|
||||
|
||||
session_manager: sessionmanager.BlockUploadSessionManager
|
||||
session_manager = shared_state.get(
|
||||
sessionmanager.BlockUploadSessionManager)
|
||||
tried_peers: UserID = []
|
||||
finishedUploads = []
|
||||
|
||||
SystemRandom().shuffle(kv.get('blocksToUpload'))
|
||||
|
||||
def remove_from_hidden(bl):
|
||||
sleep(60)
|
||||
try:
|
||||
shared_state.get_by_string(
|
||||
'PublicAPI').hideBlocks.remove(bl)
|
||||
except ValueError:
|
||||
pass
|
||||
|
||||
if len(kv.get('blocksToUpload')) != 0:
|
||||
for bl in kv.get('blocksToUpload'):
|
||||
if not stringvalidators.validate_hash(bl):
|
||||
logger.warn('Requested to upload invalid block', terminal=True)
|
||||
return
|
||||
session = session_manager.add_session(bl)
|
||||
for _ in range(min(len(kv.get('onlinePeers')), 6)):
|
||||
try:
|
||||
peer = onlinepeers.pick_online_peer(kv)
|
||||
if not block.Block(bl).isEncrypted:
|
||||
if peer in kv.get('plaintextDisabledPeers'):
|
||||
logger.info(f"Cannot upload plaintext block to peer that denies it {peer}") # noqa
|
||||
continue
|
||||
except onionrexceptions.OnlinePeerNeeded:
|
||||
continue
|
||||
try:
|
||||
session.peer_exists[peer]
|
||||
continue
|
||||
except KeyError:
|
||||
pass
|
||||
try:
|
||||
if session.peer_fails[peer] > 3:
|
||||
continue
|
||||
except KeyError:
|
||||
pass
|
||||
if peer in tried_peers:
|
||||
continue
|
||||
tried_peers.append(peer)
|
||||
url = f'http://{peer}/upload'
|
||||
try:
|
||||
data = block.Block(bl).getRaw()
|
||||
if not data:
|
||||
logger.warn(
|
||||
f"Couldn't get data for block in upload list {bl}",
|
||||
terminal=True)
|
||||
raise onionrexceptions.NoDataAvailable
|
||||
try:
|
||||
def __check_metadata():
|
||||
metadata = get_block_metadata_from_data(data)[0]
|
||||
if not validate_metadata(metadata, data):
|
||||
logger.warn(
|
||||
f"Metadata for uploading block not valid {bl}")
|
||||
raise onionrexceptions.InvalidMetadata
|
||||
__check_metadata()
|
||||
except onionrexceptions.DataExists:
|
||||
pass
|
||||
except( # noqa
|
||||
onionrexceptions.NoDataAvailable,
|
||||
onionrexceptions.InvalidMetadata) as _:
|
||||
finishedUploads.append(bl)
|
||||
break
|
||||
proxy_type = proxypicker.pick_proxy(peer)
|
||||
logger.info(
|
||||
f"Uploading block {bl[:8]} to {peer}", terminal=True)
|
||||
resp = basicrequests.do_post_request(
|
||||
url, data=data, proxyType=proxy_type,
|
||||
content_type='application/octet-stream')
|
||||
if resp is not False:
|
||||
if resp == 'success':
|
||||
Thread(target=remove_from_hidden,
|
||||
args=[bl], daemon=True).start()
|
||||
session.success()
|
||||
session.peer_exists[peer] = True
|
||||
elif resp == 'exists':
|
||||
session.success()
|
||||
session.peer_exists[peer] = True
|
||||
else:
|
||||
session.fail()
|
||||
session.fail_peer(peer)
|
||||
shared_state.get_by_string(
|
||||
'OnionrCommunicatorDaemon').getPeerProfileInstance(
|
||||
peer).addScore(-5)
|
||||
logger.warn(
|
||||
f'Failed to upload {bl[:8]}, reason: {resp}',
|
||||
terminal=True)
|
||||
else:
|
||||
session.fail()
|
||||
session_manager.clean_session()
|
||||
for x in finishedUploads:
|
||||
try:
|
||||
kv.get('blocksToUpload').remove(x)
|
||||
|
||||
shared_state.get_by_string(
|
||||
'PublicAPI').hideBlocks.remove(x)
|
||||
|
||||
except ValueError:
|
||||
pass
|
48
src/communicatorutils/uploadblocks/mixmate/__init__.py
Normal file
48
src/communicatorutils/uploadblocks/mixmate/__init__.py
Normal file
@ -0,0 +1,48 @@
|
||||
"""Onionr - Private P2P Communication.
|
||||
|
||||
Perform block mixing
|
||||
"""
|
||||
import time
|
||||
from typing import List
|
||||
|
||||
import onionrtypes
|
||||
from onionrblocks import onionrblockapi
|
||||
|
||||
from .pool import UploadPool
|
||||
from .pool import PoolFullException
|
||||
|
||||
from etc import onionrvalues
|
||||
|
||||
"""
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
"""
|
||||
upload_pool = UploadPool(4)
|
||||
|
||||
|
||||
def block_mixer(upload_list: List[onionrtypes.BlockHash],
|
||||
block_to_mix: onionrtypes.BlockHash):
|
||||
"""Delay and mix block inserts.
|
||||
|
||||
Take a block list and a received/created block and add it
|
||||
to the said block list
|
||||
"""
|
||||
bl = onionrblockapi.Block(block_to_mix)
|
||||
|
||||
try:
|
||||
if time.time() - bl.claimedTime > onionrvalues.BLOCK_POOL_MAX_AGE:
|
||||
raise ValueError
|
||||
except TypeError:
|
||||
pass
|
||||
if block_to_mix:
|
||||
upload_list.append(block_to_mix)
|
71
src/communicatorutils/uploadblocks/mixmate/pool.py
Normal file
71
src/communicatorutils/uploadblocks/mixmate/pool.py
Normal file
@ -0,0 +1,71 @@
|
||||
"""Onionr - Private P2P Communication.
|
||||
|
||||
Upload pool
|
||||
"""
|
||||
from typing import List
|
||||
from secrets import SystemRandom
|
||||
|
||||
import onionrutils
|
||||
import onionrtypes
|
||||
"""
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
"""
|
||||
|
||||
|
||||
class PoolFullException(Exception):
|
||||
"""For when the UploadPool is full.
|
||||
|
||||
Raise when a new hash is attempted to be added
|
||||
"""
|
||||
|
||||
|
||||
class PoolNotReady(Exception):
|
||||
"""Raise when UploadPool pool access is attempted without it being full."""
|
||||
|
||||
|
||||
class AlreadyInPool(Exception):
|
||||
"""Raise when a hash already in pool is attempted to be added again."""
|
||||
|
||||
|
||||
class UploadPool:
|
||||
"""Upload pool for mixing blocks together and delaying uploads."""
|
||||
|
||||
def __init__(self, pool_size: int):
|
||||
"""Create a new pool with a specified max size.
|
||||
|
||||
Uses private var and getter to avoid direct adding
|
||||
"""
|
||||
self._pool: List[onionrtypes.BlockHash] = []
|
||||
self._pool_size = pool_size
|
||||
self.birthday = onionrutils.epoch.get_epoch()
|
||||
|
||||
def add_to_pool(self, item: List[onionrtypes.BlockHash]):
|
||||
"""Add a new hash to the pool. Raise PoolFullException if full."""
|
||||
if len(self._pool) >= self._pool_size:
|
||||
raise PoolFullException
|
||||
if not onionrutils.stringvalidators.validate_hash(item):
|
||||
raise ValueError
|
||||
self._pool.append(item)
|
||||
|
||||
def get_pool(self) -> List[onionrtypes.BlockHash]:
|
||||
"""Get the hash pool in secure random order."""
|
||||
if len(self._pool) != self._pool_size:
|
||||
raise PoolNotReady
|
||||
|
||||
final_pool: List[onionrtypes.BlockHash] = list(self._pool)
|
||||
SystemRandom().shuffle(final_pool)
|
||||
|
||||
self._pool.clear()
|
||||
self.birthday = onionrutils.epoch.get_epoch()
|
||||
return final_pool
|
57
src/communicatorutils/uploadblocks/session.py
Normal file
57
src/communicatorutils/uploadblocks/session.py
Normal file
@ -0,0 +1,57 @@
|
||||
"""Onionr - Private P2P Communication.
|
||||
|
||||
Virtual upload "sessions" for blocks
|
||||
"""
|
||||
from typing import Union, Dict
|
||||
|
||||
from onionrtypes import UserID
|
||||
from onionrutils import stringvalidators
|
||||
from onionrutils import bytesconverter
|
||||
from onionrutils import epoch
|
||||
from utils import reconstructhash
|
||||
"""
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
"""
|
||||
|
||||
|
||||
class UploadSession:
|
||||
"""Manage statistics for an Onionr block upload session.
|
||||
|
||||
accept a block hash (incl. unpadded) as an argument
|
||||
"""
|
||||
|
||||
def __init__(self, block_hash: Union[str, bytes]):
|
||||
block_hash = bytesconverter.bytes_to_str(block_hash)
|
||||
block_hash = reconstructhash.reconstruct_hash(block_hash)
|
||||
if not stringvalidators.validate_hash(block_hash):
|
||||
raise ValueError
|
||||
|
||||
self.start_time = epoch.get_epoch()
|
||||
self.block_hash = reconstructhash.deconstruct_hash(block_hash)
|
||||
self.total_fail_count: int = 0
|
||||
self.total_success_count: int = 0
|
||||
self.peer_fails: Dict[UserID, int] = {}
|
||||
self.peer_exists: Dict[UserID, bool] = {}
|
||||
|
||||
def fail_peer(self, peer):
|
||||
try:
|
||||
self.peer_fails[peer] += 1
|
||||
except KeyError:
|
||||
self.peer_fails[peer] = 0
|
||||
|
||||
def fail(self):
|
||||
self.total_fail_count += 1
|
||||
|
||||
def success(self):
|
||||
self.total_success_count += 1
|
127
src/communicatorutils/uploadblocks/sessionmanager.py
Normal file
127
src/communicatorutils/uploadblocks/sessionmanager.py
Normal file
@ -0,0 +1,127 @@
|
||||
"""Onionr - Private P2P Communication.
|
||||
|
||||
Manager for upload 'sessions'
|
||||
"""
|
||||
from typing import List, Union, TYPE_CHECKING
|
||||
if TYPE_CHECKING:
|
||||
from deadsimplekv import DeadSimpleKV
|
||||
from session import UploadSession
|
||||
|
||||
from onionrutils import bytesconverter
|
||||
from etc import onionrvalues
|
||||
from utils import reconstructhash
|
||||
|
||||
from . import session
|
||||
"""
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
"""
|
||||
|
||||
|
||||
class BlockUploadSessionManager:
|
||||
"""Holds block UploadSession instances.
|
||||
|
||||
Optionally accepts iterable of sessions to added on init
|
||||
Arguments: old_session: iterable of old UploadSession objects
|
||||
"""
|
||||
|
||||
def __init__(self, old_sessions: List = None):
|
||||
if old_sessions is None:
|
||||
self.sessions = []
|
||||
else:
|
||||
self.sessions = old_sessions
|
||||
|
||||
def add_session(self,
|
||||
session_or_block: Union[str,
|
||||
bytes,
|
||||
session.UploadSession
|
||||
]
|
||||
) -> session.UploadSession:
|
||||
"""Create (or add existing) block upload session.
|
||||
|
||||
from a str/bytes block hex hash, existing UploadSession
|
||||
"""
|
||||
if isinstance(session_or_block, session.UploadSession):
|
||||
if session_or_block not in self.sessions:
|
||||
self.sessions.append(session_or_block)
|
||||
return session_or_block
|
||||
try:
|
||||
return self.get_session(session_or_block)
|
||||
except KeyError:
|
||||
pass
|
||||
# convert bytes hash to str
|
||||
if isinstance(session_or_block, bytes):
|
||||
session_or_block = bytesconverter.bytes_to_str(session_or_block)
|
||||
# intentionally not elif
|
||||
if isinstance(session_or_block, str):
|
||||
new_session = session.UploadSession(session_or_block)
|
||||
self.sessions.append(new_session)
|
||||
return new_session
|
||||
raise ValueError
|
||||
|
||||
def get_session(self,
|
||||
block_hash: Union[str, bytes]
|
||||
) -> session.UploadSession:
|
||||
block_hash = reconstructhash.deconstruct_hash(
|
||||
bytesconverter.bytes_to_str(block_hash))
|
||||
for sess in self.sessions:
|
||||
if sess.block_hash == block_hash:
|
||||
return sess
|
||||
raise KeyError
|
||||
|
||||
def clean_session(self,
|
||||
specific_session: Union[str, 'UploadSession'] = None):
|
||||
|
||||
comm_inst: 'OnionrCommunicatorDaemon' # type: ignore
|
||||
comm_inst = self._too_many.get_by_string( # pylint: disable=E1101 type: ignore
|
||||
"OnionrCommunicatorDaemon")
|
||||
kv: "DeadSimpleKV" = comm_inst.shared_state.get_by_string(
|
||||
"DeadSimpleKV")
|
||||
sessions_to_delete = []
|
||||
if kv.get('startTime') < 120:
|
||||
return
|
||||
onlinePeerCount = len(kv.get('onlinePeers'))
|
||||
|
||||
# If we have no online peers right now,
|
||||
if onlinePeerCount == 0:
|
||||
return
|
||||
|
||||
for sess in self.sessions:
|
||||
# if over 50% of peers that were online for a session have
|
||||
# become unavailable, don't kill sessions
|
||||
if sess.total_success_count > onlinePeerCount:
|
||||
if onlinePeerCount / sess.total_success_count >= 0.5:
|
||||
return
|
||||
# Clean sessions if they have uploaded to enough online peers
|
||||
if sess.total_success_count <= 0:
|
||||
continue
|
||||
if (sess.total_success_count / onlinePeerCount) >= \
|
||||
onionrvalues.MIN_BLOCK_UPLOAD_PEER_PERCENT:
|
||||
sessions_to_delete.append(sess)
|
||||
for sess in sessions_to_delete:
|
||||
try:
|
||||
self.sessions.remove(session)
|
||||
except ValueError:
|
||||
pass
|
||||
# TODO cleanup to one round of search
|
||||
# Remove the blocks from the sessions, upload list,
|
||||
# and waitforshare list
|
||||
try:
|
||||
kv.get('blocksToUpload').remove(
|
||||
reconstructhash.reconstruct_hash(sess.block_hash))
|
||||
except ValueError:
|
||||
pass
|
||||
try:
|
||||
kv.get('blocksToUpload').remove(sess.block_hash)
|
||||
except ValueError:
|
||||
pass
|
@ -6,22 +6,23 @@ import os
|
||||
from json import JSONDecodeError
|
||||
|
||||
import ujson as json
|
||||
from logger import log as logging
|
||||
import logger
|
||||
import filepaths
|
||||
|
||||
from . import onboarding
|
||||
"""
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
"""
|
||||
|
||||
_configfile = filepaths.config_file
|
||||
@ -106,7 +107,7 @@ def save():
|
||||
with open(get_config_file(), 'w', encoding="utf8") as configfile:
|
||||
json.dump(get_config(), configfile, indent=2)
|
||||
except JSONDecodeError:
|
||||
logging.warn('Failed to write to configuration file.')
|
||||
logger.warn('Failed to write to configuration file.')
|
||||
|
||||
|
||||
def reload():
|
||||
@ -117,7 +118,7 @@ def reload():
|
||||
set_config(json.loads(configfile.read()))
|
||||
except (FileNotFoundError, JSONDecodeError) as e:
|
||||
pass
|
||||
#logging.debug('Failed to parse configuration file.')
|
||||
#logger.debug('Failed to parse configuration file.')
|
||||
|
||||
|
||||
def get_config():
|
||||
|
73
src/config/onboarding.py
Normal file
73
src/config/onboarding.py
Normal file
@ -0,0 +1,73 @@
|
||||
"""Onionr - Private P2P Communication.
|
||||
|
||||
Setup config from onboarding choices
|
||||
"""
|
||||
from pathlib import Path
|
||||
from typing import Union
|
||||
from threading import Thread
|
||||
from time import sleep
|
||||
|
||||
from onionrtypes import JSONSerializable
|
||||
from onionrtypes import OnboardingConfig
|
||||
|
||||
import config
|
||||
"""
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
"""
|
||||
|
||||
|
||||
def _get_val_or_none(json: dict, key: str) -> Union[None, JSONSerializable]:
|
||||
try:
|
||||
return json['configInfo'][key]
|
||||
except KeyError:
|
||||
return None
|
||||
|
||||
|
||||
def set_config_from_onboarding(config_settings: OnboardingConfig):
|
||||
get = _get_val_or_none
|
||||
|
||||
config.reload()
|
||||
|
||||
if get(config_settings, 'optimize'):
|
||||
config.set('ui.animated_background', False)
|
||||
config.set('general.insert_deniable_blocks', False)
|
||||
|
||||
if get(config_settings, 'stateTarget') or not get(config_settings,
|
||||
'networkContrib'):
|
||||
config.set('general.security_level', 1)
|
||||
|
||||
if get(config_settings, 'localThreat'):
|
||||
config.set('general.security_level', 3)
|
||||
config.set('transports.lan', False)
|
||||
|
||||
config.set('ui.theme', 'light')
|
||||
if get(config_settings, 'useDark'):
|
||||
config.set('ui.theme', 'dark')
|
||||
|
||||
disabled = config.get('plugins.disabled', [])
|
||||
|
||||
if not get(config_settings, 'circles') or \
|
||||
config.get('general.security_level') > 0:
|
||||
disabled.append('flow')
|
||||
|
||||
if not get(config_settings, 'mail'):
|
||||
disabled.append('pms')
|
||||
|
||||
config.set('plugins.disabled', disabled)
|
||||
|
||||
config.set('general.store_plaintext_blocks',
|
||||
get(config_settings, 'plainContrib'))
|
||||
|
||||
config.set('onboarding.done', True, savefile=True)
|
||||
|
1
src/coredb/__init__.py
Normal file
1
src/coredb/__init__.py
Normal file
@ -0,0 +1 @@
|
||||
from . import keydb, blockmetadb
|
84
src/coredb/blockmetadb/__init__.py
Normal file
84
src/coredb/blockmetadb/__init__.py
Normal file
@ -0,0 +1,84 @@
|
||||
"""Onionr - Private P2P Communication.
|
||||
|
||||
Work with information relating to blocks stored on the node
|
||||
"""
|
||||
import sqlite3
|
||||
|
||||
from etc import onionrvalues
|
||||
from . import expiredblocks, updateblockinfo, add
|
||||
from .. import dbfiles
|
||||
"""
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
"""
|
||||
|
||||
update_block_info = updateblockinfo.update_block_info
|
||||
add_to_block_DB = add.add_to_block_DB
|
||||
|
||||
|
||||
def get_block_list(date_rec=None, unsaved=False):
|
||||
"""Get list of our blocks."""
|
||||
if date_rec is None:
|
||||
date_rec = 0
|
||||
|
||||
conn = sqlite3.connect(
|
||||
dbfiles.block_meta_db, timeout=onionrvalues.DATABASE_LOCK_TIMEOUT)
|
||||
c = conn.cursor()
|
||||
|
||||
execute = 'SELECT hash FROM hashes WHERE dateReceived' + \
|
||||
' >= ? ORDER BY dateReceived ASC;'
|
||||
args = (date_rec,)
|
||||
rows = list()
|
||||
for row in c.execute(execute, args):
|
||||
for i in row:
|
||||
rows.append(i)
|
||||
conn.close()
|
||||
return rows
|
||||
|
||||
|
||||
def get_block_date(blockHash):
|
||||
"""Return the date a block was received."""
|
||||
conn = sqlite3.connect(
|
||||
dbfiles.block_meta_db, timeout=onionrvalues.DATABASE_LOCK_TIMEOUT)
|
||||
c = conn.cursor()
|
||||
|
||||
execute = 'SELECT dateReceived FROM hashes WHERE hash=?;'
|
||||
args = (blockHash,)
|
||||
for row in c.execute(execute, args):
|
||||
for i in row:
|
||||
return int(i)
|
||||
conn.close()
|
||||
return None
|
||||
|
||||
|
||||
def get_blocks_by_type(blockType, orderDate=True):
|
||||
"""Return a list of blocks by the type."""
|
||||
|
||||
conn = sqlite3.connect(
|
||||
dbfiles.block_meta_db, timeout=onionrvalues.DATABASE_LOCK_TIMEOUT)
|
||||
c = conn.cursor()
|
||||
|
||||
if orderDate:
|
||||
execute = 'SELECT hash FROM hashes WHERE dataType=? ORDER BY dateReceived;'
|
||||
else:
|
||||
execute = 'SELECT hash FROM hashes WHERE dataType=?;'
|
||||
|
||||
args = (blockType,)
|
||||
rows = list()
|
||||
|
||||
for row in c.execute(execute, args):
|
||||
for i in row:
|
||||
rows.append(i)
|
||||
conn.close()
|
||||
return rows
|
||||
|
49
src/coredb/blockmetadb/add.py
Normal file
49
src/coredb/blockmetadb/add.py
Normal file
@ -0,0 +1,49 @@
|
||||
"""Onionr - Private P2P Communication.
|
||||
|
||||
Add an entry to the block metadata database
|
||||
"""
|
||||
import sqlite3
|
||||
import secrets
|
||||
from onionrutils import epoch
|
||||
from onionrblocks import blockmetadata
|
||||
from etc import onionrvalues
|
||||
from .. import dbfiles
|
||||
from onionrexceptions import BlockMetaEntryExists
|
||||
"""
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
"""
|
||||
|
||||
|
||||
def add_to_block_DB(newHash, selfInsert=False, dataSaved=False):
|
||||
"""
|
||||
Add a hash value to the block db
|
||||
|
||||
Should be in hex format!
|
||||
"""
|
||||
|
||||
if blockmetadata.has_block(newHash):
|
||||
raise BlockMetaEntryExists
|
||||
conn = sqlite3.connect(
|
||||
dbfiles.block_meta_db, timeout=onionrvalues.DATABASE_LOCK_TIMEOUT)
|
||||
c = conn.cursor()
|
||||
currentTime = epoch.get_epoch() + secrets.randbelow(61)
|
||||
if selfInsert or dataSaved:
|
||||
selfInsert = 1
|
||||
else:
|
||||
selfInsert = 0
|
||||
data = (newHash, currentTime, '', selfInsert)
|
||||
c.execute(
|
||||
'INSERT INTO hashes (hash, dateReceived, dataType, dataSaved) VALUES(?, ?, ?, ?);', data)
|
||||
conn.commit()
|
||||
conn.close()
|
41
src/coredb/blockmetadb/expiredblocks.py
Normal file
41
src/coredb/blockmetadb/expiredblocks.py
Normal file
@ -0,0 +1,41 @@
|
||||
"""Onionr - Private P2P Communication.
|
||||
|
||||
Get a list of expired blocks still stored
|
||||
"""
|
||||
import sqlite3
|
||||
from onionrutils import epoch
|
||||
from .. import dbfiles
|
||||
from etc import onionrvalues
|
||||
"""
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
"""
|
||||
|
||||
|
||||
def get_expired_blocks():
|
||||
"""Return a list of expired blocks."""
|
||||
conn = sqlite3.connect(
|
||||
dbfiles.block_meta_db, timeout=onionrvalues.DATABASE_LOCK_TIMEOUT)
|
||||
c = conn.cursor()
|
||||
date = int(epoch.get_epoch())
|
||||
|
||||
compiled = (date,)
|
||||
execute = 'SELECT hash FROM hashes WHERE ' + \
|
||||
'expire <= ? ORDER BY dateReceived;'
|
||||
|
||||
rows = list()
|
||||
for row in c.execute(execute, compiled):
|
||||
for i in row:
|
||||
rows.append(i)
|
||||
conn.close()
|
||||
return rows
|
52
src/coredb/blockmetadb/updateblockinfo.py
Normal file
52
src/coredb/blockmetadb/updateblockinfo.py
Normal file
@ -0,0 +1,52 @@
|
||||
"""Onionr - Private P2P Communication.
|
||||
|
||||
Update block information in the metadata database by a field name
|
||||
"""
|
||||
import sqlite3
|
||||
|
||||
from .. import dbfiles
|
||||
from etc import onionrvalues
|
||||
"""
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
"""
|
||||
|
||||
|
||||
def update_block_info(hash, key, data):
|
||||
"""set info associated with a block
|
||||
|
||||
hash - the hash of a block
|
||||
dateReceived - the date the block was recieved, not necessarily when it was created
|
||||
decrypted - if we can successfully decrypt the block
|
||||
dataType - data type of the block
|
||||
dataFound - if the data has been found for the block
|
||||
dataSaved - if the data has been saved for the block
|
||||
sig - defunct
|
||||
author - defunct
|
||||
dateClaimed - timestamp claimed inside the block, only as trustworthy as the block author is
|
||||
expire - expire date for a block
|
||||
"""
|
||||
if key not in ('dateReceived', 'decrypted', 'dataType', 'dataFound',
|
||||
'dataSaved', 'sig', 'author', 'dateClaimed', 'expire'):
|
||||
raise ValueError('Key must be in the allowed list')
|
||||
|
||||
conn = sqlite3.connect(dbfiles.block_meta_db,
|
||||
timeout=onionrvalues.DATABASE_LOCK_TIMEOUT)
|
||||
c = conn.cursor()
|
||||
args = (data, hash)
|
||||
# Unfortunately, not really possible to prepare this statement
|
||||
c.execute("UPDATE hashes SET " + key + " = ? where hash = ?;", args)
|
||||
conn.commit()
|
||||
conn.close()
|
||||
|
||||
return True
|
11
src/coredb/dbfiles.py
Normal file
11
src/coredb/dbfiles.py
Normal file
@ -0,0 +1,11 @@
|
||||
from utils import identifyhome
|
||||
import filepaths
|
||||
home = identifyhome.identify_home()
|
||||
if not home.endswith('/'): home += '/'
|
||||
|
||||
block_meta_db = '%sblock-metadata.db' % (home)
|
||||
block_data_db = '%s/block-data.db' % (filepaths.block_data_location,)
|
||||
address_info_db = '%saddress.db' % (home,)
|
||||
user_id_info_db = '%susers.db' % (home,)
|
||||
forward_keys_db = '%sforward-keys.db' % (home,)
|
||||
blacklist_db = '%sblacklist.db' % (home,)
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user