Skip to content

Commit b408eeb

Browse files
author
DigiByte Dev
committed
Update DIGIBYTE_FEE_ANALYSIS_V8.26.md
1 parent 0b42e64 commit b408eeb

1 file changed

Lines changed: 244 additions & 21 deletions

File tree

DIGIBYTE_FEE_ANALYSIS_V8.26.md

Lines changed: 244 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -45,13 +45,30 @@ CAmount CFeeRate::GetFee(uint32_t num_bytes) const
4545
- No absolute minimum enforced
4646
4747
2. **Mempool Acceptance** (`validation.cpp`)
48+
- Line 670-684: `CheckFeeRate()` validates against dynamic mempool minimum
4849
- Line 874-876: Checks against `m_pool.m_min_relay_feerate` (0.001 DGB/kvB)
49-
- Line 674-681: `CheckFeeRate()` validates against dynamic mempool minimum
5050
- No absolute minimum enforced
5151
5252
3. **Network Relay** (`net_processing.cpp`)
5353
- Uses `DEFAULT_MIN_RELAY_TX_FEE` for relay decisions
54-
- Fee filter uses same per-kilobyte rates
54+
- Fee filter messages (`feefilter`) use same per-kilobyte rates
55+
- `PeerManager` enforces fee expectations
56+
57+
4. **RPC Raw Transactions** (bypasses wallet logic)
58+
- `sendrawtransaction`: Direct mempool submission
59+
- `testmempoolaccept`: Fee validation testing
60+
- `submitpackage`: Package fee validation
61+
- These endpoints need explicit fee validation
62+
63+
5. **Dynamic Mempool Fee** (`txmempool.cpp`)
64+
- Line 1116: `CTxMemPool::GetMinFee()` implements rolling fee adjustments
65+
- Adjusts based on mempool size and eviction
66+
- No absolute minimum enforced
67+
68+
6. **Dandelion++ Stempool** (`dandelion.cpp`)
69+
- Transactions in stem phase before broadcast
70+
- Currently no fee validation in stempool
71+
- Potential spam vector during privacy phase
5572
5673
## Bitcoin vs DigiByte Fee Scaling Analysis
5774
@@ -136,27 +153,62 @@ CAmount final_fee = std::max(
136153
- Update `GetRequiredFee()` similarly
137154

138155
4. **src/validation.cpp**
139-
- Update `CheckFeeRate()` to enforce absolute minimum
156+
- Update `CheckFeeRate()` (line 670) to enforce absolute minimum
140157
- Modify mempool acceptance logic (lines 874-876)
158+
- Add absolute minimum check in `PreChecks()`
141159

142160
5. **src/wallet/spend.cpp**
143-
- Update fee calculation in `CreateTransactionInternal()`
161+
- Update fee calculation in `CreateTransactionInternal()` (line 967)
162+
- Add absolute minimum check after line 1096
163+
- Update coin selection parameters around line 1050
144164
- Ensure coin selection respects new minimums
145165

146166
6. **src/txmempool.cpp**
147-
- Update `GetMinFee()` to respect absolute minimum
167+
- Update `GetMinFee()` (line 1116) to respect absolute minimum
168+
- Modify rolling fee calculation to include absolute floor
169+
- ```cpp
170+
return std::max({CFeeRate(llround(rollingMinimumFeeRate)),
171+
m_incremental_relay_feerate,
172+
CFeeRate(ABSOLUTE_MIN_TX_FEE/1000)});
173+
```
174+
175+
7. **src/dandelion.cpp**
176+
- Add fee validation for stempool transactions
177+
- Update embargo logic to check minimum fees
178+
- Prevent low-fee transactions in stem phase
179+
180+
8. **src/node/transaction.cpp**
181+
- Update `BroadcastTransaction()` fee validation
182+
- Add absolute minimum check before broadcast
148183

149184
### Configuration and RPC Files
150185

151-
7. **src/init.cpp**
186+
9. **src/init.cpp**
152187
- Update help text for `-mintxfee` and `-minrelaytxfee`
153-
- Add new `-absolutemintxfee` option if desired
188+
- Add new `-absolutemintxfee` option
189+
- Parse command-line arguments for new fee options
190+
191+
10. **src/kernel/mempool_options.h**
192+
- Line 46: Update default mempool fee initialization
193+
- Add absolute minimum fee member
194+
195+
11. **src/rpc/mempool.cpp**
196+
- Update fee-related RPC responses
197+
- Add absolute minimum to `getmempoolinfo`
154198

155-
8. **src/rpc/mempool.cpp**
156-
- Update fee-related RPC responses
199+
12. **src/rpc/rawtransaction.cpp**
200+
- Add fee validation to `sendrawtransaction`
201+
- Update `testmempoolaccept` with absolute minimum check
202+
- Validate fees in `submitpackage`
157203

158-
9. **src/wallet/rpc/spend.cpp**
159-
- Update `sendtoaddress`, `sendmany`, etc. to respect new minimums
204+
13. **src/wallet/rpc/spend.cpp**
205+
- Update `sendtoaddress`, `sendmany`, etc. to respect new minimums
206+
- Add clear error messages for insufficient fees
207+
208+
14. **src/net_processing.cpp**
209+
- Update fee filter message handling
210+
- Modify `PeerManager` fee expectations
211+
- Add version-based fee enforcement logic
160212

161213
## Test Files Requiring Updates
162214

@@ -210,25 +262,51 @@ CAmount final_fee = std::max(
210262
15. **test/functional/wallet_groups.py**
211263
- Coin selection with fees
212264

265+
### Additional Tests Needed
266+
267+
16. **test/functional/feature_absolute_min_fee.py** (NEW)
268+
- Test absolute minimum fee enforcement
269+
- Verify rejection of low-fee transactions
270+
- Test hybrid approach behavior
271+
272+
17. **test/functional/dandelion_fee_validation.py** (NEW)
273+
- Test stempool fee validation
274+
- Verify Dandelion++ with minimum fees
275+
- Test embargo with fee checks
276+
277+
18. **test/functional/rpc_raw_fee_validation.py** (NEW)
278+
- Test sendrawtransaction fee validation
279+
- Test testmempoolaccept with low fees
280+
- Test submitpackage fee requirements
281+
213282
## Implementation Recommendations
214283

215284
### 1. Immediate Actions
216285

217286
1. **Implement Option 3 (Hybrid Approach)**
218287
- Provides both per-kilobyte and absolute minimum protection
219288
- Most flexible for different transaction sizes
289+
- Protects against spam while being fair to larger transactions
220290
- Easiest to roll back if issues arise
221291

222-
2. **Add Configuration Option**
292+
2. **Add Configuration Options**
223293
```cpp
224294
// Add to init.cpp
225295
"-absolutemintxfee=<amt> Absolute minimum fee per transaction (default: 0.1 DGB)"
296+
"-enforceabsolutefee=<bool> Enforce absolute minimum fee (default: true)"
226297
```
227298

228-
3. **Gradual Rollout**
229-
- Start with wallet enforcement only
230-
- Monitor network acceptance
231-
- Then enforce in mempool/relay
299+
3. **Phased Rollout Strategy**
300+
- **Phase 1**: Wallet enforcement only (immediate)
301+
- Update wallet fee calculation
302+
- Add user warnings for low fees
303+
- **Phase 2**: Mempool enforcement (after 2 weeks testing)
304+
- Enforce in validation.cpp
305+
- Update mempool acceptance rules
306+
- **Phase 3**: Network relay enforcement (after network readiness)
307+
- Update peer communication
308+
- Coordinate with major nodes/pools
309+
- Consider protocol version bump
232310

233311
### 2. Testing Strategy
234312

@@ -279,6 +357,20 @@ Add logging to track:
279357
**Problem**: Complex transactions may be disproportionately affected
280358
**Mitigation**: Monitor and adjust rates based on actual usage
281359

360+
### Issue 5: Dandelion++ Compatibility
361+
**Problem**: Stempool transactions may be rejected after broadcast
362+
**Mitigation**:
363+
- Validate fees before entering stempool
364+
- Update embargo logic to include fee checks
365+
- Ensure stem and fluff phases have consistent validation
366+
367+
### Issue 6: Raw Transaction APIs
368+
**Problem**: Direct RPC submission bypasses wallet fee logic
369+
**Mitigation**:
370+
- Add explicit fee validation in RPC handlers
371+
- Provide clear error messages for API users
372+
- Document minimum fee requirements in RPC help
373+
282374
## Conclusion
283375

284376
The current DigiByte v8.26 fee structure allows transactions to pay less than the required 0.1 DGB minimum, creating spam vulnerability. The recommended solution is a hybrid approach that enforces both:
@@ -288,6 +380,116 @@ The current DigiByte v8.26 fee structure allows transactions to pay less than th
288380

289381
This approach provides spam protection while maintaining fairness for legitimate large transactions. Implementation should be gradual with extensive testing and clear communication to the ecosystem.
290382

383+
## Additional Implementation Details
384+
385+
### Detailed Code Changes
386+
387+
#### 1. Wallet Fee Enforcement (`wallet/spend.cpp`)
388+
```cpp
389+
// After line 1096 in CreateTransactionInternal()
390+
CAmount absolute_min = ABSOLUTE_MIN_TX_FEE;
391+
if (not_input_fees < absolute_min && !coin_control.fOverrideFeeRate) {
392+
return util::Error{strprintf(_("Transaction fee %s is below minimum required %s"),
393+
FormatMoney(not_input_fees), FormatMoney(absolute_min))};
394+
}
395+
```
396+
397+
#### 2. Mempool Dynamic Fee (`txmempool.cpp`)
398+
```cpp
399+
// Update GetMinFee() at line 1137
400+
CFeeRate CTxMemPool::GetMinFee(size_t sizelimit) const {
401+
// ... existing rolling fee calculation ...
402+
CFeeRate min_fee = std::max(CFeeRate(llround(rollingMinimumFeeRate)),
403+
m_incremental_relay_feerate);
404+
// Enforce absolute minimum
405+
CFeeRate absolute_min_rate(ABSOLUTE_MIN_TX_FEE / 1000);
406+
return std::max(min_fee, absolute_min_rate);
407+
}
408+
```
409+
410+
#### 3. Validation Check (`validation.cpp`)
411+
```cpp
412+
// Update CheckFeeRate() at line 670
413+
bool CheckFeeRate(size_t package_size, CAmount package_fee, TxValidationState& state) {
414+
// Check absolute minimum first
415+
if (package_fee < ABSOLUTE_MIN_TX_FEE) {
416+
return state.Invalid(TxValidationResult::TX_MEMPOOL_POLICY,
417+
"absolute min fee not met",
418+
strprintf("%d < %d", package_fee, ABSOLUTE_MIN_TX_FEE));
419+
}
420+
// ... existing per-kb checks ...
421+
}
422+
```
423+
424+
### Stempool Integration (Dandelion++)
425+
426+
**Critical**: Transactions in the stempool must respect minimum fees to prevent spam during the privacy phase.
427+
428+
#### Files to Update:
429+
- `src/dandelion.cpp`: Add fee validation before embargo
430+
- `src/node/transaction.cpp`: Check fees in `BroadcastTransaction()`
431+
- `src/txmempool.cpp`: Validate stempool transaction fees
432+
433+
#### Example Implementation:
434+
```cpp
435+
// In dandelion.cpp
436+
bool ValidateStemPoolFee(const CTransaction& tx, CAmount& fee_out) {
437+
// Calculate transaction fee
438+
CAmount tx_fee = /* calculate from inputs - outputs */;
439+
440+
// Check absolute minimum
441+
if (tx_fee < ABSOLUTE_MIN_TX_FEE) {
442+
LogPrint(BCLog::DANDELION, "Rejecting stempool tx %s: fee %s below minimum %s\n",
443+
tx.GetHash().ToString(), FormatMoney(tx_fee), FormatMoney(ABSOLUTE_MIN_TX_FEE));
444+
return false;
445+
}
446+
447+
fee_out = tx_fee;
448+
return true;
449+
}
450+
```
451+
452+
### RPC Endpoint Updates
453+
454+
These RPC methods bypass wallet logic and need explicit fee validation:
455+
456+
1. **sendrawtransaction**: Direct mempool submission
457+
2. **testmempoolaccept**: Fee validation testing
458+
3. **submitpackage**: Package fee validation
459+
460+
#### Implementation:
461+
```cpp
462+
// In rpc/rawtransaction.cpp
463+
static RPCHelpMan sendrawtransaction() {
464+
// ... existing code ...
465+
466+
// Before accepting to mempool
467+
CAmount tx_fee = /* calculate fee */;
468+
if (tx_fee < ABSOLUTE_MIN_TX_FEE && !bypass_limits) {
469+
throw JSONRPCError(RPC_TRANSACTION_REJECTED,
470+
strprintf("Transaction fee %s is below minimum required %s",
471+
FormatMoney(tx_fee), FormatMoney(ABSOLUTE_MIN_TX_FEE)));
472+
}
473+
}
474+
```
475+
476+
### Network Protocol Updates
477+
478+
When enforcing new minimums network-wide:
479+
480+
1. **Update PROTOCOL_VERSION** to signal support
481+
2. **Add version-based enforcement** in validation
482+
3. **Update feefilter messages** to respect absolute minimum
483+
484+
```cpp
485+
// In net_processing.cpp
486+
void PeerManagerImpl::ProcessFeeFilter(CNode& peer, CAmount newFeeFilter) {
487+
// Ensure fee filter respects absolute minimum
488+
CAmount min_filter = std::max(newFeeFilter, ABSOLUTE_MIN_TX_FEE / 1000);
489+
peer.m_fee_filter_sent = min_filter;
490+
}
491+
```
492+
291493
## Appendix: Quick Reference
292494
293495
### Current State
@@ -300,14 +502,35 @@ This approach provides spam protection while maintaining fairness for legitimate
300502
- Medium TX (1000 bytes) pays: **0.1 DGB** ✓
301503
- Large TX (10000 bytes) pays: **1.0 DGB** ✓
302504
303-
### Key Files to Modify
505+
### Key Files to Modify (Priority Order)
304506
1. `src/policy/policy.h` - Add `ABSOLUTE_MIN_TX_FEE`
305507
2. `src/wallet/fees.cpp` - Enforce in `GetMinimumFee()`
306-
3. `src/validation.cpp` - Enforce in `CheckFeeRate()`
307-
4. 15+ test files - Update expectations
308-
309-
### Testing Command
508+
3. `src/wallet/spend.cpp` - Check in `CreateTransactionInternal()`
509+
4. `src/validation.cpp` - Enforce in `CheckFeeRate()`
510+
5. `src/txmempool.cpp` - Update `GetMinFee()`
511+
6. `src/dandelion.cpp` - Add stempool validation
512+
7. `src/rpc/rawtransaction.cpp` - Validate in RPC methods
513+
8. 18+ test files - Update expectations
514+
515+
### Testing Commands
310516
```bash
311517
# Run all fee-related tests after changes
312518
./test/functional/test_runner.py --extended feature_fee wallet_fee mempool_fee
519+
520+
# Test Dandelion++ integration
521+
./test/functional/test_runner.py dandelion_fee_validation
522+
523+
# Test RPC endpoints
524+
./test/functional/test_runner.py rpc_raw_fee_validation
525+
526+
# Full test suite
527+
./test/functional/test_runner.py --extended
528+
```
529+
530+
### Monitoring Metrics
531+
532+
Add these log statements for monitoring:
533+
```cpp
534+
LogPrint(BCLog::MEMPOOL, "Fee validation: tx=%s size=%d fee=%s min=%s\n",
535+
hash.ToString(), tx_size, FormatMoney(tx_fee), FormatMoney(ABSOLUTE_MIN_TX_FEE));
313536
```

0 commit comments

Comments
 (0)