|
32 | 32 | import com.ripple.cryptoconditions.CryptoConditionReader;
|
33 | 33 | import com.ripple.cryptoconditions.CryptoConditionWriter;
|
34 | 34 | import com.ripple.cryptoconditions.Fulfillment;
|
| 35 | +import com.ripple.cryptoconditions.PreimageSha256Fulfillment; |
| 36 | +import com.ripple.cryptoconditions.PreimageSha256Fulfillment.AbstractPreimageSha256Fulfillment; |
35 | 37 | import com.ripple.cryptoconditions.der.DerEncodingException;
|
36 | 38 | import org.immutables.value.Value;
|
37 | 39 | import org.slf4j.Logger;
|
|
41 | 43 | import org.xrpl.xrpl4j.model.transactions.AccountSet.AccountSetFlag;
|
42 | 44 |
|
43 | 45 | import java.util.Arrays;
|
| 46 | +import java.util.Base64; |
44 | 47 | import java.util.Locale;
|
45 | 48 | import java.util.Objects;
|
46 | 49 | import java.util.Optional;
|
@@ -69,25 +72,39 @@ static ImmutableEscrowFinish.Builder builder() {
|
69 | 72 | * transaction increases if it contains a fulfillment. If the transaction contains a fulfillment, the transaction cost
|
70 | 73 | * is 330 drops of XRP plus another 10 drops for every 16 bytes in size of the preimage.
|
71 | 74 | *
|
72 |
| - * @param currentLedgerFeeDrops The number of drops that the ledger demands at present. |
73 |
| - * @param fulfillment The {@link Fulfillment} that is being presented to the ledger for computation |
74 |
| - * purposes. |
| 75 | + * @param currentLedgerBaseFeeDrops The number of drops that the ledger demands at present. |
| 76 | + * @param fulfillment The {@link Fulfillment} that is being presented to the ledger for computation |
| 77 | + * purposes. |
75 | 78 | *
|
76 | 79 | * @return An {@link XrpCurrencyAmount} representing the computed fee.
|
77 | 80 | *
|
78 | 81 | * @see "https://xrpl.org/escrowfinish.html"
|
79 | 82 | */
|
80 |
| - static XrpCurrencyAmount computeFee(final XrpCurrencyAmount currentLedgerFeeDrops, final Fulfillment fulfillment) { |
81 |
| - Objects.requireNonNull(currentLedgerFeeDrops); |
| 83 | + static XrpCurrencyAmount computeFee( |
| 84 | + final XrpCurrencyAmount currentLedgerBaseFeeDrops, |
| 85 | + final Fulfillment<?> fulfillment |
| 86 | + ) { |
| 87 | + Objects.requireNonNull(currentLedgerBaseFeeDrops); |
82 | 88 | Objects.requireNonNull(fulfillment);
|
83 | 89 |
|
84 |
| - UnsignedLong newFee = |
85 |
| - currentLedgerFeeDrops.value() // <-- usually 10 drops, per the docs. |
86 |
| - // <-- https://github.com/ripple/rippled/blob/develop/src/ripple/app/tx/impl/Escrow.cpp#L362 |
87 |
| - .plus(UnsignedLong.valueOf(320)) |
88 |
| - // <-- 10 drops for each additional 16 bytes. |
89 |
| - .plus(UnsignedLong.valueOf(10 * (fulfillment.getDerivedCondition().getCost() / 16))); |
90 |
| - return XrpCurrencyAmount.of(newFee); |
| 90 | + if (PreimageSha256Fulfillment.class.isAssignableFrom(fulfillment.getClass())) { |
| 91 | + |
| 92 | + final long fulfillmentByteSize = Base64.getUrlDecoder().decode( |
| 93 | + ((PreimageSha256Fulfillment) fulfillment).getEncodedPreimage() |
| 94 | + ).length; |
| 95 | + // See https://xrpl.org/docs/references/protocol/transactions/types/escrowfinish#escrowfinish-fields for |
| 96 | + // computing the additional fee for Escrows. |
| 97 | + // In particular: `extraFee = view.fees().base * (32 + (fb->size() / 16))` |
| 98 | + // See https://github.com/XRPLF/rippled/blob/master/src/xrpld/app/tx/detail/Escrow.cpp#L368 |
| 99 | + final long baseFee = currentLedgerBaseFeeDrops.value().longValue(); |
| 100 | + final long extraFeeDrops = baseFee * (32 + (fulfillmentByteSize / 16)); |
| 101 | + final long totalFeeDrops = baseFee + extraFeeDrops; // <-- Add an extra base fee |
| 102 | + return XrpCurrencyAmount.of( |
| 103 | + UnsignedLong.valueOf(totalFeeDrops) |
| 104 | + ); |
| 105 | + } else { |
| 106 | + throw new RuntimeException("Only PreimageSha256Fulfillment is supported."); |
| 107 | + } |
91 | 108 | }
|
92 | 109 |
|
93 | 110 | /**
|
@@ -144,11 +161,11 @@ default TransactionFlags flags() {
|
144 | 161 | *
|
145 | 162 | * <p>Note that a similar field does not exist on {@link EscrowCreate},
|
146 | 163 | * {@link org.xrpl.xrpl4j.model.ledger.EscrowObject}, or
|
147 |
| - * {@link org.xrpl.xrpl4j.model.transactions.metadata.MetaEscrowObject} because {@link EscrowCreate}s with |
148 |
| - * malformed conditions will never be included in a ledger by the XRPL. Because of this fact, an |
| 164 | + * {@link org.xrpl.xrpl4j.model.transactions.metadata.MetaEscrowObject} because {@link EscrowCreate}s with malformed |
| 165 | + * conditions will never be included in a ledger by the XRPL. Because of this fact, an |
149 | 166 | * {@link org.xrpl.xrpl4j.model.ledger.EscrowObject} and
|
150 |
| - * {@link org.xrpl.xrpl4j.model.transactions.metadata.MetaEscrowObject} will also never contain a malformed |
151 |
| - * crypto condition.</p> |
| 167 | + * {@link org.xrpl.xrpl4j.model.transactions.metadata.MetaEscrowObject} will also never contain a malformed crypto |
| 168 | + * condition.</p> |
152 | 169 | *
|
153 | 170 | * @return An {@link Optional} {@link String} containing the hex-encoded PREIMAGE-SHA-256 condition.
|
154 | 171 | */
|
@@ -191,8 +208,8 @@ default TransactionFlags flags() {
|
191 | 208 | * <p>If {@link #condition()} is present but {@link #conditionRawValue()} is empty, we set
|
192 | 209 | * {@link #conditionRawValue()} to the underlying value of {@link #condition()}.</p>
|
193 | 210 | * <p>If {@link #condition()} is empty and {@link #conditionRawValue()} is present, we will set
|
194 |
| - * {@link #condition()} to the {@link Condition} representing the raw condition value, or leave |
195 |
| - * {@link #condition()} empty if {@link #conditionRawValue()} is a malformed {@link Condition}.</p> |
| 211 | + * {@link #condition()} to the {@link Condition} representing the raw condition value, or leave {@link #condition()} |
| 212 | + * empty if {@link #conditionRawValue()} is a malformed {@link Condition}.</p> |
196 | 213 | *
|
197 | 214 | * @return A normalized {@link EscrowFinish}.
|
198 | 215 | */
|
|
0 commit comments