1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
crate::ix!();

pub struct LockPoints {

    /**
      | Will be set to the blockchain height and
      | median time past values that would be
      | necessary to satisfy all relative locktime
      | constraints (BIP68) of this tx given our
      | view of block chain history
      */
    height:          i32, // default = { 0 }

    time:            i64, // default = { 0 }

    /**
      | As long as the current chain descends from
      | the highest height block containing one of
      | the inputs used in the calculation, then
      | the cached values are still valid even
      | after a reorg.
      */
    max_input_block: *mut BlockIndex, // default = { nullptr }
}

/**
  | \class TxMemPoolEntry
  | 
  | TxMemPoolEntry stores data about
  | the corresponding transaction, as
  | well as data about all in-mempool transactions
  | that depend on the transaction ("descendant"
  | transactions).
  | 
  | When a new entry is added to the mempool,
  | we update the descendant state (nCountWithDescendants,
  | nSizeWithDescendants, and nModFeesWithDescendants)
  | for all ancestors of the newly added
  | transaction.
  |
  */
pub struct TxMemPoolEntry {

    tx:              TransactionRef,
    parents:         RefCell<TxMemPoolEntryParents>,
    children:        RefCell<TxMemPoolEntryChildren>,

    /**
      | Cached to avoid expensive parent-transaction
      | lookups
      |
      */
    n_fee:           Amount,

    /**
      | ... and avoid recomputing tx weight
      | (also used for GetTxSize())
      |
      */
    n_tx_weight:     usize,

    /**
      | ... and total memory usage
      |
      */
    n_usage_size:    usize,

    /**
      | Local time when entering the mempool
      |
      */
    n_time:          OffsetDateTime,

    /**
      | Chain height when entering the mempool
      |
      */
    entry_height:    u32,

    /**
      | keep track of transactions that spend
      | a coinbase
      |
      */
    spends_coinbase: bool,

    /**
      | Total sigop cost
      |
      */
    sig_op_cost:     i64,

    /**
      | Used for determining the priority of
      | the transaction for mining in a block
      |
      */
    fee_delta:       i64, // default = { 0 }

    /**
      | Track the height and time at which tx
      | was final
      |
      */
    lock_points:     LockPoints,

    /*
      | Information about descendants of this
      | transaction that are in the mempool; if we
      | remove this transaction we must remove all
      | of these descendants as well.
      */

    /**
      | number of descendant transactions
      |
      */
    n_count_with_descendants:    u64, // default = { 1 }

    /**
      | ... and size
      |
      */
    n_size_with_descendants:     u64,

    /**
      | ... and total fees (all including us)
      |
      */
    n_mod_fees_with_descendants: Amount,

    /**
      | Analogous statistics for ancestor
      | transactions
      |
      */
    n_count_with_ancestors:       u64, // default = { 1 }
    n_size_with_ancestors:        u64,
    n_mod_fees_with_ancestors:    Amount,
    n_sig_op_cost_with_ancestors: i64,

    /**
      | Index in mempool's vTxHashes
      |
      */
    tx_hashes_idx: RefCell<usize>,

    /**
      | epoch when last touched, useful for
      | graph algorithms
      |
      */
    epoch_marker:  RefCell<EpochMarker>,
}

pub type TxMemPoolEntryRef = Amo<TxMemPoolEntry>;

/**
  | two aliases, should the types ever diverge
  |
  */
pub type TxMemPoolEntryParents  = HashSet<TxMemPoolEntryRef,CompareIteratorByHash>;
pub type TxMemPoolEntryChildren = HashSet<TxMemPoolEntryRef,CompareIteratorByHash>;

impl TxMemPoolEntry {
    
    pub fn get_tx(&self) -> TransactionRef {
        self.tx.clone()
    }
    
    pub fn get_fee(&self) -> &Amount {
        &self.n_fee
    }
    
    pub fn get_tx_weight(&self) -> usize {
        self.n_tx_weight
    }
    
    pub fn get_time(&self) -> OffsetDateTime {
        self.n_time
    }

    pub fn get_height(&self) -> u32 {
        self.entry_height
    }
    
    pub fn get_sig_op_cost(&self) -> i64 {
        self.sig_op_cost
    }
    
    pub fn get_modified_fee(&self) -> i64 {
        self.n_fee + self.fee_delta
    }
    
    pub fn dynamic_memory_usage(&self) -> usize {
        self.n_usage_size
    }
    
    pub fn get_lock_points(&self) -> &LockPoints {
        &self.lock_points
    }

    pub fn get_count_with_descendants(&self) -> u64 {
        self.n_count_with_descendants
    }
    
