diff --git a/DashSync.podspec b/DashSync.podspec index 3c258b0d5..24d4e3756 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.11' + s.dependency 'DashSharedCore', '0.4.14' s.dependency 'CocoaLumberjack', '3.7.2' s.ios.dependency 'DWAlertController', '0.2.1' s.dependency 'DSDynamicOptions', '0.1.2' diff --git a/DashSync/shared/Categories/NSData/NSMutableData+Dash.m b/DashSync/shared/Categories/NSData/NSMutableData+Dash.m index a4865b010..4a79f9667 100644 --- a/DashSync/shared/Categories/NSData/NSMutableData+Dash.m +++ b/DashSync/shared/Categories/NSData/NSMutableData+Dash.m @@ -65,7 +65,7 @@ static void secureDeallocate(void *ptr, void *info) { } // Since iOS does not page memory to storage, all we need to do is cleanse allocated memory prior to deallocation. -CFAllocatorRef SecureAllocator() { +CFAllocatorRef SecureAllocator(void) { static CFAllocatorRef alloc = NULL; static dispatch_once_t onceToken = 0; diff --git a/DashSync/shared/DashSync.xcdatamodeld/.xccurrentversion b/DashSync/shared/DashSync.xcdatamodeld/.xccurrentversion index 7bc3c9385..5cbe4fe8d 100644 --- a/DashSync/shared/DashSync.xcdatamodeld/.xccurrentversion +++ b/DashSync/shared/DashSync.xcdatamodeld/.xccurrentversion @@ -3,6 +3,6 @@ _XCCurrentVersionName - DashSync 19.xcdatamodel + DashSync 20.xcdatamodel diff --git a/DashSync/shared/DashSync.xcdatamodeld/DashSync 20.xcdatamodel/contents b/DashSync/shared/DashSync.xcdatamodeld/DashSync 20.xcdatamodel/contents new file mode 100644 index 000000000..559561efb --- /dev/null +++ b/DashSync/shared/DashSync.xcdatamodeld/DashSync 20.xcdatamodel/contents @@ -0,0 +1,518 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/DashSync/shared/Libraries/DSLogger.m b/DashSync/shared/Libraries/DSLogger.m index 4089ed18b..5f59dc9c7 100644 --- a/DashSync/shared/Libraries/DSLogger.m +++ b/DashSync/shared/Libraries/DSLogger.m @@ -19,6 +19,14 @@ NS_ASSUME_NONNULL_BEGIN +@interface NoTimestampLogFormatter : NSObject +@end +@implementation NoTimestampLogFormatter +- (nullable NSString *)formatLogMessage:(DDLogMessage *)logMessage { + return logMessage.message; +} +@end + @interface DSLogger () @property (readonly, nonatomic, strong) DDFileLogger *fileLogger; @@ -44,6 +52,7 @@ - (instancetype)init { DDFileLogger *fileLogger = [[DDFileLogger alloc] init]; fileLogger.rollingFrequency = 60 * 60 * 24; // 24 hour rolling fileLogger.logFileManager.maximumNumberOfLogFiles = 3; // keep a 3 days worth of log files + //[fileLogger setLogFormatter:[[NoTimestampLogFormatter alloc] init]]; // Use the custom formatter [DDLog addLogger:fileLogger]; _fileLogger = fileLogger; } diff --git a/DashSync/shared/Libraries/Networking/Private/SPTDataLoaderExponentialTimer.m b/DashSync/shared/Libraries/Networking/Private/SPTDataLoaderExponentialTimer.m index 3693a1c9c..dc48ff635 100644 --- a/DashSync/shared/Libraries/Networking/Private/SPTDataLoaderExponentialTimer.m +++ b/DashSync/shared/Libraries/Networking/Private/SPTDataLoaderExponentialTimer.m @@ -128,7 +128,7 @@ - (NSTimeInterval)timeIntervalAndCalculateNext { #define EXPT_MODULO ((u_int32_t)RAND_MAX) #define EXPT_MODULO_F64 ((double)(EXPT_MODULO)) -NS_INLINE double SPTExptRandom() { +NS_INLINE double SPTExptRandom(void) { // We need [0, 1) interval return arc4random_uniform(EXPT_MODULO); } diff --git a/DashSync/shared/Models/Chain/DSChainConstants.h b/DashSync/shared/Models/Chain/DSChainConstants.h index f352c2000..7776a9e2a 100644 --- a/DashSync/shared/Models/Chain/DSChainConstants.h +++ b/DashSync/shared/Models/Chain/DSChainConstants.h @@ -34,10 +34,10 @@ #define PROTOCOL_VERSION_MAINNET 70228 #define DEFAULT_MIN_PROTOCOL_VERSION_MAINNET 70228 -#define PROTOCOL_VERSION_TESTNET 70228 +#define PROTOCOL_VERSION_TESTNET 70230 #define DEFAULT_MIN_PROTOCOL_VERSION_TESTNET 70228 -#define PROTOCOL_VERSION_DEVNET 70228 +#define PROTOCOL_VERSION_DEVNET 70230 #define DEFAULT_MIN_PROTOCOL_VERSION_DEVNET 70228 #define PLATFORM_PROTOCOL_VERSION_MAINNET 1 diff --git a/DashSync/shared/Models/Chain/DSChainLock.m b/DashSync/shared/Models/Chain/DSChainLock.m index 2f5b0ed9d..4f50f3e10 100644 --- a/DashSync/shared/Models/Chain/DSChainLock.m +++ b/DashSync/shared/Models/Chain/DSChainLock.m @@ -119,9 +119,9 @@ - (BOOL)verifySignatureAgainstQuorum:(DSQuorumEntry *)quorumEntry { UInt256 signId = [self signIDForQuorumEntry:quorumEntry]; BOOL verified = key_bls_verify(quorumEntry.quorumPublicKey.u8, quorumEntry.useLegacyBLSScheme, signId.u8, self.signature.u8); #if DEBUG - DSLog(@"verifySignatureAgainstQuorum (%u): %u: %u: %@: %@: %@: %@: %u", verified, quorumEntry.llmqType, quorumEntry.verified, uint256_hex(quorumEntry.llmqQuorumHash), @"", uint384_hex(quorumEntry.quorumPublicKey), @"", quorumEntry.useLegacyBLSScheme); + DSLog(@"verifySignatureAgainstQuorum (%u): %u: %u: %@: %@: %@: %u", verified, quorumEntry.llmqType, quorumEntry.verified, @"", uint384_hex(quorumEntry.quorumPublicKey), @"", quorumEntry.useLegacyBLSScheme); #else - DSLogPrivate(@"verifySignatureAgainstQuorum (%u): %u: %u: %@: %@: %@: %@: %u", verified, quorumEntry.llmqType, quorumEntry.verified, uint256_hex(quorumEntry.llmqQuorumHash), uint256_hex(signId), uint384_hex(quorumEntry.quorumPublicKey), uint768_hex(self.signature), quorumEntry.useLegacyBLSScheme); + DSLogPrivate(@"verifySignatureAgainstQuorum (%u): %u: %u: %@: %@: %@: %u", verified, quorumEntry.llmqType, quorumEntry.verified, uint256_hex(signId), uint384_hex(quorumEntry.quorumPublicKey), uint768_hex(self.signature), quorumEntry.useLegacyBLSScheme); #endif return verified; } diff --git a/DashSync/shared/Models/Chain/DSFullBlock.m b/DashSync/shared/Models/Chain/DSFullBlock.m index 3f486b019..cc268d002 100644 --- a/DashSync/shared/Models/Chain/DSFullBlock.m +++ b/DashSync/shared/Models/Chain/DSFullBlock.m @@ -99,7 +99,7 @@ - (instancetype)initWithMessage:(NSData *)message onChain:(DSChain *)chain { } - (instancetype)initWithCoinbaseTransaction:(DSCoinbaseTransaction *)coinbaseTransaction transactions:(NSSet *)transactions previousBlockHash:(UInt256)previousBlockHash previousBlocks:(NSDictionary *)previousBlocks timestamp:(uint32_t)timestamp height:(uint32_t)height onChain:(DSChain *)chain { - if (!(self = [super initWithVersion:2 timestamp:timestamp height:height onChain:chain])) return nil; + if (!(self = [super initWithVersion:COINBASE_TX_CORE_19 timestamp:timestamp height:height onChain:chain])) return nil; NSMutableSet *totalTransactionsSet = [transactions mutableCopy]; [totalTransactionsSet addObject:coinbaseTransaction]; self.totalTransactions = (uint32_t)[totalTransactionsSet count]; diff --git a/DashSync/shared/Models/Entities/DSCoinbaseTransactionEntity+CoreDataClass.m b/DashSync/shared/Models/Entities/DSCoinbaseTransactionEntity+CoreDataClass.m index 80299c462..ef06f6804 100644 --- a/DashSync/shared/Models/Entities/DSCoinbaseTransactionEntity+CoreDataClass.m +++ b/DashSync/shared/Models/Entities/DSCoinbaseTransactionEntity+CoreDataClass.m @@ -20,6 +20,14 @@ - (instancetype)setAttributesFromTransaction:(DSTransaction *)tx { self.specialTransactionVersion = coinbaseTransaction.coinbaseTransactionVersion; self.height = coinbaseTransaction.height; self.merkleRootMNList = uint256_data(coinbaseTransaction.merkleRootMNList); + if (self.specialTransactionVersion >= COINBASE_TX_CORE_19) { + self.merkleRootLLMQList = uint256_data(coinbaseTransaction.merkleRootLLMQList); + if (self.specialTransactionVersion >= COINBASE_TX_CORE_20) { + self.bestCLHeightDiff = coinbaseTransaction.bestCLHeightDiff; + self.bestCLSignature = uint768_data(coinbaseTransaction.bestCLSignature); + self.creditPoolBalance = coinbaseTransaction.creditPoolBalance; + } + } }]; return self; @@ -32,11 +40,22 @@ - (DSTransaction *)transactionForChain:(DSChain *)chain { transaction.coinbaseTransactionVersion = self.specialTransactionVersion; transaction.height = self.height; transaction.merkleRootMNList = self.merkleRootMNList.UInt256; + + if (self.specialTransactionVersion >= COINBASE_TX_CORE_19) { + transaction.merkleRootLLMQList = self.merkleRootLLMQList.UInt256; + if (self.specialTransactionVersion >= COINBASE_TX_CORE_20) { + transaction.bestCLHeightDiff = self.bestCLHeightDiff; + transaction.bestCLSignature = self.bestCLSignature.UInt768; + transaction.creditPoolBalance = self.creditPoolBalance; + } + } }]; return transaction; } + + - (Class)transactionClass { return [DSCoinbaseTransaction class]; } diff --git a/DashSync/shared/Models/Entities/DSCoinbaseTransactionEntity+CoreDataProperties.h b/DashSync/shared/Models/Entities/DSCoinbaseTransactionEntity+CoreDataProperties.h index ce6fc7c70..c6e29af60 100644 --- a/DashSync/shared/Models/Entities/DSCoinbaseTransactionEntity+CoreDataProperties.h +++ b/DashSync/shared/Models/Entities/DSCoinbaseTransactionEntity+CoreDataProperties.h @@ -16,7 +16,13 @@ NS_ASSUME_NONNULL_BEGIN + (NSFetchRequest *)fetchRequest; @property (assign, nonatomic) uint32_t height; + @property (nullable, nonatomic, retain) NSData *merkleRootMNList; +@property (nullable, nonatomic, retain) NSData *merkleRootLLMQList; + +@property (assign, nonatomic) uint32_t bestCLHeightDiff; +@property (nullable, nonatomic, retain) NSData *bestCLSignature; +@property (assign, nonatomic) int64_t creditPoolBalance; @end diff --git a/DashSync/shared/Models/Entities/DSCoinbaseTransactionEntity+CoreDataProperties.m b/DashSync/shared/Models/Entities/DSCoinbaseTransactionEntity+CoreDataProperties.m index c83ac6d9c..22a99d984 100644 --- a/DashSync/shared/Models/Entities/DSCoinbaseTransactionEntity+CoreDataProperties.m +++ b/DashSync/shared/Models/Entities/DSCoinbaseTransactionEntity+CoreDataProperties.m @@ -16,5 +16,9 @@ @implementation DSCoinbaseTransactionEntity (CoreDataProperties) @dynamic height; @dynamic merkleRootMNList; +@dynamic merkleRootLLMQList; +@dynamic bestCLHeightDiff; +@dynamic bestCLSignature; +@dynamic creditPoolBalance; @end diff --git a/DashSync/shared/Models/Managers/Chain Managers/DSChainManager.h b/DashSync/shared/Models/Managers/Chain Managers/DSChainManager.h index 113c34187..500977193 100644 --- a/DashSync/shared/Models/Managers/Chain Managers/DSChainManager.h +++ b/DashSync/shared/Models/Managers/Chain Managers/DSChainManager.h @@ -97,6 +97,8 @@ typedef void (^MultipleBlockMiningCompletionBlock)(NSArray *block - (void)mineBlockAfterBlock:(DSBlock *)block toPaymentAddress:(NSString *)paymentAddress withTransactions:(NSArray *_Nullable)transactions previousBlocks:(NSDictionary *)previousBlocks nonceOffset:(uint32_t)nonceOffset withTimeout:(NSTimeInterval)timeout completion:(BlockMiningCompletionBlock)completion; +- (DSChainLock * _Nullable)chainLockForBlockHash:(UInt256)blockHash; + @end NS_ASSUME_NONNULL_END diff --git a/DashSync/shared/Models/Managers/Chain Managers/DSChainManager.m b/DashSync/shared/Models/Managers/Chain Managers/DSChainManager.m index 3d43643c8..d83a39795 100644 --- a/DashSync/shared/Models/Managers/Chain Managers/DSChainManager.m +++ b/DashSync/shared/Models/Managers/Chain Managers/DSChainManager.m @@ -676,7 +676,7 @@ - (void)chainFinishedSyncingTransactionsAndBlocks:(DSChain *)chain fromPeer:(DSP } - (void)syncBlockchain { - DSLog(@"syncBlockchain connected peers: %d phase: %d", self.peerManager.connectedPeerCount, self.syncPhase); + DSLog(@"syncBlockchain connected peers: %lu phase: %d", self.peerManager.connectedPeerCount, self.syncPhase); if (self.peerManager.connectedPeerCount == 0) { if (self.syncPhase == DSChainSyncPhase_InitialTerminalBlocks) { self.syncPhase = DSChainSyncPhase_ChainSync; @@ -794,4 +794,8 @@ - (void)wipeMasternodeInfo { [self.masternodeManager wipeMasternodeInfo]; } +- (DSChainLock * _Nullable)chainLockForBlockHash:(UInt256)blockHash { + return [self.transactionManager chainLockForBlockHash:blockHash]; +} + @end diff --git a/DashSync/shared/Models/Managers/Chain Managers/DSMasternodeManager+Mndiff.h b/DashSync/shared/Models/Managers/Chain Managers/DSMasternodeManager+Mndiff.h index faff3b684..e94622df3 100644 --- a/DashSync/shared/Models/Managers/Chain Managers/DSMasternodeManager+Mndiff.h +++ b/DashSync/shared/Models/Managers/Chain Managers/DSMasternodeManager+Mndiff.h @@ -34,7 +34,7 @@ NS_ASSUME_NONNULL_BEGIN MasternodeList *getMasternodeListByBlockHash(uint8_t (*block_hash)[32], const void *context); bool saveMasternodeList(uint8_t (*block_hash)[32], MasternodeList *masternode_list, const void *context); void destroyMasternodeList(MasternodeList *masternode_list); -void destroyHash(uint8_t *block_hash); +void destroyU8(uint8_t *block_hash); uint32_t getBlockHeightByHash(uint8_t (*block_hash)[32], const void *context); uint8_t *getBlockHashByHeight(uint32_t block_height, const void *context); uint8_t *getMerkleRootByHash(uint8_t (*block_hash)[32], const void *context); diff --git a/DashSync/shared/Models/Managers/Chain Managers/DSMasternodeManager+Mndiff.m b/DashSync/shared/Models/Managers/Chain Managers/DSMasternodeManager+Mndiff.m index b308e0d99..c46a523ba 100644 --- a/DashSync/shared/Models/Managers/Chain Managers/DSMasternodeManager+Mndiff.m +++ b/DashSync/shared/Models/Managers/Chain Managers/DSMasternodeManager+Mndiff.m @@ -29,18 +29,20 @@ #import "DSSimplifiedMasternodeEntry+Mndiff.h" #import "NSData+Dash.h" +#define AS_OBJC(context) ((__bridge DSMasternodeProcessorContext *)(context)) +#define AS_RUST(context) ((__bridge void *)(context)) + @implementation DSMasternodeManager (Mndiff) + /// /// MARK: Rust FFI callbacks /// MasternodeList *getMasternodeListByBlockHash(uint8_t (*block_hash)[32], const void *context) { UInt256 blockHash = *((UInt256 *)block_hash); - DSMasternodeProcessorContext *processorContext = NULL; MasternodeList *c_list = NULL; @synchronized (context) { - processorContext = (__bridge DSMasternodeProcessorContext *)context; - DSMasternodeList *list = processorContext.masternodeListLookup(blockHash); + DSMasternodeList *list = [AS_OBJC(context) masternodeListForBlockHash:blockHash]; if (list) { c_list = [list ffi_malloc]; } @@ -51,13 +53,11 @@ @implementation DSMasternodeManager (Mndiff) bool saveMasternodeList(uint8_t (*block_hash)[32], MasternodeList *masternode_list, const void *context) { UInt256 blockHash = *((UInt256 *)block_hash); - DSMasternodeProcessorContext *processorContext = NULL; BOOL saved = NO; @synchronized (context) { - processorContext = (__bridge DSMasternodeProcessorContext *)context; - DSChain *chain = processorContext.chain; - DSMasternodeList *masternodeList = [DSMasternodeList masternodeListWith:masternode_list onChain:chain]; - saved = [chain.chainManager.masternodeManager saveMasternodeList:masternodeList forBlockHash:blockHash]; + DSMasternodeProcessorContext *processorContext = AS_OBJC(context); + DSMasternodeList *masternodeList = [DSMasternodeList masternodeListWith:masternode_list onChain:processorContext.chain]; + saved = [processorContext saveMasternodeList:masternodeList forBlockHash:blockHash]; } processor_destroy_block_hash(block_hash); processor_destroy_masternode_list(masternode_list); @@ -68,31 +68,26 @@ void destroyMasternodeList(MasternodeList *masternode_list) { [DSMasternodeList ffi_free:masternode_list]; } -void destroyHash(uint8_t *block_hash) { // UInt256 +void destroyU8(uint8_t *block_hash) { // big uint if (block_hash) { free(block_hash); } } uint32_t getBlockHeightByHash(uint8_t (*block_hash)[32], const void *context) { - DSMasternodeProcessorContext *processorContext = NULL; UInt256 blockHash = *((UInt256 *)block_hash); uint32_t block_height = UINT32_MAX; @synchronized (context) { - processorContext = (__bridge DSMasternodeProcessorContext *)context; - block_height = processorContext.blockHeightLookup(blockHash); + block_height = [AS_OBJC(context) blockHeightForBlockHash:blockHash]; } processor_destroy_block_hash(block_hash); return block_height; } uint8_t *getBlockHashByHeight(uint32_t block_height, const void *context) { - DSMasternodeProcessorContext *processorContext = NULL; uint8_t (*block_hash)[32] = NULL; @synchronized (context) { - processorContext = (__bridge DSMasternodeProcessorContext *)context; - DSChain *chain = processorContext.chain; - DSBlock *block = [chain blockAtHeight:block_height]; + DSBlock *block = [AS_OBJC(context) blockForBlockHeight:block_height]; if (block) { block_hash = uint256_malloc(block.blockHash); } @@ -102,12 +97,10 @@ uint32_t getBlockHeightByHash(uint8_t (*block_hash)[32], const void *context) { uint8_t *getMerkleRootByHash(uint8_t (*block_hash)[32], const void *context) { - DSMasternodeProcessorContext *processorContext = NULL; UInt256 blockHash = *((UInt256 *)block_hash); uint8_t (*merkle_root)[32] = NULL; @synchronized (context) { - processorContext = (__bridge DSMasternodeProcessorContext *)context; - UInt256 merkleRoot = processorContext.merkleRootLookup(blockHash); + UInt256 merkleRoot = [AS_OBJC(context) merkleRootForBlockHash:blockHash]; merkle_root = uint256_malloc(merkleRoot); } processor_destroy_block_hash(block_hash); @@ -115,13 +108,10 @@ uint32_t getBlockHeightByHash(uint8_t (*block_hash)[32], const void *context) { } LLMQSnapshot *getLLMQSnapshotByBlockHash(uint8_t (*block_hash)[32], const void *context) { - DSMasternodeProcessorContext *processorContext = NULL; UInt256 blockHash = *((UInt256 *)block_hash); LLMQSnapshot *c_snapshot = NULL; @synchronized (context) { - processorContext = (__bridge DSMasternodeProcessorContext *)context; - DSChain *chain = processorContext.chain; - DSQuorumSnapshot *snapshot = [chain.chainManager.masternodeManager quorumSnapshotForBlockHash:blockHash]; + DSQuorumSnapshot *snapshot = [AS_OBJC(context) quorumSnapshotForBlockHash:blockHash]; if (snapshot) { c_snapshot = [snapshot ffi_malloc]; } @@ -132,14 +122,10 @@ uint32_t getBlockHeightByHash(uint8_t (*block_hash)[32], const void *context) { bool saveLLMQSnapshot(uint8_t (*block_hash)[32], LLMQSnapshot *snapshot, const void *context) { - DSMasternodeProcessorContext *processorContext = NULL; UInt256 blockHash = *((UInt256 *)block_hash); BOOL saved = NO; @synchronized (context) { - processorContext = (__bridge DSMasternodeProcessorContext *)context; - DSChain *chain = processorContext.chain; - DSQuorumSnapshot *quorumSnapshot = [DSQuorumSnapshot quorumSnapshotWith:snapshot forBlockHash:blockHash]; - saved = [chain.chainManager.masternodeManager saveQuorumSnapshot:quorumSnapshot]; + saved = [AS_OBJC(context) saveQuorumSnapshot:[DSQuorumSnapshot quorumSnapshotWith:snapshot forBlockHash:blockHash]]; } processor_destroy_block_hash(block_hash); processor_destroy_llmq_snapshot(snapshot); @@ -149,59 +135,48 @@ void destroyLLMQSnapshot(LLMQSnapshot *snapshot) { [DSQuorumSnapshot ffi_free:snapshot]; } +uint8_t *getCLSignatureByBlockHash(uint8_t (*block_hash)[32], const void *context) { + UInt256 blockHash = *((UInt256 *)block_hash); + uint8_t (*cl_signature)[96] = NULL; + @synchronized (context) { + NSData *signature = [AS_OBJC(context) CLSignatureForBlockHash:blockHash]; + if (signature) { + cl_signature = uint768_malloc(signature.UInt768); + } + } + processor_destroy_block_hash(block_hash); + return (uint8_t *)cl_signature; +} +bool saveCLSignature(uint8_t (*block_hash)[32], uint8_t (*cl_signature)[96], const void *context) { + UInt256 blockHash = *((UInt256 *)block_hash); + UInt768 clSignature = *((UInt768 *)cl_signature); + BOOL saved = NO; + @synchronized (context) { + saved = [AS_OBJC(context) saveCLSignature:blockHash signature:clSignature]; + } + processor_destroy_block_hash(block_hash); + processor_destroy_cl_signature(cl_signature); + return saved; +} + void addInsightForBlockHash(uint8_t (*block_hash)[32], const void *context) { - DSMasternodeProcessorContext *processorContext = NULL; UInt256 blockHash = *((UInt256 *)block_hash); @synchronized (context) { - processorContext = (__bridge DSMasternodeProcessorContext *)context; - DSChain *chain = processorContext.chain; - [chain blockUntilGetInsightForBlockHash:blockHash]; + [AS_OBJC(context) blockUntilGetInsightForBlockHash:blockHash]; } processor_destroy_block_hash(block_hash); } ProcessingError shouldProcessDiffWithRange(uint8_t (*base_block_hash)[32], uint8_t (*block_hash)[32], const void *context) { - DSMasternodeProcessorContext *processorContext = NULL; UInt256 baseBlockHash = *((UInt256 *)base_block_hash); UInt256 blockHash = *((UInt256 *)block_hash); processor_destroy_block_hash(base_block_hash); processor_destroy_block_hash(block_hash); + ProcessingError error = ProcessingError_None; @synchronized (context) { - processorContext = (__bridge DSMasternodeProcessorContext *)context; - uint32_t baseBlockHeight = processorContext.blockHeightLookup(baseBlockHash); - uint32_t blockHeight = processorContext.blockHeightLookup(blockHash); - if (blockHeight == UINT32_MAX) { - DSLog(@"•••• shouldProcessDiffWithRange: unknown blockHash: %u..%u %@ .. %@", baseBlockHeight, blockHeight, uint256_reverse_hex(baseBlockHash), uint256_reverse_hex(blockHash)); - return ProcessingError_UnknownBlockHash; - } - DSChain *chain = processorContext.chain; - DSMasternodeManager *manager = chain.chainManager.masternodeManager; - DSMasternodeListService *service = processorContext.isDIP0024 ? manager.quorumRotationService : manager.masternodeListDiffService; - BOOL hasRemovedFromRetrieval = [service removeRequestInRetrievalForBaseBlockHash:baseBlockHash blockHash:blockHash]; - if (!hasRemovedFromRetrieval) { - DSLog(@"•••• shouldProcessDiffWithRange: persist in retrieval: %u..%u %@ .. %@", baseBlockHeight, blockHeight, uint256_reverse_hex(baseBlockHash), uint256_reverse_hex(blockHash)); - return ProcessingError_PersistInRetrieval; - } - NSData *blockHashData = uint256_data(blockHash); - DSMasternodeList *list = processorContext.masternodeListLookup(blockHash); - BOOL needToVerifyRotatedQuorums = processorContext.isDIP0024 && (!manager.quorumRotationService.masternodeListAtH || [manager.quorumRotationService.masternodeListAtH hasUnverifiedRotatedQuorums]); - BOOL needToVerifyNonRotatedQuorums = !processorContext.isDIP0024 && [list hasUnverifiedNonRotatedQuorums]; - BOOL noNeedToVerifyQuorums = !(needToVerifyRotatedQuorums || needToVerifyNonRotatedQuorums); - BOOL hasLocallyStored = [manager.store hasMasternodeListAt:blockHashData]; - if (hasLocallyStored && noNeedToVerifyQuorums) { - DSLog(@"•••• shouldProcessDiffWithRange: already persist: %u: %@ needToVerifyRotatedQuorums: %d needToVerifyNonRotatedQuorums: %d", blockHeight, uint256_reverse_hex(blockHash), needToVerifyRotatedQuorums, needToVerifyNonRotatedQuorums); - [service removeFromRetrievalQueue:blockHashData]; - return ProcessingError_LocallyStored; - } - DSMasternodeList *baseMasternodeList = processorContext.masternodeListLookup(baseBlockHash); - if (!baseMasternodeList && !uint256_eq(chain.genesisHash, baseBlockHash) && uint256_is_not_zero(baseBlockHash)) { - // this could have been deleted in the meantime, if so rerequest - [service issueWithMasternodeListFromPeer:processorContext.peer]; - DSLog(@"•••• No base masternode list at: %d: %@", baseBlockHeight, uint256_reverse_hex(baseBlockHash)); - return ProcessingError_HasNoBaseBlockHash; - } + error = [AS_OBJC(context) shouldProcessDiffWithRange:baseBlockHash blockHash:blockHash]; } - return ProcessingError_None; + return error; } /// @@ -215,11 +190,13 @@ + (MasternodeProcessor *)registerProcessor { getBlockHashByHeight, getLLMQSnapshotByBlockHash, saveLLMQSnapshot, + getCLSignatureByBlockHash, + saveCLSignature, getMasternodeListByBlockHash, saveMasternodeList, destroyMasternodeList, addInsightForBlockHash, - destroyHash, + destroyU8, destroyLLMQSnapshot, shouldProcessDiffWithRange); } @@ -255,7 +232,7 @@ - (void)processMasternodeDiffWith:(NSData *)message context:(DSMasternodeProcess context.peer ? context.peer.version : context.chain.protocolVersion, self.processor, self.processorCache, - (__bridge void *)(context)); + AS_RUST(context)); DSMnDiffProcessingResult *processingResult = [DSMnDiffProcessingResult processingResultWith:result onChain:context.chain]; processor_destroy_mnlistdiff_result(result); completion(processingResult); @@ -274,7 +251,7 @@ - (void)processQRInfoWith:(NSData *)message context:(DSMasternodeProcessorContex context.peer ? context.peer.version : context.chain.protocolVersion, self.processor, self.processorCache, - (__bridge void *)(context)); + AS_RUST(context)); DSQRInfoProcessingResult *processingResult = [DSQRInfoProcessingResult processingResultWith:result onChain:context.chain]; processor_destroy_qr_info_result(result); completion(processingResult); @@ -294,7 +271,7 @@ - (DSMnDiffProcessingResult *)processMasternodeDiffFromFile:(NSData *)message pr protocolVersion, self.processor, self.processorCache, - (__bridge void *)(context)); + AS_RUST(context)); } DSMnDiffProcessingResult *processingResult = [DSMnDiffProcessingResult processingResultWith:result onChain:context.chain]; processor_destroy_mnlistdiff_result(result); diff --git a/DashSync/shared/Models/Managers/Chain Managers/DSMasternodeManager+Protected.h b/DashSync/shared/Models/Managers/Chain Managers/DSMasternodeManager+Protected.h index 32b8f8e07..c5b813f93 100644 --- a/DashSync/shared/Models/Managers/Chain Managers/DSMasternodeManager+Protected.h +++ b/DashSync/shared/Models/Managers/Chain Managers/DSMasternodeManager+Protected.h @@ -46,7 +46,7 @@ NS_ASSUME_NONNULL_BEGIN - (DSLocalMasternode *)localMasternodeFromSimplifiedMasternodeEntry:(DSSimplifiedMasternodeEntry *)simplifiedMasternodeEntry claimedWithOwnerWallet:(DSWallet *)wallet ownerKeyIndex:(uint32_t)ownerKeyIndex; -+ (void)saveMasternodeList:(DSMasternodeList *)masternodeList toChain:(DSChain *)chain havingModifiedMasternodes:(NSDictionary *)modifiedMasternodes addedQuorums:(NSDictionary *)addedQuorums createUnknownBlocks:(BOOL)createUnknownBlocks inContext:(NSManagedObjectContext *)context completion:(void (^)(NSError *error))completion; ++ (void)saveMasternodeList:(DSMasternodeList *)masternodeList toChain:(DSChain *)chain havingModifiedMasternodes:(NSDictionary *)modifiedMasternodes createUnknownBlocks:(BOOL)createUnknownBlocks inContext:(NSManagedObjectContext *)context completion:(void (^)(NSError *error))completion; @end diff --git a/DashSync/shared/Models/Managers/Chain Managers/DSMasternodeManager.h b/DashSync/shared/Models/Managers/Chain Managers/DSMasternodeManager.h index 3f78b4f48..6f931d3c0 100644 --- a/DashSync/shared/Models/Managers/Chain Managers/DSMasternodeManager.h +++ b/DashSync/shared/Models/Managers/Chain Managers/DSMasternodeManager.h @@ -86,6 +86,10 @@ NS_ASSUME_NONNULL_BEGIN - (BOOL)saveQuorumSnapshot:(DSQuorumSnapshot *)snapshot; - (BOOL)saveMasternodeList:(DSMasternodeList *)masternodeList forBlockHash:(UInt256)blockHash; +- (NSData *_Nullable)CLSignatureForBlockHeight:(uint32_t)blockHeight; +- (NSData *_Nullable)CLSignatureForBlockHash:(UInt256)blockHash; +- (BOOL)saveCLSignature:(NSData *)blockHashData signatureData:(NSData *)signatureData; + - (void)startSync; - (BOOL)requestMasternodeListForBlockHeight:(uint32_t)blockHeight error:(NSError *_Nullable *_Nullable)error; - (BOOL)requestMasternodeListForBlockHash:(UInt256)blockHash; @@ -97,6 +101,7 @@ NS_ASSUME_NONNULL_BEGIN - (void)checkPingTimesForCurrentMasternodeListInContext:(NSManagedObjectContext *)context withCompletion:(void (^)(NSMutableDictionary *pingTimes, NSMutableDictionary *errors))completion; +- (UInt256)buildLLMQHashFor:(DSQuorumEntry *)quorum; @end NS_ASSUME_NONNULL_END diff --git a/DashSync/shared/Models/Managers/Chain Managers/DSMasternodeManager.m b/DashSync/shared/Models/Managers/Chain Managers/DSMasternodeManager.m index bdb984a3d..c4609b2fc 100644 --- a/DashSync/shared/Models/Managers/Chain Managers/DSMasternodeManager.m +++ b/DashSync/shared/Models/Managers/Chain Managers/DSMasternodeManager.m @@ -25,6 +25,7 @@ #import "DSMasternodeManager.h" #import "DSChain+Protected.h" +#import "DSChainLock.h" #import "DSChainManager+Protected.h" #import "DSCheckpoint.h" #import "DSGetMNListDiffRequest.h" @@ -297,6 +298,34 @@ - (BOOL)saveQuorumSnapshot:(DSQuorumSnapshot *)snapshot { return YES; } +// MARK: - ChainLock Signature List Helpers +- (NSData *_Nullable)CLSignatureForBlockHeight:(uint32_t)blockHeight { + DSBlock *block = [self.chain blockAtHeight:blockHeight]; + if (!block) { + DSLog(@"No block for snapshot at height: %ul: ", blockHeight); + return nil; + } + return [self.store.cachedCLSignatures objectForKey:uint256_data(block.blockHash)]; +} + +- (NSData *_Nullable)CLSignatureForBlockHash:(UInt256)blockHash { + NSData *cachedSig = [self.store.cachedCLSignatures objectForKey:uint256_data(blockHash)]; + if (!cachedSig) { + DSChainLock *chainLock = [self.chain.chainManager chainLockForBlockHash:blockHash]; + if (chainLock) { + return uint768_data(chainLock.signature); + } + } + return cachedSig; +} + +- (BOOL)saveCLSignature:(NSData *)blockHashData signatureData:(NSData *)signatureData { + [self.store.cachedCLSignatures setObject:signatureData forKey:blockHashData]; + return YES; +} + +// MARK: - Masternode List Helpers + - (BOOL)saveMasternodeList:(DSMasternodeList *)masternodeList forBlockHash:(UInt256)blockHash { /// TODO: need to properly store in CoreData or wait for rust SQLite DSLog(@"••• addMasternodeList (saveMasternodeList) -> %@: %@", uint256_hex(blockHash), masternodeList); @@ -304,8 +333,6 @@ - (BOOL)saveMasternodeList:(DSMasternodeList *)masternodeList forBlockHash:(UInt return YES; } -// MARK: - Masternode List Helpers - - (DSMasternodeList *)masternodeListForBlockHash:(UInt256)blockHash { return [self masternodeListForBlockHash:blockHash withBlockHeightLookup:nil]; } @@ -411,7 +438,6 @@ - (DSMasternodeList *__nullable)processRequestFromFileForBlockHash:(UInt256)bloc [self.store saveMasternodeList:masternodeList addedMasternodes:result.addedMasternodes modifiedMasternodes:result.modifiedMasternodes - addedQuorums:result.addedQuorums completion:^(NSError *_Nonnull error) { DSLog(@"MNL Saved from file"); }]; @@ -522,7 +548,7 @@ - (void)processMasternodeListDiffResult:(DSMnDiffProcessingResult *)result forPe } } 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) { + [self updateStoreWithProcessingResult:masternodeList result:result completion:^(NSError *error) { if ([result hasRotatedQuorumsForChain:self.chain] && !self.chain.isRotatedQuorumsPresented) { uint32_t masternodeListBlockHeight = [self heightForBlockHash:masternodeListBlockHash]; DSLog(@"•••• processMasternodeListDiffResult: rotated quorums are presented at height %u: %@, so we'll switch into consuming qrinfo", masternodeListBlockHeight, uint256_hex(masternodeListBlockHash)); @@ -597,32 +623,32 @@ - (void)processQRInfoResult:(DSQRInfoProcessingResult *)result forPeer:(DSPeer * if (![self.quorumRotationService shouldProcessDiffResult:mnListDiffResultAtH4C skipPresenceInRetrieval:YES]) { [self.quorumRotationService issueWithMasternodeListFromPeer:peer]; } 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) {}]; +// DSLog(@"••• updateStoreWithMasternodeList (h-4c): %u: %@ (%@)", masternodeListAtH4C.height, uint256_hex(blockHashAtH4C), uint256_reverse_hex(blockHashAtH4C)); + [self updateStoreWithProcessingResult:masternodeListAtH4C result:mnListDiffResultAtH4C completion:^(NSError *error) {}]; } if (![self.quorumRotationService shouldProcessDiffResult:mnListDiffResultAtH3C skipPresenceInRetrieval:YES]) { [self.quorumRotationService issueWithMasternodeListFromPeer:peer]; } 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) {}]; +// DSLog(@"••• updateStoreWithMasternodeList (h-3c): %u: %@ (%@)", masternodeListAtH3C.height, uint256_hex(blockHashAtH3C), uint256_reverse_hex(blockHashAtH3C)); + [self updateStoreWithProcessingResult:masternodeListAtH3C result:mnListDiffResultAtH3C completion:^(NSError *error) {}]; } if (![self.quorumRotationService shouldProcessDiffResult:mnListDiffResultAtH2C skipPresenceInRetrieval:YES]) { [self.quorumRotationService issueWithMasternodeListFromPeer:peer]; } 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) {}]; +// DSLog(@"••• updateStoreWithMasternodeList (h-2c): %u: %@ (%@)", masternodeListAtH2C.height, uint256_hex(blockHashAtH2C), uint256_reverse_hex(blockHashAtH2C)); + [self updateStoreWithProcessingResult:masternodeListAtH2C result:mnListDiffResultAtH2C completion:^(NSError *error) {}]; } if (![self.quorumRotationService shouldProcessDiffResult:mnListDiffResultAtHC skipPresenceInRetrieval:YES]) { [self.quorumRotationService issueWithMasternodeListFromPeer:peer]; } 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) {}]; +// DSLog(@"••• updateStoreWithMasternodeList (h-c): %u: %@ (%@)", masternodeListAtHC.height, uint256_hex(blockHashAtHC), uint256_reverse_hex(blockHashAtHC)); + [self updateStoreWithProcessingResult:masternodeListAtHC result:mnListDiffResultAtHC completion:^(NSError *error) {}]; } if (![self.quorumRotationService shouldProcessDiffResult:mnListDiffResultAtH skipPresenceInRetrieval:YES]) { [self.quorumRotationService issueWithMasternodeListFromPeer:peer]; } 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) {}]; +// DSLog(@"••• updateStoreWithMasternodeList (h): %u: %@ (%@)", masternodeListAtH.height, uint256_hex(blockHashAtH), uint256_reverse_hex(blockHashAtH)); + [self updateStoreWithProcessingResult:masternodeListAtH result:mnListDiffResultAtH completion:^(NSError *error) {}]; } if (![self.quorumRotationService shouldProcessDiffResult:mnListDiffResultAtTip skipPresenceInRetrieval:YES]) { @@ -638,12 +664,11 @@ - (void)processQRInfoResult:(DSQRInfoProcessingResult *)result forPeer:(DSPeer * [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) {}]; +// DSLog(@"••• updateStoreWithMasternodeList (tip): %u: %@ (%@)", masternodeListAtTip.height, uint256_hex(blockHashAtTip), uint256_reverse_hex(blockHashAtTip)); + [self updateStoreWithProcessingResult:masternodeListAtTip result:mnListDiffResultAtTip completion:^(NSError *error) {}]; [self.quorumRotationService updateAfterProcessingMasternodeListWithBlockHash:blockHashDataAtTip fromPeer:peer]; } } - [self.store saveQuorumSnapshot:result.snapshotAtHC toChain:self.chain completion:^(NSError * _Nonnull error) {}]; [self.store saveQuorumSnapshot:result.snapshotAtH2C toChain:self.chain completion:^(NSError * _Nonnull error) {}]; [self.store saveQuorumSnapshot:result.snapshotAtH3C toChain:self.chain completion:^(NSError * _Nonnull error) {}]; @@ -657,16 +682,14 @@ - (void)processQRInfoResult:(DSQRInfoProcessingResult *)result forPeer:(DSPeer * if (![self.quorumRotationService shouldProcessDiffResult:diffResult skipPresenceInRetrieval:YES]) { [self.quorumRotationService issueWithMasternodeListFromPeer:peer]; } else if (![diffResult.neededMissingMasternodeLists count] || ![masternodeListQueriesNeedingQuorumsValidated containsObject:diffBlockHashData]) { - [self updateStoreWithMasternodeList:diffMasternodeList addedMasternodes:diffResult.addedMasternodes modifiedMasternodes:diffResult.modifiedMasternodes addedQuorums:diffResult.addedQuorums completion:^(NSError *error) {}]; + [self updateStoreWithProcessingResult:diffMasternodeList result:diffResult completion:^(NSError *error) {}]; } } for (DSQuorumSnapshot *snapshot in result.snapshotList) { [self.store saveQuorumSnapshot:snapshot toChain:self.chain completion:^(NSError * _Nonnull error) {}]; } - for (DSQuorumEntry *entry in result.lastQuorumPerIndex) { - [self.store.activeQuorums setObject:entry forKey:uint256_data(entry.llmqQuorumHash)]; - } + [self.store.activeQuorums unionOrderedSet:result.lastQuorumPerIndex]; } - (void)processMissingMasternodeLists:(NSOrderedSet *)neededMissingMasternodeLists forMasternodeList:(DSMasternodeList *)masternodeList { @@ -677,15 +700,14 @@ - (void)processMissingMasternodeLists:(NSOrderedSet *)neededMissingMasternodeLis [neededMasternodeLists addObject:masternodeListBlockHashData]; //also get the current one again [self getMasternodeListsForBlockHashes:neededMasternodeLists]; } - -- (void)updateStoreWithMasternodeList:(DSMasternodeList *)masternodeList addedMasternodes:(NSDictionary *)addedMasternodes modifiedMasternodes:(NSDictionary *)modifiedMasternodes addedQuorums:(NSDictionary *)addedQuorums completion:(void (^)(NSError *error))completion { +- (void)updateStoreWithProcessingResult:(DSMasternodeList *)masternodeList result:(DSMnDiffProcessingResult *)result completion:(void (^)(NSError *error))completion { if (uint256_eq(self.store.masternodeListAwaitingQuorumValidation.blockHash, masternodeList.blockHash)) { self.store.masternodeListAwaitingQuorumValidation = nil; } + [self.store.cachedCLSignatures addEntriesFromDictionary:result.clSignatures]; [self.store saveMasternodeList:masternodeList - addedMasternodes:addedMasternodes - modifiedMasternodes:modifiedMasternodes - addedQuorums:addedQuorums + addedMasternodes:result.addedMasternodes + modifiedMasternodes:result.modifiedMasternodes completion:^(NSError *error) { completion(error); if (!error || !([self.masternodeListDiffService retrievalQueueCount] + [self.quorumRotationService retrievalQueueCount])) { //if it is 0 then we most likely have wiped chain info @@ -696,7 +718,6 @@ - (void)updateStoreWithMasternodeList:(DSMasternodeList *)masternodeList addedMa [self getRecentMasternodeList]; }); }]; - } - (void)peer:(DSPeer *)peer relayedMasternodeDiffMessage:(NSData *)message { @@ -802,8 +823,18 @@ - (BOOL)hasMasternodeListCurrentlyBeingSaved { return [self.store hasMasternodeListCurrentlyBeingSaved]; } -+ (void)saveMasternodeList:(DSMasternodeList *)masternodeList toChain:(DSChain *)chain havingModifiedMasternodes:(NSDictionary *)modifiedMasternodes addedQuorums:(NSDictionary *)addedQuorums createUnknownBlocks:(BOOL)createUnknownBlocks inContext:(NSManagedObjectContext *)context completion:(void (^)(NSError *error))completion { - [DSMasternodeListStore saveMasternodeList:masternodeList toChain:chain havingModifiedMasternodes:modifiedMasternodes addedQuorums:addedQuorums createUnknownBlocks:createUnknownBlocks inContext:context completion:completion]; ++ (void)saveMasternodeList:(DSMasternodeList *)masternodeList + toChain:(DSChain *)chain + havingModifiedMasternodes:(NSDictionary *)modifiedMasternodes + createUnknownBlocks:(BOOL)createUnknownBlocks + inContext:(NSManagedObjectContext *)context + completion:(void (^)(NSError *error))completion { + [DSMasternodeListStore saveMasternodeList:masternodeList + toChain:chain + havingModifiedMasternodes:modifiedMasternodes + createUnknownBlocks:createUnknownBlocks + inContext:context + completion:completion]; } // MARK: - Quorums @@ -846,4 +877,15 @@ - (void)checkPingTimesForCurrentMasternodeListInContext:(NSManagedObjectContext } +- (UInt256)buildLLMQHashFor:(DSQuorumEntry *)quorum { + uint32_t workHeight = [self heightForBlockHash:quorum.quorumHash] - 8; + if (workHeight >= chain_core20_activation_height(self.chain.chainType)) { + DSLog(@"buildLLMQHashFor: [%u: %u] (core 20): %@", quorum.llmqType, workHeight, uint256_hex(quorum.quorumHash)); + NSData *bestCLSignature = [self CLSignatureForBlockHeight:workHeight]; + return [DSKeyManager NSDataFrom:quorum_build_llmq_hash_v20(quorum.llmqType, workHeight, bestCLSignature.bytes)].UInt256; + } else { + DSLog(@"buildLLMQHashFor: [%u: %u] (pre core 20): %@", quorum.llmqType, workHeight, uint256_hex(quorum.quorumHash)); + return [DSKeyManager NSDataFrom:quorum_build_llmq_hash(quorum.llmqType, quorum.quorumHash.u8)].UInt256; + } +} @end diff --git a/DashSync/shared/Models/Managers/Chain Managers/DSTransactionManager+Protected.h b/DashSync/shared/Models/Managers/Chain Managers/DSTransactionManager+Protected.h index ef6c30ac3..a3d5b915e 100644 --- a/DashSync/shared/Models/Managers/Chain Managers/DSTransactionManager+Protected.h +++ b/DashSync/shared/Models/Managers/Chain Managers/DSTransactionManager+Protected.h @@ -44,6 +44,8 @@ NS_ASSUME_NONNULL_BEGIN - (void)fetchMempoolFromPeer:(DSPeer *)peer; - (void)fetchMempoolFromNetwork; +- (DSChainLock * _Nullable)chainLockForBlockHash:(UInt256)blockHash; + @end NS_ASSUME_NONNULL_END diff --git a/DashSync/shared/Models/Managers/Chain Managers/DSTransactionManager.m b/DashSync/shared/Models/Managers/Chain Managers/DSTransactionManager.m index 58cbb9e8d..866e476e8 100644 --- a/DashSync/shared/Models/Managers/Chain Managers/DSTransactionManager.m +++ b/DashSync/shared/Models/Managers/Chain Managers/DSTransactionManager.m @@ -1787,4 +1787,9 @@ - (void)checkWaitingForQuorums { [self checkChainLocksWaitingForQuorums]; } +- (DSChainLock * _Nullable)chainLockForBlockHash:(UInt256)blockHash { + DSChainLock *chainLock = [self.chainLocksWaitingForQuorums objectForKey:uint256_data(blockHash)]; + return chainLock; +} + @end diff --git a/DashSync/shared/Models/Masternode/DSMasternodeList+Mndiff.m b/DashSync/shared/Models/Masternode/DSMasternodeList+Mndiff.m index a7c22a838..7eb40bdd4 100644 --- a/DashSync/shared/Models/Masternode/DSMasternodeList+Mndiff.m +++ b/DashSync/shared/Models/Masternode/DSMasternodeList+Mndiff.m @@ -26,7 +26,7 @@ @implementation DSMasternodeList (Mndiff) + (instancetype)masternodeListWith:(MasternodeList *)list onChain:(DSChain *)chain { uintptr_t masternodes_count = list->masternodes_count; NSDictionary *masternodes = [DSSimplifiedMasternodeEntry simplifiedEntriesWith:list->masternodes count:masternodes_count onChain:chain]; - NSDictionary *> *quorums = [DSQuorumEntry entriesWith:list->llmq_type_maps count:list->llmq_type_maps_count onChain:chain]; + NSDictionary *> *quorums = [DSQuorumEntry entriesWithMap:list->llmq_type_maps count:list->llmq_type_maps_count onChain:chain]; UInt256 masternodeMerkleRoot = list->masternode_merkle_root ? *((UInt256 *)list->masternode_merkle_root) : UINT256_ZERO; UInt256 quorumMerkleRoot = list->llmq_merkle_root ? *((UInt256 *)list->llmq_merkle_root) : UINT256_ZERO; UInt256 blockHash = *((UInt256 *)list->block_hash); diff --git a/DashSync/shared/Models/Masternode/DSMasternodeListService.m b/DashSync/shared/Models/Masternode/DSMasternodeListService.m index 0c1546362..38d78b3dc 100644 --- a/DashSync/shared/Models/Masternode/DSMasternodeListService.m +++ b/DashSync/shared/Models/Masternode/DSMasternodeListService.m @@ -69,7 +69,6 @@ - (void)startTimeOutObserver { } dispatch_after(timeout, self.chain.networkingQueue, ^{ __block NSSet *requestsInRetrieval2; - __block NSUInteger masternodeListCount2; @synchronized (self) { if (!self.retrievalQueueMaxAmount || self.timeOutObserverTry != timeOutObserverTry) { return; @@ -199,7 +198,7 @@ - (BOOL)shouldProcessDiffResult:(DSMnDiffProcessingResult *)diffResult skipPrese BOOL hasInRetrieval = [self.retrievalQueue containsObject:masternodeListBlockHashData]; uint32_t masternodeListBlockHeight = [self.store heightForBlockHash:masternodeListBlockHash]; BOOL shouldNot = !hasInRetrieval && !skipPresenceInRetrieval; - DSLog(@"•••• shouldProcessDiffResult: %d: %@ %d", masternodeListBlockHeight, uint256_reverse_hex(masternodeListBlockHash), !shouldNot); + //DSLog(@"•••• shouldProcessDiffResult: %d: %@ %d", masternodeListBlockHeight, uint256_reverse_hex(masternodeListBlockHash), !shouldNot); if (shouldNot) { //We most likely wiped data in the meantime [self cleanRequestsInRetrieval]; diff --git a/DashSync/shared/Models/Masternode/DSMasternodeListStore.h b/DashSync/shared/Models/Masternode/DSMasternodeListStore.h index 6f4115ccc..939f15720 100644 --- a/DashSync/shared/Models/Masternode/DSMasternodeListStore.h +++ b/DashSync/shared/Models/Masternode/DSMasternodeListStore.h @@ -39,11 +39,12 @@ FOUNDATION_EXPORT NSString *const DSQuorumListDidChangeNotification; @property (nonatomic, readonly) uint32_t lastMasternodeListBlockHeight; @property (nonatomic, readonly) NSMutableDictionary *masternodeListsByBlockHash; @property (nonatomic, readonly) NSMutableSet *masternodeListsBlockHashStubs; -@property (nonatomic, readonly) NSMutableDictionary *activeQuorums; +@property (nonatomic, readonly) NSMutableOrderedSet *activeQuorums; @property (nonatomic, readonly) uint32_t masternodeListsToSync; @property (nonatomic, readonly) BOOL masternodeListsAndQuorumsIsSynced; @property (nonatomic, readonly) NSMutableDictionary *cachedQuorumSnapshots; +@property (nonatomic, readonly) NSMutableDictionary *cachedCLSignatures; - (instancetype)initWithChain:(DSChain *)chain; - (void)setUp:(void (^)(DSMasternodeList *masternodeList))completion; @@ -65,13 +66,12 @@ FOUNDATION_EXPORT NSString *const DSQuorumListDidChangeNotification; - (void)saveMasternodeList:(DSMasternodeList *)masternodeList addedMasternodes:(NSDictionary *)addedMasternodes modifiedMasternodes:(NSDictionary *)modifiedMasternodes - addedQuorums:(NSDictionary *)addedQuorums completion:(void (^)(NSError *error))completion; - (void)saveQuorumSnapshot:(DSQuorumSnapshot *)quorumSnapshot toChain:(DSChain *)chain completion:(void (^)(NSError *error))completion; -+ (void)saveMasternodeList:(DSMasternodeList *)masternodeList toChain:(DSChain *)chain havingModifiedMasternodes:(NSDictionary *)modifiedMasternodes addedQuorums:(NSDictionary *)addedQuorums createUnknownBlocks:(BOOL)createUnknownBlocks inContext:(NSManagedObjectContext *)context completion:(void (^)(NSError *error))completion; ++ (void)saveMasternodeList:(DSMasternodeList *)masternodeList toChain:(DSChain *)chain havingModifiedMasternodes:(NSDictionary *)modifiedMasternodes createUnknownBlocks:(BOOL)createUnknownBlocks inContext:(NSManagedObjectContext *)context completion:(void (^)(NSError *error))completion; - (DSQuorumEntry *_Nullable)quorumEntryForPlatformHavingQuorumHash:(UInt256)quorumHash forBlockHeight:(uint32_t)blockHeight; diff --git a/DashSync/shared/Models/Masternode/DSMasternodeListStore.m b/DashSync/shared/Models/Masternode/DSMasternodeListStore.m index bfe90dd4a..bd56eca67 100644 --- a/DashSync/shared/Models/Masternode/DSMasternodeListStore.m +++ b/DashSync/shared/Models/Masternode/DSMasternodeListStore.m @@ -49,7 +49,7 @@ @interface DSMasternodeListStore () @property (nonatomic, strong) dispatch_queue_t masternodeSavingQueue; @property (nonatomic, assign) UInt256 lastQueriedBlockHash; //last by height, not by time queried @property (atomic, assign) uint32_t masternodeListCurrentlyBeingSavedCount; -@property (nonatomic, strong) NSMutableDictionary *activeQuorums; +@property (nonatomic, strong) NSMutableOrderedSet *activeQuorums; @property (nonatomic, strong) dispatch_group_t savingGroup; @end @@ -421,7 +421,7 @@ - (void)notifyMasternodeListUpdate { }); } -- (void)saveMasternodeList:(DSMasternodeList *)masternodeList addedMasternodes:(NSDictionary *)addedMasternodes modifiedMasternodes:(NSDictionary *)modifiedMasternodes addedQuorums:(NSDictionary *)addedQuorums completion:(void (^)(NSError *error))completion { +- (void)saveMasternodeList:(DSMasternodeList *)masternodeList addedMasternodes:(NSDictionary *)addedMasternodes modifiedMasternodes:(NSDictionary *)modifiedMasternodes completion:(void (^)(NSError *error))completion { UInt256 blockHash = masternodeList.blockHash; NSData *blockHashData = uint256_data(blockHash); DSLog(@"•••• store (%d) masternode list at: %u: %@", [self hasMasternodeListAt:blockHashData], [self heightForBlockHash:blockHash], uint256_hex(blockHash)); @@ -451,7 +451,6 @@ - (void)saveMasternodeList:(DSMasternodeList *)masternodeList addedMasternodes:( [DSMasternodeListStore saveMasternodeList:masternodeList toChain:self.chain havingModifiedMasternodes:modifiedMasternodes - addedQuorums:addedQuorums createUnknownBlocks:createUnknownBlocks inContext:self.managedObjectContext completion:^(NSError *error) { @@ -522,7 +521,6 @@ - (void)saveQuorumSnapshot:(DSQuorumSnapshot *)quorumSnapshot + (void)saveMasternodeList:(DSMasternodeList *)masternodeList toChain:(DSChain *)chain havingModifiedMasternodes:(NSDictionary *)modifiedMasternodes - addedQuorums:(NSDictionary *)addedQuorums createUnknownBlocks:(BOOL)createUnknownBlocks inContext:(NSManagedObjectContext *)context completion:(void (^)(NSError *error))completion { diff --git a/DashSync/shared/Models/Masternode/DSMasternodeProcessorContext.h b/DashSync/shared/Models/Masternode/DSMasternodeProcessorContext.h index 96665af4c..22d5c5743 100644 --- a/DashSync/shared/Models/Masternode/DSMasternodeProcessorContext.h +++ b/DashSync/shared/Models/Masternode/DSMasternodeProcessorContext.h @@ -18,6 +18,7 @@ #import "BigIntTypes.h" #import "DSChain.h" #import "DSMasternodeList.h" +#import "DSQuorumSnapshot.h" #import "DSPeer.h" #import @@ -38,6 +39,23 @@ typedef DSMerkleBlock *_Nullable(^_Nullable MerkleBlockFinder)(UInt256 blockHash @property (nonatomic, copy) BlockHeightFinder blockHeightLookup; @property (nonatomic, copy) MerkleRootFinder merkleRootLookup; + +- (uint32_t)blockHeightForBlockHash:(UInt256)blockHash; +- (UInt256)merkleRootForBlockHash:(UInt256)blockHash; +- (DSBlock *_Nullable)blockForBlockHeight:(uint32_t)blockHeight; +- (NSData *_Nullable)CLSignatureForBlockHash:(UInt256)blockHash; +- (DSQuorumSnapshot *_Nullable)quorumSnapshotForBlockHash:(UInt256)blockHash; +- (DSMasternodeList *_Nullable)masternodeListForBlockHash:(UInt256)blockHash; + +- (BOOL)saveCLSignature:(UInt256)blockHash signature:(UInt768)signature; +- (BOOL)saveQuorumSnapshot:(DSQuorumSnapshot *)snapshot; +- (BOOL)saveMasternodeList:(DSMasternodeList *)masternodeList forBlockHash:(UInt256)blockHash; + + + +- (void)blockUntilGetInsightForBlockHash:(UInt256)blockHash; +- (ProcessingError)shouldProcessDiffWithRange:(UInt256)baseBlockHash blockHash:(UInt256)blockHash; + @end NS_ASSUME_NONNULL_END diff --git a/DashSync/shared/Models/Masternode/DSMasternodeProcessorContext.m b/DashSync/shared/Models/Masternode/DSMasternodeProcessorContext.m index 6b162e596..1e53060b1 100644 --- a/DashSync/shared/Models/Masternode/DSMasternodeProcessorContext.m +++ b/DashSync/shared/Models/Masternode/DSMasternodeProcessorContext.m @@ -17,11 +17,90 @@ #import "DSMasternodeProcessorContext.h" #import "NSData+Dash.h" +#import "DSChain+Protected.h" +#import "DSChainManager.h" +#import "DSMasternodeManager.h" @implementation DSMasternodeProcessorContext +- (uint32_t)blockHeightForBlockHash:(UInt256)blockHash { + return self.blockHeightLookup(blockHash); +} + +- (DSMerkleBlock *_Nullable)blockForBlockHeight:(uint32_t)blockHeight { + return [self.chain blockAtHeight:blockHeight]; + +} +- (UInt256)merkleRootForBlockHash:(UInt256)blockHash { + return self.merkleRootLookup(blockHash); +} + +- (NSData *_Nullable)CLSignatureForBlockHash:(UInt256)blockHash { + return [self.chain.chainManager.masternodeManager CLSignatureForBlockHash:blockHash]; +} + +- (DSQuorumSnapshot *_Nullable)quorumSnapshotForBlockHash:(UInt256)blockHash { + return [self.chain.chainManager.masternodeManager quorumSnapshotForBlockHash:blockHash]; +} + +- (DSMasternodeList *_Nullable)masternodeListForBlockHash:(UInt256)blockHash { + return self.masternodeListLookup(blockHash); +} + +- (BOOL)saveCLSignature:(UInt256)blockHash signature:(UInt768)signature { + return [self.chain.chainManager.masternodeManager saveCLSignature:uint256_data(blockHash) signatureData:uint768_data(signature)]; +} + +- (BOOL)saveQuorumSnapshot:(DSQuorumSnapshot *)snapshot { + return [self.chain.chainManager.masternodeManager saveQuorumSnapshot:snapshot]; +} + +- (BOOL)saveMasternodeList:(DSMasternodeList *)masternodeList forBlockHash:(UInt256)blockHash { + return [self.chain.chainManager.masternodeManager saveMasternodeList:masternodeList forBlockHash:blockHash]; +} + +- (void)blockUntilGetInsightForBlockHash:(UInt256)blockHash { + [self.chain blockUntilGetInsightForBlockHash:blockHash]; +} + - (NSString *)description { return [[super description] stringByAppendingString:[NSString stringWithFormat:@" {%@}: [%@: %@ (%u)] genesis: %@ protocol: %u, insight: %i, from_snapshot: %i, dip-24: %i}", self.chain.name, self.peer.location, self.peer.useragent, self.peer.version, uint256_hex(self.chain.genesisHash), self.chain.protocolVersion, self.useInsightAsBackup, self.isFromSnapshot, self.isDIP0024]]; } +- (ProcessingError)shouldProcessDiffWithRange:(UInt256)baseBlockHash blockHash:(UInt256)blockHash { + uint32_t baseBlockHeight = [self blockHeightForBlockHash:baseBlockHash]; + uint32_t blockHeight = [self blockHeightForBlockHash:blockHash]; + if (blockHeight == UINT32_MAX) { + DSLog(@"•••• shouldProcessDiffWithRange: unknown blockHash: %u..%u %@ .. %@", baseBlockHeight, blockHeight, uint256_reverse_hex(baseBlockHash), uint256_reverse_hex(blockHash)); + return ProcessingError_UnknownBlockHash; + } + DSChain *chain = self.chain; + DSMasternodeManager *manager = chain.chainManager.masternodeManager; + DSMasternodeListService *service = self.isDIP0024 ? manager.quorumRotationService : manager.masternodeListDiffService; + BOOL hasRemovedFromRetrieval = [service removeRequestInRetrievalForBaseBlockHash:baseBlockHash blockHash:blockHash]; + if (!hasRemovedFromRetrieval) { + DSLog(@"•••• shouldProcessDiffWithRange: persist in retrieval: %u..%u %@ .. %@", baseBlockHeight, blockHeight, uint256_reverse_hex(baseBlockHash), uint256_reverse_hex(blockHash)); + return ProcessingError_PersistInRetrieval; + } + NSData *blockHashData = uint256_data(blockHash); + DSMasternodeList *list = self.masternodeListLookup(blockHash); + BOOL needToVerifyRotatedQuorums = self.isDIP0024 && (!manager.quorumRotationService.masternodeListAtH || [manager.quorumRotationService.masternodeListAtH hasUnverifiedRotatedQuorums]); + BOOL needToVerifyNonRotatedQuorums = !self.isDIP0024 && [list hasUnverifiedNonRotatedQuorums]; + BOOL noNeedToVerifyQuorums = !(needToVerifyRotatedQuorums || needToVerifyNonRotatedQuorums); + BOOL hasLocallyStored = [manager.store hasMasternodeListAt:blockHashData]; + if (hasLocallyStored && noNeedToVerifyQuorums) { + DSLog(@"•••• shouldProcessDiffWithRange: already persist: %u: %@ needToVerifyRotatedQuorums: %d needToVerifyNonRotatedQuorums: %d", blockHeight, uint256_reverse_hex(blockHash), needToVerifyRotatedQuorums, needToVerifyNonRotatedQuorums); + [service removeFromRetrievalQueue:blockHashData]; + return ProcessingError_LocallyStored; + } + DSMasternodeList *baseMasternodeList = self.masternodeListLookup(baseBlockHash); + if (!baseMasternodeList && !uint256_eq(chain.genesisHash, baseBlockHash) && uint256_is_not_zero(baseBlockHash)) { + // this could have been deleted in the meantime, if so rerequest + [service issueWithMasternodeListFromPeer:self.peer]; + DSLog(@"•••• No base masternode list at: %d: %@", baseBlockHeight, uint256_reverse_hex(baseBlockHash)); + return ProcessingError_HasNoBaseBlockHash; + } + return ProcessingError_None; +} + @end diff --git a/DashSync/shared/Models/Masternode/DSMnDiffProcessingResult.h b/DashSync/shared/Models/Masternode/DSMnDiffProcessingResult.h index 09e92001a..43b097dea 100644 --- a/DashSync/shared/Models/Masternode/DSMnDiffProcessingResult.h +++ b/DashSync/shared/Models/Masternode/DSMnDiffProcessingResult.h @@ -34,8 +34,10 @@ NS_ASSUME_NONNULL_BEGIN @property (nonatomic) DSMasternodeList *masternodeList; @property (nonatomic) NSDictionary *addedMasternodes; @property (nonatomic) NSDictionary *modifiedMasternodes; -@property (nonatomic) NSDictionary *addedQuorums; +@property (nonatomic) NSArray *addedQuorums; @property (nonatomic) NSOrderedSet *neededMissingMasternodeLists; +/// +@property (nonatomic) NSDictionary *clSignatures; + (instancetype)processingResultWith:(MNListDiffResult *)result onChain:(DSChain *)chain; diff --git a/DashSync/shared/Models/Masternode/DSMnDiffProcessingResult.m b/DashSync/shared/Models/Masternode/DSMnDiffProcessingResult.m index fcaa7efe0..7e3ddd912 100644 --- a/DashSync/shared/Models/Masternode/DSMnDiffProcessingResult.m +++ b/DashSync/shared/Models/Masternode/DSMnDiffProcessingResult.m @@ -15,6 +15,7 @@ // limitations under the License. // +#import "NSData+Dash.h" #import "DSMnDiffProcessingResult.h" #import "DSMasternodeList+Mndiff.h" #import "DSQuorumEntry+Mndiff.h" @@ -49,7 +50,7 @@ + (instancetype)processingResultWith:(MNListDiffResult *)result onChain:(DSChain [processingResult setAddedMasternodes:addedMasternodes]; NSDictionary *modifiedMasternodes = [DSSimplifiedMasternodeEntry simplifiedEntriesWith:result->modified_masternodes count:result->modified_masternodes_count onChain:chain]; [processingResult setModifiedMasternodes:modifiedMasternodes]; - NSDictionary *addedQuorums = [DSQuorumEntry entriesWith:result->added_llmq_type_maps count:result->added_llmq_type_maps_count onChain:chain]; + NSArray *addedQuorums = [DSQuorumEntry entriesWith:result->added_quorums count:result->added_quorums_count onChain:chain]; [processingResult setAddedQuorums:addedQuorums]; uint8_t(**needed_masternode_lists)[32] = result->needed_masternode_lists; uintptr_t needed_masternode_lists_count = result->needed_masternode_lists_count; @@ -59,6 +60,15 @@ + (instancetype)processingResultWith:(MNListDiffResult *)result onChain:(DSChain [neededMissingMasternodeLists addObject:hash]; } [processingResult setNeededMissingMasternodeLists:[neededMissingMasternodeLists copy]]; + uint8_t (**quorums_cl_signatures_hashes)[32] = result->quorums_cl_signatures_hashes; + uint8_t (**quorums_cl_signatures)[96] = result->quorums_cl_signatures; + uintptr_t quorums_cl_sigs_count = result->quorums_cl_sigs_count; + NSMutableDictionary *clSignatures = [NSMutableDictionary dictionaryWithCapacity:quorums_cl_sigs_count]; + for (NSUInteger i = 0; i < quorums_cl_sigs_count; i++) { + [clSignatures setObject:uint768_data(*(UInt768 *)quorums_cl_signatures[i]) + forKey:uint256_data(*(UInt256 *)quorums_cl_signatures_hashes[i])]; + } + [processingResult setClSignatures:clSignatures]; return processingResult; } @@ -71,9 +81,9 @@ - (BOOL)isTotallyValid { } - (BOOL)hasRotatedQuorumsForChain:(DSChain*)chain { - return [[self.addedQuorums keysOfEntriesPassingTest:^BOOL(NSNumber *_Nonnull llmqType, id _Nonnull obj, BOOL *_Nonnull stop) { + return [[self.addedQuorums indexesOfObjectsPassingTest:^BOOL(DSQuorumEntry * _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) { // TODO: make it more reliable as quorum type values may change - return ([llmqType unsignedIntValue] == quorum_type_for_isd_locks(chain.chainType)) && (*stop = TRUE); + return obj.llmqType == quorum_type_for_isd_locks(chain.chainType) && (*stop = TRUE); }] count] > 0; } diff --git a/DashSync/shared/Models/Masternode/DSQuorumEntry+Mndiff.h b/DashSync/shared/Models/Masternode/DSQuorumEntry+Mndiff.h index 4b415fb89..5427ea640 100644 --- a/DashSync/shared/Models/Masternode/DSQuorumEntry+Mndiff.h +++ b/DashSync/shared/Models/Masternode/DSQuorumEntry+Mndiff.h @@ -24,7 +24,8 @@ NS_ASSUME_NONNULL_BEGIN @interface DSQuorumEntry (Mndiff) -+ (NSDictionary *> *)entriesWith:(LLMQMap *_Nullable *_Nonnull)entries count:(uintptr_t)count onChain:(DSChain *)chain; ++ (NSDictionary *> *)entriesWithMap:(LLMQMap *_Nullable *_Nonnull)entries count:(uintptr_t)count onChain:(DSChain *)chain; ++ (NSArray *)entriesWith:(LLMQEntry *_Nullable *_Nonnull)entries count:(uintptr_t)count onChain:(DSChain *)chain; - (LLMQEntry *)ffi_malloc; + (void)ffi_free:(LLMQEntry *)entry; diff --git a/DashSync/shared/Models/Masternode/DSQuorumEntry+Mndiff.m b/DashSync/shared/Models/Masternode/DSQuorumEntry+Mndiff.m index 6f827b2f7..da662b673 100644 --- a/DashSync/shared/Models/Masternode/DSQuorumEntry+Mndiff.m +++ b/DashSync/shared/Models/Masternode/DSQuorumEntry+Mndiff.m @@ -20,7 +20,7 @@ @implementation DSQuorumEntry (Mndiff) -+ (NSDictionary *> *)entriesWith:(LLMQMap *_Nullable *_Nonnull)entries count:(uintptr_t)count onChain:(DSChain *)chain { ++ (NSDictionary *> *)entriesWithMap:(LLMQMap *_Nullable *_Nonnull)entries count:(uintptr_t)count onChain:(DSChain *)chain { NSMutableDictionary *> *quorums = [NSMutableDictionary dictionaryWithCapacity:count]; for (NSUInteger i = 0; i < count; i++) { LLMQMap *llmq_map = entries[i]; @@ -37,6 +37,14 @@ @implementation DSQuorumEntry (Mndiff) return quorums; } ++ (NSArray *)entriesWith:(LLMQEntry *_Nullable *_Nonnull)entries count:(uintptr_t)count onChain:(DSChain *)chain { + NSMutableArray *result = [NSMutableArray arrayWithCapacity:count]; + for (NSUInteger i = 0; i < count; i++) { + [result addObject:[[DSQuorumEntry alloc] initWithEntry:entries[i] onChain:chain]]; + } + return result; +} + - (LLMQEntry *)ffi_malloc { LLMQEntry *quorum_entry = malloc(sizeof(LLMQEntry)); quorum_entry->all_commitment_aggregated_signature = uint768_malloc([self allCommitmentAggregatedSignature]); diff --git a/DashSync/shared/Models/Masternode/DSQuorumEntry.h b/DashSync/shared/Models/Masternode/DSQuorumEntry.h index abe1ee54f..c211c2633 100644 --- a/DashSync/shared/Models/Masternode/DSQuorumEntry.h +++ b/DashSync/shared/Models/Masternode/DSQuorumEntry.h @@ -19,7 +19,6 @@ NS_ASSUME_NONNULL_BEGIN @property (nonatomic, readonly) uint16_t version; @property (nonatomic, readonly) uint32_t quorumIndex; @property (nonatomic, readonly) UInt256 quorumHash; -@property (nonatomic, readonly) UInt256 llmqQuorumHash; @property (nonatomic, readonly) UInt384 quorumPublicKey; @property (nonatomic, readonly) UInt768 quorumThresholdSignature; @property (nonatomic, readonly) UInt256 quorumVerificationVectorHash; diff --git a/DashSync/shared/Models/Masternode/DSQuorumEntry.m b/DashSync/shared/Models/Masternode/DSQuorumEntry.m index aeebf7375..f47957964 100644 --- a/DashSync/shared/Models/Masternode/DSQuorumEntry.m +++ b/DashSync/shared/Models/Masternode/DSQuorumEntry.m @@ -187,10 +187,6 @@ - (uint32_t)quorumThreshold { return quorum_threshold_for_type(self.llmqType); } -- (UInt256)llmqQuorumHash { - return [DSKeyManager NSDataFrom:quorum_build_llmq_hash(self.llmqType, self.quorumHash.u8)].UInt256; -} - - (BOOL)validateWithMasternodeList:(DSMasternodeList *)masternodeList { return [self validateWithMasternodeList:masternodeList blockHeightLookup:^uint32_t(UInt256 blockHash) { @@ -210,7 +206,7 @@ - (BOOL)validateWithMasternodeList:(DSMasternodeList *)masternodeList blockHeigh } MasternodeList *list = [masternodeList ffi_malloc]; LLMQEntry *quorum = [self ffi_malloc]; - BOOL is_valid = validate_masternode_list(list, quorum, blockHeightLookup(masternodeList.blockHash), self.chain.chainType); + BOOL is_valid = validate_masternode_list(list, quorum, blockHeightLookup(masternodeList.blockHash), self.chain.chainType, NULL); [DSMasternodeList ffi_free:list]; [DSQuorumEntry ffi_free:quorum]; self.verified = is_valid; diff --git a/DashSync/shared/Models/Persistence/Migration/Internal/DSCoreDataMigrationVersion.h b/DashSync/shared/Models/Persistence/Migration/Internal/DSCoreDataMigrationVersion.h index 54c595b35..066472548 100644 --- a/DashSync/shared/Models/Persistence/Migration/Internal/DSCoreDataMigrationVersion.h +++ b/DashSync/shared/Models/Persistence/Migration/Internal/DSCoreDataMigrationVersion.h @@ -40,6 +40,7 @@ typedef NS_ENUM(NSInteger, DSCoreDataMigrationVersionValue) DSCoreDataMigrationVersionValue_17 = 17, DSCoreDataMigrationVersionValue_18 = 18, DSCoreDataMigrationVersionValue_19 = 19, + DSCoreDataMigrationVersionValue_20 = 20, }; @interface DSCoreDataMigrationVersion : NSObject diff --git a/DashSync/shared/Models/Persistence/Migration/Internal/DSCoreDataMigrationVersion.m b/DashSync/shared/Models/Persistence/Migration/Internal/DSCoreDataMigrationVersion.m index 08f7e1e44..5703cf186 100644 --- a/DashSync/shared/Models/Persistence/Migration/Internal/DSCoreDataMigrationVersion.m +++ b/DashSync/shared/Models/Persistence/Migration/Internal/DSCoreDataMigrationVersion.m @@ -20,7 +20,7 @@ @implementation DSCoreDataMigrationVersion + (DSCoreDataMigrationVersionValue)current { - return DSCoreDataMigrationVersionValue_19; + return DSCoreDataMigrationVersionValue_20; } + (NSString *)modelResourceForVersion:(DSCoreDataMigrationVersionValue)version { @@ -44,6 +44,7 @@ + (NSString *)modelResourceForVersion:(DSCoreDataMigrationVersionValue)version { case DSCoreDataMigrationVersionValue_17: return @"DashSync 17"; case DSCoreDataMigrationVersionValue_18: return @"DashSync 18"; case DSCoreDataMigrationVersionValue_19: return @"DashSync 19"; + case DSCoreDataMigrationVersionValue_20: return @"DashSync 20"; default: return [NSString stringWithFormat:@"DashSync %ld", (long)version]; } diff --git a/DashSync/shared/Models/Transactions/Coinbase/DSCoinbaseTransaction+Mndiff.m b/DashSync/shared/Models/Transactions/Coinbase/DSCoinbaseTransaction+Mndiff.m index 9361e8eb2..493351f89 100644 --- a/DashSync/shared/Models/Transactions/Coinbase/DSCoinbaseTransaction+Mndiff.m +++ b/DashSync/shared/Models/Transactions/Coinbase/DSCoinbaseTransaction+Mndiff.m @@ -61,7 +61,6 @@ @implementation DSCoinbaseTransaction (Mndiff) ctx.version = tx->version; ctx.txHash = *(UInt256 *)tx->tx_hash; ctx.type = tx->tx_type; - ctx.payloadOffset = (uint32_t)tx->payload_offset; ctx.blockHeight = tx->block_height; return ctx; }*/ diff --git a/DashSync/shared/Models/Transactions/Coinbase/DSCoinbaseTransaction.h b/DashSync/shared/Models/Transactions/Coinbase/DSCoinbaseTransaction.h index ad0a27605..d5e5b7bd0 100644 --- a/DashSync/shared/Models/Transactions/Coinbase/DSCoinbaseTransaction.h +++ b/DashSync/shared/Models/Transactions/Coinbase/DSCoinbaseTransaction.h @@ -13,7 +13,9 @@ @property (nonatomic, assign) uint32_t height; @property (nonatomic, assign) UInt256 merkleRootMNList; @property (nonatomic, assign) UInt256 merkleRootLLMQList; -@property (nonatomic, assign) uint64_t lockedAmount; +@property (nonatomic, assign) uint32_t bestCLHeightDiff; +@property (nonatomic, assign) UInt768 bestCLSignature; +@property (nonatomic, assign) int64_t creditPoolBalance; - (instancetype)initWithCoinbaseMessage:(NSString *)coinbaseMessage atHeight:(uint32_t)height onChain:(DSChain *)chain; - (instancetype)initWithCoinbaseMessage:(NSString *)coinbaseMessage paymentAddresses:(NSArray *)paymentAddresses atHeight:(uint32_t)height onChain:(DSChain *)chain; diff --git a/DashSync/shared/Models/Transactions/Coinbase/DSCoinbaseTransaction.m b/DashSync/shared/Models/Transactions/Coinbase/DSCoinbaseTransaction.m index 0a440e773..339cdfb8e 100644 --- a/DashSync/shared/Models/Transactions/Coinbase/DSCoinbaseTransaction.m +++ b/DashSync/shared/Models/Transactions/Coinbase/DSCoinbaseTransaction.m @@ -27,27 +27,31 @@ - (instancetype)initWithMessage:(NSData *)message onChain:(DSChain *)chain { uint16_t version = [message UInt16AtOffset:off]; off += 2; if (length - off < 4) return nil; - uint32_t height = [message UInt32AtOffset:off]; + self.height = [message UInt32AtOffset:off]; off += 4; if (length - off < 32) return nil; - UInt256 merkleRootMNList = [message UInt256AtOffset:off]; + self.merkleRootMNList = [message UInt256AtOffset:off]; off += 32; - if (version >= 2) { + if (version >= COINBASE_TX_CORE_19) { if (length - off < 32) return nil; self.merkleRootLLMQList = [message UInt256AtOffset:off]; off += 32; + + if (version >= COINBASE_TX_CORE_20) { + if (length - off < 4) return nil; + self.bestCLHeightDiff = [message UInt32AtOffset:off]; + off += 4; + if (length - off < 96) return nil; + self.bestCLSignature = [message UInt768AtOffset:off]; + off += 96; + if (length - off < 8) return nil; + NSNumber *len; + self.creditPoolBalance = [message varIntAtOffset:off length:&len]; + off += len.unsignedIntegerValue; + } } - - if (version >= 3) { - if (length - off < 8) return nil; - self.lockedAmount = [message UInt64AtOffset:off]; - off += 8; - } - self.coinbaseTransactionVersion = version; - self.height = height; - self.merkleRootMNList = merkleRootMNList; self.payloadOffset = off; self.txHash = self.data.SHA256_2; @@ -86,11 +90,14 @@ - (NSData *)payloadData { [data appendUInt16:self.coinbaseTransactionVersion]; [data appendUInt32:self.height]; [data appendUInt256:self.merkleRootMNList]; - if (self.coinbaseTransactionVersion >= 2) { + if (self.coinbaseTransactionVersion >= COINBASE_TX_CORE_19) { [data appendUInt256:self.merkleRootLLMQList]; - } - if (self.coinbaseTransactionVersion >= 3) { - [data appendUInt64:self.lockedAmount]; + if (self.coinbaseTransactionVersion >= COINBASE_TX_CORE_20) { + [data appendUInt32:self.bestCLHeightDiff]; + // TODO: check whether it matters to check for optionals + [data appendUInt768:self.bestCLSignature]; + [data appendInt64:self.creditPoolBalance]; + } } return data; } diff --git a/Example/DashSync.xcodeproj/xcshareddata/xcschemes/DashSync-Example.xcscheme b/Example/DashSync.xcodeproj/xcshareddata/xcschemes/DashSync-Example.xcscheme index 42d0e7b91..88c79c32d 100644 --- a/Example/DashSync.xcodeproj/xcshareddata/xcschemes/DashSync-Example.xcscheme +++ b/Example/DashSync.xcodeproj/xcshareddata/xcschemes/DashSync-Example.xcscheme @@ -176,6 +176,11 @@ value = "" isEnabled = "YES"> + + 'https://github.com/dashpay/dash-shared-core.git', :branch => 'fix/revert-bls-legacy-scheme-derivation' -# pod 'DashSharedCore', :git => 'https://github.com/dashpay/dash-shared-core.git', :commit => '27157c7' +# pod 'DashSharedCore', :git => 'https://github.com/dashpay/dash-shared-core.git', :branch => 'fix/core-20-test-additional' +# pod 'DashSharedCore', :git => 'https://github.com/dashpay/dash-shared-core.git', :commit => 'e2dc943' pod 'DashSync', :path => '../' pod 'SDWebImage', '5.14.3' pod 'CocoaImageHashing', :git => 'https://github.com/ameingast/cocoaimagehashing.git', :commit => 'ad01eee' diff --git a/Example/Podfile.lock b/Example/Podfile.lock index bb8df6c35..c46846c3c 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.11) + - DashSharedCore (0.4.14) - DashSync (0.1.0): - CocoaLumberjack (= 3.7.2) - DAPI-GRPC (= 0.22.0-dev.8) - - DashSharedCore (= 0.4.11) + - DashSharedCore (= 0.4.14) - 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.24.3) + - Protobuf (3.25.0) - 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: d4dc11749f3555702dbe10c563087e6b48399394 - DashSync: 2d80784e399b869aede6d5bd476a149733451651 + DashSharedCore: dc766715605effeed166d39701825bd1f4c3c500 + DashSync: 3c7c4c0385b8c18dd764c0ef63fc02eef1c38f4f DSDynamicOptions: 347cc5d2c4e080eb3de6a86719ad3d861b82adfc DWAlertController: 5f4cd8adf90336331c054857f709f5f8d4b16a5b gRPC: 64f36d689b2ecd99c4351f74e6f91347cdc65d9f @@ -721,11 +721,11 @@ SPEC CHECKSUMS: gRPC-ProtoRPC: 1c223e0f1732bb8d0b9e9e0ea60cc0fe995b8e2d gRPC-RxLibrary: 92327f150e11cf3b1c0f52e083944fd9f5cb5d1e KVO-MVVM: 4df3afd1f7ebcb69735458b85db59c4271ada7c6 - Protobuf: 970f7ee93a3a08e3cf64859b8efd95ee32b4f87f + Protobuf: 6a4183ec1d51649eb2be7b86ccc286e5c539219c SDWebImage: 9c36e66c8ce4620b41a7407698dda44211a96764 tinycbor: d4d71dddda1f8392fbb4249f63faf8552f327590 TinyCborObjc: 5204540fb90ff0c40fb22d408fa51bab79d78a80 -PODFILE CHECKSUM: 65ee9c6b1d7ae6ab3bc40337f53a5135ff99a2f1 +PODFILE CHECKSUM: 8cb419eb95422ed65fbdc41960e405e8cc54dda7 -COCOAPODS: 1.12.1 +COCOAPODS: 1.14.2 diff --git a/Example/Tests/DSDeterministicMasternodeListTests.m b/Example/Tests/DSDeterministicMasternodeListTests.m index bc090350d..f8e9b31e6 100644 --- a/Example/Tests/DSDeterministicMasternodeListTests.m +++ b/Example/Tests/DSDeterministicMasternodeListTests.m @@ -634,7 +634,6 @@ - (void)loadMasternodeListsForFiles:(NSArray *)files [DSMasternodeManager saveMasternodeList:masternodeList toChain:chain havingModifiedMasternodes:result.modifiedMasternodes - addedQuorums:result.addedQuorums createUnknownBlocks:YES inContext:context completion:^(NSError *_Nonnull error) { @@ -747,7 +746,6 @@ - (void)testMainnetMasternodeSaving { [DSMasternodeManager saveMasternodeList:result.masternodeList toChain:chain havingModifiedMasternodes:result.modifiedMasternodes - addedQuorums:result.addedQuorums createUnknownBlocks:YES inContext:context completion:^(NSError *_Nonnull error) { @@ -812,7 +810,6 @@ - (void)testMNLSavingToDisk { [DSMasternodeManager saveMasternodeList:masternodeList toChain:chain havingModifiedMasternodes:result.modifiedMasternodes - addedQuorums:result.addedQuorums createUnknownBlocks:YES inContext:context completion:^(NSError *_Nonnull error) { @@ -888,7 +885,6 @@ - (void)testMNLSavingAndRetrievingFromDisk { [DSMasternodeManager saveMasternodeList:masternodeList122064 toChain:chain havingModifiedMasternodes:result.modifiedMasternodes - addedQuorums:result.addedQuorums createUnknownBlocks:YES inContext:context completion:^(NSError *_Nonnull error) { @@ -936,7 +932,6 @@ - (void)testMNLSavingAndRetrievingFromDisk { [DSMasternodeManager saveMasternodeList:masternodeList122088 toChain:chain havingModifiedMasternodes:result122088.modifiedMasternodes - addedQuorums:result122088.addedQuorums createUnknownBlocks:YES inContext:context completion:^(NSError *_Nonnull error) { @@ -2839,7 +2834,6 @@ - (void)testMNLSavingAndRetrievingInIncorrectOrderFromDisk { [DSMasternodeManager saveMasternodeList:masternodeList1092912 toChain:chain havingModifiedMasternodes:result.modifiedMasternodes - addedQuorums:result.addedQuorums createUnknownBlocks:YES inContext:context completion:^(NSError *_Nonnull error) { @@ -2879,11 +2873,11 @@ - (void)testMNLSavingAndRetrievingInIncorrectOrderFromDisk { XCTAssert(result1092940.rootMNListValid, @"rootMNListValid not valid at height %u", [chain heightForBlockHash:blockHash1092940]); XCTAssert(result1092940.rootQuorumListValid, @"rootQuorumListValid not valid at height %u", [chain heightForBlockHash:blockHash1092940]); XCTAssert(result1092940.validQuorums, @"validQuorums not valid at height %u", [chain heightForBlockHash:blockHash1092940]); - DSQuorumEntry *quorum1092912 = [[[[result1092940.addedQuorums allValues] firstObject] allValues] firstObject]; + DSQuorumEntry *quorum1092912 = [result1092940.addedQuorums firstObject]; // 1092912 and 1092916 are the same, 1092916 is older though and is original 1092912 is based off a reloaded 109 - NSArray *masternodeScores1092912 = [masternodeList1092912 scoresForQuorumModifier:quorum1092912.llmqQuorumHash atBlockHeight:1092912]; - NSArray *masternodeScores1092916 = [masternodeList1092916 scoresForQuorumModifier:quorum1092912.llmqQuorumHash atBlockHeight:1092912]; - + UInt256 llmqHash1092912 = [chain.chainManager.masternodeManager buildLLMQHashFor:quorum1092912]; + NSArray *masternodeScores1092912 = [masternodeList1092912 scoresForQuorumModifier:llmqHash1092912 atBlockHeight:1092912]; + NSArray *masternodeScores1092916 = [masternodeList1092916 scoresForQuorumModifier:llmqHash1092912 atBlockHeight:1092912]; // BOOL a = [quorum1092912 validateWithMasternodeList:masternodeList1092912]; // // BOOL b = [quorum1092912 validateWithMasternodeList:masternodeList1092916]; @@ -2907,10 +2901,9 @@ - (void)testMNLSavingAndRetrievingInIncorrectOrderFromDisk { // NSDictionary * interesting = [masternodeList1092912 compare:masternodeList1092916]; XCTAssertEqualObjects(masternodeScores1092912, masternodeScores1092916, @"These should be the same"); + NSArray *masternodes1092912 = [masternodeList1092912 validMasternodesForQuorumModifier:llmqHash1092912 quorumCount:[DSQuorumEntry quorumSizeForType:quorum1092912.llmqType] blockHeight:blockHeightLookup(masternodeList1092912.blockHash)]; - NSArray *masternodes1092912 = [masternodeList1092912 validMasternodesForQuorumModifier:quorum1092912.llmqQuorumHash quorumCount:[DSQuorumEntry quorumSizeForType:quorum1092912.llmqType] blockHeight:blockHeightLookup(masternodeList1092912.blockHash)]; - - NSArray *masternodes1092916 = [masternodeList1092916 validMasternodesForQuorumModifier:quorum1092912.llmqQuorumHash quorumCount:[DSQuorumEntry quorumSizeForType:quorum1092912.llmqType] blockHeight:blockHeightLookup(masternodeList1092916.blockHash)]; + NSArray *masternodes1092916 = [masternodeList1092916 validMasternodesForQuorumModifier:llmqHash1092912 quorumCount:[DSQuorumEntry quorumSizeForType:quorum1092912.llmqType] blockHeight:blockHeightLookup(masternodeList1092916.blockHash)]; XCTAssertEqualObjects(masternodes1092912, masternodes1092916, @"These should be the same"); // NSMutableArray * publicKeyArray = [NSMutableArray array]; // uint32_t i = 0; @@ -2927,7 +2920,6 @@ - (void)testMNLSavingAndRetrievingInIncorrectOrderFromDisk { [DSMasternodeManager saveMasternodeList:masternodeList1092940 toChain:chain havingModifiedMasternodes:result1092940.modifiedMasternodes - addedQuorums:result1092940.addedQuorums createUnknownBlocks:YES inContext:context completion:^(NSError *_Nonnull error) { @@ -3059,7 +3051,11 @@ - (void)testTestnetQuorumVerification { XCTAssert(result119200.rootQuorumListValid, @"rootQuorumListValid not valid at height %u", [chain heightForBlockHash:blockHash]); XCTAssert(result119200.validQuorums, @"validQuorums not valid at height %u", [chain heightForBlockHash:blockHash]); - DSQuorumEntry *quorumToVerify = [result119200.addedQuorums[@1] objectForKey:uint256_data(blockHash119064)]; + NSPredicate *predicate = [NSPredicate predicateWithBlock:^BOOL(DSQuorumEntry *entry, NSDictionary *bindings) { + return uint256_eq(entry.quorumHash, blockHash119064) && entry.llmqType == LLMQType_Llmqtype50_60; + }]; + + DSQuorumEntry *quorumToVerify = [[result119200.addedQuorums filteredArrayUsingPredicate:predicate] firstObject]; XCTAssert(quorumToVerify, @"There should be a quorum using 119064"); [quorumToVerify validateWithMasternodeList:masternodeList119064]; XCTAssert(quorumToVerify.verified, @"Unable to verify quorum"); @@ -3211,11 +3207,14 @@ - (void)testTestnetSizeQuorumVerification { XCTAssert(result370944.rootQuorumListValid, @"rootQuorumListValid not valid at height %u", [chain heightForBlockHash:blockHash]); XCTAssert(result370944.validQuorums, @"validQuorums not valid at height %u", [chain heightForBlockHash:blockHash]); - DSQuorumEntry *quorumToVerify = [result370944.addedQuorums[@1] objectForKey:uint256_data(blockHash370368)]; + NSPredicate *predicate = [NSPredicate predicateWithBlock:^BOOL(DSQuorumEntry *entry, NSDictionary *bindings) { + return uint256_eq(entry.quorumHash, blockHash370368) && entry.llmqType == LLMQType_Llmqtype50_60; + }]; + DSQuorumEntry *quorumToVerify = [[result370944.addedQuorums filteredArrayUsingPredicate:predicate] firstObject]; XCTAssert(quorumToVerify, @"There should be a quorum using 119064"); DSMasternodeList *masternodeList370944 = result370944.masternodeList; - NSArray *masternodes = [masternodeList370944 validMasternodesForQuorumModifier:quorumToVerify.llmqQuorumHash quorumCount:[DSQuorumEntry quorumSizeForType:quorumToVerify.llmqType] blockHeight:370944]; + NSArray *masternodes = [masternodeList370944 validMasternodesForQuorumModifier:[chain.chainManager.masternodeManager buildLLMQHashFor:quorumToVerify] quorumCount:[DSQuorumEntry quorumSizeForType:quorumToVerify.llmqType] blockHeight:370944]; NSArray *masternodeHashOrder = [masternodes map:^(DSSimplifiedMasternodeEntry *masternode) { return uint256_reverse_hex([masternode providerRegistrationTransactionHash]); diff --git a/Example/Tests/DSTestnetSyncTests.m b/Example/Tests/DSTestnetSyncTests.m index 1f43c5e62..36a151e8a 100644 --- a/Example/Tests/DSTestnetSyncTests.m +++ b/Example/Tests/DSTestnetSyncTests.m @@ -94,7 +94,7 @@ - (void)testTestnetFullHeadersSync { [headerFinishedExpectation fulfill]; }]; }); - [self waitForExpectations:@[headerFinishedExpectation] timeout:600]; + [self waitForExpectations:@[headerFinishedExpectation] timeout:900]; [[NSNotificationCenter defaultCenter] removeObserver:self.txStatusObserver]; }