Allow public address mapping (#767)

This commit is contained in:
Tanguy 2022-10-20 12:22:28 +02:00 committed by GitHub
parent 32233d36c8
commit 7b103e02f2
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 97 additions and 50 deletions

View File

@ -48,19 +48,19 @@ proc main() {.async.} =
swSrc = createCircuitRelaySwitch(clSrc)
swDst = createCircuitRelaySwitch(clDst)
# Create a relay address to swDst using swRel as the relay
addrs = MultiAddress.init($swRel.peerInfo.addrs[0] & "/p2p/" &
$swRel.peerInfo.peerId & "/p2p-circuit/p2p/" &
$swDst.peerInfo.peerId).get()
swDst.mount(proto)
await swRel.start()
await swSrc.start()
await swDst.start()
# Connect both Src and Dst to the relay, but not to each other.
await swSrc.connect(swRel.peerInfo.peerId, swRel.peerInfo.addrs)
let
# Create a relay address to swDst using swRel as the relay
addrs = MultiAddress.init($swRel.peerInfo.addrs[0] & "/p2p/" &
$swRel.peerInfo.peerId & "/p2p-circuit/p2p/" &
$swDst.peerInfo.peerId).get()
# Connect Dst to the relay
await swDst.connect(swRel.peerInfo.peerId, swRel.peerInfo.addrs)
# Dst reserve a slot on the relay.

View File

@ -22,11 +22,17 @@ export peerid, multiaddress, crypto, routing_record, errors, results
## Our local peer info
type
PeerInfoError* = LPError
PeerInfoError* = object of LPError
AddressMapper* =
proc(listenAddrs: seq[MultiAddress]): Future[seq[MultiAddress]]
{.gcsafe, raises: [Defect].}
PeerInfo* {.public.} = ref object
peerId*: PeerId
addrs*: seq[MultiAddress]
listenAddrs*: seq[MultiAddress]
addrs: seq[MultiAddress]
addressMappers*: seq[AddressMapper]
protocols*: seq[string]
protoVersion*: string
agentVersion*: string
@ -37,6 +43,7 @@ type
func shortLog*(p: PeerInfo): auto =
(
peerId: $p.peerId,
listenAddrs: mapIt(p.listenAddrs, $it),
addrs: mapIt(p.addrs, $it),
protocols: mapIt(p.protocols, $it),
protoVersion: p.protoVersion,
@ -44,7 +51,11 @@ func shortLog*(p: PeerInfo): auto =
)
chronicles.formatIt(PeerInfo): shortLog(it)
proc update*(p: PeerInfo) =
proc update*(p: PeerInfo) {.async.} =
p.addrs = p.listenAddrs
for mapper in p.addressMappers:
p.addrs = await mapper(p.addrs)
let sprRes = SignedPeerRecord.init(
p.privateKey,
PeerRecord.init(p.peerId, p.addrs)
@ -55,20 +66,25 @@ proc update*(p: PeerInfo) =
discard
#info "Can't update the signed peer record"
proc addrs*(p: PeerInfo): seq[MultiAddress] =
p.addrs
proc new*(
p: typedesc[PeerInfo],
key: PrivateKey,
addrs: openArray[MultiAddress] = [],
listenAddrs: openArray[MultiAddress] = [],
protocols: openArray[string] = [],
protoVersion: string = "",
agentVersion: string = ""): PeerInfo
{.raises: [Defect, PeerInfoError].} =
agentVersion: string = "",
addressMappers = newSeq[AddressMapper](),
): PeerInfo
{.raises: [Defect, LPError].} =
let pubkey = try:
key.getPublicKey().tryGet()
except CatchableError:
raise newException(PeerInfoError, "invalid private key")
let peerId = PeerId.init(key).tryGet()
let peerInfo = PeerInfo(
@ -77,10 +93,9 @@ proc new*(
privateKey: key,
protoVersion: protoVersion,
agentVersion: agentVersion,
addrs: @addrs,
listenAddrs: @listenAddrs,
protocols: @protocols,
addressMappers: addressMappers
)
peerInfo.update()
return peerInfo

View File

@ -299,11 +299,11 @@ proc start*(s: Switch) {.async, gcsafe, public.} =
trace "starting switch for peer", peerInfo = s.peerInfo
var startFuts: seq[Future[void]]
for t in s.transports:
let addrs = s.peerInfo.addrs.filterIt(
let addrs = s.peerInfo.listenAddrs.filterIt(
t.handles(it)
)
s.peerInfo.addrs.keepItIf(
s.peerInfo.listenAddrs.keepItIf(
it notin addrs
)
@ -320,9 +320,9 @@ proc start*(s: Switch) {.async, gcsafe, public.} =
for t in s.transports: # for each transport
if t.addrs.len > 0 or t.running:
s.acceptFuts.add(s.accept(t))
s.peerInfo.addrs &= t.addrs
s.peerInfo.listenAddrs &= t.addrs
s.peerInfo.update()
await s.peerInfo.update()
await s.ms.start()

View File

@ -52,6 +52,9 @@ suite "Identify":
msListen = MultistreamSelect.new()
msDial = MultistreamSelect.new()
serverFut = transport1.start(ma)
await remotePeerInfo.update()
asyncTeardown:
await conn.close()
await acceptFut
@ -61,7 +64,6 @@ suite "Identify":
asyncTest "default agent version":
msListen.addHandler(IdentifyCodec, identifyProto1)
serverFut = transport1.start(ma)
proc acceptHandler(): Future[void] {.async, gcsafe.} =
let c = await transport1.accept()
await msListen.handle(c)
@ -84,8 +86,6 @@ suite "Identify":
remotePeerInfo.agentVersion = customAgentVersion
msListen.addHandler(IdentifyCodec, identifyProto1)
serverFut = transport1.start(ma)
proc acceptHandler(): Future[void] {.async, gcsafe.} =
let c = await transport1.accept()
await msListen.handle(c)
@ -105,7 +105,6 @@ suite "Identify":
asyncTest "handle failed identify":
msListen.addHandler(IdentifyCodec, identifyProto1)
asyncSpawn transport1.start(ma)
proc acceptHandler() {.async.} =
var conn: Connection
@ -128,7 +127,6 @@ suite "Identify":
asyncTest "can send signed peer record":
msListen.addHandler(IdentifyCodec, identifyProto1)
identifyProto1.sendSignedPeerRecord = true
serverFut = transport1.start(ma)
proc acceptHandler(): Future[void] {.async, gcsafe.} =
let c = await transport1.accept()
await msListen.handle(c)
@ -195,7 +193,8 @@ suite "Identify":
asyncTest "simple push identify":
switch2.peerInfo.protocols.add("/newprotocol/")
switch2.peerInfo.addrs.add(MultiAddress.init("/ip4/127.0.0.1/tcp/5555").tryGet())
switch2.peerInfo.listenAddrs.add(MultiAddress.init("/ip4/127.0.0.1/tcp/5555").tryGet())
await switch2.peerInfo.update()
check:
switch1.peerStore[AddressBook][switch2.peerInfo.peerId] != switch2.peerInfo.addrs
@ -216,7 +215,8 @@ suite "Identify":
asyncTest "wrong peer id push identify":
switch2.peerInfo.protocols.add("/newprotocol/")
switch2.peerInfo.addrs.add(MultiAddress.init("/ip4/127.0.0.1/tcp/5555").tryGet())
switch2.peerInfo.listenAddrs.add(MultiAddress.init("/ip4/127.0.0.1/tcp/5555").tryGet())
await switch2.peerInfo.update()
check:
switch1.peerStore[AddressBook][switch2.peerInfo.peerId] != switch2.peerInfo.addrs

View File

@ -60,8 +60,7 @@ method init(p: TestProto) {.gcsafe.} =
proc createSwitch(ma: MultiAddress; outgoing: bool, secio: bool = false): (Switch, PeerInfo) =
var
privateKey = PrivateKey.random(ECDSA, rng[]).get()
peerInfo = PeerInfo.new(privateKey)
peerInfo.addrs.add(ma)
peerInfo = PeerInfo.new(privateKey, @[ma])
proc createMplex(conn: Connection): Muxer =
result = Mplex.new(conn)

View File

@ -18,22 +18,24 @@ suite "PeerInfo":
check peerId == peerInfo.peerId
check seckey.getPublicKey().get() == peerInfo.publicKey
test "Signed peer record":
const
ExpectedDomain = $multiCodec("libp2p-peer-record")
ExpectedPayloadType = @[(byte) 0x03, (byte) 0x01]
let
seckey = PrivateKey.random(rng[]).tryGet()
peerId = PeerId.init(seckey).get()
multiAddresses = @[MultiAddress.init("/ip4/0.0.0.0/tcp/24").tryGet(), MultiAddress.init("/ip4/0.0.0.0/tcp/25").tryGet()]
peerInfo = PeerInfo.new(seckey, multiAddresses)
waitFor(peerInfo.update())
let
env = peerInfo.signedPeerRecord.envelope
rec = PeerRecord.decode(env.payload()).tryGet()
# Check envelope fields
check:
env.publicKey == peerInfo.publicKey
@ -47,3 +49,17 @@ suite "PeerInfo":
rec.addresses.len == 2
rec.addresses[0].address == multiAddresses[0]
rec.addresses[1].address == multiAddresses[1]
test "Public address mapping":
let
seckey = PrivateKey.random(ECDSA, rng[]).get()
multiAddresses = @[MultiAddress.init("/ip4/0.0.0.0/tcp/24").tryGet(), MultiAddress.init("/ip4/0.0.0.0/tcp/25").tryGet()]
multiAddresses2 = @[MultiAddress.init("/ip4/8.8.8.8/tcp/33").tryGet()]
proc addressMapper(input: seq[MultiAddress]): Future[seq[MultiAddress]] {.async.} =
check input == multiAddresses
await sleepAsync(0.seconds)
return multiAddresses2
var peerInfo = PeerInfo.new(seckey, multiAddresses, addressMappers = @[addressMapper])
waitFor peerInfo.update()
check peerInfo.addrs == multiAddresses2

View File

@ -118,7 +118,6 @@ suite "Circuit Relay V2":
asyncTeardown:
checkTrackers()
var
addrs {.threadvar.}: MultiAddress
customProtoCodec {.threadvar.}: string
proto {.threadvar.}: LPProtocol
ttl {.threadvar.}: int
@ -145,9 +144,6 @@ suite "Circuit Relay V2":
src = createSwitch(srcCl)
dst = createSwitch(dstCl)
rel = newStandardSwitch()
addrs = MultiAddress.init($rel.peerInfo.addrs[0] & "/p2p/" &
$rel.peerInfo.peerId & "/p2p-circuit/p2p/" &
$dst.peerInfo.peerId).get()
asyncTest "Connection succeed":
proto.handler = proc(conn: Connection, proto: string) {.async.} =
@ -167,6 +163,10 @@ suite "Circuit Relay V2":
await src.start()
await dst.start()
let addrs = MultiAddress.init($rel.peerInfo.addrs[0] & "/p2p/" &
$rel.peerInfo.peerId & "/p2p-circuit/p2p/" &
$dst.peerInfo.peerId).get()
await src.connect(rel.peerInfo.peerId, rel.peerInfo.addrs)
await dst.connect(rel.peerInfo.peerId, rel.peerInfo.addrs)
@ -200,6 +200,10 @@ suite "Circuit Relay V2":
await src.start()
await dst.start()
let addrs = MultiAddress.init($rel.peerInfo.addrs[0] & "/p2p/" &
$rel.peerInfo.peerId & "/p2p-circuit/p2p/" &
$dst.peerInfo.peerId).get()
await src.connect(rel.peerInfo.peerId, rel.peerInfo.addrs)
await dst.connect(rel.peerInfo.peerId, rel.peerInfo.addrs)
@ -245,6 +249,10 @@ take to the ship.""")
await src.start()
await dst.start()
let addrs = MultiAddress.init($rel.peerInfo.addrs[0] & "/p2p/" &
$rel.peerInfo.peerId & "/p2p-circuit/p2p/" &
$dst.peerInfo.peerId).get()
await src.connect(rel.peerInfo.peerId, rel.peerInfo.addrs)
await dst.connect(rel.peerInfo.peerId, rel.peerInfo.addrs)
@ -277,6 +285,10 @@ take to the ship.""")
await src.start()
await dst.start()
let addrs = MultiAddress.init($rel.peerInfo.addrs[0] & "/p2p/" &
$rel.peerInfo.peerId & "/p2p-circuit/p2p/" &
$dst.peerInfo.peerId).get()
await src.connect(rel.peerInfo.peerId, rel.peerInfo.addrs)
await dst.connect(rel.peerInfo.peerId, rel.peerInfo.addrs)
@ -308,11 +320,6 @@ take to the ship.""")
rel2Cl = RelayClient.new(canHop = true)
rel2 = createSwitch(rel2Cl)
rv2 = Relay.new()
addrs = @[ MultiAddress.init($rel.peerInfo.addrs[0] & "/p2p/" &
$rel.peerInfo.peerId & "/p2p-circuit/p2p/" &
$rel2.peerInfo.peerId & "/p2p/" &
$rel2.peerInfo.peerId & "/p2p-circuit/p2p/" &
$dst.peerInfo.peerId).get() ]
rv2.setup(rel)
rel.mount(rv2)
dst.mount(proto)
@ -321,6 +328,13 @@ take to the ship.""")
await src.start()
await dst.start()
let
addrs = @[ MultiAddress.init($rel.peerInfo.addrs[0] & "/p2p/" &
$rel.peerInfo.peerId & "/p2p-circuit/p2p/" &
$rel2.peerInfo.peerId & "/p2p/" &
$rel2.peerInfo.peerId & "/p2p-circuit/p2p/" &
$dst.peerInfo.peerId).get() ]
await src.connect(rel.peerInfo.peerId, rel.peerInfo.addrs)
await rel2.connect(rel.peerInfo.peerId, rel.peerInfo.addrs)
await dst.connect(rel2.peerInfo.peerId, rel2.peerInfo.addrs)
@ -367,6 +381,16 @@ take to the ship.""")
switchA = createSwitch(clientA)
switchB = createSwitch(clientB)
switchC = createSwitch(clientC)
switchA.mount(protoBCA)
switchB.mount(protoCAB)
switchC.mount(protoABC)
await switchA.start()
await switchB.start()
await switchC.start()
let
addrsABC = MultiAddress.init($switchB.peerInfo.addrs[0] & "/p2p/" &
$switchB.peerInfo.peerId & "/p2p-circuit/p2p/" &
$switchC.peerInfo.peerId).get()
@ -376,13 +400,6 @@ take to the ship.""")
addrsCAB = MultiAddress.init($switchA.peerInfo.addrs[0] & "/p2p/" &
$switchA.peerInfo.peerId & "/p2p-circuit/p2p/" &
$switchB.peerInfo.peerId).get()
switchA.mount(protoBCA)
switchB.mount(protoCAB)
switchC.mount(protoABC)
await switchA.start()
await switchB.start()
await switchC.start()
await switchA.connect(switchB.peerInfo.peerId, switchB.peerInfo.addrs)
await switchB.connect(switchC.peerInfo.peerId, switchC.peerInfo.addrs)