mirror of
https://github.com/kaspanet/kaspad.git
synced 2025-03-30 15:08:33 +00:00

* [NOD-1500] Added Domain type and Constructor * [NOD-1500] Replaced dag+txpool with domain in flowContext * [NOD-1500] Replaced dag+txpool with domain in flowContext * [NOD-1500] Converters: domain objects from/to appmessage * [NOD-1500] Convert hashes to DomainHashes in appmessages * [NOD-1500] Remove references to daghash in dagconfig * [NOD-1500] Fixed all appmessage usages of hashes * [NOD-1500] Update all RPC to use domain * [NOD-1500] Big chunk of protocol flows re-wired to domain * [NOD-1500] Finished re-wiring all protocol flows to new Domain * [NOD-1500] Fix some mempool and kaspaminer compilation errors * [NOD-1500] Deleted util/{block,tx,daghash} and dbaccess * [NOD-1500] util.CoinbaseTransactionIndex -> transactionhelper.CoinbaseTransactionIndex * [NOD-1500] Fix txsigner * [NOD-1500] Removed all references to util/subnetworkid * [NOD-1500] Update RpcGetBlock related messages * [NOD-1500] Many more compilation fixes * [NOD-1500] Return full list of missing blocks for orphan resolution * [NOD-1500] Fixed handshake * [NOD-1500] Fixed flowcontext compilation * [NOD-1500] Update users of StartIBDIfRequired to handle error * [NOD-1500] Removed some more fields from RPC * [NOD-1500] Fix the getBlockTemplate flow * [NOD-1500] Fix HandleGetCurrentNetwork * [NOD-1500] Remove redundant code * [NOD-1500] Remove obsolete notifications * [NOD-1500] Split MiningManager and Consensus to separate fields in Domain * [NOD-1500] Update two wrong references to location of txscript * [NOD-1500] Added comments * [NOD-1500] Fix some tests * [NOD-1500] Removed serialization logic from appmessage * [NOD-1500] Rename database/serialization/messages.proto to dbobjects.proto * [NOD-1500] Delete integration tests * [NOD-1500] Remove txsort * [NOD-1500] Fix tiny bug * [NOD-1500] Remove rogue dependancy on bchd * [NOD-1500] Some stylistic fixes
208 lines
5.7 KiB
Go
208 lines
5.7 KiB
Go
package peer
|
|
|
|
import (
|
|
"sync"
|
|
"sync/atomic"
|
|
"time"
|
|
|
|
"github.com/kaspanet/kaspad/domain/consensus/model/externalapi"
|
|
"github.com/kaspanet/kaspad/infrastructure/network/netadapter"
|
|
|
|
"github.com/kaspanet/kaspad/app/appmessage"
|
|
"github.com/kaspanet/kaspad/infrastructure/network/netadapter/id"
|
|
mathUtil "github.com/kaspanet/kaspad/util/math"
|
|
"github.com/kaspanet/kaspad/util/mstime"
|
|
)
|
|
|
|
// Peer holds data about a peer.
|
|
type Peer struct {
|
|
connection *netadapter.NetConnection
|
|
|
|
selectedTipHashMtx sync.RWMutex
|
|
selectedTipHash *externalapi.DomainHash
|
|
|
|
userAgent string
|
|
services appmessage.ServiceFlag
|
|
advertisedProtocolVerion uint32 // protocol version advertised by remote
|
|
protocolVersion uint32 // negotiated protocol version
|
|
disableRelayTx bool
|
|
subnetworkID *externalapi.DomainSubnetworkID
|
|
|
|
timeOffset time.Duration
|
|
connectionStarted time.Time
|
|
|
|
pingLock sync.RWMutex
|
|
lastPingNonce uint64 // The nonce of the last ping we sent
|
|
lastPingTime time.Time // Time we sent last ping
|
|
lastPingDuration time.Duration // Time for last ping to return
|
|
|
|
isSelectedTipRequested uint32
|
|
selectedTipRequestChan chan struct{}
|
|
lastSelectedTipRequest mstime.Time
|
|
|
|
ibdStartChan chan struct{}
|
|
}
|
|
|
|
// New returns a new Peer
|
|
func New(connection *netadapter.NetConnection) *Peer {
|
|
return &Peer{
|
|
connection: connection,
|
|
selectedTipRequestChan: make(chan struct{}),
|
|
ibdStartChan: make(chan struct{}),
|
|
connectionStarted: time.Now(),
|
|
}
|
|
}
|
|
|
|
// Connection returns the NetConnection associated with this peer
|
|
func (p *Peer) Connection() *netadapter.NetConnection {
|
|
return p.connection
|
|
}
|
|
|
|
// SelectedTipHash returns the selected tip of the peer.
|
|
func (p *Peer) SelectedTipHash() *externalapi.DomainHash {
|
|
p.selectedTipHashMtx.RLock()
|
|
defer p.selectedTipHashMtx.RUnlock()
|
|
return p.selectedTipHash
|
|
}
|
|
|
|
// SetSelectedTipHash sets the selected tip of the peer.
|
|
func (p *Peer) SetSelectedTipHash(hash *externalapi.DomainHash) {
|
|
p.selectedTipHashMtx.Lock()
|
|
defer p.selectedTipHashMtx.Unlock()
|
|
p.selectedTipHash = hash
|
|
}
|
|
|
|
// SubnetworkID returns the subnetwork the peer is associated with.
|
|
// It is nil in full nodes.
|
|
func (p *Peer) SubnetworkID() *externalapi.DomainSubnetworkID {
|
|
return p.subnetworkID
|
|
}
|
|
|
|
// ID returns the peer ID.
|
|
func (p *Peer) ID() *id.ID {
|
|
return p.connection.ID()
|
|
}
|
|
|
|
// TimeOffset returns the peer's time offset.
|
|
func (p *Peer) TimeOffset() time.Duration {
|
|
return p.timeOffset
|
|
}
|
|
|
|
// UserAgent returns the peer's user agent.
|
|
func (p *Peer) UserAgent() string {
|
|
return p.userAgent
|
|
}
|
|
|
|
// AdvertisedProtocolVersion returns the peer's advertised protocol version.
|
|
func (p *Peer) AdvertisedProtocolVersion() uint32 {
|
|
return p.advertisedProtocolVerion
|
|
}
|
|
|
|
// TimeConnected returns the time since the connection to this been has been started.
|
|
func (p *Peer) TimeConnected() time.Duration {
|
|
return time.Since(p.connectionStarted)
|
|
}
|
|
|
|
// IsOutbound returns whether the peer is an outbound connection.
|
|
func (p *Peer) IsOutbound() bool {
|
|
return p.connection.IsOutbound()
|
|
}
|
|
|
|
// UpdateFieldsFromMsgVersion updates the peer with the data from the version message.
|
|
func (p *Peer) UpdateFieldsFromMsgVersion(msg *appmessage.MsgVersion) {
|
|
// Negotiate the protocol version.
|
|
p.advertisedProtocolVerion = msg.ProtocolVersion
|
|
p.protocolVersion = mathUtil.MinUint32(p.protocolVersion, p.advertisedProtocolVerion)
|
|
log.Debugf("Negotiated protocol version %d for peer %s",
|
|
p.protocolVersion, p.ID())
|
|
|
|
// Set the supported services for the peer to what the remote peer
|
|
// advertised.
|
|
p.services = msg.Services
|
|
|
|
// Set the remote peer's user agent.
|
|
p.userAgent = msg.UserAgent
|
|
|
|
p.disableRelayTx = msg.DisableRelayTx
|
|
p.selectedTipHash = msg.SelectedTipHash
|
|
p.subnetworkID = msg.SubnetworkID
|
|
|
|
p.timeOffset = mstime.Since(msg.Timestamp)
|
|
}
|
|
|
|
// SetPingPending sets the ping state of the peer to 'pending'
|
|
func (p *Peer) SetPingPending(nonce uint64) {
|
|
p.pingLock.Lock()
|
|
defer p.pingLock.Unlock()
|
|
|
|
p.lastPingNonce = nonce
|
|
p.lastPingTime = time.Now()
|
|
}
|
|
|
|
// SetPingIdle sets the ping state of the peer to 'idle'
|
|
func (p *Peer) SetPingIdle() {
|
|
p.pingLock.Lock()
|
|
defer p.pingLock.Unlock()
|
|
|
|
p.lastPingNonce = 0
|
|
p.lastPingDuration = time.Since(p.lastPingTime)
|
|
}
|
|
|
|
func (p *Peer) String() string {
|
|
return p.connection.String()
|
|
}
|
|
|
|
// RequestSelectedTipIfRequired notifies the peer that requesting
|
|
// a selected tip is required. This triggers the selected tip
|
|
// request flow.
|
|
func (p *Peer) RequestSelectedTipIfRequired() {
|
|
if atomic.SwapUint32(&p.isSelectedTipRequested, 1) != 0 {
|
|
return
|
|
}
|
|
|
|
const minGetSelectedTipInterval = time.Minute
|
|
if mstime.Since(p.lastSelectedTipRequest) < minGetSelectedTipInterval {
|
|
return
|
|
}
|
|
|
|
p.lastSelectedTipRequest = mstime.Now()
|
|
p.selectedTipRequestChan <- struct{}{}
|
|
}
|
|
|
|
// WaitForSelectedTipRequests blocks the current thread until
|
|
// a selected tip is requested from this peer
|
|
func (p *Peer) WaitForSelectedTipRequests() {
|
|
<-p.selectedTipRequestChan
|
|
}
|
|
|
|
// FinishRequestingSelectedTip finishes requesting the selected
|
|
// tip from this peer
|
|
func (p *Peer) FinishRequestingSelectedTip() {
|
|
atomic.StoreUint32(&p.isSelectedTipRequested, 0)
|
|
}
|
|
|
|
// StartIBD starts the IBD process for this peer
|
|
func (p *Peer) StartIBD() {
|
|
p.ibdStartChan <- struct{}{}
|
|
}
|
|
|
|
// WaitForIBDStart blocks the current thread until
|
|
// IBD start is requested from this peer
|
|
func (p *Peer) WaitForIBDStart() {
|
|
<-p.ibdStartChan
|
|
}
|
|
|
|
// Address returns the address associated with this connection
|
|
func (p *Peer) Address() string {
|
|
return p.connection.Address()
|
|
}
|
|
|
|
// LastPingDuration returns the duration of the last ping to
|
|
// this peer
|
|
func (p *Peer) LastPingDuration() time.Duration {
|
|
p.pingLock.Lock()
|
|
defer p.pingLock.Unlock()
|
|
|
|
return p.lastPingDuration
|
|
}
|