diff --git a/DashSync/shared/Categories/BigIntTypes.h b/DashSync/shared/Categories/BigIntTypes.h index e49e4094..6f9179a7 100644 --- a/DashSync/shared/Categories/BigIntTypes.h +++ b/DashSync/shared/Categories/BigIntTypes.h @@ -34,6 +34,7 @@ #define NoTimeLog(format, ...) CFShow([NSString stringWithFormat:format, ##__VA_ARGS__]); #endif +#define FLAG_IS_SET(value, flag) ((value & flag) == flag) typedef union _UInt768 { uint8_t u8[768 / 8]; diff --git a/DashSync/shared/Categories/NSData/NSData+Dash.m b/DashSync/shared/Categories/NSData/NSData+Dash.m index 3e9294b6..00c5ec7e 100644 --- a/DashSync/shared/Categories/NSData/NSData+Dash.m +++ b/DashSync/shared/Categories/NSData/NSData+Dash.m @@ -883,7 +883,7 @@ uint16_t compactBitsLE(UInt256 number) { for (int pos = 7; pos >= 0; pos--) { if (number.u32[pos]) { for (int bits = 31; bits > 0; bits--) { - if (number.u32[pos] & 1 << bits) + if (number.u32[pos] & 1U << bits) return 32 * pos + bits + 1; } return 32 * pos + 1; @@ -993,7 +993,7 @@ UInt256 uInt256DivideLE(UInt256 a, UInt256 b) { while (shift >= 0) { if (uint256_supeq(num, div)) { num = uInt256SubtractLE(num, div); - r.u32[shift / 32] |= (1 << (shift & 31)); // set a bit of the result. + r.u32[shift / 32] |= (1U << (shift & 31)); // set a bit of the result. } div = uInt256ShiftRightLE(div, 1); // shift back. shift--; diff --git a/DashSync/shared/DSDashSharedCore.m b/DashSync/shared/DSDashSharedCore.m index 6fe83b75..d19ab369 100644 --- a/DashSync/shared/DSDashSharedCore.m +++ b/DashSync/shared/DSDashSharedCore.m @@ -16,6 +16,7 @@ // #import "DSBlock.h" +#import "DSChain+Checkpoint.h" #import "DSChain+Params.h" #import "DSChain+Protected.h" #import "DSChain+Identity.h" @@ -46,31 +47,13 @@ #define GetBlockHeightByHash Fn_ARGS_std_os_raw_c_void_Arr_u8_32_RTRN_u32 #define GetBlockHashByHeight Fn_ARGS_std_os_raw_c_void_u32_RTRN_Option_u8_32 -#define MerkleBlockByBlockHash Fn_ARGS_std_os_raw_c_void_Arr_u8_32_RTRN_Result_ok_dash_spv_masternode_processor_common_block_MBlock_err_dash_spv_masternode_processor_processing_core_provider_CoreProviderError -#define LastMerkleBlockByBlockHashForPeer Fn_ARGS_std_os_raw_c_void_Arr_u8_32_std_os_raw_c_void_RTRN_Result_ok_dash_spv_masternode_processor_common_block_MBlock_err_dash_spv_masternode_processor_processing_core_provider_CoreProviderError - - -#define AddInsight Fn_ARGS_std_os_raw_c_void_Arr_u8_32_RTRN_ - -#define HasPersistInRetrieval Fn_ARGS_std_os_raw_c_void_Arr_u8_32_RTRN_bool -#define GetBlockHeightOrLastTerminal Fn_ARGS_std_os_raw_c_void_u32_RTRN_Result_ok_dash_spv_masternode_processor_common_block_Block_err_dash_spv_masternode_processor_processing_core_provider_CoreProviderError - -#define FnMaybeCLSignature Fn_ARGS_std_os_raw_c_void_Arr_u8_32_RTRN_Result_ok_dashcore_bls_sig_utils_BLSSignature_err_dash_spv_masternode_processor_processing_core_provider_CoreProviderError #define DMaybeCLSignature Result_ok_dashcore_bls_sig_utils_BLSSignature_err_dash_spv_masternode_processor_processing_core_provider_CoreProviderError #define DMaybeCLSignatureCtor(ok, err) Result_ok_dashcore_bls_sig_utils_BLSSignature_err_dash_spv_masternode_processor_processing_core_provider_CoreProviderError_ctor(ok, err) -#define LoadMasternodeList Fn_ARGS_std_os_raw_c_void_Arr_u8_32_RTRN_Result_ok_dashcore_sml_masternode_list_MasternodeList_err_dash_spv_masternode_processor_processing_core_provider_CoreProviderError -#define SaveMasternodeList Fn_ARGS_std_os_raw_c_void_Arr_u8_32_std_collections_Map_keys_u8_arr_32_values_dashcore_sml_masternode_list_entry_qualified_masternode_list_entry_QualifiedMasternodeListEntry_RTRN_Result_ok_bool_err_dash_spv_masternode_processor_processing_core_provider_CoreProviderError -#define LoadLLMQSnapshot Fn_ARGS_std_os_raw_c_void_Arr_u8_32_RTRN_Result_ok_dashcore_network_message_qrinfo_QuorumSnapshot_err_dash_spv_masternode_processor_processing_core_provider_CoreProviderError -#define SaveLLMQSnapshot Fn_ARGS_std_os_raw_c_void_Arr_u8_32_dashcore_network_message_qrinfo_QuorumSnapshot_RTRN_Result_ok_bool_err_dash_spv_masternode_processor_processing_core_provider_CoreProviderError - #define UpdateMasternodesAddressUsage Fn_ARGS_std_os_raw_c_void_Vec_dashcore_sml_masternode_list_entry_qualified_masternode_list_entry_QualifiedMasternodeListEntry_RTRN_ -#define IssueWithMasternodeList Fn_ARGS_std_os_raw_c_void_bool_std_os_raw_c_void_RTRN_ -#define NotifySyncState Fn_ARGS_std_os_raw_c_void_dash_spv_masternode_processor_models_sync_state_CacheState_RTRN_ - @interface DSDashSharedCore () -@property (nonatomic) DSChain *chain; +@property (nonatomic, strong) DSChain *chain; @property (nonatomic, assign) DashSPVCore *core; @property (nonatomic, strong) NSMutableDictionary *devnetSharedCoreDictionary; @@ -149,16 +132,6 @@ - (instancetype)initOnChain:(DSChain *)chain { UpdateMasternodesAddressUsage update_address_usage_of_masternodes = { .caller = &update_address_usage_of_masternodes_caller }; - IssueWithMasternodeList issue_with_masternode_list_from_peer = { - .caller = &issue_with_masternode_list_from_peer_caller - }; - FnMaybeCLSignature get_cl_signature_by_block_hash = { - .caller = &get_cl_signature_by_block_hash_caller, - .destructor = &get_cl_signature_by_block_hash_dtor - }; - NotifySyncState notify_sync_state = { - .caller = ¬ify_sync_state_caller, - }; NSArray *addresses = @[@"127.0.0.1"]; switch (chain.chainType->tag) { @@ -178,17 +151,8 @@ - (instancetype)initOnChain:(DSChain *)chain { break; } Vec_ *address_list = [NSArray ffi_to_vec:addresses]; - dash_spv_apple_bindings_DiffConfig *diff_config = NULL; - if ([chain isMainnet]) { - NSString *bundlePath = [[NSBundle bundleForClass:self.class] pathForResource:@"DashSync" ofType:@"bundle"]; - NSBundle *bundle = [NSBundle bundleWithPath:bundlePath]; - NSString *filePath = [bundle pathForResource:@"mn_list_diff_0_2227096" ofType:@"bin"]; - NSData *data = [NSData dataWithContentsOfFile:filePath]; - - diff_config = dash_spv_apple_bindings_DiffConfig_ctor(bytes_ctor(data), 2227096); - } - - self.core = dash_spv_apple_bindings_DashSPVCore_with_callbacks(chain.chainType, diff_config, address_list, get_data_contract, get_platform_activation_height, callback_signer, callback_can_sign, get_block_height_by_hash, get_block_hash_by_height, get_cl_signature_by_block_hash, update_address_usage_of_masternodes, issue_with_masternode_list_from_peer, notify_sync_state, context); + dash_spv_masternode_processor_processing_processor_DiffConfig *diff_config = [chain createDiffConfig]; + self.core = dash_spv_apple_bindings_DashSPVCore_with_callbacks(chain.chainType, diff_config, address_list, get_data_contract, get_platform_activation_height, callback_signer, callback_can_sign, get_block_height_by_hash, get_block_hash_by_height, update_address_usage_of_masternodes, context); return self; } @@ -248,7 +212,8 @@ uint32_t get_block_height_by_hash_caller(const void *context, u256 *block_hash) height = [[core.chain insightVerifiedBlocksByHashDictionary] objectForKey:NSDataFromPtr(block_hash)].height; } u256_dtor(block_hash); - DSLog(@"[SDK] get_block_height_by_hash_caller: %@ = %u", uint256_hex(blockHash), height); + if (height == UINT32_MAX) + DSLog(@"[SDK] get_block_height_by_hash_caller: %@ = %u", uint256_hex(blockHash), height); return height; } void get_block_height_by_hash_dtor(uint32_t result) {} @@ -268,61 +233,10 @@ void get_block_height_by_hash_dtor(uint32_t result) {} void get_block_hash_by_height_dtor(u256 *result) {} -DMaybeCLSignature *get_cl_signature_by_block_hash_caller(const void *context, u256 *block_hash) { - DSDashSharedCore *core = AS_OBJC(context); - UInt256 blockHash = u256_cast(block_hash); - UInt256 blockHashRev = uint256_reverse(blockHash); - u256_dtor(block_hash); - DSChainLock *chainLock = [core.chain.chainManager chainLockForBlockHash:blockHash]; - DSChainLock *chainLockRev = [core.chain.chainManager chainLockForBlockHash:blockHashRev]; - if (chainLock) { - DBLSSignature *bls_sig = DChainLockSignature(chainLock.lock); - DSLog(@"[SDK] get_cl_signature_by_block_hash_caller: %@ = %@", uint256_hex(blockHash), u768_hex(bls_sig->_0)); - return DMaybeCLSignatureCtor(bls_sig, NULL); - } else if (chainLockRev) { - DBLSSignature *bls_sig = DChainLockSignature(chainLockRev.lock); - DSLog(@"[SDK] get_cl_signature_by_block_hash_caller: %@ = %@", uint256_hex(blockHashRev), u768_hex(bls_sig->_0)); - return DMaybeCLSignatureCtor(bls_sig, NULL); - } else { - DSLog(@"[SDK] get_cl_signature_by_block_hash_caller: %@ = None", uint256_hex(blockHash)); - return DMaybeCLSignatureCtor(NULL, DCoreProviderErrorNullResultCtor(DSLocalizedChar(@"No clsig for block hash %@", nil, uint256_hex(blockHash)))); - } -} -void get_cl_signature_by_block_hash_dtor(DMaybeCLSignature *result) {} - - void update_address_usage_of_masternodes_caller(const void *context, DMasternodeEntryList *masternodes) { DSDashSharedCore *core = AS_OBJC(context); [core.chain updateAddressUsageOfSimplifiedMasternodeEntries:masternodes]; DMasternodeEntryListDtor(masternodes); } -void issue_with_masternode_list_from_peer_caller(const void *context, bool is_dip24, const void *peer_context) { - DSDashSharedCore *core = AS_OBJC(context); - DSPeer *peer = ((__bridge DSPeer *)(peer_context)); - [core.chain.masternodeManager issueWithMasternodeListFromPeer:peer]; -} - -void notify_sync_state_caller(const void *context, DMNSyncState *state) { - DSDashSharedCore *core = AS_OBJC(context); - DSMasternodeListSyncState *syncInfo = core.chain.chainManager.syncState.masternodeListSyncInfo; - @synchronized (syncInfo) { - [syncInfo updateWithSyncState:state]; - switch (state->tag) { - case DMNSyncStateQueueChanged: - DSLog(@"[%@] Masternode list queue updated: %lu/%lu", core.chain.name, state->queue_changed.count, state->queue_changed.max_amount); - break; - case DMNSyncStateStoreChanged: - DSLog(@"[%@] Masternode list store updated: %lu/%u", core.chain.name, state->store_changed.count, state->store_changed.last_block_height); - break; - case DMNSyncStateStubCount: - DSLog(@"[%@] Masternode list DB updated: %lu", core.chain.name, state->stub_count.count); - default: - break; - } - DMNSyncStateDtor(state); - [core.chain.chainManager notifySyncStateChanged]; - } -} - @end diff --git a/DashSync/shared/DashSync.m b/DashSync/shared/DashSync.m index 2521d2a1..ce64f21c 100644 --- a/DashSync/shared/DashSync.m +++ b/DashSync/shared/DashSync.m @@ -162,9 +162,11 @@ - (void)wipeBlockchainDataForChain:(DSChain *)chain inContext:(NSManagedObjectCo [DSDerivationPathEntity deleteDerivationPathsOnChainEntity:chainEntity]; [DSFriendRequestEntity deleteFriendRequestsOnChainEntity:chainEntity]; [chain wipeBlockchainInfoInContext:context]; - [chain.chainManager restartChainSyncStartHeight]; - [chain.chainManager restartTerminalSyncStartHeight]; - chain.chainManager.syncPhase = DSChainSyncPhase_InitialTerminalBlocks; + dispatch_async(chain.networkingQueue, ^{ + [chain.chainManager restartChainSyncStartHeight]; + [chain.chainManager restartTerminalSyncStartHeight]; + chain.chainManager.syncPhase = DSChainSyncPhase_InitialTerminalBlocks; + }); [DSBlockchainIdentityEntity deleteBlockchainIdentitiesOnChainEntity:chainEntity]; [DSDashpayUserEntity deleteContactsOnChainEntity:chainEntity]; // this must move after wipeBlockchainInfo where blockchain identities are removed [context ds_save]; @@ -192,7 +194,9 @@ - (void)wipeBlockchainNonTerminalDataForChain:(DSChain *)chain inContext:(NSMana [DSDerivationPathEntity deleteDerivationPathsOnChainEntity:chainEntity]; [DSFriendRequestEntity deleteFriendRequestsOnChainEntity:chainEntity]; [chain wipeBlockchainNonTerminalInfoInContext:context]; - [chain.chainManager restartChainSyncStartHeight]; + dispatch_async(chain.networkingQueue, ^{ + [chain.chainManager restartChainSyncStartHeight]; + }); [DSBlockchainIdentityEntity deleteBlockchainIdentitiesOnChainEntity:chainEntity]; [DSDashpayUserEntity deleteContactsOnChainEntity:chainEntity]; // this must move after wipeBlockchainInfo where blockchain identities are removed [context ds_save]; diff --git a/DashSync/shared/Libraries/AdvancedOperations/Others/NSError+Platform.h b/DashSync/shared/Libraries/AdvancedOperations/Others/NSError+Platform.h index 2547afe1..9e740be1 100644 --- a/DashSync/shared/Libraries/AdvancedOperations/Others/NSError+Platform.h +++ b/DashSync/shared/Libraries/AdvancedOperations/Others/NSError+Platform.h @@ -41,4 +41,8 @@ NS_ASSUME_NONNULL_BEGIN + (NSError *)ffi_from_sml_error:(dashcore_sml_error_SmlError *)ffi_ref; @end +@interface NSError (dashcore_sml_quorum_validation_error_QuorumValidationError) ++ (NSError *)ffi_from_quorum_validation_error:(dashcore_sml_quorum_validation_error_QuorumValidationError *)ffi_ref; +@end + NS_ASSUME_NONNULL_END diff --git a/DashSync/shared/Libraries/AdvancedOperations/Others/NSError+Platform.m b/DashSync/shared/Libraries/AdvancedOperations/Others/NSError+Platform.m index 1215cef0..ffefde31 100644 --- a/DashSync/shared/Libraries/AdvancedOperations/Others/NSError+Platform.m +++ b/DashSync/shared/Libraries/AdvancedOperations/Others/NSError+Platform.m @@ -92,7 +92,7 @@ @implementation NSError (dashcore_sml_quorum_validation_error_QuorumValidationEr + (NSError *)ffi_from_quorum_validation_error:(dashcore_sml_quorum_validation_error_QuorumValidationError *)ffi_ref { switch (ffi_ref->tag) { case dashcore_sml_quorum_validation_error_QuorumValidationError_RequiredBlockNotPresent: { - u256 *block_hash = dashcore_hash_types_BlockHash_inner(ffi_ref->required_block_not_present); + u256 *block_hash = dashcore_hash_types_BlockHash_inner(ffi_ref->required_block_not_present._0); return [NSError errorWithCode:0 descriptionKey:DSLocalizedFormat(@"QuorumValidationError::RequiredBlockNotPresent: %@ (%@)", nil, u256_hex(block_hash), u256_reversed_hex(block_hash))]; } case dashcore_sml_quorum_validation_error_QuorumValidationError_RequiredBlockHeightNotPresent: @@ -206,6 +206,8 @@ + (NSError *)ffi_from_processing_error:(DProcessingError *)ffi_ref { return [NSError errorWithCode:0 descriptionKey:DSLocalizedFormat(@"Decode Error: %@", nil, NSStringFromPtr(ffi_ref->decode_error))]; case dash_spv_masternode_processor_processing_processor_processing_error_ProcessingError_QuorumValidationError: return [NSError ffi_from_quorum_validation_error:ffi_ref->quorum_validation_error]; + case dash_spv_masternode_processor_processing_processor_processing_error_ProcessingError_SML: + return [NSError ffi_from_sml_error:ffi_ref->sml]; } } @end diff --git a/DashSync/shared/MasternodeLists/MNL_TESTNET_0_1220040.dat b/DashSync/shared/MasternodeLists/MNL_TESTNET_0_1220040.dat new file mode 100644 index 00000000..8bea0358 Binary files /dev/null and b/DashSync/shared/MasternodeLists/MNL_TESTNET_0_1220040.dat differ diff --git a/DashSync/shared/MasternodeLists/mn_list_diff_0_2227096.bin b/DashSync/shared/MasternodeLists/mn_list_diff_0_2227096.dat similarity index 100% rename from DashSync/shared/MasternodeLists/mn_list_diff_0_2227096.bin rename to DashSync/shared/MasternodeLists/mn_list_diff_0_2227096.dat diff --git a/DashSync/shared/Models/Chain/DSChain+Checkpoint.h b/DashSync/shared/Models/Chain/DSChain+Checkpoint.h index 095fddb5..e7b3c187 100644 --- a/DashSync/shared/Models/Chain/DSChain+Checkpoint.h +++ b/DashSync/shared/Models/Chain/DSChain+Checkpoint.h @@ -64,6 +64,7 @@ NS_ASSUME_NONNULL_BEGIN // MARK: Protected + (NSMutableArray *)createCheckpointsArrayFromCheckpoints:(checkpoint *)checkpoints count:(NSUInteger)checkpointCount; +- (dash_spv_masternode_processor_processing_processor_DiffConfig *_Nullable)createDiffConfig; @end NS_ASSUME_NONNULL_END diff --git a/DashSync/shared/Models/Chain/DSChain+Checkpoint.m b/DashSync/shared/Models/Chain/DSChain+Checkpoint.m index 0a6b8c1d..e6e8ccb1 100644 --- a/DashSync/shared/Models/Chain/DSChain+Checkpoint.m +++ b/DashSync/shared/Models/Chain/DSChain+Checkpoint.m @@ -151,4 +151,23 @@ + (NSMutableArray *)createCheckpointsArrayFromCheckpoints:(checkpoint *)checkpoi return [checkpointMutableArray copy]; } +- (dash_spv_masternode_processor_processing_processor_DiffConfig *_Nullable)createDiffConfig { + dash_spv_masternode_processor_processing_processor_DiffConfig *diff_config = NULL; + if ([self isMainnet]) { + NSString *bundlePath = [[NSBundle bundleForClass:self.class] pathForResource:@"DashSync" ofType:@"bundle"]; + NSBundle *bundle = [NSBundle bundleWithPath:bundlePath]; + NSString *filePath = [bundle pathForResource:@"mn_list_diff_0_2227096" ofType:@"dat"]; + NSData *data = [NSData dataWithContentsOfFile:filePath]; + + diff_config = dash_spv_masternode_processor_processing_processor_DiffConfig_ctor(bytes_ctor(data), 2227096); + } else if ([self isTestnet]) { + NSString *bundlePath = [[NSBundle bundleForClass:self.class] pathForResource:@"DashSync" ofType:@"bundle"]; + NSBundle *bundle = [NSBundle bundleWithPath:bundlePath]; + NSString *filePath = [bundle pathForResource:@"MNL_TESTNET_0_1220040" ofType:@"dat"]; + NSData *data = [NSData dataWithContentsOfFile:filePath]; + diff_config = dash_spv_masternode_processor_processing_processor_DiffConfig_ctor(bytes_ctor(data), 1220040); + } + return diff_config; +} + @end diff --git a/DashSync/shared/Models/Chain/DSChain+Transaction.m b/DashSync/shared/Models/Chain/DSChain+Transaction.m index 00a7cb87..2db8df6d 100644 --- a/DashSync/shared/Models/Chain/DSChain+Transaction.m +++ b/DashSync/shared/Models/Chain/DSChain+Transaction.m @@ -92,8 +92,6 @@ - (uint64_t)amountSentByTransaction:(DSTransaction *)transaction { //Does the chain mat - (BOOL)transactionHasLocalReferences:(DSTransaction *)transaction { - if ([self firstAccountThatCanContainTransaction:transaction]) return TRUE; - //PROVIDERS if ([transaction isKindOfClass:[DSProviderRegistrationTransaction class]]) { DSProviderRegistrationTransaction *tx = (DSProviderRegistrationTransaction *)transaction; @@ -230,6 +228,7 @@ - (BOOL)registerProviderUpdateRevocationTransaction:(DSProviderUpdateRevocationT return NO; } } +// always from chain.networkingQueue - (BOOL)registerAssetLockTransaction:(DSAssetLockTransaction *)transaction saveImmediately:(BOOL)saveImmediately { DSAssetLockTransaction *assetLockTransaction = (DSAssetLockTransaction *)transaction; UInt160 creditBurnPublicKeyHash = assetLockTransaction.creditBurnPublicKeyHash; @@ -272,6 +271,7 @@ - (BOOL)registerAssetLockTransaction:(DSAssetLockTransaction *)transaction saveI return isNewIdentity; } +// always from chain.networkingQueue - (BOOL)registerSpecialTransaction:(DSTransaction *)transaction saveImmediately:(BOOL)saveImmediately { if ([transaction isKindOfClass:[DSProviderRegistrationTransaction class]]) { return [self registerProviderRegistrationTransaction:(DSProviderRegistrationTransaction *)transaction saveImmediately:saveImmediately]; diff --git a/DashSync/shared/Models/Chain/DSChain.m b/DashSync/shared/Models/Chain/DSChain.m index de416103..1f741e76 100644 --- a/DashSync/shared/Models/Chain/DSChain.m +++ b/DashSync/shared/Models/Chain/DSChain.m @@ -634,7 +634,7 @@ - (NSArray *)standaloneDerivationPaths { // every time a new wallet address is added, the bloom filter has to be rebuilt, and each address is only used for // one transaction, so here we generate some spare addresses to avoid rebuilding the filter each time a wallet // transaction is encountered during the blockchain download - [wallet registerAddressesWithProlongGapLimit]; + [wallet registerAddressesAtStage:DSGapLimitStage_Prolong]; [allAddressesArray addObjectsFromArray:[wallet allAddresses]]; } @@ -654,7 +654,7 @@ - (DSBloomFilter *)bloomFilterWithFalsePositiveRate:(double)falsePositiveRate wi // every time a new wallet address is added, the bloom filter has to be rebuilt, and each address is only used for // one transaction, so here we generate some spare addresses to avoid rebuilding the filter each time a wallet // transaction is encountered during the blockchain download - [wallet registerAddressesWithInitialGapLimit]; + [wallet registerAddressesAtStage:DSGapLimitStage_Initial]; [allUTXOs addObjectsFromArray:wallet.unspentOutputs]; [allAddresses addObjectsFromArray:[wallet allAddresses]]; } @@ -1063,7 +1063,8 @@ - (BOOL)addMinedFullBlock:(DSFullBlock *)block { return TRUE; } -//TRUE if it was added to the end of the chain +// always from chain.networkingQueue +// TRUE if it was added to the end of the chain - (BOOL)addBlock:(DSBlock *)block receivedAsHeader:(BOOL)isHeaderOnly fromPeer:(DSPeer *)peer { NSString *prefix = [NSString stringWithFormat:@"[%@: %@:%d]", self.name, peer.host ? peer.host : @"TEST", peer.port]; if (peer && !self.chainManager.syncPhase) { @@ -1256,7 +1257,6 @@ - (BOOL)addBlock:(DSBlock *)block receivedAsHeader:(BOOL)isHeaderOnly fromPeer:( self.lastTerminalBlock = block; self.chainManager.syncState.estimatedBlockHeight = self.estimatedBlockHeight; self.chainManager.syncState.lastTerminalBlockHeight = block.height; - @synchronized(peer) { if (peer) { peer.currentBlockHeight = h; //might be download peer instead @@ -1454,7 +1454,7 @@ - (BOOL)addBlock:(DSBlock *)block receivedAsHeader:(BOOL)isHeaderOnly fromPeer:( if (((blockPosition & DSBlockPosition_Terminal) && block.height > self.estimatedBlockHeight) || ((blockPosition & DSBlockPosition_Sync) && block.height >= self.lastTerminalBlockHeight)) { @synchronized (self) { _bestEstimatedBlockHeight = block.height; - self.chainManager.syncState.estimatedBlockHeight = _bestEstimatedBlockHeight; + self.chainManager.syncState.estimatedBlockHeight = self->_bestEstimatedBlockHeight; } if (peer && (blockPosition & DSBlockPosition_Sync) && !savedBlockLocators) { [self saveBlockLocators]; @@ -1579,6 +1579,7 @@ - (void)clearOrphans { // MARK: Chain Locks +// always from chain.networkingQueue - (BOOL)addChainLock:(DSChainLock *)chainLock { DSBlock *terminalBlock = self.mTerminalBlocks[uint256_obj(chainLock.blockHashData.UInt256)]; [terminalBlock setChainLockedWithChainLock:chainLock]; @@ -1730,6 +1731,7 @@ - (NSTimeInterval)lastSyncBlockTimestamp { return _lastSyncBlock ? _lastSyncBlock.timestamp : (self.lastPersistedChainSyncBlockTimestamp ? self.lastPersistedChainSyncBlockTimestamp : self.lastSyncBlock.timestamp); } +// this is thread-unsafe, it's preferable to use NSNotificationCenter's DSChainManagerSyncStateDidChangeNotification to get progress in main thread - (uint32_t)lastSyncBlockHeight { @synchronized (_lastSyncBlock) { if (_lastSyncBlock) { @@ -1750,6 +1752,7 @@ - (UInt256)lastSyncBlockChainWork { return _lastSyncBlock ? _lastSyncBlock.chainWork : (uint256_is_not_zero(self.lastPersistedChainSyncBlockChainWork) ? self.lastPersistedChainSyncBlockChainWork : self.lastSyncBlock.chainWork); } +// this is thread-unsafe, it's preferable to use NSNotificationCenter's DSChainManagerSyncStateDidChangeNotification to get progress in main thread - (uint32_t)lastTerminalBlockHeight { return self.lastTerminalBlock.height; } @@ -1934,6 +1937,7 @@ - (NSUInteger)countEstimatedBlockHeightAnnouncers { return [announcers count]; } +// always from chain.networkingQueue - (void)setEstimatedBlockHeight:(uint32_t)estimatedBlockHeight fromPeer:(DSPeer *)peer thresholdPeerCount:(uint32_t)thresholdPeerCount { uint32_t oldEstimatedBlockHeight = self.estimatedBlockHeight; @@ -1968,6 +1972,7 @@ - (void)setEstimatedBlockHeight:(uint32_t)estimatedBlockHeight fromPeer:(DSPeer } } +// always from chain.networkingQueue - (void)removeEstimatedBlockHeightOfPeer:(DSPeer *)peer { for (NSNumber *height in [self.estimatedBlockHeights copy]) { NSMutableArray *announcers = self.estimatedBlockHeights[height]; @@ -2144,7 +2149,6 @@ - (void)saveBlockLocators { for (DSTransactionHashEntity *e in [DSTransactionHashEntity objectsInContext:self.chainManagedObjectContext matching:@"txHash in %@", [self.transactionHashHeights allKeys]]) { e.blockHeight = [self.transactionHashHeights[e.txHash] intValue]; e.timestamp = [self.transactionHashTimestamps[e.txHash] intValue]; - ; [entities addObject:e]; } for (DSTransactionHashEntity *e in entities) { diff --git a/DashSync/shared/Models/Chain/DSChainCheckpoints.h b/DashSync/shared/Models/Chain/DSChainCheckpoints.h index a2f49d45..ad09286c 100644 --- a/DashSync/shared/Models/Chain/DSChainCheckpoints.h +++ b/DashSync/shared/Models/Chain/DSChainCheckpoints.h @@ -24,7 +24,7 @@ typedef const struct checkpoint { const char *merkleRoot; const char *chainWork; } checkpoint; - +// height | hash | time | bits | path to MNLdiff | merkle root | chainwork static checkpoint testnet_checkpoint_array[] = { {0, "00000bafbc94add76cb75e2ec92894837288a481e5c005f6563d91623bf8bc2c", 1390666206, 0x1e0ffff0u, "", "", "0000000000000000000000000000000000000000000000000000000000100010"}, {1500, "000002d7a07979a4d6b24efdda0bbf6e3c03a59c22765a0128a5c53b3888aa28", 1423460945, 0x1e03ffffu, "", "", "000000000000000000000000000000000000000000000000000000009f403ba7"}, @@ -45,8 +45,10 @@ static checkpoint testnet_checkpoint_array[] = { {480000, "000001210c081f763d18db332b38ec1ac14fac62170a0d1a2028cabe8cecc799", 1618235036, 0x1e01eec7u, "", "d9fae96cce9bf0edcf9ece1b7894e0356165c0a5dcdc6f2e0784461c4168cbec", "000000000000000000000000000000000000000000000000022f14bf215f8016"}, {530000, "0000060db4b6bdb17f0617d15637bdf0f18ad738ccb438ee2cd000fef11c7130", 1625277934, 0x1e0fffffu, "MNT530000__70228", "7a6a78a22df2d9dc8c44afd48dfe4a60f75428f5e6004cf4cdf82e4f81a0a68b", "000000000000000000000000000000000000000000000000022f1524ad0dacd3"}, {760000, "000000b80d3010bb62b309aec9a7dd748777cc5e2640a26b1981cb3c61c66211", 1657592023, 0x1e01f865u, "", "8302c05bdca60e7dfcac26cebea8d797bda1b87111cf3a3dc33050c43f2abfbe", "000000000000000000000000000000000000000000000000027baba1fe003e84"}, + {1220040, "0000004d2801fdc42eb915df814bf9718bdb61819a9c47cb31fa3678ecf54818", 1742907841, 0x1e00eb3bu, "MNL_TESTNET_0_1220040", "a4d9cee58d0554bfa522dd6122141c0fe828c3e4741c86ca59a81678101fed60", "000000000000000000000000000000000000000000000000033ccd994d0f0a4e"}, }; + // blockchain checkpoints - these are also used as starting points for partial chain downloads, so they need to be at // difficulty transition boundaries in order to verify the block difficulty at the immediately following transition static checkpoint mainnet_checkpoint_array[] = { @@ -116,4 +118,5 @@ static checkpoint mainnet_checkpoint_array[] = { {1700000, "000000000000001d7579a371e782fd9c4480f626a62b916fa4eb97e16a49043a", 1657142113, 0x1927e30eu, "", "dafe57cefc3bc265dfe8416e2f2e3a22af268fd587a48f36affd404bec738305", "000000000000000000000000000000000000000000007562df93a26b81386288"}, {1720000, "000000000000001ef1f8a3d33bbe304c1d12f59f2c8aa989099dc215fd10903e", 1660295895, 0x19362176u, "", "67c6348c35bc42aa4cabd25e29560f5d22c6a9fba274bf0c52fe73021d0e8d5e", "000000000000000000000000000000000000000000007715a9ae4dd7ff1d3902"}, {1720000, "000000000000001ef1f8a3d33bbe304c1d12f59f2c8aa989099dc215fd10903e", 1660295895, 0x19362176u, "ML1720000__70218", "67c6348c35bc42aa4cabd25e29560f5d22c6a9fba274bf0c52fe73021d0e8d5e", "000000000000000000000000000000000000000000007715a9ae4dd7ff1d3902"}, + {2227096, "000000000000000899fdcd85241296146c365b238a655517da8dcd08a8a79b98", 1740273743, 0x19287724u, "mn_list_diff_0_2227096", "298585a781111ad060e5e99669893a3999b52b1d8125be0297e7efc6e62ff231", "00000000000000000000000000000000000000000000a491879d910661346c7b"}, }; diff --git a/DashSync/shared/Models/CoinJoin/DSCoinJoinManager.h b/DashSync/shared/Models/CoinJoin/DSCoinJoinManager.h index 84363324..e328b171 100644 --- a/DashSync/shared/Models/CoinJoin/DSCoinJoinManager.h +++ b/DashSync/shared/Models/CoinJoin/DSCoinJoinManager.h @@ -58,7 +58,7 @@ NS_ASSUME_NONNULL_BEGIN @interface DSCoinJoinManager : NSObject -@property (nonatomic, assign, nullable) DSChain *chain; +@property (nonatomic, strong, nullable) DSChain *chain; @property (nonatomic, strong, nullable) DSMasternodeGroup *masternodeGroup; @property (nonatomic, assign, nullable) DCoinJoinClientOptions *options; @property (nonatomic, nullable, weak) id managerDelegate; diff --git a/DashSync/shared/Models/CoinJoin/Utils/DSMasternodeGroup.m b/DashSync/shared/Models/CoinJoin/Utils/DSMasternodeGroup.m index c431ee2f..7b8d0f00 100644 --- a/DashSync/shared/Models/CoinJoin/Utils/DSMasternodeGroup.m +++ b/DashSync/shared/Models/CoinJoin/Utils/DSMasternodeGroup.m @@ -456,8 +456,7 @@ - (BOOL)connectTo:(DSPeer *)peer { transactionDelegate:(id) chainManager.transactionManager governanceDelegate:(id) chainManager.governanceSyncManager sporkDelegate:(id) chainManager.sporkManager - masternodeDelegate:chainManager.masternodeManager - queue:self.networkingQueue]; + masternodeDelegate:chainManager.masternodeManager]; peer.earliestKeyTime = self.chain.earliestWalletCreationTime;; @synchronized (self.peersLock) { diff --git a/DashSync/shared/Models/Derivation Paths/DSDerivationPathFactory.m b/DashSync/shared/Models/Derivation Paths/DSDerivationPathFactory.m index 233933a7..dcb0864c 100644 --- a/DashSync/shared/Models/Derivation Paths/DSDerivationPathFactory.m +++ b/DashSync/shared/Models/Derivation Paths/DSDerivationPathFactory.m @@ -279,6 +279,8 @@ - (DSAuthenticationKeysDerivationPath *)identityECDSAKeysDerivationPathForWallet [mArray addObject:fundsDerivationPath]; } } + if (account.coinJoinDerivationPath && ![account.coinJoinDerivationPath hasExtendedPublicKey]) + [mArray addObject:account.coinJoinDerivationPath]; } return [mArray copy]; diff --git a/DashSync/shared/Models/Derivation Paths/DSFundsDerivationPath.m b/DashSync/shared/Models/Derivation Paths/DSFundsDerivationPath.m index 5e26fd91..b6c074cc 100644 --- a/DashSync/shared/Models/Derivation Paths/DSFundsDerivationPath.m +++ b/DashSync/shared/Models/Derivation Paths/DSFundsDerivationPath.m @@ -135,7 +135,8 @@ - (void)loadAddresses { // MARK: - Derivation Path Addresses - (BOOL)registerTransactionAddress:(NSString *_Nonnull)address { - if ([self containsAddress:address]) { + BOOL contains = [self containsAddress:address]; + if (contains) { if (![self.mUsedAddresses containsObject:address]) { [self.mUsedAddresses addObject:address]; DSGapLimit *gapLimit = [self.allChangeAddresses containsObject:address] @@ -143,9 +144,8 @@ - (BOOL)registerTransactionAddress:(NSString *_Nonnull)address { : [DSGapLimitFunds external:SEQUENCE_GAP_LIMIT_EXTERNAL]; [self registerAddressesWithSettings:gapLimit]; } - return TRUE; } - return FALSE; + return contains; } // Wallets are composed of chains of addresses. Each chain is traversed until a gap of a certain number of addresses is diff --git a/DashSync/shared/Models/Derivation Paths/DSGapLimit.h b/DashSync/shared/Models/Derivation Paths/DSGapLimit.h index b8773800..feb391a3 100644 --- a/DashSync/shared/Models/Derivation Paths/DSGapLimit.h +++ b/DashSync/shared/Models/Derivation Paths/DSGapLimit.h @@ -25,6 +25,11 @@ typedef NS_ENUM(NSUInteger, DSGapLimitFundsDirection) { DSGapLimitFundsDirection_Both = DSGapLimitFundsDirection_Internal | DSGapLimitFundsDirection_External, }; +typedef NS_ENUM(NSUInteger, DSGapLimitStage) { + DSGapLimitStage_Initial = 1, + DSGapLimitStage_Prolong = 2, +}; + @interface DSGapLimit : NSObject @property (readwrite, nonatomic, assign) uintptr_t gapLimit; diff --git a/DashSync/shared/Models/Entities/DSBlockchainIdentityKeyPathEntity+CoreDataProperties.h b/DashSync/shared/Models/Entities/DSBlockchainIdentityKeyPathEntity+CoreDataProperties.h index bb6497e7..9cd4ff71 100644 --- a/DashSync/shared/Models/Entities/DSBlockchainIdentityKeyPathEntity+CoreDataProperties.h +++ b/DashSync/shared/Models/Entities/DSBlockchainIdentityKeyPathEntity+CoreDataProperties.h @@ -21,8 +21,8 @@ NS_ASSUME_NONNULL_BEGIN @property (nonatomic, assign) uint16_t keyType; @property (nonatomic, assign) uint16_t keyStatus; @property (nonatomic, assign) uint32_t keyID; -@property (nonatomic, assign) uint8_t securityLevel; -@property (nonatomic, assign) uint8_t purpose; +@property (nonatomic, assign) uint16_t securityLevel; +@property (nonatomic, assign) uint16_t purpose; @property (nullable, nonatomic, retain) NSData *publicKeyData; @end diff --git a/DashSync/shared/Models/Identity/DSIdentity+ContactRequest.m b/DashSync/shared/Models/Identity/DSIdentity+ContactRequest.m index 6934e219..05125f73 100644 --- a/DashSync/shared/Models/Identity/DSIdentity+ContactRequest.m +++ b/DashSync/shared/Models/Identity/DSIdentity+ContactRequest.m @@ -92,7 +92,7 @@ - (void)fetchIncomingContactRequestsInContext:(NSManagedObjectContext *)context withCompletion:(void (^)(BOOL success, NSArray *errors))completion onCompletionQueue:(dispatch_queue_t)completionQueue { - NSMutableString *debugInfo = [NSMutableString stringWithFormat:@"%@: fetch incoming contact requests: (startAfter: %@)", self.logPrefix, startAfter ? startAfter.hexString : @"NULL"]; + NSMutableString *debugInfo = [NSMutableString stringWithFormat:@"%@ Fetch Incoming Contact Requests: (after: %@)", self.logPrefix, startAfter ? startAfter.hexString : @"NULL"]; DPContract *dashpayContract = [DSDashPlatform sharedInstanceForChain:self.chain].dashPayContract; if (dashpayContract.contractState != DPContractState_Registered) { [debugInfo appendFormat:@" : ERROR: DashPay Contract State: %lu", dashpayContract.contractState]; @@ -207,7 +207,7 @@ - (void)fetchOutgoingContactRequestsInContext:(NSManagedObjectContext *)context startAfter:(NSData*_Nullable)startAfter withCompletion:(void (^)(BOOL success, NSArray *errors))completion onCompletionQueue:(dispatch_queue_t)completionQueue { - NSMutableString *debugInfo = [NSMutableString stringWithFormat:@"%@: fetch outgoing contact requests: (startAfter: %@)", self.logPrefix, startAfter ? startAfter.hexString : @"NULL"]; + NSMutableString *debugInfo = [NSMutableString stringWithFormat:@"%@ Fetch Outgoing Contact Requests: (after: %@)", self.logPrefix, startAfter ? startAfter.hexString : @"NULL"]; DPContract *dashpayContract = [DSDashPlatform sharedInstanceForChain:self.chain].dashPayContract; if (dashpayContract.contractState != DPContractState_Registered) { [debugInfo appendFormat:@" : ERROR: DashPay Contract State: %lu", dashpayContract.contractState]; @@ -291,7 +291,7 @@ - (void)fetchOutgoingContactRequestsInContext:(NSManagedObjectContext *)context [self.platformContext performBlockAndWait:^{ self.lastCheckedOutgoingContactsTimestamp = [[NSDate date] timeIntervalSince1970]; }]; - [debugInfo appendFormat:@" : OK: %u: %@", succeeded, rErrors]; + [debugInfo appendFormat:@" : %@: %@", succeeded ? @"OK" : @"No", [rErrors count] ? rErrors.description : @""]; DSLog(@"%@", debugInfo); __block NSData * hasMoreStartAfter = nil; if (documents->count > 0) { @@ -530,7 +530,7 @@ - (void)handleOutgoingRequests:(NSArray *)outgoingRequests atTimestamp:request->created_at inContext:context]; } else { - succeeded = FALSE; + succeeded = NO; [errors addObjectsFromArray:networkErrors]; } dispatch_group_leave(dispatchGroup); diff --git a/DashSync/shared/Models/Identity/DSIdentity+Profile.m b/DashSync/shared/Models/Identity/DSIdentity+Profile.m index a5a18cef..adc9eee8 100644 --- a/DashSync/shared/Models/Identity/DSIdentity+Profile.m +++ b/DashSync/shared/Models/Identity/DSIdentity+Profile.m @@ -384,7 +384,7 @@ - (void)updateDashpayProfileWithAvatarURLString:(NSString *)avatarURLString } - (void)signAndPublishProfileWithCompletion:(void (^)(BOOL success, BOOL cancelled, NSError *error))completion { - NSMutableString *debugInfo = [NSMutableString stringWithFormat:@"%@: Sign and publish profile", self.logPrefix]; + NSMutableString *debugInfo = [NSMutableString stringWithFormat:@"%@ Sign & Publish Profile", self.logPrefix]; DSLog(@"%@", debugInfo); NSManagedObjectContext *context = self.platformContext; __block uint32_t profileDocumentRevision; diff --git a/DashSync/shared/Models/Identity/DSIdentity+Username.h b/DashSync/shared/Models/Identity/DSIdentity+Username.h index b295efe4..590fab4b 100644 --- a/DashSync/shared/Models/Identity/DSIdentity+Username.h +++ b/DashSync/shared/Models/Identity/DSIdentity+Username.h @@ -43,9 +43,9 @@ NS_ASSUME_NONNULL_BEGIN status:(DUsernameStatus *)status save:(BOOL)save registerOnNetwork:(BOOL)registerOnNetwork; -- (DUsernameStatus *)statusOfUsername:(NSString *)username +- (DUsernameStatus *_Nullable)statusOfUsername:(NSString *)username inDomain:(NSString *)domain; -- (DUsernameStatus *)statusOfDashpayUsername:(NSString *)username; +- (DUsernameStatus *_Nullable)statusOfDashpayUsername:(NSString *)username; - (void)registerUsernamesWithCompletion:(void (^_Nullable)(BOOL success, NSArray *errors))completion; - (void)fetchUsernamesInContext:(NSManagedObjectContext *)context diff --git a/DashSync/shared/Models/Identity/DSIdentity+Username.m b/DashSync/shared/Models/Identity/DSIdentity+Username.m index 58849b0c..df01ee8d 100644 --- a/DashSync/shared/Models/Identity/DSIdentity+Username.m +++ b/DashSync/shared/Models/Identity/DSIdentity+Username.m @@ -130,13 +130,13 @@ - (void)addUsername:(NSString *)username }); } -- (DUsernameStatus *)statusOfUsername:(NSString *)username - inDomain:(NSString *)domain { - return dash_spv_platform_identity_model_IdentityModel_status_of_username(self.identity_model, DChar(username), DChar(domain)); +- (DUsernameStatus *_Nullable)statusOfUsername:(NSString *)username + inDomain:(NSString *)domain { + return username ? dash_spv_platform_identity_model_IdentityModel_status_of_username(self.identity_model, DChar(username), DChar(domain)) : nil; } -- (DUsernameStatus *)statusOfDashpayUsername:(NSString *)username { - return dash_spv_platform_identity_model_IdentityModel_status_of_dashpay_username(self.identity_model, DChar(username)); +- (DUsernameStatus *_Nullable)statusOfDashpayUsername:(NSString *)username { + return username ? dash_spv_platform_identity_model_IdentityModel_status_of_dashpay_username(self.identity_model, DChar(username)) : nil; } - (DUsernameStatus *)statusOfUsernameFullPath:(NSString *)usernameFullPath { @@ -339,7 +339,7 @@ - (void)saveUsername:(NSString *)username - (void)fetchUsernamesInContext:(NSManagedObjectContext *)context withCompletion:(void (^)(BOOL success, NSError *error))completion onCompletionQueue:(dispatch_queue_t)completionQueue { - NSMutableString *debugInfo = [NSMutableString stringWithFormat:@"%@: fetchUsernamesInContext", self.logPrefix]; + NSMutableString *debugInfo = [NSMutableString stringWithFormat:@"%@ Fetch Usernames", self.logPrefix]; DSLog(@"%@", debugInfo); DPContract *contract = [DSDashPlatform sharedInstanceForChain:self.chain].dpnsContract; if (contract.contractState != DPContractState_Registered) { @@ -412,7 +412,7 @@ - (NSError *_Nullable)registerUsernameWithSaltedDomainHash:(NSData *)saltedDomai andEntropyData:(NSData *)entropyData withIdentityPublicKey:(DIdentityPublicKey *)identity_public_key withPrivateKey:(DMaybeOpaqueKey *)maybe_private_key { - NSMutableString *debugInfo = [NSMutableString stringWithFormat:@"[%@]: registerUsernameWithSaltedDomainHash [%@]", self.logPrefix, saltedDomainHashData.hexString]; + NSMutableString *debugInfo = [NSMutableString stringWithFormat:@"[%@] Register Username With SaltedDomainHash [%@]", self.logPrefix, saltedDomainHashData.hexString]; DDocumentResult *result = dash_spv_platform_PlatformSDK_register_preordered_salted_domain_hash_for_username_full_path(self.chain.sharedRuntime, self.chain.sharedPlatformObj, contract, u256_ctor_u(self.uniqueID), identity_public_key, bytes_ctor(saltedDomainHashData), u256_ctor(entropyData)); if (result->error) { NSError *error = [NSError ffi_from_platform_error:result->error]; @@ -440,7 +440,7 @@ - (void)registerUsernamesAtStage:(DUsernameStatus *)status inContext:(NSManagedObjectContext *)context completion:(void (^_Nullable)(BOOL success, NSArray *errors))completion onCompletionQueue:(dispatch_queue_t)completionQueue { - NSMutableString *debugInfo = [NSMutableString stringWithFormat:@"[%@]: registerUsernamesAtStage [%lu]", self.logPrefix, (unsigned long) status]; + NSMutableString *debugInfo = [NSMutableString stringWithFormat:@"%@ Register Usernames At Stage [%hhu]", self.logPrefix, DUsernameStatusIndex(status)]; DSLog(@"%@", debugInfo); Vec_String *result = dash_spv_platform_identity_model_IdentityModel_username_full_paths_with_status(self.identity_model, status); NSArray *usernameFullPaths = [NSArray ffi_from_vec_of_string:result]; diff --git a/DashSync/shared/Models/Identity/DSIdentity.h b/DashSync/shared/Models/Identity/DSIdentity.h index 7977e18e..5bbdddd6 100644 --- a/DashSync/shared/Models/Identity/DSIdentity.h +++ b/DashSync/shared/Models/Identity/DSIdentity.h @@ -12,9 +12,6 @@ NS_ASSUME_NONNULL_BEGIN -#define FLAG_IS_SET(value, flag) ((value & flag) == flag) - - @class DSWallet, DSAccount, DSChain, DSDashpayUserEntity, DSPotentialOneWayFriendship, DSTransaction, DSFriendRequestEntity, DSPotentialContact, DSAssetLockTransaction, DSTransientDashpayUser, DSInvitation, DSAuthenticationKeysDerivationPath, UIImage; typedef NS_ENUM(NSUInteger, DSIdentityRegistrationStep) diff --git a/DashSync/shared/Models/Identity/DSIdentity.m b/DashSync/shared/Models/Identity/DSIdentity.m index a4b40f01..8a98eb50 100644 --- a/DashSync/shared/Models/Identity/DSIdentity.m +++ b/DashSync/shared/Models/Identity/DSIdentity.m @@ -295,20 +295,20 @@ - (void)applyIdentityEntity:(DSBlockchainIdentityEntity *)identityEntity { if (self.isLocal || self.isOutgoingInvitation) { if (identityEntity.registrationFundingTransaction) { self.registrationAssetLockTransactionHash = identityEntity.registrationFundingTransaction.transactionHash.txHash.UInt256; - DSLog(@"%@: AssetLockTX: Entity Attached: txHash: %@: entity: %@", self.logPrefix, uint256_hex(self.registrationAssetLockTransactionHash), identityEntity.registrationFundingTransaction); + DSLog(@"%@ AssetLockTX: Entity Attached: txHash: %@: entity: %@", self.logPrefix, uint256_hex(self.registrationAssetLockTransactionHash), identityEntity.registrationFundingTransaction); } else { NSData *transactionHashData = uint256_data(uint256_reverse(self.lockedOutpoint.hash)); - DSLog(@"%@: AssetLockTX: Load: lockedOutpoint: %@: %lu %@", self.logPrefix, uint256_hex(self.lockedOutpoint.hash), self.lockedOutpoint.n, transactionHashData.hexString); + DSLog(@"%@ AssetLockTX: Load: lockedOutpoint: %@: %lu %@", self.logPrefix, uint256_hex(self.lockedOutpoint.hash), self.lockedOutpoint.n, transactionHashData.hexString); DSAssetLockTransactionEntity *assetLockEntity = [DSAssetLockTransactionEntity anyObjectInContext:identityEntity.managedObjectContext matching:@"transactionHash.txHash == %@", transactionHashData]; if (assetLockEntity) { self.registrationAssetLockTransactionHash = assetLockEntity.transactionHash.txHash.UInt256; - DSLog(@"%@: AssetLockTX: Found: txHash: %@: entity: %@", self.logPrefix, uint256_hex(self.registrationAssetLockTransactionHash), assetLockEntity); + DSLog(@"%@ AssetLockTX: Entity Found for txHash: %@", self.logPrefix, uint256_hex(self.registrationAssetLockTransactionHash)); DSAssetLockTransaction *registrationAssetLockTransaction = (DSAssetLockTransaction *)[assetLockEntity transactionForChain:self.chain]; BOOL correctIndex = self.isOutgoingInvitation ? [registrationAssetLockTransaction checkInvitationDerivationPathIndexForWallet:self.wallet isIndex:self.index] : [registrationAssetLockTransaction checkDerivationPathIndexForWallet:self.wallet isIndex:self.index]; if (!correctIndex) { - DSLog(@"%@: AssetLockTX: IncorrectIndex %u (%@)", self.logPrefix, self.index, registrationAssetLockTransaction.toData.hexString); + DSLog(@"%@ AssetLockTX: IncorrectIndex %u (%@)", self.logPrefix, self.index, registrationAssetLockTransaction.toData.hexString); //NSAssert(FALSE, @"We should implement this"); } } @@ -348,7 +348,7 @@ - (instancetype)initAtIndex:(uint32_t)index self.lockedOutpoint = lockedOutpoint; self.uniqueID = [dsutxo_data(lockedOutpoint) SHA256_2]; - DSLog(@"%@: initAtIndex: %u lockedOutpoint: %@: %lu", self.logPrefix, index, uint256_hex(lockedOutpoint.hash), lockedOutpoint.n); + DSLog(@"%@ initAtIndex: %u lockedOutpoint: %@: %lu", self.logPrefix, index, uint256_hex(lockedOutpoint.hash), lockedOutpoint.n); return self; } @@ -583,7 +583,7 @@ - (void)registerOnNetwork:(DSIdentityRegistrationStep)steps pinPrompt:(NSString *)prompt stepCompletion:(void (^_Nullable)(DSIdentityRegistrationStep stepCompleted))stepCompletion completion:(void (^_Nullable)(DSIdentityRegistrationStep stepsCompleted, NSArray *errors))completion { - DSLog(@"%@: registerOnNetwork: %@", self.logPrefix, DSRegistrationStepsDescription(steps)); + DSLog(@"%@ Register On Network: %@", self.logPrefix, DSRegistrationStepsDescription(steps)); __block DSIdentityRegistrationStep stepsCompleted = DSIdentityRegistrationStep_None; if (![self hasIdentityExtendedPublicKeys]) { if (completion) dispatch_async(dispatch_get_main_queue(), ^{ completion(stepsCompleted, @[ERROR_REGISTER_KEYS_BEFORE_IDENTITY]); }); @@ -724,7 +724,7 @@ - (void)registerInWalletForAssetLockTransaction:(DSAssetLockTransaction *)transa self.registrationAssetLockTransactionHash = transaction.txHash; DSUTXO lockedOutpoint = transaction.lockedOutpoint; UInt256 creditBurnIdentityIdentifier = transaction.creditBurnIdentityIdentifier; - DSLog(@"%@: registerInWalletForAssetLockTransaction: txHash: %@: creditBurnIdentityID: %@, creditBurnPublicKeyHash: %@, lockedOutpoint: %@: %lu", self.logPrefix, uint256_hex(transaction.txHash), uint256_hex(creditBurnIdentityIdentifier), uint160_hex(transaction.creditBurnPublicKeyHash), uint256_hex(lockedOutpoint.hash), lockedOutpoint.n); + DSLog(@"%@ Register In Wallet (AssetLockTx Register): txHash: %@: creditBurnIdentityID: %@, creditBurnPublicKeyHash: %@, lockedOutpoint: %@: %lu", self.logPrefix, uint256_hex(transaction.txHash), uint256_hex(creditBurnIdentityIdentifier), uint160_hex(transaction.creditBurnPublicKeyHash), uint256_hex(lockedOutpoint.hash), lockedOutpoint.n); self.lockedOutpoint = lockedOutpoint; [self registerInWalletForIdentityUniqueId:creditBurnIdentityIdentifier]; //we need to also set the address of the funding transaction to being used so future identities past the initial gap limit are found @@ -738,7 +738,7 @@ - (void)registerInWalletForAssetLockTopupTransaction:(DSAssetLockTransaction *)t DSUTXO lockedOutpoint = transaction.lockedOutpoint; UInt256 creditBurnIdentityIdentifier = transaction.creditBurnIdentityIdentifier; - DSLog(@"%@: registerInWalletForAssetLockTopupTransaction: txHash: %@: creditBurnIdentityID: %@, creditBurnPublicKeyHash: %@, lockedOutpoint: %@: %lu", self.logPrefix, uint256_hex(transaction.txHash), uint256_hex(creditBurnIdentityIdentifier), uint160_hex(transaction.creditBurnPublicKeyHash), uint256_hex(lockedOutpoint.hash), lockedOutpoint.n); + DSLog(@"%@ Register In Wallet (AssetLockTx TopUp): txHash: %@: creditBurnIdentityID: %@, creditBurnPublicKeyHash: %@, lockedOutpoint: %@: %lu", self.logPrefix, uint256_hex(transaction.txHash), uint256_hex(creditBurnIdentityIdentifier), uint160_hex(transaction.creditBurnPublicKeyHash), uint256_hex(lockedOutpoint.hash), lockedOutpoint.n); // self.lockedOutpoint = lockedOutpoint; [self registerInWalletForIdentityUniqueId:creditBurnIdentityIdentifier]; //we need to also set the address of the funding transaction to being used so future identities past the initial gap limit are found @@ -1350,7 +1350,7 @@ - (void)registerIdentityWithProof:(DAssetLockProof *)proof public_key:(DIdentityPublicKey *)public_key atIndex:(uint32_t)index completion:(void (^)(BOOL, NSError *))completion { - NSMutableString *debugInfo = [NSMutableString stringWithFormat:@"%@: Register Identity using public key (%u: %p) at %u with private key: %p", self.logPrefix, public_key->tag, public_key, index, self.internalRegistrationFundingPrivateKey->ok]; + NSMutableString *debugInfo = [NSMutableString stringWithFormat:@"%@ Register Identity using public key (%u: %p) at %u with private key: %p", self.logPrefix, public_key->tag, public_key, index, self.internalRegistrationFundingPrivateKey->ok]; DSLog(@"%@", debugInfo); DMaybeStateTransitionProofResult *state_transition_result = dash_spv_platform_PlatformSDK_identity_register_using_public_key_at_index(self.chain.sharedRuntime, self.chain.sharedPlatformObj, public_key, index, proof, self.internalRegistrationFundingPrivateKey->ok); if (state_transition_result->error) { @@ -1405,7 +1405,7 @@ - (void)registerIdentityWithProof2:(DAssetLockProof *)proof public_key:(DIdentityPublicKey *)public_key atIndex:(uint32_t)index completion:(void (^)(BOOL, NSError *_Nullable))completion { - NSMutableString *debugInfo = [NSMutableString stringWithFormat:@"%@: Register Identity using public key (%u: %p) at %u with private key: %p", self.logPrefix, public_key->tag, public_key, index, self.internalRegistrationFundingPrivateKey->ok]; + NSMutableString *debugInfo = [NSMutableString stringWithFormat:@"%@ Register Identity (public key (%u: %p) at %u with private key: %p", self.logPrefix, public_key->tag, public_key, index, self.internalRegistrationFundingPrivateKey->ok]; DSLog(@"%@", debugInfo); Result_ok_dpp_identity_identity_Identity_err_dash_spv_platform_error_Error *state_transition_result = dash_spv_platform_PlatformSDK_identity_register_using_public_key_at_index2(self.chain.sharedRuntime, self.chain.sharedPlatformObj, public_key, index, proof, self.internalRegistrationFundingPrivateKey->ok); if (state_transition_result->error) { @@ -1438,7 +1438,7 @@ - (void)topupIdentityWithProof:(DAssetLockProof *)proof public_key:(DIdentityPublicKey *)public_key atIndex:(uint32_t)index completion:(void (^)(BOOL, NSError *_Nullable))completion { - NSMutableString *debugInfo = [NSMutableString stringWithFormat:@"%@: TopUp Identity using public key (%u: %p) at %u with private key: %p", self.logPrefix, public_key->tag, public_key, index, self.internalTopupFundingPrivateKey->ok]; + NSMutableString *debugInfo = [NSMutableString stringWithFormat:@"%@ TopUp Identity using public key (%u: %p) at %u with private key: %p", self.logPrefix, public_key->tag, public_key, index, self.internalTopupFundingPrivateKey->ok]; DSLog(@"%@", debugInfo); u256 *identity_id = u256_ctor_u(self.uniqueID); DMaybeStateTransitionProofResult *state_transition_result = dash_spv_platform_PlatformSDK_identity_topup(self.chain.sharedRuntime, self.chain.sharedPlatformObj, identity_id, proof, self.internalTopupFundingPrivateKey->ok); @@ -1494,7 +1494,7 @@ - (void)createAndPublishTopUpTransitionForAmount:(uint64_t)amount fundedByAccount:(DSAccount *)fundingAccount pinPrompt:(NSString *)prompt withCompletion:(void (^)(BOOL, NSError *_Nullable))completion { - NSMutableString *debugInfo = [NSMutableString stringWithFormat:@"%@: CREATE AND PUBLISH IDENTITY TOPUP TRANSITION", self.logPrefix]; + NSMutableString *debugInfo = [NSMutableString stringWithFormat:@"%@ CREATE AND PUBLISH IDENTITY TOPUP TRANSITION", self.logPrefix]; DSLog(@"%@", debugInfo); DSAssetLockDerivationPath *path = [[DSDerivationPathFactory sharedInstance] identityTopupFundingDerivationPathForWallet:self.wallet]; NSString *topupAddress = [path addressAtIndexPath:[NSIndexPath indexPathWithIndex:self.index]]; @@ -1547,7 +1547,7 @@ - (void)createAndPublishTopUpTransitionForAmount:(uint64_t)amount } - (void)createAndPublishRegistrationTransitionWithCompletion:(void (^)(BOOL, NSError *))completion { - NSMutableString *debugInfo = [NSMutableString stringWithFormat:@"%@: CREATE AND PUBLISH IDENTITY REGISTRATION TRANSITION", self.logPrefix]; + NSMutableString *debugInfo = [NSMutableString stringWithFormat:@"%@ CREATE AND PUBLISH IDENTITY REGISTRATION TRANSITION", self.logPrefix]; DSLog(@"%@", debugInfo); if (!self.internalRegistrationFundingPrivateKey) { DSLog(@"%@: ERROR: No Funding Private Key", debugInfo); @@ -1576,7 +1576,7 @@ - (void)createAndPublishRegistrationTransitionWithCompletion:(void (^)(BOOL, NSE // MARK: Retrieval - (void)fetchIdentityNetworkStateInformationWithCompletion:(void (^)(BOOL success, BOOL found, NSError *error))completion { - NSMutableString *debugString = [NSMutableString stringWithFormat:@"%@: Fetch Identity State", self.logPrefix]; + NSMutableString *debugString = [NSMutableString stringWithFormat:@"%@ Fetch Identity State", self.logPrefix]; DSLog(@"%@", debugString); dispatch_async(self.identityQueue, ^{ DMaybeIdentity *result = dash_spv_platform_identity_manager_IdentitiesManager_monitor_for_id_bytes(self.chain.sharedRuntime, self.chain.sharedIdentitiesObj, u256_ctor(self.uniqueIDData), DRetryDown50(DEFAULT_FETCH_IDENTITY_RETRY_COUNT), self.isLocal ? DAcceptIdentityNotFound() : DRaiseIdentityNotFound()); @@ -1671,7 +1671,7 @@ - (void)fetchL3NetworkStateInformation:(DSIdentityQueryStep)queryStep inContext:(NSManagedObjectContext *)context withCompletion:(void (^)(DSIdentityQueryStep failureStep, NSArray *errors))completion onCompletionQueue:(dispatch_queue_t)completionQueue { - DSLog(@"%@: Fetch L3 State (%@)", self.logPrefix, DSIdentityQueryStepsDescription(queryStep)); + DSLog(@"%@ Fetch L3 State (%@)", self.logPrefix, DSIdentityQueryStepsDescription(queryStep)); if (!(queryStep & DSIdentityQueryStep_Identity) && (!self.activeKeyCount)) { // We need to fetch keys if we want to query other information if (completion) completion(DSIdentityQueryStep_BadQuery, @[ERROR_ATTEMPT_QUERY_WITHOUT_KEYS]); @@ -1771,7 +1771,7 @@ - (void)fetchNetworkStateInformation:(DSIdentityQueryStep)querySteps inContext:(NSManagedObjectContext *)context withCompletion:(void (^)(DSIdentityQueryStep failureStep, NSArray *errors))completion onCompletionQueue:(dispatch_queue_t)completionQueue { - NSMutableString *debugString = [NSMutableString stringWithFormat:@"%@: fetchNetworkStateInformation (%@)", self.logPrefix, DSIdentityQueryStepsDescription(querySteps)]; + NSMutableString *debugString = [NSMutableString stringWithFormat:@"%@ fetchNetworkStateInformation (%@)", self.logPrefix, DSIdentityQueryStepsDescription(querySteps)]; DSLog(@"%@", debugString); if (querySteps & DSIdentityQueryStep_Identity) { [self fetchIdentityNetworkStateInformationWithCompletion:^(BOOL success, BOOL found, NSError *error) { @@ -1851,7 +1851,7 @@ - (void)fetchIfNeededNetworkStateInformation:(DSIdentityQueryStep)querySteps - (void)fetchNeededNetworkStateInformationInContext:(NSManagedObjectContext *)context withCompletion:(void (^)(DSIdentityQueryStep failureStep, NSArray *errors))completion onCompletionQueue:(dispatch_queue_t)completionQueue { - NSMutableString *debugString = [NSMutableString stringWithFormat:@"%@: fetchNeededNetworkStateInformationInContext (local: %u, active keys: %lu) ", self.logPrefix, self.isLocal, self.activeKeyCount]; + NSMutableString *debugString = [NSMutableString stringWithFormat:@"%@ Fetch Needed Network State Info (local: %u, active keys: %lu) ", self.logPrefix, self.isLocal, self.activeKeyCount]; DSLog(@"%@", debugString); dispatch_async(self.identityQueue, ^{ if (!self.activeKeyCount) { @@ -1902,34 +1902,34 @@ - (BOOL)processStateTransitionResult:(DMaybeStateTransitionProofResult *)result switch (proof_result->tag) { case dpp_state_transition_proof_result_StateTransitionProofResult_VerifiedDataContract: { NSData *identifier = NSDataFromPtr(proof_result->verified_data_contract->v0->id->_0->_0); - DSLog(@"%@: VerifiedDataContract: %@", self.logPrefix, identifier.hexString); + DSLog(@"%@ VerifiedDataContract: %@", self.logPrefix, identifier.hexString); break; } case dpp_state_transition_proof_result_StateTransitionProofResult_VerifiedIdentity: { NSData *identifier = NSDataFromPtr(proof_result->verified_identity->v0->id->_0->_0); - DSLog(@"%@: VerifiedIdentity: %@", self.logPrefix, identifier.hexString); + DSLog(@"%@ VerifiedIdentity: %@", self.logPrefix, identifier.hexString); break; } case dpp_state_transition_proof_result_StateTransitionProofResult_VerifiedPartialIdentity: { - NSData *identifier = NSDataFromPtr(proof_result->verified_partial_identity>id->_0->_0); - DSLog(@"%@: VerifiedPartialIdentity: %@", self.logPrefix, identifier.hexString); + NSData *identifier = NSDataFromPtr(proof_result->verified_partial_identity->id->_0->_0); + DSLog(@"%@ VerifiedPartialIdentity: %@", self.logPrefix, identifier.hexString); break; } case dpp_state_transition_proof_result_StateTransitionProofResult_VerifiedBalanceTransfer: { - dpp_state_transition_proof_result_StateTransitionProofResult_VerifiedBalanceTransfer_Body *transfer = proof_result->verified_balance_transfer; - NSData *from_identifier = NSDataFromPtr(transfer->_0->id->_0->_0); - NSData *to_identifier = NSDataFromPtr(transfer->_1->id->_0->_0); - DSLog(@"%@: VerifiedBalanceTransfer: %@ --> %@", self.logPrefix, from_identifier.hexString, to_identifier.hexString); + dpp_state_transition_proof_result_StateTransitionProofResult_VerifiedBalanceTransfer_Body transfer = proof_result->verified_balance_transfer; + NSData *from_identifier = NSDataFromPtr(transfer._0->id->_0->_0); + NSData *to_identifier = NSDataFromPtr(transfer._1->id->_0->_0); + DSLog(@"%@ VerifiedBalanceTransfer: %@ --> %@", self.logPrefix, from_identifier.hexString, to_identifier.hexString); break; } case dpp_state_transition_proof_result_StateTransitionProofResult_VerifiedDocuments: { std_collections_Map_keys_platform_value_types_identifier_Identifier_values_Option_dpp_document_Document *verified_documents = proof_result->verified_documents; - DSLog(@"%@: VerifiedDocuments: %u", self.logPrefix, verified_documents->count); + DSLog(@"%@ VerifiedDocuments: %lu", self.logPrefix, verified_documents->count); break; } case dpp_state_transition_proof_result_StateTransitionProofResult_VerifiedMasternodeVote: { dpp_voting_votes_Vote *verified_masternode_vote = proof_result->verified_masternode_vote; - DSLog(@"%@: VerifiedMasternodeVote: %u", self.logPrefix, verified_masternode_vote->tag); + DSLog(@"%@ VerifiedMasternodeVote: %u", self.logPrefix, verified_masternode_vote->tag); break; } default: @@ -1942,7 +1942,7 @@ - (BOOL)processStateTransitionResult:(DMaybeStateTransitionProofResult *)result // MARK: - Contracts - (void)fetchAndUpdateContract:(DPContract *)contract { - NSMutableString *debugString = [NSMutableString stringWithFormat:@"%@: fetchAndUpdateContract (%lu) ", self.logPrefix, (unsigned long) contract.contractState]; + NSMutableString *debugString = [NSMutableString stringWithFormat:@"%@ Fetch & Update Contract (%lu) ", self.logPrefix, (unsigned long) contract.contractState]; DSLog(@"%@", debugString); NSManagedObjectContext *context = [NSManagedObjectContext platformContext]; __weak typeof(contract) weakContract = contract; @@ -1967,11 +1967,11 @@ - (void)fetchAndUpdateContract:(DPContract *)contract { DMaybeStateTransitionProofResult *state_transition_result = dash_spv_platform_PlatformSDK_data_contract_create2(self.chain.sharedRuntime, self.chain.sharedPlatformObj, data_contracts_SystemDataContract_DPNS_ctor(), u256_ctor_u(self.uniqueID), 0, privateKey->ok); if (state_transition_result->error) { - DSLog(@"%@: ERROR: %@", debugString, [NSError ffi_from_platform_error:state_transition_result->error]); + DSLog(@"%@ ERROR: %@", debugString, [NSError ffi_from_platform_error:state_transition_result->error]); DMaybeStateTransitionProofResultDtor(state_transition_result); return; } - DSLog(@"%@: OK", debugString); + DSLog(@"%@ OK", debugString); if ([self processStateTransitionResult:state_transition_result]) { contract.contractState = DPContractState_Registering; } else { @@ -1983,36 +1983,36 @@ - (void)fetchAndUpdateContract:(DPContract *)contract { if (monitor_result->error) { DMaybeContractDtor(monitor_result); - DSLog(@"%@: Contract Monitoring Error: %@", self.logPrefix, [NSError ffi_from_platform_error:monitor_result->error]); + DSLog(@"%@ Contract Monitoring Error: %@", self.logPrefix, [NSError ffi_from_platform_error:monitor_result->error]); return; } if (monitor_result->ok) { NSData *identifier = NSDataFromPtr(monitor_result->ok->v0->id->_0->_0); if ([identifier isEqualToData:uint256_data(contract.contractId)]) { - DSLog(@"%@: Contract Monitoring OK", self.logPrefix); + DSLog(@"%@ Contract Monitoring OK", self.logPrefix); contract.contractState = DPContractState_Registered; [contract saveAndWaitInContext:context]; } else { - DSLog(@"%@: Contract Monitoring Error: Ids dont match", self.logPrefix); + DSLog(@"%@ Contract Monitoring Error: Ids dont match", self.logPrefix); } } - DSLog(@"%@: Contract Monitoring Error", self.logPrefix); + DSLog(@"%@ Contract Monitoring Error", self.logPrefix); } else if (contract.contractState == DPContractState_Registered || contract.contractState == DPContractState_Registering) { - DSLog(@"%@: Fetching contract for verification %@", self.logPrefix, contract.base58ContractId); + DSLog(@"%@ Fetching contract for verification %@", self.logPrefix, contract.base58ContractId); DMaybeContract *contract_result = dash_spv_platform_contract_manager_ContractsManager_fetch_contract_by_id_bytes(self.chain.sharedRuntime, self.chain.sharedContractsObj, u256_ctor_u(contract.contractId)); dispatch_async(self.identityQueue, ^{ __strong typeof(weakContract) strongContract = weakContract; if (!weakContract || !contract_result) return; if (!contract_result->ok) { - DSLog(@"%@: Contract Monitoring ERROR: NotRegistered ", self.logPrefix); + DSLog(@"%@ Contract Monitoring ERROR: NotRegistered ", self.logPrefix); strongContract.contractState = DPContractState_NotRegistered; [strongContract saveAndWaitInContext:context]; DMaybeContractDtor(contract_result); return; } - DSLog(@"%@: Contract Monitoring OK: %@ ", self.logPrefix, strongContract); + DSLog(@"%@ Contract Monitoring OK: %@ ", self.logPrefix, strongContract); if (strongContract.contractState == DPContractState_Registered && !dash_spv_platform_contract_manager_has_equal_document_type_keys(contract_result->ok, strongContract.raw_contract)) { strongContract.contractState = DPContractState_NotRegistered; [strongContract saveAndWaitInContext:context]; @@ -2034,13 +2034,13 @@ - (void)updateCreditBalance { if (!strongSelf) return; DMaybeIdentityBalance *result = dash_spv_platform_identity_manager_IdentitiesManager_fetch_balance_by_id_bytes(strongSelf.chain.sharedRuntime, strongSelf.chain.sharedIdentitiesObj, u256_ctor(self.uniqueIDData)); if (!result->ok) { - DSLog(@"%@: updateCreditBalance: ERROR RESULT: %u", self.logPrefix, result->error->tag); + DSLog(@"%@ Update Credit Balance: ERROR RESULT: %u", self.logPrefix, result->error->tag); DMaybeIdentityBalanceDtor(result); return; } uint64_t balance = result->ok[0]; DMaybeIdentityBalanceDtor(result); - DSLog(@"%@: updateCreditBalance: OK: %llu", self.logPrefix, balance); + DSLog(@"%@ Update Credit Balance: OK: %llu", self.logPrefix, balance); dispatch_async(self.identityQueue, ^{ strongSelf.creditBalance = balance; }); @@ -2445,7 +2445,7 @@ - (NSString *)debugDescription { } - (NSString *)logPrefix { - return [NSString stringWithFormat:@"[%@] [Identity: %@] ", self.chain.name, uint256_hex(self.uniqueID)]; + return [NSString stringWithFormat:@"[%@] [Identity: %@]", self.chain.name, uint256_hex(self.uniqueID)]; } diff --git a/DashSync/shared/Models/Managers/Chain Managers/DSChainManager+Protected.h b/DashSync/shared/Models/Managers/Chain Managers/DSChainManager+Protected.h index 3ae80d6a..11d5b782 100644 --- a/DashSync/shared/Models/Managers/Chain Managers/DSChainManager+Protected.h +++ b/DashSync/shared/Models/Managers/Chain Managers/DSChainManager+Protected.h @@ -34,7 +34,7 @@ typedef NS_ENUM(uint16_t, DSChainNotificationType) { - (void)wipeMasternodeInfo; - (void)notifySyncStateChanged; -- (void)notifyMasternodeSyncStateChange:(uint32_t)lastBlockHeihgt storedCount:(uintptr_t)storedCount; +- (void)notifyMasternodeSyncStateChange:(uint32_t)lastBlockHeihgt storedCount:(uint32_t)storedCount; @end diff --git a/DashSync/shared/Models/Managers/Chain Managers/DSChainManager.h b/DashSync/shared/Models/Managers/Chain Managers/DSChainManager.h index 421212f7..d359af9e 100644 --- a/DashSync/shared/Models/Managers/Chain Managers/DSChainManager.h +++ b/DashSync/shared/Models/Managers/Chain Managers/DSChainManager.h @@ -40,7 +40,7 @@ typedef NS_ENUM(uint32_t, DSSyncCountInfo) DSSyncCountInfo_GovernanceObjectVote = 11, }; -#define PROTOCOL_TIMEOUT 20.0 +#define PROTOCOL_TIMEOUT 40.0 FOUNDATION_EXPORT NSString *const DSChainManagerNotificationChainKey; FOUNDATION_EXPORT NSString *const DSChainManagerNotificationWalletKey; @@ -84,7 +84,6 @@ typedef void (^MultipleBlockMiningCompletionBlock)(NSArray *block - (void)masternodeListAndBlocksRescan; - (void)masternodeListRescan; - - (DSChainLock * _Nullable)chainLockForBlockHash:(UInt256)blockHash; @end diff --git a/DashSync/shared/Models/Managers/Chain Managers/DSChainManager.m b/DashSync/shared/Models/Managers/Chain Managers/DSChainManager.m index a95640b8..930d0bab 100644 --- a/DashSync/shared/Models/Managers/Chain Managers/DSChainManager.m +++ b/DashSync/shared/Models/Managers/Chain Managers/DSChainManager.m @@ -98,7 +98,10 @@ - (instancetype)initWithChain:(DSChain *)chain { self.lastNotifiedBlockDidChange = 0; if ([self.masternodeManager hasCurrentMasternodeListInLast30Days]) { - [self.peerManager useMasternodeList:self.masternodeManager.currentMasternodeList withConnectivityNonce:self.sessionConnectivityNonce]; + dispatch_async(self.chain.networkingQueue, ^{ + [self.peerManager useMasternodeList:self.masternodeManager.currentMasternodeList + withConnectivityNonce:self.sessionConnectivityNonce]; + }); } //[self loadMaxTransactionInfo]; @@ -110,14 +113,15 @@ - (instancetype)initWithChain:(DSChain *)chain { } - (NSString *)logPrefix { - return [NSString stringWithFormat:@"[%@] [Chain Manager] ", self.chain.name]; + return [NSString stringWithFormat:@"[%@] [Chain Manager]", self.chain.name]; } - (BOOL)isSynced { - return self.syncState.combinedSyncProgress == 1.0; + return self.syncState.progress == 1.0; } +// this is thread-unsafe, it's preferable to use NSNotificationCenter's DSChainManagerSyncStateDidChangeNotification to get progress in main thread - (double)combinedSyncProgress { - return self.syncState.combinedSyncProgress; + return self.syncState.progress; } @@ -137,10 +141,14 @@ - (void)startSync { - (void)stopSync { DSLog(@"%@ stop (chain switch)", self.logPrefix); - [self.masternodeManager stopSync]; + dispatch_async(self.chain.networkingQueue, ^{ + [self.masternodeManager stopSync]; + }); [self.peerManager disconnect:DSDisconnectReason_ChainSwitch]; - self.syncState.syncPhase = DSChainSyncPhase_Offline; - [self notifySyncStateChanged]; + dispatch_async(self.chain.networkingQueue, ^{ + self.syncState.syncPhase = DSChainSyncPhase_Offline; + [self notifySyncStateChanged]; + }); } - (void)removeNonMainnetTrustedPeer { @@ -150,81 +158,54 @@ - (void)removeNonMainnetTrustedPeer { } } -- (void)disconnectedMasternodeListAndBlocksRescan { - NSManagedObjectContext *chainContext = [NSManagedObjectContext chainContext]; - [[DashSync sharedSyncController] wipeMasternodeDataForChain:self.chain inContext:chainContext]; - [[DashSync sharedSyncController] wipeBlockchainDataForChain:self.chain inContext:chainContext]; - - [self removeNonMainnetTrustedPeer]; - [self notify:DSChainManagerSyncWillStartNotification userInfo:@{DSChainManagerNotificationChainKey: self.chain}]; - DSLog(@"[%@] Disconnected (MasternodeListAndBlocksRescan) -> peerManager::connect", self.logPrefix); - [self.peerManager connect]; -} - -- (void)disconnectedMasternodeListRescan { - NSManagedObjectContext *chainContext = [NSManagedObjectContext chainContext]; - [[DashSync sharedSyncController] wipeMasternodeDataForChain:self.chain inContext:chainContext]; - - [self removeNonMainnetTrustedPeer]; - [self notify:DSChainManagerSyncWillStartNotification userInfo:@{DSChainManagerNotificationChainKey: self.chain}]; - DSLog(@"%@ Disconnected (MasternodeListRescan) -> peerManager::connect", self.logPrefix); - [self.peerManager connect]; -} - -- (void)disconnectedSyncBlocksRescan { - NSManagedObjectContext *chainContext = [NSManagedObjectContext chainContext]; - [[DashSync sharedSyncController] wipeBlockchainNonTerminalDataForChain:self.chain inContext:chainContext]; - - [self removeNonMainnetTrustedPeer]; - [self notify:DSChainManagerSyncWillStartNotification userInfo:@{DSChainManagerNotificationChainKey: self.chain}]; - DSLog(@"%@ Disconnected (SyncBlocksRescan) -> peerManager::connect", self.logPrefix); - [self.peerManager connect]; -} - // rescans blocks and transactions after earliestKeyTime, a new random download peer is also selected due to the // possibility that a malicious node might lie by omitting transactions that match the bloom filter - (void)syncBlocksRescan { - if (!self.peerManager.connected) { - [self disconnectedSyncBlocksRescan]; - } else { - [self.peerManager disconnectDownloadPeerForError:nil - withCompletion:^(BOOL success) { - [self disconnectedSyncBlocksRescan]; - }]; - } + [self.peerManager disconnectDownloadPeerForError:nil + withCompletion:^(BOOL success) { + NSManagedObjectContext *chainContext = [NSManagedObjectContext chainContext]; + [[DashSync sharedSyncController] wipeBlockchainNonTerminalDataForChain:self.chain inContext:chainContext]; + [self removeNonMainnetTrustedPeer]; + [self notify:DSChainManagerSyncWillStartNotification userInfo:@{DSChainManagerNotificationChainKey: self.chain}]; + DSLog(@"%@ Disconnected (SyncBlocksRescan) -> peerManager::connect", self.logPrefix); + [self.peerManager connect]; + }]; } - (void)masternodeListAndBlocksRescan { - if (!self.peerManager.connected) { - [self disconnectedMasternodeListAndBlocksRescan]; - } else { - [self.peerManager disconnectDownloadPeerForError:nil - withCompletion:^(BOOL success) { - [self disconnectedMasternodeListAndBlocksRescan]; - }]; - } + [self.peerManager disconnectDownloadPeerForError:nil + withCompletion:^(BOOL success) { + NSManagedObjectContext *chainContext = [NSManagedObjectContext chainContext]; + [[DashSync sharedSyncController] wipeMasternodeDataForChain:self.chain inContext:chainContext]; + [[DashSync sharedSyncController] wipeBlockchainDataForChain:self.chain inContext:chainContext]; + [self removeNonMainnetTrustedPeer]; + [self notify:DSChainManagerSyncWillStartNotification userInfo:@{DSChainManagerNotificationChainKey: self.chain}]; + DSLog(@"%@ Disconnected (MasternodeListAndBlocksRescan) -> peerManager::connect", self.logPrefix); + [self.peerManager connect]; + }]; } - (void)masternodeListRescan { - if (!self.peerManager.connected) { - [self disconnectedMasternodeListRescan]; - } else { - [self.peerManager disconnectDownloadPeerForError:nil - withCompletion:^(BOOL success) { - [self disconnectedMasternodeListRescan]; - }]; - } + [self.peerManager disconnectDownloadPeerForError:nil withCompletion:^(BOOL success) { + NSManagedObjectContext *chainContext = [NSManagedObjectContext chainContext]; + [[DashSync sharedSyncController] wipeMasternodeDataForChain:self.chain inContext:chainContext]; + [self removeNonMainnetTrustedPeer]; + [self notify:DSChainManagerSyncWillStartNotification userInfo:@{DSChainManagerNotificationChainKey: self.chain}]; + DSLog(@"%@ Disconnected (MasternodeListRescan) -> peerManager::connect", self.logPrefix); + [self.peerManager connect]; + }]; } - // MARK: - DSChainDelegate - (void)chain:(DSChain *)chain didSetBlockHeight:(int32_t)height andTimestamp:(NSTimeInterval)timestamp forTransactionHashes:(NSArray *)txHashes updatedTransactions:(NSArray *)updatedTransactions { [self.transactionManager chain:chain didSetBlockHeight:height andTimestamp:timestamp forTransactionHashes:txHashes updatedTransactions:updatedTransactions]; } +// always from chain.networkingQueue - (void)chain:(DSChain *)chain didFinishInChainSyncPhaseFetchingIdentityDAPInformation:(DSIdentity *)identity { dispatch_async(chain.networkingQueue, ^{ + [self.syncState removeSyncKind:DSSyncStateExtKind_Platform]; [self.peerManager resumeBlockchainSynchronizationOnPeers]; }); } @@ -250,19 +231,28 @@ - (void)chainShouldStartSyncingBlockchain:(DSChain *)chain onPeer:(DSPeer *)peer DSPeerManagerNotificationPeerKey: peer ? peer : [NSNull null]}]; dispatch_async(self.chain.networkingQueue, ^{ if ((self.syncPhase != DSChainSyncPhase_ChainSync && self.syncPhase != DSChainSyncPhase_Synced) && self.chain.needsInitialTerminalHeadersSync) { + DSLog(@"%@ syncBlockchainStarted [phase:%d] -> get headers (terminal block locators)", self.logPrefix, self.syncPhase); //masternode list should be synced first and the masternode list is old + [self.syncState addSyncKind:DSSyncStateExtKind_Headers]; self.syncState.syncPhase = DSChainSyncPhase_InitialTerminalBlocks; [peer sendGetheadersMessageWithLocators:[self.chain terminalBlocksLocatorArray] andHashStop:UINT256_ZERO]; } else if (([[DSOptionsManager sharedInstance] syncType] & DSSyncType_MasternodeList) && [self.masternodeManager isMasternodeListOutdated]) { + DSLog(@"%@ syncBlockchainStarted [phase:%d] -> get masternodes", self.logPrefix, self.syncPhase); + [self.syncState addSyncKind:DSSyncStateExtKind_Masternodes]; self.syncState.syncPhase = DSChainSyncPhase_InitialTerminalBlocks; [self.masternodeManager startSync]; } else { - self.syncState.syncPhase = DSChainSyncPhase_ChainSync; BOOL startingDevnetSync = [self.chain isDevnetAny] && self.chain.lastSyncBlockHeight < 5; NSTimeInterval cutoffTime = self.chain.earliestWalletCreationTime - HEADER_WINDOW_BUFFER_TIME; if (startingDevnetSync || (self.chain.lastSyncBlockTimestamp >= cutoffTime && [self shouldRequestMerkleBlocksForZoneAfterHeight:[self.chain lastSyncBlockHeight]])) { + DSLog(@"%@ syncBlockchainStarted [phase:%d] -> get blocks", self.logPrefix, self.syncPhase); + self.syncState.syncPhase = DSChainSyncPhase_ChainSync; + [self.syncState addSyncKind:DSSyncStateExtKind_Transactions]; [peer sendGetblocksMessageWithLocators:[self.chain chainSyncBlockLocatorArray] andHashStop:UINT256_ZERO]; } else { + DSLog(@"%@ syncBlockchainStarted [phase:%d] -> get headers (sync block locators)", self.logPrefix, self.syncPhase); + self.syncState.syncPhase = DSChainSyncPhase_ChainSync; + [self.syncState addSyncKind:DSSyncStateExtKind_Headers]; [peer sendGetheadersMessageWithLocators:[self.chain chainSyncBlockLocatorArray] andHashStop:UINT256_ZERO]; } } @@ -270,9 +260,11 @@ - (void)chainShouldStartSyncingBlockchain:(DSChain *)chain onPeer:(DSPeer *)peer }); } +// always from chain.networkingQueue - (void)chainFinishedSyncingInitialHeaders:(DSChain *)chain fromPeer:(DSPeer *)peer onMainChain:(BOOL)onMainChain { if (onMainChain && peer && (peer == self.peerManager.downloadPeer)) [self relayedNewItem]; DSLog(@"%@ Sync Status: initial headers: OK -> sync masternode lists & quorums", self.logPrefix); + [self.syncState removeSyncKind:DSSyncStateExtKind_Headers]; [self.peerManager chainSyncStopped]; if (([[DSOptionsManager sharedInstance] syncType] & DSSyncType_MasternodeList)) { // make sure we care about masternode lists @@ -280,10 +272,11 @@ - (void)chainFinishedSyncingInitialHeaders:(DSChain *)chain fromPeer:(DSPeer *)p } } +// always from chain.networkingQueue - (void)chainFinishedSyncingTransactionsAndBlocks:(DSChain *)chain fromPeer:(DSPeer *)peer onMainChain:(BOOL)onMainChain { if (onMainChain && peer && (peer == self.peerManager.downloadPeer)) [self relayedNewItem]; DSLog(@"%@ Sync Status: transactions and blocks: OK -> sync mempool, sporks & governance", self.logPrefix); - + [self.syncState removeSyncKind:DSSyncStateExtKind_Transactions]; self.syncState.chainSyncStartHeight = 0; self.syncState.syncPhase = DSChainSyncPhase_Synced; [self.transactionManager fetchMempoolFromNetwork]; @@ -304,28 +297,32 @@ - (void)setSyncPhase:(DSChainSyncPhase)syncPhase { self.syncState.syncPhase = syncPhase; } +// always from chain.networkingQueue - (void)syncBlockchain { - DSLog(@"%@ syncBlockchain connected peers: %lu phase: %d", self.logPrefix, self.peerManager.connectedPeerCount, self.syncPhase); if (self.peerManager.connectedPeerCount == 0) { + DSLog(@"%@ syncBlockchain [phase:%d] (no connected peers -> connect)", self.logPrefix, self.syncPhase); if (self.syncPhase == DSChainSyncPhase_InitialTerminalBlocks) { self.syncState.syncPhase = DSChainSyncPhase_ChainSync; [self notifySyncStateChanged]; } - DSLog(@"%@ syncBlockchain -> peerManager::connect", self.logPrefix); [self.peerManager connect]; } else if (!self.peerManager.masternodeList && self.masternodeManager.currentMasternodeList) { + DSLog(@"%@ syncBlockchain [phase:%d] (use masternode list peers)", self.logPrefix, self.syncPhase); [self.peerManager useMasternodeList:self.masternodeManager.currentMasternodeList withConnectivityNonce:self.sessionConnectivityNonce]; } else if (self.syncPhase == DSChainSyncPhase_InitialTerminalBlocks) { + DSLog(@"%@ syncBlockchain [phase:%d] (should start)", self.logPrefix, self.syncPhase); self.syncState.syncPhase = DSChainSyncPhase_ChainSync; [self notifySyncStateChanged]; [self chainShouldStartSyncingBlockchain:self.chain onPeer:self.peerManager.downloadPeer]; } } +// always from chain.networkingQueue - (void)chainFinishedSyncingMasternodeListsAndQuorums:(DSChain *)chain { - if (chain.isEvolutionEnabled) { + if (chain.isEvolutionEnabled && ![self.syncState.platformSyncInfo hasRecentIdentitiesSync]) { DSLog(@"%@ Sync Status: masternode list and quorums: OK -> sync identities", self.logPrefix); [self.identitiesManager syncIdentitiesWithCompletion:^(NSArray *_Nullable identities) { + // always from chain.networkingQueue DSLog(@"%@ Sync Status: identities: OK -> sync chain", self.logPrefix); [self syncBlockchain]; }]; @@ -359,6 +356,7 @@ - (void)chain:(DSChain *)chain receivedOrphanBlock:(DSBlock *)block fromPeer:(DS - (void)chain:(DSChain *)chain wasExtendedWithBlock:(DSBlock *)merkleBlock fromPeer:(DSPeer *)peer { if (([[DSOptionsManager sharedInstance] syncType] & DSSyncType_MasternodeList)) { // make sure we care about masternode lists + DSLog(@"%@ [%@:%d] chain extended with %@ -> re-request masternode lists", self.logPrefix, peer.host, peer.port, uint256_hex(merkleBlock.blockHash)); [self.masternodeManager getCurrentMasternodeListWithSafetyDelay:3]; } } @@ -436,7 +434,7 @@ - (NSString *)terminalSyncStartHeightKey { return [NSString stringWithFormat:@"%@_%@", TERMINAL_SYNC_STARTHEIGHT_KEY, [self.chain uniqueID]]; } - +// always from chain.networkingQueue - (void)resetChainSyncStartHeight { NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults]; BOOL changed = NO; @@ -453,6 +451,7 @@ - (void)resetChainSyncStartHeight { [self notifySyncStateChanged]; } +// always from chain.networkingQueue - (void)restartChainSyncStartHeight { self.syncState.chainSyncStartHeight = 0; [[NSUserDefaults standardUserDefaults] setInteger:0 forKey:self.chainSyncStartHeightKey]; @@ -461,17 +460,18 @@ - (void)restartChainSyncStartHeight { } +// always from chain.networkingQueue - (void)resetTerminalSyncStartHeight { NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults]; if (self.syncState.terminalSyncStartHeight == 0) self.syncState.terminalSyncStartHeight = (uint32_t)[userDefaults integerForKey:self.terminalSyncStartHeightKey]; - if (self.syncState.terminalSyncStartHeight == 0) { self.syncState.terminalSyncStartHeight = self.chain.lastTerminalBlockHeight; [[NSUserDefaults standardUserDefaults] setInteger:self.syncState.terminalSyncStartHeight forKey:self.terminalSyncStartHeightKey]; } } +// always from chain.networkingQueue - (void)restartTerminalSyncStartHeight { self.syncState.terminalSyncStartHeight = 0; [[NSUserDefaults standardUserDefaults] setInteger:0 forKey:self.terminalSyncStartHeightKey]; @@ -498,9 +498,9 @@ - (void)setupNotificationTimer:(void (^ __nullable)(void))completion { } } -- (void)notifyMasternodeSyncStateChange:(uint32_t)lastBlockHeihgt storedCount:(uintptr_t)storedCount { +- (void)notifyMasternodeSyncStateChange:(uint32_t)lastBlockHeihgt storedCount:(uint32_t)storedCount { @synchronized (self.syncState) { - self.syncState.masternodeListSyncInfo.lastBlockHeight = lastBlockHeihgt; + self.syncState.masternodeListSyncInfo.lastListHeight = lastBlockHeihgt; self.syncState.masternodeListSyncInfo.storedCount = storedCount; [self notifySyncStateChanged]; } diff --git a/DashSync/shared/Models/Managers/Chain Managers/DSChainsManager.m b/DashSync/shared/Models/Managers/Chain Managers/DSChainsManager.m index bb691628..d400f222 100644 --- a/DashSync/shared/Models/Managers/Chain Managers/DSChainsManager.m +++ b/DashSync/shared/Models/Managers/Chain Managers/DSChainsManager.m @@ -73,7 +73,7 @@ - (instancetype)init { self.knownChains = [NSMutableArray array]; self.knownDevnetChains = [NSMutableArray array]; self.reachability = [DSReachabilityManager sharedManager]; - register_rust_logger(); + //register_rust_logger(); } return self; } diff --git a/DashSync/shared/Models/Managers/Chain Managers/DSGovernanceSyncManager.m b/DashSync/shared/Models/Managers/Chain Managers/DSGovernanceSyncManager.m index eec67cfa..63d1dd1a 100644 --- a/DashSync/shared/Models/Managers/Chain Managers/DSGovernanceSyncManager.m +++ b/DashSync/shared/Models/Managers/Chain Managers/DSGovernanceSyncManager.m @@ -131,7 +131,9 @@ - (void)continueGovernanceSync { - (void)startGovernanceSync { //Do we want to sync? if (!([[DSOptionsManager sharedInstance] syncType] & DSSyncType_Governance)) return; // make sure we care about Governance objects - + dispatch_async(dispatch_get_main_queue(), ^{ + [self.chain.chainManager.syncState addSyncKind:DSSyncStateExtKind_Governance]; + }); //Do we need to sync? if ([[NSUserDefaults standardUserDefaults] objectForKey:[NSString stringWithFormat:@"%@_%@", self.chain.uniqueID, LAST_SYNCED_GOVERANCE_OBJECTS]]) { //no need to do a governance sync if we already completed one recently NSTimeInterval lastSyncedGovernance = [[NSUserDefaults standardUserDefaults] integerForKey:[NSString stringWithFormat:@"%@_%@", self.chain.uniqueID, LAST_SYNCED_GOVERANCE_OBJECTS]]; @@ -139,6 +141,7 @@ - (void)startGovernanceSync { NSTimeInterval now = [[NSDate date] timeIntervalSince1970]; if (lastSyncedGovernance + interval > now) { [self continueGovernanceSync]; + [self.chain.chainManager.syncState removeSyncKind:DSSyncStateExtKind_Governance]; return; }; } @@ -196,12 +199,16 @@ - (void)finishedGovernanceObjectSyncWithPeer:(DSPeer *)peer { [[NSUserDefaults standardUserDefaults] setInteger:[[NSDate date] timeIntervalSince1970] forKey:[NSString stringWithFormat:@"%@_%@", self.chain.uniqueID, LAST_SYNCED_GOVERANCE_OBJECTS]]; //Do we want to request votes now? - if (!([[DSOptionsManager sharedInstance] syncType] & DSSyncType_GovernanceVotes)) return; + if (!([[DSOptionsManager sharedInstance] syncType] & DSSyncType_GovernanceVotes)) { + [self.chain.chainManager.syncState removeSyncKind:DSSyncStateExtKind_Governance]; + return; + } self.needVoteSyncGovernanceObjects = [self.governanceObjects mutableCopy]; [self startNextGoveranceVoteSyncWithPeer:peer]; } - (void)finishedGovernanceVoteSyncWithPeer:(DSPeer *)peer { + [self.chain.chainManager.syncState removeSyncKind:DSSyncStateExtKind_Governance]; if (peer.governanceRequestState != DSGovernanceRequestState_GovernanceObjectVotes) return; if (!([[DSOptionsManager sharedInstance] syncType] & DSSyncType_GovernanceVotes)) return; peer.governanceRequestState = DSGovernanceRequestState_None; diff --git a/DashSync/shared/Models/Managers/Chain Managers/DSIdentitiesManager.h b/DashSync/shared/Models/Managers/Chain Managers/DSIdentitiesManager.h index 52e82a6c..54138d09 100644 --- a/DashSync/shared/Models/Managers/Chain Managers/DSIdentitiesManager.h +++ b/DashSync/shared/Models/Managers/Chain Managers/DSIdentitiesManager.h @@ -37,8 +37,6 @@ typedef void (^DashpayUserInfoCompletionBlock)(BOOL success, DSTransientDashpayU /*! @brief Returns the timestamp of the last time identities were synced. */ @property (nonatomic, readonly) NSTimeInterval lastSyncedIndentitiesTimestamp; -/*! @brief Returns if we synced identities in the last 30 seconds. */ -@property (nonatomic, readonly) BOOL hasRecentIdentitiesSync; - (instancetype)initWithChain:(DSChain *)chain; diff --git a/DashSync/shared/Models/Managers/Chain Managers/DSIdentitiesManager.m b/DashSync/shared/Models/Managers/Chain Managers/DSIdentitiesManager.m index b5dd2176..7424fcac 100644 --- a/DashSync/shared/Models/Managers/Chain Managers/DSIdentitiesManager.m +++ b/DashSync/shared/Models/Managers/Chain Managers/DSIdentitiesManager.m @@ -27,7 +27,7 @@ #import "DSChain+Params.h" #import "DSChain+Protected.h" #import "DSChain+Wallet.h" -#import "DSChainManager.h" +#import "DSChainManager+Protected.h" #import "DSDashPlatform.h" #import "DSDerivationPathFactory.h" #import "DSMerkleBlock.h" @@ -52,14 +52,13 @@ @interface DSIdentitiesManager () @property (nonatomic, strong) dispatch_queue_t identityQueue; @property (nonatomic, strong) NSMutableDictionary *foreignIdentities; @property (nonatomic, assign) NSTimeInterval lastSyncedIndentitiesTimestamp; -@property (nonatomic, assign) BOOL hasRecentIdentitiesSync; @end @implementation DSIdentitiesManager - (NSString *)logPrefix { - return [NSString stringWithFormat:@"[%@] [Identity Manager] ", self.chain.name]; + return [NSString stringWithFormat:@"[%@] [Identity Manager]", self.chain.name]; } - (instancetype)initWithChain:(DSChain *)chain { @@ -68,7 +67,10 @@ - (instancetype)initWithChain:(DSChain *)chain { if (!(self = [super init])) return nil; self.chain = chain; - _identityQueue = dispatch_queue_create([@"org.dashcore.dashsync.identity" UTF8String], DISPATCH_QUEUE_SERIAL); + + dispatch_queue_attr_t attr = dispatch_queue_attr_make_with_qos_class(DISPATCH_QUEUE_SERIAL, QOS_CLASS_USER_INITIATED, 0); + _identityQueue = dispatch_queue_create("org.dashcore.dashsync.identity", attr); + [self setup]; // self.foreignIdentities = [NSMutableDictionary dictionary]; // [self loadExternalIdentities]; @@ -76,12 +78,6 @@ - (instancetype)initWithChain:(DSChain *)chain { return self; } -// MARK: - Loading - - -- (BOOL)hasRecentIdentitiesSync { - return ([[NSDate date] timeIntervalSince1970] - self.lastSyncedIndentitiesTimestamp < 30); -} // MARK: - Wiping @@ -128,11 +124,11 @@ - (NSArray *)unsyncedIdentities { NSMutableArray *unsyncedIdentities = [NSMutableArray array]; for (DSIdentity *identity in [self.chain localIdentities]) { if (!identity.registrationAssetLockTransaction || (identity.registrationAssetLockTransaction.blockHeight == BLOCK_UNKNOWN_HEIGHT)) { - DSLog(@"%@: unsynced identity (asset lock tx unknown or has unknown height) %@ %@", self.logPrefix, uint256_hex(identity.registrationAssetLockTransactionHash), identity.registrationAssetLockTransaction); + DSLog(@"%@ Unsynced identity (asset lock tx unknown or has unknown height) %@ %@", self.logPrefix, uint256_hex(identity.registrationAssetLockTransactionHash), identity.registrationAssetLockTransaction); [unsyncedIdentities addObject:identity]; } else if (self.chain.lastSyncBlockHeight > identity.dashpaySyncronizationBlockHeight) { - DSLog(@"%@: unsynced identity (lastSyncBlockHeight (%u) > dashpaySyncronizationBlockHeight %u)", self.logPrefix, self.chain.lastSyncBlockHeight, identity.dashpaySyncronizationBlockHeight); + DSLog(@"%@ Unsynced identity (lastSyncBlockHeight (%u) > dashpaySyncronizationBlockHeight %u)", self.logPrefix, self.chain.lastSyncBlockHeight, identity.dashpaySyncronizationBlockHeight); //If they are equal then the blockchain identity is synced //This is because the dashpaySyncronizationBlock represents the last block for the bloom filter used in L1 should be considered valid //That's because it is set at the time with the hash of the last @@ -142,31 +138,32 @@ - (NSArray *)unsyncedIdentities { return unsyncedIdentities; } -//- (void)syncPlatformWithCompletion:(IdentitiesSuccessCompletionBlock)completion { -// [self syncIdentitiesWithCompletion:^(NSArray *_Nullable identities) { -// [self retrieveAllIdentitiesChainStates:completion]; -// }]; -// -//} //TODO: if we get an error or identity not found, better stop the process and start syncing chain - (void)syncIdentitiesWithCompletion:(IdentitiesSuccessCompletionBlock)completion { - DSLog(@"%@: Sync Identities", self.logPrefix); if (!self.chain.isEvolutionEnabled) { if (completion) dispatch_async(self.chain.networkingQueue, ^{ completion(@[]); }); return; } + DSLog(@"%@ Sync Identities", self.logPrefix); dispatch_async(self.identityQueue, ^{ NSArray *wallets = self.chain.wallets; __block dispatch_group_t keyHashesDispatchGroup = dispatch_group_create(); __block NSMutableArray *errors = [NSMutableArray array]; __block NSMutableArray *allIdentities = [NSMutableArray array]; - + const int keysToCheck = 5; + dispatch_async(self.chain.networkingQueue, ^{ + [self.chain.chainManager.syncState addSyncKind:DSSyncStateExtKind_Platform]; + [self.chain.chainManager.syncState.platformSyncInfo addSyncKind:DSPlatformSyncStateKind_KeyHashes]; + self.chain.chainManager.syncState.platformSyncInfo.queueCount = 0; + self.chain.chainManager.syncState.platformSyncInfo.queueMaxAmount = keysToCheck * (uint32_t) wallets.count; + [self.chain.chainManager notifySyncStateChanged]; + }); + for (DSWallet *wallet in wallets) { uint32_t unusedIndex = [wallet unusedIdentityIndex]; DSAuthenticationKeysDerivationPath *derivationPath = [[DSDerivationPathFactory sharedInstance] identityECDSAKeysDerivationPathForWallet:wallet]; - const int keysToCheck = 5; NSMutableDictionary *keyIndexes = [NSMutableDictionary dictionaryWithCapacity:keysToCheck]; u160 **key_hashes = malloc(keysToCheck * sizeof(u160 *)); for (int i = 0; i < keysToCheck; i++) { @@ -179,64 +176,89 @@ - (void)syncIdentitiesWithCompletion:(IdentitiesSuccessCompletionBlock)completio dispatch_group_enter(keyHashesDispatchGroup); DRetry *stragegy = DRetryLinear(5); dash_spv_platform_identity_manager_IdentityValidator *options = DAcceptIdentityNotFound(); - Result_ok_std_collections_Map_keys_u8_arr_20_values_dpp_identity_identity_Identity_err_dash_spv_platform_error_Error *result = dash_spv_platform_identity_manager_IdentitiesManager_monitor_for_key_hashes(self.chain.sharedRuntime, self.chain.sharedIdentitiesObj, Vec_u8_20_ctor(keysToCheck, key_hashes), stragegy, options); - - if (result->error) { - NSError *error = [NSError ffi_from_platform_error:result->error]; - DSLog(@"%@: Sync Identities: ERROR %@", self.logPrefix, error); - Result_ok_std_collections_Map_keys_u8_arr_20_values_dpp_identity_identity_Identity_err_dash_spv_platform_error_Error_destroy(result); - [errors addObject:error]; - dispatch_group_leave(keyHashesDispatchGroup); - return; - } - std_collections_Map_keys_u8_arr_20_values_dpp_identity_identity_Identity *ok = result->ok; - NSMutableArray *identities = [NSMutableArray array]; - for (int j = 0; j < ok->count; j++) { - DIdentity *identity = ok->values[j]; - switch (identity->tag) { - case dpp_identity_identity_Identity_V0: { - dpp_identity_v0_IdentityV0 *identity_v0 = identity->v0; - DMaybeOpaqueKey *maybe_opaque_key = DOpaqueKeyFromIdentityPubKey(identity_v0->public_keys->values[0]); - NSData *publicKeyData = [DSKeyManager publicKeyData:maybe_opaque_key->ok]; - NSNumber *index = [keyIndexes objectForKey:publicKeyData]; - DSIdentity *identityModel = [[DSIdentity alloc] initAtIndex:index.intValue uniqueId:u256_cast(identity_v0->id->_0->_0) inWallet:wallet]; - [identityModel applyIdentity:identity save:NO inContext:nil]; - [identities addObject:identityModel]; - break; - } - - default: - break; + dispatch_async(dispatch_get_global_queue(QOS_CLASS_UTILITY, 0), ^{ + Result_ok_std_collections_Map_keys_u8_arr_20_values_dpp_identity_identity_Identity_err_dash_spv_platform_error_Error *result = dash_spv_platform_identity_manager_IdentitiesManager_monitor_for_key_hashes(self.chain.sharedRuntime, self.chain.sharedIdentitiesObj, Vec_u8_20_ctor(keysToCheck, key_hashes), stragegy, options); + + if (result->error) { + NSError *error = [NSError ffi_from_platform_error:result->error]; + DSLog(@"%@: Sync Identities: ERROR %@", self.logPrefix, error); + Result_ok_std_collections_Map_keys_u8_arr_20_values_dpp_identity_identity_Identity_err_dash_spv_platform_error_Error_destroy(result); + [errors addObject:error]; + dispatch_group_leave(keyHashesDispatchGroup); + return; } - } - Result_ok_std_collections_Map_keys_u8_arr_20_values_dpp_identity_identity_Identity_err_dash_spv_platform_error_Error_destroy(result); - BOOL success = [wallet registerIdentities:identities verify:YES]; - DSLog(@"%@: Sync Identities: %@", self.logPrefix, DSLocalizedFormat(success ? @"OK (%lu)" : @"Retrieved (%lu) but can't register in wallet", nil, identities.count)); - if (success) { - [allIdentities addObjectsFromArray:identities]; - NSManagedObjectContext *platformContext = [NSManagedObjectContext platformContext]; - [platformContext performBlockAndWait:^{ - for (DSIdentity *identity in identities) { - [identity saveInitialInContext:platformContext]; + std_collections_Map_keys_u8_arr_20_values_dpp_identity_identity_Identity *ok = result->ok; + NSMutableArray *identities = [NSMutableArray array]; + + for (int j = 0; j < ok->count; j++) { + DIdentity *identity = ok->values[j]; + switch (identity->tag) { + case dpp_identity_identity_Identity_V0: { + dpp_identity_v0_IdentityV0 *identity_v0 = identity->v0; + DMaybeOpaqueKey *maybe_opaque_key = DOpaqueKeyFromIdentityPubKey(identity_v0->public_keys->values[0]); + NSData *publicKeyData = [DSKeyManager publicKeyData:maybe_opaque_key->ok]; + NSNumber *index = [keyIndexes objectForKey:publicKeyData]; + DSIdentity *identityModel = [[DSIdentity alloc] initAtIndex:index.intValue uniqueId:u256_cast(identity_v0->id->_0->_0) inWallet:wallet]; + [identityModel applyIdentity:identity save:NO inContext:nil]; + [identities addObject:identityModel]; + break; + } + + default: + break; } - }]; - } else { - [errors addObject:ERROR_UNKNOWN_KEYS]; - } - dispatch_group_leave(keyHashesDispatchGroup); + } + + Result_ok_std_collections_Map_keys_u8_arr_20_values_dpp_identity_identity_Identity_err_dash_spv_platform_error_Error_destroy(result); + BOOL success = [wallet registerIdentities:identities verify:YES]; + dispatch_async(self.chain.networkingQueue, ^{ + self.chain.chainManager.syncState.platformSyncInfo.queueCount = keysToCheck; + }); + + DSLog(@"%@: Sync Identities: %@", self.logPrefix, DSLocalizedFormat(success ? @"OK (%lu)" : @"Retrieved (%lu) but can't register in wallet", nil, identities.count)); + if (success) { + [allIdentities addObjectsFromArray:identities]; + NSManagedObjectContext *platformContext = [NSManagedObjectContext platformContext]; + [platformContext performBlockAndWait:^{ + for (DSIdentity *identity in identities) { + [identity saveInitialInContext:platformContext]; + } + }]; + } else { + [errors addObject:ERROR_UNKNOWN_KEYS]; + } + dispatch_group_leave(keyHashesDispatchGroup); + }); + } dispatch_group_notify(keyHashesDispatchGroup, self.chain.networkingQueue, ^{ + [self.chain.chainManager.syncState.platformSyncInfo removeSyncKind:DSPlatformSyncStateKind_KeyHashes]; NSArray *identities = [self unsyncedIdentities]; - DSLog(@"%@ Sync Identities: unsynced: %@", self.logPrefix, identities); + NSMutableString *deb_id = [NSMutableString stringWithFormat:@"%@ Sync Identities: unsynced: ", self.logPrefix]; + for (DSIdentity *identitity in identities) { + [deb_id appendFormat:@"%@,", uint256_hex(identitity.uniqueID)]; + } + DSLog(@"%@", deb_id); + NSUInteger identitiesCount = [identities count]; + if (identitiesCount) { + self.chain.chainManager.syncState.platformSyncInfo.queueCount = 0; + self.chain.chainManager.syncState.platformSyncInfo.queueMaxAmount = (uint32_t) identitiesCount; + [self.chain.chainManager.syncState.platformSyncInfo addSyncKind:DSPlatformSyncStateKind_Unsynced]; + } + [self.chain.chainManager notifySyncStateChanged]; + dispatch_group_t dispatchGroup = dispatch_group_create(); __block NSMutableArray *errors = [NSMutableArray array]; for (DSIdentity *identity in identities) { dispatch_group_enter(dispatchGroup); - [self fetchNeededNetworkStateInformationForIdentity:identity - withCompletion:^(BOOL success, DSIdentity *_Nullable identity, NSError *_Nullable error) { + [self fetchNeededNetworkStateInformationForIdentity:identity withCompletion:^(BOOL success, DSIdentity *_Nullable identity, NSError *_Nullable error) { + dispatch_async(self.chain.networkingQueue, ^{ + self.chain.chainManager.syncState.platformSyncInfo.queueCount++; + [self.chain.chainManager notifySyncStateChanged]; + }); if (success && identity != nil) { dispatch_group_leave(dispatchGroup); } else { @@ -247,6 +269,12 @@ - (void)syncIdentitiesWithCompletion:(IdentitiesSuccessCompletionBlock)completio } dispatch_group_notify(dispatchGroup, self.chain.networkingQueue, ^{ self.lastSyncedIndentitiesTimestamp = [[NSDate date] timeIntervalSince1970]; + self.chain.chainManager.syncState.platformSyncInfo.queueCount = 0; + self.chain.chainManager.syncState.platformSyncInfo.queueMaxAmount = 0; + self.chain.chainManager.syncState.platformSyncInfo.lastSyncedIndentitiesTimestamp = self.lastSyncedIndentitiesTimestamp; + [self.chain.chainManager.syncState.platformSyncInfo resetSyncKind]; + [self.chain.chainManager.syncState removeSyncKind:DSSyncStateExtKind_Platform]; + [self.chain.chainManager notifySyncStateChanged]; if (!errors.count && completion) completion(identities); }); @@ -507,6 +535,7 @@ - (void)searchIdentitiesByDPNSRegisteredIdentityUniqueID:(NSData *)userID if (completion) dispatch_async(dispatch_get_main_queue(), ^{ completion(YES, [rIdentities copy], @[]); }); } +// always from chain.networkingQueue - (void)checkAssetLockTransactionForPossibleNewIdentity:(DSAssetLockTransaction *)transaction { uint32_t index; DSWallet *wallet = [self.chain walletHavingIdentityAssetLockRegistrationHash:transaction.creditBurnPublicKeyHash foundAtIndex:&index]; @@ -544,6 +573,7 @@ - (void)fetchNeededNetworkStateInformationForIdentity:(DSIdentity *)identity // MARK: - DSChainIdentitiesDelegate +// always from chain.networkingQueue - (void)chain:(DSChain *)chain didFinishInChainSyncPhaseFetchingIdentityDAPInformation:(DSIdentity *)identity { [self.chain.chainManager chain:chain didFinishInChainSyncPhaseFetchingIdentityDAPInformation:identity]; } diff --git a/DashSync/shared/Models/Managers/Chain Managers/DSKeyManager.m b/DashSync/shared/Models/Managers/Chain Managers/DSKeyManager.m index 0f8c75ce..92c0fee7 100644 --- a/DashSync/shared/Models/Managers/Chain Managers/DSKeyManager.m +++ b/DashSync/shared/Models/Managers/Chain Managers/DSKeyManager.m @@ -36,7 +36,6 @@ @implementation DSKeyManager - (instancetype)initWithChain:(DSChain *)chain { NSParameterAssert(chain); if (!(self = [super init])) return nil; - DSLog(@"[%@] DSKeyManager.initWithChain: %@: ", chain.name, chain); return self; } diff --git a/DashSync/shared/Models/Managers/Chain Managers/DSMasternodeManager+Protected.h b/DashSync/shared/Models/Managers/Chain Managers/DSMasternodeManager+Protected.h index 2f6240a2..fc9446d5 100644 --- a/DashSync/shared/Models/Managers/Chain Managers/DSMasternodeManager+Protected.h +++ b/DashSync/shared/Models/Managers/Chain Managers/DSMasternodeManager+Protected.h @@ -30,11 +30,12 @@ NS_ASSUME_NONNULL_BEGIN @interface DSMasternodeManager (Protected) +@property (nonatomic, readonly) NSManagedObjectContext *managedObjectContext; + - (instancetype)initWithChain:(DSChain *_Nonnull)chain; - (void)setUp; - (BOOL)restoreState; -//- (void)loadFileDistributedMasternodeLists; - (void)wipeMasternodeInfo; - (void)getRecentMasternodeList; - (void)getCurrentMasternodeListWithSafetyDelay:(uint32_t)safetyDelay; @@ -47,14 +48,10 @@ NS_ASSUME_NONNULL_BEGIN ownerKeyIndex:(uint32_t)ownerKeyIndex onChain:(DSChain *)chain; -//+ (nullable NSError *)saveMasternodeList:(DMasternodeList *)masternodeList -// toChain:(DSChain *)chain -// havingModifiedMasternodes:(DMasternodeEntryMap *)modifiedMasternodes -// createUnknownBlocks:(BOOL)createUnknownBlocks -// inContext:(NSManagedObjectContext *)context; - (BOOL)isMasternodeListOutdated; - (BOOL)processRequestFromFileForBlockHash:(UInt256)blockHash; -- (void)issueWithMasternodeListFromPeer:(DSPeer *)peer; + +- (void)printEngineStatus; @end diff --git a/DashSync/shared/Models/Managers/Chain Managers/DSMasternodeManager.h b/DashSync/shared/Models/Managers/Chain Managers/DSMasternodeManager.h index 1a08e6e4..07a6311d 100644 --- a/DashSync/shared/Models/Managers/Chain Managers/DSMasternodeManager.h +++ b/DashSync/shared/Models/Managers/Chain Managers/DSMasternodeManager.h @@ -25,7 +25,6 @@ #import "DSChain.h" #import "DSKeyManager.h" -//#import "DSMasternodeListStore.h" #import "DSPeer.h" #import @@ -47,14 +46,12 @@ FOUNDATION_EXPORT NSString *const DSQuorumListDidChangeNotification; @property (nonatomic, readonly) NSUInteger simplifiedMasternodeEntryCount; @property (nonatomic, readonly) NSUInteger activeQuorumsCount; @property (nonatomic, readonly) NSUInteger knownMasternodeListsCount; -//@property (nonatomic, readonly) uint32_t earliestMasternodeListBlockHeight; @property (nonatomic, readonly) uint32_t lastMasternodeListBlockHeight; @property (nonatomic, readonly) DMasternodeList *currentMasternodeList; @property (nonatomic, readonly) NSUInteger masternodeListRetrievalQueueCount; @property (nonatomic, readonly) NSUInteger masternodeListRetrievalQueueMaxAmount; @property (nonatomic, readonly) BOOL currentMasternodeListIsInLast24Hours; -//@property (nonatomic, readonly) DSMasternodeListStore *store; @property (nonatomic, readonly) DSMasternodeListDiffService *masternodeListDiffService; @property (nonatomic, readonly) DSQuorumRotationService *quorumRotationService; @property (nonatomic, assign, readonly) uint32_t rotatedQuorumsActivationHeight; @@ -69,27 +66,15 @@ FOUNDATION_EXPORT NSString *const DSQuorumListDidChangeNotification; - (DMasternodeEntry *)masternodeAtLocation:(UInt128)IPAddress port:(uint32_t)port; - (BOOL)hasMasternodeAtLocation:(UInt128)IPAddress port:(uint32_t)port; -//- (DLLMQEntry *_Nullable)quorumEntryForInstantSendRequestID:(UInt256)requestID -// withBlockHeightOffset:(uint32_t)blockHeightOffset; -//- (DLLMQEntry *_Nullable)quorumEntryForChainLockRequestID:(UInt256)requestID -// withBlockHeightOffset:(uint32_t)blockHeightOffset; -//- (DLLMQEntry *_Nullable)quorumEntryForChainLockRequestID:(UInt256)requestID -// forBlockHeight:(uint32_t)blockHeight; -//- (DLLMQEntry *_Nullable)quorumEntryForPlatformHavingQuorumHash:(UInt256)quorumHash -// forBlockHeight:(uint32_t)blockHeight; - - (DMasternodeList *_Nullable)masternodeListForBlockHash:(UInt256)blockHash - withBlockHeightLookup:(uint32_t (^_Nullable)(UInt256 blockHash))blockHeightLookup; + withBlockHeightLookup:(uint32_t (^_Nullable)(UInt256 blockHash))blockHeightLookup; - (DMasternodeList *_Nullable)masternodeListForBlockHash:(UInt256)blockHash; - (void)startSync; - (void)stopSync; -//- (BOOL)requestMasternodeListForBlockHeight:(uint32_t)blockHeight -// error:(NSError *_Nullable *_Nullable)error; /// Returns current masternode list - (void)reloadMasternodeLists; -//- (DMasternodeList *_Nullable)reloadMasternodeListsWithBlockHeightLookup:(BlockHeightFinder)blockHeightLookup; - (void)checkPingTimesForCurrentMasternodeListInContext:(NSManagedObjectContext *)context withCompletion:(void (^)(NSMutableDictionary *pingTimes, NSMutableDictionary *errors))completion; @@ -97,12 +82,15 @@ FOUNDATION_EXPORT NSString *const DSQuorumListDidChangeNotification; - (void)masternodeListServiceEmptiedRetrievalQueue:(DSMasternodeListService *)service; -- (BOOL)hasBlockForBlockHash:(NSData *)blockHashData; - (NSSet *)blockHashesUsedByMasternodeLists; - (uintptr_t)currentQuorumsOfType:(DLLMQType)type; - (uintptr_t)currentValidQuorumsOfType:(DLLMQType)type; + +- (NSError *_Nullable)requestMasternodeListForBlockHeight:(uint32_t)blockHeight; +- (void)requestMasternodeListForBlockHash:(NSData *)blockHash; +- (void)requestMasternodeListForBaseBlockHash:(NSData *)baseBlockHash blockHash:(NSData *)blockHash; @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 0105b8fb..e1204246 100644 --- a/DashSync/shared/Models/Managers/Chain Managers/DSMasternodeManager.m +++ b/DashSync/shared/Models/Managers/Chain Managers/DSMasternodeManager.m @@ -46,8 +46,10 @@ #define ENGINE_STORAGE_LOCATION(chain) [NSString stringWithFormat:@"MNL_ENGINE_%@.dat", chain.name] -#define SAVE_MASTERNODE_DIFF_TO_FILE (1 && DEBUG) -#define SAVE_ERROR_STATE (1 && DEBUG) +#define SAVE_MASTERNODE_DIFF_TO_FILE (0 && DEBUG) +#define SAVE_MASTERNODE_DIFF_ERROR_TO_FILE (1 && DEBUG) +#define SAVE_ERROR_STATE (0 && DEBUG) +#define RESTORE_FROM_CHECKPOINT (0 && DEBUG) @interface DSMasternodeManager () @@ -63,7 +65,8 @@ @interface DSMasternodeManager () @property (nonatomic, strong) NSManagedObjectContext *managedObjectContext; @property (nonatomic) BOOL isSyncing; @property (nonatomic) BOOL isRestored; -@property (nonatomic, strong) NSData* baseBlockHashWaitingForDiffs; +@property (nonatomic) BOOL hasHandledQrInfoPipeline; +@property (nonatomic) BOOL isPendingValidation; @end @@ -88,7 +91,7 @@ - (MasternodeProcessor *)processor { } - (NSString *)logPrefix { - return [NSString stringWithFormat:@"[%@] [MasternodeManager] ", self.chain.name]; + return [NSString stringWithFormat:@"[%@] [MasternodeManager]", self.chain.name]; } - (BOOL)hasCurrentMasternodeListInLast30Days { @@ -103,11 +106,12 @@ - (BOOL)hasCurrentMasternodeListInLast30Days { #pragma mark - DSMasternodeListServiceDelegate +// always from chain.networkingQueue - (void)masternodeListServiceEmptiedRetrievalQueue:(DSMasternodeListService *)service { - if (self.baseBlockHashWaitingForDiffs) - [self getRecentMasternodeList]; - else + if (!self.isPendingValidation) { + [self.chain.chainManager.syncState removeSyncKind:DSSyncStateExtKind_Masternodes]; [self.chain.chainManager chainFinishedSyncingMasternodeListsAndQuorums:self.chain]; + } } @@ -127,7 +131,11 @@ - (uint32_t)heightForBlockHash:(UInt256)blockhash { - (BOOL)isMasternodeListOutdated { uint32_t lastHeight = self.lastMasternodeListBlockHeight; - return lastHeight == UINT32_MAX || lastHeight < self.chain.lastTerminalBlockHeight - 8; + return lastHeight == UINT32_MAX || lastHeight < self.chain.lastTerminalBlockHeight; +} + +- (BOOL)isQRInfoOutdated { + return dash_spv_masternode_processor_processing_processor_MasternodeProcessor_is_qr_info_outdated(self.processor, self.chain.lastTerminalBlockHeight); } - (DMasternodeEntry *)masternodeHavingProviderRegistrationTransactionHash:(NSData *)providerRegistrationTransactionHash { @@ -208,6 +216,7 @@ - (BOOL)restoreEngine { } } +#if RESTORE_FROM_CHECKPOINT - (BOOL)restoreFromCheckpoint { DSCheckpoint *checkpoint = [self.chain lastCheckpointHavingMasternodeList]; if (!checkpoint || !checkpoint.masternodeListName || [checkpoint.masternodeListName isEqualToString:@""]) @@ -227,15 +236,20 @@ - (BOOL)restoreFromCheckpoint { DMnDiffResultDtor(result); return YES; } +#endif +// always from chain.networkingQueue - (BOOL)restoreState { + [self.chain.chainManager.syncState.masternodeListSyncInfo addSyncKind:DSMasternodeListSyncStateKind_Checkpoints]; BOOL restored = [self restoreEngine]; if (!restored) { DSLog(@"%@ No Engine Stored", self.logPrefix); + #if RESTORE_FROM_CHECKPOINT // TODO: checkpoints don't work anymore, since old protocol version support was dropped -// restored = [self restoreFromCheckpoint]; -// if (!restored) -// DSLog(@"%@ No Checkpoint Stored", self.logPrefix); + restored = [self restoreFromCheckpoint]; + if (!restored) + DSLog(@"%@ No Checkpoint Stored", self.logPrefix); + #endif } if (restored) { DMasternodeList *current_list = [self currentMasternodeList]; @@ -246,7 +260,12 @@ - (BOOL)restoreState { DSMasternodeManagerNotificationMasternodeListKey: current_list ? [NSValue valueWithPointer:current_list] : [NSNull null] }]; self.isRestored = YES; + } + self.chain.chainManager.syncState.masternodeListSyncInfo.lastListHeight = DCurrentMasternodeListBlockHeight(self.processor); + self.chain.chainManager.syncState.masternodeListSyncInfo.storedCount = (uint32_t) DKnownMasternodeListsCount(self.processor); + [self.chain.chainManager.syncState.masternodeListSyncInfo removeSyncKind:DSMasternodeListSyncStateKind_Checkpoints]; + [self.chain.chainManager notifySyncStateChanged]; return restored; } @@ -261,28 +280,22 @@ - (BOOL)restoreState { } - (void)setUp { - [self restoreState]; + dispatch_async(self.chain.networkingQueue, ^{ + [self restoreState]; + }); [DSLocalMasternodeEntity loadLocalMasternodesInContext:self.managedObjectContext onChainEntity:[self.chain chainEntityInContext:self.managedObjectContext]]; } - (void)reloadMasternodeLists { DProcessorClear(self.processor); - [self.chain.chainManager notifyMasternodeSyncStateChange:UINT32_MAX storedCount:0]; - [self restoreState]; -} - -- (BOOL)hasBlockForBlockHash:(NSData *)blockHashData { - UInt256 blockHash = blockHashData.UInt256; - BOOL hasBlock = [self.chain blockForBlockHash:blockHash] != nil; - if (!hasBlock) { - hasBlock = [DSMerkleBlockEntity hasBlocksWithHash:blockHash inContext:self.managedObjectContext]; - } - if (!hasBlock && self.chain.isTestnet) { - //We can trust insight if on testnet - [self.chain blockUntilGetInsightForBlockHash:blockHash]; - hasBlock = !![[self.chain insightVerifiedBlocksByHashDictionary] objectForKey:blockHashData]; - } - return hasBlock; + [self notify:DSCurrentMasternodeListDidChangeNotification userInfo:@{ + DSChainManagerNotificationChainKey: self.chain, + DSMasternodeManagerNotificationMasternodeListKey: [NSNull null] + }]; + dispatch_async(self.chain.networkingQueue, ^{ + [self.chain.chainManager notifyMasternodeSyncStateChange:UINT32_MAX storedCount:0]; + [self restoreState]; + }); } - (DMasternodeList *)currentMasternodeList { @@ -294,18 +307,19 @@ - (void)wipeMasternodeInfo { DProcessorClear(self.processor); [self.masternodeListDiffService cleanAllLists]; [self.quorumRotationService cleanAllLists]; - [self.chain.chainManager notifyMasternodeSyncStateChange:UINT32_MAX storedCount:0]; - dispatch_async(dispatch_get_main_queue(), ^{ - [[NSNotificationCenter defaultCenter] postNotificationName:DSMasternodeListDidChangeNotification - object:nil - userInfo:@{ - DSChainManagerNotificationChainKey: self.chain - }]; - [[NSNotificationCenter defaultCenter] postNotificationName:DSQuorumListDidChangeNotification - object:nil - userInfo:@{ - DSChainManagerNotificationChainKey: self.chain - }]; + dash_spv_masternode_processor_processing_processor_MasternodeProcessor_reinit_engine(self.processor, self.chain.chainType, [self.chain createDiffConfig]); + uint32_t lastListHeight = DCurrentMasternodeListBlockHeight(self.processor); + uint32_t storedCount = (uint32_t) DKnownMasternodeListsCount(self.processor); + DMasternodeList *current_list = [self currentMasternodeList]; + dispatch_async(self.chain.networkingQueue, ^{ +// [self.chain.chainManager.syncState.masternodeListSyncInfo resetSyncKind]; + self.chain.chainManager.syncState.masternodeListSyncInfo.queueCount = 0; + self.chain.chainManager.syncState.masternodeListSyncInfo.queueMaxAmount = 0; + self.chain.chainManager.syncState.masternodeListSyncInfo.lastListHeight = lastListHeight; + self.chain.chainManager.syncState.masternodeListSyncInfo.storedCount = storedCount; + [self.chain.chainManager notifySyncStateChanged]; + + [self notifyCurrentListChanged:current_list]; }); } @@ -324,14 +338,17 @@ - (DMasternodeList *)masternodeListForBlockHash:(UInt256)blockHash // MARK: - Requesting Masternode List +// always from chain.networkingQueue - (void)startSync { DSLog(@"%@ [Start]", self.logPrefix); self.isSyncing = YES; if (!self.isRestored) [self restoreState]; [self getRecentMasternodeList]; + [self.chain.chainManager.syncState addSyncKind:DSSyncStateExtKind_Masternodes]; } +// always from chain.networkingQueue - (void)stopSync { DSLog(@"%@ [Stop]", self.logPrefix); self.isSyncing = NO; @@ -339,6 +356,12 @@ - (void)stopSync { if (self.chain.isRotatedQuorumsPresented) [self.quorumRotationService stop]; [self.masternodeListDiffService stop]; + + self.chain.chainManager.syncState.masternodeListSyncInfo.queueCount = 0; + self.chain.chainManager.syncState.masternodeListSyncInfo.queueMaxAmount = 0; + [self.chain.chainManager.syncState.masternodeListSyncInfo resetSyncKind]; + [self.chain.chainManager.syncState removeSyncKind:DSSyncStateExtKind_Masternodes]; + [self.chain.chainManager notifySyncStateChanged]; } - (void)getRecentMasternodeList { @@ -349,7 +372,23 @@ - (void)getRecentMasternodeList { DSLog(@"%@ getRecentMasternodeList: (no block exist) for tip", self.logPrefix); return; } - [self.quorumRotationService getRecent:merkleBlock.blockHash]; + NSData *blockHash = uint256_data(merkleBlock.blockHash); + if (!self.isPendingValidation && (!self.hasHandledQrInfoPipeline || [self isQRInfoOutdated])) { + [self.quorumRotationService getRecent:blockHash]; + } + if (!self.isPendingValidation && self.hasHandledQrInfoPipeline && [self isMasternodeListOutdated]) { + + NSUInteger newCount = [self.masternodeListDiffService addToRetrievalQueue:blockHash]; + NSUInteger maxAmount = self.masternodeListDiffService.retrievalQueueMaxAmount; + [self.masternodeListDiffService dequeueMasternodeListRequest]; + dispatch_async(self.chain.networkingQueue, ^{ + self.chain.chainManager.syncState.masternodeListSyncInfo.queueCount = (uint32_t) newCount; + self.chain.chainManager.syncState.masternodeListSyncInfo.queueMaxAmount = (uint32_t) maxAmount; + [self.chain.chainManager notifySyncStateChanged]; + }); + + + } } @@ -363,7 +402,7 @@ - (void)getCurrentMasternodeListWithSafetyDelay:(uint32_t)safetyDelay { dispatch_source_set_timer(self.masternodeListTimer, dispatch_time(DISPATCH_TIME_NOW, (int64_t)(safetyDelay * NSEC_PER_SEC)), DISPATCH_TIME_FOREVER, 1ull * NSEC_PER_SEC); dispatch_source_set_event_handler(self.masternodeListTimer, ^{ NSTimeInterval timeElapsed = [[NSDate date] timeIntervalSince1970] - self.timeIntervalForMasternodeRetrievalSafetyDelay; - if (timeElapsed > safetyDelay) { + if (timeElapsed > safetyDelay && !self.isPendingValidation) { [self getRecentMasternodeList]; } }); @@ -400,28 +439,6 @@ - (BOOL)processRequestFromFileForBlockHash:(UInt256)blockHash { return YES; } - -// MARK: - Deterministic Masternode List Sync - -- (DSBlock *)lastBlockForBlockHash:(UInt256)blockHash fromPeer:(DSPeer *)peer { - DSBlock *lastBlock = nil; - if ([self.chain heightForBlockHash:blockHash]) { - lastBlock = [[peer.chain terminalBlocks] objectForKey:uint256_obj(blockHash)]; - if (!lastBlock && [peer.chain allowInsightBlocksForVerification]) { - NSData *blockHashData = uint256_data(blockHash); - lastBlock = [[peer.chain insightVerifiedBlocksByHashDictionary] objectForKey:blockHashData]; - if (!lastBlock && peer.chain.isTestnet) { - //We can trust insight if on testnet - [self.chain blockUntilGetInsightForBlockHash:blockHash]; - lastBlock = [[peer.chain insightVerifiedBlocksByHashDictionary] objectForKey:blockHashData]; - } - } - } else { - lastBlock = [peer.chain recentTerminalBlockForBlockHash:blockHash]; - } - return lastBlock; -} - - (void)issueWithMasternodeListFromPeer:(DSPeer *)peer { [self.chain.chainManager chain:self.chain badMasternodeListReceivedFromPeer:peer]; NSArray *faultyPeers = [[NSUserDefaults standardUserDefaults] arrayForKey:CHAIN_FAULTY_DML_MASTERNODE_PEERS]; @@ -431,6 +448,12 @@ - (void)issueWithMasternodeListFromPeer:(DSPeer *)peer { [self.masternodeListDiffService cleanListsRetrievalQueue]; [self.quorumRotationService cleanListsRetrievalQueue]; [[NSUserDefaults standardUserDefaults] removeObjectForKey:CHAIN_FAULTY_DML_MASTERNODE_PEERS]; + dispatch_async(self.chain.networkingQueue, ^{ + self.chain.chainManager.syncState.masternodeListSyncInfo.queueCount = 0; + self.chain.chainManager.syncState.masternodeListSyncInfo.queueMaxAmount = 0; + [self.chain.chainManager notifySyncStateChanged]; + }); + [self.chain.masternodeManager getRecentMasternodeList]; } else { if (!faultyPeers) { @@ -445,16 +468,38 @@ - (void)issueWithMasternodeListFromPeer:(DSPeer *)peer { [self.chain.chainManager notify:DSMasternodeListDiffValidationErrorNotification userInfo:@{DSChainManagerNotificationChainKey: self.chain}]; } +- (void)printEngineStatus { + dash_spv_masternode_processor_processing_processor_MasternodeProcessor_print_engine_status(self.processor); +} + +- (NSError *_Nullable)verifyQuorums { +#if defined(DASHCORE_QUORUM_VALIDATION) + DSLog(@"%@: Quorums Verification: Started", self.logPrefix); + Result_ok_bool_err_dashcore_sml_quorum_validation_error_QuorumValidationError *result = dash_spv_masternode_processor_processing_processor_MasternodeProcessor_verify_current_masternode_list_quorums(self.processor); + if (result->error) { + NSError *quorumValidationError = [NSError ffi_from_quorum_validation_error:result->error]; + DSLog(@"%@ Quorums Verification: Error: %@", self.logPrefix, quorumValidationError.description); + Result_ok_bool_err_dashcore_sml_quorum_validation_error_QuorumValidationError_destroy(result); + return quorumValidationError; + } + DSLog(@"%@: Quorums Verification: Ok", self.logPrefix); + Result_ok_bool_err_dashcore_sml_quorum_validation_error_QuorumValidationError_destroy(result); +#else + DSLog(@"%@: Quorums Verification: Disabled", self.logPrefix); +#endif + return nil; +} - (void)peer:(DSPeer *)peer relayedMasternodeDiffMessage:(NSData *)message { - DSLog(@"%@ [%@:%d] mnlistdiff: received: %@", self.logPrefix, peer.host, peer.port, uint256_hex(message.SHA256)); + //DSLog(@"%@ [%@:%d] mnlistdiff: received: %@", self.logPrefix, peer.host, peer.port, uint256_hex(message.SHA256)); @synchronized (self.masternodeListDiffService) { self.masternodeListDiffService.timedOutAttempt = 0; } dispatch_async(self.processingQueue, ^{ dispatch_group_enter(self.processingGroup); Slice_u8 *message_slice = slice_ctor(message); - DMnDiffResult *result = DMnDiffFromMessage(self.processor, message_slice, nil, false); + DMnDiffResult *result = DMnDiffFromMessage(self.processor, message_slice, nil, self.hasHandledQrInfoPipeline); + if (result->error) { NSError *error = [NSError ffi_from_processing_error:result->error]; DSLog(@"%@ mnlistdiff: Error: %@", self.logPrefix, error.description); @@ -469,25 +514,74 @@ - (void)peer:(DSPeer *)peer relayedMasternodeDiffMessage:(NSData *)message { [self issueWithMasternodeListFromPeer:peer]; break; } - #if SAVE_MASTERNODE_DIFF_TO_FILE - [self writeToDisk:[NSString stringWithFormat:@"MNL_ERR__%d_%lu.dat", peer.version, [NSDate timeIntervalSinceReferenceDate]] data:message]; + #if SAVE_MASTERNODE_DIFF_ERROR_TO_FILE + [self writeToDisk:[NSString stringWithFormat:@"MNL_ERR__%d_%f.dat", peer.version, [NSDate timeIntervalSinceReferenceDate]] data:message]; #endif DMnDiffResultDtor(result); dispatch_group_leave(self.processingGroup); return; } + [[NSUserDefaults standardUserDefaults] removeObjectForKey:CHAIN_FAULTY_DML_MASTERNODE_PEERS]; if (self.isSyncing) { + u256 *base_block_hash = dashcore_hash_types_BlockHash_inner(result->ok->o_0); u256 *block_hash = dashcore_hash_types_BlockHash_inner(result->ok->o_1); - NSData *blockHashData = NSDataFromPtr(block_hash); + UInt256 baseBlockHash = u256_cast(base_block_hash); + UInt256 blockHash = u256_cast(block_hash); + DSLog(@"%@ MNLISTDIFF: OK: %@", self.logPrefix, uint256_hex(blockHash)); + #if SAVE_MASTERNODE_DIFF_TO_FILE + [self writeToDisk:[NSString stringWithFormat:@"MNL_%@_%@__%d.dat", uint256_hex(baseBlockHash), uint256_hex(blockHash), peer.version] data:message]; + #endif + u256_dtor(base_block_hash); u256_dtor(block_hash); - [self.masternodeListDiffService removeFromRetrievalQueue:blockHashData]; + uint32_t newCount = (uint32_t) [self.masternodeListDiffService removeFromRetrievalQueue:uint256_data(blockHash)]; + uint32_t maxQueueCount = (uint32_t) [self.masternodeListDiffService retrievalQueueMaxAmount]; + [self.masternodeListDiffService removeRequestInRetrievalForBaseBlockHash:baseBlockHash blockHash:blockHash]; - if ([self.masternodeListDiffService retrievalQueueCount]) { + if ([self.masternodeListDiffService hasActiveQueue]) { + uint32_t lastListHeight = DCurrentMasternodeListBlockHeight(self.processor); + uint32_t storedCount = (uint32_t) DKnownMasternodeListsCount(self.processor); + + DMasternodeList *current_list = [self currentMasternodeList]; + dispatch_async(self.chain.networkingQueue, ^{ + self.chain.chainManager.syncState.masternodeListSyncInfo.queueCount = newCount; + self.chain.chainManager.syncState.masternodeListSyncInfo.queueMaxAmount = maxQueueCount; + self.chain.chainManager.syncState.masternodeListSyncInfo.lastListHeight = lastListHeight; + self.chain.chainManager.syncState.masternodeListSyncInfo.storedCount = storedCount; + [self.chain.chainManager notifySyncStateChanged]; + [self notifyCurrentListChanged:current_list]; + }); [self.masternodeListDiffService dequeueMasternodeListRequest]; + } else if (self.isPendingValidation) { + dispatch_async(self.chain.networkingQueue, ^{ + self.chain.chainManager.syncState.masternodeListSyncInfo.queueCount = newCount; + self.chain.chainManager.syncState.masternodeListSyncInfo.queueMaxAmount = maxQueueCount; + [self.chain.chainManager.syncState.masternodeListSyncInfo removeSyncKind:DSMasternodeListSyncStateKind_QrInfo]; + [self.chain.chainManager.syncState.masternodeListSyncInfo removeSyncKind:DSMasternodeListSyncStateKind_Diffs]; + [self.chain.chainManager.syncState.masternodeListSyncInfo addSyncKind:DSMasternodeListSyncStateKind_Quorums]; + [self.chain.chainManager notifySyncStateChanged]; + }); + NSError *quorumValidationError = [self verifyQuorums]; + if (quorumValidationError) { + dispatch_async(self.chain.networkingQueue, ^{ + [self.chain.chainManager.syncState.masternodeListSyncInfo removeSyncKind:DSMasternodeListSyncStateKind_Quorums]; + }); + } else { + [self finishIntitialQrInfoPipeline]; + } } else { - DSLog(@"%@: All diffs are here -> Re-request QRINFO for", self.logPrefix, self.baseBlockHashWaitingForDiffs.hexString); - [self getRecentMasternodeList]; + uint32_t lastListHeight = DCurrentMasternodeListBlockHeight(self.processor); + uint32_t storedCount = (uint32_t) DKnownMasternodeListsCount(self.processor); + DMasternodeList *current_list = [self currentMasternodeList]; + dispatch_async(self.chain.networkingQueue, ^{ + self.chain.chainManager.syncState.masternodeListSyncInfo.queueCount = newCount; + self.chain.chainManager.syncState.masternodeListSyncInfo.queueMaxAmount = maxQueueCount; + self.chain.chainManager.syncState.masternodeListSyncInfo.lastListHeight = lastListHeight; + self.chain.chainManager.syncState.masternodeListSyncInfo.storedCount = storedCount; + [self.chain.chainManager.syncState.masternodeListSyncInfo removeSyncKind:DSMasternodeListSyncStateKind_Diffs]; + [self.chain.chainManager notifySyncStateChanged]; + [self notifyCurrentListChanged:current_list]; + }); } } DMnDiffResultDtor(result); @@ -532,8 +626,8 @@ - (void)tryToProcessQrInfo:(DSPeer *)peer message:(NSData *)message attempt:(uin default: break; } - #if SAVE_MASTERNODE_DIFF_TO_FILE - [self writeToDisk:[NSString stringWithFormat:@"QRINFO_ERR_%d_%lu.dat", peer.version, [NSDate timeIntervalSinceReferenceDate]] data:message]; + #if SAVE_MASTERNODE_DIFF_ERROR_TO_FILE + [self writeToDisk:[NSString stringWithFormat:@"QRINFO_ERR_%d_%f.dat", peer.version, [NSDate timeIntervalSinceReferenceDate]] data:message]; #endif #if SAVE_ERROR_STATE Result_ok_Vec_u8_err_dash_spv_masternode_processor_processing_processor_processing_error_ProcessingError *bincode = dash_spv_masternode_processor_processing_processor_MasternodeProcessor_serialize_engine(self.processor); @@ -553,18 +647,36 @@ - (void)tryToProcessQrInfo:(DSPeer *)peer message:(NSData *)message attempt:(uin [[NSUserDefaults standardUserDefaults] removeObjectForKey:CHAIN_FAULTY_DML_MASTERNODE_PEERS]; std_collections_BTreeSet_dashcore_hash_types_BlockHash *missed_hashes = result->ok; - DSLog(@"%@ qrinfo: OK: %ul", self.logPrefix, (uint16_t) missed_hashes->count); + DSLog(@"%@ QRINFO: OK: %u", self.logPrefix, (uint32_t) missed_hashes->count); + #if SAVE_MASTERNODE_DIFF_TO_FILE + [self writeToDisk:[NSString stringWithFormat:@"QRINFO_MISSED_%d_%f.dat", peer.version, [NSDate timeIntervalSinceReferenceDate]] data:message]; + #endif + if (missed_hashes->count > 0) { - self.baseBlockHashWaitingForDiffs = [self.quorumRotationService retrievalBlockHash]; + self.isPendingValidation = YES; [self.quorumRotationService cleanAllLists]; NSArray *missedHashes = [NSArray ffi_from_block_hash_btree_set:missed_hashes]; - [self.masternodeListDiffService addToRetrievalQueueArray:missedHashes]; + NSUInteger newCount = [self.masternodeListDiffService addToRetrievalQueueArray:missedHashes]; + NSUInteger maxAmount = self.masternodeListDiffService.retrievalQueueMaxAmount; + dispatch_async(self.chain.networkingQueue, ^{ + [self.chain.chainManager.syncState.masternodeListSyncInfo addSyncKind:DSMasternodeListSyncStateKind_Diffs]; + self.chain.chainManager.syncState.masternodeListSyncInfo.queueCount = (uint32_t) newCount; + self.chain.chainManager.syncState.masternodeListSyncInfo.queueMaxAmount = (uint32_t) maxAmount; + [self.chain.chainManager notifySyncStateChanged]; + }); [self.masternodeListDiffService dequeueMasternodeListRequest]; } else { - self.baseBlockHashWaitingForDiffs = nil; - [self.quorumRotationService cleanAllLists]; - [self.quorumRotationService dequeueMasternodeListRequest]; - [self.chain.chainManager.transactionManager checkWaitingForQuorums]; + dispatch_async(self.chain.networkingQueue, ^{ + [self.chain.chainManager.syncState.masternodeListSyncInfo addSyncKind:DSMasternodeListSyncStateKind_Quorums]; + }); + NSError *quorumValidationError = [self verifyQuorums]; + if (quorumValidationError) { + dispatch_async(self.chain.networkingQueue, ^{ + [self.chain.chainManager.syncState.masternodeListSyncInfo removeSyncKind:DSMasternodeListSyncStateKind_Quorums]; + }); + } else { + [self finishIntitialQrInfoPipeline]; + } } DQRInfoResultDtor(result); @@ -572,8 +684,27 @@ - (void)tryToProcessQrInfo:(DSPeer *)peer message:(NSData *)message attempt:(uin }); } +- (void)finishIntitialQrInfoPipeline { + self.hasHandledQrInfoPipeline = YES; + self.isPendingValidation = NO; + DMasternodeList *current_list = [self currentMasternodeList]; + uint32_t lastListHeight = DCurrentMasternodeListBlockHeight(self.processor); + uint32_t storedCount = (uint32_t) DKnownMasternodeListsCount(self.processor); + [self.quorumRotationService cleanAllLists]; + dispatch_async(self.chain.networkingQueue, ^{ + [self.chain.chainManager.syncState.masternodeListSyncInfo removeSyncKind:DSMasternodeListSyncStateKind_Quorums]; + [self.chain.chainManager.syncState.masternodeListSyncInfo removeSyncKind:DSMasternodeListSyncStateKind_QrInfo]; + self.chain.chainManager.syncState.masternodeListSyncInfo.lastListHeight = lastListHeight; + self.chain.chainManager.syncState.masternodeListSyncInfo.storedCount = storedCount; + [self.chain.chainManager notifySyncStateChanged]; + [self.chain.chainManager.transactionManager checkWaitingForQuorums]; + [self notifyCurrentListChanged:current_list]; + }); + [self.quorumRotationService dequeueMasternodeListRequest]; +} + - (void)peer:(DSPeer *)peer relayedQuorumRotationInfoMessage:(NSData *)message { - DSLog(@"%@ [%@:%d] qrinfo: received: %@", self.logPrefix, peer.host, peer.port, uint256_hex(message.SHA256)); + //DSLog(@"%@ [%@:%d] qrinfo: received: %@", self.logPrefix, peer.host, peer.port, uint256_hex(message.SHA256)); @synchronized (self.quorumRotationService) { self.quorumRotationService.timedOutAttempt = 0; } @@ -606,4 +737,52 @@ - (uintptr_t)currentValidQuorumsOfType:(DLLMQType)type { return dash_spv_masternode_processor_processing_processor_MasternodeProcessor_current_valid_quorums_of_type_count(self.processor, &type); } + +- (NSError *_Nullable)requestMasternodeListForBlockHeight:(uint32_t)blockHeight { + DSMerkleBlock *merkleBlock = [self.chain blockAtHeight:blockHeight]; + if (!merkleBlock) + return [NSError errorWithDomain:@"DashSync" code:600 userInfo:@{NSLocalizedDescriptionKey: @"Unknown block"}]; + [self requestMasternodeListForBlockHash:uint256_data(merkleBlock.blockHash)]; + return nil; +} +- (void)requestMasternodeListForBlockHash:(NSData *)blockHash { + NSUInteger newCount = [self.masternodeListDiffService addToRetrievalQueue:blockHash]; + NSUInteger maxAmount = self.masternodeListDiffService.retrievalQueueMaxAmount; + dispatch_async(self.chain.networkingQueue, ^{ + [self.chain.chainManager.syncState.masternodeListSyncInfo addSyncKind:DSMasternodeListSyncStateKind_Diffs]; + self.chain.chainManager.syncState.masternodeListSyncInfo.queueCount = (uint32_t) newCount; + self.chain.chainManager.syncState.masternodeListSyncInfo.queueMaxAmount = (uint32_t) maxAmount; + [self.chain.chainManager notifySyncStateChanged]; + }); + [self.masternodeListDiffService dequeueMasternodeListRequest]; + +} +- (void)requestMasternodeListForBaseBlockHash:(NSData *)baseBlockHash blockHash:(NSData *)blockHash { + NSUInteger maxAmount = self.masternodeListDiffService.retrievalQueueMaxAmount; + NSUInteger newCount = [self.masternodeListDiffService addToRetrievalQueueArray:@[baseBlockHash, blockHash]]; + dispatch_async(self.chain.networkingQueue, ^{ + [self.chain.chainManager.syncState.masternodeListSyncInfo addSyncKind:DSMasternodeListSyncStateKind_Diffs]; + self.chain.chainManager.syncState.masternodeListSyncInfo.queueCount = (uint32_t) newCount; + self.chain.chainManager.syncState.masternodeListSyncInfo.queueMaxAmount = (uint32_t) maxAmount; + [self.chain.chainManager notifySyncStateChanged]; + }); + [self.masternodeListDiffService dequeueMasternodeListRequest]; +} + +- (void)notifyCurrentListChanged:(DMasternodeList *_Nullable)list { + dispatch_async(dispatch_get_main_queue(), ^{ + [[NSNotificationCenter defaultCenter] postNotificationName:DSCurrentMasternodeListDidChangeNotification object:nil userInfo:@{ + DSChainManagerNotificationChainKey: self.chain, + DSMasternodeManagerNotificationMasternodeListKey: list ? [NSValue valueWithPointer:list] : [NSNull null] + }]; + [[NSNotificationCenter defaultCenter] postNotificationName:DSMasternodeListDidChangeNotification object:nil userInfo:@{ + DSChainManagerNotificationChainKey: self.chain, + }]; + [[NSNotificationCenter defaultCenter] postNotificationName:DSQuorumListDidChangeNotification object:nil userInfo:@{ + DSChainManagerNotificationChainKey: self.chain, + }]; + }); + +} + @end diff --git a/DashSync/shared/Models/Managers/Chain Managers/DSPeerManager.m b/DashSync/shared/Models/Managers/Chain Managers/DSPeerManager.m index 4e7c1dfc..d54e94b4 100644 --- a/DashSync/shared/Models/Managers/Chain Managers/DSPeerManager.m +++ b/DashSync/shared/Models/Managers/Chain Managers/DSPeerManager.m @@ -261,7 +261,9 @@ - (void)clearPeers:(DSDisconnectReason)reason { NSMutableArray *mArray = [NSMutableArray array]; for (int i = 0; i < vec->count; i++) { Tuple_Arr_u8_16_u16 *pair = vec->values[i]; - [mArray addObject:[[DSPeer alloc] initWithAddress:u128_cast(pair->o_0) andPort:pair->o_1 onChain:self.chain]]; + UInt128 ip = u128_cast(pair->o_0); + uint16_t port = pair->o_1; + [mArray addObject:[[DSPeer alloc] initWithAddress:ip andPort:port onChain:self.chain]]; } Vec_Tuple_Arr_u8_16_u16_destroy(vec); return mArray; @@ -666,6 +668,7 @@ - (NSArray *)registeredDevnetPeerServices { // MARK: - Using Masternode List for connectivitity +// always from chain.networkingQueue - (void)useMasternodeList:(DMasternodeList *)masternodeList withConnectivityNonce:(uint64_t)connectivityNonce { self.masternodeList = masternodeList; @@ -675,7 +678,7 @@ - (void)useMasternodeList:(DMasternodeList *)masternodeList NSArray *peers = [self peers:500 withConnectivityNonce:connectivityNonce]; - + [self.chain.chainManager.syncState.peersSyncInfo addSyncKind:DSPeersSyncStateKind_Selection]; @synchronized(self) { if (!_peers) { _peers = [NSMutableOrderedSet orderedSetWithArray:peers]; @@ -688,7 +691,7 @@ - (void)useMasternodeList:(DMasternodeList *)masternodeList } if (peers.count > 1 && peers.count < 1000) [self savePeers]; // peer relaying is complete when we receive <1000 - + [self.chain.chainManager.syncState.peersSyncInfo removeSyncKind:DSPeersSyncStateKind_Selection]; if (connected) { DSLog(@"[%@] [DSPeerManager] useMasternodeList -> connect", self.chain.name); [self connect]; @@ -722,7 +725,9 @@ - (void)startBackgroundMode:(BOOL)performDisconnects { - (void)connect { DSLog(@"[%@] [DSPeerManager] connect", self.chain.name); self.desiredState = DSPeerManagerDesiredState_Connected; + dispatch_async(self.networkingQueue, ^{ + [self.chain.chainManager.syncState.peersSyncInfo addSyncKind:DSPeersSyncStateKind_Connecting]; if ([self.chain syncsBlockchain] && ![self.chain canConstructAFilter]) { DSLog(@"[%@] [DSPeerManager] failed to connect: check that wallet is created", self.chain.name); return; // check to make sure the wallet has been created if only are a basic wallet with no dash features @@ -773,7 +778,12 @@ - (void)connect { DSPeer *peer = peers[(NSUInteger)(pow(arc4random_uniform((uint32_t)peers.count), 2) / peers.count)]; if (peer && ![self.connectedPeers containsObject:peer]) { - [peer setChainDelegate:self.chainManager peerDelegate:self transactionDelegate:self.transactionManager governanceDelegate:self.governanceSyncManager sporkDelegate:self.sporkManager masternodeDelegate:self.masternodeManager queue:self.networkingQueue]; + [peer setChainDelegate:self.chainManager + peerDelegate:self + transactionDelegate:self.transactionManager + governanceDelegate:self.governanceSyncManager + sporkDelegate:self.sporkManager + masternodeDelegate:self.masternodeManager]; peer.earliestKeyTime = earliestWalletCreationTime; [self.mutableConnectedPeers addObject:peer]; @@ -791,6 +801,7 @@ - (void)connect { if (peers.count == 0) { [self chainSyncStopped]; DSLog(@"[%@] [DSPeerManager] No peers found -> SyncFailed", self.chain.name); + [self.chain.chainManager.syncState.peersSyncInfo removeSyncKind:DSPeersSyncStateKind_Connecting]; dispatch_async(dispatch_get_main_queue(), ^{ [[NSNotificationCenter defaultCenter] postNotificationName:DSChainManagerSyncFailedNotification object:nil @@ -812,6 +823,12 @@ - (void)disconnect:(DSDisconnectReason)reason { } - (void)disconnectDownloadPeerForError:(NSError *)error withCompletion:(void (^_Nullable)(BOOL success))completion { + if (!self.connected) { + dispatch_async(self.networkingQueue, ^{ + if (completion) completion(YES); + }); + return; + } [self.downloadPeer disconnectWithError:error]; dispatch_async(self.networkingQueue, ^{ if (self.downloadPeer) { // disconnect the current download peer so a new random one will be selected @@ -851,6 +868,7 @@ - (void)chainSyncStopped { // MARK: - DSPeerDelegate +// always from chain.networkingQueue - (void)peerConnected:(DSPeer *)peer { NSTimeInterval now = [NSDate timeIntervalSince1970]; @@ -870,7 +888,7 @@ - (void)peerConnected:(DSPeer *)peer { [peer disconnectWithError:ERROR_NO_BLOOM(peer.host)]; return; } - + [self.chain.chainManager.syncState.peersSyncInfo removeSyncKind:DSPeersSyncStateKind_Connecting]; if (self.connected) { if (![self.chain syncsBlockchain]) return; if ([self.chain canConstructAFilter]) { @@ -966,32 +984,36 @@ - (void)peerConnected:(DSPeer *)peer { uint32_t lastTerminalBlockHeight = self.chain.lastTerminalBlockHeight; uint32_t bestPeerLastBlockHeight = bestPeer.lastBlockHeight; bestPeer.currentBlockHeight = lastSyncBlockHeight; - - dispatch_async(dispatch_get_main_queue(), ^{ // setup a timer to detect if the sync stalls - self.chainManager.syncState.hasDownloadPeer = bestPeer; - self.chainManager.syncState.peerManagerConnected = YES; - self.chainManager.syncState.estimatedBlockHeight = estimatedBlockHeight; - self.chainManager.syncState.lastTerminalBlockHeight = lastTerminalBlockHeight; - self.chainManager.syncState.lastSyncBlockHeight = lastSyncBlockHeight; - if ([self.chain syncsBlockchain] && ((lastSyncBlockHeight != lastTerminalBlockHeight) || (lastSyncBlockHeight < bestPeerLastBlockHeight))) { - // start blockchain sync - [self restartSyncTimeout:PROTOCOL_TIMEOUT]; - [[NSNotificationCenter defaultCenter] postNotificationName:DSTransactionManagerTransactionStatusDidChangeNotification + self.chainManager.syncState.peersSyncInfo.hasDownloadPeer = bestPeer; + self.chainManager.syncState.peersSyncInfo.peerManagerConnected = YES; + self.chainManager.syncState.estimatedBlockHeight = estimatedBlockHeight; + self.chainManager.syncState.lastTerminalBlockHeight = lastTerminalBlockHeight; + self.chainManager.syncState.lastSyncBlockHeight = lastSyncBlockHeight; + if ([self.chain syncsBlockchain] && ((lastSyncBlockHeight != lastTerminalBlockHeight) || (lastSyncBlockHeight < bestPeerLastBlockHeight))) { + // start blockchain sync + [self restartSyncTimeout:PROTOCOL_TIMEOUT]; + dispatch_async(dispatch_get_main_queue(), ^{ + [[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]; - } + }); + [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(), ^{ [[NSNotificationCenter defaultCenter] postNotificationName:DSPeerManagerConnectedPeersDidChangeNotification object:nil userInfo:@{DSChainManagerNotificationChainKey: self.chain}]; [[NSNotificationCenter defaultCenter] postNotificationName:DSPeerManagerDownloadPeerDidChangeNotification object:nil userInfo:@{DSChainManagerNotificationChainKey: self.chain}]; + + }); } +// always from chain.networkingQueue - (void)peer:(DSPeer *)peer disconnectedWithError:(NSError *)error { DSLog(@"[%@: %@:%d] [DSPeerManager] disconnected %@%@", self.chain.name, peer.host, peer.port, (error ? @", " : @""), (error ? error : @"")); @@ -1010,10 +1032,9 @@ - (void)peer:(DSPeer *)peer disconnectedWithError:(NSError *)error { _connected = NO; [self.chain removeEstimatedBlockHeightOfPeer:peer]; self.downloadPeer = nil; - - self.chainManager.syncState.hasDownloadPeer = NO; + self.chainManager.syncState.peersSyncInfo.hasDownloadPeer = NO; [self.chainManager notifySyncStateChanged]; - + if (self.connectFailures > MAX_CONNECT_FAILURES) self.connectFailures = MAX_CONNECT_FAILURES; } diff --git a/DashSync/shared/Models/Managers/Chain Managers/DSSporkManager.m b/DashSync/shared/Models/Managers/Chain Managers/DSSporkManager.m index f92c01ff..96f8aa48 100644 --- a/DashSync/shared/Models/Managers/Chain Managers/DSSporkManager.m +++ b/DashSync/shared/Models/Managers/Chain Managers/DSSporkManager.m @@ -145,16 +145,15 @@ - (void)performSporkRequest { - (void)getSporks { if (!([[DSOptionsManager sharedInstance] syncType] & DSSyncType_Sporks)) return; // make sure we care about sporks - if (!self.sporkTimer) { [self performSporkRequest]; self.sporkTimer = [NSTimer scheduledTimerWithTimeInterval:600 repeats:TRUE block:^(NSTimer *_Nonnull timer) { - if (self.lastSyncedSporks < [NSDate timeIntervalSince1970] - 60 * 10) { //wait 10 minutes between requests - [self performSporkRequest]; - } - }]; + if (self.lastSyncedSporks < [NSDate timeIntervalSince1970] - 60 * 10) { //wait 10 minutes between requests + [self performSporkRequest]; + } + }]; } } diff --git a/DashSync/shared/Models/Managers/Chain Managers/DSTransactionManager.m b/DashSync/shared/Models/Managers/Chain Managers/DSTransactionManager.m index 349286cb..0113c2d8 100644 --- a/DashSync/shared/Models/Managers/Chain Managers/DSTransactionManager.m +++ b/DashSync/shared/Models/Managers/Chain Managers/DSTransactionManager.m @@ -370,9 +370,13 @@ - (void)removeUnrelayedTransactionsFromPeer:(DSPeer *)peer { dispatch_async(dispatch_get_main_queue(), ^{ [[NSNotificationCenter defaultCenter] postNotificationName:DSTransactionManagerTransactionStatusDidChangeNotification object:nil - userInfo:@{DSChainManagerNotificationChainKey: self.chain, - DSTransactionManagerNotificationTransactionKey: transaction, - DSTransactionManagerNotificationTransactionChangesKey: @{DSTransactionManagerNotificationTransactionAcceptedStatusKey: @(NO)}}]; + userInfo:@{ + DSChainManagerNotificationChainKey: self.chain, + DSTransactionManagerNotificationTransactionKey: transaction, + DSTransactionManagerNotificationTransactionChangesKey: @{ + DSTransactionManagerNotificationTransactionAcceptedStatusKey: @(NO) + } + }]; }); } } @@ -948,11 +952,28 @@ - (void)confirmPaymentRequest:(DSPaymentRequest *)paymentRequest publishedCompletion:(DSTransactionPublishedCompletionBlock)publishedCompletion errorNotificationBlock:(DSTransactionErrorNotificationBlock)errorNotificationBlock { DSPaymentProtocolRequest *protocolRequest = [paymentRequest protocolRequestForIdentity:identity onAccount:account inContext:[NSManagedObjectContext viewContext]]; - [self confirmProtocolRequest:protocolRequest forAmount:paymentRequest.amount fromAccount:account acceptInternalAddress:acceptInternalAddress acceptReusingAddress:acceptReusingAddress addressIsFromPasteboard:addressIsFromPasteboard acceptUncertifiedPayee:NO mixedOnly:NO requiresSpendingAuthenticationPrompt:requiresSpendingAuthenticationPrompt keepAuthenticatedIfErrorAfterAuthentication:keepAuthenticatedIfErrorAfterAuthentication requestingAdditionalInfo:additionalInfoRequest presentChallenge:challenge transactionCreationCompletion:transactionCreationCompletion signedCompletion:signedCompletion publishedCompletion:publishedCompletion requestRelayCompletion:nil errorNotificationBlock:errorNotificationBlock]; + [self confirmProtocolRequest:protocolRequest + forAmount:paymentRequest.amount + fromAccount:account + acceptInternalAddress:acceptInternalAddress + acceptReusingAddress:acceptReusingAddress + addressIsFromPasteboard:addressIsFromPasteboard + acceptUncertifiedPayee:NO + mixedOnly:NO +requiresSpendingAuthenticationPrompt:requiresSpendingAuthenticationPrompt +keepAuthenticatedIfErrorAfterAuthentication:keepAuthenticatedIfErrorAfterAuthentication + requestingAdditionalInfo:additionalInfoRequest + presentChallenge:challenge + transactionCreationCompletion:transactionCreationCompletion + signedCompletion:signedCompletion + publishedCompletion:publishedCompletion + requestRelayCompletion:nil + errorNotificationBlock:errorNotificationBlock]; } // MARK: - Mempools Sync +// always from chain.networkingQueue - (void)fetchMempoolFromPeer:(DSPeer *)peer { DSLog(@"[%@: %@:%d] [DSTransactionManager] fetching mempool from peer", self.chain.name, peer.host, peer.port); if (peer.status != DSPeerStatus_Connected) return; @@ -988,6 +1009,7 @@ - (void)fetchMempoolFromPeer:(DSPeer *)peer { } } if (peer == self.peerManager.downloadPeer) { + [self.chain.chainManager.syncState removeSyncKind:DSSyncStateExtKind_Mempool]; [self.peerManager chainSyncStopped]; dispatch_async(dispatch_get_main_queue(), ^{ [[NSNotificationCenter defaultCenter] postNotificationName:DSChainManagerSyncFinishedNotification object:nil userInfo:@{DSChainManagerNotificationChainKey: self.chain}]; @@ -996,6 +1018,7 @@ - (void)fetchMempoolFromPeer:(DSPeer *)peer { }]; } else if (peer == self.peerManager.downloadPeer) { DSLog(@"[%@: %@:%d] [DSTransactionManager] fetching mempool ping failure on download peer", self.chain.name, peer.host, peer.port); + [self.chain.chainManager.syncState removeSyncKind:DSSyncStateExtKind_Mempool]; [self.peerManager chainSyncStopped]; dispatch_async(dispatch_get_main_queue(), ^{ @@ -1010,10 +1033,13 @@ - (void)fetchMempoolFromPeer:(DSPeer *)peer { }]; } +// always from chain.networkingQueue - (void)fetchMempoolFromNetwork { // this can come from any queue if (!([[DSOptionsManager sharedInstance] syncType] & DSSyncType_Mempools)) return; // make sure we care about mempool - for (DSPeer *peer in self.peerManager.connectedPeers) { // after syncing, load filters and get mempools from other peers + [self.chain.chainManager.syncState addSyncKind:DSSyncStateExtKind_Mempool]; + for (DSPeer *peer in self.peerManager.connectedPeers) { + // after syncing, load filters and get mempools from other peers [self fetchMempoolFromPeer:peer]; } } @@ -1244,21 +1270,23 @@ - (void)peer:(DSPeer *)peer hasTransactionWithHash:(UInt256)txHash { [self.txRequests[hash] removeObject:peer]; } -//The peer has sent us a transaction we are interested in and that we did not send ourselves +// always from chain.networkingQueue +// The peer has sent us a transaction we are interested in and that we did not send ourselves - (void)peer:(DSPeer *)peer relayedTransaction:(DSTransaction *)transaction inBlock:(DSBlock *)block { - NSValue *hash = uint256_obj(transaction.txHash); + UInt256 txHash = transaction.txHash; + NSValue *hash = uint256_obj(txHash); BOOL syncing = (self.chain.lastSyncBlockHeight < self.chain.estimatedBlockHeight); void (^callback)(NSError *error) = self.publishedCallback[hash]; if (peer) { #if DEBUG - DSLogPrivate(@"[%@: %@:%d] relayed transaction %@", self.chain.name, peer.host, peer.port, hash); + DSLogPrivate(@"[%@: %@:%d] relayed transaction %@", self.chain.name, peer.host, peer.port, uint256_hex(txHash)); #else DSLog(@"[%@: %@:%d] relayed transaction %@", self.chain.name, peer.host, peer.port, @""); #endif } else { #if DEBUG - DSLogPrivate(@"[%@: %@:%d] accepting local transaction %@", self.chain.name, peer.host, peer.port, hash); + DSLogPrivate(@"[%@: %@:%d] accepting local transaction %@", self.chain.name, peer.host, peer.port, uint256_hex(txHash)); #else DSLog(@"[%@: %@:%d] accepting local transaction %@", self.chain.name, peer.host, peer.port, @""); #endif @@ -1273,13 +1301,13 @@ - (void)peer:(DSPeer *)peer relayedTransaction:(DSTransaction *)transaction inBl if (![self.chain transactionHasLocalReferences:transaction]) { if (peer) { #if DEBUG - DSLogPrivate(@"[%@: %@:%d] no account or local references for transaction %@", self.chain.name, peer.host, peer.port, hash); + DSLogPrivate(@"[%@: %@:%d] no account or local references for transaction %@", self.chain.name, peer.host, peer.port, uint256_hex(txHash)); #else DSLog(@"[%@: %@:%d] no account or local references for transaction %@", self.chain.name, peer.host, peer.port, @""); #endif } else { #if DEBUG - DSLogPrivate(@"[%@: %@:%d] no account or local references for transaction %@", self.chain.name, peer.host, peer.port, hash); + DSLogPrivate(@"[%@: %@:%d] no account or local references for transaction %@", self.chain.name, peer.host, peer.port, uint256_hex(txHash)); #else DSLog(@"[%@: %@:%d] no account or local references for transaction %@", self.chain.name, peer.host, peer.port, @""); #endif @@ -1288,13 +1316,13 @@ - (void)peer:(DSPeer *)peer relayedTransaction:(DSTransaction *)transaction inBl } else { if (peer) { #if DEBUG - DSLogPrivate(@"[%@: %@:%d] no account for transaction with local references %@", self.chain.name, peer.host, peer.port, hash); + DSLogPrivate(@"[%@: %@:%d] no account for transaction with local references %@", self.chain.name, peer.host, peer.port, uint256_hex(txHash)); #else DSLog(@"[%@: %@:%d] no account for transaction with local references %@", self.chain.name, peer.host, peer.port, @""); #endif } else { #if DEBUG - DSLogPrivate(@"[%@: %@:%d] no account for transaction with local references %@", self.chain.name, peer.host, peer.port, hash); + DSLogPrivate(@"[%@: %@:%d] no account for transaction with local references %@", self.chain.name, peer.host, peer.port, uint256_hex(txHash)); #else DSLog(@"[%@: %@:%d] no account for transaction with local references %@", self.chain.name, peer.host, peer.port, @""); #endif @@ -1313,13 +1341,13 @@ - (void)peer:(DSPeer *)peer relayedTransaction:(DSTransaction *)transaction inBl } else { if (peer) { #if DEBUG - DSLogPrivate(@"[%@: %@:%d] could not register transaction %@", self.chain.name, peer.host, peer.port, hash); + DSLogPrivate(@"[%@: %@:%d] could not register transaction %@", self.chain.name, peer.host, peer.port, uint256_hex(txHash)); #else DSLog(@"[%@: %@:%d] could not register transaction %@", self.chain.name, peer.host, peer.port, @""); #endif } else { #if DEBUG - DSLogPrivate(@"[%@: %@:%d] could not register transaction %@", self.chain.name, peer.host, peer.port, hash); + DSLogPrivate(@"[%@: %@:%d] could not register transaction %@", self.chain.name, peer.host, peer.port, uint256_hex(txHash)); #else DSLog(@"[%@: %@:%d] could not register transaction %@", self.chain.name, peer.host, peer.port, @""); #endif @@ -1364,10 +1392,10 @@ - (void)peer:(DSPeer *)peer relayedTransaction:(DSTransaction *)transaction inBl } } - DSInstantSendTransactionLock *transactionLockReceivedEarlier = [self.instantSendLocksWaitingForTransactions objectForKey:uint256_data(transaction.txHash)]; + DSInstantSendTransactionLock *transactionLockReceivedEarlier = [self.instantSendLocksWaitingForTransactions objectForKey:uint256_data(txHash)]; if (transactionLockReceivedEarlier) { - [self.instantSendLocksWaitingForTransactions removeObjectForKey:uint256_data(transaction.txHash)]; + [self.instantSendLocksWaitingForTransactions removeObjectForKey:uint256_data(txHash)]; [transaction setInstantSendReceivedWithInstantSendLock:transactionLockReceivedEarlier]; [transactionLockReceivedEarlier saveInitial]; } @@ -1414,12 +1442,12 @@ - (void)peer:(DSPeer *)peer relayedTransaction:(DSTransaction *)transaction inBl if (callback) [self.publishedCallback removeObjectForKey:hash]; for (DSAccount *account in accountsAcceptingTransaction) { - if (account && [self.txRelays[hash] count] >= self.peerManager.maxConnectCount && - [account transactionForHash:transaction.txHash].blockHeight == TX_UNCONFIRMED && - [account transactionForHash:transaction.txHash].timestamp == 0) { - [account setBlockHeight:TX_UNCONFIRMED - andTimestamp:[NSDate timeIntervalSince1970] - forTransactionHashes:@[hash]]; // set timestamp when tx is verified + if (account && [self.txRelays[hash] count] >= self.peerManager.maxConnectCount) { + DSTransaction *tx = [account transactionForHash:txHash]; + if (tx.blockHeight == TX_UNCONFIRMED && tx.timestamp == 0) + [account setBlockHeight:TX_UNCONFIRMED + andTimestamp:[NSDate timeIntervalSince1970] + forTransactionHashes:@[hash]]; // set timestamp when tx is verified } } @@ -1645,6 +1673,7 @@ - (void)checkInstantSendLocksWaitingForQuorums { // MARK: Blocks +// always from chain.networkingQueue - (void)peer:(DSPeer *)peer relayedHeader:(DSMerkleBlock *)block { //DSLogPrivate(@"relayed block %@ total transactions %d %u",uint256_hex(block.blockHash), block.totalTransactions,block.timestamp); // ignore block headers that are newer than 2 days before earliestKeyTime (headers have 0 totalTransactions) @@ -1660,6 +1689,7 @@ - (void)peer:(DSPeer *)peer relayedHeader:(DSMerkleBlock *)block { [self.chain addBlock:block receivedAsHeader:YES fromPeer:peer]; } +// always from chain.networkingQueue - (void)peer:(DSPeer *)peer relayedBlock:(DSMerkleBlock *)block { if (!self.chainManager.syncPhase) { DSLog(@"[%@: %@:%d] Block was received after reset, ignoring it", self.chain.name, peer.host, peer.port); @@ -1752,6 +1782,7 @@ - (void)peer:(DSPeer *)peer relayedTooManyOrphanBlocks:(NSUInteger)orphanBlockCo [self.peerManager peerMisbehaving:peer errorMessage:@"Too many orphan blocks"]; } +// always from chain.networkingQueue - (void)peer:(DSPeer *)peer relayedChainLock:(DSChainLock *)chainLock { BOOL verified = [chainLock verifySignature]; UInt256 clBlockHash = uint256_reverse(chainLock.blockHash); @@ -1766,7 +1797,7 @@ - (void)peer:(DSPeer *)peer relayedChainLock:(DSChainLock *)chainLock { [[NSNotificationCenter defaultCenter] postNotificationName:DSChainBlockWasLockedNotification object:nil userInfo:@{DSChainManagerNotificationChainKey: self.chain, DSChainNotificationBlockKey: block}]; }); } else { - DSLog(@"[%@: %@:%d] no block for chain lock %@", self.chain.name, peer.host, peer.port, uint256_hex(clBlockHash)); + DSLog(@"[%@: %@:%d] no block %@ for chain lock", self.chain.name, peer.host, peer.port, uint256_hex(clBlockHash)); [self.chainLocksWaitingForMerkleBlocks setObject:chainLock forKey:uint256_data(clBlockHash)]; } diff --git a/DashSync/shared/Models/Managers/Service Managers/DSInsightManager.m b/DashSync/shared/Models/Managers/Service Managers/DSInsightManager.m index a219f699..a1b5f6d3 100644 --- a/DashSync/shared/Models/Managers/Service Managers/DSInsightManager.m +++ b/DashSync/shared/Models/Managers/Service Managers/DSInsightManager.m @@ -23,7 +23,8 @@ #define INSIGHT_URL @"https://insight.dash.org/insight-api-dash" #define INSIGHT_FAILOVER_URL @"https://insight.dash.show/api" -#define TESTNET_INSIGHT_URL @"https://testnet-insight.dashevo.org/insight-api-dash" +#define TESTNET_INSIGHT_URL @"https://insight.testnet.networks.dash.org/insight-api" +//#define TESTNET_INSIGHT_URL @"https://testnet-insight.dashevo.org/insight-api-dash" @implementation DSInsightManager @@ -117,7 +118,7 @@ - (void)blockForBlockHeight:(uint32_t)blockHeight onChain:(DSChain *)chain compl cachePolicy:NSURLRequestReloadIgnoringCacheData timeoutInterval:20.0]; req.HTTPMethod = @"GET"; - DSLogPrivate(@"%@ GET: %@", req.URL.absoluteString, + DSLogPrivate(@"[%@] %@ GET: %@", chain.name, req.URL.absoluteString, [[NSString alloc] initWithData:req.HTTPBody encoding:NSUTF8StringEncoding]); @@ -144,6 +145,7 @@ - (void)blockForBlockHeight:(uint32_t)blockHeight onChain:(DSChain *)chain compl NSData *chainWork = [json[@"chainwork"] hexToData]; NSNumber *height = json[@"height"]; DSBlock *block = [[DSBlock alloc] initWithVersion:[version unsignedIntValue] blockHash:blockHash.reverse.UInt256 prevBlock:previousBlockHash.reverse.UInt256 timestamp:timestamp.unsignedIntValue merkleRoot:merkleRoot.reverse.UInt256 target:[targetString.hexToData UInt32AtOffset:0] chainWork:chainWork.reverse.UInt256 height:height.unsignedIntValue onChain:chain]; + DSLogPrivate(@"[%@] BLOCK FROM INSIGHT: %@", chain.name, block); completion(block, nil); }] resume]; diff --git a/DashSync/shared/Models/Masternode/DSMasternodeListDiffService.h b/DashSync/shared/Models/Masternode/DSMasternodeListDiffService.h index 0b0167d5..05f5710e 100644 --- a/DashSync/shared/Models/Masternode/DSMasternodeListDiffService.h +++ b/DashSync/shared/Models/Masternode/DSMasternodeListDiffService.h @@ -24,12 +24,10 @@ NS_ASSUME_NONNULL_BEGIN @property (nonatomic, readonly) NSOrderedSet *retrievalQueue; @property (nonatomic, readonly) NSUInteger retrievalQueueCount; -//@property (nonatomic, readonly) NSUInteger retrievalQueueMaxAmount; - (NSUInteger)addToRetrievalQueue:(NSData *)masternodeBlockHashData; - (NSUInteger)removeFromRetrievalQueue:(NSData *)masternodeBlockHashData; - (NSUInteger)addToRetrievalQueueArray:(NSArray *_Nonnull)masternodeBlockHashDataArray; -//- (void)cleanListsRetrievalQueue; - (void)fetchMasternodeListsToRetrieve:(void (^)(NSOrderedSet *listsToRetrieve))completion; diff --git a/DashSync/shared/Models/Masternode/DSMasternodeListDiffService.m b/DashSync/shared/Models/Masternode/DSMasternodeListDiffService.m index a772e300..03b2e2b9 100644 --- a/DashSync/shared/Models/Masternode/DSMasternodeListDiffService.m +++ b/DashSync/shared/Models/Masternode/DSMasternodeListDiffService.m @@ -41,36 +41,30 @@ - (instancetype)initWithChain:(DSChain *)chain { } - (NSString *)logPrefix { - return [NSString stringWithFormat:@"[%@] [MasternodeManager::DiffService] ", self.chain.name]; + return [NSString stringWithFormat:@"[%@] [MasternodeManager::DiffService]", self.chain.name]; +} + +- (void)getRecent:(NSData *)blockHash { + [self addToRetrievalQueue:blockHash]; + [self dequeueMasternodeListRequest]; } - (void)composeMasternodeListRequest:(NSOrderedSet *)list { - NSMutableString *debugString = [NSMutableString stringWithString:@"Needed:\n"]; - for (NSData *data in list) { - uint32_t h = [self.chain heightForBlockHash:data.UInt256]; - [debugString appendFormat:@"%u: %@\n", h, data.hexString]; - } - [debugString appendFormat:@"KnownLists:\n"]; - DKnownMasternodeLists *lists = dash_spv_masternode_processor_processing_processor_MasternodeProcessor_masternode_lists(self.chain.sharedProcessorObj); - for (int i = 0; i < lists->count; i++) { - dashcore_prelude_CoreBlockHeight *core_block_height = lists->keys[i]; - DMasternodeList *list = lists->values[i]; - u256 *block_hash = dashcore_hash_types_BlockHash_inner(list->block_hash); - [debugString appendFormat:@"%u: %@\n", core_block_height->_0, u256_hex(block_hash)]; - } - DKnownMasternodeListsDtor(lists); - DSLog(@"%@ composeMasternodeListRequest: \n%@", self.logPrefix, debugString); for (NSData *blockHashData in list) { // we should check the associated block still exists - if ([self.chain.masternodeManager hasBlockForBlockHash:blockHashData]) { + if ([self hasBlockForBlockHash:blockHashData]) { //there is the rare possibility we have the masternode list as a checkpoint, so lets first try that NSUInteger pos = [list indexOfObject:blockHashData]; UInt256 blockHash = blockHashData.UInt256; BOOL success = [self.chain.masternodeManager processRequestFromFileForBlockHash:blockHash]; if (success) { - [self removeFromRetrievalQueue:blockHashData]; - if (![self retrievalQueueCount]) - [self.chain.chainManager.transactionManager checkWaitingForQuorums]; + NSUInteger newCount = [self removeFromRetrievalQueue:blockHashData]; + dispatch_async(self.chain.networkingQueue, ^{ + self.chain.chainManager.syncState.masternodeListSyncInfo.queueCount = (uint32_t) newCount; + [self.chain.chainManager notifySyncStateChanged]; + if (!newCount) + [self.chain.chainManager.transactionManager checkWaitingForQuorums]; + }); } else { // we need to go get it uint32_t blockHeight = [self.chain heightForBlockHash:blockHash]; @@ -82,25 +76,40 @@ - (void)composeMasternodeListRequest:(NSOrderedSet *)list { uint32_t prevInQueueBlockHeight = [self.chain heightForBlockHash:u256_cast(prev_in_queue_block_hash)]; UInt256 previousBlockHash = pos ? (prevKnownHeight > prevInQueueBlockHeight ? prevKnownBlockHash : prevInQueueBlockHash) : prevKnownBlockHash; // request at: every new block -// NSAssert(([self.store heightForBlockHash:previousBlockHash] != UINT32_MAX) || uint256_is_zero(previousBlockHash), @"This block height should be known"); - [self requestMasternodeListDiff:previousBlockHash forBlockHash:blockHash]; -// [self requestMasternodeListDiff:@"00000ffd590b1485b3caadc19b22e6379c733355108f107a430458cdf3407ab6".hexToData.reverse.UInt256 forBlockHash:@"c21ff900433ace7e6b7841bdfec8c449ca06414b237167e30b00000000000000".hexToData.UInt256]; + // NSAssert(([self.store heightForBlockHash:previousBlockHash] != UINT32_MAX) || uint256_is_zero(previousBlockHash), @"This block height should be known"); + if (uint256_eq(previousBlockHash, blockHash)) { + NSUInteger newCount = [self removeFromRetrievalQueue:blockHashData]; + dispatch_async(self.chain.networkingQueue, ^{ + self.chain.chainManager.syncState.masternodeListSyncInfo.queueCount = (uint32_t) newCount; + [self.chain.chainManager notifySyncStateChanged]; + }); + } else { + [self requestMasternodeListDiff:previousBlockHash forBlockHash:blockHash]; + } } } else { DSLog(@"%@ Missing block (%@)", self.logPrefix, blockHashData.hexString); - [self removeFromRetrievalQueue:blockHashData]; + NSUInteger newCount = [self removeFromRetrievalQueue:blockHashData]; + dispatch_async(self.chain.networkingQueue, ^{ + self.chain.chainManager.syncState.masternodeListSyncInfo.queueCount = (uint32_t) newCount; + [self.chain.chainManager notifySyncStateChanged]; + }); } } } - (void)fetchMasternodeListsToRetrieve:(void (^)(NSOrderedSet *listsToRetrieve))completion { - if (![self retrievalQueueCount]) { + //DSLog(@"%@ fetchMasternodeListToRetrieve...: %u", self.logPrefix, [self hasActiveQueue]); + if (![self hasActiveQueue]) { DSLog(@"%@ No masternode lists in retrieval", self.logPrefix); - [self.chain.masternodeManager masternodeListServiceEmptiedRetrievalQueue:self]; + dispatch_async(self.chain.networkingQueue, ^{ + [self.chain.chainManager.syncState.masternodeListSyncInfo removeSyncKind:DSMasternodeListSyncStateKind_Diffs]; + [self.chain.masternodeManager masternodeListServiceEmptiedRetrievalQueue:self]; + }); return; } if ([self.requestsInRetrieval count]) { - //DSLog(@"%@ Already in retrieval", self.logPrefix); + DSLog(@"%@ Already in retrieval", self.logPrefix); return; } if ([self peerIsDisconnected]) { @@ -144,7 +153,6 @@ - (NSUInteger)addToRetrievalQueue:(NSData *)masternodeBlockHashData { return ([self.chain heightForBlockHash:obj1.UInt256] < [self.chain heightForBlockHash:obj2.UInt256]) ? NSOrderedAscending : NSOrderedDescending; }]; } - [self notifyQueueChange:newCount maxAmount:maxAmount]; return newCount; } @@ -153,10 +161,12 @@ - (NSUInteger)addToRetrievalQueueArray:(NSArray *_Nonnull)masternodeBl NSMutableArray *nonEmptyBlockHashes = [NSMutableArray array]; NSUInteger newCount = 0, maxAmount = 0; @synchronized (_retrievalQueue) { + NSMutableString *debugString = [NSMutableString string]; for (NSData *blockHashData in masternodeBlockHashDataArray) { NSAssert(uint256_is_not_zero(blockHashData.UInt256), @"We should not be adding an empty block hash"); if (uint256_is_not_zero(blockHashData.UInt256)) { [nonEmptyBlockHashes addObject:blockHashData]; + [debugString appendFormat:@"\t%@,\n", blockHashData.hexString]; } } [_retrievalQueue addObjectsFromArray:nonEmptyBlockHashes]; @@ -167,7 +177,6 @@ - (NSUInteger)addToRetrievalQueueArray:(NSArray *_Nonnull)masternodeBl return ([self.chain heightForBlockHash:obj1.UInt256] < [self.chain heightForBlockHash:obj2.UInt256]) ? NSOrderedAscending : NSOrderedDescending; }]; } - [self notifyQueueChange:newCount maxAmount:maxAmount]; return newCount; } @@ -177,9 +186,7 @@ - (NSUInteger)removeFromRetrievalQueue:(NSData *)masternodeBlockHashData { [_retrievalQueue removeObject:masternodeBlockHashData]; newCount = [_retrievalQueue count]; maxAmount = MAX(self.retrievalQueueMaxAmount, newCount); - } - [self notifyQueueChange:newCount maxAmount:maxAmount]; return newCount; } @@ -187,51 +194,38 @@ - (void)cleanListsRetrievalQueue { @synchronized (_retrievalQueue) { [_retrievalQueue removeAllObjects]; } + self.retrievalQueueMaxAmount = 0; } +- (BOOL)hasActiveQueue { + return [self.retrievalQueue count]; +} - (void)requestMasternodeListDiff:(UInt256)previousBlockHash forBlockHash:(UInt256)blockHash { DSGetMNListDiffRequest *request = [DSGetMNListDiffRequest requestWithBaseBlockHash:previousBlockHash blockHash:blockHash]; DSMasternodeListRequest *matchedRequest = [self requestInRetrievalFor:previousBlockHash blockHash:blockHash]; if (matchedRequest) { -// DSLog(@"[%@] •••• mnlistdiff request with such a range already in retrieval: %u..%u %@ .. %@", self.chain.name, [self.store heightForBlockHash:previousBlockHash], [self.store heightForBlockHash:blockHash], uint256_hex(previousBlockHash), uint256_hex(blockHash)); +// DSLog(@"[%@] •••• mnlistdiff request with such a range already in retrieval: %@ .. %@", self.chain.name, uint256_hex(previousBlockHash), uint256_hex(blockHash)); return; } uint32_t prev_h = [self.chain heightForBlockHash:previousBlockHash]; uint32_t h = [self.chain heightForBlockHash:blockHash]; - -// uint32_t prev_h = DHeightForBlockHash(self.chain.sharedProcessorObj, u256_ctor_u(previousBlockHash)); -// uint32_t h = DHeightForBlockHash(self.chain.sharedProcessorObj, u256_ctor_u(blockHash)); + + DSLog(@"%@ Request: %u..%u %@ .. %@", self.logPrefix, prev_h, h, uint256_hex(previousBlockHash), uint256_hex(blockHash)); - if (prev_h == 0) { - DSLog(@"%@ Zero height", self.logPrefix); - } - if (prev_h == 530000) { - DSLog(@"start from checkpoint"); - } + dispatch_async(self.chain.networkingQueue, ^{ + [self.chain.chainManager.syncState.masternodeListSyncInfo addSyncKind:DSMasternodeListSyncStateKind_Diffs]; + }); [self sendMasternodeListRequest:request]; } - (void)notifyQueueChange:(NSUInteger)newCount maxAmount:(NSUInteger)maxAmount { - DSLog(@"%@ Queue Changed: %u/%u ", self.logPrefix, (uint32_t)newCount, (uint32_t)maxAmount); - @synchronized (self.chain.chainManager.syncState) { - self.chain.chainManager.syncState.masternodeListSyncInfo.retrievalQueueCount = (uint32_t) newCount; - self.chain.chainManager.syncState.masternodeListSyncInfo.retrievalQueueMaxAmount = (uint32_t) maxAmount; + // DSLog(@"%@Queue Changed: %u/%u ", self.logPrefix, (uint32_t)newCount, (uint32_t)maxAmount); + dispatch_async(self.chain.networkingQueue, ^{ + self.chain.chainManager.syncState.masternodeListSyncInfo.queueCount = (uint32_t) newCount; + self.chain.chainManager.syncState.masternodeListSyncInfo.queueMaxAmount = (uint32_t) maxAmount; [self.chain.chainManager notifySyncStateChanged]; - } - + }); } -/// test-only -/// Used for fast obtaining list diff chain for specific block hashes like this: -/// //DSMasternodeListDiffService *service = self.masternodeListDiffService; -// [service sendReversedHashes:@"00000bafbc94add76cb75e2ec92894837288a481e5c005f6563d91623bf8bc2c" blockHash:@"000000e6b51b9aba9754e6b4ef996ef1d142d6cfcc032c1fd7fc78ca6663ee0a"]; -// [service sendReversedHashes:@"000000e6b51b9aba9754e6b4ef996ef1d142d6cfcc032c1fd7fc78ca6663ee0a" blockHash:@"00000009d7c0bcb59acf741f25239f45820eea178b74597d463ca80e104f753b"]; - -//-(void)sendReversedHashes:(NSString *)baseBlockHash blockHash:(NSString *)blockHash { -// DSGetMNListDiffRequest *request = [DSGetMNListDiffRequest requestWithBaseBlockHash:baseBlockHash.hexToData.reverse.UInt256 -// blockHash:blockHash.hexToData.reverse.UInt256]; -// [self sendMasternodeListRequest:request]; -//} - @end diff --git a/DashSync/shared/Models/Masternode/DSMasternodeListService+Protected.h b/DashSync/shared/Models/Masternode/DSMasternodeListService+Protected.h index fa4f81aa..83e93fd2 100644 --- a/DashSync/shared/Models/Masternode/DSMasternodeListService+Protected.h +++ b/DashSync/shared/Models/Masternode/DSMasternodeListService+Protected.h @@ -23,18 +23,15 @@ NS_ASSUME_NONNULL_BEGIN @interface DSMasternodeListService (Protected) -//@property (nonatomic, assign) NSMutableOrderedSet *retrievalQueue; - - (NSString *)logPrefix; +- (BOOL)hasActiveQueue; -//- (void)updateAfterProcessingMasternodeListWithBlockHash:(NSData *)blockHashData fromPeer:(DSPeer *)peer; - (BOOL)shouldProcessDiffResult:(u256 *)block_hash isValid:(BOOL)isValid skipPresenceInRetrieval:(BOOL)skipPresenceInRetrieval; -//- (BOOL)shouldProcessDiffResult:(DSMnDiffProcessingResult *)diffResult skipPresenceInRetrieval:(BOOL)skipPresenceInRetrieval; -//- (DSMasternodeListRequest*__nullable)requestInRetrievalFor:(UInt256)baseBlockHash blockHash:(UInt256)blockHash; - (UInt256)closestKnownBlockHashForBlockHeight:(uint32_t)blockHeight; - (void)startTimeOutObserver; +- (BOOL)hasBlockForBlockHash:(NSData *)blockHashData; @end diff --git a/DashSync/shared/Models/Masternode/DSMasternodeListService.h b/DashSync/shared/Models/Masternode/DSMasternodeListService.h index b82346ee..acb2ae41 100644 --- a/DashSync/shared/Models/Masternode/DSMasternodeListService.h +++ b/DashSync/shared/Models/Masternode/DSMasternodeListService.h @@ -34,37 +34,21 @@ FOUNDATION_EXPORT NSString *const DSMasternodeListDiffValidationErrorNotificatio @property (nonatomic, readonly, nonnull) DSChain *chain; @property (nonatomic, readonly) NSMutableSet *requestsInRetrieval; -//@property (nonatomic, readonly) NSOrderedSet *retrievalQueue; -//@property (nonatomic, readonly) NSUInteger retrievalQueueCount; @property (nonatomic, readwrite) NSUInteger retrievalQueueMaxAmount; - @property (nonatomic, assign) uint16_t timedOutAttempt; @property (nonatomic, assign) uint16_t timeOutObserverTry; - (instancetype)initWithChain:(DSChain *)chain; - - (void)dequeueMasternodeListRequest; +- (void)getRecent:(NSData *)blockHash; - (void)stop; - - (BOOL)peerIsDisconnected; - - (void)cleanAllLists; - (void)cleanRequestsInRetrieval; -//- (void)composeMasternodeListRequest:(NSOrderedSet *)list; - -//- (void)fetchMasternodeListsToRetrieve:(void (^)(NSOrderedSet *listsToRetrieve))completion; - -//- (NSUInteger)addToRetrievalQueue:(NSData *)masternodeBlockHashData; -//- (void)removeFromRetrievalQueue:(NSData *)masternodeBlockHashData; - (void)cleanListsRetrievalQueue; - (BOOL)removeRequestInRetrievalForBaseBlockHash:(UInt256)baseBlockHash blockHash:(UInt256)blockHash; - - (void)disconnectFromDownloadPeer; -//- (void)issueWithMasternodeListFromPeer:(DSPeer *)peer; - - (void)sendMasternodeListRequest:(DSMasternodeListRequest *)request; - -//- (void)checkWaitingForQuorums; - (DSMasternodeListRequest*__nullable)requestInRetrievalFor:(UInt256)baseBlockHash blockHash:(UInt256)blockHash; @end diff --git a/DashSync/shared/Models/Masternode/DSMasternodeListService.m b/DashSync/shared/Models/Masternode/DSMasternodeListService.m index c37d48f6..36b5ba38 100644 --- a/DashSync/shared/Models/Masternode/DSMasternodeListService.m +++ b/DashSync/shared/Models/Masternode/DSMasternodeListService.m @@ -23,6 +23,7 @@ #import "DSGetQRInfoRequest.h" #import "DSMasternodeManager+Protected.h" #import "DSMerkleBlock.h" +#import "DSMerkleBlockEntity+CoreDataClass.h" #import "DSPeerManager+Protected.h" #import "NSData+Dash.h" @@ -52,11 +53,14 @@ - (UInt256)closestKnownBlockHashForBlockHeight:(uint32_t)blockHeight { return known; } +- (BOOL)hasActiveQueue { + return NO; +} + - (void)startTimeOutObserver { [self cancelTimeOutObserver]; @synchronized (self) { NSSet *requestsInRetrieval = [self.requestsInRetrieval copy]; -// uintptr_t masternodeListCount = DKnownMasternodeListsCount(self.chain.sharedCacheObj); self.timeOutObserverTry++; uint16_t timeOutObserverTry = self.timeOutObserverTry; dispatch_time_t timeout = dispatch_time(DISPATCH_TIME_NOW, (int64_t)(40 * (self.timedOutAttempt + 1) * NSEC_PER_SEC)); @@ -65,15 +69,14 @@ - (void)startTimeOutObserver { dispatch_source_set_timer(self.timeoutTimer, timeout, DISPATCH_TIME_FOREVER, 1ull * NSEC_PER_SEC); dispatch_source_set_event_handler(self.timeoutTimer, ^{ @synchronized (self) { - if (!self.retrievalQueueMaxAmount || self.timeOutObserverTry != timeOutObserverTry) { + if (![self hasActiveQueue] || self.timeOutObserverTry != timeOutObserverTry) return; - } + NSSet *requestsInRetrieval2 = [self.requestsInRetrieval copy]; NSMutableSet *leftToGet = [requestsInRetrieval mutableCopy]; [leftToGet intersectSet:requestsInRetrieval2]; -// uintptr_t count = DKnownMasternodeListsCount(self.chain.sharedCacheObj); - - if (/*(masternodeListCount == count) &&*/ [requestsInRetrieval isEqualToSet:leftToGet]) { + + if ([requestsInRetrieval isEqualToSet:leftToGet]) { DSLog(@"%@ TimedOut -> dequeueMasternodeListRequest", self.logPrefix); self.timedOutAttempt++; [self disconnectFromDownloadPeer]; @@ -98,58 +101,18 @@ - (void)cancelTimeOutObserver { } } -//- (void)checkWaitingForQuorums { -// if (![self retrievalQueueCount]) { -// [self.chain.chainManager.transactionManager checkWaitingForQuorums]; -// } -//} +- (void)getRecent:(NSData *)blockHash { +} -//- (void)composeMasternodeListRequest:(NSOrderedSet *)list { -// /* Should be overriden */ -//} -// - (void)dequeueMasternodeListRequest { -// [self fetchMasternodeListsToRetrieve:^(NSOrderedSet *list) { -// [self composeMasternodeListRequest:list]; -// [self startTimeOutObserver]; -// }]; } - (void)stop { [self cancelTimeOutObserver]; [self cleanAllLists]; + } -//- (void)updateAfterProcessingMasternodeListWithBlockHash:(NSData *)blockHashData fromPeer:(DSPeer *)peer { -// -// [self removeFromRetrievalQueue:blockHashData]; -// DSLog(@"%@ updateAfterProcessingMasternodeListWithBlockHash %@ -> dequeueMasternodeListRequest (mn)", self.logPrefix, blockHashData.hexString); -// [self dequeueMasternodeListRequest]; -// [self checkWaitingForQuorums]; -// [[NSUserDefaults standardUserDefaults] removeObjectForKey:CHAIN_FAULTY_DML_MASTERNODE_PEERS]; -//} - -//- (NSUInteger)addToRetrievalQueue:(NSData *)masternodeBlockHashData { -// @synchronized (_retrievalQueue) { -// [_retrievalQueue addObject:uint256_data(masternodeBlockHashData.UInt256)]; -// NSUInteger newCount = [_retrievalQueue count]; -// _retrievalQueueMaxAmount = MAX(self.retrievalQueueMaxAmount, newCount); -// [_retrievalQueue sortUsingComparator:^NSComparisonResult(NSData *obj1, NSData *obj2) { -// if ([self.chain heightForBlockHash:obj1.UInt256] < [self.chain heightForBlockHash:obj2.UInt256]) { -// return NSOrderedAscending; -// } else { -// return NSOrderedDescending; -// } -// }]; -// return newCount; -// } -//} -// -//- (void)removeFromRetrievalQueue:(NSData *)masternodeBlockHashData { -// [_retrievalQueue removeObject:masternodeBlockHashData]; -//// [self.retrievalQueue ] -//// DMnDiffQueueRemove(self.chain.sharedProcessorObj, u256_ctor(masternodeBlockHashData)); -//} - (void)cleanRequestsInRetrieval { [self.requestsInRetrieval removeAllObjects]; @@ -175,30 +138,6 @@ - (DSPeerManager *)peerManager { return self.chain.chainManager.peerManager; } -//- (NSOrderedSet *)retrievalQueue { -// @synchronized (_retrievalQueue) { -// return [_retrievalQueue copy]; -// } -// -//// indexmap_IndexSet_u8_32 *queue = dash_spv_masternode_processor_processing_processor_cache_MasternodeProcessorCache_mn_list_retrieval_queue(self.chain.sharedCacheObj); -//// NSMutableOrderedSet *set = [NSMutableOrderedSet orderedSetWithCapacity:queue->count]; -//// for (int i = 0; i < queue->count; i++) { -//// [set addObject:NSDataFromPtr(queue->values[i])]; -//// } -//// indexmap_IndexSet_u8_32_destroy(queue); -//// return [_retrievalQueue copy]; -//} -// -//- (NSUInteger)retrievalQueueCount { -// @synchronized (_retrievalQueue) { -// return [_retrievalQueue count]; -// } -//// return DMnDiffQueueCount(self.chain.sharedCacheObj); -//} -//- (NSUInteger)retrievalQueueMaxAmount { -// return DMnDiffQueueMaxAmount(self.chain.sharedCacheObj); -//} - - (BOOL)peerIsDisconnected { BOOL peerIsDisconnected; @synchronized (self.peerManager.downloadPeer) { @@ -207,8 +146,6 @@ - (BOOL)peerIsDisconnected { return peerIsDisconnected; } - - - (DSMasternodeListRequest*__nullable)requestInRetrievalFor:(UInt256)baseBlockHash blockHash:(UInt256)blockHash { DSMasternodeListRequest *matchedRequest = nil; for (DSMasternodeListRequest *request in [self.requestsInRetrieval copy]) { @@ -233,30 +170,6 @@ - (void)disconnectFromDownloadPeer { [self.peerManager.downloadPeer disconnect]; } -//- (void)issueWithMasternodeListFromPeer:(DSPeer *)peer { -// [self.peerManager peerMisbehaving:peer errorMessage:@"Issue with Deterministic Masternode list"]; -// NSArray *faultyPeers = [[NSUserDefaults standardUserDefaults] arrayForKey:CHAIN_FAULTY_DML_MASTERNODE_PEERS]; -// if (faultyPeers.count >= MAX_FAULTY_DML_PEERS) { -// DSLog(@"%@ Exceeded max failures for masternode list, starting from scratch", self.logPrefix); -// //no need to remove local masternodes -// [self cleanListsRetrievalQueue]; -//// [self.store deleteAllOnChain]; -//// [self.store removeOldMasternodeLists]; -// [[NSUserDefaults standardUserDefaults] removeObjectForKey:CHAIN_FAULTY_DML_MASTERNODE_PEERS]; -// [self.chain.masternodeManager getRecentMasternodeList]; -// } else { -// if (!faultyPeers) { -// faultyPeers = @[peer.location]; -// } else if (![faultyPeers containsObject:peer.location]) { -// faultyPeers = [faultyPeers arrayByAddingObject:peer.location]; -// } -// [[NSUserDefaults standardUserDefaults] setObject:faultyPeers forKey:CHAIN_FAULTY_DML_MASTERNODE_PEERS]; -// DSLog(@"%@ Failure %lu for masternode list from peer: %@", self.logPrefix, (unsigned long)faultyPeers.count, peer); -// [self dequeueMasternodeListRequest]; -// } -// [self.chain.chainManager notify:DSMasternodeListDiffValidationErrorNotification userInfo:@{DSChainManagerNotificationChainKey: self.chain}]; -//} - - (void)sendMasternodeListRequest:(DSMasternodeListRequest *)request { // DSLog(@"•••• sendMasternodeListRequest: %@", [request toData].hexString); [self.peerManager sendRequest:request]; @@ -265,4 +178,18 @@ - (void)sendMasternodeListRequest:(DSMasternodeListRequest *)request { } } +- (BOOL)hasBlockForBlockHash:(NSData *)blockHashData { + UInt256 blockHash = blockHashData.UInt256; + BOOL hasBlock = [self.chain blockForBlockHash:blockHash] != nil; + if (!hasBlock) { + hasBlock = [DSMerkleBlockEntity hasBlocksWithHash:blockHash inContext:self.chain.masternodeManager.managedObjectContext]; + } + if (!hasBlock && self.chain.isTestnet) { + //We can trust insight if on testnet + [self.chain blockUntilGetInsightForBlockHash:blockHash]; + hasBlock = !![[self.chain insightVerifiedBlocksByHashDictionary] objectForKey:blockHashData]; + } + return hasBlock; +} + @end diff --git a/DashSync/shared/Models/Masternode/DSQuorumRotationService.h b/DashSync/shared/Models/Masternode/DSQuorumRotationService.h index 2a6bc546..c655b91e 100644 --- a/DashSync/shared/Models/Masternode/DSQuorumRotationService.h +++ b/DashSync/shared/Models/Masternode/DSQuorumRotationService.h @@ -25,7 +25,6 @@ NS_ASSUME_NONNULL_BEGIN @property (nonatomic, assign) NSTimeInterval lastSyncedTimestamp; @property (nonatomic, strong, readonly) NSData *retrievalBlockHash; -- (void)getRecent:(UInt256)blockHash; - (void)fetchMasternodeListToRetrieve:(void (^)(NSData *listsToRetrieve))completion; - (void)requestQuorumRotationInfo:(UInt256)previousBlockHash forBlockHash:(UInt256)blockHash; diff --git a/DashSync/shared/Models/Masternode/DSQuorumRotationService.m b/DashSync/shared/Models/Masternode/DSQuorumRotationService.m index 0bceb27e..18b7906c 100644 --- a/DashSync/shared/Models/Masternode/DSQuorumRotationService.m +++ b/DashSync/shared/Models/Masternode/DSQuorumRotationService.m @@ -33,7 +33,7 @@ @interface DSQuorumRotationService () @implementation DSQuorumRotationService - (NSString *)logPrefix { - return [NSString stringWithFormat:@"[%@] [MasternodeManager::QRInfoService] ", self.chain.name]; + return [NSString stringWithFormat:@"[%@] [MasternodeManager::QRInfoService]", self.chain.name]; } - (BOOL)hasRecentQrInfoSync { @@ -45,16 +45,21 @@ - (void)composeMasternodeListRequest:(NSData *)blockHashData { if (!blockHashData) { return; } - if ([self.chain.masternodeManager hasBlockForBlockHash:blockHashData]) { + if ([self hasBlockForBlockHash:blockHashData]) { UInt256 blockHash = blockHashData.UInt256; uint32_t blockHeight = [self.chain heightForBlockHash:blockHash]; UInt256 previousBlockHash = [self closestKnownBlockHashForBlockHeight:blockHeight]; -// @"000000000000000899fdcd85241296146c365b238a655517da8dcd08a8a79b98".hexToData; // NSAssert(([self.store heightForBlockHash:previousBlockHash] != UINT32_MAX) || uint256_is_zero(previousBlockHash), @"This block height should be known"); - [self requestQuorumRotationInfo:previousBlockHash forBlockHash:blockHash]; + if (uint256_eq(previousBlockHash, blockHash)) { + self.retrievalBlockHash = nil; + self.retrievalQueueMaxAmount = 0; + } else { + [self requestQuorumRotationInfo:previousBlockHash forBlockHash:blockHash]; + } } else { DSLog(@"%@ Missing block: %@ (%@)", self.logPrefix, blockHashData.hexString, blockHashData.reverse.hexString); self.retrievalBlockHash = nil; + self.retrievalQueueMaxAmount = 0; } } @@ -65,11 +70,18 @@ - (void)dequeueMasternodeListRequest { }]; } -- (NSUInteger)retrievalQueueMaxAmount { return 1; } - - (void)fetchMasternodeListToRetrieve:(void (^)(NSData *listsToRetrieve))completion { + //DSLog(@"%@ fetchMasternodeListToRetrieve...: %u", self.logPrefix, [self hasActiveQueue]); + if (![self hasActiveQueue]) { + //DSLog(@"%@ No masternode lists in retrieval", self.logPrefix); + dispatch_async(self.chain.networkingQueue, ^{ + [self.chain.chainManager.syncState.masternodeListSyncInfo removeSyncKind:DSMasternodeListSyncStateKind_QrInfo]; + [self.chain.masternodeManager masternodeListServiceEmptiedRetrievalQueue:self]; + }); + return; + } if ([self.requestsInRetrieval count]) { - DSLog(@"%@ A masternode list is already in retrieval", self.logPrefix); + //DSLog(@"%@ A masternode list is already in retrieval", self.logPrefix); return; } if ([self peerIsDisconnected]) { @@ -83,15 +95,19 @@ - (void)fetchMasternodeListToRetrieve:(void (^)(NSData *listsToRetrieve))complet completion([self.retrievalBlockHash copy]); } -- (void)getRecent:(UInt256)blockHash { - self.retrievalBlockHash = uint256_data(blockHash); +- (void)getRecent:(NSData *)blockHash { + self.retrievalQueueMaxAmount = 1; + self.retrievalBlockHash = blockHash; [self dequeueMasternodeListRequest]; } - (void)cleanListsRetrievalQueue { + self.retrievalQueueMaxAmount = 0; self.retrievalBlockHash = nil; } - +- (BOOL)hasActiveQueue { + return self.retrievalBlockHash != nil; +} - (void)requestQuorumRotationInfo:(UInt256)previousBlockHash 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 @@ -100,11 +116,16 @@ - (void)requestQuorumRotationInfo:(UInt256)previousBlockHash forBlockHash:(UInt2 DSLog(@"%@ Request: already in retrieval: %@ .. %@", self.logPrefix, uint256_hex(previousBlockHash), uint256_hex(blockHash)); return; } - NSArray *baseBlockHashes = @[[NSData dataWithUInt256:previousBlockHash]]; + + NSArray *baseBlockHashes = self.chain.isMainnet ? @[@"989ba7a808cd8dda1755658a235b366c1496122485cdfd990800000000000000".hexToData, [NSData dataWithUInt256:previousBlockHash]] : @[[NSData dataWithUInt256:previousBlockHash]]; + DSGetQRInfoRequest *request = [DSGetQRInfoRequest requestWithBaseBlockHashes:baseBlockHashes blockHash:blockHash extraShare:YES]; uint32_t prev_h = [self.chain heightForBlockHash:previousBlockHash]; uint32_t h = [self.chain heightForBlockHash:blockHash]; DSLog(@"%@ Request: %u..%u %@ .. %@", self.logPrefix, prev_h, h, uint256_hex(previousBlockHash), uint256_hex(blockHash)); + dispatch_async(self.chain.networkingQueue, ^{ + [self.chain.chainManager.syncState.masternodeListSyncInfo addSyncKind:DSMasternodeListSyncStateKind_QrInfo]; + }); [self sendMasternodeListRequest:request]; } diff --git a/DashSync/shared/Models/Messages/Masternodes/DSGetMNListDiffRequest.m b/DashSync/shared/Models/Messages/Masternodes/DSGetMNListDiffRequest.m index f31634fc..bc6ab666 100644 --- a/DashSync/shared/Models/Messages/Masternodes/DSGetMNListDiffRequest.m +++ b/DashSync/shared/Models/Messages/Masternodes/DSGetMNListDiffRequest.m @@ -79,5 +79,7 @@ -(BOOL)matchesInRangeWithBaseBlockHash:(UInt256)baseBlockHash blockHash:(UInt256 - (NSString *)logWithBlockHeightLookup:(BlockHeightFinder)blockHeightLookup { return [NSString stringWithFormat:@"%u: %@ .. %u: %@", blockHeightLookup(self.baseBlockHash), uint256_hex(self.baseBlockHash), blockHeightLookup(self.blockHash), uint256_hex(self.blockHash)]; } - +- (BOOL)logging { + return YES; +} @end diff --git a/DashSync/shared/Models/Network/DSPeer.h b/DashSync/shared/Models/Network/DSPeer.h index 9b6fa7a6..0a96dffc 100644 --- a/DashSync/shared/Models/Network/DSPeer.h +++ b/DashSync/shared/Models/Network/DSPeer.h @@ -271,6 +271,7 @@ typedef NS_ENUM(NSInteger, DSPeerType) @property (nonatomic, readonly, weak) id sporkDelegate; @property (nonatomic, readonly, weak) id masternodeDelegate; @property (nonatomic, readonly, weak) id peerChainDelegate; +// it's actually the chain networking queue @property (nonatomic, readonly) dispatch_queue_t delegateQueue; // set this to the timestamp when the wallet was created to improve initial sync time (interval since reference date) @@ -313,7 +314,7 @@ typedef NS_ENUM(NSInteger, DSPeerType) - (instancetype)initWithAddress:(UInt128)address port:(uint16_t)port onChain:(DSChain *)chain timestamp:(NSTimeInterval)timestamp services:(uint64_t)services; - (instancetype)initWithHost:(NSString *)host onChain:(DSChain *)chain; -- (void)setChainDelegate:(id)chainDelegate peerDelegate:(id)peerDelegate transactionDelegate:(id)transactionDelegate governanceDelegate:(id)governanceDelegate sporkDelegate:(id)sporkDelegate masternodeDelegate:(id)masternodeDelegate queue:(dispatch_queue_t)delegateQueue; +- (void)setChainDelegate:(id)chainDelegate peerDelegate:(id)peerDelegate transactionDelegate:(id)transactionDelegate governanceDelegate:(id)governanceDelegate sporkDelegate:(id)sporkDelegate masternodeDelegate:(id)masternodeDelegate; - (void)connect; - (void)disconnect; - (void)disconnectWithError:(NSError *_Nullable)error; diff --git a/DashSync/shared/Models/Network/DSPeer.m b/DashSync/shared/Models/Network/DSPeer.m index 49c06ebb..631c549e 100644 --- a/DashSync/shared/Models/Network/DSPeer.m +++ b/DashSync/shared/Models/Network/DSPeer.m @@ -195,7 +195,12 @@ - (void)dealloc { [NSObject cancelPreviousPerformRequestsWithTarget:self]; } -- (void)setChainDelegate:(id)chainDelegate peerDelegate:(id)peerDelegate transactionDelegate:(id)transactionDelegate governanceDelegate:(id)governanceDelegate sporkDelegate:(id)sporkDelegate masternodeDelegate:(id)masternodeDelegate queue:(dispatch_queue_t)delegateQueue { +- (void)setChainDelegate:(id)chainDelegate + peerDelegate:(id)peerDelegate + transactionDelegate:(id)transactionDelegate + governanceDelegate:(id)governanceDelegate + sporkDelegate:(id)sporkDelegate + masternodeDelegate:(id)masternodeDelegate { _peerChainDelegate = chainDelegate; _peerDelegate = peerDelegate; _transactionDelegate = transactionDelegate; @@ -203,7 +208,7 @@ - (void)setChainDelegate:(id)chainDelegate peerDelegate:(id _sporkDelegate = sporkDelegate; _masternodeDelegate = masternodeDelegate; - _delegateQueue = (delegateQueue) ? delegateQueue : dispatch_get_main_queue(); + _delegateQueue = self.chain.networkingQueue; } - (NSString *)location { @@ -562,7 +567,8 @@ - (void)mempoolTimeout { // are generated and local peer sends filterload with an updated bloom filter // - after filterload is sent, getdata is sent to re-request recent blocks that may contain new tx matching the filter -- (void)sendGetheadersMessageWithLocators:(NSArray *)locators andHashStop:(UInt256)hashStop { +- (void)sendGetheadersMessageWithLocators:(NSArray *)locators + andHashStop:(UInt256)hashStop { DSGetHeadersRequest *request = [DSGetHeadersRequest requestWithLocators:locators andHashStop:hashStop protocolVersion:self.chain.protocolVersion]; if (self.relayStartTime == 0) self.relayStartTime = [NSDate timeIntervalSince1970]; @@ -936,9 +942,11 @@ - (void)acceptAddrMessage:(NSData *)message { NSTimeInterval timestamp = [message UInt32AtOffset:off]; uint64_t services = [message UInt64AtOffset:off + sizeof(uint32_t)]; UInt128 address = *(UInt128 *)((const uint8_t *)message.bytes + off + sizeof(uint32_t) + sizeof(uint64_t)); - uint16_t port = CFSwapInt16BigToHost(*(const uint16_t *)((const uint8_t *)message.bytes + off + - sizeof(uint32_t) + sizeof(uint64_t) + - sizeof(UInt128))); + + uint16_t rawPort; + memcpy(&rawPort, (const uint8_t *)message.bytes + off + sizeof(uint32_t) + sizeof(uint64_t) + sizeof(UInt128), sizeof(rawPort)); + uint16_t port = CFSwapInt16BigToHost(rawPort); + if (!(services & SERVICES_NODE_NETWORK)) continue; // skip peers that don't carry full blocks if (address.u64[0] != 0 || address.u32[2] != CFSwapInt32HostToBig(0xffff)) continue; // ignore IPv6 for now diff --git a/DashSync/shared/Models/Notifications/DSSyncState.h b/DashSync/shared/Models/Notifications/DSSyncState.h index 89882c36..ee34a17e 100644 --- a/DashSync/shared/Models/Notifications/DSSyncState.h +++ b/DashSync/shared/Models/Notifications/DSSyncState.h @@ -24,36 +24,89 @@ typedef NS_ENUM(uint16_t, DSSyncStateKind) { DSSyncStateKind_Chain = 0, DSSyncStateKind_Headers = 1, DSSyncStateKind_Masternodes = 2, -// DSSyncStateKind_Platofrm = 3, + DSSyncStateKind_Platform = 3, }; +typedef NS_ENUM(uint32_t, DSSyncStateExtKind) { + DSSyncStateExtKind_None = 1 << 0, + DSSyncStateExtKind_Peers = 1 << 1, + DSSyncStateExtKind_Governance = 1 << 2, + DSSyncStateExtKind_Mempool = 1 << 3, + DSSyncStateExtKind_Headers = 1 << 4, + DSSyncStateExtKind_Masternodes = 1 << 5, + DSSyncStateExtKind_Transactions = 1 << 6, + DSSyncStateExtKind_CoinJoin = 1 << 7, + DSSyncStateExtKind_Platform = 1 << 8, +}; + +typedef NS_ENUM(uint16_t, DSPlatformSyncStateKind) { + DSPlatformSyncStateKind_None = 1 << 0, + DSPlatformSyncStateKind_KeyHashes = 1 << 1, + DSPlatformSyncStateKind_Unsynced = 1 << 2, +}; + +typedef NS_ENUM(uint16_t, DSPeersSyncStateKind) { + DSPeersSyncStateKind_None = 1 << 0, + DSPeersSyncStateKind_Selection = 1 << 1, + DSPeersSyncStateKind_Connecting = 1 << 2, +}; + +typedef NS_ENUM(uint16_t, DSMasternodeListSyncStateKind) { + DSMasternodeListSyncStateKind_None = 1 << 0, + DSMasternodeListSyncStateKind_Checkpoints = 1 << 1, + DSMasternodeListSyncStateKind_Diffs = 1 << 2, + DSMasternodeListSyncStateKind_QrInfo = 1 << 3, + DSMasternodeListSyncStateKind_Quorums = 1 << 4, +}; + +NSString * DSSyncStateExtKindDescription(DSSyncStateExtKind kind); +NSString * DSPeersSyncStateKindDescription(DSPeersSyncStateKind kind); +NSString * DSPlatformSyncStateKindDescription(DSPlatformSyncStateKind kind); +NSString * DSMasternodeListSyncStateKindDescription(DSMasternodeListSyncStateKind kind); @interface DSMasternodeListSyncState : NSObject -@property (nonatomic, assign) uint32_t retrievalQueueCount; -@property (nonatomic, assign) uint32_t retrievalQueueMaxAmount; -@property (nonatomic, assign) double storedCount; -@property (nonatomic, assign) double stubCount; -@property (nonatomic, assign) uint32_t lastBlockHeight; +@property (nonatomic, assign) uint32_t queueCount; +@property (nonatomic, assign) uint32_t queueMaxAmount; +@property (nonatomic, assign) uint32_t storedCount; +@property (nonatomic, assign) uint32_t lastListHeight; +@property (nonatomic, assign) uint32_t estimatedBlockHeight; +@property (nonatomic, readonly) DSMasternodeListSyncStateKind kind; + +- (void)addSyncKind:(DSMasternodeListSyncStateKind)kind; +- (void)removeSyncKind:(DSMasternodeListSyncStateKind)kind; +- (void)resetSyncKind; - (void)updateWithSyncState:(DMNSyncState *)state; @end -//@interface DSPlatformSyncState : NSObject -// -//@property (nonatomic, assign) uint32_t retrievalQueueCount; -//@property (nonatomic, assign) uint32_t retrievalQueueMaxAmount; -//@property (nonatomic, assign) double storedCount; -//@property (nonatomic, assign) double stubCount; -// -//@end +@interface DSPlatformSyncState : NSObject +@property (nonatomic, assign) uint32_t queueCount; +@property (nonatomic, assign) uint32_t queueMaxAmount; +@property (nonatomic, assign) NSTimeInterval lastSyncedIndentitiesTimestamp; +@property (nonatomic, readonly) DSPlatformSyncStateKind kind; +/*! @brief Returns if we synced identities in the last 30 seconds. */ +@property (nonatomic, readonly) BOOL hasRecentIdentitiesSync; +- (void)addSyncKind:(DSPlatformSyncStateKind)kind; +- (void)removeSyncKind:(DSPlatformSyncStateKind)kind; +- (void)resetSyncKind; -@interface DSSyncState : NSObject +@end -@property (nonatomic, assign) DSChainSyncPhase syncPhase; +@interface DSPeersSyncState : NSObject +@property (nonatomic, readonly) DSPeersSyncStateKind kind; @property (nonatomic, assign) BOOL hasDownloadPeer; @property (nonatomic, assign) BOOL peerManagerConnected; +- (void)addSyncKind:(DSPeersSyncStateKind)kind; +- (void)removeSyncKind:(DSPeersSyncStateKind)kind; +- (void)resetSyncKind; +@end + +@interface DSSyncState : NSObject + +@property (nonatomic, assign) DSChainSyncPhase syncPhase; +@property (nonatomic, readonly) DSSyncStateExtKind extKind; @property (nonatomic, assign) uint32_t estimatedBlockHeight; @@ -63,19 +116,32 @@ typedef NS_ENUM(uint16_t, DSSyncStateKind) { @property (nonatomic, assign) uint32_t lastTerminalBlockHeight; @property (nonatomic, assign) uint32_t terminalSyncStartHeight; @property (nonatomic, strong) DSMasternodeListSyncState *masternodeListSyncInfo; +@property (nonatomic, strong) DSPlatformSyncState *platformSyncInfo; +@property (nonatomic, strong) DSPeersSyncState *peersSyncInfo; // MARK: Read-only @property (nonatomic, readonly) double masternodeListProgress; @property (nonatomic, readonly) double chainSyncProgress; @property (nonatomic, readonly) double terminalHeaderSyncProgress; -@property (nonatomic, readonly) double combinedSyncProgress; +@property (nonatomic, readonly) double progress; @property (nonatomic, readonly) DSSyncStateKind kind; // MARK: Constructor - (instancetype)initWithSyncPhase:(DSChainSyncPhase)phase; +// MARK: Description + +- (NSString *)peersDescription; +- (NSString *)chainDescription; +- (NSString *)headersDescription; +- (NSString *)masternodesDescription; +- (NSString *)platformDescription; + +- (void)addSyncKind:(DSSyncStateExtKind)kind; +- (void)removeSyncKind:(DSSyncStateExtKind)kind; +- (void)resetSyncKind; @end NS_ASSUME_NONNULL_END diff --git a/DashSync/shared/Models/Notifications/DSSyncState.m b/DashSync/shared/Models/Notifications/DSSyncState.m index a1aa09c8..0e635c4b 100644 --- a/DashSync/shared/Models/Notifications/DSSyncState.m +++ b/DashSync/shared/Models/Notifications/DSSyncState.m @@ -18,37 +18,144 @@ #import "DSOptionsManager.h" #import "DSSyncState.h" +NSString * DSSyncStateExtKindDescription(DSSyncStateExtKind kind) { + NSMutableArray *components = [NSMutableArray array]; + if (FLAG_IS_SET(kind, DSSyncStateExtKind_Peers)) + [components addObject:@"Peers"]; + if (FLAG_IS_SET(kind, DSSyncStateExtKind_Governance)) + [components addObject:@"Governance"]; + if (FLAG_IS_SET(kind, DSSyncStateExtKind_Mempool)) + [components addObject:@"Mempool"]; + if (FLAG_IS_SET(kind, DSSyncStateExtKind_Headers)) + [components addObject:@"Headers"]; + if (FLAG_IS_SET(kind, DSSyncStateExtKind_Masternodes)) + [components addObject:@"Masternodes"]; + if (FLAG_IS_SET(kind, DSSyncStateExtKind_Transactions)) + [components addObject:@"Transactions"]; + if (FLAG_IS_SET(kind, DSSyncStateExtKind_CoinJoin)) + [components addObject:@"CoinJoin"]; + if (FLAG_IS_SET(kind, DSSyncStateExtKind_Platform)) + [components addObject:@"Platform"]; + return [components count] ? [components componentsJoinedByString:@" | "] : @"None"; +} + +NSString * DSPlatformSyncStateKindDescription(DSPlatformSyncStateKind kind) { + NSMutableArray *components = [NSMutableArray array]; + if (FLAG_IS_SET(kind, DSPlatformSyncStateKind_KeyHashes)) + [components addObject:@"KeyHashes"]; + if (FLAG_IS_SET(kind, DSPlatformSyncStateKind_Unsynced)) + [components addObject:@"Unsynced"]; + return [components count] ? [components componentsJoinedByString:@" | "] : @"None"; +} + +NSString * DSPeersSyncStateKindDescription(DSPeersSyncStateKind kind) { + NSMutableArray *components = [NSMutableArray array]; + if (FLAG_IS_SET(kind, DSPeersSyncStateKind_Selection)) + [components addObject:@"Selection"]; + if (FLAG_IS_SET(kind, DSPeersSyncStateKind_Connecting)) + [components addObject:@"Connecting"]; + return [components count] ? [components componentsJoinedByString:@" | "] : @"None"; +} + +NSString * DSMasternodeListSyncStateKindDescription(DSMasternodeListSyncStateKind kind) { + NSMutableArray *components = [NSMutableArray array]; + if (FLAG_IS_SET(kind, DSMasternodeListSyncStateKind_Checkpoints)) + [components addObject:@"Checkpoints"]; + if (FLAG_IS_SET(kind, DSMasternodeListSyncStateKind_Diffs)) + [components addObject:@"Diffs"]; + if (FLAG_IS_SET(kind, DSMasternodeListSyncStateKind_QrInfo)) + [components addObject:@"QrInfo"]; + if (FLAG_IS_SET(kind, DSMasternodeListSyncStateKind_Quorums)) + [components addObject:@"Quorums"]; + + return [components count] ? [components componentsJoinedByString:@" | "] : @"None"; +} + +@interface DSMasternodeListSyncState () +@property (nonatomic, assign) DSMasternodeListSyncStateKind kind; +@end @implementation DSMasternodeListSyncState - (id)copyWithZone:(NSZone *)zone { DSMasternodeListSyncState *copy = [[[self class] alloc] init]; - copy.retrievalQueueCount = self.retrievalQueueCount; - copy.retrievalQueueMaxAmount = self.retrievalQueueMaxAmount; + copy.queueCount = self.queueCount; + copy.queueMaxAmount = self.queueMaxAmount; copy.storedCount = self.storedCount; - copy.lastBlockHeight = self.lastBlockHeight; - copy.stubCount = self.stubCount; + copy.lastListHeight = self.lastListHeight; + copy.estimatedBlockHeight = self.estimatedBlockHeight; + copy.kind = self.kind; return copy; } - (NSString *)description { - return [NSString stringWithFormat:@"%u/%u/%f/%f/%u", - self.retrievalQueueCount, - self.retrievalQueueMaxAmount, + return [NSString stringWithFormat:@"[%@: %u %u/%u %u/%u = %.2f/%.2f]", + DSMasternodeListSyncStateKindDescription(self.kind), + self.lastListHeight, + self.queueCount, + self.queueMaxAmount, self.storedCount, - self.stubCount, - self.lastBlockHeight]; + [self listsToSync], + [self progress], [self weight]]; +} +- (uint32_t)listsToSync { + uint32_t estimatedBlockHeight = self.estimatedBlockHeight; + uint32_t amountLeft = self.queueCount; + uint32_t lastMasternodeListHeight = self.lastListHeight; + uint32_t maxAmount = self.queueMaxAmount; + uint32_t storedCount = self.storedCount; + uint32_t masternodeListsToSync; + if (!([[DSOptionsManager sharedInstance] syncType] & DSSyncType_MasternodeList)) + masternodeListsToSync = 0; + else if (!maxAmount || storedCount <= 1) // 1 because there might be a default + masternodeListsToSync = (lastMasternodeListHeight == UINT32_MAX || estimatedBlockHeight < lastMasternodeListHeight) + ? 24 + : MIN(24, (uint32_t)ceil((estimatedBlockHeight - lastMasternodeListHeight) / 24.0f)); + else + masternodeListsToSync = amountLeft; + + return masternodeListsToSync; } + +- (double)progress { + uint32_t amountLeft = self.queueCount; + uint32_t maxAmount = self.queueMaxAmount; + uint32_t lastBlockHeight = self.lastListHeight; + uint32_t estimatedBlockHeight = self.estimatedBlockHeight; + return amountLeft ? MAX(MIN((maxAmount - amountLeft) / maxAmount, 1), 0) : lastBlockHeight != UINT32_MAX && estimatedBlockHeight != 0 && lastBlockHeight + 16 >= estimatedBlockHeight; +} + +- (double)weight { + uint32_t listsToSync = [self listsToSync]; + return listsToSync ? (200 + 20 * (listsToSync - 1)) : 0; +} + +- (void)addSyncKind:(DSMasternodeListSyncStateKind)kind { + if (!FLAG_IS_SET(_kind, kind)) { + _kind |= kind; + } +} + +- (void)removeSyncKind:(DSMasternodeListSyncStateKind)kind { + if (FLAG_IS_SET(_kind, kind)) { + _kind &= ~kind; + } +} + +- (void)resetSyncKind { + _kind = DSMasternodeListSyncStateKind_None; +} + - (void)updateWithSyncState:(DMNSyncState *)state { switch (state->tag) { case DMNSyncStateQueueChanged: - self.retrievalQueueCount = (uint32_t) state->queue_changed.count; - self.retrievalQueueMaxAmount = (uint32_t) state->queue_changed.max_amount; + self.queueCount = (uint32_t) state->queue_changed.count; + self.queueMaxAmount = (uint32_t) state->queue_changed.max_amount; break; case DMNSyncStateStoreChanged: self.storedCount = (uint32_t) state->store_changed.count; - self.lastBlockHeight = state->store_changed.last_block_height; + self.lastListHeight = state->store_changed.last_block_height; break; - case DMNSyncStateStubCount: - self.stubCount = state->stub_count.count; +// case DMNSyncStateStubCount: +// self.stubCount = state->stub_count.count; default: break; } @@ -56,61 +163,187 @@ - (void)updateWithSyncState:(DMNSyncState *)state { @end +@interface DSPlatformSyncState () +@property (nonatomic, assign) DSPlatformSyncStateKind kind; +@end + +@implementation DSPlatformSyncState +- (id)copyWithZone:(NSZone *)zone { + DSPlatformSyncState *copy = [[[self class] alloc] init]; + copy.kind = self.kind; + copy.queueCount = self.queueCount; + copy.queueMaxAmount = self.queueMaxAmount; + copy.lastSyncedIndentitiesTimestamp = self.lastSyncedIndentitiesTimestamp; + return copy; +} +- (void)addSyncKind:(DSPlatformSyncStateKind)kind { + if (!FLAG_IS_SET(self.kind, kind)) + _kind |= kind; +} + +- (void)removeSyncKind:(DSPlatformSyncStateKind)kind { + if (FLAG_IS_SET(self.kind, kind)) + _kind &= ~kind; +} +- (void)resetSyncKind { + _kind = DSPlatformSyncStateKind_None; +} + +- (BOOL)hasRecentIdentitiesSync { + return [[NSDate date] timeIntervalSince1970] - self.lastSyncedIndentitiesTimestamp < 30; +} + +- (double)progress { + uint32_t amountLeft = self.queueCount; + uint32_t maxAmount = self.queueMaxAmount; + return amountLeft && maxAmount ? MAX(MIN((maxAmount - amountLeft) / maxAmount, 1), 0) : [self hasRecentIdentitiesSync]; +} + +- (double)weight { + uint32_t identitiesToSync = self.queueMaxAmount; + BOOL outdated = ![self hasRecentIdentitiesSync]; + return identitiesToSync ? (20000 + 2000 * (identitiesToSync - 1)) : outdated; +} + +- (NSString *)description { + return [NSString stringWithFormat:@"[%@: %f %u/%u = %.2f/%.2f]", DSPlatformSyncStateKindDescription(self.kind), self.lastSyncedIndentitiesTimestamp, self.queueCount, self.queueMaxAmount, [self progress], [self weight]]; +} + +@end +@interface DSPeersSyncState () +@property (nonatomic, assign) DSPeersSyncStateKind kind; +@end + +@implementation DSPeersSyncState +- (id)copyWithZone:(NSZone *)zone { + DSPeersSyncState *copy = [[[self class] alloc] init]; + copy.kind = self.kind; + copy.hasDownloadPeer = self.hasDownloadPeer; + copy.peerManagerConnected = self.peerManagerConnected; + return copy; +} +- (double)progress { + return self.peerManagerConnected && self.hasDownloadPeer ? 1 : 0; +} + +- (void)addSyncKind:(DSPeersSyncStateKind)kind { + if (!FLAG_IS_SET(self.kind, kind)) + _kind |= kind; +} + +- (void)removeSyncKind:(DSPeersSyncStateKind)kind { + if (FLAG_IS_SET(self.kind, kind)) + _kind &= ~kind; +} +- (void)resetSyncKind { + _kind = DSPeersSyncStateKind_None; +} + +- (NSString *)description { + return [NSString stringWithFormat:@"[%@: %u/%u]", + DSPeersSyncStateKindDescription(self.kind), + self.hasDownloadPeer, + self.peerManagerConnected]; +} + +@end + +@interface DSSyncState () +@property (nonatomic, assign) DSSyncStateExtKind extKind; +@end + @implementation DSSyncState - (instancetype)initWithSyncPhase:(DSChainSyncPhase)phase { if (!(self = [super init])) return nil; self.syncPhase = phase; + self.extKind = DSSyncStateExtKind_None; self.masternodeListSyncInfo = [[DSMasternodeListSyncState alloc] init]; + self.platformSyncInfo = [[DSPlatformSyncState alloc] init]; + self.peersSyncInfo = [[DSPeersSyncState alloc] init]; return self; } - (id)copyWithZone:(NSZone *)zone { DSSyncState *copy = [[[self class] alloc] init]; copy.syncPhase = self.syncPhase; - copy.hasDownloadPeer = self.hasDownloadPeer; - copy.peerManagerConnected = self.peerManagerConnected; + copy.extKind = self.extKind; copy.estimatedBlockHeight = self.estimatedBlockHeight; copy.chainSyncStartHeight = self.chainSyncStartHeight; copy.lastSyncBlockHeight = self.lastSyncBlockHeight; copy.terminalSyncStartHeight = self.terminalSyncStartHeight; copy.lastTerminalBlockHeight = self.lastTerminalBlockHeight; copy.masternodeListSyncInfo = [self.masternodeListSyncInfo copy]; + copy.platformSyncInfo = [self.platformSyncInfo copy]; + copy.peersSyncInfo = [self.peersSyncInfo copy]; return copy; } +- (void)addSyncKind:(DSSyncStateExtKind)kind { + if (!FLAG_IS_SET(self.extKind, kind)) + _extKind |= kind; +} + +- (void)removeSyncKind:(DSSyncStateExtKind)kind { + if (FLAG_IS_SET(self.extKind, kind)) + _extKind &= ~kind; +} +- (void)resetSyncKind { + _extKind = DSSyncStateExtKind_None; +} + - (NSString *)description { - return [NSString stringWithFormat:@"SyncState: { phase: %u, peer: %u, connected: %u, estimated: %u, chain: [%u/%u/%f] headers: [%u/%u/%f], mn: [%@/%u/%f] == %f", + return [NSString stringWithFormat:@"{ phase: %u, kind: %u, %@, estimated: %u, %@, %@, %@, %@ == %f }", self.syncPhase, - self.hasDownloadPeer, - self.peerManagerConnected, + self.extKind, + self.peersDescription, self.estimatedBlockHeight, - self.chainSyncStartHeight, - self.lastSyncBlockHeight, - self.chainSyncProgress, - self.terminalSyncStartHeight, - self.lastTerminalBlockHeight, - self.terminalHeaderSyncProgress, - self.masternodeListSyncInfo, - self.masternodeListsToSync, - self.masternodeListProgress, - self.combinedSyncProgress + self.chainDescription, + self.headersDescription, + self.masternodesDescription, + self.platformDescription, + [self progress] ]; } +- (NSString *)chainDescription { + return [NSString stringWithFormat:@"chain: [%u/%u = %.2f/%.2f]", self.chainSyncStartHeight, self.lastSyncBlockHeight, self.chainSyncProgress, self.chainSyncWeight]; +} + +- (NSString *)headersDescription { + return [NSString stringWithFormat:@"headers: [%u/%u = %.2f/%.2f]", self.terminalSyncStartHeight, self.lastTerminalBlockHeight, self.terminalHeaderSyncProgress, self.headersSyncWeight]; +} + +- (NSString *)peersDescription { + return [NSString stringWithFormat:@"peers: %@", self.peersSyncInfo]; +} + +- (NSString *)masternodesDescription { + return [NSString stringWithFormat:@"mn: %@", self.masternodeListSyncInfo]; +} + +- (NSString *)platformDescription { + return [NSString stringWithFormat:@"evo: %@", self.platformSyncInfo]; +} + - (double)masternodeListProgress { - uint32_t amountLeft = self.masternodeListSyncInfo.retrievalQueueCount; - uint32_t maxAmount = self.masternodeListSyncInfo.retrievalQueueMaxAmount; - uint32_t lastBlockHeight = self.masternodeListSyncInfo.lastBlockHeight; - uint32_t estimatedBlockHeight = self.estimatedBlockHeight; - return amountLeft ? MAX(MIN((maxAmount - amountLeft) / maxAmount, 1), 0) : lastBlockHeight != UINT32_MAX && estimatedBlockHeight != 0 && lastBlockHeight + 16 >= estimatedBlockHeight; + return [self.masternodeListSyncInfo progress]; +} + +- (double)platformProgress { + return [self.platformSyncInfo progress]; +} + +- (void)setEstimatedBlockHeight:(uint32_t)estimatedBlockHeight { + _estimatedBlockHeight = estimatedBlockHeight; + self.masternodeListSyncInfo.estimatedBlockHeight = estimatedBlockHeight; } - (double)chainSyncProgress { uint32_t chainSyncStartHeight = self.chainSyncStartHeight; uint32_t lastSyncBlockHeight = self.lastSyncBlockHeight; uint32_t estimatedBlockHeight = self.estimatedBlockHeight; - if (!self.hasDownloadPeer && chainSyncStartHeight == 0) + if (!self.peersSyncInfo.hasDownloadPeer && chainSyncStartHeight == 0) return 0.0; else if (lastSyncBlockHeight >= estimatedBlockHeight) return 1.0; @@ -126,7 +359,7 @@ - (double)terminalHeaderSyncProgress { uint32_t terminalSyncStartHeight = self.terminalSyncStartHeight; uint32_t lastTerminalBlockHeight = self.lastTerminalBlockHeight; uint32_t estimatedBlockHeight = self.estimatedBlockHeight; - if (!self.hasDownloadPeer && terminalSyncStartHeight == 0) + if (!self.peersSyncInfo.hasDownloadPeer && terminalSyncStartHeight == 0) return 0.0; else if (lastTerminalBlockHeight >= estimatedBlockHeight) return 1.0; @@ -134,46 +367,35 @@ - (double)terminalHeaderSyncProgress { return MIN(1.0, MAX(0.0, 0.1 + 0.9 * (terminalSyncStartHeight > lastTerminalBlockHeight ? lastTerminalBlockHeight / estimatedBlockHeight : (lastTerminalBlockHeight - terminalSyncStartHeight) / (estimatedBlockHeight - terminalSyncStartHeight)))); } -- (uint32_t)masternodeListsToSync { - uint32_t estimatedBlockHeight = self.estimatedBlockHeight; - uint32_t amountLeft = self.masternodeListSyncInfo.retrievalQueueCount; - uint32_t lastMasternodeListHeight = self.masternodeListSyncInfo.lastBlockHeight; - uint32_t maxAmount = self.masternodeListSyncInfo.retrievalQueueMaxAmount; - uint32_t storedCount = self.masternodeListSyncInfo.storedCount; - uint32_t masternodeListsToSync; - if (!([[DSOptionsManager sharedInstance] syncType] & DSSyncType_MasternodeList)) - masternodeListsToSync = 0; - else if (!maxAmount || storedCount <= 1) // 1 because there might be a default - masternodeListsToSync = (lastMasternodeListHeight == UINT32_MAX || estimatedBlockHeight < lastMasternodeListHeight) - ? 32 - : MIN(32, (uint32_t)ceil((estimatedBlockHeight - lastMasternodeListHeight) / 24.0f)); - else - masternodeListsToSync = amountLeft; - - return masternodeListsToSync; +- (double)chainSyncWeight { + double weight = self.lastSyncBlockHeight >= self.estimatedBlockHeight ? 0 : self.estimatedBlockHeight - self.lastSyncBlockHeight; + return weight; } +- (double)headersSyncWeight { + double weight = self.lastTerminalBlockHeight >= self.estimatedBlockHeight ? 0 : (self.estimatedBlockHeight - self.lastTerminalBlockHeight) / 4; + return weight; +} + /** * A unit of weight is the time it would take to sync 1000 blocks; * terminal headers are 4 times faster the blocks * the first masternode list is worth 20000 blocks * each masternode list after that is worth 2000 blocks */ -- (double)combinedSyncProgress { - uint32_t estimatedBlockHeight = self.estimatedBlockHeight; - uint32_t lastTerminalBlockHeight = self.lastTerminalBlockHeight; - uint32_t lastSyncBlockHeight = self.lastSyncBlockHeight; - double chainWeight = lastSyncBlockHeight >= estimatedBlockHeight ? 0 : estimatedBlockHeight - lastSyncBlockHeight; - double terminalWeight = lastTerminalBlockHeight >= estimatedBlockHeight ? 0 : (estimatedBlockHeight - lastTerminalBlockHeight) / 4; - uint32_t listsToSync = [self masternodeListsToSync]; - double masternodeWeight = listsToSync ? (20000 + 2000 * (listsToSync - 1)) : 0; - double totalWeight = chainWeight + terminalWeight + masternodeWeight; +- (double)progress { + double chainWeight = [self chainSyncWeight]; + double terminalWeight = [self headersSyncWeight]; + double platformWeight = [self.platformSyncInfo weight]; + double masternodeWeight = [self.masternodeListSyncInfo weight]; + double totalWeight = chainWeight + terminalWeight + masternodeWeight + platformWeight; if (totalWeight == 0) { - return self.peerManagerConnected && self.hasDownloadPeer ? 1 : 0; + return [self.peersSyncInfo progress]; } else { double terminalProgress = self.terminalHeaderSyncProgress * (terminalWeight / totalWeight); double chainProgress = self.chainSyncProgress * (chainWeight / totalWeight); double masternodesProgress = self.masternodeListProgress * (masternodeWeight / totalWeight); - double progress = terminalProgress + masternodesProgress + chainProgress; + double platformProgress = self.platformProgress * (platformWeight / totalWeight); + double progress = terminalProgress + masternodesProgress + chainProgress + platformProgress; if (progress < 0.99995) { return progress; } else { @@ -196,14 +418,14 @@ - (DSSyncStateKind)kind { - (BOOL)atTheEndOfSyncBlocksAndSyncingMasternodeList { // We give a 6 block window, just in case a new block comes in return self.lastSyncBlockHeight + 6 >= self.estimatedBlockHeight - && self.masternodeListSyncInfo.retrievalQueueCount > 0 + && self.masternodeListSyncInfo.queueCount > 0 && self.syncPhase == DSChainSyncPhase_Synced; } - (BOOL)atTheEndOfInitialTerminalBlocksAndSyncingMasternodeList { // We give a 6 block window, just in case a new block comes in return self.lastTerminalBlockHeight + 6 >= self.estimatedBlockHeight - && self.masternodeListSyncInfo.retrievalQueueCount > 0 + && self.masternodeListSyncInfo.queueCount > 0 && self.syncPhase == DSChainSyncPhase_InitialTerminalBlocks; } diff --git a/DashSync/shared/Models/Transactions/Base/DSAssetLockTransaction.h b/DashSync/shared/Models/Transactions/Base/DSAssetLockTransaction.h index de2946e6..7616fde5 100644 --- a/DashSync/shared/Models/Transactions/Base/DSAssetLockTransaction.h +++ b/DashSync/shared/Models/Transactions/Base/DSAssetLockTransaction.h @@ -25,6 +25,7 @@ NS_ASSUME_NONNULL_BEGIN @property (nonatomic, assign) uint8_t specialTransactionVersion; @property (nonatomic, strong) NSMutableArray *creditOutputs; +@property (nonatomic, readonly) UInt256 creditBurnIdentityIdentifier; @property (nonatomic, readonly) UInt160 creditBurnPublicKeyHash; @property (nonatomic, readonly) DSUTXO lockedOutpoint; diff --git a/DashSync/shared/Models/Transactions/Base/DSAssetLockTransaction.m b/DashSync/shared/Models/Transactions/Base/DSAssetLockTransaction.m index dcda82a0..e52eccdf 100644 --- a/DashSync/shared/Models/Transactions/Base/DSAssetLockTransaction.m +++ b/DashSync/shared/Models/Transactions/Base/DSAssetLockTransaction.m @@ -119,15 +119,15 @@ - (NSData *)basePayloadData { return data; } - -- (NSData *)toDataWithSubscriptIndex:(NSUInteger)subscriptIndex anyoneCanPay:(BOOL)anyoneCanPay { +- (NSData *)toDataWithOptions:(DSTransactionOptions *)options { @synchronized(self) { - NSMutableData *data = [[super toDataWithSubscriptIndex:subscriptIndex anyoneCanPay:anyoneCanPay] mutableCopy]; + NSMutableData *data = [[super toDataWithOptions:options] mutableCopy]; [data appendCountedData:[self payloadData]]; - if (subscriptIndex != NSNotFound) [data appendUInt32:SIGHASH_ALL]; + if (options.subscriptIndex != NSNotFound) [data appendUInt32:SIGHASH_ALL]; return data; } } + - (size_t)size { @synchronized(self) { if (uint256_is_not_zero(self.txHash)) return self.data.length; diff --git a/DashSync/shared/Models/Transactions/Base/DSAssetUnlockTransaction.m b/DashSync/shared/Models/Transactions/Base/DSAssetUnlockTransaction.m index ad2d582b..8ec89818 100644 --- a/DashSync/shared/Models/Transactions/Base/DSAssetUnlockTransaction.m +++ b/DashSync/shared/Models/Transactions/Base/DSAssetUnlockTransaction.m @@ -90,11 +90,11 @@ - (NSData *)basePayloadData { return data; } -- (NSData *)toDataWithSubscriptIndex:(NSUInteger)subscriptIndex anyoneCanPay:(BOOL)anyoneCanPay { +- (NSData *)toDataWithOptions:(DSTransactionOptions *)options { @synchronized(self) { - NSMutableData *data = [[super toDataWithSubscriptIndex:subscriptIndex anyoneCanPay:anyoneCanPay] mutableCopy]; + NSMutableData *data = [[super toDataWithOptions:options] mutableCopy]; [data appendCountedData:[self payloadData]]; - if (subscriptIndex != NSNotFound) [data appendUInt32:SIGHASH_ALL]; + if (options.subscriptIndex != NSNotFound) [data appendUInt32:SIGHASH_ALL]; return data; } } diff --git a/DashSync/shared/Models/Transactions/Base/DSTransaction.h b/DashSync/shared/Models/Transactions/Base/DSTransaction.h index 595a8f9e..c2fd4cce 100644 --- a/DashSync/shared/Models/Transactions/Base/DSTransaction.h +++ b/DashSync/shared/Models/Transactions/Base/DSTransaction.h @@ -77,6 +77,16 @@ typedef NS_ENUM(NSUInteger, DSTransactionDirection) DSTransactionDirection_NotAccountFunds, }; +@interface DSTransactionOptions : NSObject +@property (nonatomic, assign) BOOL anyoneCanPay; +@property (nonatomic, assign) NSUInteger subscriptIndex; ++ (instancetype)default; ++ (instancetype)withAnyoneCanPay:(BOOL)anyoneCanPay; ++ (instancetype)withSubscriptIndex:(NSUInteger)subscriptIndex; ++ (instancetype)withSubscriptIndex:(NSUInteger)subscriptIndex + anyoneCanPay:(BOOL)anyoneCanPay; +@end + @interface DSTransaction : NSObject @property (nonatomic, readonly) NSArray *inputs; @@ -118,7 +128,6 @@ typedef NS_ENUM(NSUInteger, DSTransactionDirection) @property (nonatomic, readonly) NSString *longDescription; @property (nonatomic, readonly) BOOL isCoinbaseClassicTransaction; @property (nonatomic, readonly) BOOL isImmatureCoinBase; -@property (nonatomic, readonly) UInt256 creditBurnIdentityIdentifier; @property (nonatomic, strong) DSShapeshiftEntity *associatedShapeshift; @property (nonatomic, readonly) DSChain *chain; @@ -167,7 +176,7 @@ typedef NS_ENUM(NSUInteger, DSTransactionDirection) // priority = sum(input_amount_in_satoshis*input_age_in_blocks)/tx_size_in_bytes - (uint64_t)priorityForAmounts:(NSArray *)amounts withAges:(NSArray *)ages; -- (NSData *)toDataWithSubscriptIndex:(NSUInteger)subscriptIndex anyoneCanPay:(BOOL)anyoneCanPay; +- (NSData *)toDataWithOptions:(DSTransactionOptions *)options; - (BOOL)hasNonDustOutputInWallet:(DSWallet *)wallet; diff --git a/DashSync/shared/Models/Transactions/Base/DSTransaction.m b/DashSync/shared/Models/Transactions/Base/DSTransaction.m index 037676c5..5cb8dcd5 100644 --- a/DashSync/shared/Models/Transactions/Base/DSTransaction.m +++ b/DashSync/shared/Models/Transactions/Base/DSTransaction.m @@ -52,6 +52,31 @@ #import "NSString+Bitcoin.h" #import "NSString+Dash.h" +@implementation DSTransactionOptions : NSObject ++ (nonnull instancetype)default { + return [DSTransactionOptions withSubscriptIndex:NSNotFound anyoneCanPay:NO]; +} ++ (nonnull instancetype)withAnyoneCanPay:(BOOL)anyoneCanPay { + return [DSTransactionOptions withSubscriptIndex:NSNotFound anyoneCanPay:anyoneCanPay]; +} ++ (nonnull instancetype)withSubscriptIndex:(NSUInteger)subscriptIndex { + return [DSTransactionOptions withSubscriptIndex:subscriptIndex anyoneCanPay:NO]; +} ++ (instancetype)withSubscriptIndex:(NSUInteger)subscriptIndex + anyoneCanPay:(BOOL)anyoneCanPay { + DSTransactionOptions *options = [[self alloc] init]; + if (options) { + options.subscriptIndex = subscriptIndex; + options.anyoneCanPay = anyoneCanPay; + } + return options; +} + + + +@end + + @interface DSTransaction () @property (nonatomic, strong) DSChain *chain; @@ -437,16 +462,18 @@ - (NSUInteger)hash { // MARK: - Wire Serialization - (NSData *)toData { - return [self toData:NO]; + return [self toDataWithOptions:[DSTransactionOptions default]]; } - (NSData *)toData:(BOOL)anyoneCanPay { - return [self toDataWithSubscriptIndex:NSNotFound anyoneCanPay:anyoneCanPay]; + return [self toDataWithOptions:[DSTransactionOptions withAnyoneCanPay:anyoneCanPay]]; } // Returns the binary transaction data that needs to be hashed and signed with the private key for the tx input at // subscriptIndex. A subscriptIndex of NSNotFound will return the entire signed transaction. -- (NSData *)toDataWithSubscriptIndex:(NSUInteger)subscriptIndex anyoneCanPay:(BOOL)anyoneCanPay { +- (NSData *)toDataWithOptions:(DSTransactionOptions *)options { + BOOL anyoneCanPay = options.anyoneCanPay; + NSUInteger subscriptIndex = options.subscriptIndex; @synchronized(self) { NSArray *inputs = self.inputs; NSArray *outputs = self.outputs; @@ -503,6 +530,7 @@ - (NSData *)toDataWithSubscriptIndex:(NSUInteger)subscriptIndex anyoneCanPay:(BO } } + // MARK: - Construction - (void)addInputHash:(UInt256)hash index:(NSUInteger)index script:(NSData *)script { @@ -649,7 +677,8 @@ - (BOOL)signWithPrivateKeys:(NSArray *)keys anyoneCanPay:(BOOL)anyoneCanPay { transactionInput.signature = [NSData data]; continue; } - NSData *data = [self toDataWithSubscriptIndex:i anyoneCanPay:anyoneCanPay]; + DSTransactionOptions *options = [DSTransactionOptions withSubscriptIndex:i anyoneCanPay:anyoneCanPay]; + NSData *data = [self toDataWithOptions:options]; uint8_t sighashFlags = SIGHASH_ALL; if (anyoneCanPay) { sighashFlags |= SIGHASH_ANYONECANPAY; @@ -660,7 +689,9 @@ - (BOOL)signWithPrivateKeys:(NSArray *)keys anyoneCanPay:(BOOL)anyoneCanPay { transactionInput.signature = sig; } if (!self.isSigned) return NO; - _txHash = self.data.SHA256_2; + // TODO: check if this is wrong +// _txHash = self.data.SHA256_2; + _txHash = [self toData:anyoneCanPay].SHA256_2; return YES; } } @@ -675,7 +706,8 @@ - (BOOL)signWithMaybePrivateKeySets:(NSArray *)keysSets anyoneCanPay:(BOOL)anyon if (maybe_opaque_keys->ok) { DOpaqueKey *opaque_key = DOpaqueKeyUsedInTxInputScript(bytes_ctor(inScript), maybe_opaque_keys->ok, self.chain.chainType); if (opaque_key) { - NSData *data = [self toDataWithSubscriptIndex:i anyoneCanPay:anyoneCanPay]; + DSTransactionOptions *options = [DSTransactionOptions withSubscriptIndex:i anyoneCanPay:anyoneCanPay]; + NSData *data = [self toDataWithOptions:options]; NSData *sig = [DSTransaction signInput:data flags:SIGHASH_ALL inputScript:inScript withOpaqueKey:opaque_key]; DOpaqueKeyDtor(opaque_key); transactionInput.signature = sig; @@ -694,7 +726,9 @@ - (BOOL)signWithPreorderedPrivateKeys:(NSArray *)keys { @synchronized (self) { for (NSUInteger i = 0; i < self.mInputs.count; i++) { DSTransactionInput *transactionInput = self.mInputs[i]; - NSData *sig = [DSTransaction signInput:[self toDataWithSubscriptIndex:i anyoneCanPay:NO] flags:SIGHASH_ALL inputScript:transactionInput.inScript withOpaqueKeyValue:keys[i]]; + DSTransactionOptions *options = [DSTransactionOptions withSubscriptIndex:i]; + NSData *data = [self toDataWithOptions:options]; + NSData *sig = [DSTransaction signInput:data flags:SIGHASH_ALL inputScript:transactionInput.inScript withOpaqueKeyValue:keys[i]]; transactionInput.signature = sig; } if (!self.isSigned) return NO; @@ -713,7 +747,7 @@ + (NSData *)signInput:(NSData *)data + (NSData *)signInput:(NSData *)data flags:(uint8_t)flags inputScript:(NSData *)inputScript - withOpaqueKey:(DOpaqueKey *)key { + withOpaqueKey:(DOpaqueKey *)key { Slice_u8 *input = slice_ctor(data); Vec_u8 *tx_input_script = bytes_ctor(inputScript); Vec_u8 *tx_sig = DOpaqueKeyCreateTxSig(key, input, flags, tx_input_script); @@ -766,15 +800,11 @@ - (BOOL)hasNonDustOutputInWallet:(DSWallet *)wallet { - (void)setInstantSendReceivedWithInstantSendLock:(DSInstantSendTransactionLock *)instantSendLock { self.instantSendReceived = instantSendLock.signatureVerified; - self.hasUnverifiedInstantSendLock = (instantSendLock && !instantSendLock.signatureVerified); - if (self.hasUnverifiedInstantSendLock) { - self.instantSendLockAwaitingProcessing = instantSendLock; - } else { - self.instantSendLockAwaitingProcessing = nil; - } - if (!instantSendLock.saved) { + BOOL hasUnverifiedISLock = instantSendLock && !instantSendLock.signatureVerified; + self.hasUnverifiedInstantSendLock = hasUnverifiedISLock; + self.instantSendLockAwaitingProcessing = hasUnverifiedISLock ? instantSendLock : nil; + if (!instantSendLock.saved) [instantSendLock saveInitial]; - } } - (uint32_t)confirmations { @@ -805,22 +835,13 @@ - (void)loadIdentitiesFromDerivationPaths:(NSArray *)derivat for (DSFundsDerivationPath *derivationPath in derivationPaths) { if ([derivationPath isKindOfClass:[DSIncomingFundsDerivationPath class]] && [derivationPath containsAddress:output.address]) { - DSIncomingFundsDerivationPath *incomingFundsDerivationPath = ((DSIncomingFundsDerivationPath *)derivationPath); - DSIdentity *destinationIdentity = [self.chain identityForUniqueId:incomingFundsDerivationPath.contactDestinationIdentityUniqueId - foundInWallet:nil - includeForeignIdentities:YES]; - - DSIdentity *sourceIdentity = [self.chain identityForUniqueId:incomingFundsDerivationPath.contactSourceIdentityUniqueId - foundInWallet:nil - includeForeignIdentities:YES]; - - - if (sourceIdentity) { + DSIncomingFundsDerivationPath *path = ((DSIncomingFundsDerivationPath *)derivationPath); + DSIdentity *destinationIdentity = [self.chain identityForUniqueId:path.contactDestinationIdentityUniqueId foundInWallet:nil includeForeignIdentities:YES]; + DSIdentity *sourceIdentity = [self.chain identityForUniqueId:path.contactSourceIdentityUniqueId foundInWallet:nil includeForeignIdentities:YES]; + if (sourceIdentity) [destinationIdentities addObject:sourceIdentity]; //these need to be inverted since the derivation path is incoming - } - if (destinationIdentity) { + if (destinationIdentity) [sourceIdentities addObject:destinationIdentity]; //these need to be inverted since the derivation path is incoming - } } } } diff --git a/DashSync/shared/Models/Transactions/Coinbase/DSCoinbaseTransaction.m b/DashSync/shared/Models/Transactions/Coinbase/DSCoinbaseTransaction.m index 40910729..b18ace69 100644 --- a/DashSync/shared/Models/Transactions/Coinbase/DSCoinbaseTransaction.m +++ b/DashSync/shared/Models/Transactions/Coinbase/DSCoinbaseTransaction.m @@ -105,10 +105,9 @@ - (NSData *)payloadData { // Returns the binary transaction data that needs to be hashed and signed with the private key for the tx input at // subscriptIndex. A subscriptIndex of NSNotFound will return the entire signed transaction. -- (NSData *)toDataWithSubscriptIndex:(NSUInteger)subscriptIndex - anyoneCanPay:(BOOL)anyoneCanPay { +- (NSData *)toDataWithOptions:(DSTransactionOptions *)options { @synchronized(self) { - NSMutableData *data = [[super toDataWithSubscriptIndex:subscriptIndex anyoneCanPay:anyoneCanPay] mutableCopy]; + NSMutableData *data = [[super toDataWithOptions:options] mutableCopy]; return [data appendCountedData:[self payloadData]]; } } diff --git a/DashSync/shared/Models/Transactions/DSTransactionFactory.m b/DashSync/shared/Models/Transactions/DSTransactionFactory.m index 1153a3cb..9c37cdb2 100644 --- a/DashSync/shared/Models/Transactions/DSTransactionFactory.m +++ b/DashSync/shared/Models/Transactions/DSTransactionFactory.m @@ -21,14 +21,14 @@ @implementation DSTransactionFactory + (DSTransactionType)transactionTypeOfMessage:(NSData *)message { uint16_t version = [message UInt16AtOffset:0]; - if (version < 3) return DSTransactionType_Classic; + if (version < SPECIAL_TX_VERSION) return DSTransactionType_Classic; return [message UInt16AtOffset:2]; } + (DSTransaction *)transactionWithMessage:(NSData *)message onChain:(DSChain *)chain { uint16_t version = [message UInt16AtOffset:0]; uint16_t type; - if (version < 3) { + if (version < SPECIAL_TX_VERSION) { type = DSTransactionType_Classic; } else { type = [message UInt16AtOffset:2]; diff --git a/DashSync/shared/Models/Transactions/Provider/DSProviderRegistrationTransaction.m b/DashSync/shared/Models/Transactions/Provider/DSProviderRegistrationTransaction.m index 6d499f77..fab6a26b 100644 --- a/DashSync/shared/Models/Transactions/Provider/DSProviderRegistrationTransaction.m +++ b/DashSync/shared/Models/Transactions/Provider/DSProviderRegistrationTransaction.m @@ -235,12 +235,11 @@ - (NSData *)payloadData { return data; } -- (NSData *)toDataWithSubscriptIndex:(NSUInteger)subscriptIndex - anyoneCanPay:(BOOL)anyoneCanPay { +- (NSData *)toDataWithOptions:(DSTransactionOptions *)options { @synchronized(self) { - NSMutableData *data = [[super toDataWithSubscriptIndex:subscriptIndex anyoneCanPay:anyoneCanPay] mutableCopy]; + NSMutableData *data = [[super toDataWithOptions:options] mutableCopy]; [data appendCountedData:[self payloadData]]; - if (subscriptIndex != NSNotFound) [data appendUInt32:SIGHASH_ALL]; + if (options.subscriptIndex != NSNotFound) [data appendUInt32:SIGHASH_ALL]; return data; } } diff --git a/DashSync/shared/Models/Transactions/Provider/DSProviderUpdateRegistrarTransaction.m b/DashSync/shared/Models/Transactions/Provider/DSProviderUpdateRegistrarTransaction.m index 604062d1..7602199e 100644 --- a/DashSync/shared/Models/Transactions/Provider/DSProviderUpdateRegistrarTransaction.m +++ b/DashSync/shared/Models/Transactions/Provider/DSProviderUpdateRegistrarTransaction.m @@ -196,14 +196,13 @@ - (NSData *)payloadData { return data; } -- (NSData *)toDataWithSubscriptIndex:(NSUInteger)subscriptIndex - anyoneCanPay:(BOOL)anyoneCanPay { +- (NSData *)toDataWithOptions:(DSTransactionOptions *)options { @synchronized(self) { - NSMutableData *data = [[super toDataWithSubscriptIndex:subscriptIndex anyoneCanPay:anyoneCanPay] mutableCopy]; + NSMutableData *data = [[super toDataWithOptions:options] mutableCopy]; NSData *payloadData = [self payloadData]; [data appendVarInt:payloadData.length]; [data appendData:payloadData]; - if (subscriptIndex != NSNotFound) [data appendUInt32:SIGHASH_ALL]; + if (options.subscriptIndex != NSNotFound) [data appendUInt32:SIGHASH_ALL]; return data; } } diff --git a/DashSync/shared/Models/Transactions/Provider/DSProviderUpdateRevocationTransaction.m b/DashSync/shared/Models/Transactions/Provider/DSProviderUpdateRevocationTransaction.m index eee818fe..6b3b8ebc 100644 --- a/DashSync/shared/Models/Transactions/Provider/DSProviderUpdateRevocationTransaction.m +++ b/DashSync/shared/Models/Transactions/Provider/DSProviderUpdateRevocationTransaction.m @@ -147,12 +147,11 @@ - (NSData *)payloadData { return data; } -- (NSData *)toDataWithSubscriptIndex:(NSUInteger)subscriptIndex - anyoneCanPay:(BOOL)anyoneCanPay { +- (NSData *)toDataWithOptions:(DSTransactionOptions *)options { @synchronized(self) { - NSMutableData *data = [[super toDataWithSubscriptIndex:subscriptIndex anyoneCanPay:anyoneCanPay] mutableCopy]; + NSMutableData *data = [[super toDataWithOptions:options] mutableCopy]; [data appendCountedData:[self payloadData]]; - if (subscriptIndex != NSNotFound) [data appendUInt32:SIGHASH_ALL]; + if (options.subscriptIndex != NSNotFound) [data appendUInt32:SIGHASH_ALL]; return data; } } diff --git a/DashSync/shared/Models/Transactions/Provider/DSProviderUpdateServiceTransaction.m b/DashSync/shared/Models/Transactions/Provider/DSProviderUpdateServiceTransaction.m index c3d39b1f..afdf0341 100644 --- a/DashSync/shared/Models/Transactions/Provider/DSProviderUpdateServiceTransaction.m +++ b/DashSync/shared/Models/Transactions/Provider/DSProviderUpdateServiceTransaction.m @@ -196,12 +196,11 @@ - (NSData *)payloadData { return data; } -- (NSData *)toDataWithSubscriptIndex:(NSUInteger)subscriptIndex - anyoneCanPay:(BOOL)anyoneCanPay { +- (NSData *)toDataWithOptions:(DSTransactionOptions *)options { @synchronized(self) { - NSMutableData *data = [[super toDataWithSubscriptIndex:subscriptIndex anyoneCanPay:anyoneCanPay] mutableCopy]; + NSMutableData *data = [[super toDataWithOptions:options] mutableCopy]; [data appendCountedData:[self payloadData]]; - if (subscriptIndex != NSNotFound) [data appendUInt32:SIGHASH_ALL]; + if (options.subscriptIndex != NSNotFound) [data appendUInt32:SIGHASH_ALL]; return data; } } diff --git a/DashSync/shared/Models/Transactions/Quorums/DSQuorumCommitmentTransaction.m b/DashSync/shared/Models/Transactions/Quorums/DSQuorumCommitmentTransaction.m index 500e09d9..b9f7fefc 100644 --- a/DashSync/shared/Models/Transactions/Quorums/DSQuorumCommitmentTransaction.m +++ b/DashSync/shared/Models/Transactions/Quorums/DSQuorumCommitmentTransaction.m @@ -132,12 +132,11 @@ - (NSData *)payloadData { return data; } -- (NSData *)toDataWithSubscriptIndex:(NSUInteger)subscriptIndex - anyoneCanPay:(BOOL)anyoneCanPay { +- (NSData *)toDataWithOptions:(DSTransactionOptions *)options { @synchronized(self) { - NSMutableData *data = [[super toDataWithSubscriptIndex:subscriptIndex anyoneCanPay:anyoneCanPay] mutableCopy]; + NSMutableData *data = [[super toDataWithOptions:options] mutableCopy]; [data appendCountedData:[self payloadData]]; - if (subscriptIndex != NSNotFound) [data appendUInt32:SIGHASH_ALL]; + if (options.subscriptIndex != NSNotFound) [data appendUInt32:SIGHASH_ALL]; return data; } } diff --git a/DashSync/shared/Models/Wallet/DSAccount.h b/DashSync/shared/Models/Wallet/DSAccount.h index 3bf196bc..5ff1c5a7 100644 --- a/DashSync/shared/Models/Wallet/DSAccount.h +++ b/DashSync/shared/Models/Wallet/DSAccount.h @@ -25,6 +25,7 @@ #import "DSAssetLockTransaction.h" #import "DSFundsDerivationPath.h" +#import "DSGapLimit.h" #import "DSIncomingFundsDerivationPath.h" #import "DSTransaction.h" #import "NSData+Dash.h" @@ -87,8 +88,7 @@ FOUNDATION_EXPORT NSString *_Nonnull const DSAccountNewAccountShouldBeAddedFromT // has an extended public key missing in one of the account derivation paths @property (nonatomic, readonly) BOOL hasAnExtendedPublicKeyMissing; -- (NSArray *_Nullable)registerAddressesWithInitialGapLimit; -- (NSArray *_Nullable)registerAddressesWithProlongGapLimit; +- (NSArray *)registerAddressesAtStage:(DSGapLimitStage)stage; + (DSAccount *)accountWithAccountNumber:(uint32_t)accountNumber withDerivationPaths:(NSArray *)derivationPaths @@ -212,6 +212,7 @@ FOUNDATION_EXPORT NSString *_Nonnull const DSAccountNewAccountShouldBeAddedFromT // true if the given transaction is associated with the account (even if it hasn't been registered), false otherwise - (BOOL)canContainTransaction:(DSTransaction *)transaction; //- (BOOL)canContainRustTransaction:(Result_ok_dashcore_blockdata_transaction_Transaction_err_dash_spv_platform_error_Error *)transaction; +- (BOOL)canContainTransactionIncludingCoinjoin:(DSTransaction *)transaction; // adds a transaction to the account, or returns false if it isn't associated with the account - (BOOL)registerTransaction:(DSTransaction *)transaction diff --git a/DashSync/shared/Models/Wallet/DSAccount.m b/DashSync/shared/Models/Wallet/DSAccount.m index a98ab42f..622a97a5 100644 --- a/DashSync/shared/Models/Wallet/DSAccount.m +++ b/DashSync/shared/Models/Wallet/DSAccount.m @@ -28,7 +28,6 @@ #import "DSChain+Params.h" #import "DSChain+Protected.h" #import "DSFundsDerivationPath.h" -#import "DSGapLimit.h" #import "DSWallet+Protected.h" #import "DSProviderRegistrationTransaction.h" @@ -304,8 +303,10 @@ - (void)loadDerivationPaths { [derivationPath loadAddresses]; } } + if (self.coinJoinDerivationPath && [self.coinJoinDerivationPath hasExtendedPublicKey]) + [self.coinJoinDerivationPath loadAddresses]; } else { - for (DSDerivationPath *derivationPath in self.fundDerivationPaths) { + for (DSFundsDerivationPath *derivationPath in self.fundDerivationPaths) { if ([derivationPath isKindOfClass:[DSIncomingFundsDerivationPath class]]) { [derivationPath registerAddressesWithSettings:[DSGapLimit withLimit:SEQUENCE_DASHPAY_GAP_LIMIT_INITIAL]]; } else { @@ -313,6 +314,10 @@ - (void)loadDerivationPaths { [derivationPath registerAddressesWithSettings:[DSGapLimitFunds external:SEQUENCE_GAP_LIMIT_INITIAL]]; } } + if (self.coinJoinDerivationPath) { + [self.coinJoinDerivationPath registerAddressesWithSettings:[DSGapLimitFunds internal:SEQUENCE_GAP_LIMIT_INITIAL_COINJOIN]]; + [self.coinJoinDerivationPath registerAddressesWithSettings:[DSGapLimitFunds external:SEQUENCE_GAP_LIMIT_INITIAL_COINJOIN]]; + } } if (!self.isViewOnlyAccount) { if (self.bip44DerivationPath && [self.bip44DerivationPath hasExtendedPublicKey]) { @@ -329,6 +334,7 @@ - (void)loadDerivationPaths { - (void)wipeBlockchainInfo { [self.mFundDerivationPaths removeObjectsInArray:[self.mContactIncomingFundDerivationPathsDictionary allValues]]; + self.coinJoinDerivationPath = nil; [self.mContactIncomingFundDerivationPathsDictionary removeAllObjects]; [self.mContactOutgoingFundDerivationPathsDictionary removeAllObjects]; [self.transactions removeAllObjects]; @@ -465,6 +471,8 @@ - (DSDerivationPath *)derivationPathContainingAddress:(NSString *)address { for (DSDerivationPath *derivationPath in self.fundDerivationPaths) { if ([derivationPath containsAddress:address]) return derivationPath; } + if (self.coinJoinDerivationPath && [self.coinJoinDerivationPath containsAddress:address]) + return self.coinJoinDerivationPath; return nil; } @@ -474,45 +482,40 @@ - (BOOL)hasAnExtendedPublicKeyMissing { for (DSDerivationPath *derivationPath in self.fundDerivationPaths) { if (![derivationPath hasExtendedPublicKey]) return YES; } + if (self.coinJoinDerivationPath && ![self.coinJoinDerivationPath hasExtendedPublicKey]) return YES; return NO; } - -- (NSArray *)registerAddressesWithInitialGapLimit { +- (NSArray *)registerAddressesAtStage:(DSGapLimitStage)stage { NSMutableArray *mArray = [NSMutableArray array]; for (DSDerivationPath *derivationPath in self.fundDerivationPaths) { if ([derivationPath isKindOfClass:[DSFundsDerivationPath class]]) { DSFundsDerivationPath *path = (DSFundsDerivationPath *)derivationPath; BOOL useReduced = [path shouldUseReducedGapLimit]; BOOL isAnonymous = path.type == DSDerivationPathType_AnonymousFunds; - NSUInteger limit = useReduced ? SEQUENCE_UNUSED_GAP_LIMIT_INITIAL : (isAnonymous ? SEQUENCE_GAP_LIMIT_INITIAL_COINJOIN : SEQUENCE_GAP_LIMIT_INITIAL); - [mArray addObjectsFromArray:[path registerAddressesWithSettings:[DSGapLimitFunds external:limit]]]; - [mArray addObjectsFromArray:[path registerAddressesWithSettings:[DSGapLimitFunds internal:limit]]]; - } else if ([derivationPath isKindOfClass:[DSIncomingFundsDerivationPath class]]) { - NSArray *addresses = [derivationPath registerAddressesWithSettings:[DSGapLimit withLimit:SEQUENCE_DASHPAY_GAP_LIMIT_INITIAL]]; - [mArray addObjectsFromArray:addresses]; - } - } - return [mArray copy]; -} + BOOL isInitial = stage == DSGapLimitStage_Initial; + NSUInteger externalLimit = useReduced ? (isInitial ? SEQUENCE_UNUSED_GAP_LIMIT_INITIAL : SEQUENCE_UNUSED_GAP_LIMIT_EXTERNAL) : (isAnonymous ? SEQUENCE_GAP_LIMIT_INITIAL_COINJOIN : (isInitial ? SEQUENCE_GAP_LIMIT_INITIAL : SEQUENCE_GAP_LIMIT_EXTERNAL)); + NSUInteger internalLimit = useReduced ? (isInitial ? SEQUENCE_UNUSED_GAP_LIMIT_INITIAL : SEQUENCE_GAP_LIMIT_INTERNAL) : (isAnonymous ? SEQUENCE_GAP_LIMIT_INITIAL_COINJOIN : (isInitial ? SEQUENCE_GAP_LIMIT_INITIAL : SEQUENCE_GAP_LIMIT_INTERNAL)); -- (NSArray *)registerAddressesWithProlongGapLimit { - NSMutableArray *mArray = [NSMutableArray array]; - for (DSDerivationPath *derivationPath in self.fundDerivationPaths) { - if ([derivationPath isKindOfClass:[DSFundsDerivationPath class]]) { - DSFundsDerivationPath *path = (DSFundsDerivationPath *)derivationPath; - BOOL useReduced = [path shouldUseReducedGapLimit]; - BOOL isAnonymous = path.type == DSDerivationPathType_AnonymousFunds; - NSUInteger externalLimit = useReduced ? SEQUENCE_UNUSED_GAP_LIMIT_EXTERNAL : (isAnonymous ? SEQUENCE_GAP_LIMIT_INITIAL_COINJOIN : SEQUENCE_GAP_LIMIT_EXTERNAL); - NSUInteger internalLimit = useReduced ? SEQUENCE_GAP_LIMIT_INTERNAL : (isAnonymous ? SEQUENCE_GAP_LIMIT_INITIAL_COINJOIN : SEQUENCE_GAP_LIMIT_INTERNAL); [mArray addObjectsFromArray:[path registerAddressesWithSettings:[DSGapLimitFunds external:externalLimit]]]; [mArray addObjectsFromArray:[path registerAddressesWithSettings:[DSGapLimitFunds internal:internalLimit]]]; } else if ([derivationPath isKindOfClass:[DSIncomingFundsDerivationPath class]]) { - NSArray *addresses = [derivationPath registerAddressesWithSettings:[DSGapLimit withLimit:SEQUENCE_DASHPAY_GAP_LIMIT_INCOMING]]; + BOOL isInitial = stage == DSGapLimitStage_Initial; + NSUInteger limit = isInitial ? SEQUENCE_DASHPAY_GAP_LIMIT_INITIAL : SEQUENCE_DASHPAY_GAP_LIMIT_INCOMING; + + NSArray *addresses = [derivationPath registerAddressesWithSettings:[DSGapLimit withLimit:limit]]; [mArray addObjectsFromArray:addresses]; } } - return mArray; - + if (self.coinJoinDerivationPath) { + BOOL useReduced = [self.coinJoinDerivationPath shouldUseReducedGapLimit]; + BOOL isInitial = stage == DSGapLimitStage_Initial; + NSUInteger externalLimit = useReduced ? (isInitial ? SEQUENCE_UNUSED_GAP_LIMIT_INITIAL : SEQUENCE_UNUSED_GAP_LIMIT_EXTERNAL) : SEQUENCE_GAP_LIMIT_INITIAL_COINJOIN; + NSUInteger internalLimit = useReduced ? (isInitial ? SEQUENCE_UNUSED_GAP_LIMIT_INITIAL : SEQUENCE_GAP_LIMIT_INTERNAL) : SEQUENCE_GAP_LIMIT_INITIAL_COINJOIN; + + [mArray addObjectsFromArray:[self.coinJoinDerivationPath registerAddressesWithSettings:[DSGapLimitFunds external:externalLimit]]]; + [mArray addObjectsFromArray:[self.coinJoinDerivationPath registerAddressesWithSettings:[DSGapLimitFunds internal:internalLimit]]]; + } + return [mArray copy]; } // all previously generated external addresses @@ -521,6 +524,9 @@ - (NSArray *)externalAddresses { for (DSDerivationPath *derivationPath in self.fundDerivationPaths) { [mSet addObjectsFromArray:[(id)derivationPath allReceiveAddresses]]; } + if (self.coinJoinDerivationPath) + [mSet addObjectsFromArray:[self.coinJoinDerivationPath allReceiveAddresses]]; + if ([mSet containsObject:[NSNull null]]) { [mSet removeObject:[NSNull null]]; } @@ -535,6 +541,8 @@ - (NSArray *)internalAddresses { [mSet addObjectsFromArray:[(DSFundsDerivationPath *)derivationPath allChangeAddresses]]; } } + if (self.coinJoinDerivationPath) + [mSet addObjectsFromArray:[self.coinJoinDerivationPath allChangeAddresses]]; if ([mSet containsObject:[NSNull null]]) { [mSet removeObject:[NSNull null]]; } @@ -546,6 +554,8 @@ - (NSSet *)allAddresses { for (DSFundsDerivationPath *derivationPath in self.fundDerivationPaths) { [mSet unionSet:[derivationPath allAddresses]]; } + if (self.coinJoinDerivationPath) + [mSet unionSet:[self.coinJoinDerivationPath allAddresses]]; return mSet; } @@ -554,6 +564,8 @@ - (NSSet *)usedAddresses { for (DSFundsDerivationPath *derivationPath in self.fundDerivationPaths) { [mSet unionSet:[derivationPath usedAddresses]]; } + if (self.coinJoinDerivationPath) + [mSet unionSet:[self.coinJoinDerivationPath usedAddresses]]; return mSet; } @@ -568,6 +580,7 @@ - (BOOL)containsAddress:(NSString *)address { for (DSFundsDerivationPath *derivationPath in self.fundDerivationPaths) { if ([derivationPath containsAddress:address]) return TRUE; } + if (self.coinJoinDerivationPath && [self.coinJoinDerivationPath containsAddress:address]) return YES; return FALSE; } @@ -597,6 +610,7 @@ - (BOOL)containsInternalAddress:(NSString *)address { return TRUE; } } + if (self.coinJoinDerivationPath && [self.coinJoinDerivationPath containsChangeAddress:address]) return YES; return FALSE; } @@ -612,6 +626,7 @@ - (BOOL)baseDerivationPathsContainAddress:(NSString *)address { return TRUE; } } + if (self.coinJoinDerivationPath && [self.coinJoinDerivationPath containsAddress:address]) return YES; return FALSE; } @@ -630,6 +645,7 @@ - (BOOL)containsExternalAddress:(NSString *)address { if ([(DSIncomingFundsDerivationPath *)derivationPath containsAddress:address]) return TRUE; //!OCLINT } } + if (self.coinJoinDerivationPath && [self.coinJoinDerivationPath containsReceiveAddress:address]) return TRUE; return FALSE; } @@ -657,6 +673,7 @@ - (BOOL)addressIsUsed:(NSString *)address { for (DSFundsDerivationPath *derivationPath in self.fundDerivationPaths) { if ([derivationPath addressIsUsed:address]) return TRUE; } + if (self.coinJoinDerivationPath && [self.coinJoinDerivationPath addressIsUsed:address]) return YES; return FALSE; } @@ -687,6 +704,8 @@ - (void)updateBalance { for (DSFundsDerivationPath *derivationPath in self.fundDerivationPaths) { derivationPath.balance = 0; } + if (self.coinJoinDerivationPath) + self.coinJoinDerivationPath.balance = 0; for (DSTransaction *tx in [self.transactions reverseObjectEnumerator]) { #if LOG_BALANCE_UPDATE @@ -791,6 +810,16 @@ - (void)updateBalance { balance += amount; } } + if (self.coinJoinDerivationPath) { + if ([self.coinJoinDerivationPath containsAddress:output.address]) { + [self.coinJoinDerivationPath setHasKnownBalance]; + uint64_t amount = output.amount; + self.coinJoinDerivationPath.balance += amount; + [utxos addObject:dsutxo_obj(((DSUTXO){tx.txHash, n}))]; + balance += amount; + } + } + n++; } @@ -814,6 +843,9 @@ - (void)updateBalance { break; } } + if (self.coinJoinDerivationPath && [self.coinJoinDerivationPath containsAddress:output.address]) { + self.coinJoinDerivationPath.balance -= amount; + } } if (prevBalance < balance) totalReceived += balance - prevBalance; @@ -975,7 +1007,7 @@ - (BOOL)hasCoinbaseTransaction { - (BOOL)canContainTransaction:(DSTransaction *)transaction { NSParameterAssert(transaction); @synchronized (self) { - if ([[NSSet setWithArray:transaction.outputAddresses] intersectsSet:self.allAddresses]) return YES; + if ([self canContainTransactionOutputAddresses:transaction]) return YES; for (DSTransactionInput *input in transaction.inputs) { DSTransaction *tx = self.allTx[uint256_obj(input.inputHash)]; uint32_t n = input.index; @@ -1000,6 +1032,44 @@ - (BOOL)canContainTransaction:(DSTransaction *)transaction { } } +- (BOOL)canContainTransactionOutputAddresses:(DSTransaction *)transaction { + return [[NSSet setWithArray:transaction.outputAddresses] intersectsSet:self.allAddresses]; +} +- (BOOL)canContainTransactionOutputAddressesIncludingCoinjoin:(DSTransaction *)transaction { + for (NSString *address in transaction.outputAddresses) { + if ([self containsCoinJoinAddress:address]) return YES; + } + return NO; +} + +- (BOOL)canContainTransactionIncludingCoinjoin:(DSTransaction *)transaction { + NSParameterAssert(transaction); + @synchronized (self) { + if ([self canContainTransactionOutputAddresses:transaction] || [self canContainTransactionOutputAddressesIncludingCoinjoin:transaction]) return YES; + for (DSTransactionInput *input in transaction.inputs) { + DSTransaction *tx = self.allTx[uint256_obj(input.inputHash)]; + uint32_t n = input.index; + if (n < tx.outputs.count && ([self containsAddress:tx.outputs[n].address] || [self containsCoinJoinAddress:tx.outputs[n].address])) + return YES; + } + if ([transaction isKindOfClass:[DSProviderRegistrationTransaction class]]) { + DSProviderRegistrationTransaction *tx = (DSProviderRegistrationTransaction *)transaction; + if ([self containsAddress:tx.payoutAddress]) return YES; + } else if ([transaction isKindOfClass:[DSProviderUpdateServiceTransaction class]]) { + DSProviderUpdateServiceTransaction *tx = (DSProviderUpdateServiceTransaction *)transaction; + NSString *payoutAddress = tx.payoutAddress; + if (payoutAddress && [self containsAddress:payoutAddress]) return YES; + } else if ([transaction isKindOfClass:[DSProviderUpdateRegistrarTransaction class]]) { + DSProviderUpdateRegistrarTransaction *tx = (DSProviderUpdateRegistrarTransaction *)transaction; + if ([self containsAddress:tx.payoutAddress]) return YES; + } + // TODO: asset locks/unlocks/transitions? +// else if ([transaction isKindOfClass:[DSAs]]) + + return NO; + } +} + - (BOOL)checkIsFirstTransaction:(DSTransaction *)transaction { NSParameterAssert(transaction); for (DSDerivationPath *path in self.fundDerivationPaths) { @@ -1381,7 +1451,7 @@ - (NSArray *)usedDerivationPathsForTransaction:(DSTransaction *)transaction { @"internalIndexes": internalIndexes }]; } - + // TODO: why coinjoin doesn't matter? return usedDerivationPaths; } @@ -1615,14 +1685,21 @@ - (BOOL)registerTransaction:(DSTransaction *)transaction for (DSFundsDerivationPath *derivationPath in self.fundDerivationPaths) { [derivationPath registerTransactionAddress:address]; //only will register if derivation path contains address } + if (self.coinJoinDerivationPath) + [self.coinJoinDerivationPath registerTransactionAddress:address]; } for (DSTransactionOutput *output in transaction.outputs) { for (DSFundsDerivationPath *derivationPath in self.fundDerivationPaths) { [derivationPath registerTransactionAddress:output.address]; //only will register if derivation path contains address } + if (self.coinJoinDerivationPath) + [self.coinJoinDerivationPath registerTransactionAddress:output.address]; //only will register if derivation path contains address } + [transaction loadIdentitiesFromDerivationPaths:self.fundDerivationPaths]; [transaction loadIdentitiesFromDerivationPaths:self.outgoingFundDerivationPaths]; + if (self.coinJoinDerivationPath) + [transaction loadIdentitiesFromDerivationPaths:@[self.coinJoinDerivationPath]]; [self updateBalance]; if (saveImmediately) { if (!self.wallet.isTransient) { diff --git a/DashSync/shared/Models/Wallet/DSWallet+Identity.m b/DashSync/shared/Models/Wallet/DSWallet+Identity.m index 80282954..ffb0cd6b 100644 --- a/DashSync/shared/Models/Wallet/DSWallet+Identity.m +++ b/DashSync/shared/Models/Wallet/DSWallet+Identity.m @@ -131,6 +131,7 @@ - (void)loadIdentities { for (DSTransaction *transaction in account.allTransactions) { [transaction loadIdentitiesFromDerivationPaths:account.fundDerivationPaths]; [transaction loadIdentitiesFromDerivationPaths:account.outgoingFundDerivationPaths]; + [transaction loadIdentitiesFromDerivationPaths:@[account.coinJoinDerivationPath]]; } } }]; diff --git a/DashSync/shared/Models/Wallet/DSWallet+Tests.m b/DashSync/shared/Models/Wallet/DSWallet+Tests.m index f8e3060f..0b7c696d 100644 --- a/DashSync/shared/Models/Wallet/DSWallet+Tests.m +++ b/DashSync/shared/Models/Wallet/DSWallet+Tests.m @@ -64,6 +64,8 @@ + (NSString *)setTransientDerivedKeyData:(NSData *)derivedKeyData withAccounts:( for (DSDerivationPath *derivationPath in account.fundDerivationPaths) { [derivationPath generateExtendedPublicKeyFromSeed:derivedKeyData storeUnderWalletUniqueId:nil]; } + if (account.coinJoinDerivationPath) + [account.coinJoinDerivationPath generateExtendedPublicKeyFromSeed:derivedKeyData storeUnderWalletUniqueId:nil]; if ([chain isEvolutionEnabled]) { [account.masterContactsDerivationPath generateExtendedPublicKeyFromSeed:derivedKeyData storeUnderWalletUniqueId:nil]; } diff --git a/DashSync/shared/Models/Wallet/DSWallet.h b/DashSync/shared/Models/Wallet/DSWallet.h index 03ccbf3b..24be8ac2 100644 --- a/DashSync/shared/Models/Wallet/DSWallet.h +++ b/DashSync/shared/Models/Wallet/DSWallet.h @@ -25,6 +25,7 @@ #import "BigIntTypes.h" #import "DSBIP39Mnemonic.h" #import "DSIdentity.h" +#import "DSGapLimit.h" #import NS_ASSUME_NONNULL_BEGIN @@ -154,8 +155,7 @@ FOUNDATION_EXPORT NSString *_Nonnull const DSWalletBalanceDidChangeNotification; - (DSTransaction *_Nullable)transactionForHash:(UInt256)txHash; - (NSArray *)allAddresses; -- (NSArray *_Nullable)registerAddressesWithInitialGapLimit; -- (NSArray *_Nullable)registerAddressesWithProlongGapLimit; +- (NSArray *)registerAddressesAtStage:(DSGapLimitStage)stage; // returns the amount received by the wallet from the transaction (total outputs to change and/or receive addresses) - (uint64_t)amountReceivedFromTransaction:(DSTransaction *)transaction; diff --git a/DashSync/shared/Models/Wallet/DSWallet.m b/DashSync/shared/Models/Wallet/DSWallet.m index 5d71896e..325e97a7 100644 --- a/DashSync/shared/Models/Wallet/DSWallet.m +++ b/DashSync/shared/Models/Wallet/DSWallet.m @@ -303,6 +303,9 @@ - (DSAccount *)addAnotherAccountIfAuthenticated { [derivationPath generateExtendedPublicKeyFromSeed:derivedKeyData storeUnderWalletUniqueId:self.uniqueIDString]; } + if (addAccount.coinJoinDerivationPath) + [addAccount.coinJoinDerivationPath generateExtendedPublicKeyFromSeed:derivedKeyData storeUnderWalletUniqueId:self.uniqueIDString]; + if ([self.chain isEvolutionEnabled]) { [addAccount.masterContactsDerivationPath generateExtendedPublicKeyFromSeed:derivedKeyData storeUnderWalletUniqueId:self.uniqueIDString]; @@ -618,6 +621,8 @@ + (NSString *)setSeedPhrase:(NSString *)seedPhrase createdAt:(NSTimeInterval)cre for (DSDerivationPath *derivationPath in account.fundDerivationPaths) { [derivationPath generateExtendedPublicKeyFromSeed:derivedKeyData storeUnderWalletUniqueId:storeOnUniqueId]; } + if (account.coinJoinDerivationPath) + [account.coinJoinDerivationPath generateExtendedPublicKeyFromSeed:derivedKeyData storeUnderWalletUniqueId:storeOnUniqueId]; if ([chain isEvolutionEnabled]) { [account.masterContactsDerivationPath generateExtendedPublicKeyFromSeed:derivedKeyData storeUnderWalletUniqueId:storeOnUniqueId]; } @@ -720,20 +725,13 @@ - (uint64_t)balance { return allAddressesArray; } -- (NSArray *)registerAddressesWithInitialGapLimit { +- (NSArray *)registerAddressesAtStage:(DSGapLimitStage)stage { NSMutableArray *mArray = [NSMutableArray array]; for (DSAccount *account in self.accounts) { - [mArray addObjectsFromArray:[account registerAddressesWithInitialGapLimit]]; + [mArray addObjectsFromArray:[account registerAddressesAtStage:stage]]; } return [mArray copy]; -} -- (NSArray *)registerAddressesWithProlongGapLimit { - NSMutableArray *mArray = [NSMutableArray array]; - for (DSAccount *account in self.accounts) { - [mArray addObjectsFromArray:[account registerAddressesWithProlongGapLimit]]; - } - return [mArray copy]; } - (DSAccount *)firstAccountThatCanContainTransaction:(DSTransaction *)transaction { @@ -1003,6 +1001,8 @@ - (void)reloadDerivationPaths { for (DSDerivationPath *derivationPath in account.fundDerivationPaths) { [derivationPath reloadAddresses]; } + if (account.coinJoinDerivationPath) + [account.coinJoinDerivationPath reloadAddresses]; } for (DSDerivationPath *derivationPath in self.specializedDerivationPaths) { [derivationPath reloadAddresses]; diff --git a/Example/DashSync.xcodeproj/project.pbxproj b/Example/DashSync.xcodeproj/project.pbxproj index e6c62fe4..dded0e64 100644 --- a/Example/DashSync.xcodeproj/project.pbxproj +++ b/Example/DashSync.xcodeproj/project.pbxproj @@ -3268,13 +3268,18 @@ "$(inherited)", "COCOAPODS=1", "$(inherited)", - "GPB_USE_PROTOBUF_FRAMEWORK_IMPORTS=1", + "DASHCORE_QUORUM_VALIDATION=1", "DPP_STATE_TRANSITIONS=1", "PLATFORM_VALUE_STD=1", ); INFOPLIST_FILE = "DashSync/DashSync-Info.plist"; IPHONEOS_DEPLOYMENT_TARGET = 15.6; MODULE_NAME = ExampleApp; + OTHER_CFLAGS = ( + "-DDASHCORE_QUORUM_VALIDATION=1", + "-DDPP_STATE_TRANSITIONS=1", + "-DPLATFORM_VALUE_STD=1", + ); OTHER_LDFLAGS = ( "$(inherited)", "-ObjC", @@ -3305,7 +3310,6 @@ "-framework", "\"UIKit\"", "-ld64", - "-DPP_STATE_TRANSITIONS", ); PRODUCT_BUNDLE_IDENTIFIER = "org.cocoapods.demo.${PRODUCT_NAME:rfc1034identifier}"; PRODUCT_NAME = "$(TARGET_NAME)"; @@ -3329,13 +3333,18 @@ "$(inherited)", "COCOAPODS=1", "$(inherited)", - "GPB_USE_PROTOBUF_FRAMEWORK_IMPORTS=1", + "DASHCORE_QUORUM_VALIDATION=1", "DPP_STATE_TRANSITIONS=1", "PLATFORM_VALUE_STD=1", ); INFOPLIST_FILE = "DashSync/DashSync-Info.plist"; IPHONEOS_DEPLOYMENT_TARGET = 15.6; MODULE_NAME = ExampleApp; + OTHER_CFLAGS = ( + "-DDASHCORE_QUORUM_VALIDATION=1", + "-DDPP_STATE_TRANSITIONS=1", + "-DPLATFORM_VALUE_STD=1", + ); OTHER_LDFLAGS = ( "$(inherited)", "-ObjC", @@ -3366,7 +3375,6 @@ "-framework", "\"UIKit\"", "-ld64", - "-DPP_STATE_TRANSITIONS", ); PRODUCT_BUNDLE_IDENTIFIER = "org.cocoapods.demo.${PRODUCT_NAME:rfc1034identifier}"; PRODUCT_NAME = "$(TARGET_NAME)"; diff --git a/Example/DashSync/Base.lproj/Main.storyboard b/Example/DashSync/Base.lproj/Main.storyboard index 51812501..0bd27a2c 100644 --- a/Example/DashSync/Base.lproj/Main.storyboard +++ b/Example/DashSync/Base.lproj/Main.storyboard @@ -21,13 +21,13 @@