fix(consensus): authenticate cluster proposals

This commit is contained in:
Nicholas Dudfield
2026-07-16 18:59:05 +07:00
parent f40041d018
commit b0e7affa73
3 changed files with 23 additions and 6 deletions

View File

@@ -63,6 +63,16 @@ public:
{
using enum detail::ProposalPrecheckResult;
//@@start test-peer-proposal-authentication
testcase("cluster transport does not bypass proposal authentication");
{
BEAST_EXPECT(detail::proposalSignatureAccepted(false, true));
BEAST_EXPECT(detail::proposalSignatureAccepted(true, true));
BEAST_EXPECT(!detail::proposalSignatureAccepted(false, false));
BEAST_EXPECT(!detail::proposalSignatureAccepted(true, false));
}
//@@end test-peer-proposal-authentication
//@@start test-proposal-precheck-legacy-ok
testcase("legacy and extended ok");
{

View File

@@ -37,6 +37,13 @@ struct ProposalPrecheckRejection
char const* feeReason;
};
inline bool
proposalSignatureAccepted(bool /* clusterPeer */, bool signatureValid)
{
// Cluster trust affects relay and charging, never validator attribution.
return signatureValid;
}
inline bool
proposalHasMalformedHashes(protocol::TMProposeSet const& set)
{

View File

@@ -3120,19 +3120,19 @@ PeerImp::checkPropose(
XRPL_ASSERT(packet, "ripple::PeerImp::checkPropose : non-null packet");
// Always verify the proposal signature before harvesting export
// sigs, even in cluster mode. Cluster peers are trusted for relay
// and resource charging, but export sigs produce on-chain artifacts
// (multisigned blobs in metadata) so they require cryptographic
// proof of validator identity regardless.
// Always authenticate validator positions, including those relayed by a
// cluster peer. Sidecar alignment counts these positions as validator
// statements, so cluster transport trust cannot replace the signature.
//@@start peer-proposal-authentication
bool const sigValid = peerPos.checkSign();
if (!cluster() && !sigValid)
if (!detail::proposalSignatureAccepted(cluster(), sigValid))
{
std::string desc{"Proposal fails sig check"};
JLOG(p_journal_.warn()) << desc;
charge(Resource::feeInvalidSignature, desc);
return;
}
//@@end peer-proposal-authentication
//@@start peer-harvest-export-sigs
// Harvest export sigs AFTER checkSign() so only cryptographically