Repository navigation
Conversation
…rectory with 3 updates Bumps the production-dependencies group with 3 updates in the / directory: [io.netty:netty-all](https://github.com/netty/netty), [dnsjava:dnsjava](https://github.com/dnsjava/dnsjava) and software.amazon.awssdk:route53. Updates `io.netty:netty-all` from 4.2.8.Final to 4.2.9.Final - [Commits](netty/netty@netty-4.2.8.Final...netty-4.2.9.Final) Updates `dnsjava:dnsjava` from 3.6.3 to 3.6.4 - [Release notes](https://github.com/dnsjava/dnsjava/releases) - [Changelog](https://github.com/dnsjava/dnsjava/blob/master/Changelog) - [Commits](dnsjava/dnsjava@v3.6.3...v3.6.4) Updates `software.amazon.awssdk:route53` from 2.40.8 to 2.41.10 --- updated-dependencies: - dependency-name: io.netty:netty-all dependency-version: 4.2.9.Final dependency-type: direct:production update-type: version-update:semver-patch dependency-group: production-dependencies - dependency-name: dnsjava:dnsjava dependency-version: 3.6.4 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: production-dependencies - dependency-name: software.amazon.awssdk:route53 dependency-version: 2.41.10 dependency-type: direct:production update-type: version-update:semver-minor dependency-group: production-dependencies ... Signed-off-by: dependabot[bot] <support@github.com>
… 1 directory with 7 updates Bumps the development-dependencies group with 7 updates in the / directory: | Package | From | To | | --- | --- | --- | | software.amazon.awssdk:apache-client | `2.40.8` | `2.41.34` | | [org.junit.jupiter:junit-jupiter](https://github.com/junit-team/junit-framework) | `6.0.1` | `6.0.3` | | [org.mockito:mockito-core](https://github.com/mockito/mockito) | `5.20.0` | `5.21.0` | | [org.mockito:mockito-junit-jupiter](https://github.com/mockito/mockito) | `5.20.0` | `5.21.0` | | [org.apache.maven.plugins:maven-compiler-plugin](https://github.com/apache/maven-compiler-plugin) | `3.14.1` | `3.15.0` | | [org.apache.maven.plugins:maven-surefire-plugin](https://github.com/apache/maven-surefire) | `3.5.4` | `3.5.5` | | [org.sonatype.central:central-publishing-maven-plugin](https://github.com/sonatype/central-publishing-maven-plugin) | `0.9.0` | `0.10.0` | Updates `software.amazon.awssdk:apache-client` from 2.40.8 to 2.41.34 Updates `org.junit.jupiter:junit-jupiter` from 6.0.1 to 6.0.3 - [Release notes](https://github.com/junit-team/junit-framework/releases) - [Commits](junit-team/junit-framework@r6.0.1...r6.0.3) Updates `org.mockito:mockito-core` from 5.20.0 to 5.21.0 - [Release notes](https://github.com/mockito/mockito/releases) - [Commits](mockito/mockito@v5.20.0...v5.21.0) Updates `org.mockito:mockito-junit-jupiter` from 5.20.0 to 5.21.0 - [Release notes](https://github.com/mockito/mockito/releases) - [Commits](mockito/mockito@v5.20.0...v5.21.0) Updates `org.mockito:mockito-junit-jupiter` from 5.20.0 to 5.21.0 - [Release notes](https://github.com/mockito/mockito/releases) - [Commits](mockito/mockito@v5.20.0...v5.21.0) Updates `org.apache.maven.plugins:maven-compiler-plugin` from 3.14.1 to 3.15.0 - [Release notes](https://github.com/apache/maven-compiler-plugin/releases) - [Commits](apache/maven-compiler-plugin@maven-compiler-plugin-3.14.1...maven-compiler-plugin-3.15.0) Updates `org.apache.maven.plugins:maven-surefire-plugin` from 3.5.4 to 3.5.5 - [Release notes](https://github.com/apache/maven-surefire/releases) - [Commits](apache/maven-surefire@surefire-3.5.4...surefire-3.5.5) Updates `org.sonatype.central:central-publishing-maven-plugin` from 0.9.0 to 0.10.0 - [Commits](https://github.com/sonatype/central-publishing-maven-plugin/commits) --- updated-dependencies: - dependency-name: software.amazon.awssdk:apache-client dependency-version: 2.41.34 dependency-type: direct:development update-type: version-update:semver-minor dependency-group: development-dependencies - dependency-name: org.junit.jupiter:junit-jupiter dependency-version: 6.0.3 dependency-type: direct:development update-type: version-update:semver-patch dependency-group: development-dependencies - dependency-name: org.mockito:mockito-core dependency-version: 5.21.0 dependency-type: direct:development update-type: version-update:semver-minor dependency-group: development-dependencies - dependency-name: org.mockito:mockito-junit-jupiter dependency-version: 5.21.0 dependency-type: direct:development update-type: version-update:semver-minor dependency-group: development-dependencies - dependency-name: org.mockito:mockito-junit-jupiter dependency-version: 5.21.0 dependency-type: direct:development update-type: version-update:semver-minor dependency-group: development-dependencies - dependency-name: org.apache.maven.plugins:maven-compiler-plugin dependency-version: 3.15.0 dependency-type: direct:development update-type: version-update:semver-minor dependency-group: development-dependencies - dependency-name: org.apache.maven.plugins:maven-surefire-plugin dependency-version: 3.5.5 dependency-type: direct:development update-type: version-update:semver-patch dependency-group: development-dependencies - dependency-name: org.sonatype.central:central-publishing-maven-plugin dependency-version: 0.10.0 dependency-type: direct:development update-type: version-update:semver-minor dependency-group: development-dependencies ... Signed-off-by: dependabot[bot] <support@github.com>
Bumps [actions/upload-artifact](https://github.com/actions/upload-artifact) from 5 to 7. - [Release notes](https://github.com/actions/upload-artifact/releases) - [Commits](actions/upload-artifact@v5...v7) --- updated-dependencies: - dependency-name: actions/upload-artifact dependency-version: '7' dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] <support@github.com>
…actions/upload-artifact-7 chore(ci)(deps): Bump actions/upload-artifact from 5 to 7
…nt-dependencies-20e0884118 chore(deps)(deps-dev): Bump the development-dependencies group across 1 directory with 7 updates
…n-dependencies-9d66e4106a chore(deps)(deps): Bump the production-dependencies group across 1 directory with 3 updates
The library is now safe to expose to peers nobody vouches for. The wire
protocol changes (frame version 2, mutual handshake, signed discovery):
0.1.7 nodes do not talk to 0.1.6 nodes.
Security
- Signed discovery (KadPacket): every UDP datagram is signed with the
node key over sha256("xdag-discovery-v2" | networkId | code | body);
the sender's identity is recovered from the signature and must match
the id the packet claims. Addresses a node claims for itself are
ignored: a node is reached where its datagrams come from.
- Endpoint proof: a node enters the table, is dialled or gets FIND_NODE
answered only after it answered a ping of ours with a pong that
echoes the hash of that ping; bonds expire after 12 h. Neighbour
answers are sent in datagrams of at most 8 nodes (1280-byte limit)
and accepted for 5 s after the question, up to a bucket's worth.
- Mutual handshake: INIT both ways; HELLO signs the dialler's nonce,
WORLD signs sha256(acceptor nonce | acceptor id). A recorded WORLD
cannot be replayed; self-connections are detected.
- Admission control before any handler sees a byte: bans enforced on
inbound connections, closed-network mode (configured peers only),
limits on total / inbound / pending-handshake / per-IP / per-subnet
connections, handshake timeout.
- Bounds on everything read off the wire (SimpleDecoder.readCount):
neighbours <= 16, capabilities <= 32, DNS nodes <= 1024; strict frame
codec (no resync on garbage); one packet in flight per connection;
per-source rate limit before signature verification; bounded numbers
of tracked nodes per IP / subnet / unverified / total; table limits.
- Backpressure: inbound byte rate guard, outbound queue bound, Netty
water marks, Channel.isWritable() / onWritabilityChanged.
- Host strings from other nodes are never resolved; ReputationManager
without Java serialisation and bounded; no network access when a
P2pConfig is created (external IP detection on request, HTTPS only).
Fixed
- Ban duration overflow after ~48 offences.
- Channel.send(Bytes) wrote unframed bytes to the socket.
- Node ids in discovery (hex) and in the handshake (Base58) never
matched; peers are now identified by the listen address they announce
(the loopback heuristic kept a node from connecting to a second
neighbour on one machine).
- getConnectableNodes() returned unverified nodes.
- PeerClient.connect() blocked until the connection closed; stop()
without start() threw.
- Remote-triggered log lines downgraded; tests hermetic (no leaked
ports, no internet).
Added
- P2pService.setPermissionless(boolean) to open or close the network at
run time, and the matching P2pConfig settings.
910 tests pass (2 skipped: they need the external-IP services).
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
…art() only changes the setting Two start-up problems found while testing xdagj on top of 0.1.7. - P2pService.start() returned while the TCP listener (PeerServer) and the discovery socket (DiscoverServer) were still being bound on their own threads. A node started right after another one dialled it too early and was refused - and an address that failed is not dialled again for 30 s, so the two connected half a minute later. stop() / close() called that early found nothing to close, and the socket stayed open for the life of the process (PeerServerTest left a listener on port 8080 that way). PeerServer.start() and DiscoverServer.init() now return when the socket is bound, or when it is clear that it cannot be: that is logged and the service runs without it (PeerServer.isListening(), NodeManager.isDiscoveryListening()). A stop that comes while a socket is being bound closes it as soon as it is. start() twice starts once; start() and stop() exclude each other. - P2pService.setPermissionless(true) before start() ran the connect loop on a service that had neither a node table nor a client yet: a NullPointerException, caught and logged as a warning at every start of a node that begins in open mode. On a service that is not running only the setting changes; ChannelManager.triggerImmediateConnect() does nothing before start and after stop; NodeManager returns empty node lists before init() instead of throwing. Tests: 923 pass, 2 skipped (they need the internet). New: P2pServiceStartTest (two services on 127.0.0.1 connect at once; both sockets bound on return; mode set before start; start twice), DiscoverServerTest, PeerServerTest (bound on return, port free after stop, port taken), ChannelManagerTest (the trigger only works while running), P2pServiceTest (mode before start and after stop, node lists before start). With either fix disabled, its tests fail. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
The start-up fixes of the previous commit (start() returns with the sockets bound; setPermissionless() before start() only changes the setting) are released as 0.1.8 instead of being added to 0.1.7, so that a build with them can be told from one without. Nothing changes on the wire: 0.1.8 and 0.1.7 nodes talk to each other. - pom.xml, default client id: 0.1.8. - CHANGELOG: the two fixes move from 0.1.7 to a 0.1.8 section. - README and guides: dependency snippet and jar names (they still said 0.1.6), what is new in 0.1.8 and 0.1.7 - including that 0.1.7 and later do not talk to 0.1.6 -, test count. Tests: 923 pass, 2 skipped (they need the internet). Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
The figures were those of 0.1.3 (76% of 15,810 instructions). Measured again with JaCoCo 0.8.14 (mvn test, example package excluded as before), three runs: instructions 75.5% (15,100-15,106 of 19,994) branches 59.8% (1,366-1,367 of 2,286) lines 75.5% (3,396-3,397 of 4,500) methods 84.5% (580 of 686), classes 90 of 95 The code grew by a quarter with the hardening of 0.1.7, and its branches are covered less well than the rest was. The runs were offline: the two tests that need the internet were skipped, which leaves the external-IP lookup uncovered. The suite takes about a minute and a half, not thirty seconds. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
The P2P layer, hardened so that it can face peers nobody vouches for. This is the precondition for removing the node whitelist in xdagj: XDagger/xdagj#363 depends on this pull request.
Two versions in one branch:
CHANGELOG.mdhas the full list. The reasoning behind each change is in xdagj'sdocs/SECURITY_AUDIT_OPEN_NETWORK.md(findings P1-P16), which is part of XDagger/xdagj#363.0.1.7
FIND_NODEanswered only after it answered one of our pings.P2pService.setPermissionless).Channel.send(Bytes)writing unframed bytes, node ids of discovery and handshake never matching (which defeated duplicate-connection detection),getConnectableNodes()returning unverified nodes,PeerClient.connect(host, port)blocking until the connection closed.ReputationManagerno longer uses Java serialisation;P2pConfigperforms no network access on construction.0.1.8
P2pService.start()returns when the TCP listener and the discovery socket are bound. It used to return while they were still coming up on their own threads: a node started right after another dialled too early and connected 30 s later, and an earlystop()left the socket open for the life of the process.P2pService.setPermissionless()may be called beforestart(); it then only changes the setting (it used to run the connect loop on a service that was not running: aNullPointerException, logged as a warning).Compatibility
permissionless,bindIp, connection limits,allowPrivateAddresses; see the "Added" section of the changelog.Testing
mvn test: 923 tests, 0 failures. Two tests need internet access and are skipped without it.mvn license:checkpasses.Notes for reviewers
master.developis currently 7 commits behindmaster(dependency updates), so untildevelopis brought up tomasterthis pull request also lists those commits.io.xdag:xdagj-p2p:0.1.8: Open network: remove the node whitelist, harden consensus behind a fork; 0.9.0 xdagj#363 cannot build in CI until 0.1.8 is published.🤖 Generated with Claude Code