diff --git a/app/protocol/flowcontext/errors.go b/app/protocol/flowcontext/errors.go index 0b1deafc1..8445fdae0 100644 --- a/app/protocol/flowcontext/errors.go +++ b/app/protocol/flowcontext/errors.go @@ -22,7 +22,7 @@ func (*FlowContext) HandleError(err error, flowName string, isStopping *uint32, panic(err) } - log.Errorf("error from %s: %+v", flowName, err) + log.Errorf("error from %s: %s", flowName, err) } if atomic.AddUint32(isStopping, 1) == 1 { diff --git a/app/protocol/flows/handshake/receiveversion.go b/app/protocol/flows/handshake/receiveversion.go index fc2c5a87b..7cd3eb70b 100644 --- a/app/protocol/flows/handshake/receiveversion.go +++ b/app/protocol/flows/handshake/receiveversion.go @@ -60,7 +60,7 @@ func (flow *receiveVersionFlow) start() (*appmessage.NetAddress, error) { } if !allowSelfConnections && flow.NetAdapter().ID().IsEqual(msgVersion.ID) { - return nil, protocolerrors.New(true, "connected to self") + return nil, protocolerrors.New(false, "connected to self") } // Disconnect and ban peers from a different network diff --git a/app/protocol/flows/testing/handle_relay_invs_test.go b/app/protocol/flows/testing/handle_relay_invs_test.go index 0a84c484f..7e506e6bd 100644 --- a/app/protocol/flows/testing/handle_relay_invs_test.go +++ b/app/protocol/flows/testing/handle_relay_invs_test.go @@ -1421,7 +1421,7 @@ func TestHandleRelayInvs(t *testing.T) { if !test.expectsIBDToFinish { t.Fatalf("IBD unexpecetedly finished") } - case <-time.After(time.Second): + case <-time.After(10 * time.Second): if test.expectsIBDToFinish { t.Fatalf("IBD didn't finished after %d", time.Second) } @@ -1436,7 +1436,7 @@ func TestHandleRelayInvs(t *testing.T) { if !errors.Is(err, router.ErrRouteClosed) { t.Fatalf("unexpected error %+v", err) } - case <-time.After(time.Second): + case <-time.After(10 * time.Second): t.Fatalf("waiting for flow to finish timed out after %s", time.Second) } } diff --git a/app/protocol/protocol.go b/app/protocol/protocol.go index 2678aff5d..605586db1 100644 --- a/app/protocol/protocol.go +++ b/app/protocol/protocol.go @@ -78,11 +78,7 @@ func (m *Manager) handleError(err error, netConnection *netadapter.NetConnection if !m.context.Config().DisableBanning && protocolErr.ShouldBan { log.Warnf("Banning %s (reason: %s)", netConnection, protocolErr.Cause) - err := m.context.ConnectionManager().Ban(netConnection) - if err != nil && !errors.Is(err, addressmanager.ErrAddressNotFound) { - panic(err) - } - + m.context.ConnectionManager().Ban(netConnection) err = outgoingRoute.Enqueue(appmessage.NewMsgReject(protocolErr.Error())) if err != nil && !errors.Is(err, routerpkg.ErrRouteClosed) { panic(err) diff --git a/domain/consensus/finality_test.go b/domain/consensus/finality_test.go index ff1547e59..80a8fc3c0 100644 --- a/domain/consensus/finality_test.go +++ b/domain/consensus/finality_test.go @@ -232,12 +232,12 @@ func TestBoundedMergeDepth(t *testing.T) { } factory := NewFactory() - consensusBuild, teardownFunc1, err := factory.NewTestConsensus(params, false, "BoundedMergeTestBuild") + consensusBuild, teardownFunc1, err := factory.NewTestConsensus(params, false, "TestBoundedMergeTestBuild") if err != nil { t.Fatalf("TestBoundedMergeDepth: Error setting up consensus: %+v", err) } - consensusReal, teardownFunc2, err := factory.NewTestConsensus(params, false, "BoundedMergeTestReal") + consensusReal, teardownFunc2, err := factory.NewTestConsensus(params, false, "TestBoundedMergeTestReal") if err != nil { t.Fatalf("TestBoundedMergeDepth: Error setting up consensus: %+v", err) } diff --git a/domain/consensus/processes/blockvalidator/block_header_in_context.go b/domain/consensus/processes/blockvalidator/block_header_in_context.go index 3ce16882f..ca595693c 100644 --- a/domain/consensus/processes/blockvalidator/block_header_in_context.go +++ b/domain/consensus/processes/blockvalidator/block_header_in_context.go @@ -1,6 +1,8 @@ package blockvalidator import ( + "fmt" + "github.com/kaspanet/kaspad/domain/consensus/model" "github.com/kaspanet/kaspad/domain/consensus/model/externalapi" "github.com/kaspanet/kaspad/domain/consensus/ruleerrors" "github.com/kaspanet/kaspad/domain/consensus/utils/consensushashing" @@ -29,6 +31,21 @@ func (v *blockValidator) ValidateHeaderInContext(blockHash *externalapi.DomainHa if err != nil { return err } + + var logErr error + log.Debug(logger.NewLogClosure(func() string { + var ghostdagData *model.BlockGHOSTDAGData + ghostdagData, logErr = v.ghostdagDataStore.Get(v.databaseContext, blockHash) + if err != nil { + return "" + } + + return fmt.Sprintf("block %s blue score is %d", blockHash, ghostdagData.BlueScore()) + })) + + if logErr != nil { + return logErr + } } err = v.validateMedianTime(header) diff --git a/infrastructure/network/addressmanager/addressmanager.go b/infrastructure/network/addressmanager/addressmanager.go index 4371cc20c..adfe8f887 100644 --- a/infrastructure/network/addressmanager/addressmanager.go +++ b/infrastructure/network/addressmanager/addressmanager.go @@ -12,16 +12,22 @@ import ( "github.com/pkg/errors" ) -// AddressRandomizer is the interface for the randomizer needed for the AddressManager. -type AddressRandomizer interface { +// addressRandomizer is the interface for the randomizer needed for the AddressManager. +type addressRandomizer interface { RandomAddress(addresses []*appmessage.NetAddress) *appmessage.NetAddress RandomAddresses(addresses []*appmessage.NetAddress, count int) []*appmessage.NetAddress } -// AddressKey represents a pair of IP and port, the IP is always in V6 representation -type AddressKey struct { +// addressKey represents a pair of IP and port, the IP is always in V6 representation +type addressKey struct { port uint16 - address [net.IPv6len]byte + address ipv6 +} + +type ipv6 [net.IPv6len]byte + +func (i ipv6) equal(other ipv6) bool { + return i == other } // ErrAddressNotFound is an error returned from some functions when a @@ -29,16 +35,16 @@ type AddressKey struct { var ErrAddressNotFound = errors.New("address not found") // NetAddressKey returns a key of the ip address to use it in maps. -func netAddressKey(netAddress *appmessage.NetAddress) AddressKey { - key := AddressKey{port: netAddress.Port} +func netAddressKey(netAddress *appmessage.NetAddress) addressKey { + key := addressKey{port: netAddress.Port} // all IPv4 can be represented as IPv6. copy(key.address[:], netAddress.IP.To16()) return key } // netAddressKeys returns a key of the ip address to use it in maps. -func netAddressesKeys(netAddresses []*appmessage.NetAddress) map[AddressKey]bool { - result := make(map[AddressKey]bool, len(netAddresses)) +func netAddressesKeys(netAddresses []*appmessage.NetAddress) map[addressKey]bool { + result := make(map[addressKey]bool, len(netAddresses)) for _, netAddress := range netAddresses { key := netAddressKey(netAddress) result[key] = true @@ -50,12 +56,12 @@ func netAddressesKeys(netAddresses []*appmessage.NetAddress) map[AddressKey]bool // AddressManager provides a concurrency safe address manager for caching potential // peers on the Kaspa network. type AddressManager struct { - addresses map[AddressKey]*appmessage.NetAddress - bannedAddresses map[AddressKey]*appmessage.NetAddress + addresses map[addressKey]*appmessage.NetAddress + bannedAddresses map[ipv6]*appmessage.NetAddress localAddresses *localAddressManager mutex sync.Mutex cfg *Config - random AddressRandomizer + random addressRandomizer } // New returns a new Kaspa address manager. @@ -66,8 +72,8 @@ func New(cfg *Config) (*AddressManager, error) { } return &AddressManager{ - addresses: map[AddressKey]*appmessage.NetAddress{}, - bannedAddresses: map[AddressKey]*appmessage.NetAddress{}, + addresses: map[addressKey]*appmessage.NetAddress{}, + bannedAddresses: map[ipv6]*appmessage.NetAddress{}, localAddresses: localAddresses, random: NewAddressRandomize(), cfg: cfg, @@ -111,7 +117,6 @@ func (am *AddressManager) RemoveAddress(address *appmessage.NetAddress) { key := netAddressKey(address) delete(am.addresses, key) - delete(am.bannedAddresses, key) } // Addresses returns all addresses @@ -175,21 +180,23 @@ func (am *AddressManager) BestLocalAddress(remoteAddress *appmessage.NetAddress) } // Ban marks the given address as banned -func (am *AddressManager) Ban(address *appmessage.NetAddress) error { +func (am *AddressManager) Ban(addressToBan *appmessage.NetAddress) { am.mutex.Lock() defer am.mutex.Unlock() - key := netAddressKey(address) - addressToBan, ok := am.addresses[key] - if !ok { - return errors.Wrapf(ErrAddressNotFound, "address %s "+ - "is not registered with the address manager", address.TCPAddress()) + keyToBan := netAddressKey(addressToBan) + keysToDelete := make([]addressKey, 0) + for _, address := range am.addresses { + key := netAddressKey(address) + if key.address.equal(keyToBan.address) { + keysToDelete = append(keysToDelete, key) + } + } + for _, key := range keysToDelete { + delete(am.addresses, key) } - delete(am.addresses, key) - am.bannedAddresses[key] = addressToBan - return nil - + am.bannedAddresses[keyToBan.address] = addressToBan } // Unban unmarks the given address as banned @@ -198,13 +205,13 @@ func (am *AddressManager) Unban(address *appmessage.NetAddress) error { defer am.mutex.Unlock() key := netAddressKey(address) - bannedAddress, ok := am.bannedAddresses[key] + bannedAddress, ok := am.bannedAddresses[key.address] if !ok { return errors.Wrapf(ErrAddressNotFound, "address %s "+ "is not registered with the address manager as banned", address.TCPAddress()) } - delete(am.bannedAddresses, key) + delete(am.bannedAddresses, key.address) am.addresses[key] = bannedAddress return nil } @@ -215,7 +222,7 @@ func (am *AddressManager) IsBanned(address *appmessage.NetAddress) (bool, error) defer am.mutex.Unlock() key := netAddressKey(address) - if _, ok := am.bannedAddresses[key]; !ok { + if _, ok := am.bannedAddresses[key.address]; !ok { if _, ok = am.addresses[key]; !ok { return false, errors.Wrapf(ErrAddressNotFound, "address %s "+ "is not registered with the address manager", address.TCPAddress()) diff --git a/infrastructure/network/addressmanager/addressrandomize.go b/infrastructure/network/addressmanager/addressrandomize.go index 03e17d26b..d27f9847f 100644 --- a/infrastructure/network/addressmanager/addressrandomize.go +++ b/infrastructure/network/addressmanager/addressrandomize.go @@ -7,7 +7,7 @@ import ( "github.com/kaspanet/kaspad/app/appmessage" ) -// AddressRandomize implement AddressRandomizer interface +// AddressRandomize implement addressRandomizer interface type AddressRandomize struct { random *rand.Rand } diff --git a/infrastructure/network/addressmanager/localaddressmanager.go b/infrastructure/network/addressmanager/localaddressmanager.go index d9274a432..8a06f64bc 100644 --- a/infrastructure/network/addressmanager/localaddressmanager.go +++ b/infrastructure/network/addressmanager/localaddressmanager.go @@ -38,7 +38,7 @@ type localAddress struct { } type localAddressManager struct { - localAddresses map[AddressKey]*localAddress + localAddresses map[addressKey]*localAddress lookupFunc func(string) ([]net.IP, error) cfg *Config mutex sync.Mutex @@ -46,7 +46,7 @@ type localAddressManager struct { func newLocalAddressManager(cfg *Config) (*localAddressManager, error) { localAddressManager := localAddressManager{ - localAddresses: map[AddressKey]*localAddress{}, + localAddresses: map[addressKey]*localAddress{}, cfg: cfg, lookupFunc: cfg.Lookup, } diff --git a/infrastructure/network/connmanager/connmanager.go b/infrastructure/network/connmanager/connmanager.go index eb3ec4f9d..8a5392049 100644 --- a/infrastructure/network/connmanager/connmanager.go +++ b/infrastructure/network/connmanager/connmanager.go @@ -126,12 +126,21 @@ func (c *ConnectionManager) ConnectionCount() int { } // Ban marks the given netConnection as banned -func (c *ConnectionManager) Ban(netConnection *netadapter.NetConnection) error { - return c.addressManager.Ban(netConnection.NetAddress()) +func (c *ConnectionManager) Ban(netConnection *netadapter.NetConnection) { + if c.isPermanent(netConnection.Address()) { + log.Infof("Cannot ban %s because it's a permanent connection", netConnection.Address()) + return + } + + c.addressManager.Ban(netConnection.NetAddress()) } // IsBanned returns whether the given netConnection is banned func (c *ConnectionManager) IsBanned(netConnection *netadapter.NetConnection) (bool, error) { + if c.isPermanent(netConnection.Address()) { + return false, nil + } + return c.addressManager.IsBanned(netConnection.NetAddress()) } @@ -159,3 +168,15 @@ func (c *ConnectionManager) connectionExists(addressString string) bool { return false } + +func (c *ConnectionManager) isPermanent(addressString string) bool { + if conn, ok := c.activeRequested[addressString]; ok { + return conn.isPermanent + } + + if conn, ok := c.pendingRequested[addressString]; ok { + return conn.isPermanent + } + + return false +}