Repository navigation
Conversation
merge to master
Firefly v0.8.0
Bumps [com.fasterxml.jackson.core:jackson-databind](https://github.com/FasterXML/jackson) from 2.18.6 to 2.18.9. - [Commits](https://github.com/FasterXML/jackson/commits) --- updated-dependencies: - dependency-name: com.fasterxml.jackson.core:jackson-databind dependency-version: 2.18.9 dependency-type: direct:production ... Signed-off-by: dependabot[bot] <support@github.com>
Bumps [com.fasterxml.jackson.core:jackson-core](https://github.com/FasterXML/jackson-core) from 2.18.6 to 2.18.8. - [Commits](FasterXML/jackson-core@jackson-core-2.18.6...jackson-core-2.18.8) --- updated-dependencies: - dependency-name: com.fasterxml.jackson.core:jackson-core dependency-version: 2.18.8 dependency-type: direct:production ... Signed-off-by: dependabot[bot] <support@github.com>
Bumps org.apache.logging.log4j:log4j-api from 2.25.4 to 2.25.5. --- updated-dependencies: - dependency-name: org.apache.logging.log4j:log4j-api dependency-version: 2.25.5 dependency-type: direct:production ... Signed-off-by: dependabot[bot] <support@github.com>
…he.logging.log4j-log4j-api-2.25.5 Bump org.apache.logging.log4j:log4j-api from 2.25.4 to 2.25.5
…erxml.jackson.core-jackson-core-2.18.8 Bump com.fasterxml.jackson.core:jackson-core from 2.18.6 to 2.18.8
…e-jackson-databind-2.18.9
…erxml.jackson.core-jackson-databind-2.18.9 Bump com.fasterxml.jackson.core:jackson-databind from 2.18.6 to 2.18.9
…rk; version 0.9.0 Anybody can run a node. The whitelist (node.whiteIPs) is gone; what replaces it, and why it could not simply be removed, is in docs/OPEN_NETWORK.md and docs/SECURITY_AUDIT_OPEN_NETWORK.md. Network - The 0.8.x transport (io.xdag.net frames, handshake, whitelist) is replaced by xdagj-p2p 0.1.7: signed handshake, signed Kademlia discovery with endpoint proof, admission control, backpressure. The wire protocol is not compatible with 0.8.x (networkVersion 1, XDAG messages at codes 0x20-0x2A): upgrading a network is a flag day. - node.seeds (entry points, no privilege) and node.trustedPeers (kept connected, never banned) replace node.whiteIPs, which is still read and mapped to both with a warning. The node has its own identity key (node.keyFile) instead of using the wallet key. - The node runs closed (configured peers only - what the whitelist did) until the open-network hardening fork is in force on its chain, then opens up by itself (ChannelManager.applyOpenness). - XdagP2pHandler: request spans bounded to what the protocol produces, per-peer rate limits, misbehaviour scores and bans, impossible network statistics ignored, relay TTL capped, one peer asked for a missing parent, outbound requests throttled, silent peers scored. - BlockStoreImpl.loadSum refuses non-positive spans (a span of 2^63 looped forever). Consensus (gated behind consensus.opennet.forkEpoch; devnet from genesis, testnet/mainnet not scheduled - MainnetConfig.OPEN_NET_FORK_EPOCH is set in code by the maintainers, the config file is ignored on mainnet) - Only end-of-epoch candidates carry difficulty (C1); duplicate inputs of one block are added up (C2); peer-supplied execution status is ignored (C3); overflow-safe execution, nothing throws out of setMain (C4); no "input address must exist" import rule (C6); exact address total (C7); crash mark for interrupted main-chain updates (C8, detection only); RandomX fork time no longer set to -1 on unwind (C9). - Also fixed, found in this work: block without an output signature (NPE after state mutation), amount-bearing coinbase field in a non-transaction block (IndexOutOfBounds in setMain), zero-output account transaction (division by zero), unApplyBlock on snapshot blocks (NPE), a skipped transaction un-skipped by an unrelated unwind, removeOrphan overwriting the recorded fee, and confirmation depending on BI_REF, which rollTx clears - so the order of arrival decided when a main block was confirmed. - The 0.8.x rules are kept bug for bug for the history before the fork. Once a fork-era main block is confirmed the node latches (persisted) and checks every block with the hardened rules. - Transaction history (optional MySQL store) is written when a transaction executes and removed when that is undone (S2). Other bug fixes from the Rust port's review (docs/BUGS.md there) - xfer / doXfer spend from exactly one account with its own nonce (O1); rewards of blocks found without a pool go to the node (O2); pending pool awards survive restarts (O7); node payments de-duplicated (the same block could be spent twice in one transaction); amounts parsed exactly instead of rounded to 0.01 XDAG (A2); history paging without a global static (P3); snapshot-inherited blocks report their record over RPC (O9). - Remaining Chinese comments translated to English. Tests: 244 pass, including OpenNetForkTest (legacy vs hardened rules), DeterminismTest (random histories delivered in four orders must give the same state; 600 seeds pass under the hardened rules) and TwoNodeNetworkTest (two nodes on the loopback interface: seed, gossip, request, ban, closed mode). Deferred, documented: C5 (fee on failed transactions; mitigated by a local pool admission policy), C8 atomicity, the Kryo storage format (S1), the swapped BLOCK/TIME directory names (O6). Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
…t by its tip, claims or sums A node that was behind could be made to call itself synchronised, and to stop fetching history for good, by any peer and without any work (docs/SECURITY_AUDIT_OPEN_NETWORK.md, X12 and X13): - Three blocks without work but with current timestamps are the heaviest thing a stale node knows and become its latest main blocks. That moved the frontier of XdagSync (the time of the latest main block) to the present and satisfied the "latest main block is recent" rule; SYNC_DONE then stopped the comparison with the peers. - The sums of that comparison are plain sums of block words. Blocks nobody needs, dated into the spans a node is missing and with one field chosen for the purpose, bring its sums to those of an honest peer, and nothing is fetched there any more - found while fixing the first point, and it defeated a first fix that decided by "the comparison found nothing to fetch". What cannot be had for free: a block only becomes part of a node's blocks when everything it refers to is there. XdagSync - Rounds with one peer at a time, in cycles in which every connected peer gets exactly one round (a peer under a new name waits for the next cycle). Rounds never stop, also not after the node called itself synchronised. - Compare: the whole sums tree, wherever the tip is, down to the snapshot the node was booted from; spans in which the peer has more are fetched, oldest first. A span fetched from a peer is settled for that peer while the peer's sums stay the same; spans in which this node holds at least as much are looked into a few per round; a synchronised node fetches at most 16 spans per round. - Verify (not synchronised): the two request spans that are being written to are fetched whatever the sums say. The node is in sync with the peer only if those blocks attach to its own (PeerEvidence). - Recover: if they do not attach although the sums show nothing to fetch, the node looks at spans of the peer without importing them until it has found where its own blocks end, and fetches everything from there on regardless of the sums. - The time limit of a round is checked before every request; a peer that did not answer, or whose sums promised blocks for a whole round of which none was new, gets a short round and short waits. SyncManager - Open network: synchronised when a cycle of rounds (with at least half of the current peers) was held since the node last caught up, most of the peers that showed blocks from the present (or did not answer) had none the node could not attach, and the best chain has not advanced through old blocks for 30 s. Revoked when older blocks with more work arrive; XdagPow pauses and resumes with the state. - waitEpoch only starts a node that has no peers. - Closed network: the 0.8.x rule, unchanged. XdagP2pHandler - SYNC_BLOCKs are only taken in answer to a request of this node (for the span or for the block), and so is news dated more than about nine hours ago: nobody writes into a node's past unasked. ChannelManager no longer tells a P2P service that is not running yet to open (a NullPointerException warning from its connect loop at start). Tests: 263 pass. SyncUnderAttackTest (three nodes on 127.0.0.1: blocks without work, eclipse and revocation, sums made equal, blocks nobody needs at an honest peer, the node's own loops), SyncDoneDecisionTest, XdagSyncCycleTest, XdagP2pHandlerTest (history and old news only when asked for). Network tests no longer depend on the first dial winning the race against the listener's bind (NetNode.awaitConnectedTo). Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
xdagj-p2p (branch security/open-network-hardening, d97265d) returns from start() when the TCP listener and the discovery socket are bound, and setPermissionless() before start() only changes the setting. Recorded as P16 in docs/SECURITY_AUDIT_OPEN_NETWORK.md (xdagj-p2p: 923 tests); two comments that described the old behaviour are corrected. No change in behaviour here: 263 tests pass against that build. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
0.1.8 is 0.1.7 plus the two start-up fixes (start() returns with the sockets bound; setPermissionless() before start() only changes the setting) and is the same on the wire. The design and audit documents name the version accordingly (P16 is fixed in 0.1.8). Tests: 263 pass against xdagj-p2p 0.1.8. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
The design and audit documents pointed at a local path and at documents of the Rust port that are not published. Reworded; nothing else changes. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
This branch has not been deployed
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
Anybody can run a node: the node whitelist (
node.whiteIPs) is removed. What replaces it, and why it could not simply be deleted, is indocs/OPEN_NETWORK.md; what was found and fixed on the way is indocs/SECURITY_AUDIT_OPEN_NETWORK.md. Version 0.9.0.Depends on xdagj-p2p 0.1.8: XDagger/xdagj-p2p#31. Until that version is published to Maven Central, CI on this pull request cannot resolve the dependency and will fail.
What changes
Network
io.xdag.netframes, handshake, whitelist) is replaced by xdagj-p2p 0.1.8: signed handshake, signed discovery with endpoint proof, admission control, backpressure.node.seeds(entry points, no privilege) andnode.trustedPeers(kept connected) replacenode.whiteIPs, which is still read and mapped to both with a warning. The node has its own identity key (node.keyFile) instead of using the wallet key.XdagP2pHandler: request spans bounded, per-peer rate limits, misbehaviour scores and bans, history only accepted in answer to a request.Consensus - behind a fork, not active on mainnet
consensus.opennet.forkEpochon: devnet from genesis, testnet and mainnet not scheduled. On testnet the epoch comes from the configuration file; on mainnet it is a constant inMainnetConfigthat the maintainers set, and the configuration file is ignored.Synchronisation
Other fixes (from a review done while porting the node to Rust): single-account spend with its own nonce in
xfer, rewards of blocks found without a pool, pending pool awards surviving restarts, exact amount parsing, history paging without a global static, snapshot block records over RPC. Remaining Chinese comments translated to English.Compatibility and rollout
node.seeds/node.trustedPeersin place of the whitelist.Decisions this needs from the maintainers
OPEN_NET_FORK_EPOCH).docs/OPEN_NETWORK.md(section 2.3): fee on failed transactions, atomic main-chain updates, the Kryo storage format.Testing
mvn test: 263 tests, 0 failures.OpenNetForkTest: legacy against hardened behaviour, the latch, execution rules following the main block's epoch.DeterminismTest: random histories delivered in different orders must give the same state (600 seeds under the hardened rules).TwoNodeNetworkTest,SyncUnderAttackTest: real nodes on the loopback interface - seed, gossip, request, ban, closed mode; a node that is behind and a peer that tries to make it believe it is synchronised.XdagP2pHandlerTest,SyncDoneDecisionTest,XdagSyncCycleTest,ChannelManagerTest,NodeKeyStoreTest,PeerSettingsTest.mvn license:checkpasses.No test connects to a real network.
Notes for reviewers
master.developis currently 13 commits behindmaster(dependency updates), so untildevelopis brought up tomasterthis pull request also lists those commits.docs/OPEN_NETWORK.md, thenBlockchainImpl(search forhardened),XdagSync/SyncManager,XdagP2pHandler,net/ChannelManager.🤖 Generated with Claude Code