    pub fn get_size_with_descendants(&self) -> u64 {
        self.n_size_with_descendants
    }
    
    pub fn get_mod_fees_with_descendants(&self) -> Amount {
        self.n_mod_fees_with_descendants
    }
    
    pub fn get_spends_coinbase(&self) -> bool {
        self.spends_coinbase
    }
    
    pub fn get_count_with_ancestors(&self) -> u64 {
        self.n_count_with_ancestors
    }
    
    pub fn get_size_with_ancestors(&self) -> u64 {
        self.n_size_with_ancestors
    }
    
    pub fn get_mod_fees_with_ancestors(&self) -> Amount {
        self.n_mod_fees_with_ancestors
    }
    
    pub fn get_sig_op_cost_with_ancestors(&self) -> i64 {
        self.n_sig_op_cost_with_ancestors
    }
    
    pub fn get_mem_pool_parents_const(&self) -> &TxMemPoolEntryParents {
        todo!();
        /*
        self.parents
        */
    }
    
    pub fn get_mem_pool_children_const(&self) -> &TxMemPoolEntryChildren {
        todo!();
        /*
        self.children
        */
    }
    
    pub fn get_mem_pool_parents(&self) -> &mut TxMemPoolEntryParents {
        todo!();
        /*
        self.parents
        */
    }
    
    pub fn get_mem_pool_children(&self) -> &mut TxMemPoolEntryChildren {
        todo!();
        /*
        self.children
        */
    }
    
    /**
      | Adjusts the descendant state.
      |
      */
    pub fn update_descendant_state(&mut self, 
        modify_size:  i64,
        modify_fee:   Amount,
        modify_count: i64)  {
        
        todo!();
        /*
            nSizeWithDescendants += modifySize;
        assert(int64_t(nSizeWithDescendants) > 0);
        nModFeesWithDescendants += modifyFee;
        nCountWithDescendants += modifyCount;
        assert(int64_t(nCountWithDescendants) > 0);
        */
    }
    
    /**
      | Adjusts the ancestor state
      |
      */
    pub fn update_ancestor_state(&mut self, 
        modify_size:    i64,
        modify_fee:     Amount,
        modify_count:   i64,
        modify_sig_ops: i64)  {
        
        todo!();
        /*
            nSizeWithAncestors += modifySize;
        assert(int64_t(nSizeWithAncestors) > 0);
        nModFeesWithAncestors += modifyFee;
        nCountWithAncestors += modifyCount;
        assert(int64_t(nCountWithAncestors) > 0);
        nSigOpCostWithAncestors += modifySigOps;
        assert(int(nSigOpCostWithAncestors) >= 0);
        */
    }
    
    pub fn new(
        tx:              &TransactionRef,
        fee:             Amount,
        time:            i64,
        entry_height:    u32,
        spends_coinbase: bool,
        sigops_cost:     i64,
        lp:              LockPoints) -> Self {
    
        todo!();
        /*


            : tx{tx},
          nFee{fee},
          nTxWeight(GetTransactionWeight(*tx)),
          nUsageSize{RecursiveDynamicUsage(tx)},
          nTime{time},
          entryHeight{entry_height},
          spendsCoinbase{spends_coinbase},
          sigOpCost{sigops_cost},
          lockPoints{lp},
          nSizeWithDescendants{GetTxSize()},
          nModFeesWithDescendants{nFee},
          nSizeWithAncestors{GetTxSize()},
          nModFeesWithAncestors{nFee},
          nSigOpCostWithAncestors{sigOpCost}
        */
    }
    
    /**
      | Updates the fee delta used for mining
      | priority score, and the modified fees
      | with descendants.
      |
      */
    pub fn update_fee_delta(&mut self, new_fee_delta: i64)  {
        
        todo!();
        /*
           nModFeesWithDescendants += newFeeDelta - feeDelta;
           nModFeesWithAncestors += newFeeDelta - feeDelta;
           feeDelta = newFeeDelta;
           */
    }
    
    /**
      | Update the LockPoints after a reorg
      |
      */
    pub fn update_lock_points(&mut self, lp: LockPoints)  {
        self.lock_points = lp;
    }
    
    pub fn get_tx_size(&self) -> usize {

        get_virtual_transaction_size(
            self.n_tx_weight.try_into().unwrap(), 
            self.sig_op_cost
        ).try_into().unwrap()
    }
}

#[inline] pub fn get_virtual_transaction_size(
        weight:     i64,
        sigop_cost: i64) -> i64 {
    
    todo!();
        /*
            return GetVirtualTransactionSize(weight, sigop_cost, ::nBytesPerSigOp);
        */
}