1use crate::model::RecordPackage;
5use bitcoin::{BlockHash, Txid, Wtxid};
6use libp2p::{Multiaddr, PeerId};
7use serde::{Deserialize, Serialize};
8
9pub const PROTOCOL: &str = "/urma/node/record/5";
10pub const VERSION: u32 = 5;
11pub const REQUEST_LIMIT: usize = 1024;
12pub const RESPONSE_LIMIT: usize = 32 * 1024 * 1024;
13pub const PARENT_LIMIT: usize = 8 * 1024 * 1024;
15pub const INVENTORY_SPAN: u64 = 4096;
17pub const INVENTORY_ENTRIES: u32 = 512;
19pub const INVENTORY_LIMIT: usize = 256 * 1024;
21pub const PEERS_MAX: u32 = 32;
23pub const PEER_ADDRESSES_MAX: usize = 4;
25pub const PEERS_LIMIT: usize = 32 * 1024;
27
28#[derive(Clone, Copy, Debug, PartialEq, Eq, Serialize, Deserialize)]
29#[serde(tag = "kind", rename_all = "kebab-case", deny_unknown_fields)]
30pub enum Kind {
31 Record {
32 txid: Txid,
33 },
34 Parent {
36 txid: Txid,
37 },
38 Inventory {
40 from_height: u64,
41 to_height: u64,
42 after: Option<Placement>,
43 limit: u32,
44 },
45 Peers {
47 limit: u32,
48 },
49}
50
51#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
54#[serde(deny_unknown_fields)]
55pub struct GossipPeer {
56 #[serde(with = "base58_peer")]
57 pub peer_id: PeerId,
58 pub addrs: Vec<Multiaddr>,
59 pub last_seen: u64,
60}
61
62mod base58_peer {
64 use libp2p::PeerId;
65 use serde::{Deserialize, Deserializer, Serializer, de::Error};
66
67 pub fn serialize<S: Serializer>(peer: &PeerId, serializer: S) -> Result<S::Ok, S::Error> {
68 serializer.collect_str(peer)
69 }
70
71 pub fn deserialize<'de, D: Deserializer<'de>>(deserializer: D) -> Result<PeerId, D::Error> {
72 String::deserialize(deserializer)?
73 .parse()
74 .map_err(D::Error::custom)
75 }
76}
77
78#[derive(Clone, Copy, Debug, PartialEq, Eq, Serialize, Deserialize)]
80#[serde(deny_unknown_fields)]
81pub struct Placement {
82 pub height: u64,
83 pub block_hash: BlockHash,
84 pub position: u32,
85 pub txid: Txid,
86 pub wtxid: Wtxid,
87}
88
89#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
94#[serde(deny_unknown_fields)]
95pub struct InventoryPage {
96 pub scanned_from: u64,
97 pub scanned_through: Option<u64>,
98 pub entries: Vec<Placement>,
99 pub more: bool,
100}
101
102#[derive(Clone, Debug, Serialize, Deserialize)]
103#[serde(deny_unknown_fields)]
104pub struct Request {
105 pub version: u32,
106 pub chain_genesis: BlockHash,
107 pub kind: Kind,
108}
109
110#[derive(Clone, Debug, Serialize, Deserialize)]
111#[serde(deny_unknown_fields)]
112pub struct Response {
113 pub version: u32,
114 pub chain_genesis: BlockHash,
115 pub kind: Kind,
116 pub result: Reply,
117}
118
119#[derive(Clone, Debug, Serialize, Deserialize)]
120#[serde(
121 tag = "status",
122 content = "package",
123 rename_all = "kebab-case",
124 deny_unknown_fields
125)]
126pub enum Reply {
127 Record(Box<RecordPackage>),
128 Parent(String),
130 Inventory(InventoryPage),
131 Peers(Vec<GossipPeer>),
132 Missing,
134 WrongNetwork,
135 UnsupportedVersion,
136 Busy,
137 TooLarge,
138 Refused,
140}