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/4";
10pub const VERSION: u32 = 4;
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)]
91#[serde(deny_unknown_fields)]
92pub struct InventoryPage {
93 pub scanned_through: Option<u64>,
94 pub entries: Vec<Placement>,
95 pub more: bool,
96}
97
98#[derive(Clone, Debug, Serialize, Deserialize)]
99#[serde(deny_unknown_fields)]
100pub struct Request {
101 pub version: u32,
102 pub chain_genesis: BlockHash,
103 pub kind: Kind,
104}
105
106#[derive(Clone, Debug, Serialize, Deserialize)]
107#[serde(deny_unknown_fields)]
108pub struct Response {
109 pub version: u32,
110 pub chain_genesis: BlockHash,
111 pub kind: Kind,
112 pub result: Reply,
113}
114
115#[derive(Clone, Debug, Serialize, Deserialize)]
116#[serde(
117 tag = "status",
118 content = "package",
119 rename_all = "kebab-case",
120 deny_unknown_fields
121)]
122pub enum Reply {
123 Record(Box<RecordPackage>),
124 Parent(String),
126 Inventory(InventoryPage),
127 Peers(Vec<GossipPeer>),
128 Missing,
130 WrongNetwork,
131 UnsupportedVersion,
132 Busy,
133 TooLarge,
134 Refused,
136}