v2.0.0-p8

This commit is contained in:
Cassandra Heart 2024-10-18 01:55:51 -05:00
parent 5e2c944246
commit 1bd670e773
No known key found for this signature in database
GPG Key ID: 6352152859385958
9 changed files with 403 additions and 219 deletions

View File

@ -36,5 +36,5 @@ func FormatVersion(version []byte) string {
} }
func GetPatchNumber() byte { func GetPatchNumber() byte {
return 0x07 return 0x08
} }

View File

@ -225,7 +225,7 @@ func (e *DataClockConsensusEngine) sync(
response, err := client.GetDataFrame( response, err := client.GetDataFrame(
context.TODO(), context.TODO(),
&protobufs.GetDataFrameRequest{ &protobufs.GetDataFrameRequest{
FrameNumber: 0, FrameNumber: currentLatest.FrameNumber + 1,
}, },
grpc.MaxCallRecvMsgSize(600*1024*1024), grpc.MaxCallRecvMsgSize(600*1024*1024),
) )

View File

@ -315,17 +315,27 @@ func (e *DataClockConsensusEngine) Start() <-chan error {
go func() { go func() {
thresholdBeforeConfirming := 4 thresholdBeforeConfirming := 4
frame, err := e.dataTimeReel.Head()
if err != nil {
panic(err)
}
for { for {
list := &protobufs.DataPeerListAnnounce{ nextFrame, err := e.dataTimeReel.Head()
PeerList: []*protobufs.DataPeer{},
}
frame, err := e.dataTimeReel.Head()
if err != nil { if err != nil {
panic(err) panic(err)
} }
if frame.FrameNumber >= nextFrame.FrameNumber {
time.Sleep(30 * time.Second)
continue
}
frame = nextFrame
list := &protobufs.DataPeerListAnnounce{
PeerList: []*protobufs.DataPeer{},
}
e.latestFrameReceived = frame.FrameNumber e.latestFrameReceived = frame.FrameNumber
e.logger.Info( e.logger.Info(
"preparing peer announce", "preparing peer announce",

View File

@ -15,18 +15,18 @@ func (e *DataClockConsensusEngine) RegisterExecutor(
go func() { go func() {
for { for {
masterFrame, err := e.masterTimeReel.Head() dataFrame, err := e.dataTimeReel.Head()
if err != nil { if err != nil {
panic(err) panic(err)
} }
logger.Info( logger.Info(
"awaiting frame", "awaiting frame",
zap.Uint64("current_frame", masterFrame.FrameNumber), zap.Uint64("current_frame", dataFrame.FrameNumber),
zap.Uint64("target_frame", frame), zap.Uint64("target_frame", frame),
) )
newFrame := masterFrame.FrameNumber newFrame := dataFrame.FrameNumber
if newFrame >= frame { if newFrame >= frame {
logger.Info( logger.Info(
"injecting execution engine at frame", "injecting execution engine at frame",
@ -57,18 +57,18 @@ func (e *DataClockConsensusEngine) UnregisterExecutor(
go func() { go func() {
for { for {
masterFrame, err := e.masterTimeReel.Head() dataFrame, err := e.dataTimeReel.Head()
if err != nil { if err != nil {
panic(err) panic(err)
} }
logger.Info( logger.Info(
"awaiting frame", "awaiting frame",
zap.Uint64("current_frame", masterFrame.FrameNumber), zap.Uint64("current_frame", dataFrame.FrameNumber),
zap.Uint64("target_frame", frame), zap.Uint64("target_frame", frame),
) )
newFrame := masterFrame.FrameNumber newFrame := dataFrame.FrameNumber
if newFrame >= frame { if newFrame >= frame {
logger.Info( logger.Info(
"removing execution engine at frame", "removing execution engine at frame",

View File

@ -81,8 +81,6 @@ func (e *DataClockConsensusEngine) runMessageHandler() {
return nil return nil
}() }()
} }
} else {
return
} }
any := &anypb.Any{} any := &anypb.Any{}
@ -273,7 +271,6 @@ func (e *DataClockConsensusEngine) handleDataPeerListAnnounce(
} }
e.peerMapMx.Unlock() e.peerMapMx.Unlock()
} }
return nil return nil
} }
@ -296,40 +293,42 @@ func (e *DataClockConsensusEngine) handleDataAnnounceProverJoin(
address []byte, address []byte,
any *anypb.Any, any *anypb.Any,
) error { ) error {
announce := &protobufs.AnnounceProverJoin{} if e.GetFrameProverTries()[0].Contains(e.parentSelector) {
if err := any.UnmarshalTo(announce); err != nil { announce := &protobufs.AnnounceProverJoin{}
return errors.Wrap(err, "handle data announce prover join") if err := any.UnmarshalTo(announce); err != nil {
} return errors.Wrap(err, "handle data announce prover join")
}
if announce.PublicKeySignatureEd448 == nil || announce.Filter == nil { if announce.PublicKeySignatureEd448 == nil || announce.Filter == nil {
return errors.Wrap( return errors.Wrap(
errors.New("invalid data"), errors.New("invalid data"),
"handle data announce prover join", "handle data announce prover join",
) )
} }
address, err := e.getAddressFromSignature(announce.PublicKeySignatureEd448) address, err := e.getAddressFromSignature(announce.PublicKeySignatureEd448)
if err != nil { if err != nil {
return errors.Wrap(err, "handle data announce prover join") return errors.Wrap(err, "handle data announce prover join")
} }
msg := []byte("join") msg := []byte("join")
msg = binary.BigEndian.AppendUint64(msg, announce.FrameNumber) msg = binary.BigEndian.AppendUint64(msg, announce.FrameNumber)
msg = append(msg, announce.Filter...) msg = append(msg, announce.Filter...)
if err := announce.GetPublicKeySignatureEd448().Verify(msg); err != nil { if err := announce.GetPublicKeySignatureEd448().Verify(msg); err != nil {
return errors.Wrap(err, "handle data announce prover join") return errors.Wrap(err, "handle data announce prover join")
} }
e.proverTrieRequestsMx.Lock() e.proverTrieRequestsMx.Lock()
if len(announce.Filter) != len(e.filter) { if len(announce.Filter) != len(e.filter) {
return errors.Wrap( return errors.Wrap(
errors.New("filter width mismatch"), errors.New("filter width mismatch"),
"handle data announce prover join", "handle data announce prover join",
) )
} }
e.proverTrieJoinRequests[string(address)] = string(announce.Filter) e.proverTrieJoinRequests[string(address)] = string(announce.Filter)
e.proverTrieRequestsMx.Unlock() e.proverTrieRequestsMx.Unlock()
}
return nil return nil
} }
@ -338,41 +337,43 @@ func (e *DataClockConsensusEngine) handleDataAnnounceProverLeave(
address []byte, address []byte,
any *anypb.Any, any *anypb.Any,
) error { ) error {
announce := &protobufs.AnnounceProverLeave{} if e.GetFrameProverTries()[0].Contains(e.parentSelector) {
if err := any.UnmarshalTo(announce); err != nil { announce := &protobufs.AnnounceProverLeave{}
return errors.Wrap(err, "handle data announce prover leave") if err := any.UnmarshalTo(announce); err != nil {
return errors.Wrap(err, "handle data announce prover leave")
}
if announce.PublicKeySignatureEd448 == nil || announce.Filter == nil {
return errors.Wrap(
errors.New("invalid data"),
"handle data announce prover leave",
)
}
e.proverTrieRequestsMx.Lock()
if len(announce.Filter) != len(e.filter) {
return errors.Wrap(
errors.New("filter width mismatch"),
"handle data announce prover leave",
)
}
msg := []byte("leave")
msg = binary.BigEndian.AppendUint64(msg, announce.FrameNumber)
msg = append(msg, announce.Filter...)
if err := announce.GetPublicKeySignatureEd448().Verify(msg); err != nil {
return errors.Wrap(err, "handle data announce prover leave")
}
address, err := e.getAddressFromSignature(announce.PublicKeySignatureEd448)
if err != nil {
return errors.Wrap(err, "handle data announce prover leave")
}
e.proverTrieLeaveRequests[string(address)] = string(announce.Filter)
e.proverTrieRequestsMx.Unlock()
} }
if announce.PublicKeySignatureEd448 == nil || announce.Filter == nil {
return errors.Wrap(
errors.New("invalid data"),
"handle data announce prover leave",
)
}
e.proverTrieRequestsMx.Lock()
if len(announce.Filter) != len(e.filter) {
return errors.Wrap(
errors.New("filter width mismatch"),
"handle data announce prover leave",
)
}
msg := []byte("leave")
msg = binary.BigEndian.AppendUint64(msg, announce.FrameNumber)
msg = append(msg, announce.Filter...)
if err := announce.GetPublicKeySignatureEd448().Verify(msg); err != nil {
return errors.Wrap(err, "handle data announce prover leave")
}
address, err := e.getAddressFromSignature(announce.PublicKeySignatureEd448)
if err != nil {
return errors.Wrap(err, "handle data announce prover leave")
}
e.proverTrieLeaveRequests[string(address)] = string(announce.Filter)
e.proverTrieRequestsMx.Unlock()
return nil return nil
} }
@ -381,40 +382,42 @@ func (e *DataClockConsensusEngine) handleDataAnnounceProverPause(
address []byte, address []byte,
any *anypb.Any, any *anypb.Any,
) error { ) error {
announce := &protobufs.AnnounceProverPause{} if e.GetFrameProverTries()[0].Contains(e.parentSelector) {
if err := any.UnmarshalTo(announce); err != nil { announce := &protobufs.AnnounceProverPause{}
return errors.Wrap(err, "handle data announce prover pause") if err := any.UnmarshalTo(announce); err != nil {
} return errors.Wrap(err, "handle data announce prover pause")
}
if announce.PublicKeySignatureEd448 == nil || announce.Filter == nil { if announce.PublicKeySignatureEd448 == nil || announce.Filter == nil {
return errors.Wrap( return errors.Wrap(
errors.New("invalid data"), errors.New("invalid data"),
"handle data announce prover leave", "handle data announce prover leave",
) )
} }
e.proverTrieRequestsMx.Lock() e.proverTrieRequestsMx.Lock()
if len(announce.Filter) != len(e.filter) { if len(announce.Filter) != len(e.filter) {
return errors.Wrap( return errors.Wrap(
errors.New("filter width mismatch"), errors.New("filter width mismatch"),
"handle data announce prover pause", "handle data announce prover pause",
) )
} }
msg := []byte("pause") msg := []byte("pause")
msg = binary.BigEndian.AppendUint64(msg, announce.FrameNumber) msg = binary.BigEndian.AppendUint64(msg, announce.FrameNumber)
msg = append(msg, announce.Filter...) msg = append(msg, announce.Filter...)
if err := announce.GetPublicKeySignatureEd448().Verify(msg); err != nil { if err := announce.GetPublicKeySignatureEd448().Verify(msg); err != nil {
return errors.Wrap(err, "handle data announce prover pause") return errors.Wrap(err, "handle data announce prover pause")
} }
address, err := e.getAddressFromSignature(announce.PublicKeySignatureEd448) address, err := e.getAddressFromSignature(announce.PublicKeySignatureEd448)
if err != nil { if err != nil {
return errors.Wrap(err, "handle data announce prover pause") return errors.Wrap(err, "handle data announce prover pause")
} }
e.proverTriePauseRequests[string(address)] = string(announce.Filter) e.proverTriePauseRequests[string(address)] = string(announce.Filter)
e.proverTrieRequestsMx.Unlock() e.proverTrieRequestsMx.Unlock()
}
return nil return nil
} }
@ -423,104 +426,108 @@ func (e *DataClockConsensusEngine) handleDataAnnounceProverResume(
address []byte, address []byte,
any *anypb.Any, any *anypb.Any,
) error { ) error {
announce := &protobufs.AnnounceProverResume{} if e.GetFrameProverTries()[0].Contains(e.parentSelector) {
if err := any.UnmarshalTo(announce); err != nil { announce := &protobufs.AnnounceProverResume{}
return errors.Wrap(err, "handle data announce prover resume") if err := any.UnmarshalTo(announce); err != nil {
} return errors.Wrap(err, "handle data announce prover resume")
}
if announce.PublicKeySignatureEd448 == nil || announce.Filter == nil { if announce.PublicKeySignatureEd448 == nil || announce.Filter == nil {
return errors.Wrap( return errors.Wrap(
errors.New("invalid data"), errors.New("invalid data"),
"handle data announce prover resume", "handle data announce prover resume",
) )
} }
e.proverTrieRequestsMx.Lock() e.proverTrieRequestsMx.Lock()
if len(announce.Filter) != len(e.filter) { if len(announce.Filter) != len(e.filter) {
return errors.Wrap( return errors.Wrap(
errors.New("filter width mismatch"), errors.New("filter width mismatch"),
"handle data announce prover resume", "handle data announce prover resume",
) )
} }
address, err := e.getAddressFromSignature(announce.PublicKeySignatureEd448) address, err := e.getAddressFromSignature(announce.PublicKeySignatureEd448)
if err != nil { if err != nil {
return errors.Wrap(err, "handle data announce prover resume") return errors.Wrap(err, "handle data announce prover resume")
} }
msg := []byte("resume") msg := []byte("resume")
msg = binary.BigEndian.AppendUint64(msg, announce.FrameNumber) msg = binary.BigEndian.AppendUint64(msg, announce.FrameNumber)
msg = append(msg, announce.Filter...) msg = append(msg, announce.Filter...)
if err := announce.GetPublicKeySignatureEd448().Verify(msg); err != nil { if err := announce.GetPublicKeySignatureEd448().Verify(msg); err != nil {
return errors.Wrap(err, "handle data announce prover resume") return errors.Wrap(err, "handle data announce prover resume")
} }
e.proverTrieResumeRequests[string(address)] = string(announce.Filter) e.proverTrieResumeRequests[string(address)] = string(announce.Filter)
e.proverTrieRequestsMx.Unlock() e.proverTrieRequestsMx.Unlock()
}
return nil return nil
} }
func (e *DataClockConsensusEngine) handleTokenRequest( func (e *DataClockConsensusEngine) handleTokenRequest(
transition *protobufs.TokenRequest, transition *protobufs.TokenRequest,
) error { ) error {
e.stagedTransactionsMx.Lock() if e.GetFrameProverTries()[0].Contains(e.parentSelector) {
if e.stagedTransactions == nil { e.stagedTransactionsMx.Lock()
e.stagedTransactions = &protobufs.TokenRequests{} if e.stagedTransactions == nil {
} e.stagedTransactions = &protobufs.TokenRequests{}
}
found := false found := false
for _, ti := range e.stagedTransactions.Requests { for _, ti := range e.stagedTransactions.Requests {
switch t := ti.Request.(type) { switch t := ti.Request.(type) {
case *protobufs.TokenRequest_Transfer:
switch r := transition.Request.(type) {
case *protobufs.TokenRequest_Transfer: case *protobufs.TokenRequest_Transfer:
if bytes.Equal(r.Transfer.OfCoin.Address, t.Transfer.OfCoin.Address) { switch r := transition.Request.(type) {
found = true case *protobufs.TokenRequest_Transfer:
if bytes.Equal(r.Transfer.OfCoin.Address, t.Transfer.OfCoin.Address) {
found = true
}
} }
}
case *protobufs.TokenRequest_Split:
switch r := transition.Request.(type) {
case *protobufs.TokenRequest_Split: case *protobufs.TokenRequest_Split:
if bytes.Equal(r.Split.OfCoin.Address, r.Split.OfCoin.Address) { switch r := transition.Request.(type) {
found = true case *protobufs.TokenRequest_Split:
if bytes.Equal(r.Split.OfCoin.Address, r.Split.OfCoin.Address) {
found = true
}
} }
}
case *protobufs.TokenRequest_Merge:
switch r := transition.Request.(type) {
case *protobufs.TokenRequest_Merge: case *protobufs.TokenRequest_Merge:
checkmerge: switch r := transition.Request.(type) {
for i := range t.Merge.Coins { case *protobufs.TokenRequest_Merge:
for j := range r.Merge.Coins { checkmerge:
if bytes.Equal(t.Merge.Coins[i].Address, r.Merge.Coins[j].Address) { for i := range t.Merge.Coins {
found = true for j := range r.Merge.Coins {
break checkmerge if bytes.Equal(t.Merge.Coins[i].Address, r.Merge.Coins[j].Address) {
found = true
break checkmerge
}
} }
} }
} }
}
case *protobufs.TokenRequest_Mint:
switch r := transition.Request.(type) {
case *protobufs.TokenRequest_Mint: case *protobufs.TokenRequest_Mint:
checkmint: switch r := transition.Request.(type) {
for i := range t.Mint.Proofs { case *protobufs.TokenRequest_Mint:
for j := range r.Mint.Proofs { checkmint:
if bytes.Equal(t.Mint.Proofs[i], r.Mint.Proofs[j]) { for i := range t.Mint.Proofs {
found = true for j := range r.Mint.Proofs {
break checkmint if bytes.Equal(t.Mint.Proofs[i], r.Mint.Proofs[j]) {
found = true
break checkmint
}
} }
} }
} }
} }
} }
}
if !found { if !found {
e.stagedTransactions.Requests = append( e.stagedTransactions.Requests = append(
e.stagedTransactions.Requests, e.stagedTransactions.Requests,
transition, transition,
) )
}
e.stagedTransactionsMx.Unlock()
} }
e.stagedTransactionsMx.Unlock()
return nil return nil
} }
@ -547,8 +554,7 @@ func (e *DataClockConsensusEngine) handleClockFrameData(
} }
for _, trie := range e.GetFrameProverTries() { for _, trie := range e.GetFrameProverTries() {
prover := trie.FindNearest(addr.Bytes()) if trie.Contains(addr.Bytes()) {
if !bytes.Equal(prover.External.Key, addr.Bytes()) {
e.logger.Info( e.logger.Info(
"prover not in trie at frame, address may be in fork", "prover not in trie at frame, address may be in fork",
zap.Binary("address", address), zap.Binary("address", address),

View File

@ -133,7 +133,7 @@ func (e *DataClockConsensusEngine) decompressAndStoreCandidates(
delete(e.peerMap, string(peerId)) delete(e.peerMap, string(peerId))
} }
e.peerMapMx.Unlock() e.peerMapMx.Unlock()
return nil, errors.New("invalid continuity for compressed sync response") return nil, errors.New("invalid continuity for compressed x response")
} }
var final *protobufs.ClockFrame var final *protobufs.ClockFrame

View File

@ -277,71 +277,128 @@ func (d *DataTimeReel) runLoop() {
for { for {
select { select {
case frame := <-d.frames: case frame := <-d.frames:
rawFrame, err := d.clockStore.GetStagedDataClockFrame(
d.filter,
frame.frameNumber,
frame.selector.FillBytes(make([]byte, 32)),
false,
)
if err != nil {
panic(err)
}
d.logger.Debug(
"processing frame",
zap.Uint64("frame_number", rawFrame.FrameNumber),
zap.String("output_tag", hex.EncodeToString(rawFrame.Output[:64])),
zap.Uint64("head_number", d.head.FrameNumber),
zap.String("head_output_tag", hex.EncodeToString(d.head.Output[:64])),
)
// Most common scenario: in order new frame is higher number // Most common scenario: in order new frame is higher number
if d.head.FrameNumber < frame.frameNumber { if d.head.FrameNumber < rawFrame.FrameNumber {
d.logger.Debug( d.logger.Debug("frame is higher")
"frame is higher",
zap.Uint64("head_frame_number", d.head.FrameNumber),
zap.Uint64("frame_number", frame.frameNumber),
)
rawFrame, err := d.clockStore.GetStagedDataClockFrame( parent := new(big.Int).SetBytes(rawFrame.ParentSelector)
d.filter, selector, err := rawFrame.GetSelector()
frame.frameNumber,
frame.selector.FillBytes(make([]byte, 32)),
false,
)
if err != nil { if err != nil {
panic(err) panic(err)
} }
distance, err := d.GetDistance(rawFrame) distance, err := d.GetDistance(rawFrame)
if err != nil { if err != nil {
panic(err) if !errors.Is(err, store.ErrNotFound) {
panic(err)
}
d.addPending(selector, parent, frame.frameNumber)
d.processPending(d.head, frame)
continue
} }
// Otherwise set it as the next and process all pending
d.setHead(rawFrame, distance)
} else if d.head.FrameNumber == frame.frameNumber {
// frames are equivalent, no need to act
headSelector, err := d.head.GetSelector() headSelector, err := d.head.GetSelector()
if err != nil { if err != nil {
panic(err) panic(err)
} }
if headSelector.Cmp(frame.selector) == 0 { // If the frame has a gap from the head or is not descendent, mark it as
d.logger.Debug("equivalent frame") // pending:
if rawFrame.FrameNumber-d.head.FrameNumber != 1 {
d.logger.Debug(
"frame has has gap, fork choice",
zap.Bool("has_gap", rawFrame.FrameNumber-d.head.FrameNumber != 1),
zap.String("parent_selector", parent.Text(16)),
zap.String("head_selector", headSelector.Text(16)),
)
d.forkChoice(rawFrame, distance)
d.processPending(d.head, frame)
continue continue
} }
rawFrame, err := d.clockStore.GetStagedDataClockFrame( // Otherwise set it as the next and process all pending
d.filter, d.setHead(rawFrame, distance)
frame.frameNumber, d.processPending(d.head, frame)
frame.selector.FillBytes(make([]byte, 32)), } else if d.head.FrameNumber == rawFrame.FrameNumber {
false, // frames are equivalent, no need to act
) if bytes.Equal(d.head.Output, rawFrame.Output) {
if err != nil { d.logger.Debug("equivalent frame")
panic(err) d.processPending(d.head, frame)
continue
} }
distance, err := d.GetDistance(rawFrame) distance, err := d.GetDistance(rawFrame)
if err != nil { if err != nil {
panic(err) panic(err)
} }
d.logger.Debug(
"frame is same height",
zap.String("head_distance", d.headDistance.Text(16)),
zap.String("distance", distance.Text(16)),
)
// Optimization: if competing frames share a parent we can short-circuit // Optimization: if competing frames share a parent we can short-circuit
// fork choice // fork choice
if new(big.Int).SetBytes(d.head.ParentSelector).Cmp( if bytes.Equal(d.head.ParentSelector, rawFrame.ParentSelector) &&
frame.parentSelector, distance.Cmp(d.headDistance) < 0 {
) == 0 && distance.Cmp(d.headDistance) < 0 {
d.logger.Debug( d.logger.Debug(
"frame shares parent, has shorter distance, short circuit", "frame shares parent, has shorter distance, short circuit",
) )
d.totalDistance.Sub(d.totalDistance, d.headDistance)
d.setHead(rawFrame, distance) d.setHead(rawFrame, distance)
d.processPending(d.head, frame)
continue continue
} }
// Choose fork
d.forkChoice(rawFrame, distance)
d.processPending(d.head, frame)
} else { } else {
d.logger.Debug("frame is lower height") d.logger.Debug("frame is lower height")
// tag: dusk we should have some kind of check here to avoid brutal
// thrashing
existing, _, err := d.clockStore.GetDataClockFrame(
d.filter,
rawFrame.FrameNumber,
true,
)
if err != nil {
// if this returns an error it's either not found (which shouldn't
// happen without corruption) or pebble is borked, either way, panic
panic(err)
}
// It's a fork, but it's behind. We need to stash it until it catches
// up (or dies off)
if !bytes.Equal(existing.Output, rawFrame.Output) {
d.logger.Debug("is fork, add pending")
parent, selector, err := rawFrame.GetParentAndSelector()
if err != nil {
panic(err)
}
d.addPending(selector, parent, frame.frameNumber)
d.processPending(d.head, frame)
}
} }
case <-d.done: case <-d.done:
return return

View File

@ -332,6 +332,9 @@ func main() {
} }
if *core != 0 { if *core != 0 {
runtime.GOMAXPROCS(2)
rdebug.SetGCPercent(9999)
if nodeConfig.Engine.DataWorkerMemoryLimit == 0 { if nodeConfig.Engine.DataWorkerMemoryLimit == 0 {
nodeConfig.Engine.DataWorkerMemoryLimit = 1792 * 1024 * 1024 // 1.75GiB nodeConfig.Engine.DataWorkerMemoryLimit = 1792 * 1024 * 1024 // 1.75GiB
} }

View File

@ -5,10 +5,15 @@ import (
"context" "context"
"crypto/rand" "crypto/rand"
"encoding/hex" "encoding/hex"
"encoding/json"
"fmt" "fmt"
"io"
"math/big" "math/big"
"math/bits" "math/bits"
"net" "net"
"net/http"
"strconv"
"strings"
"sync" "sync"
"time" "time"
@ -28,6 +33,7 @@ import (
"github.com/mr-tron/base58" "github.com/mr-tron/base58"
ma "github.com/multiformats/go-multiaddr" ma "github.com/multiformats/go-multiaddr"
madns "github.com/multiformats/go-multiaddr-dns" madns "github.com/multiformats/go-multiaddr-dns"
mn "github.com/multiformats/go-multiaddr/net"
"github.com/pkg/errors" "github.com/pkg/errors"
"github.com/prometheus/client_golang/prometheus" "github.com/prometheus/client_golang/prometheus"
"go.uber.org/zap" "go.uber.org/zap"
@ -207,6 +213,8 @@ func NewBlossomSub(
routingDiscovery := routing.NewRoutingDiscovery(kademliaDHT) routingDiscovery := routing.NewRoutingDiscovery(kademliaDHT)
util.Advertise(ctx, routingDiscovery, getNetworkNamespace(p2pConfig.Network)) util.Advertise(ctx, routingDiscovery, getNetworkNamespace(p2pConfig.Network))
verifyReachability(p2pConfig)
discoverPeers(p2pConfig, ctx, logger, h, routingDiscovery) discoverPeers(p2pConfig, ctx, logger, h, routingDiscovery)
// TODO: turn into an option flag for console logging, this is too noisy for // TODO: turn into an option flag for console logging, this is too noisy for
@ -473,10 +481,19 @@ func initDHT(
var kademliaDHT *dht.IpfsDHT var kademliaDHT *dht.IpfsDHT
var err error var err error
if isBootstrapPeer { if isBootstrapPeer {
panic( if p2pConfig.Network == 0 {
"this release is for normal peers only, if you are running a " + panic(
"bootstrap node, please use v2.0-bootstrap", "this release is for normal peers only, if you are running a " +
) "bootstrap node, please use v2.0-bootstrap",
)
} else {
kademliaDHT, err = dht.New(
ctx,
h,
dht.Mode(dht.ModeServer),
dht.BootstrapPeers(bootstrappers...),
)
}
} else { } else {
kademliaDHT, err = dht.New( kademliaDHT, err = dht.New(
ctx, ctx,
@ -520,7 +537,9 @@ func initDHT(
go func() { go func() {
for { for {
time.Sleep(30 * time.Second) time.Sleep(30 * time.Second)
reconnect() if len(h.Network().Peers()) == 0 {
reconnect()
}
} }
}() }()
@ -675,6 +694,91 @@ func (b *BlossomSub) SignMessage(msg []byte) ([]byte, error) {
return sig, errors.Wrap(err, "sign message") return sig, errors.Wrap(err, "sign message")
} }
type ReachabilityRequest struct {
Port uint16 `json:"port"`
Type string `json:"type"`
}
type ReachabilityResponse struct {
Reachable bool `json:"reachable"`
Error string `json:"error"`
}
func verifyReachability(cfg *config.P2PConfig) bool {
a, err := ma.NewMultiaddr(cfg.ListenMultiaddr)
if err != nil {
return false
}
transport, addr, err := mn.DialArgs(a)
if err != nil {
return false
}
addrparts := strings.Split(addr, ":")
if len(addrparts) != 2 {
return false
}
port, err := strconv.ParseUint(addrparts[1], 10, 0)
if err != nil {
return false
}
if !strings.Contains(transport, "tcp") {
transport = "quic"
} else {
transport = "tcp"
}
req := &ReachabilityRequest{
Port: uint16(port),
Type: transport,
}
b, err := json.Marshal(req)
if err != nil {
return false
}
resp, err := http.Post(
"https://rpc.quilibrium.com/connectivity-check",
"application/json",
bytes.NewBuffer(b),
)
if err != nil {
fmt.Println("Reachability check not currently available, skipping test.")
return true
}
defer resp.Body.Close()
if resp.StatusCode != 200 {
fmt.Println("Reachability check not currently available, skipping test.")
return true
}
bodyBytes, err := io.ReadAll(resp.Body)
if err != nil {
fmt.Println("Reachability check not currently available, skipping test.")
return true
}
r := &ReachabilityResponse{}
err = json.Unmarshal(bodyBytes, r)
if err != nil {
fmt.Println("Reachability check not currently available, skipping test.")
return true
}
if r.Error != "" {
fmt.Println("Reachability check failed: " + r.Error)
return false
}
fmt.Println("Node passed reachability check.")
return true
}
func discoverPeers( func discoverPeers(
p2pConfig *config.P2PConfig, p2pConfig *config.P2PConfig,
ctx context.Context, ctx context.Context,
@ -691,6 +795,7 @@ func discoverPeers(
) )
if err != nil { if err != nil {
logger.Error("could not find peers", zap.Error(err)) logger.Error("could not find peers", zap.Error(err))
return
} }
for peer := range peerChan { for peer := range peerChan {
@ -714,6 +819,9 @@ func discoverPeers(
"connected to peer", "connected to peer",
zap.String("peer_id", peer.ID.String()), zap.String("peer_id", peer.ID.String()),
) )
if len(h.Network().Peers()) >= 6 {
break
}
} }
} }
} }
@ -722,8 +830,8 @@ func discoverPeers(
go func() { go func() {
for { for {
time.Sleep(5 * time.Minute) time.Sleep(5 * time.Second)
if len(h.Network().Peers()) < 16 { if len(h.Network().Peers()) < 6 {
discover() discover()
} }
} }