Files
kaspad/protocol/handshake.go
Ori Newman 04b578cee1 [NOD-1137] Implement handshake protocol (#792)
* [NOD-1126] Implement block relay flow

* [NOD-1126] Implement block relay flow

* [NOD-1126] Add StartGetRelayBlocksListener

* [NOD-1126] Integrate with new interface

* [NOD-1126] Fix comments

* [NOD-1126] Refactor protocol.go

* [NOD-1126] Split long lines

* [NOD-1126] Fix comment

* [NOD-1126] move sharedRequestedBlocks to a separate file

* [NOD-1126] Fix error message

* [NOD-1126] Move handleInv to StartBlockRelay

* [NOD-1126] Create hashesQueueSet type

* [NOD-1126] Make deleteFromRequestedBlocks a method

* [NOD-1126] Fix comment

* [NOD-1126] Add block logger

* [NOD-1126] Rename advertisedProtoVer->advertisedProtocolVer

* [NOD-1126] Fix comment and an error message

* [NOD-1126] Remove redundant loop

* [NOD-1126] Move requestBlocks upper

* [NOD-1126] Remove exiting blocks in requestedBlocks from hashesToRequest

* [NOD-1126] Change comment

* [NOD-1126] Rename stallResponseTimeout->timeout

* [NOD-1126] Use switch inside readMsgBlock

* [NOD-1126] Fix error message and remove redundant log

* [NOD-1126] Rename pacakge names

* [NOD-1126] Fix comment

* [NOD-1126] Change file names

* [NOD-1126] Convert block to partial if needed

* [NOD-1126] Remove function redeclaration

* [NOD-1126] continue instead of return

* [NOD-1126] Rename LogBlockBlueScore->LogBlock

* [NOD-1126] Add minimum functions to utils

* [NOD-1126] Flip condition on readInv

* [NOD-1126] Rename utilMath->mathUtil

* [NOD-1126] Fix comment

* [NOD-1137] Implement handshake

* [NOD-1137] Replace version's nonce with ID

* [NOD-1137] Remove redundant function

* [NOD-1137] Move handshake to a separate file

* [NOD-1137] Add todo

* [NOD-1137] Replace peer internal id with global peer ID

* [NOD-1137] Add serializer/deserializer to ID

* [NOD-1137] Remove validation from AddUserAgent

* [NOD-1137] Add missing id package

* [NOD-1137] Rename variables

* [NOD-1137] Add comment

* [NOD-1137] Implement GetBestLocalAddress

* [NOD-1137] Implement TODOs

* [NOD-1137] Rename variables

* [NOD-1137] Move errors.Is inside err!=nil branch

* [NOD-1137] Fix erroneous condition on Dequeue

* [NOD-1137] Fix bug in GetReadyPeerIDs

* [NOD-1137] Handle external IP on GetBestLocalAddress

* [NOD-1137] Remove version and verack message types when handshake is over

* [NOD-1137] Add FromBytes to id package

* [NOD-1137] Add protocol error

* [NOD-1137] Add ErrTimeout

* [NOD-1137] Log error only if exists

* [NOD-1137] Replace idFromBytes->id.FromBytes

* [NOD-1137] Add comments

* [NOD-1137] Remove ErrTimeout

* [NOD-1137] Unremove ErrTimeout

* [NOD-1137] Change comment

* [NOD-1137] Use EnqueueWithTimeout everywhere in protocol
2020-07-14 17:20:29 +03:00

111 lines
2.6 KiB
Go

package protocol
import (
"github.com/kaspanet/kaspad/addrmgr"
"github.com/kaspanet/kaspad/blockdag"
"github.com/kaspanet/kaspad/netadapter"
routerpkg "github.com/kaspanet/kaspad/netadapter/router"
peerpkg "github.com/kaspanet/kaspad/protocol/peer"
"github.com/kaspanet/kaspad/protocol/receiveversion"
"github.com/kaspanet/kaspad/protocol/sendversion"
"github.com/kaspanet/kaspad/util/locks"
"github.com/kaspanet/kaspad/wire"
"github.com/pkg/errors"
"sync"
"sync/atomic"
)
func handshake(router *routerpkg.Router, netAdapter *netadapter.NetAdapter, peer *peerpkg.Peer,
dag *blockdag.BlockDAG, addressManager *addrmgr.AddrManager) (closed bool, err error) {
receiveVersionRoute, err := router.AddIncomingRoute([]string{wire.CmdVersion})
if err != nil {
panic(err)
}
sendVersionRoute, err := router.AddIncomingRoute([]string{wire.CmdVerAck})
if err != nil {
panic(err)
}
// For the handshake to finish, we need to get from the other node
// a version and verack messages, so we increase the wait group by 2
// and block the handshake with wg.Wait().
wg := sync.WaitGroup{}
wg.Add(2)
errChanUsed := uint32(0)
errChan := make(chan error)
var peerAddress *wire.NetAddress
spawn(func() {
defer wg.Done()
address, closed, err := receiveversion.ReceiveVersion(receiveVersionRoute, router.OutgoingRoute(), netAdapter, peer, dag)
if err != nil {
log.Errorf("error from ReceiveVersion: %s", err)
}
if err != nil || closed {
if atomic.AddUint32(&errChanUsed, 1) != 1 {
errChan <- err
}
return
}
peerAddress = address
})
spawn(func() {
defer wg.Done()
closed, err := sendversion.SendVersion(sendVersionRoute, router.OutgoingRoute(), netAdapter, dag)
if err != nil {
log.Errorf("error from SendVersion: %s", err)
}
if err != nil || closed {
if atomic.AddUint32(&errChanUsed, 1) != 1 {
errChan <- err
}
return
}
})
select {
case err := <-errChan:
if err != nil {
return false, err
}
return true, nil
case <-locks.ReceiveFromChanWhenDone(func() { wg.Wait() }):
}
err = peerpkg.AddToReadyPeers(peer)
if err != nil {
if errors.Is(err, peerpkg.ErrPeerWithSameIDExists) {
return false, err
}
panic(err)
}
peerID, err := peer.ID()
if err != nil {
panic(err)
}
err = netAdapter.AssociateRouterID(router, peerID)
if err != nil {
panic(err)
}
if peerAddress != nil {
subnetworkID, err := peer.SubnetworkID()
if err != nil {
panic(err)
}
addressManager.AddAddress(peerAddress, peerAddress, subnetworkID)
}
err = router.RemoveRoute([]string{wire.CmdVersion, wire.CmdVerAck})
if err != nil {
panic(err)
}
return false, nil
}