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
crate::ix!();

pub trait AddTxAnnouncement {

    fn add_tx_announcement(self: Arc<Self>, 
        node:         &mut AmoWriteGuard<Box<dyn NodeInterface>>,
        gtxid:        &GenTxId,
        current_time: OffsetDateTime /* micros */);
}

impl AddTxAnnouncement for PeerManager {

    /**
      | Register with TxRequestTracker that
      | an INV has been received from a peer.
      | The announcement parameters are decided
      | in PeerManager and then passed to TxRequestTracker.
      |
      */
    #[EXCLUSIVE_LOCKS_REQUIRED(::CS_MAIN)]
    fn add_tx_announcement(
        self:         Arc<Self>, 
        node:         &mut AmoWriteGuard<Box<dyn NodeInterface>>,
        gtxid:        &GenTxId,
        current_time: OffsetDateTime /* micros */)  {
        
        //  For m_txrequest
        assert_lock_held!(CS_MAIN);

        let nodeid: NodeId = node.get_id();

        if !node.has_permission(NetPermissionFlags::Relay) 
        && self.inner.lock().txrequest.lock().count(nodeid) >= MAX_PEER_TX_ANNOUNCEMENTS.try_into().unwrap() {
            //  Too many queued announcements from this peer
            return;
        }

        let state: Amo<NodeState> = create_state(nodeid);

        //  Decide the TxRequestTracker parameters for this announcement:
        //  - "preferred": if fPreferredDownload is set (= outbound, or NetPermissionFlags::NoBan permission)
        //  - "reqtime": current time plus delays for:
        //    - NONPREF_PEER_TX_DELAY for announcements from non-preferred connections
        //    - TXID_RELAY_DELAY for txid announcements while wtxid peers are available
        //    - OVERLOADED_PEER_TX_DELAY for announcements from peers which have at least
        //      MAX_PEER_TX_REQUEST_IN_FLIGHT requests in flight (and don't have NetPermissionFlags::Relay).
        let mut delay = Duration::microseconds(0);
        let preferred: bool = state.get().preferred_download.load(atomic::Ordering::Relaxed);

        if !preferred {
            delay += NONPREF_PEER_TX_DELAY;
        }

        if !gtxid.is_wtxid() && self.inner.lock().wtxid_relay_peers.load(atomic::Ordering::Relaxed) > 0 {
            delay += TXID_RELAY_DELAY;
        }

        let overloaded: bool = 
        !node.has_permission(NetPermissionFlags::Relay) 
        && self.inner.lock().txrequest.lock().count_in_flight(nodeid) >= MAX_PEER_TX_REQUEST_IN_FLIGHT.try_into().unwrap();

        if overloaded {
            delay += OVERLOADED_PEER_TX_DELAY;
        }

        self.inner.lock().txrequest.lock().received_inv(nodeid, gtxid, preferred, current_time + delay);
    }
}