From fb9d4ffd1b5d122c40f406875b2927611d1c2b22 Mon Sep 17 00:00:00 2001 From: pankcuf Date: Fri, 21 Jul 2023 17:56:09 +0700 Subject: [PATCH 01/19] fix: make peer handlers (ping/pong) --- .../Managers/Chain Managers/DSSporkManager.m | 14 +++--- DashSync/shared/Models/Network/DSPeer.h | 2 +- DashSync/shared/Models/Network/DSPeer.m | 49 +++++++++++-------- 3 files changed, 37 insertions(+), 28 deletions(-) diff --git a/DashSync/shared/Models/Managers/Chain Managers/DSSporkManager.m b/DashSync/shared/Models/Managers/Chain Managers/DSSporkManager.m index 15da1ffbb..b0b0f6768 100644 --- a/DashSync/shared/Models/Managers/Chain Managers/DSSporkManager.m +++ b/DashSync/shared/Models/Managers/Chain Managers/DSSporkManager.m @@ -171,12 +171,16 @@ - (void)peer:(DSPeer *_Nonnull)peer hasSporkHashes:(NSSet *_Nonnull)sporkHashes if (hasNew) [self getSporks]; } -- (void)peer:(DSPeer *)peer relayedSpork:(DSSpork *)spork { +- (void)peer:(DSPeer *)peer relayedSpork:(NSData *)message { + DSSpork *spork = [DSSpork sporkWithMessage:message onChain:self.chain]; + DSLog(@"received spork %u (%@) with message %@", spork.identifier, spork.identifierString, message.hexString); if (!spork.isValid) { [self.peerManager peerMisbehaving:peer errorMessage:@"Spork is not valid"]; return; } - self.lastSyncedSporks = [NSDate timeIntervalSince1970]; + @synchronized (self) { + self.lastSyncedSporks = [NSDate timeIntervalSince1970]; + } DSSpork *currentSpork = self.sporkDictionary[@(spork.identifier)]; BOOL updatedSpork = FALSE; __block NSMutableDictionary *dictionary = [[NSMutableDictionary alloc] init]; @@ -195,8 +199,7 @@ - (void)peer:(DSPeer *)peer relayedSpork:(DSSpork *)spork { [self setSporkValue:spork forKeyIdentifier:spork.identifier]; } if (!currentSpork || updatedSpork) { - [dictionary setObject:spork - forKey:@"new"]; + [dictionary setObject:spork forKey:@"new"]; [dictionary setObject:self.chain forKey:DSChainManagerNotificationChainKey]; [self.managedObjectContext performBlockAndWait:^{ @autoreleasepool { @@ -206,8 +209,7 @@ - (void)peer:(DSPeer *)peer relayedSpork:(DSSpork *)spork { if (!sporkEntity) { sporkEntity = [DSSporkEntity managedObjectInBlockedContext:self.managedObjectContext]; } - [sporkEntity setAttributesFromSpork:spork - withSporkHash:hashEntity]; // add new peers + [sporkEntity setAttributesFromSpork:spork withSporkHash:hashEntity]; // add new peers [self.managedObjectContext ds_save]; } else { DSLog(@"Spork was received that wasn't requested"); diff --git a/DashSync/shared/Models/Network/DSPeer.h b/DashSync/shared/Models/Network/DSPeer.h index f43063b80..db8421e13 100644 --- a/DashSync/shared/Models/Network/DSPeer.h +++ b/DashSync/shared/Models/Network/DSPeer.h @@ -235,7 +235,7 @@ typedef void (^MempoolCompletionBlock)(BOOL success, BOOL needed, BOOL interrupt @protocol DSPeerSporkDelegate @required -- (void)peer:(DSPeer *)peer relayedSpork:(DSSpork *)spork; +- (void)peer:(DSPeer *)peer relayedSpork:(NSData *)message; - (void)peer:(DSPeer *)peer hasSporkHashes:(NSSet *)sporkHashes; @end diff --git a/DashSync/shared/Models/Network/DSPeer.m b/DashSync/shared/Models/Network/DSPeer.m index caee03c48..3f0d3c041 100644 --- a/DashSync/shared/Models/Network/DSPeer.m +++ b/DashSync/shared/Models/Network/DSPeer.m @@ -124,6 +124,7 @@ @interface DSPeer () @property (nonatomic, assign) uint64_t receivedOrphanCount; @property (nonatomic, assign) NSTimeInterval mempoolRequestTime; @property (nonatomic, strong) dispatch_semaphore_t outputBufferSemaphore; +@property (nonatomic, strong) dispatch_queue_t handlersQueue; @end @@ -150,6 +151,7 @@ - (instancetype)initWithAddress:(UInt128)address andPort:(uint16_t)port onChain: _port = (port == 0) ? [chain standardPort] : port; self.chain = chain; _outputBufferSemaphore = dispatch_semaphore_create(1); + _handlersQueue = dispatch_queue_create("org.dash.dashsync.peerHandlers", DISPATCH_QUEUE_SERIAL); return self; } @@ -175,6 +177,7 @@ - (instancetype)initWithHost:(NSString *)host onChain:(DSChain *)chain { if (_port == 0) _port = chain.standardPort; self.chain = chain; _outputBufferSemaphore = dispatch_semaphore_create(1); + _handlersQueue = dispatch_queue_create("org.dash.dashsync.peerHandlers", DISPATCH_QUEUE_SERIAL); return self; } @@ -331,17 +334,18 @@ - (void)disconnectWithError:(NSError *)error { CFRunLoopStop([self.runLoop getCFRunLoop]); _status = DSPeerStatus_Disconnected; - dispatch_async(self.delegateQueue, ^{ + + dispatch_async(self.handlersQueue, ^{ [NSObject cancelPreviousPerformRequestsWithTarget:self]; - while (self.pongHandlers.count) { ((void (^)(BOOL))self.pongHandlers[0])(NO); [self.pongHandlers removeObjectAtIndex:0]; } - if (self.mempoolTransactionCompletion) self.mempoolTransactionCompletion(NO, YES, YES); self.mempoolTransactionCompletion = nil; - [self.peerDelegate peer:self disconnectedWithError:error]; + dispatch_async(self.delegateQueue, ^{ + [self.peerDelegate peer:self disconnectedWithError:error]; + }); }); } @@ -672,21 +676,18 @@ - (void)sendGetaddrMessage { } - (void)sendPingMessageWithPongHandler:(void (^)(BOOL success))pongHandler { - NSMutableData *msg = [NSMutableData data]; - - dispatch_async(self.delegateQueue, ^{ + dispatch_async(self.handlersQueue, ^{ if (!self.pongHandlers) self.pongHandlers = [NSMutableArray array]; - [self.pongHandlers addObject:(pongHandler) ? [pongHandler copy] : [^(BOOL success) { - } copy]]; - - [msg appendUInt64:self.localNonce]; + [self.pongHandlers addObject:(pongHandler) ? [pongHandler copy] : [^(BOOL success) {} copy]]; + uint64_t localNonce = self.localNonce; self.pingStartTime = [NSDate timeIntervalSince1970]; #if MESSAGE_LOGGING DSLog(@"%@:%u sending ping", self.host, self.port); #endif - - [self sendRequest:[DSPingRequest requestWithLocalNonce:self.localNonce]]; + dispatch_async(self.delegateQueue, ^{ + [self sendRequest:[DSPingRequest requestWithLocalNonce:localNonce]]; + }); }); } @@ -1594,8 +1595,14 @@ - (void)acceptPongMessage:(NSData *)message { [self error:@"pong message contained wrong nonce: %llu, expected: %llu", [message UInt64AtOffset:0], self.localNonce]; return; } else if (!self.pongHandlers.count) { - DSLog(@"%@:%u got unexpected pong", self.host, self.port); - return; + __block BOOL hasNoHandlers; + dispatch_sync(self.handlersQueue, ^{ + hasNoHandlers = ![self.pongHandlers count]; + }); + if (hasNoHandlers) { + DSLog(@"%@:%u got unexpected pong", self.host, self.port); + return; + } } if (self.pingStartTime > 1) { @@ -1609,11 +1616,13 @@ - (void)acceptPongMessage:(NSData *)message { #if MESSAGE_LOGGING DSLog(@"%@:%u got pong in %fs", self.host, self.port, self.pingTime); #endif - - dispatch_async(self.delegateQueue, ^{ + dispatch_async(self.handlersQueue, ^{ if (self->_status == DSPeerStatus_Connected && self.pongHandlers.count) { - ((void (^)(BOOL))self.pongHandlers[0])(YES); + void (^handler)(BOOL) = [self.pongHandlers objectAtIndex:0]; [self.pongHandlers removeObjectAtIndex:0]; + dispatch_async(self.delegateQueue, ^{ + handler(YES); + }); } }); } @@ -1724,9 +1733,7 @@ - (void)acceptFeeFilterMessage:(NSData *)message { // MARK: - accept Control - (void)acceptSporkMessage:(NSData *)message { - DSSpork *spork = [DSSpork sporkWithMessage:message onChain:self.chain]; - DSLog(@"received spork %u (%@) with message %@", spork.identifier, spork.identifierString, message.hexString); - [self.sporkDelegate peer:self relayedSpork:spork]; + [self.sporkDelegate peer:self relayedSpork:message]; } // MARK: - accept Masternode From 11a0d0856fc30ee30bbe72fb73767d121e41c03c Mon Sep 17 00:00:00 2001 From: pankcuf Date: Fri, 21 Jul 2023 17:56:48 +0700 Subject: [PATCH 02/19] fix: ping/pong continue --- DashSync/shared/Models/Network/DSPeer.m | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/DashSync/shared/Models/Network/DSPeer.m b/DashSync/shared/Models/Network/DSPeer.m index 3f0d3c041..483989916 100644 --- a/DashSync/shared/Models/Network/DSPeer.m +++ b/DashSync/shared/Models/Network/DSPeer.m @@ -1594,7 +1594,7 @@ - (void)acceptPongMessage:(NSData *)message { } else if ([message UInt64AtOffset:0] != self.localNonce) { [self error:@"pong message contained wrong nonce: %llu, expected: %llu", [message UInt64AtOffset:0], self.localNonce]; return; - } else if (!self.pongHandlers.count) { + } else { __block BOOL hasNoHandlers; dispatch_sync(self.handlersQueue, ^{ hasNoHandlers = ![self.pongHandlers count]; From 2bbece55f43c5c199820b8a1061811fd0162198c Mon Sep 17 00:00:00 2001 From: pankcuf Date: Fri, 21 Jul 2023 18:40:32 +0700 Subject: [PATCH 03/19] fix: all found thread-safety issues --- DashSync/shared/DashSync.m | 4 +- DashSync/shared/Models/Chain/DSChain.m | 356 ++++++++++-------- .../Managers/Chain Managers/DSChainManager.m | 20 +- .../Chain Managers/DSGovernanceSyncManager.m | 1 + .../Chain Managers/DSMasternodeManager.m | 51 ++- .../Managers/Chain Managers/DSPeerManager.h | 12 +- .../Managers/Chain Managers/DSPeerManager.m | 128 ++++--- .../Managers/Chain Managers/DSSporkManager.m | 6 +- .../Chain Managers/DSTransactionManager.m | 3 +- .../Masternode/DSMasternodeListService.m | 44 ++- .../Models/Masternode/DSMasternodeListStore.m | 60 +-- .../Masternode/DSQuorumRotationService.m | 22 +- DashSync/shared/Models/Network/DSPeer.m | 30 +- 13 files changed, 441 insertions(+), 296 deletions(-) diff --git a/DashSync/shared/DashSync.m b/DashSync/shared/DashSync.m index e3f8dfa89..e97d7c9a0 100644 --- a/DashSync/shared/DashSync.m +++ b/DashSync/shared/DashSync.m @@ -121,7 +121,7 @@ - (void)startSyncForChain:(DSChain *)chain { - (void)stopSyncAllChains { NSArray *chains = [[DSChainsManager sharedInstance] chains]; for (DSChain *chain in chains) { - [[[DSChainsManager sharedInstance] chainManagerForChain:chain].peerManager disconnect]; + [[[DSChainsManager sharedInstance] chainManagerForChain:chain].peerManager disconnect: DSDisconnectReason_ChainWipe]; } } @@ -136,7 +136,7 @@ - (void)wipePeerDataForChain:(DSChain *)chain inContext:(NSManagedObjectContext [self stopSyncForChain:chain]; [[[DSChainsManager sharedInstance] chainManagerForChain:chain].peerManager removeTrustedPeerHost]; - [[[DSChainsManager sharedInstance] chainManagerForChain:chain].peerManager clearPeers]; + [[[DSChainsManager sharedInstance] chainManagerForChain:chain].peerManager clearPeers:DSDisconnectReason_ChainWipe]; [context performBlockAndWait:^{ DSChainEntity *chainEntity = [chain chainEntityInContext:context]; [DSPeerEntity deletePeersForChainEntity:chainEntity]; diff --git a/DashSync/shared/Models/Chain/DSChain.m b/DashSync/shared/Models/Chain/DSChain.m index e9094b943..94e151d6c 100644 --- a/DashSync/shared/Models/Chain/DSChain.m +++ b/DashSync/shared/Models/Chain/DSChain.m @@ -414,47 +414,59 @@ - (KeyKind)activeBLSType { } - (NSDictionary *)syncBlocks { - return [self.mSyncBlocks copy]; + @synchronized (self.mSyncBlocks) { + return [self.mSyncBlocks copy]; + } } - (NSDictionary *)mainChainSyncBlocks { - NSMutableDictionary *mainChainSyncBlocks = [self.mSyncBlocks mutableCopy]; - [mainChainSyncBlocks removeObjectsForKeys:[[self forkChainsSyncBlocks] allKeys]]; - return mainChainSyncBlocks; + @synchronized (self.mSyncBlocks) { + NSMutableDictionary *mainChainSyncBlocks = [self.mSyncBlocks mutableCopy]; + [mainChainSyncBlocks removeObjectsForKeys:[[self forkChainsSyncBlocks] allKeys]]; + return mainChainSyncBlocks; + } } - (NSDictionary *)forkChainsSyncBlocks { - NSMutableDictionary *forkChainsSyncBlocks = [self.mSyncBlocks mutableCopy]; - DSBlock *b = self.lastSyncBlock; - NSUInteger count = 0; - while (b && b.height > 0) { - b = self.mSyncBlocks[b.prevBlockValue]; - [forkChainsSyncBlocks removeObjectForKey:uint256_obj(b.blockHash)]; - count++; + @synchronized (self.mSyncBlocks) { + NSMutableDictionary *forkChainsSyncBlocks = [self.mSyncBlocks mutableCopy]; + DSBlock *b = self.lastSyncBlock; + NSUInteger count = 0; + while (b && b.height > 0) { + b = self.mSyncBlocks[b.prevBlockValue]; + [forkChainsSyncBlocks removeObjectForKey:uint256_obj(b.blockHash)]; + count++; + } + return forkChainsSyncBlocks; } - return forkChainsSyncBlocks; } - (NSDictionary *)terminalBlocks { - return [self.mTerminalBlocks copy]; + @synchronized (self.mTerminalBlocks) { + return [self.mTerminalBlocks copy]; + } } - (NSDictionary *)mainChainTerminalBlocks { - NSMutableDictionary *mainChainTerminalBlocks = [self.mTerminalBlocks mutableCopy]; - [mainChainTerminalBlocks removeObjectsForKeys:[[self forkChainsTerminalBlocks] allKeys]]; - return mainChainTerminalBlocks; + @synchronized (self.mTerminalBlocks) { + NSMutableDictionary *mainChainTerminalBlocks = [self.mTerminalBlocks mutableCopy]; + [mainChainTerminalBlocks removeObjectsForKeys:[[self forkChainsTerminalBlocks] allKeys]]; + return mainChainTerminalBlocks; + } } - (NSDictionary *)forkChainsTerminalBlocks { - NSMutableDictionary *forkChainsTerminalBlocks = [self.mTerminalBlocks mutableCopy]; - DSBlock *b = self.lastTerminalBlock; - NSUInteger count = 0; - while (b && b.height > 0) { - b = self.mTerminalBlocks[b.prevBlockValue]; - [forkChainsTerminalBlocks removeObjectForKey:uint256_obj(b.blockHash)]; - count++; + @synchronized (self.mTerminalBlocks) { + NSMutableDictionary *forkChainsTerminalBlocks = [self.mTerminalBlocks mutableCopy]; + DSBlock *b = self.lastTerminalBlock; + NSUInteger count = 0; + while (b && b.height > 0) { + b = self.mTerminalBlocks[b.prevBlockValue]; + [forkChainsTerminalBlocks removeObjectForKey:uint256_obj(b.blockHash)]; + count++; + } + return forkChainsTerminalBlocks; } - return forkChainsTerminalBlocks; } - (NSDictionary *)orphans { @@ -1566,10 +1578,12 @@ - (DSBlock *)lastSyncBlockWithUseCheckpoints:(BOOL)useCheckpoints { } - (NSMutableDictionary *)mSyncBlocks { - if (_mSyncBlocks.count > 0) { - if (!_checkpointsByHashDictionary) _checkpointsByHashDictionary = [NSMutableDictionary dictionary]; - if (!_checkpointsByHeightDictionary) _checkpointsByHeightDictionary = [NSMutableDictionary dictionary]; - return _mSyncBlocks; + @synchronized (_mSyncBlocks) { + if (_mSyncBlocks.count > 0) { + if (!_checkpointsByHashDictionary) _checkpointsByHashDictionary = [NSMutableDictionary dictionary]; + if (!_checkpointsByHeightDictionary) _checkpointsByHeightDictionary = [NSMutableDictionary dictionary]; + return _mSyncBlocks; + } } [self.chainManagedObjectContext performBlockAndWait:^{ @@ -1643,9 +1657,14 @@ - (NSMutableDictionary *)mSyncBlocks { - (DSBlock *_Nullable)blockForBlockHash:(UInt256)blockHash { - DSBlock *b = self.mSyncBlocks[uint256_obj(blockHash)]; + DSBlock *b; + @synchronized (self.mSyncBlocks) { + b = self.mSyncBlocks[uint256_obj(blockHash)]; + } if (b) return b; - b = self.mTerminalBlocks[uint256_obj(blockHash)]; + @synchronized (self.mTerminalBlocks) { + b = self.mTerminalBlocks[uint256_obj(blockHash)]; + } if (b) return b; if ([self allowInsightBlocksForVerification]) { return [self.insightVerifiedBlocksByHashDictionary objectForKey:uint256_data(blockHash)]; @@ -1777,7 +1796,9 @@ - (BOOL)addMinedFullBlock:(DSFullBlock *)block { [self setBlockHeight:block.height andTimestamp:txTime forTransactionHashes:txHashes]; if (block.height > self.estimatedBlockHeight) { - _bestEstimatedBlockHeight = block.height; + @synchronized (self) { + _bestEstimatedBlockHeight = block.height; + } [self saveBlockLocators]; [self saveTerminalBlocks]; @@ -1854,7 +1875,9 @@ - (BOOL)addBlock:(DSBlock *)block receivedAsHeader:(BOOL)isHeaderOnly fromPeer:( BOOL syncDone = NO; - block.height = prev.height + 1; + @synchronized (block) { + block.height = prev.height + 1; + } UInt256 target = setCompactLE(block.target); NSAssert(uint256_is_not_zero(prev.chainWork), @"previous block should have aggregate work set"); block.chainWork = uInt256AddLE(prev.chainWork, uInt256AddOneLE(uInt256DivideLE(uint256_inverse(target), uInt256AddOneLE(target)))); @@ -1944,9 +1967,10 @@ - (BOOL)addBlock:(DSBlock *)block receivedAsHeader:(BOOL)isHeaderOnly fromPeer:( BOOL onMainChain = FALSE; + uint32_t h = block.height; if ((phase == DSChainSyncPhase_ChainSync || phase == DSChainSyncPhase_Synced) && uint256_eq(block.prevBlock, self.lastSyncBlockHash)) { // new block extends sync chain - if ((block.height % 1000) == 0 || txHashes.count > 0 || block.height > peer.lastBlockHeight) { - DSLog(@"[%@: %@] + sync block at: %d: %@", self.name, peer.host ? peer.host : @"TEST", block.height, uint256_hex(block.blockHash)); + if ((block.height % 1000) == 0 || txHashes.count > 0 || h > peer.lastBlockHeight) { + DSLog(@"[%@: %@] + sync block at: %d: %@", self.name, peer.host ? peer.host : @"TEST", h, uint256_hex(block.blockHash)); } @synchronized(self.mSyncBlocks) { self.mSyncBlocks[blockHash] = block; @@ -1957,42 +1981,46 @@ - (BOOL)addBlock:(DSBlock *)block receivedAsHeader:(BOOL)isHeaderOnly fromPeer:( self.lastSyncBlock = block; if (!equivalentTerminalBlock && uint256_eq(block.prevBlock, self.lastTerminalBlock.blockHash)) { - if ((block.height % 1000) == 0 || txHashes.count > 0 || block.height > peer.lastBlockHeight) { - DSLog(@"[%@: %@] + terminal block (caught up) at: %d: %@", self.name, peer.host ? peer.host : @"TEST", block.height, uint256_hex(block.blockHash)); + if ((h % 1000) == 0 || txHashes.count > 0 || h > peer.lastBlockHeight) { + DSLog(@"[%@: %@] + terminal block (caught up) at: %d: %@", self.name, peer.host ? peer.host : @"TEST", h, uint256_hex(block.blockHash)); } @synchronized(self.mTerminalBlocks) { self.mTerminalBlocks[blockHash] = block; } self.lastTerminalBlock = block; } - if (peer) { - peer.currentBlockHeight = block.height; //might be download peer instead + @synchronized(peer) { + if (peer) { + peer.currentBlockHeight = h; //might be download peer instead + } } - if (block.height == self.estimatedBlockHeight) syncDone = YES; + if (h == self.estimatedBlockHeight) syncDone = YES; [self setBlockHeight:block.height andTimestamp:txTime forTransactionHashes:txHashes]; onMainChain = TRUE; - if ([self blockHeightHasCheckpoint:block.height] || - ((block.height % 1000 == 0) && (block.height + BLOCK_NO_FORK_DEPTH < self.lastTerminalBlockHeight) && !self.chainManager.masternodeManager.hasMasternodeListCurrentlyBeingSaved)) { + if ([self blockHeightHasCheckpoint:h] || + ((h % 1000 == 0) && (h + BLOCK_NO_FORK_DEPTH < self.lastTerminalBlockHeight) && !self.chainManager.masternodeManager.hasMasternodeListCurrentlyBeingSaved)) { [self saveBlockLocators]; } } else if (uint256_eq(block.prevBlock, self.lastTerminalBlock.blockHash)) { // new block extends terminal chain - if ((block.height % 500) == 0 || txHashes.count > 0 || block.height > peer.lastBlockHeight) { - DSLog(@"[%@: %@] + terminal block at: %d: %@", self.name, peer.host ? peer.host : @"TEST", block.height, uint256_hex(block.blockHash)); + if ((h % 500) == 0 || txHashes.count > 0 || h > peer.lastBlockHeight) { + DSLog(@"[%@: %@] + terminal block at: %d: %@", self.name, peer.host ? peer.host : @"TEST", h, uint256_hex(block.blockHash)); } @synchronized(self.mTerminalBlocks) { self.mTerminalBlocks[blockHash] = block; } self.lastTerminalBlock = block; - if (peer) { - peer.currentBlockHeight = block.height; //might be download peer instead + @synchronized(peer) { + if (peer) { + peer.currentBlockHeight = h; //might be download peer instead + } } - if (block.height == self.estimatedBlockHeight) syncDone = YES; + if (h == self.estimatedBlockHeight) syncDone = YES; onMainChain = TRUE; } else if ((phase == DSChainSyncPhase_ChainSync || phase == DSChainSyncPhase_Synced) && self.mSyncBlocks[blockHash] != nil) { // we already have the block (or at least the header) - if ((block.height % 1) == 0 || txHashes.count > 0 || block.height > peer.lastBlockHeight) { - DSLog(@"%@:%d relayed existing sync block at height %d", peer.host, peer.port, block.height); + if ((h % 1) == 0 || txHashes.count > 0 || h > peer.lastBlockHeight) { + DSLog(@"%@:%d relayed existing sync block at height %d", peer.host, peer.port, h); } @synchronized(self.mSyncBlocks) { @@ -2003,49 +2031,51 @@ - (BOOL)addBlock:(DSBlock *)block receivedAsHeader:(BOOL)isHeaderOnly fromPeer:( [block setChainLockedWithEquivalentBlock:equivalentTerminalBlock]; } - if (peer) { - peer.currentBlockHeight = block.height; //might be download peer instead + @synchronized(peer) { + if (peer) { + peer.currentBlockHeight = h; //might be download peer instead + } } - + DSBlock *b = self.lastSyncBlock; - while (b && b.height > block.height) b = self.mSyncBlocks[b.prevBlockValue]; // is block in main chain? + while (b && b.height > h) b = self.mSyncBlocks[b.prevBlockValue]; // is block in main chain? if (b != nil && uint256_eq(b.blockHash, block.blockHash)) { // if it's not on a fork, set block heights for its transactions - [self setBlockHeight:block.height andTimestamp:txTime forTransactionHashes:txHashes]; - if (block.height == self.lastSyncBlockHeight) self.lastSyncBlock = block; + [self setBlockHeight:h andTimestamp:txTime forTransactionHashes:txHashes]; + if (h == self.lastSyncBlockHeight) self.lastSyncBlock = block; } } else if (self.mTerminalBlocks[blockHash] != nil && (blockPosition & DSBlockPosition_Terminal)) { // we already have the block (or at least the header) - if ((block.height % 1) == 0 || txHashes.count > 0 || block.height > peer.lastBlockHeight) { - DSLog(@"%@:%d relayed existing terminal block at height %d (last sync height %d)", peer.host, peer.port, block.height, self.lastSyncBlockHeight); + if ((h % 1) == 0 || txHashes.count > 0 || h > peer.lastBlockHeight) { + DSLog(@"%@:%d relayed existing terminal block at height %d (last sync height %d)", peer.host, peer.port, h, self.lastSyncBlockHeight); } @synchronized(self.mTerminalBlocks) { self.mTerminalBlocks[blockHash] = block; } - if (peer) { - peer.currentBlockHeight = block.height; //might be download peer instead + @synchronized(peer) { + if (peer) { + peer.currentBlockHeight = h; //might be download peer instead + } } - + DSBlock *b = self.lastTerminalBlock; - while (b && b.height > block.height) b = self.mTerminalBlocks[b.prevBlockValue]; // is block in main chain? + while (b && b.height > h) b = self.mTerminalBlocks[b.prevBlockValue]; // is block in main chain? if (b != nil && uint256_eq(b.blockHash, block.blockHash)) { // if it's not on a fork, set block heights for its transactions - [self setBlockHeight:block.height andTimestamp:txTime forTransactionHashes:txHashes]; - if (block.height == self.lastTerminalBlockHeight) self.lastTerminalBlock = block; + [self setBlockHeight:h andTimestamp:txTime forTransactionHashes:txHashes]; + if (h == self.lastTerminalBlockHeight) self.lastTerminalBlock = block; } } else { // new block is on a fork - if (block.height <= [self lastCheckpoint].height) { // fork is older than last checkpoint - DSLog(@"ignoring block on fork older than most recent checkpoint, fork height: %d, blockHash: %@", - block.height, blockHash); + if (h <= [self lastCheckpoint].height) { // fork is older than last checkpoint + DSLog(@"ignoring block on fork older than most recent checkpoint, fork height: %d, blockHash: %@", h, blockHash); return TRUE; } - if (block.height <= self.lastChainLock.height) { - DSLog(@"ignoring block on fork when main chain is chainlocked: %d, blockHash: %@", - block.height, blockHash); + if (h <= self.lastChainLock.height) { + DSLog(@"ignoring block on fork when main chain is chainlocked: %d, blockHash: %@", h, blockHash); return TRUE; } @@ -2066,17 +2096,19 @@ - (BOOL)addBlock:(DSBlock *)block receivedAsHeader:(BOOL)isHeaderOnly fromPeer:( } if (!uint256_eq(b.blockHash, b2.blockHash) && b2.chainLocked) { //intermediate chain locked block - DSLog(@"no reorganizing chain to height %d because of chainlock at height %d", block.height, b2.height); + DSLog(@"no reorganizing chain to height %d because of chainlock at height %d", h, b2.height); return TRUE; } - DSLog(@"reorganizing terminal chain from height %d, new height is %d", b.height, block.height); + DSLog(@"reorganizing terminal chain from height %d, new height is %d", b.height, h); self.lastTerminalBlock = block; - if (peer) { - peer.currentBlockHeight = block.height; //might be download peer instead + @synchronized(peer) { + if (peer) { + peer.currentBlockHeight = h; //might be download peer instead + } } - if (block.height == self.estimatedBlockHeight) syncDone = YES; + if (h == self.estimatedBlockHeight) syncDone = YES; } else { if (phase == DSChainSyncPhase_ChainSync || phase == DSChainSyncPhase_Synced) { @synchronized(self.mTerminalBlocks) { @@ -2093,7 +2125,7 @@ - (BOOL)addBlock:(DSBlock *)block receivedAsHeader:(BOOL)isHeaderOnly fromPeer:( } if (uint256_supeq(self.lastSyncBlock.chainWork, block.chainWork)) return TRUE; // if fork is shorter than main chain, ignore it for now - DSLog(@"found sync chain fork on height %d", block.height); + DSLog(@"found sync chain fork on height %d", h); if ((phase == DSChainSyncPhase_ChainSync || phase == DSChainSyncPhase_Synced) && !uint256_supeq(self.lastTerminalBlock.chainWork, block.chainWork)) { DSBlock *b = block, *b2 = self.lastTerminalBlock; @@ -2103,12 +2135,14 @@ - (BOOL)addBlock:(DSBlock *)block receivedAsHeader:(BOOL)isHeaderOnly fromPeer:( } if (!uint256_eq(b.blockHash, b2.blockHash) && b2.chainLocked) { //intermediate chain locked block - DSLog(@"no reorganizing chain to height %d because of chainlock at height %d", block.height, b2.height); + DSLog(@"no reorganizing chain to height %d because of chainlock at height %d", h, b2.height); } else { - DSLog(@"reorganizing terminal chain from height %d, new height is %d", b.height, block.height); + DSLog(@"reorganizing terminal chain from height %d, new height is %d", b.height, h); self.lastTerminalBlock = block; - if (peer) { - peer.currentBlockHeight = block.height; //might be download peer instead + @synchronized(peer) { + if (peer) { + peer.currentBlockHeight = h; //might be download peer instead + } } } } @@ -2121,11 +2155,11 @@ - (BOOL)addBlock:(DSBlock *)block receivedAsHeader:(BOOL)isHeaderOnly fromPeer:( } if (!uint256_eq(b.blockHash, b2.blockHash) && b2.chainLocked) { //intermediate chain locked block - DSLog(@"no reorganizing sync chain to height %d because of chainlock at height %d", block.height, b2.height); + DSLog(@"no reorganizing sync chain to height %d because of chainlock at height %d", h, b2.height); return TRUE; } - DSLog(@"reorganizing sync chain from height %d, new height is %d", b.height, block.height); + DSLog(@"reorganizing sync chain from height %d, new height is %d", b.height, h); NSMutableArray *txHashes = [NSMutableArray array]; // mark transactions after the join point as unconfirmed @@ -2136,9 +2170,7 @@ - (BOOL)addBlock:(DSBlock *)block receivedAsHeader:(BOOL)isHeaderOnly fromPeer:( } } - [self setBlockHeight:TX_UNCONFIRMED - andTimestamp:0 - forTransactionHashes:txHashes]; + [self setBlockHeight:TX_UNCONFIRMED andTimestamp:0 forTransactionHashes:txHashes]; b = block; while (b.height > b2.height) { // set transaction heights for new main chain @@ -2148,7 +2180,7 @@ - (BOOL)addBlock:(DSBlock *)block receivedAsHeader:(BOOL)isHeaderOnly fromPeer:( } self.lastSyncBlock = block; - if (block.height == self.estimatedBlockHeight) syncDone = YES; + if (h == self.estimatedBlockHeight) syncDone = YES; } } @@ -2183,7 +2215,9 @@ - (BOOL)addBlock:(DSBlock *)block receivedAsHeader:(BOOL)isHeaderOnly fromPeer:( } if (((blockPosition & DSBlockPosition_Terminal) && block.height > self.estimatedBlockHeight) || ((blockPosition & DSBlockPosition_Sync) && block.height >= self.lastTerminalBlockHeight)) { - _bestEstimatedBlockHeight = block.height; + @synchronized (self) { + _bestEstimatedBlockHeight = block.height; + } if (peer && (blockPosition & DSBlockPosition_Sync) && !savedBlockLocators) { [self saveBlockLocators]; } @@ -2255,63 +2289,66 @@ - (void)notifyBlocksChanged:(DSBlockPosition)blockPosition { // MARK: Terminal Blocks - (NSMutableDictionary *)mTerminalBlocks { - if (_mTerminalBlocks.count > 0) { - if (!_checkpointsByHashDictionary) _checkpointsByHashDictionary = [NSMutableDictionary dictionary]; - if (!_checkpointsByHeightDictionary) _checkpointsByHeightDictionary = [NSMutableDictionary dictionary]; - return _mTerminalBlocks; - } - - [self.chainManagedObjectContext performBlockAndWait:^{ - if (self->_mTerminalBlocks.count > 0) return; - self->_mTerminalBlocks = [NSMutableDictionary dictionary]; - self.checkpointsByHashDictionary = [NSMutableDictionary dictionary]; - self.checkpointsByHeightDictionary = [NSMutableDictionary dictionary]; - for (DSCheckpoint *checkpoint in self.checkpoints) { // add checkpoints to the block collection - UInt256 checkpointHash = checkpoint.blockHash; - - self->_mTerminalBlocks[uint256_obj(checkpointHash)] = [[DSBlock alloc] initWithCheckpoint:checkpoint onChain:self]; - self.checkpointsByHeightDictionary[@(checkpoint.height)] = checkpoint; - self.checkpointsByHashDictionary[uint256_data(checkpointHash)] = checkpoint; - } - for (DSMerkleBlockEntity *e in [DSMerkleBlockEntity lastTerminalBlocks:KEEP_RECENT_TERMINAL_BLOCKS onChainEntity:[self chainEntityInContext:self.chainManagedObjectContext]]) { - @autoreleasepool { - DSMerkleBlock *b = e.merkleBlock; + @synchronized (_mTerminalBlocks) { + if (_mTerminalBlocks.count > 0) { + if (!_checkpointsByHashDictionary) _checkpointsByHashDictionary = [NSMutableDictionary dictionary]; + if (!_checkpointsByHeightDictionary) _checkpointsByHeightDictionary = [NSMutableDictionary dictionary]; + return _mTerminalBlocks; + } + [self.chainManagedObjectContext performBlockAndWait:^{ + if (self->_mTerminalBlocks.count > 0) return; + self->_mTerminalBlocks = [NSMutableDictionary dictionary]; + self.checkpointsByHashDictionary = [NSMutableDictionary dictionary]; + self.checkpointsByHeightDictionary = [NSMutableDictionary dictionary]; + for (DSCheckpoint *checkpoint in self.checkpoints) { // add checkpoints to the block collection + UInt256 checkpointHash = checkpoint.blockHash; - if (b) self->_mTerminalBlocks[b.blockHashValue] = b; + self->_mTerminalBlocks[uint256_obj(checkpointHash)] = [[DSBlock alloc] initWithCheckpoint:checkpoint onChain:self]; + self.checkpointsByHeightDictionary[@(checkpoint.height)] = checkpoint; + self.checkpointsByHashDictionary[uint256_data(checkpointHash)] = checkpoint; } - }; - }]; - - return _mTerminalBlocks; + for (DSMerkleBlockEntity *e in [DSMerkleBlockEntity lastTerminalBlocks:KEEP_RECENT_TERMINAL_BLOCKS onChainEntity:[self chainEntityInContext:self.chainManagedObjectContext]]) { + @autoreleasepool { + DSMerkleBlock *b = e.merkleBlock; + + if (b) self->_mTerminalBlocks[b.blockHashValue] = b; + } + }; + }]; + + return _mTerminalBlocks; + } } - (DSBlock *)lastTerminalBlock { - if (_lastTerminalBlock) return _lastTerminalBlock; - - [self.chainManagedObjectContext performBlockAndWait:^{ - NSArray *lastTerminalBlocks = [DSMerkleBlockEntity lastTerminalBlocks:1 onChainEntity:[self chainEntityInContext:self.chainManagedObjectContext]]; - DSMerkleBlock *lastTerminalBlock = [[lastTerminalBlocks firstObject] merkleBlock]; - self->_lastTerminalBlock = lastTerminalBlock; - if (lastTerminalBlock) { - DSLog(@"last terminal block at height %d recovered from db (hash is %@)", lastTerminalBlock.height, [NSData dataWithUInt256:lastTerminalBlock.blockHash].hexString); - } - }]; - - if (!_lastTerminalBlock) { - // if we don't have any headers yet, use the latest checkpoint - DSCheckpoint *lastCheckpoint = self.terminalHeadersOverrideUseCheckpoint ? self.terminalHeadersOverrideUseCheckpoint : self.lastCheckpoint; - uint32_t lastSyncBlockHeight = self.lastSyncBlockHeight; + @synchronized (self) { + if (_lastTerminalBlock) return _lastTerminalBlock; - if (lastCheckpoint.height >= lastSyncBlockHeight) { - [self setLastTerminalBlockFromCheckpoints]; - } else { - _lastTerminalBlock = self.lastSyncBlock; + [self.chainManagedObjectContext performBlockAndWait:^{ + NSArray *lastTerminalBlocks = [DSMerkleBlockEntity lastTerminalBlocks:1 onChainEntity:[self chainEntityInContext:self.chainManagedObjectContext]]; + DSMerkleBlock *lastTerminalBlock = [[lastTerminalBlocks firstObject] merkleBlock]; + self->_lastTerminalBlock = lastTerminalBlock; + if (lastTerminalBlock) { + DSLog(@"last terminal block at height %d recovered from db (hash is %@)", lastTerminalBlock.height, [NSData dataWithUInt256:lastTerminalBlock.blockHash].hexString); + } + }]; + + if (!_lastTerminalBlock) { + // if we don't have any headers yet, use the latest checkpoint + DSCheckpoint *lastCheckpoint = self.terminalHeadersOverrideUseCheckpoint ? self.terminalHeadersOverrideUseCheckpoint : self.lastCheckpoint; + uint32_t lastSyncBlockHeight = self.lastSyncBlockHeight; + + if (lastCheckpoint.height >= lastSyncBlockHeight) { + [self setLastTerminalBlockFromCheckpoints]; + } else { + _lastTerminalBlock = self.lastSyncBlock; + } } + + if (_lastTerminalBlock.height > self.estimatedBlockHeight) _bestEstimatedBlockHeight = _lastTerminalBlock.height; + + return _lastTerminalBlock; } - - if (_lastTerminalBlock.height > self.estimatedBlockHeight) _bestEstimatedBlockHeight = _lastTerminalBlock.height; - - return _lastTerminalBlock; } - (NSArray *)terminalBlocksLocatorArray { @@ -2505,7 +2542,15 @@ - (NSTimeInterval)lastSyncBlockTimestamp { } - (uint32_t)lastSyncBlockHeight { - return _lastSyncBlock ? _lastSyncBlock.height : (self.lastPersistedChainSyncBlockHeight ? self.lastPersistedChainSyncBlockHeight : self.lastSyncBlock.height); + @synchronized (_lastSyncBlock) { + if (_lastSyncBlock) { + return _lastSyncBlock.height; + } else if (self.lastPersistedChainSyncBlockHeight) { + return self.lastPersistedChainSyncBlockHeight; + } else { + return self.lastSyncBlock.height; + } + } } - (UInt256)lastSyncBlockHash { @@ -2531,14 +2576,18 @@ - (uint32_t)quickHeightForBlockHash:(UInt256)blockhash { return checkpoint.height; } - DSBlock *syncBlock = [self.mSyncBlocks objectForKey:uint256_obj(blockhash)]; - if (syncBlock && (syncBlock.height != UINT32_MAX)) { - return syncBlock.height; + @synchronized (self.mSyncBlocks) { + DSBlock *syncBlock = [self.mSyncBlocks objectForKey:uint256_obj(blockhash)]; + if (syncBlock && (syncBlock.height != UINT32_MAX)) { + return syncBlock.height; + } } - DSBlock *terminalBlock = [self.mTerminalBlocks objectForKey:uint256_obj(blockhash)]; - if (terminalBlock && (terminalBlock.height != UINT32_MAX)) { - return terminalBlock.height; + @synchronized (self.mSyncBlocks) { + DSBlock *terminalBlock = [self.mTerminalBlocks objectForKey:uint256_obj(blockhash)]; + if (terminalBlock && (terminalBlock.height != UINT32_MAX)) { + return terminalBlock.height; + } } for (DSCheckpoint *checkpoint in self.checkpoints) { @@ -2555,15 +2604,18 @@ - (uint32_t)heightForBlockHash:(UInt256)blockhash { if (checkpoint) { return checkpoint.height; } - - DSBlock *syncBlock = [self.mSyncBlocks objectForKey:uint256_obj(blockhash)]; - if (syncBlock && (syncBlock.height != UINT32_MAX)) { - return syncBlock.height; + @synchronized (self.mSyncBlocks) { + DSBlock *syncBlock = [self.mSyncBlocks objectForKey:uint256_obj(blockhash)]; + if (syncBlock && (syncBlock.height != UINT32_MAX)) { + return syncBlock.height; + } } - DSBlock *terminalBlock = [self.mTerminalBlocks objectForKey:uint256_obj(blockhash)]; - if (terminalBlock && (terminalBlock.height != UINT32_MAX)) { - return terminalBlock.height; + @synchronized (self.mTerminalBlocks) { + DSBlock *terminalBlock = [self.mTerminalBlocks objectForKey:uint256_obj(blockhash)]; + if (terminalBlock && (terminalBlock.height != UINT32_MAX)) { + return terminalBlock.height; + } } DSBlock *b = self.lastTerminalBlock; @@ -2673,9 +2725,11 @@ - (void)reloadDerivationPaths { } - (uint32_t)estimatedBlockHeight { - if (_bestEstimatedBlockHeight) return _bestEstimatedBlockHeight; - _bestEstimatedBlockHeight = [self decideFromPeerSoftConsensusEstimatedBlockHeight]; - return _bestEstimatedBlockHeight; + @synchronized (self) { + if (_bestEstimatedBlockHeight) return _bestEstimatedBlockHeight; + _bestEstimatedBlockHeight = [self decideFromPeerSoftConsensusEstimatedBlockHeight]; + return _bestEstimatedBlockHeight; + } } - (uint32_t)decideFromPeerSoftConsensusEstimatedBlockHeight { diff --git a/DashSync/shared/Models/Managers/Chain Managers/DSChainManager.m b/DashSync/shared/Models/Managers/Chain Managers/DSChainManager.m index da0fede06..19fe4aabc 100644 --- a/DashSync/shared/Models/Managers/Chain Managers/DSChainManager.m +++ b/DashSync/shared/Models/Managers/Chain Managers/DSChainManager.m @@ -393,11 +393,15 @@ - (void)restartTerminalSyncStartHeight { } - (void)relayedNewItem { - self.lastChainRelayTime = [NSDate timeIntervalSince1970]; + dispatch_sync(dispatch_get_main_queue(), ^{ + self.lastChainRelayTime = [NSDate timeIntervalSince1970]; + }); } - (void)resetLastRelayedItemTime { - self.lastChainRelayTime = 0; + dispatch_sync(dispatch_get_main_queue(), ^{ + self.lastChainRelayTime = 0; + }); } // MARK: - Mining @@ -471,11 +475,12 @@ - (void)startSync { object:nil userInfo:@{DSChainManagerNotificationChainKey: self.chain}]; }); + DSLog(@"startSync -> peerManager::connect"); [self.peerManager connect]; } - (void)stopSync { - [self.peerManager disconnect]; + [self.peerManager disconnect:DSDisconnectReason_ChainSwitch]; self.syncPhase = DSChainSyncPhase_Offline; } @@ -497,6 +502,7 @@ - (void)disconnectedMasternodeListAndBlocksRescan { object:nil userInfo:@{DSChainManagerNotificationChainKey: self.chain}]; }); + DSLog(@"disconnectedMasternodeListAndBlocksRescan -> peerManager::connect"); [self.peerManager connect]; } @@ -510,6 +516,7 @@ - (void)disconnectedMasternodeListRescan { object:nil userInfo:@{DSChainManagerNotificationChainKey: self.chain}]; }); + DSLog(@"disconnectedMasternodeListRescan -> peerManager::connect"); [self.peerManager connect]; } @@ -523,6 +530,7 @@ - (void)disconnectedSyncBlocksRescan { object:nil userInfo:@{DSChainManagerNotificationChainKey: self.chain}]; }); + DSLog(@"disconnectedSyncBlocksRescan -> peerManager::connect"); [self.peerManager connect]; } @@ -650,7 +658,8 @@ - (void)chainShouldStartSyncingBlockchain:(DSChain *)chain onPeer:(DSPeer *)peer } - (void)chainFinishedSyncingInitialHeaders:(DSChain *)chain fromPeer:(DSPeer *)peer onMainChain:(BOOL)onMainChain { - if (onMainChain && peer && (peer == self.peerManager.downloadPeer)) self.lastChainRelayTime = [NSDate timeIntervalSince1970]; + if (onMainChain && peer && (peer == self.peerManager.downloadPeer)) [self relayedNewItem]; + [self.peerManager chainSyncStopped]; if (([[DSOptionsManager sharedInstance] syncType] & DSSyncType_MasternodeList)) { // make sure we care about masternode lists @@ -659,7 +668,7 @@ - (void)chainFinishedSyncingInitialHeaders:(DSChain *)chain fromPeer:(DSPeer *)p } - (void)chainFinishedSyncingTransactionsAndBlocks:(DSChain *)chain fromPeer:(DSPeer *)peer onMainChain:(BOOL)onMainChain { - if (onMainChain && peer && (peer == self.peerManager.downloadPeer)) self.lastChainRelayTime = [NSDate timeIntervalSince1970]; + if (onMainChain && peer && (peer == self.peerManager.downloadPeer)) [self relayedNewItem]; DSLog(@"chain finished syncing"); self.chainSyncStartHeight = 0; self.syncPhase = DSChainSyncPhase_Synced; @@ -678,6 +687,7 @@ - (void)syncBlockchain { if (self.syncPhase == DSChainSyncPhase_InitialTerminalBlocks) { self.syncPhase = DSChainSyncPhase_ChainSync; } + DSLog(@"syncBlockchain -> peerManager::connect"); [self.peerManager connect]; } else if (!self.peerManager.masternodeList && self.masternodeManager.currentMasternodeList) { [self.peerManager useMasternodeList:self.masternodeManager.currentMasternodeList withConnectivityNonce:self.sessionConnectivityNonce]; diff --git a/DashSync/shared/Models/Managers/Chain Managers/DSGovernanceSyncManager.m b/DashSync/shared/Models/Managers/Chain Managers/DSGovernanceSyncManager.m index a5098115f..3398b51c3 100644 --- a/DashSync/shared/Models/Managers/Chain Managers/DSGovernanceSyncManager.m +++ b/DashSync/shared/Models/Managers/Chain Managers/DSGovernanceSyncManager.m @@ -525,6 +525,7 @@ - (DSGovernanceVote *)peer:(DSPeer *_Nullable)peer requestedVote:(UInt256)voteHa - (void)peer:(DSPeer *)peer ignoredGovernanceSync:(DSGovernanceRequestState)governanceRequestState { [self.peerManager peerMisbehaving:peer errorMessage:@"Ignored Governance Sync"]; + DSLog(@"ignoredGovernanceSync -> peerManager::connect"); [self.peerManager connect]; } diff --git a/DashSync/shared/Models/Managers/Chain Managers/DSMasternodeManager.m b/DashSync/shared/Models/Managers/Chain Managers/DSMasternodeManager.m index 5fca43392..a1404c3f2 100644 --- a/DashSync/shared/Models/Managers/Chain Managers/DSMasternodeManager.m +++ b/DashSync/shared/Models/Managers/Chain Managers/DSMasternodeManager.m @@ -184,13 +184,15 @@ - (uint32_t)estimatedMasternodeListsToSync { } - (double)masternodeListAndQuorumsSyncProgress { - double amountLeft = self.masternodeListRetrievalQueueCount; - double maxAmount = self.masternodeListRetrievalQueueMaxAmount; - if (!amountLeft) { - return self.store.masternodeListsAndQuorumsIsSynced; + @synchronized (self) { + double amountLeft = self.masternodeListRetrievalQueueCount; + double maxAmount = self.masternodeListRetrievalQueueMaxAmount; + if (!amountLeft) { + return self.store.masternodeListsAndQuorumsIsSynced; + } + double progress = MAX(MIN((maxAmount - amountLeft) / maxAmount, 1), 0); + return progress; } - double progress = MAX(MIN((maxAmount - amountLeft) / maxAmount, 1), 0); - return progress; } - (BOOL)currentMasternodeListIsInLast24Hours { @@ -361,7 +363,9 @@ - (BOOL)requestMasternodeListForBlockHeight:(uint32_t)blockHeight error:(NSError - (BOOL)requestMasternodeListForBlockHash:(UInt256)blockHash { self.store.lastQueriedBlockHash = blockHash; NSData *blockHashData = uint256_data(blockHash); - [self.store.masternodeListQueriesNeedingQuorumsValidated addObject:blockHashData]; + @synchronized (self.store.masternodeListQueriesNeedingQuorumsValidated) { + [self.store.masternodeListQueriesNeedingQuorumsValidated addObject:blockHashData]; + } // this is safe [self getMasternodeListsForBlockHashes:[NSOrderedSet orderedSetWithObject:blockHashData]]; return TRUE; @@ -501,14 +505,21 @@ - (void)processMasternodeListDiffResult:(DSMnDiffProcessingResult *)result forPe DSLog(@"•••• processMasternodeListDiffResult: missingMasternodeLists: %@", [self logListSet:neededMissingMasternodeLists]); UInt256 masternodeListBlockHash = masternodeList.blockHash; NSData *masternodeListBlockHashData = uint256_data(masternodeListBlockHash); - if ([neededMissingMasternodeLists count] && [self.store.masternodeListQueriesNeedingQuorumsValidated containsObject:masternodeListBlockHashData]) { + BOOL hasAwaitingQuorumValidation; + @synchronized (self.store.masternodeListQueriesNeedingQuorumsValidated) { + hasAwaitingQuorumValidation = [self.store.masternodeListQueriesNeedingQuorumsValidated containsObject:masternodeListBlockHashData]; + } + + if ([neededMissingMasternodeLists count] && hasAwaitingQuorumValidation) { [self.masternodeListDiffService removeFromRetrievalQueue:masternodeListBlockHashData]; [self processMissingMasternodeLists:neededMissingMasternodeLists forMasternodeList:masternodeList]; completion(); } else { if (uint256_eq(self.store.lastQueriedBlockHash, masternodeListBlockHash)) { self.masternodeListDiffService.currentMasternodeList = masternodeList; - [self.store.masternodeListQueriesNeedingQuorumsValidated removeObject:masternodeListBlockHashData]; + @synchronized (self.store.masternodeListQueriesNeedingQuorumsValidated) { + [self.store.masternodeListQueriesNeedingQuorumsValidated removeObject:masternodeListBlockHashData]; + } } DSLog(@"••• updateStoreWithMasternodeList: %u: %@ (%@)", masternodeList.height, uint256_hex(masternodeListBlockHash), uint256_reverse_hex(masternodeListBlockHash)); [self updateStoreWithMasternodeList:masternodeList addedMasternodes:result.addedMasternodes modifiedMasternodes:result.modifiedMasternodes addedQuorums:result.addedQuorums completion:^(NSError *error) { @@ -579,33 +590,37 @@ - (void)processQRInfoResult:(DSQRInfoProcessingResult *)result forPeer:(DSPeer * NSData *blockHashDataAtH2C = uint256_data(blockHashAtH2C); NSData *blockHashDataAtH3C = uint256_data(blockHashAtH3C); NSData *blockHashDataAtH4C = uint256_data(blockHashAtH4C); + NSMutableSet *masternodeListQueriesNeedingQuorumsValidated; + @synchronized (self.store.masternodeListQueriesNeedingQuorumsValidated) { + masternodeListQueriesNeedingQuorumsValidated = self.store.masternodeListQueriesNeedingQuorumsValidated; + } if (![self.quorumRotationService shouldProcessDiffResult:mnListDiffResultAtH4C skipPresenceInRetrieval:YES]) { [self.quorumRotationService issueWithMasternodeListFromPeer:peer]; - } else if (![missingMasternodeListsAtH4C count] || ![self.store.masternodeListQueriesNeedingQuorumsValidated containsObject:blockHashDataAtH4C]) { + } else if (![missingMasternodeListsAtH4C count] || ![masternodeListQueriesNeedingQuorumsValidated containsObject:blockHashDataAtH4C]) { DSLog(@"••• updateStoreWithMasternodeList (h-4c): %u: %@ (%@)", masternodeListAtH4C.height, uint256_hex(blockHashAtH4C), uint256_reverse_hex(blockHashAtH4C)); [self updateStoreWithMasternodeList:masternodeListAtH4C addedMasternodes:mnListDiffResultAtH4C.addedMasternodes modifiedMasternodes:mnListDiffResultAtH4C.modifiedMasternodes addedQuorums:mnListDiffResultAtH4C.addedQuorums completion:^(NSError *error) {}]; } if (![self.quorumRotationService shouldProcessDiffResult:mnListDiffResultAtH3C skipPresenceInRetrieval:YES]) { [self.quorumRotationService issueWithMasternodeListFromPeer:peer]; - } else if (![missingMasternodeListsAtH3C count] || ![self.store.masternodeListQueriesNeedingQuorumsValidated containsObject:blockHashDataAtH3C]) { + } else if (![missingMasternodeListsAtH3C count] || ![masternodeListQueriesNeedingQuorumsValidated containsObject:blockHashDataAtH3C]) { DSLog(@"••• updateStoreWithMasternodeList (h-3c): %u: %@ (%@)", masternodeListAtH3C.height, uint256_hex(blockHashAtH3C), uint256_reverse_hex(blockHashAtH3C)); [self updateStoreWithMasternodeList:masternodeListAtH3C addedMasternodes:mnListDiffResultAtH3C.addedMasternodes modifiedMasternodes:mnListDiffResultAtH3C.modifiedMasternodes addedQuorums:mnListDiffResultAtH3C.addedQuorums completion:^(NSError *error) {}]; } if (![self.quorumRotationService shouldProcessDiffResult:mnListDiffResultAtH2C skipPresenceInRetrieval:YES]) { [self.quorumRotationService issueWithMasternodeListFromPeer:peer]; - } else if (![missingMasternodeListsAtH2C count] || ![self.store.masternodeListQueriesNeedingQuorumsValidated containsObject:blockHashDataAtH2C]) { + } else if (![missingMasternodeListsAtH2C count] || ![masternodeListQueriesNeedingQuorumsValidated containsObject:blockHashDataAtH2C]) { DSLog(@"••• updateStoreWithMasternodeList (h-2c): %u: %@ (%@)", masternodeListAtH2C.height, uint256_hex(blockHashAtH2C), uint256_reverse_hex(blockHashAtH2C)); [self updateStoreWithMasternodeList:masternodeListAtH2C addedMasternodes:mnListDiffResultAtH2C.addedMasternodes modifiedMasternodes:mnListDiffResultAtH2C.modifiedMasternodes addedQuorums:mnListDiffResultAtH2C.addedQuorums completion:^(NSError *error) {}]; } if (![self.quorumRotationService shouldProcessDiffResult:mnListDiffResultAtHC skipPresenceInRetrieval:YES]) { [self.quorumRotationService issueWithMasternodeListFromPeer:peer]; - } else if (![missingMasternodeListsAtHC count] || ![self.store.masternodeListQueriesNeedingQuorumsValidated containsObject:blockHashDataAtHC]) { + } else if (![missingMasternodeListsAtHC count] || ![masternodeListQueriesNeedingQuorumsValidated containsObject:blockHashDataAtHC]) { DSLog(@"••• updateStoreWithMasternodeList (h-c): %u: %@ (%@)", masternodeListAtHC.height, uint256_hex(blockHashAtHC), uint256_reverse_hex(blockHashAtHC)); [self updateStoreWithMasternodeList:masternodeListAtHC addedMasternodes:mnListDiffResultAtHC.addedMasternodes modifiedMasternodes:mnListDiffResultAtHC.modifiedMasternodes addedQuorums:mnListDiffResultAtHC.addedQuorums completion:^(NSError *error) {}]; } if (![self.quorumRotationService shouldProcessDiffResult:mnListDiffResultAtH skipPresenceInRetrieval:YES]) { [self.quorumRotationService issueWithMasternodeListFromPeer:peer]; - } else if (![missingMasternodeListsAtH count] || ![self.store.masternodeListQueriesNeedingQuorumsValidated containsObject:blockHashDataAtH]) { + } else if (![missingMasternodeListsAtH count] || ![masternodeListQueriesNeedingQuorumsValidated containsObject:blockHashDataAtH]) { DSLog(@"••• updateStoreWithMasternodeList (h): %u: %@ (%@)", masternodeListAtH.height, uint256_hex(blockHashAtH), uint256_reverse_hex(blockHashAtH)); [self updateStoreWithMasternodeList:masternodeListAtH addedMasternodes:mnListDiffResultAtH.addedMasternodes modifiedMasternodes:mnListDiffResultAtH.modifiedMasternodes addedQuorums:mnListDiffResultAtH.addedQuorums completion:^(NSError *error) {}]; } @@ -613,13 +628,15 @@ - (void)processQRInfoResult:(DSQRInfoProcessingResult *)result forPeer:(DSPeer * if (![self.quorumRotationService shouldProcessDiffResult:mnListDiffResultAtTip skipPresenceInRetrieval:YES]) { [self.quorumRotationService issueWithMasternodeListFromPeer:peer]; } else { - if ([missingMasternodeListsAtTip count] && [self.store.masternodeListQueriesNeedingQuorumsValidated containsObject:blockHashDataAtTip]) { + if ([missingMasternodeListsAtTip count] && [masternodeListQueriesNeedingQuorumsValidated containsObject:blockHashDataAtTip]) { [self.quorumRotationService removeFromRetrievalQueue:blockHashDataAtTip]; [self processMissingMasternodeLists:missingMasternodeLists forMasternodeList:masternodeListAtTip]; } else { if (uint256_eq(self.store.lastQueriedBlockHash, blockHashAtTip)) { self.quorumRotationService.currentMasternodeList = masternodeListAtTip; - [self.store.masternodeListQueriesNeedingQuorumsValidated removeObject:blockHashDataAtTip]; + @synchronized (self.store.masternodeListQueriesNeedingQuorumsValidated) { + [self.store.masternodeListQueriesNeedingQuorumsValidated removeObject:blockHashDataAtTip]; + } } DSLog(@"••• updateStoreWithMasternodeList (tip): %u: %@ (%@)", masternodeListAtTip.height, uint256_hex(blockHashAtTip), uint256_reverse_hex(blockHashAtTip)); [self updateStoreWithMasternodeList:masternodeListAtTip addedMasternodes:mnListDiffResultAtTip.addedMasternodes modifiedMasternodes:mnListDiffResultAtTip.modifiedMasternodes addedQuorums:mnListDiffResultAtTip.addedQuorums completion:^(NSError *error) {}]; @@ -639,7 +656,7 @@ - (void)processQRInfoResult:(DSQRInfoProcessingResult *)result forPeer:(DSPeer * NSData *diffBlockHashData = uint256_data(diffBlockHash); if (![self.quorumRotationService shouldProcessDiffResult:diffResult skipPresenceInRetrieval:YES]) { [self.quorumRotationService issueWithMasternodeListFromPeer:peer]; - } else if (![diffResult.neededMissingMasternodeLists count] || ![self.store.masternodeListQueriesNeedingQuorumsValidated containsObject:diffBlockHashData]) { + } else if (![diffResult.neededMissingMasternodeLists count] || ![masternodeListQueriesNeedingQuorumsValidated containsObject:diffBlockHashData]) { [self updateStoreWithMasternodeList:diffMasternodeList addedMasternodes:diffResult.addedMasternodes modifiedMasternodes:diffResult.modifiedMasternodes addedQuorums:diffResult.addedQuorums completion:^(NSError *error) {}]; } } diff --git a/DashSync/shared/Models/Managers/Chain Managers/DSPeerManager.h b/DashSync/shared/Models/Managers/Chain Managers/DSPeerManager.h index 58c24aeb8..174409623 100644 --- a/DashSync/shared/Models/Managers/Chain Managers/DSPeerManager.h +++ b/DashSync/shared/Models/Managers/Chain Managers/DSPeerManager.h @@ -56,6 +56,14 @@ FOUNDATION_EXPORT NSString *_Nonnull const DSPeerManagerFilterDidChangeNotificat UIAlertViewDelegate #endif > +typedef NS_ENUM(uint16_t, DSDisconnectReason) +{ + DSDisconnectReason_StartNewPhase = 0, + DSDisconnectReason_ChainWipe, + DSDisconnectReason_ChainSwitch, + DSDisconnectReason_TrustedPeerSet, + DSDisconnectReason_Error, +}; @property (nonatomic, readonly) BOOL connected; @property (nonatomic, readonly) NSUInteger peerCount; @@ -74,9 +82,9 @@ FOUNDATION_EXPORT NSString *_Nonnull const DSPeerManagerFilterDidChangeNotificat - (void)removeTrustedPeerHost; -- (void)clearPeers; +- (void)clearPeers:(DSDisconnectReason)reason; - (void)connect; -- (void)disconnect; +- (void)disconnect:(DSDisconnectReason)reason; - (void)clearRegisteredPeers; - (void)registerPeerAtLocation:(UInt128)IPAddress port:(uint32_t)port dapiJRPCPort:(uint32_t)dapiJRPCPort dapiGRPCPort:(uint32_t)dapiGRPCPort; diff --git a/DashSync/shared/Models/Managers/Chain Managers/DSPeerManager.m b/DashSync/shared/Models/Managers/Chain Managers/DSPeerManager.m index 1b2de112d..de3417d57 100644 --- a/DashSync/shared/Models/Managers/Chain Managers/DSPeerManager.m +++ b/DashSync/shared/Models/Managers/Chain Managers/DSPeerManager.m @@ -254,12 +254,12 @@ + (UInt128)ipAddressFromString:(NSString *)address { } - (void)removeTrustedPeerHost { - [self disconnect]; + [self disconnect:DSDisconnectReason_TrustedPeerSet]; [self setTrustedPeerHost:nil]; } -- (void)clearPeers { - [self disconnect]; +- (void)clearPeers:(DSDisconnectReason)reason { + [self disconnect:reason]; @synchronized(self) { _peers = nil; } @@ -431,6 +431,7 @@ - (void)peerMisbehaving:(DSPeer *)peer errorMessage:(NSString *)errorMessage { } [peer disconnectWithError:[NSError errorWithCode:500 localizedDescriptionKey:errorMessage]]; + DSLog(@"peerMisbehaving -> peerManager::connect"); [self connect]; } } @@ -551,8 +552,7 @@ - (void)setTrustedPeerHost:(NSString *_Nullable)host { if (!host) [[NSUserDefaults standardUserDefaults] removeObjectForKey:[self settingsFixedPeerKey]]; else - [[NSUserDefaults standardUserDefaults] setObject:host - forKey:[self settingsFixedPeerKey]]; + [[NSUserDefaults standardUserDefaults] setObject:host forKey:[self settingsFixedPeerKey]]; } // MARK: - Peer Registration @@ -566,6 +566,7 @@ - (void)resumeBlockchainSynchronizationOnPeers { if (self.downloadPeer) { [self updateFilterOnPeers]; } else { + DSLog(@"resumeBlockchainSynchronizationOnPeers -> peerManager::connect"); [self connect]; } } @@ -610,7 +611,7 @@ - (void)updateFilterOnPeers { // MARK: - Peer Registration - (void)clearRegisteredPeers { - [self clearPeers]; + [self clearPeers:DSDisconnectReason_ChainWipe]; setKeychainArray(@[], self.chain.registeredPeersKey, NO); } @@ -673,7 +674,7 @@ - (void)useMasternodeList:(DSMasternodeList *)masternodeList withConnectivityNon if (!_peers) { _peers = [NSMutableOrderedSet orderedSetWithArray:peers]; } else { - [self clearPeers]; + [self clearPeers:DSDisconnectReason_StartNewPhase]; _peers = [NSMutableOrderedSet orderedSetWithArray:peers]; [self.peers minusSet:self.misbehavingPeers]; } @@ -683,6 +684,7 @@ - (void)useMasternodeList:(DSMasternodeList *)masternodeList withConnectivityNon if (peers.count > 1 && peers.count < 1000) [self savePeers]; // peer relaying is complete when we receive <1000 if (connected) { + DSLog(@"useMasternodeList -> peerManager::connect"); [self connect]; } dispatch_async(dispatch_get_main_queue(), ^{ @@ -700,43 +702,55 @@ - (void)connect { dispatch_async(self.networkingQueue, ^{ if ([self.chain syncsBlockchain] && ![self.chain canConstructAFilter]) return; // check to make sure the wallet has been created if only are a basic wallet with no dash features if (self.connectFailures >= MAX_CONNECT_FAILURES) self.connectFailures = 0; // this attempt is a manual retry - - if (self.chainManager.terminalHeaderSyncProgress < 1.0) { - [self.chainManager resetTerminalSyncStartHeight]; -#if TARGET_OS_IOS - if (self.blockLocatorsSaveTaskId == UIBackgroundTaskInvalid) { // start a background task for the chain sync - self.blockLocatorsSaveTaskId = [[UIApplication sharedApplication] beginBackgroundTaskWithExpirationHandler:^{ - dispatch_async(self.networkingQueue, ^{ - [self.chain saveBlockLocators]; - }); - - [self chainSyncStopped]; - }]; + @synchronized (self.chainManager) { + if (self.chainManager.terminalHeaderSyncProgress < 1.0) { + [self.chainManager resetTerminalSyncStartHeight]; + #if TARGET_OS_IOS + if (self.blockLocatorsSaveTaskId == UIBackgroundTaskInvalid) { // start a background task for the chain sync + self.blockLocatorsSaveTaskId = [[UIApplication sharedApplication] beginBackgroundTaskWithExpirationHandler:^{ + dispatch_async(self.networkingQueue, ^{ + [self.chain saveBlockLocators]; + }); + + [self chainSyncStopped]; + }]; + } + #endif } -#endif - } - if (self.chainManager.chainSyncProgress < 1.0) { - [self.chainManager resetChainSyncStartHeight]; -#if TARGET_OS_IOS - if (self.terminalHeadersSaveTaskId == UIBackgroundTaskInvalid) { // start a background task for the chain sync - self.terminalHeadersSaveTaskId = [[UIApplication sharedApplication] beginBackgroundTaskWithExpirationHandler:^{ - dispatch_async(self.networkingQueue, ^{ - [self.chain saveTerminalBlocks]; - }); - - [self chainSyncStopped]; - }]; + if (self.chainManager.chainSyncProgress < 1.0) { + [self.chainManager resetChainSyncStartHeight]; + #if TARGET_OS_IOS + if (self.terminalHeadersSaveTaskId == UIBackgroundTaskInvalid) { // start a background task for the chain sync + self.terminalHeadersSaveTaskId = [[UIApplication sharedApplication] beginBackgroundTaskWithExpirationHandler:^{ + dispatch_async(self.networkingQueue, ^{ + [self.chain saveTerminalBlocks]; + }); + + [self chainSyncStopped]; + }]; + } + #endif } -#endif } - +// @synchronized(self.mutableConnectedPeers) { +// [self.mutableConnectedPeers minusSet:[self.connectedPeers objectsPassingTest:^BOOL(id obj, BOOL *stop) { +// return ([obj status] == DSPeerStatus_Disconnected) ? YES : NO; +// }]]; +// } @synchronized(self.mutableConnectedPeers) { - [self.mutableConnectedPeers minusSet:[self.connectedPeers objectsPassingTest:^BOOL(id obj, BOOL *stop) { - return ([obj status] == DSPeerStatus_Disconnected) ? YES : NO; - }]]; + NSMutableSet *disconnectedPeers = [NSMutableSet set]; + for (DSPeer *peer in self.mutableConnectedPeers) { + @synchronized(peer) { + if (peer.status == DSPeerStatus_Disconnected) { + [disconnectedPeers addObject:peer]; + } + } + } + [self.mutableConnectedPeers minusSet:disconnectedPeers]; } + self.fixedPeer = [self trustedPeerHost] ? [DSPeer peerWithHost:[self trustedPeerHost] onChain:self.chain] : nil; self.maxConnectCount = (self.fixedPeer) ? 1 : PEER_MAX_CONNECTIONS; if (self.connectedPeers.count >= self.maxConnectCount) return; // already connected to maxConnectCount peers @@ -781,11 +795,12 @@ - (void)connect { }); } -- (void)disconnect { +- (void)disconnect:(DSDisconnectReason)reason { self.desiredState = DSPeerManagerDesiredState_Disconnected; dispatch_async(self.networkingQueue, ^{ - for (DSPeer *peer in self.connectedPeers) { + if (reason != DSDisconnectReason_StartNewPhase) self.connectFailures = MAX_CONNECT_FAILURES; // prevent futher automatic reconnect attempts + for (DSPeer *peer in self.connectedPeers) { [peer disconnect]; } }); @@ -802,15 +817,18 @@ - (void)disconnectDownloadPeerForError:(NSError *)error withCompletion:(void (^_ } - (void)syncTimeout { - NSTimeInterval now = [NSDate timeIntervalSince1970]; - - if (now - self.chainManager.lastChainRelayTime < PROTOCOL_TIMEOUT) { // the download peer relayed something in time, so restart timer - [NSObject cancelPreviousPerformRequestsWithTarget:self selector:@selector(syncTimeout) object:nil]; - [self performSelector:@selector(syncTimeout) - withObject:nil - afterDelay:PROTOCOL_TIMEOUT - (now - self.chainManager.lastChainRelayTime)]; - return; + @synchronized (self.chainManager) { + NSTimeInterval now = [NSDate timeIntervalSince1970]; + NSTimeInterval delta = now - self.chainManager.lastChainRelayTime; + if (delta < PROTOCOL_TIMEOUT) { // the download peer relayed something in time, so restart timer + [NSObject cancelPreviousPerformRequestsWithTarget:self selector:@selector(syncTimeout) object:nil]; + [self performSelector:@selector(syncTimeout) + withObject:nil + afterDelay:PROTOCOL_TIMEOUT - delta]; + return; + } } + [self disconnectDownloadPeerForError:[NSError errorWithCode:500 descriptionKey:DSLocalizedString(@"Synchronization Timeout", @"An error message for notifying that chain sync has timed out")] withCompletion:nil]; } @@ -931,14 +949,18 @@ - (void)peerConnected:(DSPeer *)peer { [self.downloadPeer disconnect]; self.downloadPeer = bestPeer; - _connected = YES; + @synchronized (self) { + _connected = YES; + } if ([self.chain syncsBlockchain] && [self.chain canConstructAFilter]) { [bestPeer sendFilterloadMessage:[self.transactionManager transactionsBloomFilterForPeer:bestPeer].data]; } bestPeer.currentBlockHeight = self.chain.lastSyncBlockHeight; [self.chainManager assignSyncWeights]; - if ([self.chain syncsBlockchain] && ((self.chain.lastSyncBlockHeight != self.chain.lastTerminalBlockHeight) || (self.chain.lastSyncBlockHeight < bestPeer.lastBlockHeight))) { // start blockchain sync + if ([self.chain syncsBlockchain] && + ((self.chain.lastSyncBlockHeight != self.chain.lastTerminalBlockHeight) || + (self.chain.lastSyncBlockHeight < bestPeer.lastBlockHeight))) { // start blockchain sync [self.chainManager resetLastRelayedItemTime]; dispatch_async(dispatch_get_main_queue(), ^{ // setup a timer to detect if the sync stalls [NSObject cancelPreviousPerformRequestsWithTarget:self selector:@selector(syncTimeout) object:nil]; @@ -964,9 +986,10 @@ - (void)peerConnected:(DSPeer *)peer { - (void)peer:(DSPeer *)peer disconnectedWithError:(NSError *)error { DSLog(@"%@:%d disconnected%@%@", peer.host, peer.port, (error ? @", " : @""), (error ? error : @"")); - + BOOL banned = NO; if ([error.domain isEqual:@"DashSync"]) { //} && error.code != DASH_PEER_TIMEOUT_CODE) { [self peerMisbehaving:peer errorMessage:error.localizedDescription]; // if it's protocol error other than timeout, the peer isn't following the rules + banned = YES; } else if (error) { // timeout or some non-protocol related network error [self.peers removeObject:peer]; self.connectFailures++; @@ -981,7 +1004,7 @@ - (void)peer:(DSPeer *)peer disconnectedWithError:(NSError *)error { if (self.connectFailures > MAX_CONNECT_FAILURES) self.connectFailures = MAX_CONNECT_FAILURES; } - if (!self.connected && self.connectFailures == MAX_CONNECT_FAILURES) { + if (!self.connected && self.connectFailures >= MAX_CONNECT_FAILURES) { [self chainSyncStopped]; // clear out stored peers so we get a fresh list from DNS on next connect attempt @@ -1008,7 +1031,8 @@ - (void)peer:(DSPeer *)peer disconnectedWithError:(NSError *)error { #if TARGET_OS_IOS if ((self.desiredState == DSPeerManagerDesiredState_Connected) && (self.terminalHeadersSaveTaskId != UIBackgroundTaskInvalid || [UIApplication sharedApplication].applicationState != UIApplicationStateBackground)) { - [self connect]; // try connecting to another peer + DSLog(@"peer disconnectedWithError -> peerManager::connect"); + if (!banned) [self connect]; // try connecting to another peer } #else if (self.desiredState == DSPeerManagerDesiredState_Connected) { diff --git a/DashSync/shared/Models/Managers/Chain Managers/DSSporkManager.m b/DashSync/shared/Models/Managers/Chain Managers/DSSporkManager.m index b0b0f6768..5689e075f 100644 --- a/DashSync/shared/Models/Managers/Chain Managers/DSSporkManager.m +++ b/DashSync/shared/Models/Managers/Chain Managers/DSSporkManager.m @@ -94,7 +94,7 @@ - (BOOL)instantSendActive { - (BOOL)sporksUpdatedSignatures { DSSpork *updateSignatureSpork = self.sporkDictionary[@(DSSporkIdentifier_Spork6NewSigs)]; if (!updateSignatureSpork) return FALSE; //assume false - return updateSignatureSpork.value <= self.chain.lastTerminalBlockHeight; + return updateSignatureSpork.value <= self.chain.lastTerminalBlock.height; } - (BOOL)deterministicMasternodeListEnabled { @@ -122,7 +122,9 @@ - (BOOL)chainLocksEnabled { } - (NSDictionary *)sporkDictionary { - return [_mSporkDictionary copy]; + @synchronized (self) { + return [_mSporkDictionary copy]; + } } // MARK: - Spork Sync diff --git a/DashSync/shared/Models/Managers/Chain Managers/DSTransactionManager.m b/DashSync/shared/Models/Managers/Chain Managers/DSTransactionManager.m index ba2c5bb31..ba8e88aa7 100644 --- a/DashSync/shared/Models/Managers/Chain Managers/DSTransactionManager.m +++ b/DashSync/shared/Models/Managers/Chain Managers/DSTransactionManager.m @@ -70,6 +70,7 @@ #define MAX_TOTAL_TRANSACTIONS_FOR_BLOOM_FILTER_RETARGETING 500 #define SAVE_MAX_TRANSACTIONS_INFO (DEBUG && 0) +#define DEBUG_CHAIN_LOCKS_WAITING_FOR_QUORUMS (DEBUG && 0) @interface DSTransactionManager () @@ -1751,7 +1752,7 @@ - (void)checkChainLocksWaitingForQuorums { [[NSNotificationCenter defaultCenter] postNotificationName:DSChainBlockWasLockedNotification object:nil userInfo:@{DSChainManagerNotificationChainKey: self.chain, DSChainNotificationBlockKey: block}]; }); } else { -#if DEBUG +#if DEBUG_CHAIN_LOCKS_WAITING_FOR_QUORUMS DSMasternodeList *masternodeList = nil; DSQuorumEntry *quorum = [chainLock findSigningQuorumReturnMasternodeList:&masternodeList]; if (quorum && masternodeList) { diff --git a/DashSync/shared/Models/Masternode/DSMasternodeListService.m b/DashSync/shared/Models/Masternode/DSMasternodeListService.m index a4af718a9..e73f52698 100644 --- a/DashSync/shared/Models/Masternode/DSMasternodeListService.m +++ b/DashSync/shared/Models/Masternode/DSMasternodeListService.m @@ -56,18 +56,27 @@ - (instancetype)initWithChain:(DSChain *)chain store:(DSMasternodeListStore *)st } - (void)startTimeOutObserver { - __block NSSet *requestsInRetrieval = [self.requestsInRetrieval copy]; + __block NSSet *requestsInRetrieval; + @synchronized (self.requestsInRetrieval) { + requestsInRetrieval = [self.requestsInRetrieval copy]; + } __block NSUInteger masternodeListCount = [self.store knownMasternodeListsCount]; self.timeOutObserverTry++; __block uint16_t timeOutObserverTry = self.timeOutObserverTry; dispatch_time_t timeout = dispatch_time(DISPATCH_TIME_NOW, (int64_t)(20 * (self.timedOutAttempt + 1) * NSEC_PER_SEC)); dispatch_after(timeout, self.chain.networkingQueue, ^{ + if (!self.retrievalQueueMaxAmount || self.timeOutObserverTry != timeOutObserverTry) { return; } + __block NSSet *requestsInRetrieval2; + @synchronized (self.requestsInRetrieval) { + requestsInRetrieval2 = [self.requestsInRetrieval copy]; + } + // Removes from the receiving set each object that isn’t a member of another given set. NSMutableSet *leftToGet = [requestsInRetrieval mutableCopy]; - [leftToGet intersectSet:self.requestsInRetrieval]; + [leftToGet intersectSet:requestsInRetrieval2]; if ((masternodeListCount == [self.store knownMasternodeListsCount]) && [requestsInRetrieval isEqualToSet:leftToGet]) { DSLog(@"TimedOut"); @@ -101,7 +110,6 @@ - (void)composeMasternodeListRequest:(NSOrderedSet *)list { - (void)dequeueMasternodeListRequest { [self fetchMasternodeListsToRetrieve:^(NSOrderedSet *list) { -// NSLog(@"•••• dequeueMasternodeListRequest with list: (%@)", [self logListSet:list]); [self composeMasternodeListRequest:list]; [self startTimeOutObserver]; }]; @@ -258,7 +266,10 @@ - (NSUInteger)retrievalQueueCount { } - (void)updateMasternodeRetrievalQueue { - self.retrievalQueueMaxAmount = MAX(self.retrievalQueueMaxAmount, self.retrievalQueue.count); + NSUInteger currentCount = self.retrievalQueue.count; + dispatch_async(dispatch_get_main_queue(), ^{ + self.retrievalQueueMaxAmount = MAX(self.retrievalQueueMaxAmount, currentCount); + }); [self.retrievalQueue sortUsingComparator:^NSComparisonResult(NSData *_Nonnull obj1, NSData *_Nonnull obj2) { return [self.store heightForBlockHash:obj1.UInt256] < [self.store heightForBlockHash:obj2.UInt256] ? NSOrderedAscending : NSOrderedDescending; }]; @@ -299,16 +310,24 @@ - (DSMasternodeListRequest*__nullable)requestInRetrievalFor:(UInt256)baseBlockHa - (BOOL)removeRequestInRetrievalForBaseBlockHash:(UInt256)baseBlockHash blockHash:(UInt256)blockHash { DSMasternodeListRequest *matchedRequest = [self requestInRetrievalFor:baseBlockHash blockHash:blockHash]; if (!matchedRequest) { + #if DEBUG + NSSet *requestsInRetrieval; + @synchronized (self.requestsInRetrieval) { + requestsInRetrieval = [self.requestsInRetrieval copy]; + } NSMutableArray *requestsInRetrievalStrings = [NSMutableArray array]; - for (DSMasternodeListRequest *requestInRetrieval in [self.requestsInRetrieval copy]) { + for (DSMasternodeListRequest *requestInRetrieval in requestsInRetrieval) { [requestsInRetrievalStrings addObject:[requestInRetrieval logWithBlockHeightLookup:^uint32_t(UInt256 blockHash) { return [self.store heightForBlockHash:blockHash]; }]]; } - DSLog(@"•••• A masternode list (%u..%u %@ .. %@) was received that is not set to be retrieved (%@)", [self.store heightForBlockHash:baseBlockHash], [self.store heightForBlockHash:blockHash], uint256_hex(baseBlockHash), uint256_hex(blockHash), [requestsInRetrievalStrings componentsJoinedByString:@", "]); - return NO; - } - [self.requestsInRetrieval removeObject:matchedRequest]; + DSLog(@"•••• A masternode list (%@ .. %@) was received that is not set to be retrieved (%@)", uint256_hex(baseBlockHash), uint256_hex(blockHash), [requestsInRetrievalStrings componentsJoinedByString:@", "]); + #endif /* DEBUG */ + return NO; + } + @synchronized (self.requestsInRetrieval) { + [self.requestsInRetrieval removeObject:matchedRequest]; + } return YES; } @@ -337,8 +356,7 @@ - (void)issueWithMasternodeListFromPeer:(DSPeer *)peer { } else if (![faultyPeers containsObject:peer.location]) { faultyPeers = [faultyPeers arrayByAddingObject:peer.location]; } - [[NSUserDefaults standardUserDefaults] setObject:faultyPeers - forKey:CHAIN_FAULTY_DML_MASTERNODE_PEERS]; + [[NSUserDefaults standardUserDefaults] setObject:faultyPeers forKey:CHAIN_FAULTY_DML_MASTERNODE_PEERS]; [self dequeueMasternodeListRequest]; } dispatch_async(dispatch_get_main_queue(), ^{ @@ -349,7 +367,9 @@ - (void)issueWithMasternodeListFromPeer:(DSPeer *)peer { - (void)sendMasternodeListRequest:(DSMasternodeListRequest *)request { // DSLog(@"•••• sendMasternodeListRequest: %@", [request toData].hexString); [self.peerManager sendRequest:request]; - [self.requestsInRetrieval addObject:request]; + @synchronized (self.requestsInRetrieval) { + [self.requestsInRetrieval addObject:request]; + } } @end diff --git a/DashSync/shared/Models/Masternode/DSMasternodeListStore.m b/DashSync/shared/Models/Masternode/DSMasternodeListStore.m index 4e965dfdc..e2815ca3c 100644 --- a/DashSync/shared/Models/Masternode/DSMasternodeListStore.m +++ b/DashSync/shared/Models/Masternode/DSMasternodeListStore.m @@ -95,40 +95,54 @@ - (NSArray *)recentMasternodeLists { } - (NSUInteger)knownMasternodeListsCount { - NSMutableSet *masternodeListHashes = [NSMutableSet setWithArray:self.masternodeListsByBlockHash.allKeys]; - [masternodeListHashes addObjectsFromArray:[self.masternodeListsBlockHashStubs allObjects]]; - return [masternodeListHashes count]; + @synchronized (self.masternodeListsByBlockHash) { + @synchronized (self.masternodeListsBlockHashStubs) { + NSMutableSet *masternodeListHashes = [NSMutableSet setWithArray:self.masternodeListsByBlockHash.allKeys]; + [masternodeListHashes addObjectsFromArray:[self.masternodeListsBlockHashStubs allObjects]]; + return [masternodeListHashes count]; + } + } } - (uint32_t)earliestMasternodeListBlockHeight { uint32_t earliest = UINT32_MAX; - for (NSData *blockHash in [self.masternodeListsBlockHashStubs copy]) { - earliest = MIN(earliest, [self heightForBlockHash:blockHash.UInt256]); + @synchronized (self.masternodeListsBlockHashStubs) { + for (NSData *blockHash in self.masternodeListsBlockHashStubs) { + earliest = MIN(earliest, [self heightForBlockHash:blockHash.UInt256]); + } } - for (NSData *blockHash in [self.masternodeListsByBlockHash copy]) { - earliest = MIN(earliest, [self heightForBlockHash:blockHash.UInt256]); + @synchronized (self.masternodeListsByBlockHash) { + for (NSData *blockHash in self.masternodeListsByBlockHash) { + earliest = MIN(earliest, [self heightForBlockHash:blockHash.UInt256]); + } } return earliest; } - (uint32_t)lastMasternodeListBlockHeight { uint32_t last = 0; - for (NSData *blockHash in [self.masternodeListsBlockHashStubs copy]) { - last = MAX(last, [self heightForBlockHash:blockHash.UInt256]); + @synchronized (self.masternodeListsBlockHashStubs) { + for (NSData *blockHash in self.masternodeListsBlockHashStubs) { + last = MAX(last, [self heightForBlockHash:blockHash.UInt256]); + } } - for (NSData *blockHash in [self.masternodeListsByBlockHash copy]) { - last = MAX(last, [self heightForBlockHash:blockHash.UInt256]); + @synchronized (self.masternodeListsByBlockHash) { + for (NSData *blockHash in self.masternodeListsByBlockHash) { + last = MAX(last, [self heightForBlockHash:blockHash.UInt256]); + } } return last ? last : UINT32_MAX; } - (uint32_t)heightForBlockHash:(UInt256)blockhash { if (uint256_is_zero(blockhash)) return 0; - NSNumber *cachedHeightNumber = [self.cachedBlockHashHeights objectForKey:uint256_data(blockhash)]; - if (cachedHeightNumber) return [cachedHeightNumber intValue]; - uint32_t chainHeight = [self.chain heightForBlockHash:blockhash]; - if (chainHeight != UINT32_MAX) [self.cachedBlockHashHeights setObject:@(chainHeight) forKey:uint256_data(blockhash)]; - return chainHeight; + @synchronized (self.cachedBlockHashHeights) { + NSNumber *cachedHeightNumber = [self.cachedBlockHashHeights objectForKey:uint256_data(blockhash)]; + if (cachedHeightNumber) return [cachedHeightNumber intValue]; + uint32_t chainHeight = [self.chain heightForBlockHash:blockhash]; + if (chainHeight != UINT32_MAX) [self.cachedBlockHashHeights setObject:@(chainHeight) forKey:uint256_data(blockhash)]; + return chainHeight; + } } - (UInt256)closestKnownBlockHashForBlockHash:(UInt256)blockHash { @@ -259,9 +273,6 @@ - (DSMasternodeList *)loadMasternodeListsWithBlockHeightLookup:(BlockHeightFinde if ((i == masternodeListEntities.count - 1) || ((self.masternodeListsByBlockHash.count < 3) && (neededMasternodeListHeight >= masternodeListEntity.block.height))) { //either last one or there are less than 3 (we aim for 3) //we only need a few in memory as new quorums will mostly be verified against recent masternode lists DSMasternodeList *masternodeList = [masternodeListEntity masternodeListWithSimplifiedMasternodeEntryPool:[simplifiedMasternodeEntryPool copy] quorumEntryPool:quorumEntryPool withBlockHeightLookup:blockHeightLookup]; -// [masternodeList saveToJsonFileExtended:[NSString stringWithFormat:@"MNLIST_ext_%@_%@_%@.json", @(masternodeList.height), @([[NSDate date] timeIntervalSince1970]), @"loadMasternodeListsWithBlockHeightLookup"]]; - - DSLog(@"••• addMasternodeList (loadMasternodeListsWithBlockHeightLookup) -> %@: %@", uint256_hex(masternodeList.blockHash), masternodeList.debugDescription); [self.masternodeListsByBlockHash setObject:masternodeList forKey:uint256_data(masternodeList.blockHash)]; [self.cachedBlockHashHeights setObject:@(masternodeListEntity.block.height) forKey:uint256_data(masternodeList.blockHash)]; [simplifiedMasternodeEntryPool addEntriesFromDictionary:masternodeList.simplifiedMasternodeListDictionaryByReversedRegistrationTransactionHash]; @@ -407,10 +418,9 @@ - (void)saveMasternodeList:(DSMasternodeList *)masternodeList addedMasternodes:( } NSArray *updatedSimplifiedMasternodeEntries = [addedMasternodes.allValues arrayByAddingObjectsFromArray:modifiedMasternodes.allValues]; [self.chain updateAddressUsageOfSimplifiedMasternodeEntries:updatedSimplifiedMasternodeEntries]; - DSLog(@"••• addMasternodeList -> %@: %@", blockHashData.hexString, masternodeList); -// [masternodeList saveToJsonFileExtended:[NSString stringWithFormat:@"MNLIST_ext_%@_%@_%@.json", @(masternodeList.height), @([[NSDate date] timeIntervalSince1970]), @"saveMasternodeList"]]; - - [self.masternodeListsByBlockHash setObject:masternodeList forKey:blockHashData]; + @synchronized (self.masternodeListsByBlockHash) { + [self.masternodeListsByBlockHash setObject:masternodeList forKey:blockHashData]; + } [self notifyMasternodeListUpdate]; dispatch_group_enter(self.savingGroup); //We will want to create unknown blocks if they came from insight @@ -737,7 +747,9 @@ - (BOOL)addBlockToValidationQueue:(DSMerkleBlock *)merkleBlock { return NO; } self.lastQueriedBlockHash = merkleBlockHash; - [self.masternodeListQueriesNeedingQuorumsValidated addObject:merkleBlockHashData]; + @synchronized (self.masternodeListQueriesNeedingQuorumsValidated) { + [self.masternodeListQueriesNeedingQuorumsValidated addObject:merkleBlockHashData]; + } return YES; } diff --git a/DashSync/shared/Models/Masternode/DSQuorumRotationService.m b/DashSync/shared/Models/Masternode/DSQuorumRotationService.m index e4810a15d..cf0196604 100644 --- a/DashSync/shared/Models/Masternode/DSQuorumRotationService.m +++ b/DashSync/shared/Models/Masternode/DSQuorumRotationService.m @@ -103,31 +103,13 @@ - (void)requestQuorumRotationInfo:(UInt256)previousBlockHash forBlockHash:(UInt2 // blockHeight % dkgInterval == activeSigningQuorumsCount + 11 + 8 DSMasternodeListRequest *matchedRequest = [self requestInRetrievalFor:previousBlockHash blockHash:blockHash]; if (matchedRequest) { - NSLog(@"•••• qrinfo request with such a range already in retrieval: %u..%u %@ .. %@", [self.store heightForBlockHash:previousBlockHash], [self.store heightForBlockHash:blockHash], uint256_hex(previousBlockHash), uint256_hex(blockHash)); + DSLog(@"•••• qrinfo request with such a range already in retrieval: %@ .. %@", uint256_hex(previousBlockHash), uint256_hex(blockHash)); return; } NSArray *baseBlockHashes = @[[NSData dataWithUInt256:previousBlockHash]]; DSGetQRInfoRequest *request = [DSGetQRInfoRequest requestWithBaseBlockHashes:baseBlockHashes blockHash:blockHash extraShare:YES]; - NSLog(@"•••• requestQuorumRotationInfo: %u..%u %@ .. %@", [self.store heightForBlockHash:previousBlockHash], [self.store heightForBlockHash:blockHash], uint256_hex(previousBlockHash), uint256_hex(blockHash)); + DSLog(@"•••• requestQuorumRotationInfo: %@ .. %@", uint256_hex(previousBlockHash), uint256_hex(blockHash)); [self sendMasternodeListRequest:request]; } -- (void)requestQuorumRotationInfo2:(NSArray *)previousBlockHashes forBlockHash:(UInt256)blockHash { - // TODO: optimize qrinfo request queue (up to 4 blocks simultaneously, so we'd make masternodeListsToRetrieve.count%4) - // blockHeight % dkgInterval == activeSigningQuorumsCount + 11 + 8 -// DSMasternodeListRequest *matchedRequest = [self requestInRetrievalFor:previousBlockHash blockHash:blockHash]; -// if (matchedRequest) { -// NSLog(@"•••• qrinfo request with such a range already in retrieval: %u..%u %@ .. %@", self.blockHeightLookup(previousBlockHash), self.blockHeightLookup(blockHash), uint256_hex(previousBlockHash), uint256_hex(blockHash)); -// return; -// } -// NSArray *baseBlockHashes = @[[NSData dataWithUInt256:previousBlockHash]]; -// NSMutableSet *log = [NSMutableSet set]; - NSMutableString *log = [NSMutableString stringWithFormat:@""]; - for (NSData *baseBlockHashData in previousBlockHashes) { - [log appendString:[NSString stringWithFormat:@"%u, ", [self.store heightForBlockHash:baseBlockHashData.UInt256]]]; - } - DSGetQRInfoRequest *request = [DSGetQRInfoRequest requestWithBaseBlockHashes:previousBlockHashes blockHash:blockHash extraShare:YES]; - NSLog(@"•••• requestQuorumRotationInfo: %@: .. %d", log, [self.store heightForBlockHash:blockHash]); - [self sendMasternodeListRequest:request]; -} @end diff --git a/DashSync/shared/Models/Network/DSPeer.m b/DashSync/shared/Models/Network/DSPeer.m index 483989916..6a2e4dd05 100644 --- a/DashSync/shared/Models/Network/DSPeer.m +++ b/DashSync/shared/Models/Network/DSPeer.m @@ -221,7 +221,9 @@ - (NSString *)host { - (void)connect { if (self.status != DSPeerStatus_Disconnected) return; - _status = DSPeerStatus_Connecting; + @synchronized (self) { + _status = DSPeerStatus_Connecting; + } _pingTime = DBL_MAX; if (!self.reachability) self.reachability = [DSReachabilityManager sharedManager]; @@ -235,7 +237,9 @@ - (void)connect { queue:nil usingBlock:^(NSNotification *note) { if (self.reachabilityObserver && self.reachability.networkReachabilityStatus != DSReachabilityStatusNotReachable) { - self->_status = DSPeerStatus_Disconnected; + @synchronized (self) { + self->_status = DSPeerStatus_Disconnected; + } [self connect]; } }]; @@ -319,7 +323,9 @@ - (void)disconnectWithError:(NSError *)error { } [NSObject cancelPreviousPerformRequestsWithTarget:self]; // cancel connect timeout - _status = DSPeerStatus_Disconnected; + @synchronized (self) { + _status = DSPeerStatus_Disconnected; + } if (self.reachabilityObserver) { self.reachability = nil; @@ -333,7 +339,9 @@ - (void)disconnectWithError:(NSError *)error { CFRunLoopStop([self.runLoop getCFRunLoop]); - _status = DSPeerStatus_Disconnected; + @synchronized (self) { + _status = DSPeerStatus_Disconnected; + } dispatch_async(self.handlersQueue, ^{ [NSObject cancelPreviousPerformRequestsWithTarget:self]; @@ -362,7 +370,9 @@ - (void)didConnect { DSLog(@"%@:%u handshake completed %@", self.host, self.port, (self.peerDelegate.downloadPeer == self) ? @"(download peer)" : @""); [NSObject cancelPreviousPerformRequestsWithTarget:self]; // cancel pending handshake timeout - _status = DSPeerStatus_Connected; + @synchronized (self) { + _status = DSPeerStatus_Connected; + } dispatch_async(self.delegateQueue, ^{ if (self->_status == DSPeerStatus_Connected) [self.peerDelegate peerConnected:self]; @@ -1071,7 +1081,11 @@ - (void)acceptInvMessage:(NSData *)message { } } } - + uint32_t currentHeight; + @synchronized (self) { + currentHeight = self.currentBlockHeight; + } + if ([self.chain syncsBlockchain] && !self.sentFilter && !self.sentMempool && !self.sentGetblocks && (txHashes.count > 0) && !onlyPrivateSendTransactions) { [self error:@"got tx inv message before loading a filter"]; return; @@ -1079,8 +1093,8 @@ - (void)acceptInvMessage:(NSData *)message { DSLog(@"%@:%u too many transactions, disconnecting", self.host, self.port); [self disconnect]; // disconnecting seems to be the easiest way to mitigate it return; - } else if (self.currentBlockHeight > 0 && blockHashes.count > 2 && blockHashes.count < 500 && - self.currentBlockHeight + self.knownBlockHashes.count + blockHashes.count < self.lastBlockHeight) { + } else if (currentHeight > 0 && blockHashes.count > 2 && blockHashes.count < 500 && + currentHeight + self.knownBlockHashes.count + blockHashes.count < self.lastBlockHeight) { [self error:@"non-standard inv, %u is fewer block hashes than expected", (int)blockHashes.count]; return; } From d25ce515a59d448535e836dcaf9b66ae9b95eca5 Mon Sep 17 00:00:00 2001 From: pankcuf Date: Fri, 21 Jul 2023 20:57:04 +0700 Subject: [PATCH 04/19] fix: some more thread sync --- DashSync/shared/Models/Chain/DSChain.m | 15 +++++++++------ .../Managers/Chain Managers/DSChainManager.m | 6 ++---- .../Models/Masternode/DSMasternodeListStore.m | 6 +++++- 3 files changed, 16 insertions(+), 11 deletions(-) diff --git a/DashSync/shared/Models/Chain/DSChain.m b/DashSync/shared/Models/Chain/DSChain.m index 94e151d6c..63abddf09 100644 --- a/DashSync/shared/Models/Chain/DSChain.m +++ b/DashSync/shared/Models/Chain/DSChain.m @@ -2323,16 +2323,19 @@ - (NSMutableDictionary *)mTerminalBlocks { - (DSBlock *)lastTerminalBlock { @synchronized (self) { if (_lastTerminalBlock) return _lastTerminalBlock; - - [self.chainManagedObjectContext performBlockAndWait:^{ - NSArray *lastTerminalBlocks = [DSMerkleBlockEntity lastTerminalBlocks:1 onChainEntity:[self chainEntityInContext:self.chainManagedObjectContext]]; - DSMerkleBlock *lastTerminalBlock = [[lastTerminalBlocks firstObject] merkleBlock]; + } + [self.chainManagedObjectContext performBlockAndWait:^{ + NSArray *lastTerminalBlocks = [DSMerkleBlockEntity lastTerminalBlocks:1 onChainEntity:[self chainEntityInContext:self.chainManagedObjectContext]]; + DSMerkleBlock *lastTerminalBlock = [[lastTerminalBlocks firstObject] merkleBlock]; + @synchronized (self) { self->_lastTerminalBlock = lastTerminalBlock; if (lastTerminalBlock) { DSLog(@"last terminal block at height %d recovered from db (hash is %@)", lastTerminalBlock.height, [NSData dataWithUInt256:lastTerminalBlock.blockHash].hexString); } - }]; - + } + }]; + + @synchronized (self) { if (!_lastTerminalBlock) { // if we don't have any headers yet, use the latest checkpoint DSCheckpoint *lastCheckpoint = self.terminalHeadersOverrideUseCheckpoint ? self.terminalHeadersOverrideUseCheckpoint : self.lastCheckpoint; diff --git a/DashSync/shared/Models/Managers/Chain Managers/DSChainManager.m b/DashSync/shared/Models/Managers/Chain Managers/DSChainManager.m index 19fe4aabc..ad4de436a 100644 --- a/DashSync/shared/Models/Managers/Chain Managers/DSChainManager.m +++ b/DashSync/shared/Models/Managers/Chain Managers/DSChainManager.m @@ -346,10 +346,8 @@ - (double)combinedSyncProgress { DSLog(@"combinedSyncProgress breakdown %f %f %f", self.terminalHeaderSyncProgress, self.masternodeManager.masternodeListAndQuorumsSyncProgress, self.chainSyncProgress); #endif if ((self.terminalHeaderSyncWeight + self.chainSyncWeight + self.masternodeListSyncWeight) == 0) { - if (self.peerManager.connected) { - return 1; - } else { - return 0; + @synchronized (self.peerManager) { + return self.peerManager.connected ? 1 : 0; } } else { double progress = self.terminalHeaderSyncProgress * self.terminalHeaderSyncWeight + self.masternodeManager.masternodeListAndQuorumsSyncProgress * self.masternodeListSyncWeight + self.chainSyncProgress * self.chainSyncWeight; diff --git a/DashSync/shared/Models/Masternode/DSMasternodeListStore.m b/DashSync/shared/Models/Masternode/DSMasternodeListStore.m index e2815ca3c..b5efad560 100644 --- a/DashSync/shared/Models/Masternode/DSMasternodeListStore.m +++ b/DashSync/shared/Models/Masternode/DSMasternodeListStore.m @@ -297,7 +297,11 @@ - (DSMasternodeList *_Nullable)masternodeListBeforeBlockHash:(UInt256)blockHash uint32_t minDistance = UINT32_MAX; uint32_t blockHeight = [self heightForBlockHash:blockHash]; DSMasternodeList *closestMasternodeList = nil; - NSDictionary *lists = [self.masternodeListsByBlockHash copy]; + NSDictionary *lists; + @synchronized (self.masternodeListsByBlockHash) { + lists = [self.masternodeListsByBlockHash copy]; + } + for (NSData *blockHashData in lists) { uint32_t masternodeListBlockHeight = [self heightForBlockHash:blockHashData.UInt256]; if (blockHeight <= masternodeListBlockHeight) continue; From 2617c7a1036856bd3775cbe68f59fbddee02fdf7 Mon Sep 17 00:00:00 2001 From: pankcuf Date: Sat, 22 Jul 2023 20:59:19 +0700 Subject: [PATCH 05/19] chore: @sync masternode cache --- DashSync/shared/Models/Masternode/DSMasternodeListStore.m | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/DashSync/shared/Models/Masternode/DSMasternodeListStore.m b/DashSync/shared/Models/Masternode/DSMasternodeListStore.m index b5efad560..6ef66d992 100644 --- a/DashSync/shared/Models/Masternode/DSMasternodeListStore.m +++ b/DashSync/shared/Models/Masternode/DSMasternodeListStore.m @@ -350,7 +350,9 @@ - (void)removeOldMasternodeLists:(uint32_t)lastBlockHeight { //A quorum references the masternode list by it's block //we need to check if this masternode list is being referenced by a quorum using the inverse of quorum.block.masternodeList [self.managedObjectContext deleteObject:masternodeListEntity]; - [self.masternodeListsByBlockHash removeObjectForKey:masternodeListEntity.block.blockHash]; + @synchronized (self.masternodeListsByBlockHash) { + [self.masternodeListsByBlockHash removeObjectForKey:masternodeListEntity.block.blockHash]; + } } if (removedItems) { //Now we should delete old quorums From 1d5fce39b09be67b00623c10a2eafa628a3abb44 Mon Sep 17 00:00:00 2001 From: pankcuf Date: Tue, 25 Jul 2023 12:30:15 +0700 Subject: [PATCH 06/19] chore: some more syncs --- DashSync/shared/Models/Chain/DSChain.m | 272 +++++++----------- .../Chain Managers/DSMasternodeManager.m | 8 +- .../Masternode/DSMasternodeListService.m | 55 ++-- .../Models/Masternode/DSMasternodeListStore.m | 11 +- DashSync/shared/Models/Network/DSPeer.m | 8 +- 5 files changed, 156 insertions(+), 198 deletions(-) diff --git a/DashSync/shared/Models/Chain/DSChain.m b/DashSync/shared/Models/Chain/DSChain.m index 63abddf09..295ada963 100644 --- a/DashSync/shared/Models/Chain/DSChain.m +++ b/DashSync/shared/Models/Chain/DSChain.m @@ -414,59 +414,47 @@ - (KeyKind)activeBLSType { } - (NSDictionary *)syncBlocks { - @synchronized (self.mSyncBlocks) { - return [self.mSyncBlocks copy]; - } + return [self.mSyncBlocks copy]; } - (NSDictionary *)mainChainSyncBlocks { - @synchronized (self.mSyncBlocks) { - NSMutableDictionary *mainChainSyncBlocks = [self.mSyncBlocks mutableCopy]; - [mainChainSyncBlocks removeObjectsForKeys:[[self forkChainsSyncBlocks] allKeys]]; - return mainChainSyncBlocks; - } + NSMutableDictionary *mainChainSyncBlocks = [self.mSyncBlocks mutableCopy]; + [mainChainSyncBlocks removeObjectsForKeys:[[self forkChainsSyncBlocks] allKeys]]; + return mainChainSyncBlocks; } - (NSDictionary *)forkChainsSyncBlocks { - @synchronized (self.mSyncBlocks) { - NSMutableDictionary *forkChainsSyncBlocks = [self.mSyncBlocks mutableCopy]; - DSBlock *b = self.lastSyncBlock; - NSUInteger count = 0; - while (b && b.height > 0) { - b = self.mSyncBlocks[b.prevBlockValue]; - [forkChainsSyncBlocks removeObjectForKey:uint256_obj(b.blockHash)]; - count++; - } - return forkChainsSyncBlocks; + NSMutableDictionary *forkChainsSyncBlocks = [self.mSyncBlocks mutableCopy]; + DSBlock *b = self.lastSyncBlock; + NSUInteger count = 0; + while (b && b.height > 0) { + b = self.mSyncBlocks[b.prevBlockValue]; + [forkChainsSyncBlocks removeObjectForKey:uint256_obj(b.blockHash)]; + count++; } + return forkChainsSyncBlocks; } - (NSDictionary *)terminalBlocks { - @synchronized (self.mTerminalBlocks) { - return [self.mTerminalBlocks copy]; - } + return [self.mTerminalBlocks copy]; } - (NSDictionary *)mainChainTerminalBlocks { - @synchronized (self.mTerminalBlocks) { - NSMutableDictionary *mainChainTerminalBlocks = [self.mTerminalBlocks mutableCopy]; - [mainChainTerminalBlocks removeObjectsForKeys:[[self forkChainsTerminalBlocks] allKeys]]; - return mainChainTerminalBlocks; - } + NSMutableDictionary *mainChainTerminalBlocks = [self.mTerminalBlocks mutableCopy]; + [mainChainTerminalBlocks removeObjectsForKeys:[[self forkChainsTerminalBlocks] allKeys]]; + return mainChainTerminalBlocks; } - (NSDictionary *)forkChainsTerminalBlocks { - @synchronized (self.mTerminalBlocks) { - NSMutableDictionary *forkChainsTerminalBlocks = [self.mTerminalBlocks mutableCopy]; - DSBlock *b = self.lastTerminalBlock; - NSUInteger count = 0; - while (b && b.height > 0) { - b = self.mTerminalBlocks[b.prevBlockValue]; - [forkChainsTerminalBlocks removeObjectForKey:uint256_obj(b.blockHash)]; - count++; - } - return forkChainsTerminalBlocks; + NSMutableDictionary *forkChainsTerminalBlocks = [self.mTerminalBlocks mutableCopy]; + DSBlock *b = self.lastTerminalBlock; + NSUInteger count = 0; + while (b && b.height > 0) { + b = self.mTerminalBlocks[b.prevBlockValue]; + [forkChainsTerminalBlocks removeObjectForKey:uint256_obj(b.blockHash)]; + count++; } + return forkChainsTerminalBlocks; } - (NSDictionary *)orphans { @@ -1584,28 +1572,28 @@ - (NSMutableDictionary *)mSyncBlocks { if (!_checkpointsByHeightDictionary) _checkpointsByHeightDictionary = [NSMutableDictionary dictionary]; return _mSyncBlocks; } - } - [self.chainManagedObjectContext performBlockAndWait:^{ - if (self->_mSyncBlocks.count > 0) return; - self->_mSyncBlocks = [NSMutableDictionary dictionary]; - - if (uint256_is_not_zero(self.lastPersistedChainSyncBlockHash)) { - self->_mSyncBlocks[uint256_obj(self.lastPersistedChainSyncBlockHash)] = [[DSMerkleBlock alloc] initWithVersion:2 blockHash:self.lastPersistedChainSyncBlockHash prevBlock:UINT256_ZERO timestamp:self.lastPersistedChainSyncBlockTimestamp height:self.lastPersistedChainSyncBlockHeight chainWork:self.lastPersistedChainSyncBlockChainWork onChain:self]; - } - - self.checkpointsByHashDictionary = [NSMutableDictionary dictionary]; - self.checkpointsByHeightDictionary = [NSMutableDictionary dictionary]; - for (DSCheckpoint *checkpoint in self.checkpoints) { // add checkpoints to the block collection - UInt256 checkpointHash = checkpoint.blockHash; + [self.chainManagedObjectContext performBlockAndWait:^{ + if (self->_mSyncBlocks.count > 0) return; + self->_mSyncBlocks = [NSMutableDictionary dictionary]; - self->_mSyncBlocks[uint256_obj(checkpointHash)] = [[DSBlock alloc] initWithCheckpoint:checkpoint onChain:self]; - self.checkpointsByHeightDictionary[@(checkpoint.height)] = checkpoint; - self.checkpointsByHashDictionary[uint256_data(checkpointHash)] = checkpoint; - } - }]; - - return _mSyncBlocks; + if (uint256_is_not_zero(self.lastPersistedChainSyncBlockHash)) { + self->_mSyncBlocks[uint256_obj(self.lastPersistedChainSyncBlockHash)] = [[DSMerkleBlock alloc] initWithVersion:2 blockHash:self.lastPersistedChainSyncBlockHash prevBlock:UINT256_ZERO timestamp:self.lastPersistedChainSyncBlockTimestamp height:self.lastPersistedChainSyncBlockHeight chainWork:self.lastPersistedChainSyncBlockChainWork onChain:self]; + } + + self.checkpointsByHashDictionary = [NSMutableDictionary dictionary]; + self.checkpointsByHeightDictionary = [NSMutableDictionary dictionary]; + for (DSCheckpoint *checkpoint in self.checkpoints) { // add checkpoints to the block collection + UInt256 checkpointHash = checkpoint.blockHash; + + self->_mSyncBlocks[uint256_obj(checkpointHash)] = [[DSBlock alloc] initWithCheckpoint:checkpoint onChain:self]; + self.checkpointsByHeightDictionary[@(checkpoint.height)] = checkpoint; + self.checkpointsByHashDictionary[uint256_data(checkpointHash)] = checkpoint; + } + }]; + + return _mSyncBlocks; + } } - (NSArray *)chainSyncBlockLocatorArray { @@ -1658,13 +1646,9 @@ - (NSMutableDictionary *)mSyncBlocks { - (DSBlock *_Nullable)blockForBlockHash:(UInt256)blockHash { DSBlock *b; - @synchronized (self.mSyncBlocks) { - b = self.mSyncBlocks[uint256_obj(blockHash)]; - } + b = self.mSyncBlocks[uint256_obj(blockHash)]; if (b) return b; - @synchronized (self.mTerminalBlocks) { - b = self.mTerminalBlocks[uint256_obj(blockHash)]; - } + b = self.mTerminalBlocks[uint256_obj(blockHash)]; if (b) return b; if ([self allowInsightBlocksForVerification]) { return [self.insightVerifiedBlocksByHashDictionary objectForKey:uint256_data(blockHash)]; @@ -1780,15 +1764,9 @@ - (BOOL)addMinedFullBlock:(DSFullBlock *)block { if (!uint256_eq(self.lastSyncBlock.blockHash, self.mSyncBlocks[prevBlock].blockHash)) return NO; if (!uint256_eq(self.lastTerminalBlock.blockHash, self.mTerminalBlocks[prevBlock].blockHash)) return NO; - - @synchronized(self.mSyncBlocks) { - self.mSyncBlocks[blockHash] = block; - } + self.mSyncBlocks[blockHash] = block; self.lastSyncBlock = block; - - @synchronized(self.mTerminalBlocks) { - self.mTerminalBlocks[blockHash] = block; - } + self.mTerminalBlocks[blockHash] = block; self.lastTerminalBlock = block; uint32_t txTime = block.timestamp / 2 + self.mTerminalBlocks[prevBlock].timestamp / 2; @@ -1885,35 +1863,31 @@ - (BOOL)addBlock:(DSBlock *)block receivedAsHeader:(BOOL)isHeaderOnly fromPeer:( uint32_t txTime = block.timestamp / 2 + prev.timestamp / 2; if ((blockPosition & DSBlockPosition_Terminal) && ((block.height % 10000) == 0 || ((block.height == self.estimatedBlockHeight) && (block.height % 100) == 0))) { //free up some memory from time to time - @synchronized(self.mTerminalBlocks) { - //[self saveTerminalBlocks]; - DSBlock *b = block; - - for (uint32_t i = 0; b && i < KEEP_RECENT_TERMINAL_BLOCKS; i++) { - b = self.mTerminalBlocks[b.prevBlockValue]; - } - NSMutableArray *blocksToRemove = [NSMutableArray array]; - while (b) { // free up some memory - [blocksToRemove addObject:b.blockHashValue]; - b = self.mTerminalBlocks[b.prevBlockValue]; - } - [self.mTerminalBlocks removeObjectsForKeys:blocksToRemove]; + //[self saveTerminalBlocks]; + DSBlock *b = block; + + for (uint32_t i = 0; b && i < KEEP_RECENT_TERMINAL_BLOCKS; i++) { + b = self.mTerminalBlocks[b.prevBlockValue]; } + NSMutableArray *blocksToRemove = [NSMutableArray array]; + while (b) { // free up some memory + [blocksToRemove addObject:b.blockHashValue]; + b = self.mTerminalBlocks[b.prevBlockValue]; + } + [self.mTerminalBlocks removeObjectsForKeys:blocksToRemove]; } if ((blockPosition & DSBlockPosition_Sync) && ((block.height % 1000) == 0)) { //free up some memory from time to time - @synchronized(self.mSyncBlocks) { - DSBlock *b = block; - - for (uint32_t i = 0; b && i < KEEP_RECENT_SYNC_BLOCKS; i++) { - b = self.mSyncBlocks[b.prevBlockValue]; - } - NSMutableArray *blocksToRemove = [NSMutableArray array]; - while (b) { // free up some memory - [blocksToRemove addObject:b.blockHashValue]; - b = self.mSyncBlocks[b.prevBlockValue]; - } - [self.mSyncBlocks removeObjectsForKeys:blocksToRemove]; + DSBlock *b = block; + + for (uint32_t i = 0; b && i < KEEP_RECENT_SYNC_BLOCKS; i++) { + b = self.mSyncBlocks[b.prevBlockValue]; + } + NSMutableArray *blocksToRemove = [NSMutableArray array]; + while (b) { // free up some memory + [blocksToRemove addObject:b.blockHashValue]; + b = self.mSyncBlocks[b.prevBlockValue]; } + [self.mSyncBlocks removeObjectsForKeys:blocksToRemove]; } // verify block difficulty if block is past last checkpoint @@ -1922,9 +1896,7 @@ - (BOOL)addBlock:(DSBlock *)block receivedAsHeader:(BOOL)isHeaderOnly fromPeer:( DSBlock *equivalentTerminalBlock = nil; if ((blockPosition & DSBlockPosition_Sync) && (self.lastSyncBlockHeight + 1 >= lastCheckpoint.height)) { - @synchronized(self.mTerminalBlocks) { - equivalentTerminalBlock = self.mTerminalBlocks[blockHash]; - } + equivalentTerminalBlock = self.mTerminalBlocks[blockHash]; } @@ -1972,9 +1944,7 @@ - (BOOL)addBlock:(DSBlock *)block receivedAsHeader:(BOOL)isHeaderOnly fromPeer:( if ((block.height % 1000) == 0 || txHashes.count > 0 || h > peer.lastBlockHeight) { DSLog(@"[%@: %@] + sync block at: %d: %@", self.name, peer.host ? peer.host : @"TEST", h, uint256_hex(block.blockHash)); } - @synchronized(self.mSyncBlocks) { - self.mSyncBlocks[blockHash] = block; - } + self.mSyncBlocks[blockHash] = block; if (equivalentTerminalBlock && equivalentTerminalBlock.chainLocked && !block.chainLocked) { [block setChainLockedWithEquivalentBlock:equivalentTerminalBlock]; } @@ -1984,9 +1954,7 @@ - (BOOL)addBlock:(DSBlock *)block receivedAsHeader:(BOOL)isHeaderOnly fromPeer:( if ((h % 1000) == 0 || txHashes.count > 0 || h > peer.lastBlockHeight) { DSLog(@"[%@: %@] + terminal block (caught up) at: %d: %@", self.name, peer.host ? peer.host : @"TEST", h, uint256_hex(block.blockHash)); } - @synchronized(self.mTerminalBlocks) { - self.mTerminalBlocks[blockHash] = block; - } + self.mTerminalBlocks[blockHash] = block; self.lastTerminalBlock = block; } @synchronized(peer) { @@ -2007,9 +1975,7 @@ - (BOOL)addBlock:(DSBlock *)block receivedAsHeader:(BOOL)isHeaderOnly fromPeer:( if ((h % 500) == 0 || txHashes.count > 0 || h > peer.lastBlockHeight) { DSLog(@"[%@: %@] + terminal block at: %d: %@", self.name, peer.host ? peer.host : @"TEST", h, uint256_hex(block.blockHash)); } - @synchronized(self.mTerminalBlocks) { - self.mTerminalBlocks[blockHash] = block; - } + self.mTerminalBlocks[blockHash] = block; self.lastTerminalBlock = block; @synchronized(peer) { if (peer) { @@ -2022,11 +1988,7 @@ - (BOOL)addBlock:(DSBlock *)block receivedAsHeader:(BOOL)isHeaderOnly fromPeer:( if ((h % 1) == 0 || txHashes.count > 0 || h > peer.lastBlockHeight) { DSLog(@"%@:%d relayed existing sync block at height %d", peer.host, peer.port, h); } - - @synchronized(self.mSyncBlocks) { - self.mSyncBlocks[blockHash] = block; - } - + self.mSyncBlocks[blockHash] = block; if (equivalentTerminalBlock && equivalentTerminalBlock.chainLocked && !block.chainLocked) { [block setChainLockedWithEquivalentBlock:equivalentTerminalBlock]; } @@ -2049,11 +2011,7 @@ - (BOOL)addBlock:(DSBlock *)block receivedAsHeader:(BOOL)isHeaderOnly fromPeer:( if ((h % 1) == 0 || txHashes.count > 0 || h > peer.lastBlockHeight) { DSLog(@"%@:%d relayed existing terminal block at height %d (last sync height %d)", peer.host, peer.port, h, self.lastSyncBlockHeight); } - - @synchronized(self.mTerminalBlocks) { - self.mTerminalBlocks[blockHash] = block; - } - + self.mTerminalBlocks[blockHash] = block; @synchronized(peer) { if (peer) { peer.currentBlockHeight = h; //might be download peer instead @@ -2082,9 +2040,7 @@ - (BOOL)addBlock:(DSBlock *)block receivedAsHeader:(BOOL)isHeaderOnly fromPeer:( DSLog(@"potential chain fork to height %d blockPosition %d", block.height, blockPosition); if (!(blockPosition & DSBlockPosition_Sync)) { //this is only a reorg of the terminal blocks - @synchronized(self.mTerminalBlocks) { - self.mTerminalBlocks[blockHash] = block; - } + self.mTerminalBlocks[blockHash] = block; if (uint256_supeq(self.lastTerminalBlock.chainWork, block.chainWork)) return TRUE; // if fork is shorter than main chain, ignore it for now DSLog(@"found potential chain fork on height %d", block.height); @@ -2111,15 +2067,10 @@ - (BOOL)addBlock:(DSBlock *)block receivedAsHeader:(BOOL)isHeaderOnly fromPeer:( if (h == self.estimatedBlockHeight) syncDone = YES; } else { if (phase == DSChainSyncPhase_ChainSync || phase == DSChainSyncPhase_Synced) { - @synchronized(self.mTerminalBlocks) { - self.mTerminalBlocks[blockHash] = block; - } - } - - @synchronized(self.mSyncBlocks) { - self.mSyncBlocks[blockHash] = block; + self.mTerminalBlocks[blockHash] = block; } - + self.mSyncBlocks[blockHash] = block; + if (equivalentTerminalBlock && equivalentTerminalBlock.chainLocked && !block.chainLocked) { [block setChainLockedWithEquivalentBlock:equivalentTerminalBlock]; } @@ -2490,9 +2441,7 @@ - (BOOL)addChainLock:(DSChainLock *)chainLock { } } - [self setBlockHeight:TX_UNCONFIRMED - andTimestamp:0 - forTransactionHashes:txHashes]; + [self setBlockHeight:TX_UNCONFIRMED andTimestamp:0 forTransactionHashes:txHashes]; clb = syncBlock; while (clb.height > sbmc.height) { // set transaction heights for new main chain @@ -2569,8 +2518,7 @@ - (uint32_t)lastTerminalBlockHeight { } - (BOOL)allowInsightBlocksForVerification { - if (self.isMainnet) return NO; - return YES; + return !self.isMainnet; } - (uint32_t)quickHeightForBlockHash:(UInt256)blockhash { @@ -2579,20 +2527,16 @@ - (uint32_t)quickHeightForBlockHash:(UInt256)blockhash { return checkpoint.height; } - @synchronized (self.mSyncBlocks) { - DSBlock *syncBlock = [self.mSyncBlocks objectForKey:uint256_obj(blockhash)]; - if (syncBlock && (syncBlock.height != UINT32_MAX)) { - return syncBlock.height; - } + DSBlock *syncBlock = [self.mSyncBlocks objectForKey:uint256_obj(blockhash)]; + if (syncBlock && (syncBlock.height != UINT32_MAX)) { + return syncBlock.height; } - - @synchronized (self.mSyncBlocks) { - DSBlock *terminalBlock = [self.mTerminalBlocks objectForKey:uint256_obj(blockhash)]; - if (terminalBlock && (terminalBlock.height != UINT32_MAX)) { - return terminalBlock.height; - } + + DSBlock *terminalBlock = [self.mTerminalBlocks objectForKey:uint256_obj(blockhash)]; + if (terminalBlock && (terminalBlock.height != UINT32_MAX)) { + return terminalBlock.height; } - + for (DSCheckpoint *checkpoint in self.checkpoints) { if (uint256_eq(checkpoint.blockHash, blockhash)) { return checkpoint.height; @@ -2607,38 +2551,32 @@ - (uint32_t)heightForBlockHash:(UInt256)blockhash { if (checkpoint) { return checkpoint.height; } - @synchronized (self.mSyncBlocks) { - DSBlock *syncBlock = [self.mSyncBlocks objectForKey:uint256_obj(blockhash)]; - if (syncBlock && (syncBlock.height != UINT32_MAX)) { - return syncBlock.height; - } + DSBlock *syncBlock = [self.mSyncBlocks objectForKey:uint256_obj(blockhash)]; + if (syncBlock && (syncBlock.height != UINT32_MAX)) { + return syncBlock.height; } - - @synchronized (self.mTerminalBlocks) { - DSBlock *terminalBlock = [self.mTerminalBlocks objectForKey:uint256_obj(blockhash)]; - if (terminalBlock && (terminalBlock.height != UINT32_MAX)) { - return terminalBlock.height; - } + + DSBlock *terminalBlock = [self.mTerminalBlocks objectForKey:uint256_obj(blockhash)]; + if (terminalBlock && (terminalBlock.height != UINT32_MAX)) { + return terminalBlock.height; } - + DSBlock *b = self.lastTerminalBlock; if (!b) { b = self.lastSyncBlock; } - @synchronized(self.mTerminalBlocks) { - while (b && b.height > 0) { - if (uint256_eq(b.blockHash, blockhash)) { - return b.height; - } - b = self.mTerminalBlocks[b.prevBlockValue]; - if (!b) { - b = self.mSyncBlocks[b.prevBlockValue]; - } + while (b && b.height > 0) { + if (uint256_eq(b.blockHash, blockhash)) { + return b.height; + } + b = self.mTerminalBlocks[b.prevBlockValue]; + if (!b) { + b = self.mSyncBlocks[b.prevBlockValue]; } } - + for (DSCheckpoint *checkpoint in self.checkpoints) { if (uint256_eq(checkpoint.blockHash, blockhash)) { return checkpoint.height; diff --git a/DashSync/shared/Models/Managers/Chain Managers/DSMasternodeManager.m b/DashSync/shared/Models/Managers/Chain Managers/DSMasternodeManager.m index a1404c3f2..bdb984a3d 100644 --- a/DashSync/shared/Models/Managers/Chain Managers/DSMasternodeManager.m +++ b/DashSync/shared/Models/Managers/Chain Managers/DSMasternodeManager.m @@ -701,7 +701,9 @@ - (void)updateStoreWithMasternodeList:(DSMasternodeList *)masternodeList addedMa - (void)peer:(DSPeer *)peer relayedMasternodeDiffMessage:(NSData *)message { DSLog(@"•••• -> received mnlistdiff: %@", uint256_hex(message.SHA256)); - self.masternodeListDiffService.timedOutAttempt = 0; + @synchronized (self.masternodeListDiffService) { + self.masternodeListDiffService.timedOutAttempt = 0; + } dispatch_async(self.processingQueue, ^{ dispatch_group_enter(self.processingGroup); DSMasternodeProcessorContext *ctx = [self createDiffMessageContext:self.chain.isTestnet isFromSnapshot:NO isDIP0024:NO peer:peer merkleRootLookup:^UInt256(UInt256 blockHash) { @@ -736,7 +738,9 @@ - (void)peer:(DSPeer *)peer relayedMasternodeDiffMessage:(NSData *)message { - (void)peer:(DSPeer *)peer relayedQuorumRotationInfoMessage:(NSData *)message { DSLog(@"•••• -> received qrinfo: %@", uint256_hex(message.SHA256)); - self.quorumRotationService.timedOutAttempt = 0; + @synchronized (self.quorumRotationService) { + self.quorumRotationService.timedOutAttempt = 0; + } dispatch_async(self.processingQueue, ^{ dispatch_group_enter(self.processingGroup); MerkleRootFinder merkleRootLookup = ^UInt256(UInt256 blockHash) { diff --git a/DashSync/shared/Models/Masternode/DSMasternodeListService.m b/DashSync/shared/Models/Masternode/DSMasternodeListService.m index e73f52698..0c1546362 100644 --- a/DashSync/shared/Models/Masternode/DSMasternodeListService.m +++ b/DashSync/shared/Models/Masternode/DSMasternodeListService.m @@ -57,35 +57,36 @@ - (instancetype)initWithChain:(DSChain *)chain store:(DSMasternodeListStore *)st - (void)startTimeOutObserver { __block NSSet *requestsInRetrieval; - @synchronized (self.requestsInRetrieval) { + __block NSUInteger masternodeListCount; + __block uint16_t timeOutObserverTry; + dispatch_time_t timeout; + @synchronized (self) { requestsInRetrieval = [self.requestsInRetrieval copy]; + masternodeListCount = [self.store knownMasternodeListsCount]; + self.timeOutObserverTry++; + timeOutObserverTry = self.timeOutObserverTry; + timeout = dispatch_time(DISPATCH_TIME_NOW, (int64_t)(20 * (self.timedOutAttempt + 1) * NSEC_PER_SEC)); } - __block NSUInteger masternodeListCount = [self.store knownMasternodeListsCount]; - self.timeOutObserverTry++; - __block uint16_t timeOutObserverTry = self.timeOutObserverTry; - dispatch_time_t timeout = dispatch_time(DISPATCH_TIME_NOW, (int64_t)(20 * (self.timedOutAttempt + 1) * NSEC_PER_SEC)); dispatch_after(timeout, self.chain.networkingQueue, ^{ - - if (!self.retrievalQueueMaxAmount || self.timeOutObserverTry != timeOutObserverTry) { - return; - } __block NSSet *requestsInRetrieval2; - @synchronized (self.requestsInRetrieval) { + __block NSUInteger masternodeListCount2; + @synchronized (self) { + if (!self.retrievalQueueMaxAmount || self.timeOutObserverTry != timeOutObserverTry) { + return; + } requestsInRetrieval2 = [self.requestsInRetrieval copy]; - } - - // Removes from the receiving set each object that isn’t a member of another given set. - NSMutableSet *leftToGet = [requestsInRetrieval mutableCopy]; - [leftToGet intersectSet:requestsInRetrieval2]; - - if ((masternodeListCount == [self.store knownMasternodeListsCount]) && [requestsInRetrieval isEqualToSet:leftToGet]) { - DSLog(@"TimedOut"); - self.timedOutAttempt++; - [self disconnectFromDownloadPeer]; - [self cleanRequestsInRetrieval]; - [self dequeueMasternodeListRequest]; - } else { - [self startTimeOutObserver]; + // Removes from the receiving set each object that isn’t a member of another given set. + NSMutableSet *leftToGet = [requestsInRetrieval mutableCopy]; + [leftToGet intersectSet:requestsInRetrieval2]; + if ((masternodeListCount == [self.store knownMasternodeListsCount]) && [requestsInRetrieval isEqualToSet:leftToGet]) { + DSLog(@"TimedOut"); + self.timedOutAttempt++; + [self disconnectFromDownloadPeer]; + [self cleanRequestsInRetrieval]; + [self dequeueMasternodeListRequest]; + } else { + [self startTimeOutObserver]; + } } }); } @@ -285,7 +286,11 @@ - (void)fetchMasternodeListsToRetrieve:(void (^)(NSOrderedSet *listsTo DSLog(@"A masternode list is already in retrieval: %@", self); return; } - if (!self.peerManager.downloadPeer || (self.peerManager.downloadPeer.status != DSPeerStatus_Connected)) { + BOOL peerIsDisconnected; + @synchronized (self.peerManager.downloadPeer) { + peerIsDisconnected = !self.peerManager.downloadPeer || self.peerManager.downloadPeer.status != DSPeerStatus_Connected; + } + if (peerIsDisconnected) { if (self.chain.chainManager.syncPhase != DSChainSyncPhase_Offline) { dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(5 * NSEC_PER_SEC)), self.chain.networkingQueue, ^{ [self fetchMasternodeListsToRetrieve:completion]; diff --git a/DashSync/shared/Models/Masternode/DSMasternodeListStore.m b/DashSync/shared/Models/Masternode/DSMasternodeListStore.m index 6ef66d992..4812e02c9 100644 --- a/DashSync/shared/Models/Masternode/DSMasternodeListStore.m +++ b/DashSync/shared/Models/Masternode/DSMasternodeListStore.m @@ -203,8 +203,15 @@ - (BOOL)hasBlockForBlockHash:(NSData *)blockHashData { - (BOOL)hasMasternodeListAt:(NSData *)blockHashData { - // DSLog(@"We already have this masternodeList %@ (%u)", blockHashData.reverse.hexString, [self heightForBlockHash:blockHash]); - return [self.masternodeListsByBlockHash objectForKey:blockHashData] || [self.masternodeListsBlockHashStubs containsObject:blockHashData]; + BOOL hasList; + @synchronized (self.masternodeListsByBlockHash) { + hasList = [self.masternodeListsByBlockHash objectForKey:blockHashData]; + } + BOOL hasStub; + @synchronized (self.masternodeListsBlockHashStubs) { + hasStub = [self.masternodeListsBlockHashStubs containsObject:blockHashData]; + } + return hasList || hasStub; } - (BOOL)hasMasternodeListCurrentlyBeingSaved { diff --git a/DashSync/shared/Models/Network/DSPeer.m b/DashSync/shared/Models/Network/DSPeer.m index 6a2e4dd05..fc46a60fe 100644 --- a/DashSync/shared/Models/Network/DSPeer.m +++ b/DashSync/shared/Models/Network/DSPeer.m @@ -474,7 +474,9 @@ - (void)sendVerackMessage { } - (void)sendFilterloadMessage:(NSData *)filter { - self.sentFilter = YES; + @synchronized (self) { + self.sentFilter = YES; + } #if DEBUG DSLogPrivate(@"Sending filter with fingerprint %@ to node %@ %@", [NSData dataWithUInt256:filter.SHA256].shortHexString, self.host, self.peerDelegate.downloadPeer == self ? @"(download peer) " : @""); #else @@ -1082,11 +1084,13 @@ - (void)acceptInvMessage:(NSData *)message { } } uint32_t currentHeight; + BOOL isFilterNotLoaded; @synchronized (self) { currentHeight = self.currentBlockHeight; + isFilterNotLoaded = !self.sentFilter && !self.sentMempool && !self.sentGetblocks; } - if ([self.chain syncsBlockchain] && !self.sentFilter && !self.sentMempool && !self.sentGetblocks && (txHashes.count > 0) && !onlyPrivateSendTransactions) { + if ([self.chain syncsBlockchain] && isFilterNotLoaded && (txHashes.count > 0) && !onlyPrivateSendTransactions) { [self error:@"got tx inv message before loading a filter"]; return; } else if (txHashes.count + instantSendLockHashes.count + instantSendLockDHashes.count > 10000) { // this was happening on testnet, some sort of DOS/spam attack? From 25994ddfa2cdf9072ebd968220a4e6d4bdc78e27 Mon Sep 17 00:00:00 2001 From: pankcuf Date: Tue, 25 Jul 2023 13:23:53 +0700 Subject: [PATCH 07/19] chore: format --- .../Models/Managers/Chain Managers/DSTransactionManager.m | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/DashSync/shared/Models/Managers/Chain Managers/DSTransactionManager.m b/DashSync/shared/Models/Managers/Chain Managers/DSTransactionManager.m index ba8e88aa7..7197e67b4 100644 --- a/DashSync/shared/Models/Managers/Chain Managers/DSTransactionManager.m +++ b/DashSync/shared/Models/Managers/Chain Managers/DSTransactionManager.m @@ -886,8 +886,7 @@ - (void)fetchMempoolFromPeer:(DSPeer *)peer { [peer sendFilterloadMessage:[self transactionsBloomFilterForPeer:peer].data]; } - [peer sendInvMessageForHashes:self.publishedTx.allKeys - ofType:DSInvType_Tx]; // publish pending tx + [peer sendInvMessageForHashes:self.publishedTx.allKeys ofType:DSInvType_Tx]; // publish pending tx [peer sendPingMessageWithPongHandler:^(BOOL success) { if (success) { DSLog(@"[DSTransactionManager] fetching mempool ping success peer %@", peer.host); From 24cb890c04e81be55bb5dd21311e952afd783968 Mon Sep 17 00:00:00 2001 From: pankcuf Date: Wed, 26 Jul 2023 10:24:02 +0700 Subject: [PATCH 08/19] chore: peer: synchronized knownTxHashes & separate method for dispatch in delegate queue --- .../Chain Managers/DSTransactionManager.m | 3 +- DashSync/shared/Models/Network/DSPeer.m | 146 +++++++++--------- 2 files changed, 76 insertions(+), 73 deletions(-) diff --git a/DashSync/shared/Models/Managers/Chain Managers/DSTransactionManager.m b/DashSync/shared/Models/Managers/Chain Managers/DSTransactionManager.m index 7197e67b4..58cbb9e8d 100644 --- a/DashSync/shared/Models/Managers/Chain Managers/DSTransactionManager.m +++ b/DashSync/shared/Models/Managers/Chain Managers/DSTransactionManager.m @@ -1143,8 +1143,7 @@ - (DSTransaction *)peer:(DSPeer *)peer requestedTransaction:(UInt256)txHash { #define TEST_NO_RELAY (0 && !DEBUG) -- (void)peer:(DSPeer *)peer hasTransactionWithHash:(UInt256)txHash; -{ +- (void)peer:(DSPeer *)peer hasTransactionWithHash:(UInt256)txHash { #if TEST_NO_RELAY return; #endif diff --git a/DashSync/shared/Models/Network/DSPeer.m b/DashSync/shared/Models/Network/DSPeer.m index fc46a60fe..ebc961571 100644 --- a/DashSync/shared/Models/Network/DSPeer.m +++ b/DashSync/shared/Models/Network/DSPeer.m @@ -351,9 +351,9 @@ - (void)disconnectWithError:(NSError *)error { } if (self.mempoolTransactionCompletion) self.mempoolTransactionCompletion(NO, YES, YES); self.mempoolTransactionCompletion = nil; - dispatch_async(self.delegateQueue, ^{ + [self dispatchAsyncInDelegateQueue:^{ [self.peerDelegate peer:self disconnectedWithError:error]; - }); + }]; }); } @@ -374,9 +374,9 @@ - (void)didConnect { _status = DSPeerStatus_Connected; } - dispatch_async(self.delegateQueue, ^{ + [self dispatchAsyncInDelegateQueue:^{ if (self->_status == DSPeerStatus_Connected) [self.peerDelegate peerConnected:self]; - }); + }]; } - (void)receivedOrphanBlock { @@ -502,14 +502,16 @@ - (void)sendMempoolMessage:(NSArray *)publishedTxHashes completion:(MempoolCompl #else DSLog(@"%@:%u sendMempoolMessage %@", self.host, self.port, @""); #endif - [self.knownTxHashes addObjectsFromArray:publishedTxHashes]; + @synchronized (self.knownTxHashes) { + [self.knownTxHashes addObjectsFromArray:publishedTxHashes]; + } self.sentMempool = YES; if (completion) { if (self.mempoolTransactionCompletion) { - dispatch_async(self.delegateQueue, ^{ + [self dispatchAsyncInDelegateQueue:^{ if (self->_status == DSPeerStatus_Connected) completion(NO, NO, NO); - }); + }]; } else { self.mempoolTransactionCompletion = completion; dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(MEMPOOL_TIMEOUT * NSEC_PER_SEC)), self.delegateQueue, ^{ @@ -592,14 +594,18 @@ - (void)sendGetblocksMessageWithLocators:(NSArray *)locators andHashStop:(UInt25 - (void)sendInvMessageForHashes:(NSArray *)invHashes ofType:(DSInvType)invType { DSLogPrivate(@"%@:%u sending inv message of type %@ hashes count %lu", self.host, self.port, [self nameOfInvMessage:invType], (unsigned long)invHashes.count); NSMutableOrderedSet *hashes = [NSMutableOrderedSet orderedSetWithArray:invHashes]; - [hashes minusOrderedSet:self.knownTxHashes]; + @synchronized (self.knownTxHashes) { + [hashes minusOrderedSet:self.knownTxHashes]; + } if (hashes.count == 0) return; DSInvRequest *request = [DSInvRequest requestWithHashes:hashes ofInvType:invType]; [self sendRequest:request]; switch (invType) { case DSInvType_Tx: - [self.knownTxHashes unionOrderedSet:hashes]; + @synchronized (self.knownTxHashes) { + [self.knownTxHashes unionOrderedSet:hashes]; + } break; case DSInvType_GovernanceObjectVote: [self.knownGovernanceObjectVoteHashes unionOrderedSet:hashes]; @@ -621,13 +627,17 @@ - (void)sendInvMessageForHashes:(NSArray *)invHashes ofType:(DSInvType)invType { - (void)sendTransactionInvMessagesforTransactionHashes:(NSArray *)txInvHashes txLockRequestHashes:(NSArray *)txLockRequestInvHashes { NSMutableOrderedSet *txHashes = txInvHashes ? [NSMutableOrderedSet orderedSetWithArray:txInvHashes] : nil; NSMutableOrderedSet *txLockRequestHashes = txLockRequestInvHashes ? [NSMutableOrderedSet orderedSetWithArray:txLockRequestInvHashes] : nil; - [txHashes minusOrderedSet:self.knownTxHashes]; - [txLockRequestHashes minusOrderedSet:self.knownTxHashes]; + @synchronized (self.knownTxHashes) { + [txHashes minusOrderedSet:self.knownTxHashes]; + [txLockRequestHashes minusOrderedSet:self.knownTxHashes]; + } if (txHashes.count + txLockRequestHashes.count == 0) return; DSTransactionInvRequest *request = [DSTransactionInvRequest requestWithTransactionHashes:txHashes txLockRequestHashes:txLockRequestHashes]; [self sendRequest:request]; - txHashes ? [self.knownTxHashes unionOrderedSet:txHashes] : nil; - txLockRequestHashes ? [self.knownTxHashes unionOrderedSet:txLockRequestHashes] : nil; + @synchronized (self.knownTxHashes) { + txHashes ? [self.knownTxHashes unionOrderedSet:txHashes] : nil; + txLockRequestHashes ? [self.knownTxHashes unionOrderedSet:txLockRequestHashes] : nil; + } } - (void)sendGetdataMessageForTxHash:(UInt256)txHash { @@ -697,9 +707,9 @@ - (void)sendPingMessageWithPongHandler:(void (^)(BOOL success))pongHandler { #if MESSAGE_LOGGING DSLog(@"%@:%u sending ping", self.host, self.port); #endif - dispatch_async(self.delegateQueue, ^{ + [self dispatchAsyncInDelegateQueue:^{ [self sendRequest:[DSPingRequest requestWithLocalNonce:localNonce]]; - }); + }]; }); } @@ -944,10 +954,9 @@ - (void)acceptAddrMessage:(NSData *)message { timestamp:timestamp - 2 * 60 * 60 services:services]]; } - - dispatch_async(self.delegateQueue, ^{ + [self dispatchAsyncInDelegateQueue:^{ if (self->_status == DSPeerStatus_Connected) [self.peerDelegate peer:self relayedPeers:peers]; - }); + }]; } - (void)acceptAddrV2Message:(NSData *)message { @@ -1113,27 +1122,27 @@ - (void)acceptInvMessage:(NSData *)message { if (blockHashes.count == 1) self.lastBlockHash = blockHashes[0]; if (blockHashes.count > 0) { // remember blockHashes in case we need to re-request them with an updated bloom filter - dispatch_async(self.delegateQueue, ^{ + [self dispatchAsyncInDelegateQueue:^{ [self.knownBlockHashes unionOrderedSet:blockHashes]; - while (self.knownBlockHashes.count > MAX_GETDATA_HASHES) { [self.knownBlockHashes removeObjectsInRange:NSMakeRange(0, self.knownBlockHashes.count / 3)]; } - }); + }]; } - - if ([txHashes intersectsOrderedSet:self.knownTxHashes]) { // remove transactions we already have - for (NSValue *hash in txHashes) { - UInt256 h; - if (![self.knownTxHashes containsObject:hash]) continue; - [hash getValue:&h]; - dispatch_async(self.delegateQueue, ^{ - if (self->_status == DSPeerStatus_Connected) [self.transactionDelegate peer:self hasTransactionWithHash:h]; - }); + @synchronized (self.knownTxHashes) { + if ([txHashes intersectsOrderedSet:self.knownTxHashes]) { // remove transactions we already have + for (NSValue *hash in txHashes) { + UInt256 h; + if (![self.knownTxHashes containsObject:hash]) continue; + [hash getValue:&h]; + [self dispatchAsyncInDelegateQueue:^{ + if (self->_status == DSPeerStatus_Connected) [self.transactionDelegate peer:self hasTransactionWithHash:h]; + }]; + } + [txHashes minusOrderedSet:self.knownTxHashes]; } - [txHashes minusOrderedSet:self.knownTxHashes]; + [self.knownTxHashes unionOrderedSet:txHashes]; } - [self.knownTxHashes unionOrderedSet:txHashes]; if (instantSendLockHashes.count > 0) { for (NSValue *hash in instantSendLockHashes) { @@ -1144,10 +1153,9 @@ - (void)acceptInvMessage:(NSData *)message { } [instantSendLockHashes minusOrderedSet:self.knownInstantSendLockHashes]; - - dispatch_async(self.delegateQueue, ^{ + [self dispatchAsyncInDelegateQueue:^{ if (self->_status == DSPeerStatus_Connected) [self.transactionDelegate peer:self hasInstantSendLockHashes:instantSendLockHashes]; - }); + }]; [self.knownInstantSendLockHashes unionOrderedSet:instantSendLockHashes]; } @@ -1162,9 +1170,9 @@ - (void)acceptInvMessage:(NSData *)message { [instantSendLockDHashes minusOrderedSet:self.knownInstantSendLockDHashes]; - dispatch_async(self.delegateQueue, ^{ + [self dispatchAsyncInDelegateQueue:^{ if (self->_status == DSPeerStatus_Connected) [self.transactionDelegate peer:self hasInstantSendLockDHashes:instantSendLockDHashes]; - }); + }]; [self.knownInstantSendLockDHashes unionOrderedSet:instantSendLockDHashes]; } @@ -1180,10 +1188,9 @@ - (void)acceptInvMessage:(NSData *)message { } [chainLockHashes minusOrderedSet:self.knownChainLockHashes]; - - dispatch_async(self.delegateQueue, ^{ + [self dispatchAsyncInDelegateQueue:^{ if (self->_status == DSPeerStatus_Connected) [self.transactionDelegate peer:self hasChainLockHashes:chainLockHashes]; - }); + }]; [self.knownChainLockHashes unionOrderedSet:chainLockHashes]; } @@ -1265,9 +1272,9 @@ - (void)acceptTxMessage:(NSData *)message { if (tx) { __block DSMerkleBlock *currentBlock = self.currentBlock; - dispatch_async(self.delegateQueue, ^{ + [self dispatchAsyncInDelegateQueue:^{ [self.transactionDelegate peer:self relayedTransaction:tx inBlock:currentBlock]; - }); + }]; #if LOG_FULL_TX_MESSAGE #if DEBUG DSLogPrivate(@"%@:%u got tx %@ %@", self.host, self.port, uint256_obj(tx.txHash), message.hexString); @@ -1335,10 +1342,9 @@ - (void)acceptIslockMessage:(NSData *)message { [self error:@"got islock message before loading a filter"]; return; } - - dispatch_async(self.delegateQueue, ^{ + [self dispatchAsyncInDelegateQueue:^{ [self.transactionDelegate peer:self relayedInstantSendTransactionLock:instantSendTransactionLock]; - }); + }]; } - (void)acceptIsdlockMessage:(NSData *)message { @@ -1362,10 +1368,9 @@ - (void)acceptIsdlockMessage:(NSData *)message { [self error:@"got isdlock message before loading a filter"]; return; } - - dispatch_async(self.delegateQueue, ^{ + [self dispatchAsyncInDelegateQueue:^{ [self.transactionDelegate peer:self relayedInstantSendTransactionLock:instantSendTransactionLock]; - }); + }]; } // HEADER FORMAT: @@ -1472,9 +1477,9 @@ - (void)acceptHeadersMessage:(NSData *)message { [self error:@"invalid block header %@", uint256_obj(block.blockHash)]; return; } - dispatch_async(self.delegateQueue, ^{ + [self dispatchAsyncInDelegateQueue:^{ [self.transactionDelegate peer:self relayedHeader:block]; - }); + }]; } } @@ -1499,8 +1504,7 @@ - (void)acceptGetdataMessage:(NSData *)message { } DSLog(@"%@:%u %@got getdata for %u item%@", self.host, self.port, self.peerDelegate.downloadPeer == self ? @"(download peer)" : @"", (int)count, count == 1 ? @"" : @"s"); - - dispatch_async(self.delegateQueue, ^{ + [self dispatchAsyncInDelegateQueue:^{ NSMutableData *notfound = [NSMutableData data]; for (NSUInteger off = l; off < l + count * 36; off += 36) { @@ -1562,7 +1566,7 @@ - (void)acceptGetdataMessage:(NSData *)message { DSNotFoundRequest *request = [DSNotFoundRequest requestWithData:notfound]; [self sendRequest:request]; } - }); + }]; } - (void)acceptNotfoundMessage:(NSData *)message { @@ -1588,10 +1592,9 @@ - (void)acceptNotfoundMessage:(NSData *)message { [blockHashes addObject:uint256_obj([message UInt256AtOffset:off + sizeof(uint32_t)])]; } } - - dispatch_async(self.delegateQueue, ^{ + [self dispatchAsyncInDelegateQueue:^{ [self.transactionDelegate peer:self relayedNotFoundMessagesWithTransactionHashes:txHashes andBlockHashes:blockHashes]; - }); + }]; } - (void)acceptPingMessage:(NSData *)message { @@ -1638,9 +1641,9 @@ - (void)acceptPongMessage:(NSData *)message { if (self->_status == DSPeerStatus_Connected && self.pongHandlers.count) { void (^handler)(BOOL) = [self.pongHandlers objectAtIndex:0]; [self.pongHandlers removeObjectAtIndex:0]; - dispatch_async(self.delegateQueue, ^{ + [self dispatchAsyncInDelegateQueue:^{ handler(YES); - }); + }]; } }); } @@ -1663,21 +1666,21 @@ - (void)acceptMerkleblockMessage:(NSData *)message { //else DSLog(@"%@:%u got merkleblock %@", self.host, self.port, block.blockHash); NSMutableOrderedSet *txHashes = [NSMutableOrderedSet orderedSetWithArray:block.transactionHashes]; - - [txHashes minusOrderedSet:self.knownTxHashes]; + @synchronized (self.knownTxHashes) { + [txHashes minusOrderedSet:self.knownTxHashes]; + } if (txHashes.count > 0) { // wait til we get all the tx messages before processing the block self.currentBlock = block; self.currentBlockTxHashes = txHashes; } else { - dispatch_async(self.delegateQueue, ^{ + [self dispatchAsyncInDelegateQueue:^{ [self.transactionDelegate peer:self relayedBlock:block]; - #if SAVE_INCOMING_BLOCKS NSString *fileName = [NSString stringWithFormat:@"%@-%d-%@.block", self.chain.devnetIdentifier, block.height, uint256_hex(block.blockHash)]; [message saveToFile:fileName inDirectory:NSCachesDirectory]; #endif - }); + }]; } } @@ -1700,10 +1703,9 @@ - (void)acceptChainLockMessage:(NSData *)message { [self error:@"got chain lock message before loading a filter"]; return; } - - dispatch_async(self.delegateQueue, ^{ + [self dispatchAsyncInDelegateQueue:^{ [self.transactionDelegate peer:self relayedChainLock:chainLock]; - }); + }]; } // BIP61: https://github.com/bitcoin/bips/blob/master/bip-0061.mediawiki @@ -1727,9 +1729,9 @@ - (void)acceptRejectMessage:(NSData *)message { reason = nil; // fixes an unused variable warning for non-debug builds if (uint256_is_not_zero(txHash)) { - dispatch_async(self.delegateQueue, ^{ + [self dispatchAsyncInDelegateQueue:^{ [self.transactionDelegate peer:self rejectedTransaction:txHash withCode:code]; - }); + }]; } } @@ -1742,10 +1744,9 @@ - (void)acceptFeeFilterMessage:(NSData *)message { _feePerByte = ceilf((float)[message UInt64AtOffset:0] / 1000.0f); DSLog(@"%@:%u got feefilter with rate %llu per Byte", self.host, self.port, self.feePerByte); - - dispatch_async(self.delegateQueue, ^{ + [self dispatchAsyncInDelegateQueue:^{ [self.transactionDelegate peer:self setFeePerByte:self.feePerByte]; - }); + }]; } // MARK: - accept Control @@ -2074,4 +2075,7 @@ - (void)stream:(NSStream *)aStream handleEvent:(NSStreamEvent)eventCode { } } +- (void)dispatchAsyncInDelegateQueue:(void (^)(void))block { + dispatch_async(self.delegateQueue, ^{ block(); }); +} @end From c471c4b390a25d774dbba8db136878e0c927437e Mon Sep 17 00:00:00 2001 From: pankcuf Date: Wed, 26 Jul 2023 12:55:33 +0700 Subject: [PATCH 09/19] improve: rewrite initialisation for blocks RAM storage --- DashSync/shared/Models/Chain/DSChain.m | 166 ++++++++---------- .../Managers/Chain Managers/DSChainManager.m | 20 ++- DashSync/shared/Models/Network/DSPeer.m | 18 +- 3 files changed, 99 insertions(+), 105 deletions(-) diff --git a/DashSync/shared/Models/Chain/DSChain.m b/DashSync/shared/Models/Chain/DSChain.m index 295ada963..1f4bbd444 100644 --- a/DashSync/shared/Models/Chain/DSChain.m +++ b/DashSync/shared/Models/Chain/DSChain.m @@ -178,6 +178,8 @@ - (instancetype)init { if (!(self = [super init])) return nil; NSAssert([NSThread isMainThread], @"Chains should only be created on main thread (for chain entity optimizations)"); self.mOrphans = [NSMutableDictionary dictionary]; + self.mSyncBlocks = [NSMutableDictionary dictionary]; + self.mTerminalBlocks = [NSMutableDictionary dictionary]; self.mWallets = [NSMutableArray array]; self.estimatedBlockHeights = [NSMutableDictionary dictionary]; @@ -209,6 +211,8 @@ - (instancetype)initWithType:(ChainType)type checkpoints:(NSArray *)checkpoints self.headersMaxAmount = chain_headers_max_amount(type); self.checkpoints = checkpoints; self.genesisHash = self.checkpoints[0].blockHash; + _checkpointsByHashDictionary = [NSMutableDictionary dictionary]; + _checkpointsByHeightDictionary = [NSMutableDictionary dictionary]; dispatch_sync(self.networkingQueue, ^{ self.chainManagedObjectContext = [NSManagedObjectContext chainContext]; }); @@ -763,55 +767,59 @@ - (void)setIsRotatedQuorumsPresented:(BOOL)isRotatedQuorumsPresented { } - (uint32_t)minProtocolVersion { - if (_cachedMinProtocolVersion) return _cachedMinProtocolVersion; - switch (self.chainType.tag) { - case ChainType_MainNet: { - NSError *error = nil; - uint32_t minProtocolVersion = (uint32_t)getKeychainInt([NSString stringWithFormat:@"MAINNET_%@", DEFAULT_MIN_PROTOCOL_VERSION_LOCATION], &error); - if (!error && minProtocolVersion) - _cachedMinProtocolVersion = MAX(minProtocolVersion, DEFAULT_MIN_PROTOCOL_VERSION_MAINNET); - else - _cachedMinProtocolVersion = DEFAULT_MIN_PROTOCOL_VERSION_MAINNET; - break; - } - case ChainType_TestNet: { - NSError *error = nil; - uint32_t minProtocolVersion = (uint32_t)getKeychainInt([NSString stringWithFormat:@"TESTNET_%@", DEFAULT_MIN_PROTOCOL_VERSION_LOCATION], &error); - if (!error && minProtocolVersion) - _cachedMinProtocolVersion = MAX(minProtocolVersion, DEFAULT_MIN_PROTOCOL_VERSION_TESTNET); - else - _cachedMinProtocolVersion = DEFAULT_MIN_PROTOCOL_VERSION_TESTNET; - break; - } - case ChainType_DevNet: { - NSError *error = nil; - uint32_t minProtocolVersion = (uint32_t)getKeychainInt([NSString stringWithFormat:@"%@%@", [DSKeyManager devnetIdentifierFor:self.chainType], DEFAULT_MIN_PROTOCOL_VERSION_LOCATION], &error); - if (!error && minProtocolVersion) - _cachedMinProtocolVersion = MAX(minProtocolVersion, DEFAULT_MIN_PROTOCOL_VERSION_DEVNET); - else - _cachedMinProtocolVersion = DEFAULT_MIN_PROTOCOL_VERSION_DEVNET; - break; + @synchronized(self) { + if (_cachedMinProtocolVersion) return _cachedMinProtocolVersion; + switch (self.chainType.tag) { + case ChainType_MainNet: { + NSError *error = nil; + uint32_t minProtocolVersion = (uint32_t)getKeychainInt([NSString stringWithFormat:@"MAINNET_%@", DEFAULT_MIN_PROTOCOL_VERSION_LOCATION], &error); + if (!error && minProtocolVersion) + _cachedMinProtocolVersion = MAX(minProtocolVersion, DEFAULT_MIN_PROTOCOL_VERSION_MAINNET); + else + _cachedMinProtocolVersion = DEFAULT_MIN_PROTOCOL_VERSION_MAINNET; + break; + } + case ChainType_TestNet: { + NSError *error = nil; + uint32_t minProtocolVersion = (uint32_t)getKeychainInt([NSString stringWithFormat:@"TESTNET_%@", DEFAULT_MIN_PROTOCOL_VERSION_LOCATION], &error); + if (!error && minProtocolVersion) + _cachedMinProtocolVersion = MAX(minProtocolVersion, DEFAULT_MIN_PROTOCOL_VERSION_TESTNET); + else + _cachedMinProtocolVersion = DEFAULT_MIN_PROTOCOL_VERSION_TESTNET; + break; + } + case ChainType_DevNet: { + NSError *error = nil; + uint32_t minProtocolVersion = (uint32_t)getKeychainInt([NSString stringWithFormat:@"%@%@", [DSKeyManager devnetIdentifierFor:self.chainType], DEFAULT_MIN_PROTOCOL_VERSION_LOCATION], &error); + if (!error && minProtocolVersion) + _cachedMinProtocolVersion = MAX(minProtocolVersion, DEFAULT_MIN_PROTOCOL_VERSION_DEVNET); + else + _cachedMinProtocolVersion = DEFAULT_MIN_PROTOCOL_VERSION_DEVNET; + break; + } } + return _cachedMinProtocolVersion; } - return _cachedMinProtocolVersion; } - (void)setMinProtocolVersion:(uint32_t)minProtocolVersion { - if (minProtocolVersion < MIN_VALID_MIN_PROTOCOL_VERSION || minProtocolVersion > MAX_VALID_MIN_PROTOCOL_VERSION) return; - switch (self.chainType.tag) { - case ChainType_MainNet: - setKeychainInt(MAX(minProtocolVersion, DEFAULT_MIN_PROTOCOL_VERSION_MAINNET), [NSString stringWithFormat:@"MAINNET_%@", DEFAULT_MIN_PROTOCOL_VERSION_LOCATION], NO); - _cachedMinProtocolVersion = MAX(minProtocolVersion, DEFAULT_MIN_PROTOCOL_VERSION_MAINNET); - break; - case ChainType_TestNet: - setKeychainInt(MAX(minProtocolVersion, DEFAULT_MIN_PROTOCOL_VERSION_TESTNET), [NSString stringWithFormat:@"TESTNET_%@", DEFAULT_MIN_PROTOCOL_VERSION_LOCATION], NO); - _cachedMinProtocolVersion = MAX(minProtocolVersion, DEFAULT_MIN_PROTOCOL_VERSION_TESTNET); - break; - case ChainType_DevNet: { - setKeychainInt(MAX(minProtocolVersion, DEFAULT_MIN_PROTOCOL_VERSION_DEVNET), [NSString stringWithFormat:@"%@%@", [DSKeyManager devnetIdentifierFor:self.chainType], DEFAULT_MIN_PROTOCOL_VERSION_LOCATION], NO); - _cachedMinProtocolVersion = MAX(minProtocolVersion, DEFAULT_MIN_PROTOCOL_VERSION_DEVNET); - break; + @synchronized(self) { + if (minProtocolVersion < MIN_VALID_MIN_PROTOCOL_VERSION || minProtocolVersion > MAX_VALID_MIN_PROTOCOL_VERSION) return; + switch (self.chainType.tag) { + case ChainType_MainNet: + setKeychainInt(MAX(minProtocolVersion, DEFAULT_MIN_PROTOCOL_VERSION_MAINNET), [NSString stringWithFormat:@"MAINNET_%@", DEFAULT_MIN_PROTOCOL_VERSION_LOCATION], NO); + _cachedMinProtocolVersion = MAX(minProtocolVersion, DEFAULT_MIN_PROTOCOL_VERSION_MAINNET); + break; + case ChainType_TestNet: + setKeychainInt(MAX(minProtocolVersion, DEFAULT_MIN_PROTOCOL_VERSION_TESTNET), [NSString stringWithFormat:@"TESTNET_%@", DEFAULT_MIN_PROTOCOL_VERSION_LOCATION], NO); + _cachedMinProtocolVersion = MAX(minProtocolVersion, DEFAULT_MIN_PROTOCOL_VERSION_TESTNET); + break; + case ChainType_DevNet: { + setKeychainInt(MAX(minProtocolVersion, DEFAULT_MIN_PROTOCOL_VERSION_DEVNET), [NSString stringWithFormat:@"%@%@", [DSKeyManager devnetIdentifierFor:self.chainType], DEFAULT_MIN_PROTOCOL_VERSION_LOCATION], NO); + _cachedMinProtocolVersion = MAX(minProtocolVersion, DEFAULT_MIN_PROTOCOL_VERSION_DEVNET); + break; + } } } } @@ -1352,17 +1360,6 @@ - (DSCheckpoint *)checkpointForBlockHeight:(uint32_t)blockHeight { return [self.checkpointsByHeightDictionary objectForKey:@(blockHeight)]; } - -- (NSMutableDictionary *)checkpointsByHashDictionary { - if (!_checkpointsByHashDictionary) [self mSyncBlocks]; - return _checkpointsByHashDictionary; -} - -- (NSMutableDictionary *)checkpointsByHeightDictionary { - if (!_checkpointsByHeightDictionary) [self mSyncBlocks]; - return _checkpointsByHeightDictionary; -} - - (void)useCheckpointBeforeOrOnHeightForTerminalBlocksSync:(uint32_t)blockHeight { DSCheckpoint *checkpoint = [self lastCheckpointOnOrBeforeHeight:blockHeight]; self.terminalHeadersOverrideUseCheckpoint = checkpoint; @@ -1568,27 +1565,21 @@ - (DSBlock *)lastSyncBlockWithUseCheckpoints:(BOOL)useCheckpoints { - (NSMutableDictionary *)mSyncBlocks { @synchronized (_mSyncBlocks) { if (_mSyncBlocks.count > 0) { - if (!_checkpointsByHashDictionary) _checkpointsByHashDictionary = [NSMutableDictionary dictionary]; - if (!_checkpointsByHeightDictionary) _checkpointsByHeightDictionary = [NSMutableDictionary dictionary]; return _mSyncBlocks; } [self.chainManagedObjectContext performBlockAndWait:^{ if (self->_mSyncBlocks.count > 0) return; - self->_mSyncBlocks = [NSMutableDictionary dictionary]; - if (uint256_is_not_zero(self.lastPersistedChainSyncBlockHash)) { self->_mSyncBlocks[uint256_obj(self.lastPersistedChainSyncBlockHash)] = [[DSMerkleBlock alloc] initWithVersion:2 blockHash:self.lastPersistedChainSyncBlockHash prevBlock:UINT256_ZERO timestamp:self.lastPersistedChainSyncBlockTimestamp height:self.lastPersistedChainSyncBlockHeight chainWork:self.lastPersistedChainSyncBlockChainWork onChain:self]; } - self.checkpointsByHashDictionary = [NSMutableDictionary dictionary]; - self.checkpointsByHeightDictionary = [NSMutableDictionary dictionary]; for (DSCheckpoint *checkpoint in self.checkpoints) { // add checkpoints to the block collection UInt256 checkpointHash = checkpoint.blockHash; self->_mSyncBlocks[uint256_obj(checkpointHash)] = [[DSBlock alloc] initWithCheckpoint:checkpoint onChain:self]; - self.checkpointsByHeightDictionary[@(checkpoint.height)] = checkpoint; - self.checkpointsByHashDictionary[uint256_data(checkpointHash)] = checkpoint; + self->_checkpointsByHeightDictionary[@(checkpoint.height)] = checkpoint; + self->_checkpointsByHashDictionary[uint256_data(checkpointHash)] = checkpoint; } }]; @@ -2242,26 +2233,20 @@ - (void)notifyBlocksChanged:(DSBlockPosition)blockPosition { - (NSMutableDictionary *)mTerminalBlocks { @synchronized (_mTerminalBlocks) { if (_mTerminalBlocks.count > 0) { - if (!_checkpointsByHashDictionary) _checkpointsByHashDictionary = [NSMutableDictionary dictionary]; - if (!_checkpointsByHeightDictionary) _checkpointsByHeightDictionary = [NSMutableDictionary dictionary]; return _mTerminalBlocks; } [self.chainManagedObjectContext performBlockAndWait:^{ if (self->_mTerminalBlocks.count > 0) return; - self->_mTerminalBlocks = [NSMutableDictionary dictionary]; - self.checkpointsByHashDictionary = [NSMutableDictionary dictionary]; - self.checkpointsByHeightDictionary = [NSMutableDictionary dictionary]; for (DSCheckpoint *checkpoint in self.checkpoints) { // add checkpoints to the block collection UInt256 checkpointHash = checkpoint.blockHash; self->_mTerminalBlocks[uint256_obj(checkpointHash)] = [[DSBlock alloc] initWithCheckpoint:checkpoint onChain:self]; - self.checkpointsByHeightDictionary[@(checkpoint.height)] = checkpoint; - self.checkpointsByHashDictionary[uint256_data(checkpointHash)] = checkpoint; + self->_checkpointsByHeightDictionary[@(checkpoint.height)] = checkpoint; + self->_checkpointsByHashDictionary[uint256_data(checkpointHash)] = checkpoint; } for (DSMerkleBlockEntity *e in [DSMerkleBlockEntity lastTerminalBlocks:KEEP_RECENT_TERMINAL_BLOCKS onChainEntity:[self chainEntityInContext:self.chainManagedObjectContext]]) { @autoreleasepool { DSMerkleBlock *b = e.merkleBlock; - if (b) self->_mTerminalBlocks[b.blockHashValue] = b; } }; @@ -2526,15 +2511,17 @@ - (uint32_t)quickHeightForBlockHash:(UInt256)blockhash { if (checkpoint) { return checkpoint.height; } - - DSBlock *syncBlock = [self.mSyncBlocks objectForKey:uint256_obj(blockhash)]; - if (syncBlock && (syncBlock.height != UINT32_MAX)) { - return syncBlock.height; + @synchronized (_mSyncBlocks) { + DSBlock *syncBlock = [_mSyncBlocks objectForKey:uint256_obj(blockhash)]; + if (syncBlock && (syncBlock.height != UINT32_MAX)) { + return syncBlock.height; + } } - - DSBlock *terminalBlock = [self.mTerminalBlocks objectForKey:uint256_obj(blockhash)]; - if (terminalBlock && (terminalBlock.height != UINT32_MAX)) { - return terminalBlock.height; + @synchronized (_mTerminalBlocks) { + DSBlock *terminalBlock = [_mTerminalBlocks objectForKey:uint256_obj(blockhash)]; + if (terminalBlock && (terminalBlock.height != UINT32_MAX)) { + return terminalBlock.height; + } } for (DSCheckpoint *checkpoint in self.checkpoints) { @@ -2551,14 +2538,17 @@ - (uint32_t)heightForBlockHash:(UInt256)blockhash { if (checkpoint) { return checkpoint.height; } - DSBlock *syncBlock = [self.mSyncBlocks objectForKey:uint256_obj(blockhash)]; - if (syncBlock && (syncBlock.height != UINT32_MAX)) { - return syncBlock.height; + @synchronized (_mSyncBlocks) { + DSBlock *syncBlock = [_mSyncBlocks objectForKey:uint256_obj(blockhash)]; + if (syncBlock && (syncBlock.height != UINT32_MAX)) { + return syncBlock.height; + } } - - DSBlock *terminalBlock = [self.mTerminalBlocks objectForKey:uint256_obj(blockhash)]; - if (terminalBlock && (terminalBlock.height != UINT32_MAX)) { - return terminalBlock.height; + @synchronized (_mTerminalBlocks) { + DSBlock *terminalBlock = [_mTerminalBlocks objectForKey:uint256_obj(blockhash)]; + if (terminalBlock && (terminalBlock.height != UINT32_MAX)) { + return terminalBlock.height; + } } DSBlock *b = self.lastTerminalBlock; @@ -2921,8 +2911,8 @@ - (void)wipeBlockchainInfoInContext:(NSManagedObjectContext *)context { [self.viewingAccount wipeBlockchainInfo]; [self.chainManager.identitiesManager clearExternalBlockchainIdentities]; _bestBlockHeight = 0; - _mSyncBlocks = nil; - _mTerminalBlocks = nil; + _mSyncBlocks = [NSMutableDictionary dictionary]; + _mTerminalBlocks = [NSMutableDictionary dictionary]; _lastSyncBlock = nil; _lastTerminalBlock = nil; _lastPersistedChainSyncLocators = nil; @@ -2945,7 +2935,7 @@ - (void)wipeBlockchainNonTerminalInfoInContext:(NSManagedObjectContext *)context [self.viewingAccount wipeBlockchainInfo]; [self.chainManager.identitiesManager clearExternalBlockchainIdentities]; _bestBlockHeight = 0; - _mSyncBlocks = nil; + _mSyncBlocks = [NSMutableDictionary dictionary]; _lastSyncBlock = nil; _lastPersistedChainSyncLocators = nil; _lastPersistedChainSyncBlockHash = UINT256_ZERO; diff --git a/DashSync/shared/Models/Managers/Chain Managers/DSChainManager.m b/DashSync/shared/Models/Managers/Chain Managers/DSChainManager.m index ad4de436a..5dd1b2894 100644 --- a/DashSync/shared/Models/Managers/Chain Managers/DSChainManager.m +++ b/DashSync/shared/Models/Managers/Chain Managers/DSChainManager.m @@ -284,15 +284,17 @@ - (void)assignSyncWeights { uint32_t terminalWeight = terminalBlocks / 4; uint32_t masternodeWeight = masternodeListsToSync ? (20000 + 2000 * (masternodeListsToSync - 1)) : 0; uint32_t totalWeight = chainWeight + terminalWeight + masternodeWeight; - if (totalWeight == 0) { - self.terminalHeaderSyncWeight = 0; - self.masternodeListSyncWeight = 0; - self.chainSyncWeight = 1; - } else { - self.chainSyncWeight = ((float)chainWeight) / totalWeight; - self.terminalHeaderSyncWeight = ((float)terminalWeight) / totalWeight; - self.masternodeListSyncWeight = ((float)masternodeWeight) / totalWeight; - } + dispatch_sync(dispatch_get_main_queue(), ^{ + if (totalWeight == 0) { + self.terminalHeaderSyncWeight = 0; + self.masternodeListSyncWeight = 0; + self.chainSyncWeight = 1; + } else { + self.chainSyncWeight = ((float)chainWeight) / totalWeight; + self.terminalHeaderSyncWeight = ((float)terminalWeight) / totalWeight; + self.masternodeListSyncWeight = ((float)masternodeWeight) / totalWeight; + } + }); } - (uint32_t)chainBlocksToSync { diff --git a/DashSync/shared/Models/Network/DSPeer.m b/DashSync/shared/Models/Network/DSPeer.m index ebc961571..ce90f3fec 100644 --- a/DashSync/shared/Models/Network/DSPeer.m +++ b/DashSync/shared/Models/Network/DSPeer.m @@ -566,14 +566,16 @@ - (void)sendGetblocksMessageWithLocators:(NSArray *)locators andHashStop:(UInt25 #if MESSAGE_LOGGING NSMutableArray *locatorHexes = [NSMutableArray arrayWithCapacity:[locators count]]; - [locators enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) { - uint32_t knownHeight = [self.chain quickHeightForBlockHash:((NSData *)obj).UInt256]; - if (knownHeight == UINT32_MAX) { - [locatorHexes addObject:[NSString stringWithFormat:@"%@ (block height unknown)", ((NSData *)obj).reverse.hexString]]; - } else { - [locatorHexes addObject:[NSString stringWithFormat:@"%@ (block %d)", ((NSData *)obj).reverse.hexString, knownHeight]]; - } - }]; + dispatch_sync(self.delegateQueue, ^{ + [locators enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) { + uint32_t knownHeight = [self.chain quickHeightForBlockHash:((NSData *)obj).UInt256]; + if (knownHeight == UINT32_MAX) { + [locatorHexes addObject:[NSString stringWithFormat:@"%@ (block height unknown)", ((NSData *)obj).reverse.hexString]]; + } else { + [locatorHexes addObject:[NSString stringWithFormat:@"%@ (block %d)", ((NSData *)obj).reverse.hexString, knownHeight]]; + } + }]; + }); #if DEBUG DSLogPrivate(@"%@:%u %@sending getblocks with locators %@", self.host, self.port, self.peerDelegate.downloadPeer == self ? @"(download peer) " : @"", locatorHexes); #else From f24434893c465f8e826ba46398fdcfbf7d091a5d Mon Sep 17 00:00:00 2001 From: pankcuf Date: Wed, 26 Jul 2023 12:57:10 +0700 Subject: [PATCH 10/19] fix: access to chain quick height --- DashSync/shared/Models/Network/DSPeer.m | 18 ++++++++---------- 1 file changed, 8 insertions(+), 10 deletions(-) diff --git a/DashSync/shared/Models/Network/DSPeer.m b/DashSync/shared/Models/Network/DSPeer.m index ce90f3fec..ebc961571 100644 --- a/DashSync/shared/Models/Network/DSPeer.m +++ b/DashSync/shared/Models/Network/DSPeer.m @@ -566,16 +566,14 @@ - (void)sendGetblocksMessageWithLocators:(NSArray *)locators andHashStop:(UInt25 #if MESSAGE_LOGGING NSMutableArray *locatorHexes = [NSMutableArray arrayWithCapacity:[locators count]]; - dispatch_sync(self.delegateQueue, ^{ - [locators enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) { - uint32_t knownHeight = [self.chain quickHeightForBlockHash:((NSData *)obj).UInt256]; - if (knownHeight == UINT32_MAX) { - [locatorHexes addObject:[NSString stringWithFormat:@"%@ (block height unknown)", ((NSData *)obj).reverse.hexString]]; - } else { - [locatorHexes addObject:[NSString stringWithFormat:@"%@ (block %d)", ((NSData *)obj).reverse.hexString, knownHeight]]; - } - }]; - }); + [locators enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) { + uint32_t knownHeight = [self.chain quickHeightForBlockHash:((NSData *)obj).UInt256]; + if (knownHeight == UINT32_MAX) { + [locatorHexes addObject:[NSString stringWithFormat:@"%@ (block height unknown)", ((NSData *)obj).reverse.hexString]]; + } else { + [locatorHexes addObject:[NSString stringWithFormat:@"%@ (block %d)", ((NSData *)obj).reverse.hexString, knownHeight]]; + } + }]; #if DEBUG DSLogPrivate(@"%@:%u %@sending getblocks with locators %@", self.host, self.port, self.peerDelegate.downloadPeer == self ? @"(download peer) " : @"", locatorHexes); #else From 70867775f8b077bcff07acdf5732199718dda441 Mon Sep 17 00:00:00 2001 From: pankcuf Date: Wed, 26 Jul 2023 13:40:24 +0700 Subject: [PATCH 11/19] fix: synced remove masternode list cache --- DashSync/shared/Models/Masternode/DSMasternodeListStore.m | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/DashSync/shared/Models/Masternode/DSMasternodeListStore.m b/DashSync/shared/Models/Masternode/DSMasternodeListStore.m index 4812e02c9..50483a24c 100644 --- a/DashSync/shared/Models/Masternode/DSMasternodeListStore.m +++ b/DashSync/shared/Models/Masternode/DSMasternodeListStore.m @@ -336,8 +336,12 @@ - (DSMasternodeList *)masternodeListForBlockHash:(UInt256)blockHash withBlockHei - (void)removeAllMasternodeLists { DSLog(@"••• removeAllMasternodeLists -> "); - [self.masternodeListsByBlockHash removeAllObjects]; - [self.masternodeListsBlockHashStubs removeAllObjects]; + @synchronized (self.masternodeListsByBlockHash) { + [self.masternodeListsByBlockHash removeAllObjects]; + } + @synchronized (self.masternodeListsBlockHashStubs) { + [self.masternodeListsBlockHashStubs removeAllObjects]; + } self.masternodeListAwaitingQuorumValidation = nil; } From 766046d704892a6636a58396c49e4f71d0ede13a Mon Sep 17 00:00:00 2001 From: pankcuf Date: Wed, 26 Jul 2023 13:50:56 +0700 Subject: [PATCH 12/19] fix: revert assign-sync-weights --- .../Managers/Chain Managers/DSChainManager.m | 20 +++++++++---------- 1 file changed, 9 insertions(+), 11 deletions(-) diff --git a/DashSync/shared/Models/Managers/Chain Managers/DSChainManager.m b/DashSync/shared/Models/Managers/Chain Managers/DSChainManager.m index 5dd1b2894..ad4de436a 100644 --- a/DashSync/shared/Models/Managers/Chain Managers/DSChainManager.m +++ b/DashSync/shared/Models/Managers/Chain Managers/DSChainManager.m @@ -284,17 +284,15 @@ - (void)assignSyncWeights { uint32_t terminalWeight = terminalBlocks / 4; uint32_t masternodeWeight = masternodeListsToSync ? (20000 + 2000 * (masternodeListsToSync - 1)) : 0; uint32_t totalWeight = chainWeight + terminalWeight + masternodeWeight; - dispatch_sync(dispatch_get_main_queue(), ^{ - if (totalWeight == 0) { - self.terminalHeaderSyncWeight = 0; - self.masternodeListSyncWeight = 0; - self.chainSyncWeight = 1; - } else { - self.chainSyncWeight = ((float)chainWeight) / totalWeight; - self.terminalHeaderSyncWeight = ((float)terminalWeight) / totalWeight; - self.masternodeListSyncWeight = ((float)masternodeWeight) / totalWeight; - } - }); + if (totalWeight == 0) { + self.terminalHeaderSyncWeight = 0; + self.masternodeListSyncWeight = 0; + self.chainSyncWeight = 1; + } else { + self.chainSyncWeight = ((float)chainWeight) / totalWeight; + self.terminalHeaderSyncWeight = ((float)terminalWeight) / totalWeight; + self.masternodeListSyncWeight = ((float)masternodeWeight) / totalWeight; + } } - (uint32_t)chainBlocksToSync { From 78316d26859a10333ed10a4c97c160f17d03ac56 Mon Sep 17 00:00:00 2001 From: pankcuf Date: Wed, 26 Jul 2023 14:52:08 +0700 Subject: [PATCH 13/19] fix: @sync blocks storage when wiping --- DashSync/shared/Models/Chain/DSChain.m | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/DashSync/shared/Models/Chain/DSChain.m b/DashSync/shared/Models/Chain/DSChain.m index 1f4bbd444..cd560f147 100644 --- a/DashSync/shared/Models/Chain/DSChain.m +++ b/DashSync/shared/Models/Chain/DSChain.m @@ -1890,7 +1890,6 @@ - (BOOL)addBlock:(DSBlock *)block receivedAsHeader:(BOOL)isHeaderOnly fromPeer:( equivalentTerminalBlock = self.mTerminalBlocks[blockHash]; } - if (!equivalentTerminalBlock && ((blockPosition & DSBlockPosition_Terminal) || [block canCalculateDifficultyWithPreviousBlocks:self.mSyncBlocks])) { //no need to check difficulty if we already have terminal blocks uint32_t foundDifficulty = 0; if ((block.height > self.minimumDifficultyBlocks) && (block.height > (lastCheckpoint.height + DGW_PAST_BLOCKS_MAX)) && @@ -2911,8 +2910,12 @@ - (void)wipeBlockchainInfoInContext:(NSManagedObjectContext *)context { [self.viewingAccount wipeBlockchainInfo]; [self.chainManager.identitiesManager clearExternalBlockchainIdentities]; _bestBlockHeight = 0; - _mSyncBlocks = [NSMutableDictionary dictionary]; - _mTerminalBlocks = [NSMutableDictionary dictionary]; + @synchronized (_mSyncBlocks) { + _mSyncBlocks = [NSMutableDictionary dictionary]; + } + @synchronized (_mTerminalBlocks) { + _mTerminalBlocks = [NSMutableDictionary dictionary]; + } _lastSyncBlock = nil; _lastTerminalBlock = nil; _lastPersistedChainSyncLocators = nil; @@ -2935,7 +2938,9 @@ - (void)wipeBlockchainNonTerminalInfoInContext:(NSManagedObjectContext *)context [self.viewingAccount wipeBlockchainInfo]; [self.chainManager.identitiesManager clearExternalBlockchainIdentities]; _bestBlockHeight = 0; - _mSyncBlocks = [NSMutableDictionary dictionary]; + @synchronized (_mSyncBlocks) { + _mSyncBlocks = [NSMutableDictionary dictionary]; + } _lastSyncBlock = nil; _lastPersistedChainSyncLocators = nil; _lastPersistedChainSyncBlockHash = UINT256_ZERO; From fb194b461093a71eacfed6f3d66725eb2efac943 Mon Sep 17 00:00:00 2001 From: pankcuf Date: Wed, 26 Jul 2023 15:19:50 +0700 Subject: [PATCH 14/19] fix: tmp remove assert --- .../Entities/DSSimplifiedMasternodeEntryEntity+CoreDataClass.m | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/DashSync/shared/Models/Entities/DSSimplifiedMasternodeEntryEntity+CoreDataClass.m b/DashSync/shared/Models/Entities/DSSimplifiedMasternodeEntryEntity+CoreDataClass.m index 6865b4e52..691dcdf44 100644 --- a/DashSync/shared/Models/Entities/DSSimplifiedMasternodeEntryEntity+CoreDataClass.m +++ b/DashSync/shared/Models/Entities/DSSimplifiedMasternodeEntryEntity+CoreDataClass.m @@ -37,7 +37,7 @@ - (void)updateAttributesFromSimplifiedMasternodeEntry:(DSSimplifiedMasternodeEnt - (void)updateAttributesFromSimplifiedMasternodeEntry:(DSSimplifiedMasternodeEntry *)simplifiedMasternodeEntry atBlockHeight:(uint32_t)blockHeight knownOperatorAddresses:(NSDictionary *)knownOperatorAddresses knownVotingAddresses:(NSDictionary *)knownVotingAddresses localMasternodes:(NSDictionary *)localMasternodes { if (self.updateHeight < blockHeight) { - NSAssert(simplifiedMasternodeEntry.updateHeight == blockHeight, @"the block height should be the same as the entry update height"); + //NSAssert(simplifiedMasternodeEntry.updateHeight == blockHeight, @"the block height should be the same as the entry update height"); self.updateHeight = blockHeight; //we should only update if the data received is the most recent if (!uint128_eq(self.ipv6Address.UInt128, simplifiedMasternodeEntry.address)) { From 0dd60c95815f0ae23189591bc767bb57185f086f Mon Sep 17 00:00:00 2001 From: pankcuf Date: Wed, 26 Jul 2023 15:23:04 +0700 Subject: [PATCH 15/19] fix: revert peer @sync status (it can lead to deadlocks) --- DashSync/shared/Models/Network/DSPeer.m | 21 ++++----------------- 1 file changed, 4 insertions(+), 17 deletions(-) diff --git a/DashSync/shared/Models/Network/DSPeer.m b/DashSync/shared/Models/Network/DSPeer.m index ebc961571..c7cf23882 100644 --- a/DashSync/shared/Models/Network/DSPeer.m +++ b/DashSync/shared/Models/Network/DSPeer.m @@ -221,9 +221,7 @@ - (NSString *)host { - (void)connect { if (self.status != DSPeerStatus_Disconnected) return; - @synchronized (self) { - _status = DSPeerStatus_Connecting; - } + _status = DSPeerStatus_Connecting; _pingTime = DBL_MAX; if (!self.reachability) self.reachability = [DSReachabilityManager sharedManager]; @@ -237,9 +235,7 @@ - (void)connect { queue:nil usingBlock:^(NSNotification *note) { if (self.reachabilityObserver && self.reachability.networkReachabilityStatus != DSReachabilityStatusNotReachable) { - @synchronized (self) { - self->_status = DSPeerStatus_Disconnected; - } + self->_status = DSPeerStatus_Disconnected; [self connect]; } }]; @@ -323,10 +319,7 @@ - (void)disconnectWithError:(NSError *)error { } [NSObject cancelPreviousPerformRequestsWithTarget:self]; // cancel connect timeout - @synchronized (self) { - _status = DSPeerStatus_Disconnected; - } - + _status = DSPeerStatus_Disconnected; if (self.reachabilityObserver) { self.reachability = nil; [[NSNotificationCenter defaultCenter] removeObserver:self.reachabilityObserver]; @@ -339,10 +332,6 @@ - (void)disconnectWithError:(NSError *)error { CFRunLoopStop([self.runLoop getCFRunLoop]); - @synchronized (self) { - _status = DSPeerStatus_Disconnected; - } - dispatch_async(self.handlersQueue, ^{ [NSObject cancelPreviousPerformRequestsWithTarget:self]; while (self.pongHandlers.count) { @@ -370,9 +359,7 @@ - (void)didConnect { DSLog(@"%@:%u handshake completed %@", self.host, self.port, (self.peerDelegate.downloadPeer == self) ? @"(download peer)" : @""); [NSObject cancelPreviousPerformRequestsWithTarget:self]; // cancel pending handshake timeout - @synchronized (self) { - _status = DSPeerStatus_Connected; - } + _status = DSPeerStatus_Connected; [self dispatchAsyncInDelegateQueue:^{ if (self->_status == DSPeerStatus_Connected) [self.peerDelegate peerConnected:self]; From 5ddc7db79a6a19be65782b6d1e45d37ec5fdd219 Mon Sep 17 00:00:00 2001 From: pankcuf Date: Wed, 26 Jul 2023 15:37:01 +0700 Subject: [PATCH 16/19] fix: @sync masternode cache while retrieving it from DB --- DashSync/shared/Models/Masternode/DSMasternodeListStore.m | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/DashSync/shared/Models/Masternode/DSMasternodeListStore.m b/DashSync/shared/Models/Masternode/DSMasternodeListStore.m index 50483a24c..bfe90dd4a 100644 --- a/DashSync/shared/Models/Masternode/DSMasternodeListStore.m +++ b/DashSync/shared/Models/Masternode/DSMasternodeListStore.m @@ -256,8 +256,12 @@ - (DSMasternodeList *)loadMasternodeListAtBlockHash:(NSData *)blockHash withBloc masternodeList = [masternodeListEntity masternodeListWithSimplifiedMasternodeEntryPool:[simplifiedMasternodeEntryPool copy] quorumEntryPool:quorumEntryPool withBlockHeightLookup:blockHeightLookup]; if (masternodeList) { DSLog(@"••• addMasternodeList (loadMasternodeListAtBlockHash) -> %@: %@", blockHash.hexString, masternodeList); - [self.masternodeListsByBlockHash setObject:masternodeList forKey:blockHash]; - [self.masternodeListsBlockHashStubs removeObject:blockHash]; + @synchronized (self.masternodeListsByBlockHash) { + [self.masternodeListsByBlockHash setObject:masternodeList forKey:blockHash]; + } + @synchronized (self.masternodeListsByBlockHash) { + [self.masternodeListsBlockHashStubs removeObject:blockHash]; + } DSLog(@"Loading Masternode List at height %u for blockHash %@ with %lu entries", masternodeList.height, uint256_hex(masternodeList.blockHash), (unsigned long)masternodeList.simplifiedMasternodeEntries.count); } }]; From e50aa019bf87360b709a8cabf5e7385888c7dfe5 Mon Sep 17 00:00:00 2001 From: pankcuf Date: Wed, 26 Jul 2023 17:18:31 +0700 Subject: [PATCH 17/19] fix: main thread deadlock --- .../Managers/Chain Managers/DSChainManager.m | 8 +--- .../Managers/Chain Managers/DSPeerManager.m | 38 +++++++++---------- DashSync/shared/Models/Network/DSPeer.m | 27 ++++++------- 3 files changed, 34 insertions(+), 39 deletions(-) diff --git a/DashSync/shared/Models/Managers/Chain Managers/DSChainManager.m b/DashSync/shared/Models/Managers/Chain Managers/DSChainManager.m index ad4de436a..3d43643c8 100644 --- a/DashSync/shared/Models/Managers/Chain Managers/DSChainManager.m +++ b/DashSync/shared/Models/Managers/Chain Managers/DSChainManager.m @@ -391,15 +391,11 @@ - (void)restartTerminalSyncStartHeight { } - (void)relayedNewItem { - dispatch_sync(dispatch_get_main_queue(), ^{ - self.lastChainRelayTime = [NSDate timeIntervalSince1970]; - }); + self.lastChainRelayTime = [NSDate timeIntervalSince1970]; } - (void)resetLastRelayedItemTime { - dispatch_sync(dispatch_get_main_queue(), ^{ - self.lastChainRelayTime = 0; - }); + self.lastChainRelayTime = 0; } // MARK: - Mining diff --git a/DashSync/shared/Models/Managers/Chain Managers/DSPeerManager.m b/DashSync/shared/Models/Managers/Chain Managers/DSPeerManager.m index de3417d57..09922f025 100644 --- a/DashSync/shared/Models/Managers/Chain Managers/DSPeerManager.m +++ b/DashSync/shared/Models/Managers/Chain Managers/DSPeerManager.m @@ -741,11 +741,11 @@ - (void)connect { @synchronized(self.mutableConnectedPeers) { NSMutableSet *disconnectedPeers = [NSMutableSet set]; for (DSPeer *peer in self.mutableConnectedPeers) { - @synchronized(peer) { +// @synchronized(peer) { if (peer.status == DSPeerStatus_Disconnected) { [disconnectedPeers addObject:peer]; } - } +// } } [self.mutableConnectedPeers minusSet:disconnectedPeers]; } @@ -957,24 +957,22 @@ - (void)peerConnected:(DSPeer *)peer { } bestPeer.currentBlockHeight = self.chain.lastSyncBlockHeight; - [self.chainManager assignSyncWeights]; - if ([self.chain syncsBlockchain] && - ((self.chain.lastSyncBlockHeight != self.chain.lastTerminalBlockHeight) || - (self.chain.lastSyncBlockHeight < bestPeer.lastBlockHeight))) { // start blockchain sync - [self.chainManager resetLastRelayedItemTime]; - dispatch_async(dispatch_get_main_queue(), ^{ // setup a timer to detect if the sync stalls - [NSObject cancelPreviousPerformRequestsWithTarget:self selector:@selector(syncTimeout) object:nil]; - [self performSelector:@selector(syncTimeout) withObject:nil afterDelay:PROTOCOL_TIMEOUT]; - - [[NSNotificationCenter defaultCenter] postNotificationName:DSTransactionManagerTransactionStatusDidChangeNotification object:nil userInfo:@{DSChainManagerNotificationChainKey: self.chain}]; - - [self.chainManager chainWillStartSyncingBlockchain:self.chain]; - [self.chainManager chainShouldStartSyncingBlockchain:self.chain onPeer:bestPeer]; - }); - } else { // we're already synced - [self.chainManager chainFinishedSyncingTransactionsAndBlocks:self.chain fromPeer:nil onMainChain:TRUE]; - } - dispatch_async(dispatch_get_main_queue(), ^{ + dispatch_async(dispatch_get_main_queue(), ^{ // setup a timer to detect if the sync stalls + [self.chainManager assignSyncWeights]; + if ([self.chain syncsBlockchain] && + ((self.chain.lastSyncBlockHeight != self.chain.lastTerminalBlockHeight) || + (self.chain.lastSyncBlockHeight < bestPeer.lastBlockHeight))) { // start blockchain sync + [self.chainManager resetLastRelayedItemTime]; + [NSObject cancelPreviousPerformRequestsWithTarget:self selector:@selector(syncTimeout) object:nil]; + [self performSelector:@selector(syncTimeout) withObject:nil afterDelay:PROTOCOL_TIMEOUT]; + + [[NSNotificationCenter defaultCenter] postNotificationName:DSTransactionManagerTransactionStatusDidChangeNotification object:nil userInfo:@{DSChainManagerNotificationChainKey: self.chain}]; + + [self.chainManager chainWillStartSyncingBlockchain:self.chain]; + [self.chainManager chainShouldStartSyncingBlockchain:self.chain onPeer:bestPeer]; + } else { // we're already synced + [self.chainManager chainFinishedSyncingTransactionsAndBlocks:self.chain fromPeer:nil onMainChain:TRUE]; + } [[NSNotificationCenter defaultCenter] postNotificationName:DSPeerManagerConnectedPeersDidChangeNotification object:nil userInfo:@{DSChainManagerNotificationChainKey: self.chain}]; diff --git a/DashSync/shared/Models/Network/DSPeer.m b/DashSync/shared/Models/Network/DSPeer.m index c7cf23882..c439fc485 100644 --- a/DashSync/shared/Models/Network/DSPeer.m +++ b/DashSync/shared/Models/Network/DSPeer.m @@ -124,7 +124,7 @@ @interface DSPeer () @property (nonatomic, assign) uint64_t receivedOrphanCount; @property (nonatomic, assign) NSTimeInterval mempoolRequestTime; @property (nonatomic, strong) dispatch_semaphore_t outputBufferSemaphore; -@property (nonatomic, strong) dispatch_queue_t handlersQueue; +//@property (nonatomic, strong) dispatch_queue_t handlersQueue; @end @@ -151,7 +151,7 @@ - (instancetype)initWithAddress:(UInt128)address andPort:(uint16_t)port onChain: _port = (port == 0) ? [chain standardPort] : port; self.chain = chain; _outputBufferSemaphore = dispatch_semaphore_create(1); - _handlersQueue = dispatch_queue_create("org.dash.dashsync.peerHandlers", DISPATCH_QUEUE_SERIAL); +// _handlersQueue = dispatch_queue_create("org.dash.dashsync.peerHandlers", DISPATCH_QUEUE_SERIAL); return self; } @@ -177,7 +177,7 @@ - (instancetype)initWithHost:(NSString *)host onChain:(DSChain *)chain { if (_port == 0) _port = chain.standardPort; self.chain = chain; _outputBufferSemaphore = dispatch_semaphore_create(1); - _handlersQueue = dispatch_queue_create("org.dash.dashsync.peerHandlers", DISPATCH_QUEUE_SERIAL); +// _handlersQueue = dispatch_queue_create("org.dash.dashsync.peerHandlers", DISPATCH_QUEUE_SERIAL); return self; } @@ -311,6 +311,7 @@ - (void)disconnect { } - (void)disconnectWithError:(NSError *)error { + if (_status == DSPeerStatus_Disconnected) return; if (!error) { DSLog(@"Disconnected from peer %@ (%@ protocol %d) with no error", self.host, self.useragent, self.version); @@ -332,7 +333,7 @@ - (void)disconnectWithError:(NSError *)error { CFRunLoopStop([self.runLoop getCFRunLoop]); - dispatch_async(self.handlersQueue, ^{ +// dispatch_async(self.handlersQueue, ^{ [NSObject cancelPreviousPerformRequestsWithTarget:self]; while (self.pongHandlers.count) { ((void (^)(BOOL))self.pongHandlers[0])(NO); @@ -343,7 +344,7 @@ - (void)disconnectWithError:(NSError *)error { [self dispatchAsyncInDelegateQueue:^{ [self.peerDelegate peer:self disconnectedWithError:error]; }]; - }); +// }); } - (void)error:(NSString *)message, ... NS_FORMAT_FUNCTION(1, 2) { @@ -685,7 +686,7 @@ - (void)sendGetaddrMessage { } - (void)sendPingMessageWithPongHandler:(void (^)(BOOL success))pongHandler { - dispatch_async(self.handlersQueue, ^{ +// dispatch_async(self.handlersQueue, ^{ if (!self.pongHandlers) self.pongHandlers = [NSMutableArray array]; [self.pongHandlers addObject:(pongHandler) ? [pongHandler copy] : [^(BOOL success) {} copy]]; uint64_t localNonce = self.localNonce; @@ -697,7 +698,7 @@ - (void)sendPingMessageWithPongHandler:(void (^)(BOOL success))pongHandler { [self dispatchAsyncInDelegateQueue:^{ [self sendRequest:[DSPingRequest requestWithLocalNonce:localNonce]]; }]; - }); +// }); } // re-request blocks starting from blockHash, useful for getting any additional transactions after a bloom filter update @@ -1603,10 +1604,10 @@ - (void)acceptPongMessage:(NSData *)message { [self error:@"pong message contained wrong nonce: %llu, expected: %llu", [message UInt64AtOffset:0], self.localNonce]; return; } else { - __block BOOL hasNoHandlers; - dispatch_sync(self.handlersQueue, ^{ - hasNoHandlers = ![self.pongHandlers count]; - }); + __block BOOL hasNoHandlers = ![self.pongHandlers count]; +// dispatch_sync(self.handlersQueue, ^{ +// hasNoHandlers = ![self.pongHandlers count]; +// }); if (hasNoHandlers) { DSLog(@"%@:%u got unexpected pong", self.host, self.port); return; @@ -1624,7 +1625,7 @@ - (void)acceptPongMessage:(NSData *)message { #if MESSAGE_LOGGING DSLog(@"%@:%u got pong in %fs", self.host, self.port, self.pingTime); #endif - dispatch_async(self.handlersQueue, ^{ +// dispatch_async(self.handlersQueue, ^{ if (self->_status == DSPeerStatus_Connected && self.pongHandlers.count) { void (^handler)(BOOL) = [self.pongHandlers objectAtIndex:0]; [self.pongHandlers removeObjectAtIndex:0]; @@ -1632,7 +1633,7 @@ - (void)acceptPongMessage:(NSData *)message { handler(YES); }]; } - }); +// }); } #define SAVE_INCOMING_BLOCKS 0 From e2c34f3bbef8a7fc74beb2caa0e930a5c19ec42b Mon Sep 17 00:00:00 2001 From: pankcuf Date: Wed, 26 Jul 2023 17:26:16 +0700 Subject: [PATCH 18/19] chore: remove unsued --- DashSync/shared/Models/Network/DSPeer.m | 62 ++++++++++--------------- 1 file changed, 25 insertions(+), 37 deletions(-) diff --git a/DashSync/shared/Models/Network/DSPeer.m b/DashSync/shared/Models/Network/DSPeer.m index c439fc485..ebd8ed663 100644 --- a/DashSync/shared/Models/Network/DSPeer.m +++ b/DashSync/shared/Models/Network/DSPeer.m @@ -124,7 +124,6 @@ @interface DSPeer () @property (nonatomic, assign) uint64_t receivedOrphanCount; @property (nonatomic, assign) NSTimeInterval mempoolRequestTime; @property (nonatomic, strong) dispatch_semaphore_t outputBufferSemaphore; -//@property (nonatomic, strong) dispatch_queue_t handlersQueue; @end @@ -151,7 +150,6 @@ - (instancetype)initWithAddress:(UInt128)address andPort:(uint16_t)port onChain: _port = (port == 0) ? [chain standardPort] : port; self.chain = chain; _outputBufferSemaphore = dispatch_semaphore_create(1); -// _handlersQueue = dispatch_queue_create("org.dash.dashsync.peerHandlers", DISPATCH_QUEUE_SERIAL); return self; } @@ -177,7 +175,6 @@ - (instancetype)initWithHost:(NSString *)host onChain:(DSChain *)chain { if (_port == 0) _port = chain.standardPort; self.chain = chain; _outputBufferSemaphore = dispatch_semaphore_create(1); -// _handlersQueue = dispatch_queue_create("org.dash.dashsync.peerHandlers", DISPATCH_QUEUE_SERIAL); return self; } @@ -333,18 +330,16 @@ - (void)disconnectWithError:(NSError *)error { CFRunLoopStop([self.runLoop getCFRunLoop]); -// dispatch_async(self.handlersQueue, ^{ - [NSObject cancelPreviousPerformRequestsWithTarget:self]; - while (self.pongHandlers.count) { - ((void (^)(BOOL))self.pongHandlers[0])(NO); - [self.pongHandlers removeObjectAtIndex:0]; - } - if (self.mempoolTransactionCompletion) self.mempoolTransactionCompletion(NO, YES, YES); - self.mempoolTransactionCompletion = nil; - [self dispatchAsyncInDelegateQueue:^{ - [self.peerDelegate peer:self disconnectedWithError:error]; - }]; -// }); + [NSObject cancelPreviousPerformRequestsWithTarget:self]; + while (self.pongHandlers.count) { + ((void (^)(BOOL))self.pongHandlers[0])(NO); + [self.pongHandlers removeObjectAtIndex:0]; + } + if (self.mempoolTransactionCompletion) self.mempoolTransactionCompletion(NO, YES, YES); + self.mempoolTransactionCompletion = nil; + [self dispatchAsyncInDelegateQueue:^{ + [self.peerDelegate peer:self disconnectedWithError:error]; + }]; } - (void)error:(NSString *)message, ... NS_FORMAT_FUNCTION(1, 2) { @@ -686,19 +681,17 @@ - (void)sendGetaddrMessage { } - (void)sendPingMessageWithPongHandler:(void (^)(BOOL success))pongHandler { -// dispatch_async(self.handlersQueue, ^{ - if (!self.pongHandlers) self.pongHandlers = [NSMutableArray array]; - [self.pongHandlers addObject:(pongHandler) ? [pongHandler copy] : [^(BOOL success) {} copy]]; - uint64_t localNonce = self.localNonce; - self.pingStartTime = [NSDate timeIntervalSince1970]; + if (!self.pongHandlers) self.pongHandlers = [NSMutableArray array]; + [self.pongHandlers addObject:(pongHandler) ? [pongHandler copy] : [^(BOOL success) {} copy]]; + uint64_t localNonce = self.localNonce; + self.pingStartTime = [NSDate timeIntervalSince1970]; #if MESSAGE_LOGGING - DSLog(@"%@:%u sending ping", self.host, self.port); + DSLog(@"%@:%u sending ping", self.host, self.port); #endif - [self dispatchAsyncInDelegateQueue:^{ - [self sendRequest:[DSPingRequest requestWithLocalNonce:localNonce]]; - }]; -// }); + [self dispatchAsyncInDelegateQueue:^{ + [self sendRequest:[DSPingRequest requestWithLocalNonce:localNonce]]; + }]; } // re-request blocks starting from blockHash, useful for getting any additional transactions after a bloom filter update @@ -1605,9 +1598,6 @@ - (void)acceptPongMessage:(NSData *)message { return; } else { __block BOOL hasNoHandlers = ![self.pongHandlers count]; -// dispatch_sync(self.handlersQueue, ^{ -// hasNoHandlers = ![self.pongHandlers count]; -// }); if (hasNoHandlers) { DSLog(@"%@:%u got unexpected pong", self.host, self.port); return; @@ -1625,15 +1615,13 @@ - (void)acceptPongMessage:(NSData *)message { #if MESSAGE_LOGGING DSLog(@"%@:%u got pong in %fs", self.host, self.port, self.pingTime); #endif -// dispatch_async(self.handlersQueue, ^{ - if (self->_status == DSPeerStatus_Connected && self.pongHandlers.count) { - void (^handler)(BOOL) = [self.pongHandlers objectAtIndex:0]; - [self.pongHandlers removeObjectAtIndex:0]; - [self dispatchAsyncInDelegateQueue:^{ - handler(YES); - }]; - } -// }); + if (self->_status == DSPeerStatus_Connected && self.pongHandlers.count) { + void (^handler)(BOOL) = [self.pongHandlers objectAtIndex:0]; + [self.pongHandlers removeObjectAtIndex:0]; + [self dispatchAsyncInDelegateQueue:^{ + handler(YES); + }]; + } } #define SAVE_INCOMING_BLOCKS 0 From 88e91454d9a82a382449c6974257bc47e755e716 Mon Sep 17 00:00:00 2001 From: pankcuf Date: Wed, 13 Sep 2023 15:35:52 +0700 Subject: [PATCH 19/19] chore: update dash-shared-core 0.4.11 (fix: check script nullability) --- DashSync.podspec | 2 +- Example/Podfile.lock | 12 ++++++------ 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/DashSync.podspec b/DashSync.podspec index b7351785b..3c258b0d5 100644 --- a/DashSync.podspec +++ b/DashSync.podspec @@ -34,7 +34,7 @@ Pod::Spec.new do |s| s.ios.framework = 'UIKit' s.macos.framework = 'Cocoa' s.compiler_flags = '-Wno-comma' - s.dependency 'DashSharedCore', '0.4.10' + s.dependency 'DashSharedCore', '0.4.11' s.dependency 'CocoaLumberjack', '3.7.2' s.ios.dependency 'DWAlertController', '0.2.1' s.dependency 'DSDynamicOptions', '0.1.2' diff --git a/Example/Podfile.lock b/Example/Podfile.lock index 97caec045..bb8df6c35 100644 --- a/Example/Podfile.lock +++ b/Example/Podfile.lock @@ -586,11 +586,11 @@ PODS: - "!ProtoCompiler-gRPCPlugin (~> 1.0)" - DAPI-GRPC/Messages - gRPC-ProtoRPC - - DashSharedCore (0.4.10) + - DashSharedCore (0.4.11) - DashSync (0.1.0): - CocoaLumberjack (= 3.7.2) - DAPI-GRPC (= 0.22.0-dev.8) - - DashSharedCore (= 0.4.10) + - DashSharedCore (= 0.4.11) - DSDynamicOptions (= 0.1.2) - DWAlertController (= 0.2.1) - TinyCborObjc (= 0.4.6) @@ -657,7 +657,7 @@ PODS: - gRPC/Interface-Legacy (1.49.0): - gRPC-RxLibrary/Interface (= 1.49.0) - KVO-MVVM (0.5.1) - - Protobuf (3.23.4) + - Protobuf (3.24.3) - SDWebImage (5.14.3): - SDWebImage/Core (= 5.14.3) - SDWebImage/Core (5.14.3) @@ -712,8 +712,8 @@ SPEC CHECKSUMS: CocoaImageHashing: 8656031d0899abe6c1c415827de43e9798189c53 CocoaLumberjack: b7e05132ff94f6ae4dfa9d5bce9141893a21d9da DAPI-GRPC: 138d62523bbfe7e88a39896f1053c0bc12390d9f - DashSharedCore: d107a64758acebc53edacc160ad450f539ff33ee - DashSync: 4a9504583105eb2ace98f38f377cb44fe62f5021 + DashSharedCore: d4dc11749f3555702dbe10c563087e6b48399394 + DashSync: 2d80784e399b869aede6d5bd476a149733451651 DSDynamicOptions: 347cc5d2c4e080eb3de6a86719ad3d861b82adfc DWAlertController: 5f4cd8adf90336331c054857f709f5f8d4b16a5b gRPC: 64f36d689b2ecd99c4351f74e6f91347cdc65d9f @@ -721,7 +721,7 @@ SPEC CHECKSUMS: gRPC-ProtoRPC: 1c223e0f1732bb8d0b9e9e0ea60cc0fe995b8e2d gRPC-RxLibrary: 92327f150e11cf3b1c0f52e083944fd9f5cb5d1e KVO-MVVM: 4df3afd1f7ebcb69735458b85db59c4271ada7c6 - Protobuf: c6bc59bbab3d38a71c67f62d7cb7ca8f8ea4eca1 + Protobuf: 970f7ee93a3a08e3cf64859b8efd95ee32b4f87f SDWebImage: 9c36e66c8ce4620b41a7407698dda44211a96764 tinycbor: d4d71dddda1f8392fbb4249f63faf8552f327590 TinyCborObjc: 5204540fb90ff0c40fb22d408fa51bab79d78a80