fix(sync): trust only initial validators + disable peer_private#10
Merged
LeJamon merged 3 commits intoJun 4, 2026
Merged
Conversation
Two follow-on fixes after XRPL-Commons#9 to make the cross-impl late-join sync actually run end-to-end: 1. Trusted UNL = initial validators only. The topology was being built with `numInitial + 1` keys so the late joiner had a slot, but `WithValidatorConfig` uploads the full key set as the trusted UNL on every node. rippled then applies its BFT rule (quorum = ceil(0.8 * trusted_count)), which on a 3-key list demands quorum=3 — and the 2-node initial network never validates. rxrpl honored the configured quorum directly so the rxrpl-only test masked this. Drop the late joiner from the trusted set; it's a pure observer that catches up via received validations and doesn't need to be trusted itself. 2. peer_private=0 for sync tests. `topology.go:EnvForNode` hardcodes XRPL_PEER_PRIVATE=1. With that, rippled servers respond to non-fixed inbound connections with a 503 redirect ("processResponse: failed to connect to peer: redirected"). The late joiner's IP is not in the initial nodes' [ips_fixed] at boot, so it can never establish a peer link. Override to 0 in the sync suite — rxrpl ignores the flag entirely (which is why the rxrpl-only path was unaffected). Result on `--client rxrpl,rippled` (4 sub-tests): initial=rxrpl late=rxrpl PASS initial=rxrpl late=rippled fail (rippled catch-up from rxrpl) initial=rippled late=rxrpl PASS <-- the cross-impl signal initial=rippled late=rippled fail (test-side: payment not yet in the first 10 ledgers under rippled's pacing) The two remaining failures are independent issues: the second is a rippled bug surface for catch-up from a non-rippled UNL, the fourth is a test-pacing artifact. Both can be tackled in follow-ups without further changes to this scaffolding.
After the previous fix the rippled→rippled sub-test still failed with "account not found": WaitForLedger(10) returned as soon as the late joiner saw a validated ledger ≥10, but the payment is in ledger ~11+ under rippled's idle pacing. Late joiner could be at exactly ledger 10 when AccountInfo runs. Use the same target ledger (15) for both the initial-network post-payment wait and the late-joiner sync wait. Bump the late-joiner timeout to 240s to leave headroom for catch-up under rippled's slower close cadence.
5 tasks
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
Two follow-on fixes after #9 to make the cross-impl late-join sync actually run end-to-end.
1. Trusted UNL = initial validators only
The topology was being built with
numInitial + 1keys so the late joiner had a slot, butWithValidatorConfiguploads the full key set as the trusted UNL on every node. rippled then applies its BFT rule (quorum = ceil(0.8 * trusted_count)), which on a 3-key list demands quorum=3 — and the 2-node initial network never validates.rxrpl honored the configured
XRPL_VALIDATION_QUORUMdirectly, so the rxrpl-only test passed and masked this. Drop the late joiner from the trusted set; it's a pure observer that catches up via received validations and doesn't need to be trusted itself.2. peer_private=0 for sync tests
xrplsim/topology.go:EnvForNodehardcodesXRPL_PEER_PRIVATE=1. With that, rippled servers respond to non-fixed inbound connections with a 503 redirect (processResponse: failed to connect to peer: redirected). The late joiner's IP is not in the initial nodes'[ips_fixed]at boot, so it can never establish a peer link.Override to 0 in the sync suite — rxrpl ignores the flag entirely (which is why the rxrpl-only path was unaffected by either issue).
Result on `--client rxrpl,rippled` (4 sub-tests):
STATE->disconnecteddespite peer link up)Why the partial fail is still progress
Before this PR the suite reported 0/1 passing in mixed mode and never actually exercised cross-impl sync. After this PR the canonical mainnet-shaped scenario "a fresh rxrpl observes a rippled-validated network and catches up" passes empirically, account state included.
Test plan