@@ -656,20 +656,29 @@ void allThreeFeeLevelsAreScaled() {
656656
657657 @ Test
658658 void escrowFinishWithoutFulfillmentCostsOneBaseFee () {
659- assertFeeUnits (paramsFor (escrowFinish (false )), 1 );
659+ assertFeeUnits (paramsFor (escrowFinish (0 )), 1 );
660660 }
661661
662662 @ Test
663663 void escrowFinishWithFulfillmentAddsTheSizeSurcharge () {
664- // 1 + (32 + 32/16) = 35
665- assertFeeUnits (paramsFor (escrowFinish (true )), 35 );
664+ // rippled charges by the on-wire fulfillment blob, not the preimage. A 32-byte preimage DER-encodes to a
665+ // 36-byte blob, so the surcharge is 32 + 36/16 = 34: total 1 + 34 = 35.
666+ assertFeeUnits (paramsFor (escrowFinish (32 )), 35 );
667+ }
668+
669+ @ Test
670+ void escrowFinishSurchargeUsesTheEncodedBlobSizeNotThePreimageSize () {
671+ // Boundary case exposing the difference: a 28-byte preimage DER-encodes to a 32-byte blob. Measuring the blob
672+ // (correct, matches rippled) gives 32 + 32/16 = 34 -> total 35. Measuring the preimage (the old, buggy
673+ // behavior) would give 32 + 28/16 = 33 -> total 34, underpaying by one base fee.
674+ assertFeeUnits (paramsFor (escrowFinish (28 )), 35 );
666675 }
667676
668677 @ Test
669678 void escrowFinishSurchargeIsAddedToTheSignatureTerms () {
670679 // (1 + 2) + (32 + 32/16) = 37 — the signer terms EscrowFinish.computeFee omits.
671680 assertFeeUnits (
672- FeeParams .builder ().feeResult (feeResultBuilder ().build ()).transaction (escrowFinish (true ))
681+ FeeParams .builder ().feeResult (feeResultBuilder ().build ()).transaction (escrowFinish (32 ))
673682 .signersCount (UnsignedInteger .valueOf (2 )),
674683 37
675684 );
@@ -1052,16 +1061,20 @@ private AccountDelete accountDelete() {
10521061 .build ();
10531062 }
10541063
1055- private EscrowFinish escrowFinish (final boolean withFulfillment ) {
1064+ /**
1065+ * An {@link EscrowFinish} carrying a PREIMAGE-SHA-256 fulfillment built from a {@code preimageBytes}-byte preimage,
1066+ * or no fulfillment when {@code preimageBytes} is 0.
1067+ */
1068+ private EscrowFinish escrowFinish (final int preimageBytes ) {
10561069 ImmutableEscrowFinish .Builder builder = EscrowFinish .builder ()
10571070 .account (ALICE )
10581071 .owner (BOB )
10591072 .offerSequence (UnsignedInteger .ONE )
10601073 .fee (XrpCurrencyAmount .ofDrops (0 ))
10611074 .sequence (UnsignedInteger .ONE )
10621075 .signingPublicKey (PUBLIC_KEY );
1063- return withFulfillment ?
1064- builder .fulfillment (PreimageSha256Fulfillment .from (new byte [32 ])). build () : builder .build ();
1076+ return preimageBytes == 0 ?
1077+ builder .build () : builder . fulfillment (PreimageSha256Fulfillment .from (new byte [preimageBytes ])).build ();
10651078 }
10661079
10671080 private Batch batch (final Address outerAccount , final Transaction ... inners ) {
0 commit comments