node: Add support for `.onion` addresses in wire
Adds support for encoding and decoding onion addresses in the gossip protocol.
This commit is contained in:
parent
ae709b00ed
commit
7a1ba7d4b1
|
|
@ -15,6 +15,7 @@ use std::string::FromUtf8Error;
|
|||
use std::{io, mem};
|
||||
|
||||
use byteorder::{NetworkEndian, ReadBytesExt, WriteBytesExt};
|
||||
use cyphernet::addr::tor;
|
||||
|
||||
use crate::crypto::{PublicKey, Signature, Unverified};
|
||||
use crate::git;
|
||||
|
|
@ -56,6 +57,8 @@ pub enum Error {
|
|||
InvalidControlMessage(u8),
|
||||
#[error("invalid protocol version header `{0:x?}`")]
|
||||
InvalidProtocolVersion([u8; 4]),
|
||||
#[error("invalid onion address: {0}")]
|
||||
InvalidOnionAddr(#[from] tor::OnionAddrDecodeError),
|
||||
#[error("unknown address type `{0}`")]
|
||||
UnknownAddressType(u8),
|
||||
#[error("unknown message type `{0}`")]
|
||||
|
|
@ -237,6 +240,12 @@ impl Encode for Refs {
|
|||
}
|
||||
}
|
||||
|
||||
impl Encode for cyphernet::addr::tor::OnionAddrV3 {
|
||||
fn encode<W: io::Write + ?Sized>(&self, writer: &mut W) -> Result<usize, io::Error> {
|
||||
self.into_raw_bytes().encode(writer)
|
||||
}
|
||||
}
|
||||
|
||||
impl Encode for Alias {
|
||||
fn encode<W: io::Write + ?Sized>(&self, writer: &mut W) -> Result<usize, io::Error> {
|
||||
self.as_ref().encode(writer)
|
||||
|
|
@ -509,6 +518,15 @@ impl Decode for node::Features {
|
|||
}
|
||||
}
|
||||
|
||||
impl Decode for tor::OnionAddrV3 {
|
||||
fn decode<R: io::Read + ?Sized>(reader: &mut R) -> Result<Self, Error> {
|
||||
let bytes: [u8; tor::ONION_V3_RAW_LEN] = Decode::decode(reader)?;
|
||||
let addr = tor::OnionAddrV3::from_raw_bytes(bytes)?;
|
||||
|
||||
Ok(addr)
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
use std::{io, mem, net};
|
||||
|
||||
use byteorder::{NetworkEndian, ReadBytesExt};
|
||||
use cyphernet::addr::{Addr, HostName, NetAddr};
|
||||
use cyphernet::addr::{tor, Addr, HostName, NetAddr};
|
||||
use radicle::git::Oid;
|
||||
use radicle::node::Address;
|
||||
|
||||
|
|
@ -386,8 +386,12 @@ impl wire::Encode for Address {
|
|||
n += u8::from(AddressType::Dns).encode(writer)?;
|
||||
n += dns.encode(writer)?;
|
||||
}
|
||||
HostName::Tor(addr) => {
|
||||
n += u8::from(AddressType::Onion).encode(writer)?;
|
||||
n += addr.encode(writer)?;
|
||||
}
|
||||
_ => {
|
||||
todo!();
|
||||
return Err(io::ErrorKind::Unsupported.into());
|
||||
}
|
||||
}
|
||||
n += self.port().encode(writer)?;
|
||||
|
|
@ -418,7 +422,9 @@ impl wire::Decode for Address {
|
|||
HostName::Dns(dns)
|
||||
}
|
||||
Ok(AddressType::Onion) => {
|
||||
todo!();
|
||||
let onion: tor::OnionAddrV3 = wire::Decode::decode(reader)?;
|
||||
|
||||
HostName::Tor(onion)
|
||||
}
|
||||
Err(other) => return Err(wire::Error::UnknownAddressType(other)),
|
||||
};
|
||||
|
|
|
|||
|
|
@ -6,6 +6,8 @@ use std::{iter, net};
|
|||
|
||||
use crypto::test::signer::MockSigner;
|
||||
use crypto::{PublicKey, Unverified, Verified};
|
||||
use cyphernet::addr::tor::OnionAddrV3;
|
||||
use cyphernet::EcPk;
|
||||
use nonempty::NonEmpty;
|
||||
use qcheck::Arbitrary;
|
||||
|
||||
|
|
@ -260,7 +262,7 @@ impl Arbitrary for RepoId {
|
|||
|
||||
impl Arbitrary for AddressType {
|
||||
fn arbitrary(g: &mut qcheck::Gen) -> Self {
|
||||
let t = *g.choose(&[1, 2, 3]).unwrap() as u8;
|
||||
let t = *g.choose(&[1, 2, 3, 4]).unwrap() as u8;
|
||||
|
||||
AddressType::try_from(t).unwrap()
|
||||
}
|
||||
|
|
@ -285,7 +287,13 @@ impl Arbitrary for Address {
|
|||
.unwrap()
|
||||
.to_string(),
|
||||
),
|
||||
AddressType::Onion => todo!(),
|
||||
AddressType::Onion => {
|
||||
let pk = PublicKey::arbitrary(g);
|
||||
let addr = OnionAddrV3::from(
|
||||
cyphernet::ed25519::PublicKey::from_pk_compressed(**pk).unwrap(),
|
||||
);
|
||||
cyphernet::addr::HostName::Tor(addr)
|
||||
}
|
||||
};
|
||||
|
||||
Address::from(cyphernet::addr::NetAddr {
|
||||
|
|
|
|||
Loading…
Reference in New Issue