mirror of
https://github.com/PeernetOfficial/core.git
synced 2026-07-17 02:47:51 +01:00
Finally moving Sequence code into protocol package
This commit is contained in:
@@ -48,8 +48,8 @@ const (
|
||||
// MessageRaw is a high-level message between peers that has not been decoded
|
||||
type MessageRaw struct {
|
||||
protocol.PacketRaw
|
||||
SenderPublicKey *btcec.PublicKey // Sender Public Key, ECDSA (secp256k1) 257-bit
|
||||
SequenceInfo *SequenceExpiry // Sequence
|
||||
SenderPublicKey *btcec.PublicKey // Sender Public Key, ECDSA (secp256k1) 257-bit
|
||||
SequenceInfo *protocol.SequenceExpiry // Sequence
|
||||
}
|
||||
|
||||
// MessageAnnouncement is the decoded announcement message.
|
||||
|
||||
@@ -186,12 +186,14 @@ func (nets *Networks) packetWorker() {
|
||||
case protocol.CommandResponse: // Response
|
||||
if response, _ := msgDecodeResponse(raw); response != nil {
|
||||
// Validate sequence number which prevents unsolicited responses.
|
||||
if valid, rtt := nets.Sequences.ValidateSequence(raw, response.Actions&(1<<ActionSequenceLast) > 0); !valid {
|
||||
sequenceInfo, valid, rtt := nets.Sequences.ValidateSequence(raw.SenderPublicKey, raw.Sequence, response.Actions&(1<<ActionSequenceLast) > 0, true)
|
||||
if !valid {
|
||||
//Filters.LogError("packetWorker", "message with invalid sequence %d command %d from %s\n", raw.Sequence, raw.Command, raw.connection.Address.String()) // Only log for debug purposes.
|
||||
continue
|
||||
} else if rtt > 0 {
|
||||
connection.RoundTripTime = rtt
|
||||
}
|
||||
raw.SequenceInfo = sequenceInfo
|
||||
|
||||
// Update known internal/external port and User Agent
|
||||
connection.PortInternal = response.PortInternal
|
||||
@@ -228,12 +230,14 @@ func (nets *Networks) packetWorker() {
|
||||
|
||||
case protocol.CommandPong: // Ping
|
||||
// Validate sequence number which prevents unsolicited responses.
|
||||
if valid, rtt := nets.Sequences.ValidateSequence(raw, true); !valid {
|
||||
sequenceInfo, valid, rtt := nets.Sequences.ValidateSequence(raw.SenderPublicKey, raw.Sequence, true, false)
|
||||
if !valid {
|
||||
//Filters.LogError("packetWorker", "message with invalid sequence %d command %d from %s\n", raw.Sequence, raw.Command, raw.connection.Address.String()) // Only log for debug purposes.
|
||||
continue
|
||||
} else if rtt > 0 {
|
||||
connection.RoundTripTime = rtt
|
||||
}
|
||||
raw.SequenceInfo = sequenceInfo
|
||||
|
||||
Filters.MessageIn(peer, raw, nil)
|
||||
|
||||
|
||||
10
Networks.go
10
Networks.go
@@ -6,7 +6,11 @@ Author: Peter Kleissner
|
||||
|
||||
package core
|
||||
|
||||
import "sync"
|
||||
import (
|
||||
"sync"
|
||||
|
||||
"github.com/PeernetOfficial/core/protocol"
|
||||
)
|
||||
|
||||
// Networks is the collection of all connected networks
|
||||
type Networks struct {
|
||||
@@ -24,7 +28,7 @@ type Networks struct {
|
||||
rawPacketsIncoming chan networkWire
|
||||
|
||||
// Sequences keeps track of all message sequence number, regardless of the network connection.
|
||||
Sequences *SequenceManager
|
||||
Sequences *protocol.SequenceManager
|
||||
|
||||
// ipListen keeps a simple list of IPs listened to. This allows quickly identifying if an IP matches with a listened one.
|
||||
ipListen *ipList
|
||||
@@ -40,7 +44,7 @@ func initMessageSequence() {
|
||||
|
||||
networks.rawPacketsIncoming = make(chan networkWire, 1000) // buffer up to 1000 UDP packets before they get buffered by the OS network stack and eventually dropped
|
||||
|
||||
networks.Sequences = NewSequenceManager(ReplyTimeout)
|
||||
networks.Sequences = protocol.NewSequenceManager(ReplyTimeout)
|
||||
|
||||
networks.ipListen = NewIPList()
|
||||
}
|
||||
|
||||
@@ -1,9 +1,10 @@
|
||||
/*
|
||||
File Name: Message Sequence.go
|
||||
File Name: Sequence.go
|
||||
Copyright: 2021 Peernet s.r.o.
|
||||
Author: Peter Kleissner
|
||||
|
||||
Records and verifies message sequences. Sequence numbers are valid on a peer level, independent of which network connection was used.
|
||||
This code caches and verifies message sequences. Sequence numbers are valid on a peer level, independent of which network connection was used.
|
||||
They can be used to map incoming response messages to previous outgoing requests. The remote peer ID is used together with a consecutive sequence number as unique key.
|
||||
|
||||
Advantages:
|
||||
* This secures against replay and poisoning attacks.
|
||||
@@ -12,7 +13,7 @@ Advantages:
|
||||
* (future) It can be used to detect missed and lost replies.
|
||||
*/
|
||||
|
||||
package core
|
||||
package protocol
|
||||
|
||||
import (
|
||||
"math/rand"
|
||||
@@ -21,7 +22,6 @@ import (
|
||||
"sync/atomic"
|
||||
"time"
|
||||
|
||||
"github.com/PeernetOfficial/core/protocol"
|
||||
"github.com/btcsuite/btcd/btcec"
|
||||
)
|
||||
|
||||
@@ -111,13 +111,8 @@ func (manager *SequenceManager) ArbitrarySequence(publicKey *btcec.PublicKey, da
|
||||
}
|
||||
|
||||
// ValidateSequence validates the sequence number of an incoming message. It will set raw.sequence if valid.
|
||||
func (manager *SequenceManager) ValidateSequence(raw *MessageRaw, invalidate bool) (valid bool, rtt time.Duration) {
|
||||
// Only Response and Pong
|
||||
if raw.Command != protocol.CommandResponse && raw.Command != protocol.CommandPong {
|
||||
return true, rtt
|
||||
}
|
||||
|
||||
key := string(raw.SenderPublicKey.SerializeCompressed()) + strconv.FormatUint(uint64(raw.Sequence), 10)
|
||||
func (manager *SequenceManager) ValidateSequence(publicKey *btcec.PublicKey, sequenceNumber uint32, invalidate, extendValidity bool) (sequenceInfo *SequenceExpiry, valid bool, rtt time.Duration) {
|
||||
key := string(publicKey.SerializeCompressed()) + strconv.FormatUint(uint64(sequenceNumber), 10)
|
||||
|
||||
manager.Lock()
|
||||
defer manager.Unlock()
|
||||
@@ -125,7 +120,7 @@ func (manager *SequenceManager) ValidateSequence(raw *MessageRaw, invalidate boo
|
||||
// lookup the sequence
|
||||
sequence, ok := manager.sequences[key]
|
||||
if !ok {
|
||||
return false, rtt
|
||||
return nil, false, rtt
|
||||
}
|
||||
|
||||
// Initial reply: Store latest roundtrip time. That value might be distorted on Response vs Pong since Response messages might send data
|
||||
@@ -139,24 +134,17 @@ func (manager *SequenceManager) ValidateSequence(raw *MessageRaw, invalidate boo
|
||||
// invalidate the sequence immediately?
|
||||
if invalidate {
|
||||
delete(manager.sequences, key)
|
||||
} else if raw.Command == protocol.CommandResponse {
|
||||
// Special case CommandResponse: Extend validity in case there are follow-up responses by half of the round-trip time since they will be sent one-way.
|
||||
} else if extendValidity {
|
||||
// Special case CommandResponse: Extend validity in case there are follow-up responses, by half of the round-trip time since they will be sent one-way.
|
||||
sequence.expires = time.Now().Add(time.Duration(manager.ReplyTimeout) * time.Second / 2)
|
||||
}
|
||||
|
||||
raw.SequenceInfo = sequence
|
||||
|
||||
return sequence.expires.After(time.Now()), rtt
|
||||
return sequence, sequence.expires.After(time.Now()), rtt
|
||||
}
|
||||
|
||||
// InvalidateSequence invalidates the sequence number.
|
||||
func (manager *SequenceManager) InvalidateSequence(raw *MessageRaw) {
|
||||
// Only Response
|
||||
if raw.Command != protocol.CommandResponse {
|
||||
return
|
||||
}
|
||||
|
||||
key := string(raw.SenderPublicKey.SerializeCompressed()) + strconv.FormatUint(uint64(raw.Sequence), 10)
|
||||
func (manager *SequenceManager) InvalidateSequence(publicKey *btcec.PublicKey, sequenceNumber uint32) {
|
||||
key := string(publicKey.SerializeCompressed()) + strconv.FormatUint(uint64(sequenceNumber), 10)
|
||||
|
||||
manager.Lock()
|
||||
delete(manager.sequences, key)
|
||||
Reference in New Issue
Block a user