|
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