mirror of
https://github.com/vacp2p/mix.git
synced 2026-01-09 21:07:59 -05:00
Add support for circuit relay multiaddresses and fixes quic multiaddresses (#69)
Fixes #61
This commit is contained in:
@@ -1,7 +1,7 @@
|
||||
const
|
||||
k* = 16 # Security parameter
|
||||
r* = 5 # Maximum path length
|
||||
t* = 3 # t.k - combined length of next hop address and delay
|
||||
t* = 6 # t.k - combined length of next hop address and delay
|
||||
L* = 3 # Path length
|
||||
alphaSize* = 32 # Group element
|
||||
betaSize* = ((r * (t + 1)) + 1) * k # (r(t+1)+1)k bytes
|
||||
|
||||
@@ -2,7 +2,7 @@ import results, strutils
|
||||
import stew/base58
|
||||
import ./config
|
||||
|
||||
const addrBytesSize* = 46
|
||||
const multiAddrLen = 39
|
||||
|
||||
proc bytesToUInt16*(data: openArray[byte]): Result[uint16, string] =
|
||||
if len(data) != 2:
|
||||
@@ -29,15 +29,38 @@ proc uint32ToBytes*(value: uint32): seq[byte] =
|
||||
byte(value and 0xFF),
|
||||
]
|
||||
|
||||
proc extractPeerId(parts: seq[string], index: int): Result[seq[byte], string] =
|
||||
if parts[index - 1] != "p2p":
|
||||
return err("Invalid peerId component")
|
||||
let peerIdBase58 = parts[index]
|
||||
if peerIdBase58.len != 53:
|
||||
return err("Peer ID must be exactly 53 characters")
|
||||
try:
|
||||
let peerIdBytes = Base58.decode(peerIdBase58)
|
||||
if peerIdBytes.len != multiAddrLen:
|
||||
return err("Peer ID must be exactly " & $multiAddrLen & " bytes")
|
||||
return ok(peerIdBytes)
|
||||
except Base58Error:
|
||||
return err("Invalid Peer ID")
|
||||
|
||||
proc multiAddrToBytes*(multiAddr: string): Result[seq[byte], string] =
|
||||
var
|
||||
parts = multiAddr.split('/')
|
||||
res: seq[byte] = @[]
|
||||
|
||||
if parts.len != 7:
|
||||
const minMultiAddrComponentLen = 7
|
||||
const maxMultiAddrComponentLen = 11
|
||||
|
||||
if not (
|
||||
parts.len >= minMultiAddrComponentLen and parts.len <= maxMultiAddrComponentLen
|
||||
):
|
||||
return err("Invalid multiaddress format")
|
||||
|
||||
# IP address (4 bytes) ToDo: Add support for ipv6. Supporting ipv4 only for testing purposes
|
||||
if parts[1] != "ip4":
|
||||
# ToDo: Add support for ipv6. Supporting ipv4 only for testing purposes
|
||||
return err("Only ip4 addresses are supported")
|
||||
|
||||
# IP address (4 bytes)
|
||||
let ipParts = parts[2].split('.')
|
||||
if ipParts.len != 4:
|
||||
return err("Invalid IP address format")
|
||||
@@ -51,12 +74,14 @@ proc multiAddrToBytes*(multiAddr: string): Result[seq[byte], string] =
|
||||
return err("Invalid IP address format")
|
||||
|
||||
# Protocol (1 byte) ToDo: TLS or QUIC
|
||||
if parts[3] != "tcp" and parts[3] != "quic":
|
||||
var isQuic = false
|
||||
if parts[3] != "tcp" and not (parts[3] == "udp" and parts[5] == "quic-v1"):
|
||||
return err("Unsupported protocol")
|
||||
res.add(
|
||||
if parts[3] == "tcp":
|
||||
byte(0)
|
||||
else:
|
||||
isQuic = true
|
||||
byte(1)
|
||||
) # Using TCP for testing purposes
|
||||
|
||||
@@ -69,22 +94,26 @@ proc multiAddrToBytes*(multiAddr: string): Result[seq[byte], string] =
|
||||
except ValueError:
|
||||
return err("Invalid port")
|
||||
|
||||
# PeerID (39 bytes)
|
||||
let peerIdBase58 = parts[6]
|
||||
if peerIdBase58.len != 53:
|
||||
return err("Peer ID must be exactly 53 characters")
|
||||
try:
|
||||
let peerIdBytes = Base58.decode(peerIdBase58)
|
||||
if peerIdBytes.len != 39:
|
||||
return err("Peer ID must be exactly 39 bytes")
|
||||
res.add(peerIdBytes)
|
||||
except Base58Error:
|
||||
return err("Invalid Peer ID")
|
||||
# PeerID (39 bytes), if using circuit relay, this represents the relay server
|
||||
let peerId1Bytes = ?extractPeerId(parts, if isQuic: 7 else: 6)
|
||||
res.add(peerId1Bytes)
|
||||
|
||||
if res.len != addrSize:
|
||||
return err("Address must be exactly " & $addrSize & " bytes")
|
||||
if parts.len > minMultiAddrComponentLen + (if isQuic: 1 else: 0):
|
||||
if not (
|
||||
parts.len == maxMultiAddrComponentLen - 1 or
|
||||
(isQuic and parts.len == maxMultiAddrComponentLen)
|
||||
):
|
||||
return err("invalid p2p circuit relay multiaddress")
|
||||
elif not (parts[if isQuic: 8 else: 7] == "p2p-circuit"):
|
||||
return err("Invalid p2p-circuit component")
|
||||
|
||||
return ok(res)
|
||||
let peerId2Bytes = ?extractPeerId(parts, if isQuic: 10 else: 9)
|
||||
res.add(peerId2Bytes)
|
||||
|
||||
if res.len > addrSize:
|
||||
return err("Address must be <= " & $addrSize & " bytes")
|
||||
|
||||
return ok(res & newSeq[byte](addrSize - res.len))
|
||||
|
||||
proc bytesToMultiAddr*(bytes: openArray[byte]): Result[string, string] =
|
||||
if bytes.len != addrSize:
|
||||
@@ -95,14 +124,24 @@ proc bytesToMultiAddr*(bytes: openArray[byte]): Result[string, string] =
|
||||
ipParts.add($bytes[i])
|
||||
# ToDo: Add support for ipv6. Supporting ipv4 only for testing purposes
|
||||
|
||||
let protocol = if bytes[4] == 0: "tcp" else: "quic"
|
||||
let protocol = if bytes[4] == 0: "tcp" else: "udp"
|
||||
|
||||
let quic = if bytes[4] == 1: "/quic-v1" else: ""
|
||||
|
||||
# ToDo: TLS or QUIC (Using TCP for testing purposes)
|
||||
|
||||
let port = bytesToUInt16(bytes[5 .. 6]).valueOr:
|
||||
return err("Error in conversion of bytes to port no.: " & error)
|
||||
|
||||
let peerIdBase58 = Base58.encode(bytes[7 ..^ 1])
|
||||
let peerId1 = "/p2p/" & Base58.encode(bytes[7 ..< 46])
|
||||
|
||||
let peerId2Bytes = bytes[7 + multiAddrLen ..< 7 + (multiAddrLen * 2)]
|
||||
let peerId2 =
|
||||
if peerId2Bytes != newSeq[byte](multiAddrLen):
|
||||
"/p2p-circuit/p2p/" & Base58.encode(peerId2Bytes)
|
||||
else:
|
||||
""
|
||||
|
||||
return ok(
|
||||
"/ip4/" & ipParts.join(".") & "/" & protocol & "/" & $port & "/p2p/" & peerIdBase58
|
||||
"/ip4/" & ipParts.join(".") & "/" & protocol & "/" & $port & quic & peerId1 & peerId2
|
||||
)
|
||||
|
||||
@@ -7,8 +7,10 @@ suite "Utils tests":
|
||||
test "multi_addr_conversion":
|
||||
let multiAddrs = [
|
||||
"/ip4/0.0.0.0/tcp/4242/p2p/16Uiu2HAmFkwLVsVh6gGPmSm9R3X4scJ5thVdKfWYeJsKeVrbcgVC",
|
||||
"/ip4/192.168.1.1/quic/8080/p2p/16Uiu2HAm6WNzw8AssyPscYYi8x1bY5wXyQrGTShRH75bh5dPCjBQ",
|
||||
"/ip4/10.0.0.1/tcp/1234/p2p/16Uiu2HAmDHw4mwBdEjxjJPhrt8Eq1kvDjXAuwkqCmhNiz363AFV2",
|
||||
"/ip4/192.168.1.1/udp/8080/quic-v1/p2p/16Uiu2HAm6WNzw8AssyPscYYi8x1bY5wXyQrGTShRH75bh5dPCjBQ",
|
||||
"/ip4/10.0.0.1/tcp/1234/p2p/16Uiu2HAmDHw4mwBdEjxjJPhrt8Eq1kvDjXAuwkqCmhNiz363AFV2/p2p-circuit/p2p/16Uiu2HAm6WNzw8AssyPscYYi8x1bY5wXyQrGTShRH75bh5dPCjBQ",
|
||||
"/ip4/10.0.0.1/udp/1234/quic-v1/p2p/16Uiu2HAmDHw4mwBdEjxjJPhrt8Eq1kvDjXAuwkqCmhNiz363AFV2/p2p-circuit/p2p/16Uiu2HAm6WNzw8AssyPscYYi8x1bY5wXyQrGTShRH75bh5dPCjBQ",
|
||||
]
|
||||
|
||||
for multiAddr in multiAddrs:
|
||||
@@ -34,7 +36,7 @@ suite "Utils tests":
|
||||
|
||||
test "invalid_protocol":
|
||||
let res = multiAddrToBytes(
|
||||
"/ip4/0.0.0.0/udp/4242/p2p/16Uiu2HAmFkwLVsVh6gGPmSm9R3X4scJ5thVdKfWYeJsKeVrbcgVC"
|
||||
"/ip4/0.0.0.0/abc/4242/p2p/16Uiu2HAmFkwLVsVh6gGPmSm9R3X4scJ5thVdKfWYeJsKeVrbcgVC"
|
||||
)
|
||||
if res.isOk:
|
||||
error "Expected error for invalid protocol, but conversion succeeded"
|
||||
|
||||
Reference in New Issue
Block a user