use crate::model::RecordPackage;
use bitcoin::{BlockHash, Txid, Wtxid};
use libp2p::{Multiaddr, PeerId};
use serde::{Deserialize, Serialize};
pub const PROTOCOL: &str = "/urma/node/record/5";
pub const VERSION: u32 = 5;
pub const REQUEST_LIMIT: usize = 1024;
pub const RESPONSE_LIMIT: usize = 32 * 1024 * 1024;
pub const PARENT_LIMIT: usize = 8 * 1024 * 1024;
pub const INVENTORY_SPAN: u64 = 4096;
pub const INVENTORY_ENTRIES: u32 = 512;
pub const INVENTORY_LIMIT: usize = 256 * 1024;
pub const PEERS_MAX: u32 = 32;
pub const PEER_ADDRESSES_MAX: usize = 4;
pub const PEERS_LIMIT: usize = 32 * 1024;
#[derive(Clone, Copy, Debug, PartialEq, Eq, Serialize, Deserialize)]
#[serde(tag = "kind", rename_all = "kebab-case", deny_unknown_fields)]
pub enum Kind {
Record {
txid: Txid,
},
Parent {
txid: Txid,
},
Inventory {
from_height: u64,
to_height: u64,
after: Option<Placement>,
limit: u32,
},
Peers {
limit: u32,
},
}
#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
#[serde(deny_unknown_fields)]
pub struct GossipPeer {
#[serde(with = "base58_peer")]
pub peer_id: PeerId,
pub addrs: Vec<Multiaddr>,
pub last_seen: u64,
}
mod base58_peer {
use libp2p::PeerId;
use serde::{Deserialize, Deserializer, Serializer, de::Error};
pub fn serialize<S: Serializer>(peer: &PeerId, serializer: S) -> Result<S::Ok, S::Error> {
serializer.collect_str(peer)
}
pub fn deserialize<'de, D: Deserializer<'de>>(deserializer: D) -> Result<PeerId, D::Error> {
String::deserialize(deserializer)?
.parse()
.map_err(D::Error::custom)
}
}
#[derive(Clone, Copy, Debug, PartialEq, Eq, Serialize, Deserialize)]
#[serde(deny_unknown_fields)]
pub struct Placement {
pub height: u64,
pub block_hash: BlockHash,
pub position: u32,
pub txid: Txid,
pub wtxid: Wtxid,
}
#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
#[serde(deny_unknown_fields)]
pub struct InventoryPage {
pub scanned_from: u64,
pub scanned_through: Option<u64>,
pub entries: Vec<Placement>,
pub more: bool,
}
#[derive(Clone, Debug, Serialize, Deserialize)]
#[serde(deny_unknown_fields)]
pub struct Request {
pub version: u32,
pub chain_genesis: BlockHash,
pub kind: Kind,
}
#[derive(Clone, Debug, Serialize, Deserialize)]
#[serde(deny_unknown_fields)]
pub struct Response {
pub version: u32,
pub chain_genesis: BlockHash,
pub kind: Kind,
pub result: Reply,
}
#[derive(Clone, Debug, Serialize, Deserialize)]
#[serde(
tag = "status",
content = "package",
rename_all = "kebab-case",
deny_unknown_fields
)]
pub enum Reply {
Record(Box<RecordPackage>),
Parent(String),
Inventory(InventoryPage),
Peers(Vec<GossipPeer>),
Missing,
WrongNetwork,
UnsupportedVersion,
Busy,
TooLarge,
Refused,
}