diff --git a/DashSync/shared/DSDashSharedCore.m b/DashSync/shared/DSDashSharedCore.m index a6601099d..6fe83b75c 100644 --- a/DashSync/shared/DSDashSharedCore.m +++ b/DashSync/shared/DSDashSharedCore.m @@ -178,8 +178,17 @@ - (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, 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); + 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); return self; } diff --git a/DashSync/shared/DashSync.h b/DashSync/shared/DashSync.h index a2e362438..001cf0014 100644 --- a/DashSync/shared/DashSync.h +++ b/DashSync/shared/DashSync.h @@ -102,6 +102,8 @@ #import "DSProviderUpdateRegistrarTransaction.h" #import "DSProviderUpdateRevocationTransaction.h" #import "DSProviderUpdateServiceTransaction.h" +#import "DSAssetLockTransaction.h" +#import "DSAssetUnlockTransaction.h" #import "DSPaymentProtocol.h" #import "DSPaymentRequest.h" diff --git a/DashSync/shared/Libraries/AdvancedOperations/Others/NSError+Platform.h b/DashSync/shared/Libraries/AdvancedOperations/Others/NSError+Platform.h index 8ab4c7d91..2547afe1c 100644 --- a/DashSync/shared/Libraries/AdvancedOperations/Others/NSError+Platform.h +++ b/DashSync/shared/Libraries/AdvancedOperations/Others/NSError+Platform.h @@ -16,22 +16,21 @@ // #import -#import "dash_spv_apple_bindings.h" #import "DSKeyManager.h" NS_ASSUME_NONNULL_BEGIN -@interface NSError (dash_spv_platform_error_Error) -+ (NSError *)ffi_from_platform_error:(dash_spv_platform_error_Error *)ffi_ref; +@interface NSError (DPlatformError) ++ (NSError *)ffi_from_platform_error:(DPlatformError *)ffi_ref; @end -@interface NSError (dash_spv_crypto_keys_KeyError) +@interface NSError (DKeyError) + (NSError *)ffi_from_key_error:(DKeyError *)ffi_ref; @end -@interface NSError (dash_spv_masternode_processor_processing_core_provider_CoreProviderError) -+ (NSError *)ffi_from_core_provider_error:(dash_spv_masternode_processor_processing_core_provider_CoreProviderError *)ffi_ref; +@interface NSError (DCoreProviderError) ++ (NSError *)ffi_from_core_provider_error:(DCoreProviderError *)ffi_ref; @end @interface NSError (DProcessingError) diff --git a/DashSync/shared/Libraries/AdvancedOperations/Others/NSError+Platform.m b/DashSync/shared/Libraries/AdvancedOperations/Others/NSError+Platform.m index d6b2c7729..1215cef07 100644 --- a/DashSync/shared/Libraries/AdvancedOperations/Others/NSError+Platform.m +++ b/DashSync/shared/Libraries/AdvancedOperations/Others/NSError+Platform.m @@ -19,9 +19,9 @@ #import "NSError+Dash.h" #import "NSError+Platform.h" -@implementation NSError (dash_spv_platform_error_Error) +@implementation NSError (DPlatformError) -+ (nonnull NSError *)ffi_from_platform_error:(nonnull dash_spv_platform_error_Error *)ffi_ref { ++ (nonnull NSError *)ffi_from_platform_error:(nonnull DPlatformError *)ffi_ref { switch (ffi_ref->tag) { case dash_spv_platform_error_Error_KeyError: return [NSError ffi_from_key_error:ffi_ref->key_error]; @@ -38,7 +38,7 @@ + (nonnull NSError *)ffi_from_platform_error:(nonnull dash_spv_platform_error_Er @end -@implementation NSError (dash_spv_crypto_keys_KeyError) +@implementation NSError (DKeyError) + (nonnull NSError *)ffi_from_key_error:(nonnull DKeyError *)ffi_ref { switch (ffi_ref->tag) { @@ -59,7 +59,7 @@ + (nonnull NSError *)ffi_from_key_error:(nonnull DKeyError *)ffi_ref { case dash_spv_crypto_keys_KeyError_Product: return [NSError errorWithCode:0 localizedDescriptionKey:@"Can't multiple keys"]; case dash_spv_crypto_keys_KeyError_Any: - return [NSError errorWithCode:0 localizedDescriptionKey:NSStringFromPtr(ffi_ref->any)]; + return [NSError errorWithCode:0 descriptionKey:NSStringFromPtr(ffi_ref->any)]; } } @@ -74,14 +74,14 @@ + (nonnull NSError *)ffi_from_client_data_retrieval_error:(nonnull dashcore_sml_ NSString *blockHashString = u256_hex(block_hash); NSString *blockHashRevString = u256_reversed_hex(block_hash); u256_dtor(block_hash); - return [NSError errorWithCode:0 descriptionKey:DSLocalizedFormat(@"Required Block Not Present %@ (%@)", nil, blockHashString, blockHashRevString)]; + return [NSError errorWithCode:0 descriptionKey:DSLocalizedFormat(@"ClientDataRetrievalError::RequiredBlockNotPresent: %@ (%@)", nil, blockHashString, blockHashRevString)]; } case dashcore_sml_quorum_validation_error_ClientDataRetrievalError_CoinbaseNotFoundOnBlock: { u256 *block_hash = dashcore_hash_types_BlockHash_inner(ffi_ref->coinbase_not_found_on_block); NSString *blockHashString = u256_hex(block_hash); NSString *blockHashRevString = u256_reversed_hex(block_hash); u256_dtor(block_hash); - return [NSError errorWithCode:0 descriptionKey:DSLocalizedFormat(@"Coinbase Not Found On Block %@ (%@)", nil, blockHashString, blockHashRevString)]; + return [NSError errorWithCode:0 descriptionKey:DSLocalizedFormat(@"ClientDataRetrievalError::CoinbaseNotFoundOnBlock: %@ (%@)", nil, blockHashString, blockHashRevString)]; } } } @@ -93,90 +93,90 @@ + (NSError *)ffi_from_quorum_validation_error:(dashcore_sml_quorum_validation_er 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); - return [NSError errorWithCode:0 localizedDescriptionKey:DSLocalizedFormat(@"Required block %@ (%@) not present", nil, u256_hex(block_hash), u256_reversed_hex(block_hash))]; + 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: - return [NSError errorWithCode:0 localizedDescriptionKey:DSLocalizedFormat(@"Required block height (%u) not present", nil, ffi_ref->required_block_height_not_present->_0)]; + return [NSError errorWithCode:0 descriptionKey:DSLocalizedFormat(@"QuorumValidationError::RequiredBlockHeightNotPresent: %u", nil, ffi_ref->required_block_height_not_present->_0)]; case dashcore_sml_quorum_validation_error_QuorumValidationError_VerifyingMasternodeListNotPresent: - return [NSError errorWithCode:0 localizedDescriptionKey:DSLocalizedFormat(@"Verifying MasternodeList (%u) not present", nil, ffi_ref->verifying_masternode_list_not_present->_0)]; + return [NSError errorWithCode:0 descriptionKey:DSLocalizedFormat(@"QuorumValidationError::VerifyingMasternodeListNotPresent: %u", nil, ffi_ref->verifying_masternode_list_not_present->_0)]; case dashcore_sml_quorum_validation_error_QuorumValidationError_RequiredMasternodeListNotPresent: - return [NSError errorWithCode:0 localizedDescriptionKey:DSLocalizedFormat(@"Required MasternodeList (%u) not present", nil, ffi_ref->required_masternode_list_not_present->_0)]; + return [NSError errorWithCode:0 descriptionKey:DSLocalizedFormat(@"QuorumValidationError::RequiredMasternodeListNotPresent: %u", nil, ffi_ref->required_masternode_list_not_present->_0)]; case dashcore_sml_quorum_validation_error_QuorumValidationError_RequiredChainLockNotPresent: { u256 *block_hash = dashcore_hash_types_BlockHash_inner(ffi_ref->required_chain_lock_not_present._1); - return [NSError errorWithCode:0 localizedDescriptionKey:DSLocalizedFormat(@"Required ChainLock %u: %@ (%@) not present", nil, ffi_ref->required_chain_lock_not_present._0->_0, u256_hex(block_hash), u256_reversed_hex(block_hash))]; + return [NSError errorWithCode:0 descriptionKey:DSLocalizedFormat(@"QuorumValidationError::RequiredChainLockNotPresent: %u: %@ (%@)", nil, ffi_ref->required_chain_lock_not_present._0->_0, u256_hex(block_hash), u256_reversed_hex(block_hash))]; } case dashcore_sml_quorum_validation_error_QuorumValidationError_RequiredRotatedChainLockSigNotPresent: { uint8_t index = ffi_ref->required_rotated_chain_lock_sig_not_present._0; u256 *block_hash = dashcore_hash_types_BlockHash_inner(ffi_ref->required_rotated_chain_lock_sig_not_present._1); - return [NSError errorWithCode:0 localizedDescriptionKey:DSLocalizedFormat(@"Required Rotated ChainLock Signature at index: %u: %@ (%@) not present", nil, index, u256_hex(block_hash), u256_reversed_hex(block_hash))]; + return [NSError errorWithCode:0 descriptionKey:DSLocalizedFormat(@"QuorumValidationError::RequiredRotatedChainLockSigNotPresent: %u: %@ (%@)", nil, index, u256_hex(block_hash), u256_reversed_hex(block_hash))]; } case dashcore_sml_quorum_validation_error_QuorumValidationError_RequiredRotatedChainLockSigsNotPresent: { u256 *block_hash = dashcore_hash_types_BlockHash_inner(ffi_ref->required_rotated_chain_lock_sigs_not_present); - return [NSError errorWithCode:0 localizedDescriptionKey:DSLocalizedFormat(@"Required ChainLock Signatures %@ (%@) not present", nil, u256_hex(block_hash), u256_reversed_hex(block_hash))]; + return [NSError errorWithCode:0 descriptionKey:DSLocalizedFormat(@"QuorumValidationError::RequiredRotatedChainLockSigsNotPresent: %@ (%@)", nil, u256_hex(block_hash), u256_reversed_hex(block_hash))]; } case dashcore_sml_quorum_validation_error_QuorumValidationError_InsufficientSigners: - return [NSError errorWithCode:0 localizedDescriptionKey:DSLocalizedFormat(@"Insufficient Signers (%llu/%llu)", nil, ffi_ref->insufficient_signers.found, ffi_ref->insufficient_signers.required)]; + return [NSError errorWithCode:0 descriptionKey:DSLocalizedFormat(@"QuorumValidationError::InsufficientSigners (%llu/%llu)", nil, ffi_ref->insufficient_signers.found, ffi_ref->insufficient_signers.required)]; case dashcore_sml_quorum_validation_error_QuorumValidationError_InsufficientValidMembers: - return [NSError errorWithCode:0 localizedDescriptionKey:DSLocalizedFormat(@"Insufficient Valid Members (%llu/%llu)", nil, ffi_ref->insufficient_valid_members.found, ffi_ref->insufficient_valid_members.required)]; + return [NSError errorWithCode:0 descriptionKey:DSLocalizedFormat(@"QuorumValidationError::InsufficientValidMembers (%llu/%llu)", nil, ffi_ref->insufficient_valid_members.found, ffi_ref->insufficient_valid_members.required)]; case dashcore_sml_quorum_validation_error_QuorumValidationError_MismatchedBitsetLengths: - return [NSError errorWithCode:0 localizedDescriptionKey:DSLocalizedFormat(@"Mismatched Bitset Lengths (%lu/%lu)", nil, ffi_ref->mismatched_bitset_lengths.signers_len, ffi_ref->mismatched_bitset_lengths.valid_members_len)]; + return [NSError errorWithCode:0 descriptionKey:DSLocalizedFormat(@"QuorumValidationError::MismatchedBitsetLengths (%lu/%lu)", nil, ffi_ref->mismatched_bitset_lengths.signers_len, ffi_ref->mismatched_bitset_lengths.valid_members_len)]; case dashcore_sml_quorum_validation_error_QuorumValidationError_InvalidQuorumPublicKey: - return [NSError errorWithCode:0 localizedDescriptionKey:DSLocalizedFormat(@"Invalid Quorum PublicKey", nil)]; + return [NSError errorWithCode:0 descriptionKey:DSLocalizedFormat(@"QuorumValidationError::InvalidQuorumPublicKey", nil)]; case dashcore_sml_quorum_validation_error_QuorumValidationError_InvalidBLSPublicKey: - return [NSError errorWithCode:0 localizedDescriptionKey:DSLocalizedFormat(@"Invalid BLS PublicKey (%@)", nil, NSStringFromPtr(ffi_ref->invalid_bls_public_key))]; + return [NSError errorWithCode:0 descriptionKey:DSLocalizedFormat(@"QuorumValidationError::InvalidBLSPublicKey: %@", nil, NSStringFromPtr(ffi_ref->invalid_bls_public_key))]; case dashcore_sml_quorum_validation_error_QuorumValidationError_InvalidBLSSignature: - return [NSError errorWithCode:0 localizedDescriptionKey:DSLocalizedFormat(@"Invalid BLS Signature (%@)", nil, NSStringFromPtr(ffi_ref->invalid_bls_signature))]; + return [NSError errorWithCode:0 descriptionKey:DSLocalizedFormat(@"QuorumValidationError::InvalidBLSSignature: %@", nil, NSStringFromPtr(ffi_ref->invalid_bls_signature))]; case dashcore_sml_quorum_validation_error_QuorumValidationError_InvalidQuorumSignature: - return [NSError errorWithCode:0 localizedDescriptionKey:DSLocalizedFormat(@"Invalid Quorum Signature", nil)]; + return [NSError errorWithCode:0 descriptionKey:DSLocalizedFormat(@"QuorumValidationError::InvalidQuorumSignature", nil)]; case dashcore_sml_quorum_validation_error_QuorumValidationError_InvalidFinalSignature: - return [NSError errorWithCode:0 localizedDescriptionKey:DSLocalizedFormat(@"Invalid Final Signature", nil)]; + return [NSError errorWithCode:0 descriptionKey:DSLocalizedFormat(@"QuorumValidationError::InvalidFinalSignature", nil)]; case dashcore_sml_quorum_validation_error_QuorumValidationError_AllCommitmentAggregatedSignatureNotValid: - return [NSError errorWithCode:0 localizedDescriptionKey:DSLocalizedFormat(@"All Commitment Aggregated Signature Not Valid (%@)", nil, NSStringFromPtr(ffi_ref->all_commitment_aggregated_signature_not_valid))]; + return [NSError errorWithCode:0 descriptionKey:DSLocalizedFormat(@"QuorumValidationError::AllCommitmentAggregatedSignatureNotValid: %@", nil, NSStringFromPtr(ffi_ref->all_commitment_aggregated_signature_not_valid))]; case dashcore_sml_quorum_validation_error_QuorumValidationError_ThresholdSignatureNotValid: - return [NSError errorWithCode:0 localizedDescriptionKey:DSLocalizedFormat(@"Threshold Signature Not Valid (%@)", nil, NSStringFromPtr(ffi_ref->threshold_signature_not_valid))]; + return [NSError errorWithCode:0 descriptionKey:DSLocalizedFormat(@"QuorumValidationError::ThresholdSignatureNotValid: %@", nil, NSStringFromPtr(ffi_ref->threshold_signature_not_valid))]; case dashcore_sml_quorum_validation_error_QuorumValidationError_CommitmentHashNotPresent: - return [NSError errorWithCode:0 localizedDescriptionKey:DSLocalizedFormat(@"Commitment Hash not present", nil)]; + return [NSError errorWithCode:0 descriptionKey:DSLocalizedFormat(@"QuorumValidationError::CommitmentHashNotPresent", nil)]; case dashcore_sml_quorum_validation_error_QuorumValidationError_RequiredSnapshotNotPresent: { u256 *block_hash = dashcore_hash_types_BlockHash_inner(ffi_ref->required_snapshot_not_present); - return [NSError errorWithCode:0 localizedDescriptionKey:DSLocalizedFormat(@"Required Snapshot (%@) not present", nil, u256_hex(block_hash))]; + return [NSError errorWithCode:0 descriptionKey:DSLocalizedFormat(@"QuorumValidationError::RequiredSnapshotNotPresent: %@", nil, u256_hex(block_hash))]; } case dashcore_sml_quorum_validation_error_QuorumValidationError_SMLError: return [NSError ffi_from_sml_error:ffi_ref->sml_error]; case dashcore_sml_quorum_validation_error_QuorumValidationError_RequiredQuorumIndexNotPresent: { u256 *quorum_hash = dashcore_hash_types_QuorumHash_inner(ffi_ref->required_quorum_index_not_present); - return [NSError errorWithCode:0 localizedDescriptionKey:DSLocalizedFormat(@"Required Quorum Index (%@) not present", nil, u256_hex(quorum_hash))]; + return [NSError errorWithCode:0 descriptionKey:DSLocalizedFormat(@"QuorumValidationError::RequiredQuorumIndexNotPresent: %@", nil, u256_hex(quorum_hash))]; } case dashcore_sml_quorum_validation_error_QuorumValidationError_CorruptedCodeExecution: - return [NSError errorWithCode:0 localizedDescriptionKey:DSLocalizedFormat(@"Corruped Code Execution (%@)", nil, NSStringFromPtr(ffi_ref->all_commitment_aggregated_signature_not_valid))]; + return [NSError errorWithCode:0 descriptionKey:DSLocalizedFormat(@"QuorumValidationError::CorruptedCodeExecution: %@", nil, NSStringFromPtr(ffi_ref->corrupted_code_execution))]; case dashcore_sml_quorum_validation_error_QuorumValidationError_ExpectedOnlyRotatedQuorums: { u256 *quorum_hash = dashcore_hash_types_QuorumHash_inner(ffi_ref->expected_only_rotated_quorums._0); - return [NSError errorWithCode:0 localizedDescriptionKey:DSLocalizedFormat(@"Expected Only Rotated Quorums (%u: %@)", nil, dashcore_sml_llmq_type_LLMQType_index(ffi_ref->expected_only_rotated_quorums._1), u256_hex(quorum_hash))]; + return [NSError errorWithCode:0 descriptionKey:DSLocalizedFormat(@"QuorumValidationError::ExpectedOnlyRotatedQuorums: %u: %@", nil, DLLMQTypeIndex(ffi_ref->expected_only_rotated_quorums._1), u256_hex(quorum_hash))]; } case dashcore_sml_quorum_validation_error_QuorumValidationError_ClientDataRetrievalError: return [NSError ffi_from_client_data_retrieval_error:ffi_ref->client_data_retrieval_error]; case dashcore_sml_quorum_validation_error_QuorumValidationError_FeatureNotTurnedOn: - return [NSError errorWithCode:0 localizedDescriptionKey:DSLocalizedFormat(@"Feature Not Turned On (%@)", nil, NSStringFromPtr(ffi_ref->feature_not_turned_on))]; + return [NSError errorWithCode:0 descriptionKey:DSLocalizedFormat(@"QuorumValidationError::FeatureNotTurnedOn: %@", nil, NSStringFromPtr(ffi_ref->feature_not_turned_on))]; } } @end -@implementation NSError (dash_spv_masternode_processor_processing_core_provider_CoreProviderError) -+ (NSError *)ffi_from_core_provider_error:(dash_spv_masternode_processor_processing_core_provider_CoreProviderError *)ffi_ref { +@implementation NSError (DCoreProviderError) ++ (NSError *)ffi_from_core_provider_error:(DCoreProviderError *)ffi_ref { switch (ffi_ref->tag) { case dash_spv_masternode_processor_processing_core_provider_CoreProviderError_NullResult: - return [NSError errorWithCode:0 localizedDescriptionKey:DSLocalizedString(@"Core Provider Null Result", nil)]; + return [NSError errorWithCode:0 descriptionKey:DSLocalizedString(@"Core Provider Null Result", nil)]; case dash_spv_masternode_processor_processing_core_provider_CoreProviderError_BadBlockHash: - return [NSError errorWithCode:0 localizedDescriptionKey:DSLocalizedFormat(@"Bad Block Hash (%@)", nil, u256_hex(ffi_ref->bad_block_hash))]; + return [NSError errorWithCode:0 descriptionKey:DSLocalizedFormat(@"Bad Block Hash (%@)", nil, u256_hex(ffi_ref->bad_block_hash))]; case dash_spv_masternode_processor_processing_core_provider_CoreProviderError_UnknownBlockHeightForHash: - return [NSError errorWithCode:0 localizedDescriptionKey:DSLocalizedFormat(@"Unknown height for Hash (%@)", nil, u256_hex(ffi_ref->unknown_block_height_for_hash))]; + return [NSError errorWithCode:0 descriptionKey:DSLocalizedFormat(@"Unknown height for Hash (%@)", nil, u256_hex(ffi_ref->unknown_block_height_for_hash))]; case dash_spv_masternode_processor_processing_core_provider_CoreProviderError_BlockHashNotFoundAt: - return [NSError errorWithCode:0 localizedDescriptionKey:DSLocalizedFormat(@"Block hash for height %u not found", nil, ffi_ref->block_hash_not_found_at)]; + return [NSError errorWithCode:0 descriptionKey:DSLocalizedFormat(@"Block hash for height %u not found", nil, ffi_ref->block_hash_not_found_at)]; case dash_spv_masternode_processor_processing_core_provider_CoreProviderError_NoSnapshot: - return [NSError errorWithCode:0 localizedDescriptionKey:DSLocalizedString(@"Quorum Snapshot not found", nil)]; + return [NSError errorWithCode:0 descriptionKey:DSLocalizedString(@"Quorum Snapshot not found", nil)]; case dash_spv_masternode_processor_processing_core_provider_CoreProviderError_HexError: - return [NSError errorWithCode:0 localizedDescriptionKey:DSLocalizedString(@"Parse Hex Error", nil)]; + return [NSError errorWithCode:0 descriptionKey:DSLocalizedString(@"Parse Hex Error", nil)]; case dash_spv_masternode_processor_processing_core_provider_CoreProviderError_MissedMasternodeListAt: - return [NSError errorWithCode:0 localizedDescriptionKey:DSLocalizedFormat(@"Missed Masternode List at (%@)", nil, u256_hex(ffi_ref->missed_masternode_list_at))]; + return [NSError errorWithCode:0 descriptionKey:DSLocalizedFormat(@"Missed Masternode List at (%@)", nil, u256_hex(ffi_ref->missed_masternode_list_at))]; } } @end @@ -185,25 +185,25 @@ @implementation NSError (DProcessingError) + (NSError *)ffi_from_processing_error:(DProcessingError *)ffi_ref { switch (ffi_ref->tag) { case dash_spv_masternode_processor_processing_processor_processing_error_ProcessingError_PersistInRetrieval: - return [NSError errorWithCode:0 localizedDescriptionKey:DSLocalizedFormat(@"Unexpected Diff Processing (%@..%@)", nil, u256_hex(ffi_ref->persist_in_retrieval._0), u256_hex(ffi_ref->persist_in_retrieval._1))]; + return [NSError errorWithCode:0 descriptionKey:DSLocalizedFormat(@"Unexpected Diff Processing (%@..%@)", nil, u256_hex(ffi_ref->persist_in_retrieval._0), u256_hex(ffi_ref->persist_in_retrieval._1))]; case dash_spv_masternode_processor_processing_processor_processing_error_ProcessingError_LocallyStored: - return [NSError errorWithCode:0 localizedDescriptionKey:DSLocalizedFormat(@"Masternode List already stored for %u: %@", nil, ffi_ref->locally_stored._0, u256_hex(ffi_ref->locally_stored._1))]; + return [NSError errorWithCode:0 descriptionKey:DSLocalizedFormat(@"Masternode List already stored for %u: %@", nil, ffi_ref->locally_stored._0, u256_hex(ffi_ref->locally_stored._1))]; case dash_spv_masternode_processor_processing_processor_processing_error_ProcessingError_ParseError: - return [NSError errorWithCode:0 localizedDescriptionKey:DSLocalizedFormat(@"Message Parse Error", nil, NSStringFromPtr(ffi_ref->parse_error))]; + return [NSError errorWithCode:0 descriptionKey:DSLocalizedFormat(@"Message Parse Error", nil, NSStringFromPtr(ffi_ref->parse_error))]; case dash_spv_masternode_processor_processing_processor_processing_error_ProcessingError_HasNoBaseBlockHash: - return [NSError errorWithCode:0 localizedDescriptionKey:DSLocalizedFormat(@"Unknown base block hash", nil, u256_hex(ffi_ref->has_no_base_block_hash))]; + return [NSError errorWithCode:0 descriptionKey:DSLocalizedFormat(@"Unknown base block hash", nil, u256_hex(ffi_ref->has_no_base_block_hash))]; case dash_spv_masternode_processor_processing_processor_processing_error_ProcessingError_UnknownBlockHash: - return [NSError errorWithCode:0 localizedDescriptionKey:DSLocalizedFormat(@"Unknown block hash %@", nil, u256_hex(ffi_ref->unknown_block_hash))]; + return [NSError errorWithCode:0 descriptionKey:DSLocalizedFormat(@"Unknown block hash %@", nil, u256_hex(ffi_ref->unknown_block_hash))]; case dash_spv_masternode_processor_processing_processor_processing_error_ProcessingError_InvalidResult: - return [NSError errorWithCode:0 localizedDescriptionKey:DSLocalizedFormat(@"Invalid Result", nil, NSStringFromPtr(ffi_ref->invalid_result))]; + return [NSError errorWithCode:0 descriptionKey:DSLocalizedFormat(@"Invalid Result", nil, NSStringFromPtr(ffi_ref->invalid_result))]; case dash_spv_masternode_processor_processing_processor_processing_error_ProcessingError_CoreProvider: return [NSError ffi_from_core_provider_error:ffi_ref->core_provider]; case dash_spv_masternode_processor_processing_processor_processing_error_ProcessingError_MissingLists: - return [NSError errorWithCode:0 localizedDescriptionKey:DSLocalizedFormat(@"Missing Masternode Lists: %@", nil, NSStringFromPtr(ffi_ref->missing_lists))]; + return [NSError errorWithCode:0 descriptionKey:DSLocalizedFormat(@"Missing Masternode Lists: %@", nil, NSStringFromPtr(ffi_ref->missing_lists))]; case dash_spv_masternode_processor_processing_processor_processing_error_ProcessingError_EncodeError: - return [NSError errorWithCode:0 localizedDescriptionKey:DSLocalizedFormat(@"Encode Error: %@", nil, NSStringFromPtr(ffi_ref->encode_error))]; + return [NSError errorWithCode:0 descriptionKey:DSLocalizedFormat(@"Encode Error: %@", nil, NSStringFromPtr(ffi_ref->encode_error))]; case dash_spv_masternode_processor_processing_processor_processing_error_ProcessingError_DecodeError: - return [NSError errorWithCode:0 localizedDescriptionKey:DSLocalizedFormat(@"Decode Error: %@", nil, NSStringFromPtr(ffi_ref->decode_error))]; + 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]; } @@ -215,33 +215,33 @@ + (NSError *)ffi_from_sml_error:(dashcore_sml_error_SmlError *)ffi_ref { switch (ffi_ref->tag) { case dashcore_sml_error_SmlError_BaseBlockNotGenesis: { u256 *block_hash = dashcore_hash_types_BlockHash_inner(ffi_ref->base_block_not_genesis); - return [NSError errorWithCode:0 localizedDescriptionKey:DSLocalizedFormat(@"SmlError::BaseBlockNotGenesis %@ (%@)", nil, u256_hex(block_hash), u256_reversed_hex(block_hash))]; + return [NSError errorWithCode:0 descriptionKey:DSLocalizedFormat(@"SmlError::BaseBlockNotGenesis %@ (%@)", nil, u256_hex(block_hash), u256_reversed_hex(block_hash))]; } case dashcore_sml_error_SmlError_BlockHashLookupFailed: { u256 *block_hash = dashcore_hash_types_BlockHash_inner(ffi_ref->block_hash_lookup_failed); - return [NSError errorWithCode:0 localizedDescriptionKey:DSLocalizedFormat(@"SmlError::BlockHashLookupFailed %@ (%@)", nil, u256_hex(block_hash), u256_reversed_hex(block_hash))]; + return [NSError errorWithCode:0 descriptionKey:DSLocalizedFormat(@"SmlError::BlockHashLookupFailed %@ (%@)", nil, u256_hex(block_hash), u256_reversed_hex(block_hash))]; } case dashcore_sml_error_SmlError_IncompleteMnListDiff: - return [NSError errorWithCode:0 localizedDescriptionKey:DSLocalizedFormat(@"SmlError::IncompleteMnListDiff", nil)]; + return [NSError errorWithCode:0 descriptionKey:DSLocalizedFormat(@"SmlError::IncompleteMnListDiff", nil)]; case dashcore_sml_error_SmlError_MissingStartMasternodeList: { u256 *block_hash = dashcore_hash_types_BlockHash_inner(ffi_ref->missing_start_masternode_list); - return [NSError errorWithCode:0 localizedDescriptionKey:DSLocalizedFormat(@"SmlError::MissingStartMasternodeList %@ (%@)", nil, u256_hex(block_hash), u256_reversed_hex(block_hash))]; + return [NSError errorWithCode:0 descriptionKey:DSLocalizedFormat(@"SmlError::MissingStartMasternodeList %@ (%@)", nil, u256_hex(block_hash), u256_reversed_hex(block_hash))]; } case dashcore_sml_error_SmlError_BaseBlockHashMismatch: { u256 *block_hash_expected = dashcore_hash_types_BlockHash_inner(ffi_ref->base_block_hash_mismatch.expected); u256 *block_hash_found = dashcore_hash_types_BlockHash_inner(ffi_ref->base_block_hash_mismatch.found); - return [NSError errorWithCode:0 localizedDescriptionKey:DSLocalizedFormat(@"SmlError::BaseBlockHashMismatch: expected: %@ (%@), found: %@ (%@)", nil, u256_hex(block_hash_expected), u256_hex(block_hash_expected), u256_hex(block_hash_found), u256_hex(block_hash_found))]; + return [NSError errorWithCode:0 descriptionKey:DSLocalizedFormat(@"SmlError::BaseBlockHashMismatch: expected: %@ (%@), found: %@ (%@)", nil, u256_hex(block_hash_expected), u256_hex(block_hash_expected), u256_hex(block_hash_found), u256_hex(block_hash_found))]; } case dashcore_sml_error_SmlError_UnknownError: - return [NSError errorWithCode:0 localizedDescriptionKey:DSLocalizedFormat(@"SmlError::UnknownError", nil)]; + return [NSError errorWithCode:0 descriptionKey:DSLocalizedFormat(@"SmlError::UnknownError", nil)]; case dashcore_sml_error_SmlError_CorruptedCodeExecution: - return [NSError errorWithCode:0 localizedDescriptionKey:DSLocalizedFormat(@"SmlError::CorruptedCodeExecution: %@", nil, NSStringFromPtr(ffi_ref->corrupted_code_execution))]; + return [NSError errorWithCode:0 descriptionKey:DSLocalizedFormat(@"SmlError::CorruptedCodeExecution: %@", nil, NSStringFromPtr(ffi_ref->corrupted_code_execution))]; case dashcore_sml_error_SmlError_FeatureNotTurnedOn: - return [NSError errorWithCode:0 localizedDescriptionKey:DSLocalizedFormat(@"SmlError::FeatureNotTurnedOn: %@", nil, NSStringFromPtr(ffi_ref->feature_not_turned_on))]; + return [NSError errorWithCode:0 descriptionKey:DSLocalizedFormat(@"SmlError::FeatureNotTurnedOn: %@", nil, NSStringFromPtr(ffi_ref->feature_not_turned_on))]; case dashcore_sml_error_SmlError_InvalidIndexInSignatureSet: - return [NSError errorWithCode:0 localizedDescriptionKey:DSLocalizedFormat(@"SmlError::InvalidIndexInSignatureSet: %u", nil, ffi_ref->invalid_index_in_signature_set)]; + return [NSError errorWithCode:0 descriptionKey:DSLocalizedFormat(@"SmlError::InvalidIndexInSignatureSet: %u", nil, ffi_ref->invalid_index_in_signature_set)]; case dashcore_sml_error_SmlError_IncompleteSignatureSet: - return [NSError errorWithCode:0 localizedDescriptionKey:DSLocalizedFormat(@"SmlError::IncompleteSignatureSet", nil)]; + return [NSError errorWithCode:0 descriptionKey:DSLocalizedFormat(@"SmlError::IncompleteSignatureSet", nil)]; } } @end diff --git a/DashSync/shared/MasternodeLists/mn_list_diff_0_2227096.bin b/DashSync/shared/MasternodeLists/mn_list_diff_0_2227096.bin new file mode 100644 index 000000000..a75870c79 Binary files /dev/null and b/DashSync/shared/MasternodeLists/mn_list_diff_0_2227096.bin differ diff --git a/DashSync/shared/Models/Chain/DSChain+Params.m b/DashSync/shared/Models/Chain/DSChain+Params.m index cb8dc5096..0acd1b7df 100644 --- a/DashSync/shared/Models/Chain/DSChain+Params.m +++ b/DashSync/shared/Models/Chain/DSChain+Params.m @@ -315,8 +315,8 @@ - (BOOL)allowMinDifficultyBlocks { } - (uint64_t)baseReward { - if (dash_spv_crypto_network_chain_type_ChainType_is_mainnet(self.chainType)) return 5 * DUFFS; - return 50 * DUFFS; + if (dash_spv_crypto_network_chain_type_ChainType_is_mainnet(self.chainType)) return 5 * DUFFS_OBJC; + return 50 * (unsigned long long) DUFFS_OBJC; } - (uint32_t)coinType { return dash_spv_crypto_network_chain_type_ChainType_coin_type(self.chainType); diff --git a/DashSync/shared/Models/Chain/DSChain+Transaction.m b/DashSync/shared/Models/Chain/DSChain+Transaction.m index b48606d04..00a7cb87e 100644 --- a/DashSync/shared/Models/Chain/DSChain+Transaction.m +++ b/DashSync/shared/Models/Chain/DSChain+Transaction.m @@ -314,8 +314,9 @@ - (void)triggerUpdatesForLocalReferences:(DSTransaction *)transaction { UInt160 creditBurnPublicKeyHash = tx.creditBurnPublicKeyHash; uint32_t index; DSWallet *wallet = [self walletHavingIdentityAssetLockRegistrationHash:creditBurnPublicKeyHash foundAtIndex:&index]; + UInt256 identityId = tx.creditBurnIdentityIdentifier; if (wallet) { - DSIdentity *identity = [wallet identityForUniqueId:tx.creditBurnIdentityIdentifier]; + DSIdentity *identity = [wallet identityForUniqueId:identityId]; if (!identity) { identity = [[DSIdentity alloc] initAtIndex:index withAssetLockTransaction:tx inWallet:wallet]; [identity registerInWalletForAssetLockTransaction:tx]; @@ -323,13 +324,17 @@ - (void)triggerUpdatesForLocalReferences:(DSTransaction *)transaction { } else { wallet = [self walletHavingIdentityAssetLockTopupHash:creditBurnPublicKeyHash foundAtIndex:&index]; if (wallet) { - DSIdentity *identity = [wallet identityForUniqueId:tx.creditBurnIdentityIdentifier]; -// [identity r] + DSIdentity *identity = [wallet identityForUniqueId:identityId]; + if (identity) { + [identity registerInWalletForAssetLockTopupTransaction:tx]; + } else { + NSAssert(NO, @"Topup unknown identity %@", uint256_hex(identityId)); + } } else { wallet = [self walletHavingIdentityAssetLockInvitationHash:creditBurnPublicKeyHash foundAtIndex:&index]; if (wallet) { - DSInvitation *invitation = [wallet invitationForUniqueId:tx.creditBurnIdentityIdentifier]; + DSInvitation *invitation = [wallet invitationForUniqueId:identityId]; if (!invitation) { invitation = [[DSInvitation alloc] initAtIndex:index withAssetLockTransaction:tx inWallet:wallet]; [invitation registerInWalletForAssetLockTransaction:tx]; diff --git a/DashSync/shared/Models/Chain/DSChain.h b/DashSync/shared/Models/Chain/DSChain.h index 6463e631d..c37e51285 100644 --- a/DashSync/shared/Models/Chain/DSChain.h +++ b/DashSync/shared/Models/Chain/DSChain.h @@ -169,6 +169,7 @@ typedef NS_ENUM(uint16_t, DSChainSyncPhase) /*! @brief Returns a known block with a given distance from the chain tip. A null result would mean that the given distance exceeded the number of blocks kept locally. */ - (DSMerkleBlock *_Nullable)blockFromChainTip:(NSUInteger)blocksAgo; +- (UInt256)chainTipHash; - (uint32_t)chainTipHeight; // MARK: Chain Sync diff --git a/DashSync/shared/Models/Chain/DSChain.m b/DashSync/shared/Models/Chain/DSChain.m index 128c67c77..de416103b 100644 --- a/DashSync/shared/Models/Chain/DSChain.m +++ b/DashSync/shared/Models/Chain/DSChain.m @@ -155,7 +155,7 @@ - (instancetype)initAsDevnetWithIdentifier:(dash_spv_crypto_network_chain_type_D checkpoints:(NSArray *)checkpoints { //for devnet the genesis checkpoint is really the second block if (!(self = [self init])) return nil; - self.chainType = dash_spv_crypto_network_chain_type_ChainType_DevNet_ctor(devnetType); + self.chainType = DChainTypeDevnet(devnetType); if (!checkpoints || ![checkpoints count]) { DSCheckpoint *genesisCheckpoint = [DSCheckpoint genesisDevnetCheckpoint]; DSCheckpoint *secondCheckpoint = [self createDevNetGenesisBlockCheckpointForParentCheckpoint:genesisCheckpoint withIdentifier:devnetType onProtocolVersion:protocolVersion]; @@ -246,7 +246,7 @@ + (DSChain *)mainnet { static dispatch_once_t mainnetToken = 0; __block BOOL inSetUp = FALSE; dispatch_once(&mainnetToken, ^{ - _mainnet = [[DSChain alloc] initWithType:dash_spv_crypto_network_chain_type_ChainType_MainNet_ctor() checkpoints:[DSChain createCheckpointsArrayFromCheckpoints:mainnet_checkpoint_array count:(sizeof(mainnet_checkpoint_array) / sizeof(*mainnet_checkpoint_array))]]; + _mainnet = [[DSChain alloc] initWithType:DChainTypeMainnet() checkpoints:[DSChain createCheckpointsArrayFromCheckpoints:mainnet_checkpoint_array count:(sizeof(mainnet_checkpoint_array) / sizeof(*mainnet_checkpoint_array))]]; inSetUp = TRUE; }); if (inSetUp) { @@ -270,7 +270,7 @@ + (DSChain *)testnet { static dispatch_once_t testnetToken = 0; __block BOOL inSetUp = FALSE; dispatch_once(&testnetToken, ^{ - _testnet = [[DSChain alloc] initWithType:dash_spv_crypto_network_chain_type_ChainType_TestNet_ctor() checkpoints:[DSChain createCheckpointsArrayFromCheckpoints:testnet_checkpoint_array count:(sizeof(testnet_checkpoint_array) / sizeof(*testnet_checkpoint_array))]]; + _testnet = [[DSChain alloc] initWithType:DChainTypeTestnet() checkpoints:[DSChain createCheckpointsArrayFromCheckpoints:testnet_checkpoint_array count:(sizeof(testnet_checkpoint_array) / sizeof(*testnet_checkpoint_array))]]; inSetUp = TRUE; }); if (inSetUp) { @@ -557,6 +557,9 @@ - (NSTimeInterval)startSyncFromTime { - (NSString *)chainTip { return [NSData dataWithUInt256:self.lastTerminalBlock.blockHash].shortHexString; } +- (UInt256)chainTipHash { + return self.lastTerminalBlock.blockHash; +} - (uint32_t)chainTipHeight { return self.lastTerminalBlock.height; } @@ -1072,7 +1075,7 @@ - (BOOL)addBlock:(DSBlock *)block receivedAsHeader:(BOOL)isHeaderOnly fromPeer:( NSValue *blockHash = uint256_obj(block.blockHash), *prevBlock = uint256_obj(block.prevBlock); DSBlock *prev = nil; - DSLog(@"[%@] + block (asHeader: %u) %@ prev: %@", self.name, isHeaderOnly, uint256_hex(block.blockHash), uint256_hex(block.prevBlock)); + //DSLog(@"[%@] + block (asHeader: %u) %@ prev: %@", self.name, isHeaderOnly, uint256_hex(block.blockHash), uint256_hex(block.prevBlock)); DSBlockPosition blockPosition = DSBlockPosition_Orphan; DSChainSyncPhase phase = self.chainManager.syncPhase; diff --git a/DashSync/shared/Models/CoinJoin/DSCoinJoinManager.m b/DashSync/shared/Models/CoinJoin/DSCoinJoinManager.m index de3f78448..af77a0c9f 100644 --- a/DashSync/shared/Models/CoinJoin/DSCoinJoinManager.m +++ b/DashSync/shared/Models/CoinJoin/DSCoinJoinManager.m @@ -97,7 +97,7 @@ - (void)initMasternodeGroup { } - (DCoinJoinClientOptions *)createOptions { - DCoinJoinClientOptions *options = dash_spv_coinjoin_models_coinjoin_client_options_CoinJoinClientOptions_ctor(true, DUFFS / 8, 6, 1, COINJOIN_RANDOM_ROUNDS, DEFAULT_COINJOIN_DENOMS_GOAL, DEFAULT_COINJOIN_DENOMS_HARDCAP, false, self.chain.chainType, false); + DCoinJoinClientOptions *options = dash_spv_coinjoin_models_coinjoin_client_options_CoinJoinClientOptions_ctor(true, DUFFS_OBJC / 8, 6, 1, COINJOIN_RANDOM_ROUNDS, DEFAULT_COINJOIN_DENOMS_GOAL, DEFAULT_COINJOIN_DENOMS_HARDCAP, false, self.chain.chainType, false); return options; } @@ -586,7 +586,7 @@ - (uint32_t)countInputsWithAmount:(uint64_t)inputAmount { } found = !dash_spv_coinjoin_coinjoin_CoinJoin_is_denominated_amount(value); } else if (coinType == dash_spv_coinjoin_models_coin_control_CoinType_OnlyMasternodeCollateral) { - found = value == 1000 * DUFFS; + found = value == 1000 * DUFFS_OBJC; } else if (coinType == dash_spv_coinjoin_models_coin_control_CoinType_OnlyCoinJoinCollateral) { found = dash_spv_coinjoin_coinjoin_CoinJoin_is_collateral_amount(value); } else { @@ -626,7 +626,7 @@ - (uint32_t)countInputsWithAmount:(uint64_t)inputAmount { [vCoins addObject:[[DSInputCoin alloc] initWithTx:coin index:i]]; // Checks the sum amount of all UTXO's. - if (minimumSumAmount != MAX_MONEY) { + if (minimumSumAmount != MAX_MONEY_OBJC) { total += value; if (total >= minimumSumAmount) { diff --git a/DashSync/shared/Models/CoinJoin/DSCoinJoinWrapper.h b/DashSync/shared/Models/CoinJoin/DSCoinJoinWrapper.h index f818167d1..cfd44ba65 100644 --- a/DashSync/shared/Models/CoinJoin/DSCoinJoinWrapper.h +++ b/DashSync/shared/Models/CoinJoin/DSCoinJoinWrapper.h @@ -43,6 +43,8 @@ NS_ASSUME_NONNULL_BEGIN #define DCoinJoinTransactionType dash_spv_coinjoin_models_coinjoin_tx_type_CoinJoinTransactionType #define DCoinJoinTransactionTypeIndex(ptr) dash_spv_coinjoin_models_coinjoin_tx_type_CoinJoinTransactionType_index(ptr) #define DCoinJoinClientOptions dash_spv_coinjoin_models_coinjoin_client_options_CoinJoinClientOptions +#define DCoinJoinClientOptionsCtor(enable, amount, sessions, rounds, random_rounds, denoms_goal, denoms_hardcap, multi_session, chain_type, denom_only) dash_spv_coinjoin_models_coinjoin_client_options_CoinJoinClientOptions_ctor(enable, amount, sessions, rounds, random_rounds, denoms_goal, denoms_hardcap, multi_session, chain_type, denom_only) +#define DCoinJoinClientOptionsDtor(ptr) dash_spv_coinjoin_models_coinjoin_client_options_CoinJoinClientOptions_destroy(ptr) #define DInputCoin dash_spv_coinjoin_coin_selection_input_coin_InputCoin #define DInputCoinCtor(outpoint, out, value) dash_spv_coinjoin_coin_selection_input_coin_InputCoin_ctor(outpoint, out, value) #define DInputCoinDtor(ptr) dash_spv_coinjoin_coin_selection_input_coin_InputCoin_destroy(ptr) diff --git a/DashSync/shared/Models/CoinJoin/DSCoinJoinWrapper.m b/DashSync/shared/Models/CoinJoin/DSCoinJoinWrapper.m index db67ef88d..129661474 100644 --- a/DashSync/shared/Models/CoinJoin/DSCoinJoinWrapper.m +++ b/DashSync/shared/Models/CoinJoin/DSCoinJoinWrapper.m @@ -17,7 +17,7 @@ #import "DSCoinJoinManager.h" #import "DSWallet.h" -#import "DSTransaction+CoinJoin.h" +#import "DSTransaction+FFI.h" #import "DSAccount.h" #import "DSChain+Params.h" #import "DSChain+Transaction.h" @@ -393,8 +393,8 @@ bool isMineInput(const void *context, DOutPoint *outpoint) { onlySafe:onlySafe coinControl:cc minimumAmount:1 - maximumAmount:MAX_MONEY - minimumSumAmount:MAX_MONEY + maximumAmount:MAX_MONEY_OBJC + minimumSumAmount:MAX_MONEY_OBJC maximumCount:0]; DCoinControlDtor(coinControl); NSUInteger count = coins.count; @@ -435,7 +435,7 @@ bool isMineInput(const void *context, DOutPoint *outpoint) { DTransaction* signTransaction(const void *context, DTransaction *transaction, bool anyoneCanPay) { @synchronized (context) { DSCoinJoinWrapper *wrapper = AS_OBJC(context); - DSTransaction *tx = [[DSTransaction alloc] initWithTransaction:transaction onChain:wrapper.chain]; + DSTransaction *tx = [DSTransaction ffi_from:transaction onChain:wrapper.chain]; DTransactionDtor(transaction); BOOL isSigned = [wrapper.chain.wallets.firstObject.accounts.firstObject signTransaction:tx anyoneCanPay:anyoneCanPay]; if (isSigned) { diff --git a/DashSync/shared/Models/CoinJoin/DSInputCoin.m b/DashSync/shared/Models/CoinJoin/DSInputCoin.m index 285b96ff8..e63789f86 100644 --- a/DashSync/shared/Models/CoinJoin/DSInputCoin.m +++ b/DashSync/shared/Models/CoinJoin/DSInputCoin.m @@ -16,6 +16,7 @@ // #import "DSInputCoin.h" +#import "DSTransactionOutput+FFI.h" @implementation DSInputCoin @@ -33,8 +34,7 @@ - (instancetype)initWithTx:(DSTransaction *)tx index:(int32_t)i { - (DInputCoin *)ffi_malloc:(DChainType *)type { // TODO: check outpoint hash reverse or not DOutPoint *outpoint = DOutPointCtorU(self.outpointHash, self.outpointIndex); - DTxOut *tx_out = DTxOutCtor(self.output.amount, DScriptBufCtor(bytes_ctor(self.output.outScript))); - return DInputCoinCtor(outpoint, tx_out, self.effectiveValue); + return DInputCoinCtor(outpoint, [self.output ffi_malloc], self.effectiveValue); } + (void)ffi_free:(DInputCoin *)inputCoin { diff --git a/DashSync/shared/Models/CoinJoin/Utils/DSMasternodeGroup.m b/DashSync/shared/Models/CoinJoin/Utils/DSMasternodeGroup.m index 3f41c15a8..c431ee2f6 100644 --- a/DashSync/shared/Models/CoinJoin/Utils/DSMasternodeGroup.m +++ b/DashSync/shared/Models/CoinJoin/Utils/DSMasternodeGroup.m @@ -448,14 +448,15 @@ - (BOOL)connectTo:(DSPeer *)peer { DSLog(@"[%@] CoinJoin: session is not connected to a masternode, sessionId: %@", self.chain.name, uint256_hex(sessionId)); return NO; } - + DSChainManager *chainManager = self.chain.chainManager; DSLog(@"[%@] CoinJoin: masternode[connecting] %@: %@; %@", self.chain.name, peer.location, uint256_hex(proTxHash), uint256_hex(sessionId)); - [peer setChainDelegate:self.chain.chainManager - peerDelegate:self transactionDelegate:self.chain.chainManager.transactionManager - governanceDelegate:self.chain.chainManager.governanceSyncManager - sporkDelegate:self.chain.chainManager.sporkManager - masternodeDelegate:self.chain.chainManager.masternodeManager + [peer setChainDelegate:chainManager + peerDelegate:self + transactionDelegate:(id) chainManager.transactionManager + governanceDelegate:(id) chainManager.governanceSyncManager + sporkDelegate:(id) chainManager.sporkManager + masternodeDelegate:chainManager.masternodeManager queue:self.networkingQueue]; peer.earliestKeyTime = self.chain.earliestWalletCreationTime;; diff --git a/DashSync/shared/Models/Derivation Paths/DSAuthenticationKeysDerivationPath.h b/DashSync/shared/Models/Derivation Paths/DSAuthenticationKeysDerivationPath.h index ab32972f0..d9922c08b 100644 --- a/DashSync/shared/Models/Derivation Paths/DSAuthenticationKeysDerivationPath.h +++ b/DashSync/shared/Models/Derivation Paths/DSAuthenticationKeysDerivationPath.h @@ -29,6 +29,7 @@ NS_ASSUME_NONNULL_BEGIN - (DMaybeOpaqueKey *_Nullable)privateKeyAtIndexPath:(NSIndexPath *)indexPath; +- (UInt256)keyIdAtIndex:(uint32_t)index; @end NS_ASSUME_NONNULL_END diff --git a/DashSync/shared/Models/Derivation Paths/DSAuthenticationKeysDerivationPath.m b/DashSync/shared/Models/Derivation Paths/DSAuthenticationKeysDerivationPath.m index 22c295854..1da0f8242 100644 --- a/DashSync/shared/Models/Derivation Paths/DSAuthenticationKeysDerivationPath.m +++ b/DashSync/shared/Models/Derivation Paths/DSAuthenticationKeysDerivationPath.m @@ -313,4 +313,9 @@ - (void)storeNewAddressInContext:(NSString *)address }]; } +- (UInt256)keyIdAtIndex:(uint32_t)index { + NSData *data = [self publicKeyDataAtIndexPath:[NSIndexPath indexPathWithIndex:index]]; + return [data SHA256]; +} + @end diff --git a/DashSync/shared/Models/Entities/DSInstantSendLockEntity+CoreDataClass.m b/DashSync/shared/Models/Entities/DSInstantSendLockEntity+CoreDataClass.m index f5674ff39..751219b1f 100644 --- a/DashSync/shared/Models/Entities/DSInstantSendLockEntity+CoreDataClass.m +++ b/DashSync/shared/Models/Entities/DSInstantSendLockEntity+CoreDataClass.m @@ -11,7 +11,7 @@ #import "DSInstantSendLockEntity+CoreDataClass.h" #import "DSInstantSendTransactionLock.h" #import "DSTransactionEntity+CoreDataClass.h" -#import "DSTransactionHashEntity+CoreDataClass.m" +#import "DSTransactionHashEntity+CoreDataClass.h" #import "DSTxInputEntity+CoreDataClass.h" #import "NSData+Dash.h" #import "NSManagedObject+Sugar.h" @@ -50,13 +50,13 @@ - (DSInstantSendTransactionLock *)instantSendTransactionLockForChain:(DSChain *) [inputOutpoints addObject:dsutxo_data(input.outpoint)]; } return [[DSInstantSendTransactionLock alloc] initWithTransactionHash:self.transaction.transactionHash.txHash - withInputOutpoints:inputOutpoints - version:self.version - signature:self.signature - cycleHash:self.cycleHash - signatureVerified:TRUE - quorumVerified:TRUE - onChain:chain]; + withInputOutpoints:inputOutpoints + version:self.version + signature:self.signature + cycleHash:self.cycleHash + signatureVerified:TRUE + quorumVerified:TRUE + onChain:chain]; } @end diff --git a/DashSync/shared/Models/Identity/DSIdentity.h b/DashSync/shared/Models/Identity/DSIdentity.h index 7139dafb9..7977e18e4 100644 --- a/DashSync/shared/Models/Identity/DSIdentity.h +++ b/DashSync/shared/Models/Identity/DSIdentity.h @@ -203,11 +203,14 @@ NSString * DSIdentityQueryStepsDescription(DSIdentityQueryStep step); */ - (BOOL)unregisterLocally; -/*! @brief Register the blockchain identity to its wallet from a credit funding registration transaction. This should only be done once on the creation of the blockchain identity. +/*! @brief Register the blockchain identity to its wallet from a asset lock transaction. This should only be done once on the creation of the blockchain identity. @param transaction The asset lock transaction used to initially fund the blockchain identity. */ - (void)registerInWalletForAssetLockTransaction:(DSAssetLockTransaction *)transaction; + +- (void)registerInWalletForAssetLockTopupTransaction:(DSAssetLockTransaction *)transaction; + // MARK: - Keys /*! @brief Register the blockchain identity to its wallet from a credit funding registration transaction. This should only be done once on the creation of the blockchain identity. diff --git a/DashSync/shared/Models/Identity/DSIdentity.m b/DashSync/shared/Models/Identity/DSIdentity.m index e691b0c34..a4b40f012 100644 --- a/DashSync/shared/Models/Identity/DSIdentity.m +++ b/DashSync/shared/Models/Identity/DSIdentity.m @@ -32,6 +32,7 @@ #import "DSFriendRequestEntity+CoreDataClass.h" #import "DSMerkleBlock.h" #import "DSOptionsManager.h" +#import "DSTransactionOutput+FFI.h" #import "DSTransactionHashEntity+CoreDataClass.h" #import "DSWallet+Identity.h" #import "NSData+Encryption.h" @@ -1317,7 +1318,7 @@ - (DAssetLockProof *)createInstantProof:(DInstantLock *)isLock { DTxOut **tx_outputs = malloc(sizeof(DTxOut *) * outputsCount); for (int i = 0; i < outputs.count; i++) { DSTransactionOutput *o = outputs[i]; - tx_outputs[i] = DTxOutCtor(o.amount, DScriptBufCtor(o.outScript ? bytes_ctor(o.outScript) : bytes_ctor([NSData data]))); + tx_outputs[i] = [o ffi_malloc]; } uint8_t asset_lock_payload_version = self.registrationAssetLockTransaction.specialTransactionVersion; @@ -1326,7 +1327,7 @@ - (DAssetLockProof *)createInstantProof:(DInstantLock *)isLock { DTxOut **credit_outputs = malloc(sizeof(DTxOut *) * creditOutputsCount); for (int i = 0; i < creditOutputsCount; i++) { DSTransactionOutput *o = creditOutputs[i]; - credit_outputs[i] = DTxOutCtor(o.amount, DScriptBufCtor(o.outScript ? bytes_ctor(o.outScript) : bytes_ctor([NSData data]))); + credit_outputs[i] = [o ffi_malloc]; } DTxInputs *input_vec = DTxInputsCtor(inputsCount, tx_inputs); diff --git a/DashSync/shared/Models/Identity/DSInvitation.h b/DashSync/shared/Models/Identity/DSInvitation.h index 428d8f21f..1f4996e13 100644 --- a/DashSync/shared/Models/Identity/DSInvitation.h +++ b/DashSync/shared/Models/Identity/DSInvitation.h @@ -47,7 +47,7 @@ FOUNDATION_EXPORT NSString *const DSInvitationUpdateEventLink; @property (nonatomic, weak, readonly) DSWallet *wallet; /*! @brief A name for locally created invitation. */ -@property (nonatomic, copy) NSString *name; +@property (nonatomic, nullable, copy) NSString *name; /*! @brief A tag for locally created invitation. */ @property (nonatomic, copy) NSString *tag; diff --git a/DashSync/shared/Models/Identity/DSInvitation.m b/DashSync/shared/Models/Identity/DSInvitation.m index afc18d8ae..aca7f3e8b 100644 --- a/DashSync/shared/Models/Identity/DSInvitation.m +++ b/DashSync/shared/Models/Identity/DSInvitation.m @@ -16,17 +16,18 @@ // #import "DSInvitation.h" +#import "DSAssetLockDerivationPath.h" #import "DSAuthenticationManager.h" -#import "DSIdentity+Profile.h" -#import "DSIdentity+Protected.h" -#import "DSIdentity+Username.h" #import "DSBlockchainInvitationEntity+CoreDataClass.h" #import "DSChain+Params.h" #import "DSChainManager.h" -#import "DSAssetLockDerivationPath.h" #import "DSDerivationPathFactory.h" #import "DSIdentitiesManager+Protected.h" +#import "DSIdentity+Profile.h" +#import "DSIdentity+Protected.h" +#import "DSIdentity+Username.h" #import "DSInstantSendTransactionLock.h" +#import "DSTransaction+FFI.h" #import "DSWallet.h" #import "DSWallet+Identity.h" #import "DSWallet+Invitation.h" diff --git a/DashSync/shared/Models/Managers/Chain Managers/DSIdentitiesManager.h b/DashSync/shared/Models/Managers/Chain Managers/DSIdentitiesManager.h index 137e61afd..52e82a6c0 100644 --- a/DashSync/shared/Models/Managers/Chain Managers/DSIdentitiesManager.h +++ b/DashSync/shared/Models/Managers/Chain Managers/DSIdentitiesManager.h @@ -22,7 +22,7 @@ NS_ASSUME_NONNULL_BEGIN @class DSChain, DSIdentity, DSAssetLockTransaction, DSTransientDashpayUser; -@protocol DSDAPINetworkServiceRequest; +//@protocol DSDAPINetworkServiceRequest; typedef void (^IdentitiesSuccessCompletionBlock)(NSArray *_Nullable identities); typedef void (^IdentitiesCompletionBlock)(BOOL success, NSArray *_Nullable identities, NSArray *errors); diff --git a/DashSync/shared/Models/Managers/Chain Managers/DSKeyManager.h b/DashSync/shared/Models/Managers/Chain Managers/DSKeyManager.h index 156dd0f26..0b1925334 100644 --- a/DashSync/shared/Models/Managers/Chain Managers/DSKeyManager.h +++ b/DashSync/shared/Models/Managers/Chain Managers/DSKeyManager.h @@ -183,21 +183,6 @@ #define DCoreProviderError dash_spv_masternode_processor_processing_core_provider_CoreProviderError #define DCoreProviderErrorNullResultCtor(message) dash_spv_masternode_processor_processing_core_provider_CoreProviderError_NullResult_ctor(message) -#define MaybeBool Result_ok_bool_err_dash_spv_masternode_processor_processing_core_provider_CoreProviderError -#define MaybeLLMQSnapshot Result_ok_dash_spv_masternode_processor_models_snapshot_LLMQSnapshot_err_dash_spv_masternode_processor_processing_core_provider_CoreProviderError - -#define DBlock dash_spv_masternode_processor_common_block_Block -#define DBlockCtor(height, hash) dash_spv_masternode_processor_common_block_Block_ctor(height, hash) - -#define DMBlock dash_spv_masternode_processor_common_block_MBlock -#define DMBlockCtor(height, hash, merkle_root) dash_spv_masternode_processor_common_block_MBlock_ctor(height, hash, merkle_root) - -#define DMaybeBlock Result_ok_dash_spv_masternode_processor_common_block_Block_err_dash_spv_masternode_processor_processing_core_provider_CoreProviderError -#define DMaybeBlockCtor(ok, err) Result_ok_dash_spv_masternode_processor_common_block_Block_err_dash_spv_masternode_processor_processing_core_provider_CoreProviderError_ctor(ok, err) -#define DMaybeBlockDtor(ptr) Result_ok_dash_spv_masternode_processor_common_block_Block_err_dash_spv_masternode_processor_processing_core_provider_CoreProviderError_destroy(ptr) - -#define DMaybeMBlock Result_ok_dash_spv_masternode_processor_common_block_MBlock_err_dash_spv_masternode_processor_processing_core_provider_CoreProviderError -#define DMaybeMBlockCtor(ok, err) Result_ok_dash_spv_masternode_processor_common_block_MBlock_err_dash_spv_masternode_processor_processing_core_provider_CoreProviderError_ctor(ok, err) #define DMasternodeList dashcore_sml_masternode_list_MasternodeList #define DMasternodeListDtor(ptr) dashcore_sml_masternode_list_MasternodeList_destroy(ptr) @@ -212,11 +197,12 @@ #define DLLMQEntry dashcore_sml_quorum_entry_qualified_quorum_entry_QualifiedQuorumEntry #define DLLMQEntryDtor(ptr) dashcore_sml_quorum_entry_qualified_quorum_entry_QualifiedQuorumEntry_destroy(ptr) -#define DLLMQEntryList Vec_dash_spv_crypto_llmq_entry_LLMQEntry -#define DLLMQEntryListCtor(count, list) Vec_dash_spv_crypto_llmq_entry_LLMQEntry_ctor(count, list) +#define DLLMQType dashcore_sml_llmq_type_LLMQType +#define DLLMQTypeIndex(ptr) dashcore_sml_llmq_type_LLMQType_index(ptr) +#define DLLMQSnapshot dashcore_network_message_qrinfo_QuorumSnapshot + +#define DPlatformError dash_spv_platform_error_Error -#define DLLMQType dash_spv_crypto_network_llmq_type_LLMQType -#define DLLMQSnapshot dash_spv_masternode_processor_models_snapshot_LLMQSnapshot #define DKeyError dash_spv_crypto_keys_KeyError #define DKeyKind dash_spv_crypto_keys_key_KeyKind #define DKeyKindIndex(kind) dash_spv_crypto_keys_key_KeyKind_index(kind) @@ -326,6 +312,11 @@ #define DMaybeKeyString Result_ok_String_err_dash_spv_crypto_keys_KeyError #define DChainType dash_spv_crypto_network_chain_type_ChainType #define DDevnetType dash_spv_crypto_network_chain_type_DevnetType +#define DChainTypeMainnet() dash_spv_crypto_network_chain_type_ChainType_MainNet_ctor() +#define DChainTypeTestnet() dash_spv_crypto_network_chain_type_ChainType_TestNet_ctor() +#define DChainTypeDevnet(devnet) dash_spv_crypto_network_chain_type_ChainType_DevNet_ctor(devnet) +#define DChainTypeDevnetFromID(identifier) dash_spv_crypto_network_chain_type_devnet_type_from_identifier(identifier) + #define DIndexPathU256 dash_spv_crypto_keys_key_IndexPathU256 #define DMaybeOpaqueKeyDtor(ptr) Result_ok_dash_spv_crypto_keys_key_OpaqueKey_err_dash_spv_crypto_keys_KeyError_destroy(ptr) #define DMaybeKeyDataDtor(ptr) Result_ok_Vec_u8_err_dash_spv_crypto_keys_KeyError_destroy(ptr) @@ -353,6 +344,8 @@ #define DMnDiffResult Result_Tuple_dashcore_hash_types_BlockHash_dashcore_hash_types_BlockHash_err_dash_spv_masternode_processor_processing_processor_processing_error_ProcessingError #define DMnDiffResultDtor(ptr) Result_Tuple_dashcore_hash_types_BlockHash_dashcore_hash_types_BlockHash_err_dash_spv_masternode_processor_processing_processor_processing_error_ProcessingError_destroy(ptr) +#define DKnownMasternodeLists std_collections_Map_keys_dashcore_prelude_CoreBlockHeight_values_dashcore_sml_masternode_list_MasternodeList +#define DKnownMasternodeListsDtor(ptr) std_collections_Map_keys_dashcore_prelude_CoreBlockHeight_values_dashcore_sml_masternode_list_MasternodeList_destroy(ptr) #define DMasternodeListForBlockHash(processor, block_hash) dash_spv_masternode_processor_processing_processor_MasternodeProcessor_masternode_list_for_block_hash(processor, block_hash) #define DMasternodeListByBlockHash(cache, block_hash) dash_spv_masternode_processor_processing_processor_cache_MasternodeProcessorCache_masternode_list_by_block_hash(cache, block_hash) diff --git a/DashSync/shared/Models/Managers/Chain Managers/DSMasternodeManager.h b/DashSync/shared/Models/Managers/Chain Managers/DSMasternodeManager.h index 7f6694faf..1a08e6e4a 100644 --- a/DashSync/shared/Models/Managers/Chain Managers/DSMasternodeManager.h +++ b/DashSync/shared/Models/Managers/Chain Managers/DSMasternodeManager.h @@ -101,6 +101,8 @@ FOUNDATION_EXPORT NSString *const DSQuorumListDidChangeNotification; - (NSSet *)blockHashesUsedByMasternodeLists; +- (uintptr_t)currentQuorumsOfType:(DLLMQType)type; +- (uintptr_t)currentValidQuorumsOfType:(DLLMQType)type; @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 5a784119c..0105b8fb5 100644 --- a/DashSync/shared/Models/Managers/Chain Managers/DSMasternodeManager.m +++ b/DashSync/shared/Models/Managers/Chain Managers/DSMasternodeManager.m @@ -63,6 +63,7 @@ @interface DSMasternodeManager () @property (nonatomic, strong) NSManagedObjectContext *managedObjectContext; @property (nonatomic) BOOL isSyncing; @property (nonatomic) BOOL isRestored; +@property (nonatomic, strong) NSData* baseBlockHashWaitingForDiffs; @end @@ -103,7 +104,10 @@ - (BOOL)hasCurrentMasternodeListInLast30Days { - (void)masternodeListServiceEmptiedRetrievalQueue:(DSMasternodeListService *)service { - [self.chain.chainManager chainFinishedSyncingMasternodeListsAndQuorums:self.chain]; + if (self.baseBlockHashWaitingForDiffs) + [self getRecentMasternodeList]; + else + [self.chain.chainManager chainFinishedSyncingMasternodeListsAndQuorums:self.chain]; } @@ -332,10 +336,8 @@ - (void)stopSync { DSLog(@"%@ [Stop]", self.logPrefix); self.isSyncing = NO; [self cancelMasternodeListTimer]; - - if (self.chain.isRotatedQuorumsPresented) { + if (self.chain.isRotatedQuorumsPresented) [self.quorumRotationService stop]; - } [self.masternodeListDiffService stop]; } @@ -452,9 +454,7 @@ - (void)peer:(DSPeer *)peer relayedMasternodeDiffMessage:(NSData *)message { dispatch_async(self.processingQueue, ^{ dispatch_group_enter(self.processingGroup); Slice_u8 *message_slice = slice_ctor(message); - - DMnDiffResult *result = DMnDiffFromMessage(self.processor, message_slice, nil, true); - + DMnDiffResult *result = DMnDiffFromMessage(self.processor, message_slice, nil, false); if (result->error) { NSError *error = [NSError ffi_from_processing_error:result->error]; DSLog(@"%@ mnlistdiff: Error: %@", self.logPrefix, error.description); @@ -464,57 +464,44 @@ - (void)peer:(DSPeer *)peer relayedMasternodeDiffMessage:(NSData *)message { break; case dash_spv_masternode_processor_processing_processor_processing_error_ProcessingError_InvalidResult: [self.masternodeListDiffService cleanRequestsInRetrieval]; - DSLog(@"%@ mnlistdiff: InvalidResult -> dequeueMasternodeListRequest (mn)", self.chain.name); [self.masternodeListDiffService dequeueMasternodeListRequest]; default: [self issueWithMasternodeListFromPeer:peer]; break; } -//#if SAVE_MASTERNODE_DIFF_TO_FILE -// NSString *fileName = [NSString stringWithFormat:@"MNL_ERR__%d.dat", peer.version]; -// DSLog(@"%@ •-• File %@ saved", self.logPrefix, fileName); -// [message saveToFile:fileName inDirectory:NSCachesDirectory]; -//#endif - + #if SAVE_MASTERNODE_DIFF_TO_FILE + [self writeToDisk:[NSString stringWithFormat:@"MNL_ERR__%d_%lu.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 *block_hash = dashcore_hash_types_BlockHash_inner(result->ok->o_1); NSData *blockHashData = NSDataFromPtr(block_hash); u256_dtor(block_hash); [self.masternodeListDiffService removeFromRetrievalQueue:blockHashData]; - [self.masternodeListDiffService dequeueMasternodeListRequest]; - if (![self.masternodeListDiffService retrievalQueueCount]) - [self.chain.chainManager.transactionManager checkWaitingForQuorums]; - [[NSUserDefaults standardUserDefaults] removeObjectForKey:CHAIN_FAULTY_DML_MASTERNODE_PEERS]; - -// [self.masternodeListDiffService updateAfterProcessingMasternodeListWithBlockHash:masternodeListBlockHashData fromPeer:peer]; + + if ([self.masternodeListDiffService retrievalQueueCount]) { + [self.masternodeListDiffService dequeueMasternodeListRequest]; + } else { + DSLog(@"%@: All diffs are here -> Re-request QRINFO for", self.logPrefix, self.baseBlockHashWaitingForDiffs.hexString); + [self getRecentMasternodeList]; + } } -//#if SAVE_MASTERNODE_DIFF_TO_FILE -// u256 *base_block_hash = result->ok->o_0; -// uint32_t base_block_height = DHeightForBlockHash(self.processor, base_block_hash); -// uint32_t block_height = DHeightForBlockHash(self.processor, block_hash); -// NSString *fileName = [NSString stringWithFormat:@"MNL_%@_%@__%d.dat", @(base_block_height), @(block_height), peer.version]; -// DSLog(@"%@ •-• File %@ saved", self.logPrefix, fileName); -// [message saveToFile:fileName inDirectory:NSCachesDirectory]; -//#endif -// DMnDiffResultDtor(result); DMnDiffResultDtor(result); - dispatch_group_leave(self.processingGroup); }); } - (void)tryToProcessQrInfo:(DSPeer *)peer message:(NSData *)message attempt:(uint8_t)attempt { - // uint32_t protocol_version = peer ? peer.version : self.chain.protocolVersion; __block NSUInteger numOfAttempt = attempt; dispatch_async(self.processingQueue, ^{ dispatch_group_enter(self.processingGroup); Slice_u8 *slice_msg = slice_ctor(message); - DQRInfoResult *result = dash_spv_masternode_processor_processing_processor_MasternodeProcessor_process_qr_info_result_from_message(self.processor, slice_msg, true, true); + DQRInfoResult *result = dash_spv_masternode_processor_processing_processor_MasternodeProcessor_process_qr_info_result_from_message(self.processor, slice_msg, false, true); if (result->error) { NSError *error = [NSError ffi_from_processing_error:result->error]; DSLog(@"%@ qrinfo: Error: %@", self.logPrefix, error); @@ -530,13 +517,11 @@ - (void)tryToProcessQrInfo:(DSPeer *)peer message:(NSData *)message attempt:(uin case dash_spv_masternode_processor_processing_processor_processing_error_ProcessingError_QuorumValidationError: switch (result->error->quorum_validation_error->tag) { case dashcore_sml_quorum_validation_error_QuorumValidationError_RequiredBlockNotPresent: { -// DBlockHash *unknown_block_hash = result->error->quorum_validation_error->required_block_not_present; - // TODO: it can be tip so we can wait for 300ms and try again if (attempt < 3) { - sleep(10); - numOfAttempt++; - dispatch_group_leave(self.processingGroup); - [self tryToProcessQrInfo:peer message:message attempt:attempt]; + dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(1 * NSEC_PER_SEC)), self.processingQueue, ^{ + numOfAttempt++; + [self tryToProcessQrInfo:peer message:message attempt:attempt]; + }); } break; } @@ -548,9 +533,7 @@ - (void)tryToProcessQrInfo:(DSPeer *)peer message:(NSData *)message attempt:(uin break; } #if SAVE_MASTERNODE_DIFF_TO_FILE - NSString *fileName = [NSString stringWithFormat:@"QRINFO_ERR_%d.dat", peer.version]; - DSLog(@"%@ •-• File %@ saved", self.logPrefix, fileName); - [message saveToFile:fileName inDirectory:NSCachesDirectory]; + [self writeToDisk:[NSString stringWithFormat:@"QRINFO_ERR_%d_%lu.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); @@ -567,30 +550,23 @@ - (void)tryToProcessQrInfo:(DSPeer *)peer message:(NSData *)message attempt:(uin dispatch_group_leave(self.processingGroup); return; } + [[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); if (missed_hashes->count > 0) { + self.baseBlockHashWaitingForDiffs = [self.quorumRotationService retrievalBlockHash]; + [self.quorumRotationService cleanAllLists]; NSArray *missedHashes = [NSArray ffi_from_block_hash_btree_set:missed_hashes]; [self.masternodeListDiffService addToRetrievalQueueArray:missedHashes]; - } - - //#if SAVE_MASTERNODE_DIFF_TO_FILE - // u256 *base_block_hash = result->ok->o_0; - // uint32_t base_block_height = DHeightForBlockHash(self.processor, base_block_hash); - // uint32_t block_height = DHeightForBlockHash(self.processor, block_hash); - // NSString *fileName = [NSString stringWithFormat:@"QRINFO_%@_%@__%d.dat", @(base_block_height), @(block_height), peer.version]; - // DSLog(@"%@ •-• File %@ saved", self.logPrefix, fileName); - // [message saveToFile:fileName inDirectory:NSCachesDirectory]; - //#endif - // [self.quorumRotationService updateAfterProcessingMasternodeListWithBlockHash:NSDataFromPtr(block_hash) fromPeer:peer]; - - [self.quorumRotationService cleanListsRetrievalQueue]; - [self.quorumRotationService dequeueMasternodeListRequest]; - if (missed_hashes->count == 0) + [self.masternodeListDiffService dequeueMasternodeListRequest]; + } else { + self.baseBlockHashWaitingForDiffs = nil; + [self.quorumRotationService cleanAllLists]; + [self.quorumRotationService dequeueMasternodeListRequest]; [self.chain.chainManager.transactionManager checkWaitingForQuorums]; - [[NSUserDefaults standardUserDefaults] removeObjectForKey:CHAIN_FAULTY_DML_MASTERNODE_PEERS]; + } - DQRInfoResultDtor(result); dispatch_group_leave(self.processingGroup); }); @@ -601,7 +577,6 @@ - (void)peer:(DSPeer *)peer relayedQuorumRotationInfoMessage:(NSData *)message { @synchronized (self.quorumRotationService) { self.quorumRotationService.timedOutAttempt = 0; } - [self tryToProcessQrInfo:peer message:message attempt:0]; } @@ -623,4 +598,12 @@ - (void)checkPingTimesForCurrentMasternodeListInContext:(NSManagedObjectContext } +- (uintptr_t)currentQuorumsOfType:(DLLMQType)type { + return dash_spv_masternode_processor_processing_processor_MasternodeProcessor_current_quorums_of_type_count(self.processor, &type); + +} +- (uintptr_t)currentValidQuorumsOfType:(DLLMQType)type { + return dash_spv_masternode_processor_processing_processor_MasternodeProcessor_current_valid_quorums_of_type_count(self.processor, &type); +} + @end diff --git a/DashSync/shared/Models/Managers/Chain Managers/DSTransactionManager.m b/DashSync/shared/Models/Managers/Chain Managers/DSTransactionManager.m index bfb818c52..349286cb4 100644 --- a/DashSync/shared/Models/Managers/Chain Managers/DSTransactionManager.m +++ b/DashSync/shared/Models/Managers/Chain Managers/DSTransactionManager.m @@ -1754,13 +1754,9 @@ - (void)peer:(DSPeer *)peer relayedTooManyOrphanBlocks:(NSUInteger)orphanBlockCo - (void)peer:(DSPeer *)peer relayedChainLock:(DSChainLock *)chainLock { BOOL verified = [chainLock verifySignature]; - UInt256 clBlockHash = chainLock.blockHash; - UInt256 clBlockHashRev = uint256_reverse(clBlockHash); - DSLog(@"[%@: %@:%d] relayed chain lock %@", self.chain.name, peer.host, peer.port, uint256_hex(clBlockHash)); - + UInt256 clBlockHash = uint256_reverse(chainLock.blockHash); DSMerkleBlock *block = [self.chain blockForBlockHash:clBlockHash]; - if (!block) - block = [self.chain blockForBlockHash:clBlockHashRev]; + DSLog(@"[%@: %@:%d] relayed chain lock %@ (verified: %u)", self.chain.name, peer.host, peer.port, uint256_hex(clBlockHash), verified); if (block) { [self.chain addChainLock:chainLock]; diff --git a/DashSync/shared/Models/Managers/Service Managers/DSPriceManager.m b/DashSync/shared/Models/Managers/Service Managers/DSPriceManager.m index 0cc2cc920..b72fc2071 100644 --- a/DashSync/shared/Models/Managers/Service Managers/DSPriceManager.m +++ b/DashSync/shared/Models/Managers/Service Managers/DSPriceManager.m @@ -58,7 +58,7 @@ #define VOLATILE_RATES_CUTTOFF_PERIOD 7 * 24 * 60 * 60 // 7 Days #define DEFAULT_CURRENCY_CODE @"USD" -#define DEFAULT_SPENT_LIMIT DUFFS +#define DEFAULT_SPENT_LIMIT DUFFS_OBJC #define LOCAL_CURRENCY_CODE_KEY @"LOCAL_CURRENCY_CODE" @@ -113,7 +113,7 @@ - (instancetype)init { self.dashFormat.currencySymbol = DASH; self.dashFormat.maximumFractionDigits = 8; self.dashFormat.minimumFractionDigits = 0; // iOS 8 bug, minimumFractionDigits now has to be set after currencySymbol - self.dashFormat.maximum = @(MAX_MONEY / (int64_t)pow(10.0, self.dashFormat.maximumFractionDigits)); + self.dashFormat.maximum = @(MAX_MONEY_OBJC / (int64_t)pow(10.0, self.dashFormat.maximumFractionDigits)); _csvDashFormat = [self.dashFormat copy]; self.csvDashFormat.currencyCode = @""; @@ -137,7 +137,7 @@ - (instancetype)init { self.dashSignificantFormat.maximumSignificantDigits = 6; self.dashSignificantFormat.maximumFractionDigits = 8; self.dashSignificantFormat.minimumFractionDigits = 0; // iOS 8 bug, minimumFractionDigits now has to be set after currencySymbol - self.dashSignificantFormat.maximum = @(MAX_MONEY / (int64_t)pow(10.0, self.dashFormat.maximumFractionDigits)); + self.dashSignificantFormat.maximum = @(MAX_MONEY_OBJC / (int64_t)pow(10.0, self.dashFormat.maximumFractionDigits)); _bitcoinFormat = [NSNumberFormatter new]; self.bitcoinFormat.lenient = YES; @@ -153,7 +153,7 @@ - (instancetype)init { self.bitcoinFormat.currencySymbol = BTC; self.bitcoinFormat.maximumFractionDigits = 8; self.bitcoinFormat.minimumFractionDigits = 0; // iOS 8 bug, minimumFractionDigits now has to be set after currencySymbol - self.bitcoinFormat.maximum = @(MAX_MONEY / (int64_t)pow(10.0, self.bitcoinFormat.maximumFractionDigits)); + self.bitcoinFormat.maximum = @(MAX_MONEY_OBJC / (int64_t)pow(10.0, self.bitcoinFormat.maximumFractionDigits)); _unknownFormat = [NSNumberFormatter new]; self.unknownFormat.lenient = YES; @@ -243,7 +243,7 @@ - (void)setLocalCurrencyCode:(NSString *)code { self.localFormat.currencyCode = _localCurrencyCode; self.localFormat.maximum = [[NSDecimalNumber decimalNumberWithDecimal:self.localCurrencyDashPrice.decimalValue] - decimalNumberByMultiplyingBy:(id)[NSDecimalNumber numberWithLongLong:MAX_MONEY / DUFFS]]; + decimalNumberByMultiplyingBy:(id)[NSDecimalNumber numberWithLongLong:MAX_MONEY_OBJC / DUFFS_OBJC]]; if ([self.localCurrencyCode isEqual:[NSLocale currentLocale].currencyCode]) { [defs removeObjectForKey:LOCAL_CURRENCY_CODE_KEY]; @@ -445,13 +445,13 @@ - (int64_t)amountForLocalCurrencyString:(NSString *)string overflowbits = 0, p = 10, min, max, amount; if (local == 0 || price < 1) return 0; - while (llabs(local) + 1 > INT64_MAX / DUFFS) local /= 2, overflowbits++; // make sure we won't overflow an int64_t - min = llabs(local) * DUFFS / price + 1; // minimum amount that safely matches local currency string - max = (llabs(local) + 1) * DUFFS / price - 1; // maximum amount that safely matches local currency string + while (llabs(local) + 1 > INT64_MAX / DUFFS_OBJC) local /= 2, overflowbits++; // make sure we won't overflow an int64_t + min = llabs(local) * DUFFS_OBJC / price + 1; // minimum amount that safely matches local currency string + max = (llabs(local) + 1) * DUFFS_OBJC / price - 1; // maximum amount that safely matches local currency string amount = (min + max) / 2; // average min and max while (overflowbits > 0) local *= 2, min *= 2, max *= 2, amount *= 2, overflowbits--; - if (amount >= MAX_MONEY) return (local < 0) ? -MAX_MONEY : MAX_MONEY; + if (amount >= MAX_MONEY_OBJC) return (local < 0) ? -MAX_MONEY_OBJC : MAX_MONEY_OBJC; while ((amount / p) * p >= min && p <= INT64_MAX / 10) p *= 10; // lowest decimal precision matching local currency string p /= 10; return (local < 0) ? -(amount / p) * p : (amount / p) * p; @@ -475,14 +475,14 @@ - (int64_t)amountForBitcoinCurrencyString:(NSString *)string { int64_t local = amt + DBL_EPSILON * amt, overflowbits = 0; if (local == 0) return 0; - while (llabs(local) + 1 > INT64_MAX / DUFFS) local /= 2, overflowbits++; // make sure we won't overflow an int64_t - int64_t min = llabs(local) * DUFFS / (int64_t)(price + DBL_EPSILON * price) + 1, - max = (llabs(local) + 1) * DUFFS / (int64_t)(price + DBL_EPSILON * price) - 1, + while (llabs(local) + 1 > INT64_MAX / DUFFS_OBJC) local /= 2, overflowbits++; // make sure we won't overflow an int64_t + int64_t min = llabs(local) * DUFFS_OBJC / (int64_t)(price + DBL_EPSILON * price) + 1, + max = (llabs(local) + 1) * DUFFS_OBJC / (int64_t)(price + DBL_EPSILON * price) - 1, amount = (min + max) / 2, p = 10; while (overflowbits > 0) local *= 2, min *= 2, max *= 2, amount *= 2, overflowbits--; - if (amount >= MAX_MONEY) return (local < 0) ? -MAX_MONEY : MAX_MONEY; + if (amount >= MAX_MONEY_OBJC) return (local < 0) ? -MAX_MONEY_OBJC : MAX_MONEY_OBJC; while ((amount / p) * p >= min && p <= INT64_MAX / 10) p *= 10; // lowest decimal precision matching local currency string p /= 10; return (local < 0) ? -(amount / p) * p : (amount / p) * p; @@ -494,7 +494,7 @@ - (NSString *)bitcoinCurrencyStringForAmount:(int64_t)amount { NSDecimalNumber *n = [[[NSDecimalNumber decimalNumberWithDecimal:self.bitcoinDashPrice.decimalValue] decimalNumberByMultiplyingBy:(id)[NSDecimalNumber numberWithLongLong:llabs(amount)]] - decimalNumberByDividingBy:(id)[NSDecimalNumber numberWithLongLong:DUFFS]], + decimalNumberByDividingBy:(id)[NSDecimalNumber numberWithLongLong:DUFFS_OBJC]], *min = [[NSDecimalNumber one] decimalNumberByMultiplyingByPowerOf10:-self.bitcoinFormat.maximumFractionDigits]; @@ -534,7 +534,7 @@ - (NSString *)localCurrencyStringForBitcoinAmount:(int64_t)amount { NSDecimalNumber *n = [[[NSDecimalNumber decimalNumberWithDecimal:self.localCurrencyBitcoinPrice.decimalValue] decimalNumberByMultiplyingBy:(id)[NSDecimalNumber numberWithLongLong:llabs(amount)]] - decimalNumberByDividingBy:(id)[NSDecimalNumber numberWithLongLong:DUFFS]], + decimalNumberByDividingBy:(id)[NSDecimalNumber numberWithLongLong:DUFFS_OBJC]], *min = [[NSDecimalNumber one] decimalNumberByMultiplyingByPowerOf10:-self.localFormat.maximumFractionDigits]; @@ -557,7 +557,7 @@ - (NSNumber *_Nullable)localCurrencyNumberForDashAmount:(int64_t)amount { NSDecimalNumber *n = [[[NSDecimalNumber decimalNumberWithDecimal:local.decimalValue] decimalNumberByMultiplyingBy:(id)[NSDecimalNumber numberWithLongLong:llabs(amount)]] - decimalNumberByDividingBy:(id)[NSDecimalNumber numberWithLongLong:DUFFS]], + decimalNumberByDividingBy:(id)[NSDecimalNumber numberWithLongLong:DUFFS_OBJC]], *min = [[NSDecimalNumber one] decimalNumberByMultiplyingByPowerOf10:-self.localFormat.maximumFractionDigits]; @@ -583,7 +583,7 @@ - (NSNumber *_Nullable)fiatCurrencyNumber:(NSString *)currencyCode forDashAmount NSDecimalNumber *n = [[[NSDecimalNumber decimalNumberWithDecimal:@(price).decimalValue] decimalNumberByMultiplyingBy:(id)[NSDecimalNumber numberWithLongLong:llabs(amount)]] - decimalNumberByDividingBy:(id)[NSDecimalNumber numberWithLongLong:DUFFS]], + decimalNumberByDividingBy:(id)[NSDecimalNumber numberWithLongLong:DUFFS_OBJC]], *min = [[NSDecimalNumber one] decimalNumberByMultiplyingByPowerOf10:-self.localFormat.maximumFractionDigits]; diff --git a/DashSync/shared/Models/Masternode/DSMasternodeListDiffService.m b/DashSync/shared/Models/Masternode/DSMasternodeListDiffService.m index 7221514e9..a772e3009 100644 --- a/DashSync/shared/Models/Masternode/DSMasternodeListDiffService.m +++ b/DashSync/shared/Models/Masternode/DSMasternodeListDiffService.m @@ -27,17 +27,39 @@ @interface DSMasternodeListDiffService () -@property (nonatomic, assign) NSMutableOrderedSet *retrievalQueue; +@property (nonatomic, strong) NSMutableOrderedSet *retrievalQueue; @end @implementation DSMasternodeListDiffService +- (instancetype)initWithChain:(DSChain *)chain { + NSParameterAssert(chain); + if (!(self = [super initWithChain:chain])) return nil; + _retrievalQueue = [NSMutableOrderedSet orderedSet]; + return self; +} + - (NSString *)logPrefix { - return [NSString stringWithFormat:@"[%@] [MLDiffService] ", self.chain.name]; + return [NSString stringWithFormat:@"[%@] [MasternodeManager::DiffService] ", self.chain.name]; } - (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]) { @@ -47,9 +69,8 @@ - (void)composeMasternodeListRequest:(NSOrderedSet *)list { BOOL success = [self.chain.masternodeManager processRequestFromFileForBlockHash:blockHash]; if (success) { [self removeFromRetrievalQueue:blockHashData]; - if (![self retrievalQueueCount]) { + if (![self retrievalQueueCount]) [self.chain.chainManager.transactionManager checkWaitingForQuorums]; - } } else { // we need to go get it uint32_t blockHeight = [self.chain heightForBlockHash:blockHash]; @@ -59,8 +80,6 @@ - (void)composeMasternodeListRequest:(NSOrderedSet *)list { u256 *prev_in_queue_block_hash = u256_ctor_u(prevInQueueBlockHash); uint32_t prevKnownHeight = [self.chain heightForBlockHash:u256_cast(prev_known_block_hash)]; uint32_t prevInQueueBlockHeight = [self.chain heightForBlockHash:u256_cast(prev_in_queue_block_hash)]; -// uint32_t prevKnownHeight = DHeightForBlockHash(self.chain.sharedProcessorObj, prev_known_block_hash); -// uint32_t prevInQueueBlockHeight = DHeightForBlockHash(self.chain.sharedProcessorObj, 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"); @@ -81,7 +100,7 @@ - (void)fetchMasternodeListsToRetrieve:(void (^)(NSOrderedSet *listsTo return; } if ([self.requestsInRetrieval count]) { - DSLog(@"%@ Already in retrieval", self.logPrefix); + //DSLog(@"%@ Already in retrieval", self.logPrefix); return; } if ([self peerIsDisconnected]) { @@ -194,6 +213,7 @@ - (void)requestMasternodeListDiff:(UInt256)previousBlockHash forBlockHash:(UInt2 } - (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; diff --git a/DashSync/shared/Models/Masternode/DSMasternodeListService.m b/DashSync/shared/Models/Masternode/DSMasternodeListService.m index 7e9f93746..c37d48f6e 100644 --- a/DashSync/shared/Models/Masternode/DSMasternodeListService.m +++ b/DashSync/shared/Models/Masternode/DSMasternodeListService.m @@ -59,7 +59,7 @@ - (void)startTimeOutObserver { // 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)(20 * (self.timedOutAttempt + 1) * NSEC_PER_SEC)); + dispatch_time_t timeout = dispatch_time(DISPATCH_TIME_NOW, (int64_t)(40 * (self.timedOutAttempt + 1) * NSEC_PER_SEC)); self.timeoutTimer = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0, self.chain.networkingQueue); if (self.timeoutTimer) { dispatch_source_set_timer(self.timeoutTimer, timeout, DISPATCH_TIME_FOREVER, 1ull * NSEC_PER_SEC); diff --git a/DashSync/shared/Models/Masternode/DSQuorumRotationService.h b/DashSync/shared/Models/Masternode/DSQuorumRotationService.h index 93055e0a9..2a6bc5466 100644 --- a/DashSync/shared/Models/Masternode/DSQuorumRotationService.h +++ b/DashSync/shared/Models/Masternode/DSQuorumRotationService.h @@ -24,14 +24,10 @@ NS_ASSUME_NONNULL_BEGIN @interface DSQuorumRotationService : DSMasternodeListService @property (nonatomic, assign) NSTimeInterval lastSyncedTimestamp; -//@property (nonatomic, assign, nullable) DMasternodeList *masternodeListAtTip; -//@property (nonatomic, assign, nullable) DMasternodeList *masternodeListAtH; -//@property (nonatomic, assign, nullable) DMasternodeList *masternodeListAtHC; -//@property (nonatomic, assign, nullable) DMasternodeList *masternodeListAtH2C; -//@property (nonatomic, assign, nullable) DMasternodeList *masternodeListAtH3C; -//@property (nonatomic, assign, nullable) DMasternodeList *masternodeListAtH4C; +@property (nonatomic, strong, readonly) NSData *retrievalBlockHash; - (void)getRecent:(UInt256)blockHash; - (void)fetchMasternodeListToRetrieve:(void (^)(NSData *listsToRetrieve))completion; +- (void)requestQuorumRotationInfo:(UInt256)previousBlockHash forBlockHash:(UInt256)blockHash; @end diff --git a/DashSync/shared/Models/Masternode/DSQuorumRotationService.m b/DashSync/shared/Models/Masternode/DSQuorumRotationService.m index 08fd48097..0bceb27e6 100644 --- a/DashSync/shared/Models/Masternode/DSQuorumRotationService.m +++ b/DashSync/shared/Models/Masternode/DSQuorumRotationService.m @@ -22,17 +22,18 @@ #import "DSQuorumRotationService.h" #import "DSMasternodeListService+Protected.h" #import "DSMasternodeManager.h" +#import "NSString+Bitcoin.h" @interface DSQuorumRotationService () -@property (nonatomic, strong) NSData *retrievalBlockHash; +@property (nonatomic, strong, nullable) NSData *retrievalBlockHash; @end @implementation DSQuorumRotationService - (NSString *)logPrefix { - return [NSString stringWithFormat:@"[%@] [QRInfoService] ", self.chain.name]; + return [NSString stringWithFormat:@"[%@] [MasternodeManager::QRInfoService] ", self.chain.name]; } - (BOOL)hasRecentQrInfoSync { @@ -48,6 +49,7 @@ - (void)composeMasternodeListRequest:(NSData *)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]; } else { @@ -82,15 +84,8 @@ - (void)fetchMasternodeListToRetrieve:(void (^)(NSData *listsToRetrieve))complet } - (void)getRecent:(UInt256)blockHash { -// if (self.retrievalBlockHash) -// BOOL hasLatestBlockWithHash = uint256_eq(self.retrievalBlockHash.UInt256, blockHash); -// if (hasLatestBlockWithHash || [self hasRecentQrInfoSync]) -// return; self.retrievalBlockHash = uint256_data(blockHash); [self dequeueMasternodeListRequest]; -// NSUInteger newCount = [self addToRetrievalQueue:uint256_data(blockHash)]; -// if (newCount == 1) { -// } } - (void)cleanListsRetrievalQueue { @@ -109,9 +104,6 @@ - (void)requestQuorumRotationInfo:(UInt256)previousBlockHash forBlockHash:(UInt2 DSGetQRInfoRequest *request = [DSGetQRInfoRequest requestWithBaseBlockHashes:baseBlockHashes blockHash:blockHash extraShare:YES]; 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)); [self sendMasternodeListRequest:request]; } diff --git a/DashSync/shared/Models/Messages/DSMessageRequest.h b/DashSync/shared/Models/Messages/DSMessageRequest.h index f99bb249e..37a14ca5d 100644 --- a/DashSync/shared/Models/Messages/DSMessageRequest.h +++ b/DashSync/shared/Models/Messages/DSMessageRequest.h @@ -21,6 +21,7 @@ NS_ASSUME_NONNULL_BEGIN @interface DSMessageRequest : NSObject +@property (nonatomic, readonly) BOOL logging; @property (nonatomic, readonly) NSString *type; + (instancetype)requestWithType:(NSString *)type; diff --git a/DashSync/shared/Models/Messages/DSMessageRequest.m b/DashSync/shared/Models/Messages/DSMessageRequest.m index fa2dd6e03..4784d6396 100644 --- a/DashSync/shared/Models/Messages/DSMessageRequest.m +++ b/DashSync/shared/Models/Messages/DSMessageRequest.m @@ -62,6 +62,8 @@ + (BOOL)supportsSecureCoding { return YES; } - +- (BOOL)logging { + return NO; +} @end diff --git a/DashSync/shared/Models/Messages/Masternodes/DSGetQRInfoRequest.m b/DashSync/shared/Models/Messages/Masternodes/DSGetQRInfoRequest.m index c12b5d9ef..31b0ecc38 100644 --- a/DashSync/shared/Models/Messages/Masternodes/DSGetQRInfoRequest.m +++ b/DashSync/shared/Models/Messages/Masternodes/DSGetQRInfoRequest.m @@ -92,4 +92,7 @@ - (NSString *)logWithBlockHeightLookup:(BlockHeightFinder)blockHeightLookup { return [NSString stringWithFormat:@"%u: %@ .. %u: %@", blockHeightLookup(self.baseBlockHashes[0].UInt256), self.baseBlockHashes[0].hexString, blockHeightLookup(self.blockHash), uint256_hex(self.blockHash)]; } +- (BOOL)logging { + return YES; +} @end diff --git a/DashSync/shared/Models/Network/DSPeer.m b/DashSync/shared/Models/Network/DSPeer.m index b376adca9..49c06ebb3 100644 --- a/DashSync/shared/Models/Network/DSPeer.m +++ b/DashSync/shared/Models/Network/DSPeer.m @@ -376,7 +376,8 @@ - (void)receivedOrphanBlock { - (void)sendRequest:(DSMessageRequest *)request { NSString *type = [request type]; NSData *payload = [request toData]; -// DSLog(@"%@:%u sendRequest: [%@]: %@", self.host, self.port, type, [payload hexString]); + if ([request logging]) + DSLog(@"%@:%u sendRequest: [%@]: %@", self.host, self.port, type, [payload hexString]); [self sendMessage:payload type:type]; } diff --git a/DashSync/shared/Models/Payment/DSPaymentProtocol.m b/DashSync/shared/Models/Payment/DSPaymentProtocol.m index 3bc4608a3..6da2a2a35 100644 --- a/DashSync/shared/Models/Payment/DSPaymentProtocol.m +++ b/DashSync/shared/Models/Payment/DSPaymentProtocol.m @@ -456,79 +456,68 @@ - (NSArray *)certs { - (BOOL)isValid { BOOL r = YES; - if (![self.pkiType isEqual:@"none"]) { NSMutableArray *certs = [NSMutableArray array]; - NSArray *policies = @[CFBridgingRelease(SecPolicyCreateBasicX509())]; + NSArray *policies = @[(__bridge_transfer id)SecPolicyCreateBasicX509()]; SecTrustRef trust = NULL; - for (NSData *d in self.certs) { SecCertificateRef cert = SecCertificateCreateWithData(NULL, (__bridge CFDataRef)d); - - if (cert) [certs addObject:CFBridgingRelease(cert)]; - } - - if (certs.count > 0) { - _commonName = CFBridgingRelease(SecCertificateCopySubjectSummary((__bridge SecCertificateRef)certs[0])); + if (cert) [certs addObject:(__bridge_transfer id)cert]; } - + if (certs.count > 0) + _commonName = (__bridge_transfer NSString *)SecCertificateCopySubjectSummary((__bridge SecCertificateRef)certs[0]); SecTrustCreateWithCertificates((__bridge CFArrayRef)certs, (__bridge CFArrayRef)policies, &trust); CFErrorRef error = NULL; - BOOL isValid = FALSE; - if (trust) { - isValid = SecTrustEvaluateWithError(trust, &error); // verify certificate chain - } - + // verify certificate chain + BOOL isValid = trust ? SecTrustEvaluateWithError(trust, &error) : NO; // kSecTrustResultUnspecified indicates a positive result that wasn't decided by the user - if (error) { - _errorMessage = (certs.count > 0) ? DSLocalizedString(@"Untrusted certificate", nil) : - DSLocalizedString(@"Missing certificate", nil); - - if (trust) { - for (NSDictionary *property in CFBridgingRelease(SecTrustCopyProperties(trust))) { - if ([property[@"type"] isEqual:(__bridge id)kSecPropertyTypeError]) { - _errorMessage = [_errorMessage stringByAppendingFormat:@" - %@", property[@"value"]]; - break; - } - } + if (!isValid || error) { + _errorMessage = DSLocalizedString(certs.count > 0 ? @"Untrusted certificate" : @"Missing certificate", nil); + if (error) { + NSString *errStr = CFBridgingRelease(CFErrorCopyDescription(error)); + _errorMessage = [_errorMessage stringByAppendingFormat:@" - %@", errStr ?: @"Unknown error"]; + CFRelease(error); } - r = NO; } - SecKeyRef pubKey = (trust) ? SecTrustCopyPublicKey(trust) : NULL; - OSStatus status = errSecUnimplemented; - NSData *sig = _signature; - - _signature = [NSData data]; // set signature to 0 bytes, a signature can't sign itself - - if (pubKey && [self.pkiType isEqual:@"x509+sha256"]) { - status = SecKeyRawVerify(pubKey, kSecPaddingPKCS1SHA256, self.data.SHA256.u8, sizeof(UInt256), sig.bytes, - sig.length); - } else if (pubKey && [self.pkiType isEqual:@"x509+sha1"]) { - status = SecKeyRawVerify(pubKey, kSecPaddingPKCS1SHA1, self.data.SHA1.u8, sizeof(UInt160), sig.bytes, - sig.length); - } + if (trust) { + SecKeyRef pubKey = SecTrustCopyKey(trust); + NSData *sig = _signature; + _signature = [NSData data]; // set signature to 0 bytes, a signature can't sign itself + + SecKeyAlgorithm algorithm = NULL; + NSData *hashData = nil; + + if ([self.pkiType isEqualToString:@"x509+sha256"]) { + algorithm = kSecKeyAlgorithmRSASignatureDigestPKCS1v15SHA256; + hashData = uint256_data(self.data.SHA256); + } else if ([self.pkiType isEqualToString:@"x509+sha1"]) { + algorithm = kSecKeyAlgorithmRSASignatureDigestPKCS1v15SHA1; + hashData = uint160_data(self.data.SHA1); + } - _signature = sig; - if (pubKey) CFRelease(pubKey); - if (trust) CFRelease(trust); + _signature = sig; - if (status != errSecSuccess) { - if (status == errSecUnimplemented) { + if (pubKey && algorithm && SecKeyIsAlgorithmSupported(pubKey, kSecKeyOperationTypeVerify, algorithm)) { + BOOL verified = SecKeyVerifySignature(pubKey, algorithm, (__bridge CFDataRef)hashData, (__bridge CFDataRef)sig, NULL); + if (!verified) { + _errorMessage = DSLocalizedString(@"Invalid signature", nil); + DSLog(@"%@", _errorMessage); + r = NO; + } + } else if (pubKey) { _errorMessage = DSLocalizedString(@"Unsupported signature type", nil); DSLog(@"%@", _errorMessage); - } else { - _errorMessage = [NSError osStatusErrorWithCode:status].localizedDescription; - DSLog(@"SecKeyRawVerify error: %@", _errorMessage); + r = NO; } - r = NO; + if (pubKey) CFRelease(pubKey); + CFRelease(trust); } } else if (self.certs.firstObject) { // non-standard extention to include an un-certified request name _commonName = [[NSString alloc] initWithData:self.certs.firstObject encoding:NSUTF8StringEncoding]; } - if (r && self.details.expires >= 1 && [NSDate timeIntervalSince1970] > self.details.expires) { _errorMessage = DSLocalizedString(@"Request expired", nil); r = NO; diff --git a/DashSync/shared/Models/Transactions/Base/DSAssetLockTransaction.h b/DashSync/shared/Models/Transactions/Base/DSAssetLockTransaction.h index d1e9db213..de2946e6b 100644 --- a/DashSync/shared/Models/Transactions/Base/DSAssetLockTransaction.h +++ b/DashSync/shared/Models/Transactions/Base/DSAssetLockTransaction.h @@ -28,7 +28,18 @@ NS_ASSUME_NONNULL_BEGIN @property (nonatomic, readonly) UInt160 creditBurnPublicKeyHash; @property (nonatomic, readonly) DSUTXO lockedOutpoint; -- (instancetype)initOnChain:(DSChain *)chain withCreditOutputs:(NSArray *)creditOutputs; +- (instancetype)initOnChain:(DSChain *)chain withCreditOutputs:(NSArray *)creditOutputs payloadVersion:(uint8_t)payloadVersion; + +- (instancetype)initWithInputHashes:(NSArray *)hashes + inputIndexes:(NSArray *)indexes + inputScripts:(NSArray *)scripts + inputSequences:(NSArray *)inputSequences + outputAddresses:(NSArray *)addresses + outputAmounts:(NSArray *)amounts + creditOutputs:(NSArray *)creditOutputs + payloadVersion:(uint8_t)payloadVersion + onChain:(DSChain *)chain; + - (BOOL)checkInvitationDerivationPathIndexForWallet:(DSWallet *)wallet isIndex:(uint32_t)index; - (BOOL)checkDerivationPathIndexForWallet:(DSWallet *)wallet isIndex:(uint32_t)index; @@ -38,8 +49,4 @@ NS_ASSUME_NONNULL_BEGIN @end -@interface DSAssetLockTransaction (FFI) -+ (instancetype)ffi_from:(dashcore_blockdata_transaction_Transaction *)transaction onChain:(DSChain *)chain; -@end - NS_ASSUME_NONNULL_END diff --git a/DashSync/shared/Models/Transactions/Base/DSAssetLockTransaction.m b/DashSync/shared/Models/Transactions/Base/DSAssetLockTransaction.m index e99ceb3ee..dcda82a06 100644 --- a/DashSync/shared/Models/Transactions/Base/DSAssetLockTransaction.m +++ b/DashSync/shared/Models/Transactions/Base/DSAssetLockTransaction.m @@ -21,23 +21,50 @@ #import "DSAssetLockTransactionEntity+CoreDataClass.h" #import "DSDerivationPathFactory.h" #import "DSGapLimit.h" +#import "DSTransaction+FFI.h" #import "DSTransactionFactory.h" #import "NSData+Dash.h" #import "NSMutableData+Dash.h" @implementation DSAssetLockTransaction -- (instancetype)initOnChain:(DSChain *)chain withCreditOutputs:(NSArray *)creditOutputs { +- (instancetype)initOnChain:(DSChain *)chain withCreditOutputs:(NSArray *)creditOutputs payloadVersion:(uint8_t)payloadVersion { self = [super initOnChain:chain]; if (self) { self.type = DSTransactionType_AssetLock; self.version = SPECIAL_TX_VERSION; self.creditOutputs = [creditOutputs mutableCopy]; - self.specialTransactionVersion = 1; + self.specialTransactionVersion = payloadVersion; } return self; } +- (instancetype)initWithInputHashes:(NSArray *)hashes + inputIndexes:(NSArray *)indexes + inputScripts:(NSArray *)scripts + inputSequences:(NSArray *)inputSequences + outputAddresses:(NSArray *)addresses + outputAmounts:(NSArray *)amounts + creditOutputs:(NSArray *)creditOutputs + payloadVersion:(uint8_t)payloadVersion + onChain:(DSChain *)chain { + self = [super initWithInputHashes:hashes + inputIndexes:indexes + inputScripts:scripts + inputSequences:inputSequences + outputAddresses:addresses + outputAmounts:amounts + onChain:chain]; + if (self) { + self.type = DSTransactionType_AssetLock; + self.version = SPECIAL_TX_VERSION; + self.creditOutputs = [creditOutputs mutableCopy]; + self.specialTransactionVersion = payloadVersion; + } + return self; + +} + - (instancetype)initWithMessage:(NSData *)message onChain:(DSChain *)chain { if (!(self = [super initWithMessage:message onChain:chain])) return nil; @@ -170,21 +197,31 @@ - (Class)entityClass { @end -@implementation DSAssetLockTransaction (FFI) -+ (instancetype)ffi_from:(dashcore_blockdata_transaction_Transaction *)transaction onChain:(DSChain *)chain { - if (!transaction->special_transaction_payload) { - return nil; - } - // TODO: it's used just for ui - switch (transaction->special_transaction_payload->tag) { - case dashcore_blockdata_transaction_special_transaction_TransactionPayload_AssetLockPayloadType: { - dashcore_blockdata_transaction_special_transaction_asset_lock_AssetLockPayload *payload = transaction->special_transaction_payload->asset_lock_payload_type; - // TODO: implement it - DSAssetLockTransaction *tx = [[DSAssetLockTransaction alloc] initOnChain:chain]; -// tx. - return tx; - } - default: return nil; - } -} -@end +//@implementation DSAssetLockTransaction (FFI) +//+ (instancetype)ffi_from:(DTransaction *)transaction onChain:(DSChain *)chain { +// if (!transaction->special_transaction_payload) { +// return nil; +// } +// +// DSAssetLockTransaction *tx = (DSAssetLockTransaction *) [DSTransaction ffi_from:transaction onChain:chain]; +// +// // TODO: it's used just for ui +// switch (transaction->special_transaction_payload->tag) { +// case dashcore_blockdata_transaction_special_transaction_TransactionPayload_AssetLockPayloadType: { +// dashcore_blockdata_transaction_special_transaction_asset_lock_AssetLockPayload *payload = transaction->special_transaction_payload->asset_lock_payload_type; +// // TODO: implement it +// NSMutableArray *creditOutputs = [NSMutableArray arrayWithCapacity:payload->credit_outputs->count]; +// for (int i = 0; i < payload->credit_outputs->count; i++) { +// DTxOut *output = payload->credit_outputs->values[i]; +// NSData *script = NSDataFromPtr(output->script_pubkey->_0); +// [creditOutputs addObject:[DSTransactionOutput transactionOutputWithAmount:output->value outScript:script onChain:chain]]; +// } +// +// DSAssetLockTransaction *tx = [[DSAssetLockTransaction alloc] initOnChain:chain withCreditOutputs:creditOutputs payloadVersion:payload->version]; +//// tx. +// return tx; +// } +// default: return nil; +// } +//} +//@end diff --git a/DashSync/shared/Models/Transactions/Base/DSInstantSendTransactionLock.m b/DashSync/shared/Models/Transactions/Base/DSInstantSendTransactionLock.m index cbc445c76..0e8c11e54 100644 --- a/DashSync/shared/Models/Transactions/Base/DSInstantSendTransactionLock.m +++ b/DashSync/shared/Models/Transactions/Base/DSInstantSendTransactionLock.m @@ -14,7 +14,6 @@ #import "DSMasternodeManager.h" #import "DSSporkManager.h" #import "DSTransactionEntity+CoreDataClass.h" -#import "DSTransactionHashEntity+CoreDataClass.h" #import "NSData+Dash.h" #import "NSManagedObject+Sugar.h" #import "NSMutableData+Dash.h" diff --git a/DashSync/shared/Models/CoinJoin/DSTransaction+CoinJoin.h b/DashSync/shared/Models/Transactions/Base/DSTransaction+FFI.h similarity index 87% rename from DashSync/shared/Models/CoinJoin/DSTransaction+CoinJoin.h rename to DashSync/shared/Models/Transactions/Base/DSTransaction+FFI.h index d895a7ad3..00c2fd842 100644 --- a/DashSync/shared/Models/CoinJoin/DSTransaction+CoinJoin.h +++ b/DashSync/shared/Models/Transactions/Base/DSTransaction+FFI.h @@ -21,10 +21,9 @@ NS_ASSUME_NONNULL_BEGIN -@interface DSTransaction (CoinJoin) - -- (DSTransaction *)initWithTransaction:(DTransaction *)transaction onChain:(DSChain *)chain; +@interface DSTransaction (FFI) ++ (instancetype)ffi_from:(DTransaction *)transaction onChain:(DSChain *)chain; - (DTransaction *)ffi_malloc:(DChainType *)chainType; + (void)ffi_free:(DTransaction *)tx; diff --git a/DashSync/shared/Models/CoinJoin/DSTransaction+CoinJoin.m b/DashSync/shared/Models/Transactions/Base/DSTransaction+FFI.m similarity index 56% rename from DashSync/shared/Models/CoinJoin/DSTransaction+CoinJoin.m rename to DashSync/shared/Models/Transactions/Base/DSTransaction+FFI.m index 84a86f975..e5081690d 100644 --- a/DashSync/shared/Models/CoinJoin/DSTransaction+CoinJoin.m +++ b/DashSync/shared/Models/Transactions/Base/DSTransaction+FFI.m @@ -17,15 +17,16 @@ #import "BigIntTypes.h" #import "DSChain+Transaction.h" -#import "DSTransaction.h" -#import "DSTransaction+CoinJoin.h" -#import "DSTransactionInput+CoinJoin.h" +#import "DSAssetLockTransaction.h" +#import "DSTransaction+FFI.h" +#import "DSTransactionInput+FFI.h" +#import "DSTransactionOutput+FFI.h" #import "NSData+Dash.h" #import "DSKeyManager.h" -@implementation DSTransaction (CoinJoin) +@implementation DSTransaction (FFI) -- (DSTransaction *)initWithTransaction:(DTransaction *)transaction onChain:(DSChain *)chain { ++ (nonnull instancetype)ffi_from:(nonnull DTransaction *)transaction onChain:(nonnull DSChain *)chain { NSMutableArray *hashes = [NSMutableArray array]; NSMutableArray *indexes = [NSMutableArray array]; NSMutableArray *scripts = [NSMutableArray array]; @@ -61,13 +62,41 @@ - (DSTransaction *)initWithTransaction:(DTransaction *)transaction onChain:(DSCh [amounts addObject:amount]; } - DSTransaction *tx = [[DSTransaction alloc] initWithInputHashes:hashes - inputIndexes:indexes - inputScripts:scripts - inputSequences:inputSequences - outputAddresses:addresses - outputAmounts:amounts - onChain:chain]; + DSTransaction *tx; + switch (transaction->special_transaction_payload->tag) { + case dashcore_blockdata_transaction_special_transaction_TransactionPayload_AssetLockPayloadType: { + dashcore_blockdata_transaction_special_transaction_asset_lock_AssetLockPayload *payload = transaction->special_transaction_payload->asset_lock_payload_type; + NSMutableArray *creditOutputs = [NSMutableArray arrayWithCapacity:payload->credit_outputs->count]; + for (int i = 0; i < payload->credit_outputs->count; i++) { + DTxOut *output = payload->credit_outputs->values[i]; + NSData *script = NSDataFromPtr(output->script_pubkey->_0); + [creditOutputs addObject:[DSTransactionOutput transactionOutputWithAmount:output->value outScript:script onChain:chain]]; + } + + tx = [[DSAssetLockTransaction alloc] initWithInputHashes:hashes + inputIndexes:indexes + inputScripts:scripts + inputSequences:inputSequences + outputAddresses:addresses + outputAmounts:amounts + creditOutputs:creditOutputs + payloadVersion:payload->version + onChain:chain]; + } + default: { + // TODO: implement other transactions types + tx = [[DSTransaction alloc] initWithInputHashes:hashes + inputIndexes:indexes + inputScripts:scripts + inputSequences:inputSequences + outputAddresses:addresses + outputAmounts:amounts + onChain:chain]; + + }; + } + + tx.version = transaction->version; return tx; @@ -84,7 +113,7 @@ - (DTransaction *)ffi_malloc:(DChainType *)chainType { for (uintptr_t i = 0; i < outputsCount; ++i) { DSTransactionOutput *output = self.outputs[i]; - output_values[i] = DTxOutCtor(output.amount, DScriptBufCtor(bytes_ctor(output.outScript))); + output_values[i] = [output ffi_malloc]; } DTransaction *transaction = DTransactionCtor(self.version, self.lockTime, DTxInputsCtor(inputsCount, input_values), DTxOutputsCtor(outputsCount, output_values), NULL); return transaction; @@ -95,5 +124,7 @@ + (void)ffi_free:(DTransaction *)tx { DTransactionDtor(tx); } + + @end diff --git a/DashSync/shared/Models/Transactions/Base/DSTransaction.h b/DashSync/shared/Models/Transactions/Base/DSTransaction.h index 04dbb7aea..595a8f9e8 100644 --- a/DashSync/shared/Models/Transactions/Base/DSTransaction.h +++ b/DashSync/shared/Models/Transactions/Base/DSTransaction.h @@ -41,7 +41,7 @@ NS_ASSUME_NONNULL_BEGIN #define TX_FEE_PER_INPUT 10000ULL // standard ix fee per input #define TX_OUTPUT_SIZE 34 // estimated size for a typical transaction output #define TX_INPUT_SIZE 148 // estimated size for a typical compact pubkey transaction input -#define TX_MIN_OUTPUT_AMOUNT (TX_FEE_PER_B * 3 * (TX_OUTPUT_SIZE + TX_INPUT_SIZE)) //no txout can be below this amount +//#define TX_MIN_OUTPUT_AMOUNT (TX_FEE_PER_B * 3 * (TX_OUTPUT_SIZE + TX_INPUT_SIZE)) //no txout can be below this amount #define TX_MAX_SIZE 100000 // no tx can be larger than this size in bytes //#define TX_UNCONFIRMED INT32_MAX // block height indicating transaction is unconfirmed #define TX_MAX_LOCK_HEIGHT 500000000 // a lockTime below this value is a block height, otherwise a timestamp diff --git a/DashSync/shared/Models/Transactions/Base/DSTransaction.m b/DashSync/shared/Models/Transactions/Base/DSTransaction.m index f38577a1b..037676c5e 100644 --- a/DashSync/shared/Models/Transactions/Base/DSTransaction.m +++ b/DashSync/shared/Models/Transactions/Base/DSTransaction.m @@ -73,7 +73,7 @@ + (instancetype)transactionWithMessage:(NSData *)message onChain:(DSChain *)chai return [[self alloc] initWithMessage:message onChain:chain]; } -+ (UInt256)devnetGenesisCoinbaseTxHash:(dash_spv_crypto_network_chain_type_DevnetType *)devnetType ++ (UInt256)devnetGenesisCoinbaseTxHash:(DDevnetType *)devnetType onProtocolVersion:(uint32_t)protocolVersion forChain:(DSChain *)chain { DSTransaction *transaction = [[self alloc] initOnChain:chain]; @@ -966,9 +966,6 @@ - (BOOL)saveInitialInContext:(NSManagedObjectContext *)context { return YES; } -@end - -@implementation DSTransaction (Extensions) - (DSTransactionDirection)direction { if (self.cachedDirection != DSTransactionDirection_NotAccountFunds) { return self.cachedDirection; diff --git a/DashSync/shared/Models/CoinJoin/DSTransactionInput+CoinJoin.h b/DashSync/shared/Models/Transactions/Base/DSTransactionInput+FFI.h similarity index 96% rename from DashSync/shared/Models/CoinJoin/DSTransactionInput+CoinJoin.h rename to DashSync/shared/Models/Transactions/Base/DSTransactionInput+FFI.h index 08cba834d..d7dfbd8bc 100644 --- a/DashSync/shared/Models/CoinJoin/DSTransactionInput+CoinJoin.h +++ b/DashSync/shared/Models/Transactions/Base/DSTransactionInput+FFI.h @@ -21,7 +21,7 @@ NS_ASSUME_NONNULL_BEGIN -@interface DSTransactionInput (CoinJoin) +@interface DSTransactionInput (FFI) - (DTxIn *)ffi_malloc; + (void)ffi_free:(DTxIn *)input; diff --git a/DashSync/shared/Models/CoinJoin/DSTransactionInput+CoinJoin.m b/DashSync/shared/Models/Transactions/Base/DSTransactionInput+FFI.m similarity index 94% rename from DashSync/shared/Models/CoinJoin/DSTransactionInput+CoinJoin.m rename to DashSync/shared/Models/Transactions/Base/DSTransactionInput+FFI.m index 971587e54..3681e5dc5 100644 --- a/DashSync/shared/Models/CoinJoin/DSTransactionInput+CoinJoin.m +++ b/DashSync/shared/Models/Transactions/Base/DSTransactionInput+FFI.m @@ -17,10 +17,10 @@ #import "BigIntTypes.h" #import "DSTransactionInput.h" -#import "DSTransactionInput+CoinJoin.h" +#import "DSTransactionInput+FFI.h" #import "NSData+Dash.h" -@implementation DSTransactionInput (CoinJoin) +@implementation DSTransactionInput (FFI) - (DTxIn *)ffi_malloc { DOutPoint *outpoint = DOutPointCtorU(self.inputHash, self.index); diff --git a/DashSync/shared/Models/Transactions/Base/DSTransactionOutput+FFI.h b/DashSync/shared/Models/Transactions/Base/DSTransactionOutput+FFI.h new file mode 100644 index 000000000..568cc45e6 --- /dev/null +++ b/DashSync/shared/Models/Transactions/Base/DSTransactionOutput+FFI.h @@ -0,0 +1,31 @@ +// +// Created by Vladimir Pirogov +// Copyright © 2025 Dash Core Group. All rights reserved. +// +// Licensed under the MIT License (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// https://opensource.org/licenses/MIT +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// + +#import "DSKeyManager.h" +#import "DSTransactionOutput.h" +#import + +NS_ASSUME_NONNULL_BEGIN + +@interface DSTransactionOutput (FFI) + +- (DTxOut *)ffi_malloc; ++ (void)ffi_free:(DTxOut *)output; + +@end + +NS_ASSUME_NONNULL_END diff --git a/DashSync/shared/Models/Transactions/Base/DSTransactionOutput+FFI.m b/DashSync/shared/Models/Transactions/Base/DSTransactionOutput+FFI.m new file mode 100644 index 000000000..ff47d870c --- /dev/null +++ b/DashSync/shared/Models/Transactions/Base/DSTransactionOutput+FFI.m @@ -0,0 +1,31 @@ +// +// Created by Vladimir Pirogov +// Copyright © 2025 Dash Core Group. All rights reserved. +// +// Licensed under the MIT License (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// https://opensource.org/licenses/MIT +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// + +#import "DSTransactionOutput+FFI.h" + +@implementation DSTransactionOutput (FFI) + +- (DTxOut *)ffi_malloc { + return DTxOutCtor(self.amount, DScriptBufCtor(self.outScript ? bytes_ctor(self.outScript) : bytes_ctor([NSData data]))); +} + ++ (void)ffi_free:(DTxOut *)output { + if (!output) return; + DTxOutDtor(output); +} + +@end diff --git a/DashSync/shared/Models/Wallet/DSAccount.m b/DashSync/shared/Models/Wallet/DSAccount.m index dd338bb47..a98ab42f6 100644 --- a/DashSync/shared/Models/Wallet/DSAccount.m +++ b/DashSync/shared/Models/Wallet/DSAccount.m @@ -1044,7 +1044,7 @@ - (DSAssetLockTransaction *)assetLockTransactionFor:(uint64_t)amount NSParameterAssert(address); NSData *script = [NSData scriptPubKeyForAddress:address forChain:self.wallet.chain]; DSTransactionOutput *creditOutput = [DSTransactionOutput transactionOutputWithAmount:amount outScript:script onChain:self.wallet.chain]; - DSAssetLockTransaction *transaction = [[DSAssetLockTransaction alloc] initOnChain:self.wallet.chain withCreditOutputs:@[creditOutput]]; + DSAssetLockTransaction *transaction = [[DSAssetLockTransaction alloc] initOnChain:self.wallet.chain withCreditOutputs:@[creditOutput] payloadVersion:1]; return (DSAssetLockTransaction *)[self updateTransaction:transaction forAmounts:@[@(amount)] toOutputScripts:@[[NSData assetLockOutputScript]] diff --git a/DashSync/shared/Models/Wallet/DSWallet+Tests.h b/DashSync/shared/Models/Wallet/DSWallet+Tests.h index bcaf97118..52e663bf8 100644 --- a/DashSync/shared/Models/Wallet/DSWallet+Tests.h +++ b/DashSync/shared/Models/Wallet/DSWallet+Tests.h @@ -26,13 +26,6 @@ NS_ASSUME_NONNULL_BEGIN + (DSWallet *)transientWalletWithDerivedKeyData:(NSData *)derivedData forChain:(DSChain *)chain; -+ (DSWallet *_Nullable)standardWalletWithRandomSeedPhraseForChain:(DSChain *)chain - storeSeedPhrase:(BOOL)store - isTransient:(BOOL)isTransient; -+ (DSWallet *_Nullable)standardWalletWithRandomSeedPhraseInLanguage:(DSBIP39Language)language - forChain:(DSChain *)chain - storeSeedPhrase:(BOOL)store - isTransient:(BOOL)isTransient; @end diff --git a/DashSync/shared/Models/Wallet/DSWallet+Tests.m b/DashSync/shared/Models/Wallet/DSWallet+Tests.m index de6c4a05f..f8e3060f4 100644 --- a/DashSync/shared/Models/Wallet/DSWallet+Tests.m +++ b/DashSync/shared/Models/Wallet/DSWallet+Tests.m @@ -52,18 +52,6 @@ + (DSWallet *)transientWalletWithDerivedKeyData:(NSData *)derivedData forChain:( return wallet; } -+ (DSWallet *)standardWalletWithRandomSeedPhraseForChain:(DSChain *)chain storeSeedPhrase:(BOOL)store isTransient:(BOOL)isTransient { - NSParameterAssert(chain); - - return [self standardWalletWithRandomSeedPhraseInLanguage:DSBIP39Language_Default forChain:chain storeSeedPhrase:store isTransient:isTransient]; -} - -+ (DSWallet *)standardWalletWithRandomSeedPhraseInLanguage:(DSBIP39Language)language forChain:(DSChain *)chain storeSeedPhrase:(BOOL)store isTransient:(BOOL)isTransient { - NSParameterAssert(chain); - - return [self standardWalletWithSeedPhrase:[self generateRandomSeedPhraseForLanguage:language] setCreationDate:[NSDate timeIntervalSince1970] forChain:chain storeSeedPhrase:store isTransient:isTransient]; -} - + (NSString *)setTransientDerivedKeyData:(NSData *)derivedKeyData withAccounts:(NSArray *)accounts forChain:(DSChain *)chain { if (!derivedKeyData) return nil; NSString *uniqueID = nil; diff --git a/DashSync/shared/Models/Wallet/DSWallet.h b/DashSync/shared/Models/Wallet/DSWallet.h index 2a6ade3cf..03ccbf3b8 100644 --- a/DashSync/shared/Models/Wallet/DSWallet.h +++ b/DashSync/shared/Models/Wallet/DSWallet.h @@ -35,8 +35,8 @@ typedef void (^SecureSeedRequestBlock)(NSString *_Nullable authprompt, uint64_t FOUNDATION_EXPORT NSString *_Nonnull const DSWalletBalanceDidChangeNotification; -#define DUFFS 100000000LL -#define MAX_MONEY (21000000LL * DUFFS) +#define DUFFS_OBJC 100000000LL +#define MAX_MONEY_OBJC (21000000LL * DUFFS_OBJC) @class DSChain, DSAccount, DSTransaction, DSDerivationPath, DSLocalMasternode, DSSpecialTransactionsWalletHolder, DSInvitation; @@ -91,6 +91,14 @@ FOUNDATION_EXPORT NSString *_Nonnull const DSWalletBalanceDidChangeNotification; - (void)authPrivateKey:(void (^_Nullable)(NSString *_Nullable authKey))completion; ++ (DSWallet *_Nullable)standardWalletWithRandomSeedPhraseForChain:(DSChain *)chain + storeSeedPhrase:(BOOL)store + isTransient:(BOOL)isTransient; ++ (DSWallet *_Nullable)standardWalletWithRandomSeedPhraseInLanguage:(DSBIP39Language)language + forChain:(DSChain *)chain + storeSeedPhrase:(BOOL)store + isTransient:(BOOL)isTransient; + + (DSWallet *_Nullable)standardWalletWithSeedPhrase:(NSString *)seedPhrase setCreationDate:(NSTimeInterval)creationDate forChain:(DSChain *)chain @@ -182,6 +190,9 @@ FOUNDATION_EXPORT NSString *_Nonnull const DSWalletBalanceDidChangeNotification; fromSeed:(NSData *_Nonnull)seed; - (NSString *_Nullable)privateKeyAddressForAddress:(NSString *)address fromSeed:(NSData *)seed; +- (NSData *_Nullable)signDigest:(UInt256)digest + usingPrivateKeyForAddress:(NSString *)address + fromSeed:(NSData *)seed; //generate a random Mnemonic seed + (NSString *_Nullable)generateRandomSeedPhrase; diff --git a/DashSync/shared/Models/Wallet/DSWallet.m b/DashSync/shared/Models/Wallet/DSWallet.m index 355ea2e04..5d71896e4 100644 --- a/DashSync/shared/Models/Wallet/DSWallet.m +++ b/DashSync/shared/Models/Wallet/DSWallet.m @@ -86,6 +86,16 @@ @interface DSWallet () { @implementation DSWallet ++ (DSWallet *)standardWalletWithRandomSeedPhraseForChain:(DSChain *)chain storeSeedPhrase:(BOOL)store isTransient:(BOOL)isTransient { + NSParameterAssert(chain); + return [self standardWalletWithRandomSeedPhraseInLanguage:DSBIP39Language_Default forChain:chain storeSeedPhrase:store isTransient:isTransient]; +} + ++ (DSWallet *)standardWalletWithRandomSeedPhraseInLanguage:(DSBIP39Language)language forChain:(DSChain *)chain storeSeedPhrase:(BOOL)store isTransient:(BOOL)isTransient { + NSParameterAssert(chain); + return [self standardWalletWithSeedPhrase:[self generateRandomSeedPhraseForLanguage:language] setCreationDate:[NSDate timeIntervalSince1970] forChain:chain storeSeedPhrase:store isTransient:isTransient]; +} + + (DSWallet *)standardWalletWithSeedPhrase:(NSString *)seedPhrase setCreationDate:(NSTimeInterval)creationDate forChain:(DSChain *)chain storeSeedPhrase:(BOOL)store isTransient:(BOOL)isTransient { NSParameterAssert(seedPhrase); NSParameterAssert(chain); @@ -976,6 +986,18 @@ - (NSString *)privateKeyAddressForAddress:(NSString *)address fromSeed:(NSData * return keyAddress; } +- (NSData *_Nullable)signDigest:(UInt256)digest + usingPrivateKeyForAddress:(NSString *)address + fromSeed:(NSData *)seed { + DMaybeOpaqueKey *opaque_key = [self privateKeyForAddress:address fromSeed:seed]; + if (opaque_key->error) { + return nil; + } + NSData *signature = [DSKeyManager signMesasageDigest:opaque_key->ok digest:digest]; + DMaybeOpaqueKeyDtor(opaque_key); + return signature; +} + - (void)reloadDerivationPaths { for (DSAccount *account in self.accounts) { for (DSDerivationPath *derivationPath in account.fundDerivationPaths) { diff --git a/Example/DashSync.xcodeproj/project.pbxproj b/Example/DashSync.xcodeproj/project.pbxproj index 9ce7e5e99..e6c62fe4d 100644 --- a/Example/DashSync.xcodeproj/project.pbxproj +++ b/Example/DashSync.xcodeproj/project.pbxproj @@ -2423,6 +2423,7 @@ ORGANIZATIONNAME = "Dash Core Group"; TargetAttributes = { 6003F589195388D20070C39A = { + DevelopmentTeam = 44RJ69WHFF; ProvisioningStyle = Automatic; }; 6003F5AD195388D20070C39A = { @@ -2794,10 +2795,12 @@ inputPaths = ( "${PODS_ROOT}/Target Support Files/Pods-NetworkInfo/Pods-NetworkInfo-resources.sh", "${PODS_CONFIGURATION_BUILD_DIR}/DashSync-macOS/DashSync.bundle", + "${PODS_CONFIGURATION_BUILD_DIR}/SDWebImage-macOS/SDWebImage.bundle", ); name = "[CP] Copy Pods Resources"; outputPaths = ( "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/DashSync.bundle", + "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/SDWebImage.bundle", ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/sh; @@ -2834,10 +2837,12 @@ inputPaths = ( "${PODS_ROOT}/Target Support Files/Pods-DashSync-DashSync_Example/Pods-DashSync-DashSync_Example-resources.sh", "${PODS_CONFIGURATION_BUILD_DIR}/DashSync-iOS/DashSync.bundle", + "${PODS_CONFIGURATION_BUILD_DIR}/SDWebImage-iOS/SDWebImage.bundle", ); name = "[CP] Copy Pods Resources"; outputPaths = ( "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/DashSync.bundle", + "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/SDWebImage.bundle", ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/sh; @@ -3255,7 +3260,7 @@ ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; CODE_SIGN_IDENTITY = "Apple Development"; CODE_SIGN_STYLE = Automatic; - DEVELOPMENT_TEAM = ""; + DEVELOPMENT_TEAM = 44RJ69WHFF; EXCLUDED_ARCHS = ""; GCC_PRECOMPILE_PREFIX_HEADER = YES; GCC_PREFIX_HEADER = "DashSync/DashSync-Prefix.pch"; @@ -3316,7 +3321,7 @@ ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; CODE_SIGN_IDENTITY = "Apple Development"; CODE_SIGN_STYLE = Automatic; - DEVELOPMENT_TEAM = ""; + DEVELOPMENT_TEAM = 44RJ69WHFF; EXCLUDED_ARCHS = ""; GCC_PRECOMPILE_PREFIX_HEADER = YES; GCC_PREFIX_HEADER = "DashSync/DashSync-Prefix.pch"; @@ -3443,26 +3448,18 @@ OTHER_LDFLAGS = ( "$(inherited)", "-ObjC", - "-l\"BoringSSL-GRPC-macOS\"", "-l\"CocoaImageHashing-macOS\"", "-l\"CocoaLumberjack-macOS\"", - "-l\"DAPI-GRPC-macOS\"", "-l\"DSDynamicOptions-macOS\"", "-l\"DashSync-macOS\"", "-l\"Protobuf-macOS\"", "-l\"SDWebImage-macOS\"", - "-l\"TinyCborObjc-macOS\"", "-l\"abseil-macOS\"", "-l\"bz2\"", "-l\"c++\"", "-l\"dash_shared_core_macos\"", - "-l\"gRPC-Core-macOS\"", - "-l\"gRPC-ProtoRPC-macOS\"", - "-l\"gRPC-RxLibrary-macOS\"", - "-l\"gRPC-macOS\"", "-l\"resolv\"", "-l\"sqlite3\"", - "-l\"tinycbor-macOS\"", "-l\"z\"", "-framework", "\"BackgroundTasks\"", @@ -3478,7 +3475,6 @@ "\"Security\"", "-framework", "\"SystemConfiguration\"", - "\"-ld_classic\"", ); PRODUCT_NAME = "$(TARGET_NAME)"; PROVISIONING_PROFILE_SPECIFIER = ""; @@ -3510,26 +3506,18 @@ OTHER_LDFLAGS = ( "$(inherited)", "-ObjC", - "-l\"BoringSSL-GRPC-macOS\"", "-l\"CocoaImageHashing-macOS\"", "-l\"CocoaLumberjack-macOS\"", - "-l\"DAPI-GRPC-macOS\"", "-l\"DSDynamicOptions-macOS\"", "-l\"DashSync-macOS\"", "-l\"Protobuf-macOS\"", "-l\"SDWebImage-macOS\"", - "-l\"TinyCborObjc-macOS\"", "-l\"abseil-macOS\"", "-l\"bz2\"", "-l\"c++\"", "-l\"dash_shared_core_macos\"", - "-l\"gRPC-Core-macOS\"", - "-l\"gRPC-ProtoRPC-macOS\"", - "-l\"gRPC-RxLibrary-macOS\"", - "-l\"gRPC-macOS\"", "-l\"resolv\"", "-l\"sqlite3\"", - "-l\"tinycbor-macOS\"", "-l\"z\"", "-framework", "\"BackgroundTasks\"", @@ -3545,7 +3533,6 @@ "\"Security\"", "-framework", "\"SystemConfiguration\"", - "\"-ld_classic\"", ); PRODUCT_NAME = "$(TARGET_NAME)"; PROVISIONING_PROFILE_SPECIFIER = ""; diff --git a/Example/DashSync/Actions.storyboard b/Example/DashSync/Actions.storyboard index e3e8991a7..7d3c93171 100644 --- a/Example/DashSync/Actions.storyboard +++ b/Example/DashSync/Actions.storyboard @@ -1,9 +1,9 @@ - + - + @@ -745,7 +745,7 @@ - + diff --git a/Example/DashSync/BlockchainIdentities.storyboard b/Example/DashSync/BlockchainIdentities.storyboard index 11beb7f82..b71ec673e 100644 --- a/Example/DashSync/BlockchainIdentities.storyboard +++ b/Example/DashSync/BlockchainIdentities.storyboard @@ -2,6 +2,7 @@ + @@ -335,7 +336,7 @@ - - + - + -