-
Notifications
You must be signed in to change notification settings - Fork 37.7k
Full CJDNS support #23077
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Full CJDNS support #23077
Conversation
Concept ACK and building to try it 😃 Edit: debug build is clean and a first read through the commits looks straightforward. |
Concept ACK |
Concept ACK 🌱 |
Sorry but this doesn't look good enough to add one more network to Bitcoin Core. We already have 4 options: ipv4, ipv6, Tor, i2p and 14 combinations which can be used in Will do more research about CJDNS and compare with other networks before ACKing the concept. Let me know if you know any links. |
The following sections might be updated with supplementary metadata relevant to reviewers and maintainers. ConflictsReviewers, this pull request conflicts with the following ones:
If you consider this pull request important, please also help to review the conflicting pull requests. Ideally, start with the one that should be merged first. |
Thanks for providing this motivation, it's helpful to understand the aim of this PR. Could you go a bit further and share your perspective on why you think CJDNS should be a first class citizen network in bitcoin core? Does it provide different features / privacy / etc. from other networks? Or is this a case where you think optionality is good, so supporting more networks is better? Thanks in advance! |
FWIW, BIP155 does already reserve a network ID for CJDNS (that's not an argument either way of course, but perhaps the BIP's author have opinions on this too). @laanwj? |
I did some research about CJDNS, GNUnet and Yggdrasil. Will read more about these networks and also compare with few others in next few days. Shared initial thoughts and things I did here: https://blockchaincommons.github.io/Bitcoin-Camouflage//blog/cjdns/ |
@prayank23, @amitiuttarwar, Compared to IPv4/6, CJDNS provides e2e encryption and protects nodes from the traditional traffic analysis and filtering. For example, an ISP blocks port 8333 (dumb) or analyses the traffic to/from a given node, regardless of the port (it is easy to detect that it is Bitcoin P2P protocol being talked on a TCP connection, even if the port is not 8333). Compared to Tor and I2P, CJDNS provides redundancy. Each of those have their own shades, which may suit different users. For example Tor is popular/widespread but is somewhat centralized, which could lead to problems. I2P connections have source address, but I2P is somewhat slow. CJDNS does not hide the sender and the recipient from intermediate routers, but it is fast. Different things may work for different people. It is good to have options. So, why not have support for CJDNS? It must be noted that support for X does not come for free. We have to pay the following prices:
For the implementation cost, notice that CJDNS is already included in BIP155 and that there is already rudimentary support for it in $ git grep -i cjdns origin/master |wc -l
49 As a result this PR is relatively small and straight-forward. Review cost should be low. From the application's point of view, connecting to CJDNS is as easy as connecting to a normal IPv6 address. Bitcoin Core need not implement support for a specific proxy that talks a specific protocol. Tor and I2P require that. We have this maintenance cost for them: $ wc -l src/torcontrol.cpp src/i2p.cpp
636 src/torcontrol.cpp
418 src/i2p.cpp Support for CJDNS goes without that, so its maintenance cost is low compared to Tor and I2P. Notice also that OpenWRT routers support CJDNS, so from user's perspective it would be a matter of enabling it on their routers and running Bitcoin Core with In the case of CJDNS, my personal opinion is that the benefits outweigh the cost. |
Yes, BIP155 and Tor v3 implementation were both fairly deep changes. I2P was also extensive. This change set is relatively tiny, I've done a first review pass, and in terms of time it was well under 10% that of any of the BIP155 impl, Tor v3, and I2P for me. |
Concept ACK, awesome to see this! |
Concept ACK seeing as there is already basic existing support for this in master and noting that this may match some users' needs of speed while still protecting against traffic analysis. Going to build and try this out |
A testing/experimental Bitcoin Core node is running (most of the time) at |
// learn a new local address | ||
bool AddLocal(const CService& addr, int nScore) | ||
bool AddLocal(const CService& addr_, int nScore) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In commit ec2dc39,
Not sure I like this addr_ approach.
Don't you think a caller should be aware of the transition to CJDNS?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think the callers of AddLocal()
do not care that a passed fc...
address may be interpreted as CJDNS instead of IPv6.
Actually, I started by doing the flip just before AddLocal()
is called, but ended up with duplicated code all over the place in all callers of AddLocal()
which prompted me to move that snippet inside AddLocal()
.
Ideally a CJDNS object should be returned by LookupIntern()
which is the function which creates the CNetAddr
objects, so they will not be created as IPv6 and later flipped to CJDNS. However LookupIntern()
and WrappedGetAddrInfo()
(which it uses) are defined in netbase.cpp
and IsReachable()
(needed to tell whether IPv6 or CJDNS should be created) is in net.cpp
which would create a circular dependency. Hmm... maybe I should move IsReachable()
to netbase.cpp
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actually, I started by doing the flip just before AddLocal() is called, but ended up with duplicated code all over the place in all callers of AddLocal() which prompted me to move that snippet inside AddLocal().
I think this is a good move, i was just wondering whether it's ok to do it quietly.
Imagine logging something like "finished processing IPv6 addr" after calling AddLocal, while it's not actually IPv6.
I think since this is not really the case now, making a comment along AddrLocal might be sufficient to prevent the confusion.
Hmm... maybe I should move IsReachable() to netbase.cpp?
Perhaps attempt that in a separate PR then?
ACK baae5be modulo questions above. I haven't run the code. |
How about simply requiring a " |
Internally the addresses are already distinguished in the For representation purposes:
Does that answer the question or did I misunderstand it? |
From what I understood back then is that CJDNS is fairly pervasive in mesh networking. You can peer it over arbitrary networks and physical layers but you'll still have a global address from the viewpoint of software. With no central authority that needs to assign that. What makes it different to I2P and Tor is that it is not an anonymity network. It encrypts the payload but does not hide where it comes from. This means it can be very lightweight and low-latency. This is good for initial sync and gossip, maybe not so much for transaction broadcasting. But it's not worse than clearnet. Also unlike those, from the viewpoint of software it's simply another IPv6 interface. This means it requires only little extra code to support (mostly related to gossip and reachability). No need for proxies or special negotiation (as @vasild already mentions above). |
Connected to @vasild with his help (thanks!) and the connection has been reliable and fast so far. Running a bitcoind cjdns service at |
Ah, I did try to connect to Vasil a few days ago and had trouble. Was there something specific you had to resolve before you could? I'll try again tomorrow when I can. |
This will help with propagation, so that multi-homed nodes can learn CJDNS addresses outside of the CJDNS network.
CJDNS addresses start with constant 8 bits, so in order to account for the first 4 random ones, we must take the first 12. Otherwise the entire CJDNS network will belong to one group.
An IPv6 address from fc00::/8 could be either from the CJDNS network or from a private-unroutable-reserved segment of IPv6. A seed node with such an address must be from the CJDNS network, otherwise other peers will not be able to connect to it.
ACK 420695c |
re-ACK 420695c per Have been running this patch with that change since yesterday evening. |
Code review ACK 420695c |
7b65287 cli: hoist networks class data members to a constant (Jon Atack) 5bd40a3 cli: add cjdns network to -addrinfo and -netinfo (Jon Atack) Pull request description: Follow-up to #23077 and #23324. ``` $ ./src/bitcoin-cli -addrinfo { "addresses_known": { "ipv4": 47782, "ipv6": 10307, "onion": 8030, "i2p": 41, "cjdns": 1, "total": 66161 } } $ ./src/bitcoin-cli -netinfo Bitcoin Core client v22.99.0-deb6223d4c55 - server 70016/Satoshi:22.99.0(jon)/ ipv4 ipv6 onion i2p cjdns total block manual in 0 5 12 5 1 23 out 2 2 9 5 2 20 2 10 total 2 7 21 10 3 43 ``` ``` $ ./src/bitcoin-cli -netinfo 1 ```  ACKs for top commit: laanwj: Code review ACK 7b65287 Tree-SHA512: 9c740d394d9842d38a1c01a824271b25277baac11ed090f0430daa15b580c2bf3d114ac6b8254b19d6aaee57cbe1ca6a414996e6994e0bf4a577bed771382eca
7b65287 cli: hoist networks class data members to a constant (Jon Atack) 5bd40a3 cli: add cjdns network to -addrinfo and -netinfo (Jon Atack) Pull request description: Follow-up to bitcoin#23077 and bitcoin#23324. ``` $ ./src/bitcoin-cli -addrinfo { "addresses_known": { "ipv4": 47782, "ipv6": 10307, "onion": 8030, "i2p": 41, "cjdns": 1, "total": 66161 } } $ ./src/bitcoin-cli -netinfo Bitcoin Core client v22.99.0-deb6223d4c55 - server 70016/Satoshi:22.99.0(jon)/ ipv4 ipv6 onion i2p cjdns total block manual in 0 5 12 5 1 23 out 2 2 9 5 2 20 2 10 total 2 7 21 10 3 43 ``` ``` $ ./src/bitcoin-cli -netinfo 1 ```  ACKs for top commit: laanwj: Code review ACK 7b65287 Tree-SHA512: 9c740d394d9842d38a1c01a824271b25277baac11ed090f0430daa15b580c2bf3d114ac6b8254b19d6aaee57cbe1ca6a414996e6994e0bf4a577bed771382eca
…JDNS peers b7be28c test: add combined CJDNS/I2P/localhost/onion eviction protection tests (Jon Atack) 0a1bb84 test: add tests for inbound eviction protection of CJDNS peers (Jon Atack) 0c00c0c test: fix off-by-one logic in an eviction protection test (Jon Atack) f7b8094 p2p: extend inbound eviction protection by network to CJDNS peers (Jon Atack) Pull request description: Extend inbound eviction protection for peers connected over CJDNS, as is the case for peers connected via onion, localhost, and I2P since #21261 and #20197. CJDNS peers seem to have better min ping latency than onion and I2P peers but still higher than that of unencrypted IPv4/6 peers and can be disadvantaged under our eviction criteria. They are also very few in number, which is a further reason to protect them, as the goal of this logic is to favorise the diversity of our peer connections. CJDNS support was added in #23077 for the upcoming v23 release. ACKs for top commit: laanwj: Concept and code review ACK b7be28c w0xlt: tACK b7be28c Tree-SHA512: 89ebdd217602e16ae14b9bd0d5a25fc09f9b2384c951f820bc0f5a6d8452bbc9042065db817d5d5296c0ad22988491a83fc5b9a611e660c40ebd4f03448c4061
Adapted in part from the CJDNS description in bitcoin#23077 by Vasil Dimov. Co-authored-by: Vasil Dimov <vd@FreeBSD.org>
Adapted in part from the CJDNS description in bitcoin#23077 by Vasil Dimov. Co-authored-by: Vasil Dimov <vd@FreeBSD.org>
Adapted in part from the CJDNS description in bitcoin#23077 by Vasil Dimov. Co-authored-by: Vasil Dimov <vd@FreeBSD.org>
Adapted in part from the CJDNS description in bitcoin#23077 by Vasil Dimov. Co-authored-by: Vasil Dimov <vd@FreeBSD.org>
Adapted in part from the CJDNS description in bitcoin#23077 by Vasil Dimov and from CJDNS documentation and feedback by Caleb James DeLisle. Co-authored-by: Vasil Dimov <vd@FreeBSD.org>
Adapted in part from the CJDNS description in bitcoin#23077 by Vasil Dimov and from CJDNS documentation and feedback by Caleb James DeLisle. Co-authored-by: Vasil Dimov <vd@FreeBSD.org>
…NS how-to documentation f44efc3 doc: update i2p.md with cjdns, improve local addresses section (Jon Atack) 3bf6f0c doc: update tor.md with cjdns and getnodeaddresses, fix tor grep, (Jon Atack) ed15848 doc: create initial doc/cjdns.md for cjdns how-to documentation (Jon Atack) Pull request description: and update and improve doc/tor.md and doc/i2p.md. Adapted in part from the CJDNS description in bitcoin/bitcoin#23077 and feedback by Vasil Dimov and from the CJDNS documentation and feedback by Caleb James DeLisle. Targets backport to v23.x. Co-authored-by: Vasil Dimov <vd@FreeBSD.org> ACKs for top commit: vasild: ACK f44efc3 lsilva01: ACK f44efc3 Tree-SHA512: 7b7c69f76bc8a5705d324892f32bfe0eb21bcf048054748053eca167c65a2121f6332f40ac6ff98c955e6e8b53233c74c365d887c364ef1d5944f1c49675a6b4
Adapted in part from the CJDNS description in bitcoin#23077 by Vasil Dimov and from CJDNS documentation and feedback by Caleb James DeLisle. Co-authored-by: Vasil Dimov <vd@FreeBSD.org> Github-Pull: bitcoin#24555 Rebased-From: ed15848
Adapted in part from the CJDNS description in bitcoin#23077 by Vasil Dimov and from CJDNS documentation and feedback by Caleb James DeLisle. Co-authored-by: Vasil Dimov <vd@FreeBSD.org> Github-Pull: bitcoin#24555 Rebased-From: ed15848
CJDNS overview
CJDNS is like a distributed, shared VPN with multiple entry points where every participant can reach any other participant. All participants use addresses from the
fc00::/8
network (reserved IPv6 range). Installation and configuration is done outside of applications, similarly to VPN (either in the host/OS or on the network router).Motivation
Even without this PR it is possible to connect two Bitcoin Core nodes through CJDNS manually by using e.g.
-addnode
in environments where CJDNS is set up. However, this PR is necessary for address relay to work properly and automatic connections to be made to CJDNS peers. I.e. to make CJDNS a first class citizen network like IPv4, IPv6, Tor and I2P.Considerations
An address from the
fc00::/8
network, could mean two things:10.0.0.0/8
. Bitcoin Core could be running on a machine with such address and have peers with those (e.g. in a local network), but those addresses are not relayed to other peers because they are not globally routable on the internet.So, Bitcoin Core needs to be able to tell which one is it when it encounters a bare
fc00::/8
address, e.g. from-externalip=
or by looking up the machine's own addresses. Thus a new config option is introduced-cjdnsreachable
:-cjdnsreachable=0
: it is assumed afc00::/8
address is a private IPv6 (1.)-cjdnsreachable=1
: it is assumed afc00::/8
address is a CJDNS one (2.)After setting up CJDNS outside of Bitcoin Core, a node operator only needs to enable this option.
Addresses from P2P relay/gossip don't need that because they are properly tagged as IPv6 or as CJDNS.
For testing