Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
M
mybee
Project
Project
Details
Activity
Releases
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
vicotor
mybee
Commits
c1bac941
Unverified
Commit
c1bac941
authored
Jun 05, 2020
by
Petar Radovic
Committed by
GitHub
Jun 05, 2020
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Handshake with observable underlay (#257)
* handshake with observable underlay
parent
ebb776f4
Changes
7
Expand all
Show whitespace changes
Inline
Side-by-side
Showing
7 changed files
with
362 additions
and
685 deletions
+362
-685
address.go
pkg/bzz/address.go
+14
-6
connections_test.go
pkg/p2p/libp2p/connections_test.go
+1
-3
handshake.go
pkg/p2p/libp2p/internal/handshake/handshake.go
+80
-59
handshake_test.go
pkg/p2p/libp2p/internal/handshake/handshake_test.go
+100
-196
handshake.pb.go
pkg/p2p/libp2p/internal/handshake/pb/handshake.pb.go
+157
-401
handshake.proto
pkg/p2p/libp2p/internal/handshake/pb/handshake.proto
+6
-11
libp2p.go
pkg/p2p/libp2p/libp2p.go
+4
-9
No files found.
pkg/bzz/address.go
View file @
c1bac941
...
...
@@ -35,9 +35,12 @@ type addressJSON struct {
}
func
NewAddress
(
signer
crypto
.
Signer
,
underlay
ma
.
Multiaddr
,
overlay
swarm
.
Address
,
networkID
uint64
)
(
*
Address
,
error
)
{
networkIDBytes
:=
make
([]
byte
,
8
)
binary
.
BigEndian
.
PutUint64
(
networkIDBytes
,
networkID
)
signature
,
err
:=
signer
.
Sign
(
append
(
underlay
.
Bytes
(),
networkIDBytes
...
))
underlayBinary
,
err
:=
underlay
.
MarshalBinary
()
if
err
!=
nil
{
return
nil
,
err
}
signature
,
err
:=
signer
.
Sign
(
generateSignData
(
underlayBinary
,
overlay
.
Bytes
(),
networkID
))
if
err
!=
nil
{
return
nil
,
err
}
...
...
@@ -50,9 +53,7 @@ func NewAddress(signer crypto.Signer, underlay ma.Multiaddr, overlay swarm.Addre
}
func
ParseAddress
(
underlay
,
overlay
,
signature
[]
byte
,
networkID
uint64
)
(
*
Address
,
error
)
{
networkIDBytes
:=
make
([]
byte
,
8
)
binary
.
BigEndian
.
PutUint64
(
networkIDBytes
,
networkID
)
recoveredPK
,
err
:=
crypto
.
Recover
(
signature
,
append
(
underlay
,
networkIDBytes
...
))
recoveredPK
,
err
:=
crypto
.
Recover
(
signature
,
generateSignData
(
underlay
,
overlay
,
networkID
))
if
err
!=
nil
{
return
nil
,
ErrInvalidAddress
}
...
...
@@ -74,6 +75,13 @@ func ParseAddress(underlay, overlay, signature []byte, networkID uint64) (*Addre
},
nil
}
func
generateSignData
(
underlay
,
overlay
[]
byte
,
networkID
uint64
)
[]
byte
{
networkIDBytes
:=
make
([]
byte
,
8
)
binary
.
BigEndian
.
PutUint64
(
networkIDBytes
,
networkID
)
signData
:=
append
(
underlay
,
overlay
...
)
return
append
(
signData
,
networkIDBytes
...
)
}
func
(
a
*
Address
)
Equal
(
b
*
Address
)
bool
{
return
a
.
Overlay
.
Equal
(
b
.
Overlay
)
&&
a
.
Underlay
.
Equal
(
b
.
Underlay
)
&&
bytes
.
Equal
(
a
.
Signature
,
b
.
Signature
)
}
...
...
pkg/p2p/libp2p/connections_test.go
View file @
c1bac941
...
...
@@ -270,9 +270,7 @@ func TestConnectRepeatHandshake(t *testing.T) {
defer
cancel
()
s1
,
overlay1
:=
newService
(
t
,
1
,
libp2p
.
Options
{})
s2
,
overlay2
:=
newService
(
t
,
1
,
libp2p
.
Options
{})
addr
:=
serviceUnderlayAddress
(
t
,
s1
)
_
,
err
:=
s2
.
Connect
(
ctx
,
addr
)
...
...
@@ -293,7 +291,7 @@ func TestConnectRepeatHandshake(t *testing.T) {
t
.
Fatal
(
err
)
}
if
_
,
err
:=
s2
.
HandshakeService
()
.
Handshake
(
libp2p
.
NewStream
(
stream
));
err
==
nil
{
if
_
,
err
:=
s2
.
HandshakeService
()
.
Handshake
(
libp2p
.
NewStream
(
stream
)
,
info
.
Addrs
[
0
],
info
.
ID
);
err
==
nil
{
t
.
Fatalf
(
"expected stream error"
)
}
...
...
pkg/p2p/libp2p/internal/handshake/handshake.go
View file @
c1bac941
...
...
@@ -5,7 +5,6 @@
package
handshake
import
(
"bytes"
"errors"
"fmt"
"sync"
...
...
@@ -38,20 +37,17 @@ var (
// ErrHandshakeDuplicate is returned if the handshake response has been received by an already processed peer.
ErrHandshakeDuplicate
=
errors
.
New
(
"duplicate handshake"
)
// ErrInvalidBzzAddress is returned if peer info was received with invalid bzz address
ErrInvalidBzzAddress
=
errors
.
New
(
"invalid bzz address"
)
// ErrInvalidAck is returned if ack does not match the syn provided
// ErrInvalidAck is returned if data in received in ack is not valid (invalid signature for example).
ErrInvalidAck
=
errors
.
New
(
"invalid ack"
)
)
// PeerFinder has the information if the peer already exists in swarm.
type
PeerFinder
interface
{
Exists
(
overlay
swarm
.
Address
)
(
found
bool
)
}
// ErrInvalidSyn is returned if observable address in ack is not a valid..
ErrInvalidSyn
=
errors
.
New
(
"invalid syn"
)
)
type
Service
struct
{
bzzAddress
bzz
.
Address
signer
crypto
.
Signer
overlay
swarm
.
Address
lightNode
bool
networkID
uint64
receivedHandshakes
map
[
libp2ppeer
.
ID
]
struct
{}
receivedHandshakesMu
sync
.
Mutex
...
...
@@ -60,30 +56,32 @@ type Service struct {
network
.
Notifiee
// handshake service can be the receiver for network.Notify
}
func
New
(
overlay
swarm
.
Address
,
underlay
ma
.
Multiaddr
,
signer
crypto
.
Signer
,
networkID
uint64
,
logger
logging
.
Logger
)
(
*
Service
,
error
)
{
bzzAddress
,
err
:=
bzz
.
NewAddress
(
signer
,
underlay
,
overlay
,
networkID
)
if
err
!=
nil
{
return
nil
,
err
}
func
New
(
overlay
swarm
.
Address
,
signer
crypto
.
Signer
,
networkID
uint64
,
lighNode
bool
,
logger
logging
.
Logger
)
(
*
Service
,
error
)
{
return
&
Service
{
bzzAddress
:
*
bzzAddress
,
signer
:
signer
,
overlay
:
overlay
,
networkID
:
networkID
,
lightNode
:
lighNode
,
receivedHandshakes
:
make
(
map
[
libp2ppeer
.
ID
]
struct
{}),
logger
:
logger
,
Notifiee
:
new
(
network
.
NoopNotifiee
),
},
nil
}
func
(
s
*
Service
)
Handshake
(
stream
p2p
.
Stream
)
(
i
*
Info
,
err
error
)
{
func
(
s
*
Service
)
Handshake
(
stream
p2p
.
Stream
,
peerMultiaddr
ma
.
Multiaddr
,
peerID
libp2ppeer
.
ID
)
(
i
*
Info
,
err
error
)
{
w
,
r
:=
protobuf
.
NewWriterAndReader
(
stream
)
fullRemoteMA
,
err
:=
buildFullMA
(
peerMultiaddr
,
peerID
)
if
err
!=
nil
{
return
nil
,
err
}
fullRemoteMABytes
,
err
:=
fullRemoteMA
.
MarshalBinary
()
if
err
!=
nil
{
return
nil
,
err
}
if
err
:=
w
.
WriteMsgWithTimeout
(
messageTimeout
,
&
pb
.
Syn
{
BzzAddress
:
&
pb
.
BzzAddress
{
Underlay
:
s
.
bzzAddress
.
Underlay
.
Bytes
(),
Signature
:
s
.
bzzAddress
.
Signature
,
Overlay
:
s
.
bzzAddress
.
Overlay
.
Bytes
(),
},
NetworkID
:
s
.
networkID
,
ObservedUnderlay
:
fullRemoteMABytes
,
});
err
!=
nil
{
return
nil
,
fmt
.
Errorf
(
"write syn message: %w"
,
err
)
}
...
...
@@ -93,67 +91,82 @@ func (s *Service) Handshake(stream p2p.Stream) (i *Info, err error) {
return
nil
,
fmt
.
Errorf
(
"read synack message: %w"
,
err
)
}
if
err
:=
s
.
checkAck
(
resp
.
Ack
);
err
!=
nil
{
remoteBzzAddress
,
err
:=
s
.
parseCheckAck
(
resp
.
Ack
,
fullRemoteMABytes
)
if
err
!=
nil
{
return
nil
,
err
}
if
resp
.
Syn
.
NetworkID
!=
s
.
networkID
{
return
nil
,
ErrNetworkIDIncompatible
addr
,
err
:=
ma
.
NewMultiaddrBytes
(
resp
.
Syn
.
ObservedUnderlay
)
if
err
!=
nil
{
return
nil
,
ErrInvalidSyn
}
bzzAddress
,
err
:=
bzz
.
ParseAddress
(
resp
.
Syn
.
BzzAddress
.
Underlay
,
resp
.
Syn
.
BzzAddress
.
Overlay
,
resp
.
Syn
.
BzzAddress
.
Signature
,
resp
.
Syn
.
N
etworkID
)
bzzAddress
,
err
:=
bzz
.
NewAddress
(
s
.
signer
,
addr
,
s
.
overlay
,
s
.
n
etworkID
)
if
err
!=
nil
{
return
nil
,
ErrInvalidBzzAddress
return
nil
,
err
}
if
err
:=
w
.
WriteMsgWithTimeout
(
messageTimeout
,
&
pb
.
Ack
{
BzzAddress
:
resp
.
Syn
.
BzzAddress
,
Overlay
:
bzzAddress
.
Overlay
.
Bytes
(),
Signature
:
bzzAddress
.
Signature
,
NetworkID
:
s
.
networkID
,
Light
:
s
.
lightNode
,
});
err
!=
nil
{
return
nil
,
fmt
.
Errorf
(
"write ack message: %w"
,
err
)
}
s
.
logger
.
Tracef
(
"handshake finished for peer %s"
,
swarm
.
NewAddress
(
resp
.
Syn
.
BzzAddress
.
Overlay
)
.
String
())
s
.
logger
.
Tracef
(
"handshake finished for peer %s"
,
remoteBzzAddress
.
Overlay
.
String
())
return
&
Info
{
BzzAddress
:
b
zzAddress
,
Light
:
resp
.
Syn
.
Light
,
BzzAddress
:
remoteB
zzAddress
,
Light
:
resp
.
Ack
.
Light
,
},
nil
}
func
(
s
*
Service
)
Handle
(
stream
p2p
.
Stream
,
p
eerID
libp2ppeer
.
ID
)
(
i
*
Info
,
err
error
)
{
func
(
s
*
Service
)
Handle
(
stream
p2p
.
Stream
,
remoteMultiaddr
ma
.
Multiaddr
,
remoteP
eerID
libp2ppeer
.
ID
)
(
i
*
Info
,
err
error
)
{
s
.
receivedHandshakesMu
.
Lock
()
if
_
,
exists
:=
s
.
receivedHandshakes
[
p
eerID
];
exists
{
if
_
,
exists
:=
s
.
receivedHandshakes
[
remoteP
eerID
];
exists
{
s
.
receivedHandshakesMu
.
Unlock
()
return
nil
,
ErrHandshakeDuplicate
}
s
.
receivedHandshakes
[
p
eerID
]
=
struct
{}{}
s
.
receivedHandshakes
[
remoteP
eerID
]
=
struct
{}{}
s
.
receivedHandshakesMu
.
Unlock
()
w
,
r
:=
protobuf
.
NewWriterAndReader
(
stream
)
fullRemoteMA
,
err
:=
buildFullMA
(
remoteMultiaddr
,
remotePeerID
)
if
err
!=
nil
{
return
nil
,
err
}
fullRemoteMABytes
,
err
:=
fullRemoteMA
.
MarshalBinary
()
if
err
!=
nil
{
return
nil
,
err
}
var
req
pb
.
Syn
if
err
:=
r
.
ReadMsgWithTimeout
(
messageTimeout
,
&
req
);
err
!=
nil
{
var
syn
pb
.
Syn
if
err
:=
r
.
ReadMsgWithTimeout
(
messageTimeout
,
&
syn
);
err
!=
nil
{
return
nil
,
fmt
.
Errorf
(
"read syn message: %w"
,
err
)
}
if
req
.
NetworkID
!=
s
.
networkID
{
return
nil
,
ErrNetworkIDIncompatible
addr
,
err
:=
ma
.
NewMultiaddrBytes
(
syn
.
ObservedUnderlay
)
if
err
!=
nil
{
return
nil
,
ErrInvalidSyn
}
bzzAddress
,
err
:=
bzz
.
ParseAddress
(
req
.
BzzAddress
.
Underlay
,
req
.
BzzAddress
.
Overlay
,
req
.
BzzAddress
.
Signature
,
req
.
N
etworkID
)
bzzAddress
,
err
:=
bzz
.
NewAddress
(
s
.
signer
,
addr
,
s
.
overlay
,
s
.
n
etworkID
)
if
err
!=
nil
{
return
nil
,
ErrInvalidBzzAddress
return
nil
,
err
}
if
err
:=
w
.
WriteMsgWithTimeout
(
messageTimeout
,
&
pb
.
SynAck
{
Syn
:
&
pb
.
Syn
{
BzzAddress
:
&
pb
.
BzzAddress
{
Underlay
:
s
.
bzzAddress
.
Underlay
.
Bytes
(),
Signature
:
s
.
bzzAddress
.
Signature
,
Overlay
:
s
.
bzzAddress
.
Overlay
.
Bytes
(),
ObservedUnderlay
:
fullRemoteMABytes
,
},
Ack
:
&
pb
.
Ack
{
Overlay
:
bzzAddress
.
Overlay
.
Bytes
(),
Signature
:
bzzAddress
.
Signature
,
NetworkID
:
s
.
networkID
,
Light
:
s
.
lightNode
,
},
Ack
:
&
pb
.
Ack
{
BzzAddress
:
req
.
BzzAddress
},
});
err
!=
nil
{
return
nil
,
fmt
.
Errorf
(
"write synack message: %w"
,
err
)
}
...
...
@@ -163,14 +176,15 @@ func (s *Service) Handle(stream p2p.Stream, peerID libp2ppeer.ID) (i *Info, err
return
nil
,
fmt
.
Errorf
(
"read ack message: %w"
,
err
)
}
if
err
:=
s
.
checkAck
(
&
ack
);
err
!=
nil
{
remoteBzzAddress
,
err
:=
s
.
parseCheckAck
(
&
ack
,
fullRemoteMABytes
)
if
err
!=
nil
{
return
nil
,
err
}
s
.
logger
.
Tracef
(
"handshake finished for peer %s"
,
swarm
.
NewAddress
(
req
.
BzzAddress
.
Overlay
)
.
String
())
s
.
logger
.
Tracef
(
"handshake finished for peer %s"
,
remoteBzzAddress
.
Overlay
.
String
())
return
&
Info
{
BzzAddress
:
b
zzAddress
,
Light
:
req
.
Light
,
BzzAddress
:
remoteB
zzAddress
,
Light
:
ack
.
Light
,
},
nil
}
...
...
@@ -180,14 +194,21 @@ func (s *Service) Disconnected(_ network.Network, c network.Conn) {
delete
(
s
.
receivedHandshakes
,
c
.
RemotePeer
())
}
func
(
s
*
Service
)
checkAck
(
ack
*
pb
.
Ack
)
error
{
if
!
bytes
.
Equal
(
ack
.
BzzAddress
.
Overlay
,
s
.
bzzAddress
.
Overlay
.
Bytes
())
||
!
bytes
.
Equal
(
ack
.
BzzAddress
.
Underlay
,
s
.
bzzAddress
.
Underlay
.
Bytes
())
||
!
bytes
.
Equal
(
ack
.
BzzAddress
.
Signature
,
s
.
bzzAddress
.
Signature
)
{
return
ErrInvalidAck
func
buildFullMA
(
addr
ma
.
Multiaddr
,
peerID
libp2ppeer
.
ID
)
(
ma
.
Multiaddr
,
error
)
{
return
ma
.
NewMultiaddr
(
fmt
.
Sprintf
(
"%s/p2p/%s"
,
addr
.
String
(),
peerID
.
Pretty
()))
}
func
(
s
*
Service
)
parseCheckAck
(
ack
*
pb
.
Ack
,
remoteMA
[]
byte
)
(
*
bzz
.
Address
,
error
)
{
if
ack
.
NetworkID
!=
s
.
networkID
{
return
nil
,
ErrNetworkIDIncompatible
}
bzzAddress
,
err
:=
bzz
.
ParseAddress
(
remoteMA
,
ack
.
Overlay
,
ack
.
Signature
,
s
.
networkID
)
if
err
!=
nil
{
return
nil
,
ErrInvalidAck
}
return
nil
return
bzzAddress
,
nil
}
type
Info
struct
{
...
...
pkg/p2p/libp2p/internal/handshake/handshake_test.go
View file @
c1bac941
This diff is collapsed.
Click to expand it.
pkg/p2p/libp2p/internal/handshake/pb/handshake.pb.go
View file @
c1bac941
This diff is collapsed.
Click to expand it.
pkg/p2p/libp2p/internal/handshake/pb/handshake.proto
View file @
c1bac941
...
...
@@ -9,22 +9,17 @@ package handshake;
option
go_package
=
"pb"
;
message
Syn
{
BzzAddress
BzzAddress
=
1
;
uint64
NetworkID
=
2
;
bool
Light
=
3
;
bytes
ObservedUnderlay
=
1
;
}
message
Ack
{
BzzAddress
BzzAddress
=
1
;
bytes
Overlay
=
1
;
bytes
Signature
=
2
;
uint64
NetworkID
=
3
;
bool
Light
=
4
;
}
message
SynAck
{
Syn
Syn
=
1
;
Ack
Ack
=
2
;
}
\ No newline at end of file
message
BzzAddress
{
bytes
Underlay
=
1
;
bytes
Signature
=
2
;
bytes
Overlay
=
3
;
}
pkg/p2p/libp2p/libp2p.go
View file @
c1bac941
...
...
@@ -61,6 +61,7 @@ type Options struct {
PrivateKey
*
ecdsa
.
PrivateKey
DisableWS
bool
DisableQUIC
bool
LightNode
bool
Addressbook
addressbook
.
Putter
Logger
logging
.
Logger
Tracer
*
tracing
.
Tracer
...
...
@@ -156,13 +157,7 @@ func New(ctx context.Context, signer beecrypto.Signer, networkID uint64, overlay
return
nil
,
fmt
.
Errorf
(
"autonat: %w"
,
err
)
}
// todo: handle different underlays
underlay
,
err
:=
buildUnderlayAddress
(
h
.
Addrs
()[
1
],
h
.
ID
())
if
err
!=
nil
{
return
nil
,
fmt
.
Errorf
(
"build host multiaddress: %w"
,
err
)
}
handshakeService
,
err
:=
handshake
.
New
(
overlay
,
underlay
,
signer
,
networkID
,
o
.
Logger
)
handshakeService
,
err
:=
handshake
.
New
(
overlay
,
signer
,
networkID
,
o
.
LightNode
,
o
.
Logger
)
if
err
!=
nil
{
return
nil
,
fmt
.
Errorf
(
"handshake service: %w"
,
err
)
}
...
...
@@ -192,7 +187,7 @@ func New(ctx context.Context, signer beecrypto.Signer, networkID uint64, overlay
// handshake
s
.
host
.
SetStreamHandlerMatch
(
id
,
matcher
,
func
(
stream
network
.
Stream
)
{
peerID
:=
stream
.
Conn
()
.
RemotePeer
()
i
,
err
:=
s
.
handshakeService
.
Handle
(
NewStream
(
stream
),
peerID
)
i
,
err
:=
s
.
handshakeService
.
Handle
(
NewStream
(
stream
),
stream
.
Conn
()
.
RemoteMultiaddr
(),
peerID
)
if
err
!=
nil
{
s
.
logger
.
Debugf
(
"handshake: handle %s: %v"
,
peerID
,
err
)
s
.
logger
.
Errorf
(
"unable to handshake with peer %v"
,
peerID
)
...
...
@@ -334,7 +329,7 @@ func (s *Service) Connect(ctx context.Context, addr ma.Multiaddr) (address *bzz.
return
nil
,
err
}
i
,
err
:=
s
.
handshakeService
.
Handshake
(
NewStream
(
stream
))
i
,
err
:=
s
.
handshakeService
.
Handshake
(
NewStream
(
stream
)
,
stream
.
Conn
()
.
RemoteMultiaddr
(),
stream
.
Conn
()
.
RemotePeer
()
)
if
err
!=
nil
{
_
=
s
.
disconnect
(
info
.
ID
)
return
nil
,
fmt
.
Errorf
(
"handshake: %w"
,
err
)
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment