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
//! During the lifetime of a Bitcoin client, we have a couple of phases that are slightly different
//! from each other, having to implement their own state-machines and logic for handing requests.
//! While we could simply put everything in one struct and have a single `impl` block, that would
//! create a massive amount of if's in the code, taking different paths depending on which state
//! are we in. For that reason, we define the basics of a node, like code shared by all the
//! states into one base struct called `UtreexoNode`, we then further refine this struct using
//! fine-tunned `Contexts`, that should implement [NodeContext] and are passed-in as a generic
//! parameter by the caller.
//!
//! The three flavors of node are:
//!  - ChainSelector: This finds the best PoW chain, by downloding multiple candidates and taking
//!                   the one with more PoW. It should do it's job quickly, as it blocks our main
//!                   client and can't proceed without this information.
//!  - SyncNode: Used to download and verify all blocks in a chain. This is computationally
//!              expensive and may take a while to run. After this ends it's job, it gives us 100%
//!              centanty that this chain is valid.
//!  - Running Node: This is the one that users interacts with, and should be the one running most
//!                  of the time. This node is started right after `ChainSelector` returns, and
//!                  will handle new blocks (even if `SyncNode` haven't returned) and handle
//!                  requests by users.

use bitcoin::p2p::ServiceFlags;

/// This trait mainly defines a bunch of constants that we need for the node, but we may tweak
/// those values for each one. It's also an organized way of defining those constants anyway.
pub trait NodeContext {
    const REQUEST_TIMEOUT: u64;
    /// Max number of simultaneous connections we initiates we are willing to hold
    const MAX_OUTGOING_PEERS: usize = 10;
    /// We ask for peers every ASK_FOR_PEERS_INTERVAL seconds
    const ASK_FOR_PEERS_INTERVAL: u64 = 60 * 60; // One hour
    /// Save our database of peers every PEER_DB_DUMP_INTERVAL seconds
    const PEER_DB_DUMP_INTERVAL: u64 = 30; // 30 seconds
    /// Attempt to open a new connection (if needed) every TRY_NEW_CONNECTION seconds
    const TRY_NEW_CONNECTION: u64 = 10; // 10 seconds
    /// If ASSUME_STALE seconds passed since our last tip update, treat it as stale
    const ASSUME_STALE: u64 = 15 * 60; // 15 minutes
    /// While on IBD, if we've been without blocks for this long, ask for headers again
    const IBD_REQUEST_BLOCKS_AGAIN: u64 = 30; // 30 seconds
    /// How often we broadcast transactions
    const BROADCAST_DELAY: u64 = 30; // 30 seconds
    /// Max number of simultaneous inflight requests we allow
    const MAX_INFLIGHT_REQUESTS: usize = 1_000;
    /// Interval at which we open new feeler connections
    const FEELER_INTERVAL: u64 = 30; // 30 seconds
    /// Interval at which we rearrange our addresses
    const ADDRESS_REARRANGE_INTERVAL: u64 = 60 * 60; // 1 hour
    /// How long we ban a peer for
    const BAN_TIME: u64 = 60 * 60 * 24;
    /// How often we check if we haven't missed a block
    const BLOCK_CHECK_INTERVAL: u64 = 60 * 5; // 5 minutes
    /// How often we send our addresses to our peers
    const SEND_ADDRESSES_INTERVAL: u64 = 60 * 60; // 1 hour
    fn get_required_services(&self) -> ServiceFlags {
        ServiceFlags::NETWORK
    }
}

pub(crate) type PeerId = u32;