diff --git a/.coderabbit.yaml b/.coderabbit.yaml new file mode 100644 index 000000000..1316a8796 --- /dev/null +++ b/.coderabbit.yaml @@ -0,0 +1,23 @@ +# CodeRabbit Configuration +# Documentation: https://docs.coderabbit.ai/guides/configure-coderabbit + +language: en-US + +reviews: + # Automatically review new PRs and incremental pushes + auto_review: + enabled: true + drafts: false + base_branches: + - master + - develop + + # Review profile - chill for balanced feedback + profile: chill + + # Request changes when issues are found + request_changes_workflow: true + +chat: + # Allow interaction with CodeRabbit via comments + auto_reply: true diff --git a/CLAUDE.md b/CLAUDE.md new file mode 100644 index 000000000..3b2c3b399 --- /dev/null +++ b/CLAUDE.md @@ -0,0 +1,211 @@ +# DashSync iOS + +DashSync is a lightweight blockchain client library for iOS/macOS that enables applications to interact with the Dash cryptocurrency network. It supports both Dash Core Network (Layer 1) and Dash Platform (Layer 2). + +## Quick Reference + +- **Language**: Objective-C with C/C++/Rust interop +- **Build System**: Xcode + CocoaPods +- **Deployment**: iOS 13.0+, macOS 10.15+ +- **Pod Name**: `DashSyncPod` + +## Build Requirements + +```bash +# Install Rust +curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh +rustup target add aarch64-apple-ios x86_64-apple-ios aarch64-apple-ios-sim + +# Install protobuf and grpc +brew install protobuf grpc cmake +``` + +## Common Commands + +```bash +# Run example project +cd Example && pod install && open DashSync.xcworkspace + +# Run tests +cd Example && xcodebuild test -workspace DashSync.xcworkspace -scheme DashSync-Example -destination 'platform=iOS Simulator,name=iPhone 15' + +# Update pods +cd Example && pod update +``` + +## Project Structure + +``` +DashSync/ +├── DashSync/shared/ # Main framework source (cross-platform) +│ ├── Models/ # Core domain models (24 subdirectories) +│ ├── Libraries/ # Utility libraries +│ └── DashSync.xcdatamodeld/ # Core Data model (83 entities) +├── DashSync/iOS/ # iOS-specific code +├── DashSync/macOS/ # macOS-specific code +├── Example/ # Reference app and tests +├── Scripts/ # Build utilities +└── ChainResources/ # Blockchain data files +``` + +## Architecture + +### Two-Layer Design +- **Layer 1 (Core)**: Traditional blockchain - transactions, blocks, masternodes +- **Layer 2 (Platform)**: Decentralized apps - identities, documents, contracts + +### Model-Manager Pattern +- **Models**: Data structures (`DSChain`, `DSWallet`, `DSTransaction`) +- **Managers**: Service coordinators (`DSChainManager`, `DSPeerManager`) + +### Key Managers +| Manager | Purpose | +|---------|---------| +| `DSChainsManager` | Multi-chain coordinator (singleton) | +| `DSChainManager` | Single chain operations | +| `DSPeerManager` | P2P network connectivity | +| `DSTransactionManager` | Transaction pool | +| `DSMasternodeManager` | Masternode lists & quorums | +| `DSIdentitiesManager` | Blockchain identities | +| `DSGovernanceSyncManager` | Governance data sync | + +### Persistence +- **Core Data** with SQLite backend +- 83 entity definitions in `DashSync.xcdatamodeld` +- Custom transformers in `Models/Persistence/Transformers/` + +## Code Conventions + +### Naming +- All classes prefixed with `DS` (e.g., `DSChain`, `DSWallet`) +- Entities suffixed with `Entity` (e.g., `DSChainEntity`) +- Managers suffixed with `Manager` (e.g., `DSPeerManager`) + +### File Organization +- Public headers in main directory +- `+Protected.h` files for subclass-accessible interfaces +- Categories in `Categories/` subdirectories + +### Notifications +Event-driven via `NSNotificationCenter`: +- `DSChainBlocksDidFinishSyncingNotification` +- `DSWalletBalanceDidChangeNotification` +- `DSPeerManagerConnectedPeersDidChangeNotification` + +## Key Classes + +### Chain & Sync +- `DSChain` (3,562 lines) - Central blockchain state manager +- `DSBlock`, `DSMerkleBlock` - Block representations +- `DSChainLock` - Chain lock mechanism + +### Wallet +- `DSWallet` - HD wallet management +- `DSAccount` - Account within wallet +- `DSBIP39Mnemonic` - Mnemonic seed handling +- `DSDerivationPath` - BIP32/44 key derivation + +### Transactions +- `DSTransaction` - Base transaction class +- `DSCoinbaseTransaction` - Mining rewards +- `DSProviderRegistrationTransaction` - Masternode registration +- `DSQuorumCommitmentTransaction` - Quorum operations +- `DSCreditFundingTransaction` - Platform funding + +### Identity & Platform +- `DSBlockchainIdentity` - Dash Platform identity +- `DSBlockchainInvitation` - Contact requests +- `DPContract` - Platform smart contracts +- `DPDocument` - Platform documents + +### Privacy +- `DSCoinJoinManager` - CoinJoin mixing coordination +- `DSCoinJoinWrapper` - Protocol implementation + +## Network Support + +| Network | Purpose | +|---------|---------| +| Mainnet | Production Dash network | +| Testnet | Testing environment | +| Devnet | Development chains | +| Regnet | Local regression testing | + +## Testing + +Tests located in `Example/Tests/`: +- `DSChainTests.m` - Chain operations +- `DSTransactionTests.m` - Transaction handling +- `DSDeterministicMasternodeListTests.m` - Masternode lists +- `DSCoinJoinSessionTest.m` - Privacy mixing +- `DSDIP14Tests.m` - DIP compliance + +## CI/CD Workflows + +- `build.yml` - Main CI pipeline +- `test.yml` - Unit tests +- `lint.yml` - Code linting +- `coverage.yml` - Code coverage +- `syncTestMainnet.yml` / `syncTestTestnet.yml` - Network sync tests + +## Dependencies + +Key CocoaPods: +- **DashSharedCore** - Rust-based cryptographic primitives +- **CocoaLumberjack** - Logging framework +- **DAPI-GRPC** - Decentralized API protocol +- **TinyCborObjc** - CBOR serialization + +## Localization + +Supports 15+ languages: en, de, es, ja, zh-Hans, zh-Hant-TW, uk, bg, el, it, cs, sk, ko, pl, tr, vi + +## Development Workflow + +### Git Workflow Policy + +**NEVER commit or push changes without explicit user permission.** + +When the user asks you to make code changes: +1. Make the requested changes to the code +2. Show what was changed (using `git diff` or explanation) +3. **STOP and WAIT** for explicit permission to commit/push +4. Only commit/push when the user explicitly says to do so + +**Example phrases that give permission to commit/push:** +- "commit these changes" +- "push to github" +- "create a commit and push" +- "commit and push all changes" + +**Do NOT commit/push** just because the user asked for code changes. They may want to test first. + +#### Permission Does NOT Carry Over + +**Each set of changes requires its own explicit permission.** If the user gave permission to commit earlier in the conversation, that permission applies ONLY to those specific changes - NOT to any subsequent changes. + +**Example scenario:** +1. User: "Fix bug X, then commit and push" → Permission granted for bug X fix only +2. User: "Now fix bug Y" → Make the fix, show diff, **STOP AND WAIT** - no permission to commit yet +3. User: "Looks good, commit it" → NOW permission is granted for bug Y fix + +**Common mistake to avoid:** After completing a task like "address review comments" or "fix these issues", do NOT automatically commit. The user needs to test the changes first. Always pause after showing the diff and wait for explicit commit instruction. + +#### Testing Before Commit + +This is especially important for DashSync because: +- Changes affect downstream projects (dashwallet-ios, other consumers) +- Logging and behavioral changes need runtime verification +- The user must run the code to confirm changes work as expected + +Always wait for the user to confirm they have tested and verified the changes before committing. + +### Related Repositories +- **DashJ** (Android equivalent): https://github.com/dashpay/dashj +- **Dash Wallet Android**: https://github.com/dashpay/dash-wallet + +## External Resources + +- [Dash Core Specs](https://dashcore.readme.io/docs) +- [Dash Improvement Proposals](https://github.com/dashpay/dips) +- [Developer Discord](https://discord.com/channels/484546513507188745/614505310593351735) diff --git a/DashSync/shared/Categories/NSData/NSData+Dash.m b/DashSync/shared/Categories/NSData/NSData+Dash.m index ae9ddb2a4..dea693ff6 100644 --- a/DashSync/shared/Categories/NSData/NSData+Dash.m +++ b/DashSync/shared/Categories/NSData/NSData+Dash.m @@ -55,7 +55,6 @@ BOOL setKeychainData(NSData *data, NSString *key, BOOL authenticated) { OSStatus status = SecItemAdd((__bridge CFDictionaryRef)item, NULL); if (status == noErr) return YES; - DSLogPrivate(@"SecItemAdd error: %@", [NSError osStatusErrorWithCode:status].localizedDescription); return NO; } @@ -63,7 +62,6 @@ BOOL setKeychainData(NSData *data, NSString *key, BOOL authenticated) { OSStatus status = SecItemDelete((__bridge CFDictionaryRef)query); if (status == noErr) return YES; - DSLogPrivate(@"SecItemDelete error: %@", [NSError osStatusErrorWithCode:status].localizedDescription); return NO; } @@ -72,7 +70,6 @@ BOOL setKeychainData(NSData *data, NSString *key, BOOL authenticated) { OSStatus status = SecItemUpdate((__bridge CFDictionaryRef)query, (__bridge CFDictionaryRef)update); if (status == noErr) return YES; - DSLogPrivate(@"SecItemUpdate error: %@", [NSError osStatusErrorWithCode:status].localizedDescription); return NO; } @@ -89,7 +86,6 @@ BOOL hasKeychainData(NSString *key, NSError **error) { if (status == errSecItemNotFound) return NO; if (status == noErr) return YES; - DSLogPrivate(@"SecItemCopyMatching error: %@", [NSError osStatusErrorWithCode:status].localizedDescription); if (error) *error = [NSError osStatusErrorWithCode:status]; return NO; } @@ -104,7 +100,6 @@ BOOL hasKeychainData(NSString *key, NSError **error) { if (status == errSecItemNotFound) return nil; if (status == noErr) return CFBridgingRelease(result); - DSLogPrivate(@"SecItemCopyMatching error: %@", [NSError osStatusErrorWithCode:status].localizedDescription); if (error) *error = [NSError osStatusErrorWithCode:status]; return nil; } @@ -164,9 +159,6 @@ BOOL setKeychainDict(NSDictionary *dict, NSString *key, BOOL authenticated) { ]]; set = [set setByAddingObjectsFromArray:classes]; NSDictionary *dictionary = [NSKeyedUnarchiver unarchivedObjectOfClasses:set fromData:d error:error]; - if (*error) { - DSLogPrivate(@"error retrieving dictionary from keychain %@", *error); - } return dictionary; //} } @@ -189,9 +181,6 @@ BOOL setKeychainArray(NSArray *array, NSString *key, BOOL authenticated) { ]]; set = [set setByAddingObjectsFromArray:classes]; NSArray *array = [NSKeyedUnarchiver unarchivedObjectOfClasses:set fromData:d error:error]; - if (*error) { - DSLogPrivate(@"error retrieving array from keychain %@", *error); - } return array; } } diff --git a/DashSync/shared/Categories/NSManagedObject+Sugar.m b/DashSync/shared/Categories/NSManagedObject+Sugar.m index 4a4202ae5..0a45ef240 100644 --- a/DashSync/shared/Categories/NSManagedObject+Sugar.m +++ b/DashSync/shared/Categories/NSManagedObject+Sugar.m @@ -209,7 +209,6 @@ + (NSArray *)fetchObjects:(NSFetchRequest *)request inContext:(NSManagedObjectCo [context performBlockAndWait:^{ a = [context executeFetchRequest:request error:&error]; - if (error) DSLog(@"%s: %@", __func__, error); }]; return a; @@ -277,7 +276,6 @@ + (NSUInteger)countObjects:(NSFetchRequest *)request inContext:(NSManagedObjectC [context performBlockAndWait:^{ count = [context countForFetchRequest:request error:&error]; - if (error) DSLog(@"%s: %@", __func__, error); }]; return count; diff --git a/DashSync/shared/Categories/NSManagedObjectContext+DSSugar.m b/DashSync/shared/Categories/NSManagedObjectContext+DSSugar.m index e9c0c68ca..2d9d5dd08 100644 --- a/DashSync/shared/Categories/NSManagedObjectContext+DSSugar.m +++ b/DashSync/shared/Categories/NSManagedObjectContext+DSSugar.m @@ -16,6 +16,7 @@ // #import "DSDataController.h" +#import "DSLogger.h" #import "NSManagedObjectContext+DSSugar.h" @@ -66,13 +67,18 @@ - (NSError *)ds_saveInBlockAndWait { - (NSError *)ds_save { if (!self.hasChanges) return nil; + + NSTimeInterval saveStart = [[NSDate date] timeIntervalSince1970]; + NSUInteger insertedCount = self.insertedObjects.count; + NSUInteger updatedCount = self.updatedObjects.count; + NSUInteger deletedCount = self.deletedObjects.count; + #if TARGET_OS_IOS NSUInteger taskId = [[UIApplication sharedApplication] beginBackgroundTaskWithExpirationHandler:^{ }]; #endif NSError *error = nil; if (![self save:&error]) { // persist changes - DSLog(@"%s: %@", __func__, error); #if DEBUG abort(); #endif @@ -80,6 +86,11 @@ - (NSError *)ds_save { #if TARGET_OS_IOS [[UIApplication sharedApplication] endBackgroundTask:taskId]; #endif + + NSTimeInterval saveTime = ([[NSDate date] timeIntervalSince1970] - saveStart) * 1000.0; + DSLogInfo(@"CoreData", @"Save completed in %.1f ms (inserted: %lu, updated: %lu, deleted: %lu)", + saveTime, (unsigned long)insertedCount, (unsigned long)updatedCount, (unsigned long)deletedCount); + return error; } diff --git a/DashSync/shared/DashSync.m b/DashSync/shared/DashSync.m index 030364cc0..4d94a29fc 100644 --- a/DashSync/shared/DashSync.m +++ b/DashSync/shared/DashSync.m @@ -209,7 +209,6 @@ - (void)wipeBlockchainNonTerminalDataForChain:(DSChain *)chain inContext:(NSMana - (void)wipeMasternodeDataForChain:(DSChain *)chain inContext:(NSManagedObjectContext *)context { NSParameterAssert(chain); - DSLog(@"wipeMasternodeDataForChain: %@", chain); [self stopSyncForChain:chain]; [context performBlockAndWait:^{ DSChainEntity *chainEntity = [chain chainEntityInContext:context]; @@ -317,16 +316,11 @@ - (void)scheduleBackgroundFetch { NSError *error = nil; [[BGTaskScheduler sharedScheduler] submitTaskRequest:request error:&error]; - if (error) { - DSLog(@"Error scheduling background refresh"); - } } - (void)performFetchWithCompletionHandler:(void (^)(UIBackgroundFetchResult))completionHandler { DSChainManager *mainnetManager = [[DSChainsManager sharedInstance] mainnetManager]; if (mainnetManager.syncState.chainSyncProgress >= 1.0) { - DSLog(@"Background fetch: already synced"); - if (completionHandler) { completionHandler(UIBackgroundFetchResultNoData); } @@ -343,7 +337,6 @@ - (void)performFetchWithCompletionHandler:(void (^)(UIBackgroundFetchResult))com object:nil queue:nil usingBlock:^(NSNotification *note) { - DSLog(@"Background fetch: protected data available"); [[[DSChainsManager sharedInstance] mainnetManager] startSync]; }]; @@ -352,7 +345,6 @@ - (void)performFetchWithCompletionHandler:(void (^)(UIBackgroundFetchResult))com object:nil queue:nil usingBlock:^(NSNotification *note) { - DSLog(@"Background fetch: sync finished"); [self finishBackgroundFetchWithResult:UIBackgroundFetchResultNewData]; }]; @@ -361,11 +353,9 @@ - (void)performFetchWithCompletionHandler:(void (^)(UIBackgroundFetchResult))com object:nil queue:nil usingBlock:^(NSNotification *note) { - DSLog(@"Background fetch: sync failed"); [self finishBackgroundFetchWithResult:UIBackgroundFetchResultFailed]; }]; - DSLog(@"Background fetch: starting"); [mainnetManager startSync]; // sync events to the server @@ -374,8 +364,6 @@ - (void)performFetchWithCompletionHandler:(void (^)(UIBackgroundFetchResult))com - (void)backgroundFetchTimedOut { const double syncProgress = [[DSChainsManager sharedInstance] mainnetManager].syncState.chainSyncProgress; - DSLog(@"Background fetch timeout with progress: %f", syncProgress); - const UIBackgroundFetchResult fetchResult = syncProgress > 0.1 ? UIBackgroundFetchResultNewData : UIBackgroundFetchResultFailed; [self finishBackgroundFetchWithResult:fetchResult]; diff --git a/DashSync/shared/Libraries/AdvancedOperations/Operations/DSOperation.m b/DashSync/shared/Libraries/AdvancedOperations/Operations/DSOperation.m index 2583854bb..20993ea90 100644 --- a/DashSync/shared/Libraries/AdvancedOperations/Operations/DSOperation.m +++ b/DashSync/shared/Libraries/AdvancedOperations/Operations/DSOperation.m @@ -259,7 +259,6 @@ - (void)start { their readiness state. */ - (void)execute { - DSLog(@"%@ must override `execute`.", NSStringFromClass(self.class)); [self finish]; } diff --git a/DashSync/shared/Libraries/DSLogger.h b/DashSync/shared/Libraries/DSLogger.h index c4680c2ba..af15f5e0f 100644 --- a/DashSync/shared/Libraries/DSLogger.h +++ b/DashSync/shared/Libraries/DSLogger.h @@ -25,7 +25,30 @@ static const DDLogLevel ddLogLevel = DDLogLevelVerbose; static const DDLogLevel ddLogLevel = DDLogLevelInfo; #endif /* DEBUG */ -#define DSLog(frmt, ...) DDLogInfo(frmt, ##__VA_ARGS__) //!OCLINT +NS_ASSUME_NONNULL_BEGIN + +// Thread name helper +NSString *DSCurrentThreadName(void); + +#pragma mark - Android-style logging macros +// Format: "HH:MM:SS [thread] ClassName - message" +// These match the Android/DashJ log format + +#define DSLogInfo(className, frmt, ...) DDLogInfo(@"[%@] %@ - " frmt, DSCurrentThreadName(), className, ##__VA_ARGS__) +#define DSLogDebug(className, frmt, ...) DDLogDebug(@"[%@] %@ - " frmt, DSCurrentThreadName(), className, ##__VA_ARGS__) +#define DSLogWarn(className, frmt, ...) DDLogWarn(@"[%@] %@ - " frmt, DSCurrentThreadName(), className, ##__VA_ARGS__) +#define DSLogError(className, frmt, ...) DDLogError(@"[%@] %@ - " frmt, DSCurrentThreadName(), className, ##__VA_ARGS__) + +#ifdef DEBUG +#define DSLogVerbose(className, frmt, ...) DDLogVerbose(@"[%@] %@ - " frmt, DSCurrentThreadName(), className, ##__VA_ARGS__) +#else +#define DSLogVerbose(className, frmt, ...) +#endif /* DEBUG */ + +#pragma mark - Legacy logging macros (deprecated - for backward compatibility during migration) +// These will be removed after full migration to Android-style logging + +#define DSLog(frmt, ...) DDLogInfo(frmt, ##__VA_ARGS__) #ifdef DEBUG #define DSLogPrivate(s, ...) DDLogVerbose(s, ##__VA_ARGS__) @@ -33,8 +56,6 @@ static const DDLogLevel ddLogLevel = DDLogLevelInfo; #define DSLogPrivate(s, ...) #endif /* DEBUG */ -NS_ASSUME_NONNULL_BEGIN - @interface DSLogger : NSObject + (instancetype)sharedInstance; @@ -42,11 +63,24 @@ NS_ASSUME_NONNULL_BEGIN - (NSArray *)logFiles; /** @fn log: - * @brief This method is identical to `DSLog` macro + * @brief This method logs a message with default class name * @param message Final message to log */ + (void)log:(NSString *)message; +/** @fn log:className: + * @brief This method logs a message with specified class name + * @param message Final message to log + * @param className The class name to include in the log + */ ++ (void)log:(NSString *)message className:(NSString *)className; + +/** @fn logVersionInfo + * @brief Logs the app version and DashSync version at startup + * Called automatically when DSLogger is initialized. + */ ++ (void)logVersionInfo; + - (instancetype)init NS_UNAVAILABLE; + (instancetype)new NS_UNAVAILABLE; diff --git a/DashSync/shared/Libraries/DSLogger.m b/DashSync/shared/Libraries/DSLogger.m index 2d68e4ee0..2cf2ed886 100644 --- a/DashSync/shared/Libraries/DSLogger.m +++ b/DashSync/shared/Libraries/DSLogger.m @@ -20,12 +20,50 @@ NS_ASSUME_NONNULL_BEGIN -@interface NoTimestampLogFormatter : NSObject +// Thread name helper - returns current thread name or identifier +NSString *DSCurrentThreadName(void) { + NSThread *thread = [NSThread currentThread]; + NSString *name = thread.name; + if (name.length > 0) { + return name; + } + if ([thread isMainThread]) { + return @"main"; + } + // Use thread number as fallback + NSString *description = thread.description; + NSRange numRange = [description rangeOfString:@"number = "]; + if (numRange.location != NSNotFound) { + NSUInteger start = numRange.location + numRange.length; + NSRange endRange = [description rangeOfString:@"," options:0 range:NSMakeRange(start, description.length - start)]; + if (endRange.location != NSNotFound) { + return [NSString stringWithFormat:@"Thread-%@", [description substringWithRange:NSMakeRange(start, endRange.location - start)]]; + } + } + return @"Thread"; +} + +// Custom log formatter that adds timestamp in Android format (HH:MM:SS) +@interface DSAndroidStyleLogFormatter : NSObject @end -@implementation NoTimestampLogFormatter + +@implementation DSAndroidStyleLogFormatter + - (nullable NSString *)formatLogMessage:(DDLogMessage *)logMessage { - return logMessage.message; + // Get time components + static NSDateFormatter *formatter = nil; + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + formatter = [[NSDateFormatter alloc] init]; + formatter.dateFormat = @"HH:mm:ss"; + formatter.timeZone = [NSTimeZone timeZoneWithAbbreviation:@"UTC"]; + }); + NSString *timestamp = [formatter stringFromDate:logMessage.timestamp]; + + // The message already contains [thread] ClassName - message format from our macros + return [NSString stringWithFormat:@"%@ %@", timestamp, logMessage.message]; } + @end @interface DSLogger () @@ -48,17 +86,27 @@ + (instancetype)sharedInstance { - (instancetype)init { self = [super init]; if (self) { - [DDLog addLogger:[DDOSLogger sharedInstance]]; // os_log + DSAndroidStyleLogFormatter *formatter = [[DSAndroidStyleLogFormatter alloc] init]; - unsigned long long maxFileSize = 1024 * 1024 * 5; // 5 MB max. Then log files are ziped + // Console logger with formatter + DDOSLogger *osLogger = [DDOSLogger sharedInstance]; + [osLogger setLogFormatter:formatter]; + [DDLog addLogger:osLogger]; + + // File logger with formatter + unsigned long long maxFileSize = 1024 * 1024 * 5; // 5 MB max CompressingLogFileManager *logFileManager = [[CompressingLogFileManager alloc] initWithFileSize:maxFileSize]; DDFileLogger *fileLogger = [[DDFileLogger alloc] initWithLogFileManager:logFileManager]; fileLogger.rollingFrequency = 60 * 60 * 24; // 24 hour rolling fileLogger.maximumFileSize = maxFileSize; fileLogger.logFileManager.maximumNumberOfLogFiles = 10; - + [fileLogger setLogFormatter:formatter]; + [DDLog addLogger:fileLogger]; _fileLogger = fileLogger; + + // Log version info at startup + [DSLogger logVersionInfo]; } return self; } @@ -70,22 +118,44 @@ - (instancetype)init { for (NSString *fileName in fileNames) { BOOL hasProperSuffix = [fileName hasSuffix:@".log"] || [fileName hasSuffix:@".gz"]; - + if (hasProperSuffix) { NSString *filePath = [logsDirectory stringByAppendingPathComponent:fileName]; NSURL *fileURL = [NSURL fileURLWithPath:filePath]; - + if (fileURL) { [logFiles addObject:fileURL]; } } } - + return [logFiles copy]; } + (void)log:(NSString *)message { - DSLog(@"%@", message); + DDLogInfo(@"%@", message); +} + ++ (void)log:(NSString *)message className:(NSString *)className { + DSLogInfo(className, @"%@", message); +} + ++ (void)logVersionInfo { + // Get host app version info + NSBundle *mainBundle = [NSBundle mainBundle]; + NSString *appVersion = mainBundle.infoDictionary[@"CFBundleShortVersionString"] ?: @"Unknown"; + NSString *appBuild = mainBundle.infoDictionary[@"CFBundleVersion"] ?: @"Unknown"; + NSString *appName = mainBundle.infoDictionary[@"CFBundleDisplayName"] ?: mainBundle.infoDictionary[@"CFBundleName"] ?: @"DashWallet"; + + // Get DashSync framework version + NSBundle *dashSyncBundle = [NSBundle bundleForClass:[DSLogger class]]; + NSString *dashSyncVersion = dashSyncBundle.infoDictionary[@"CFBundleShortVersionString"] ?: @"Unknown"; + + // Log version info at startup (matching Android format) + DSLogInfo(@"DSLogger", @"===== Application Startup ====="); + DSLogInfo(@"DSLogger", @"%@ v%@ (build %@)", appName, appVersion, appBuild); + DSLogInfo(@"DSLogger", @"DashSync Framework v%@", dashSyncVersion); + DSLogInfo(@"DSLogger", @"==============================="); } @end diff --git a/DashSync/shared/Libraries/DSMerkleTree.m b/DashSync/shared/Libraries/DSMerkleTree.m index 74cabb17e..997da369f 100644 --- a/DashSync/shared/Libraries/DSMerkleTree.m +++ b/DashSync/shared/Libraries/DSMerkleTree.m @@ -103,8 +103,6 @@ - (instancetype)initWithHashes:(NSData *)hashes flags:(NSData *)flags treeElemen // true if the given tx hash is included in the block - (BOOL)containsHash:(UInt256)hash { for (NSUInteger i = 0; i < self.hashes.length; i += sizeof(UInt256)) { - DSLogPrivate(@"hash %@", [NSData dataWithUInt256:[self.hashes UInt256AtOffset:i]].hexString); - DSLogPrivate(@"looking for %@", [NSData dataWithUInt256:hash].hexString); if (uint256_eq(hash, [self.hashes UInt256AtOffset:i])) return YES; } diff --git a/DashSync/shared/Libraries/Logs/CompressingLogFileManager.m b/DashSync/shared/Libraries/Logs/CompressingLogFileManager.m index e1aaa013c..db155ce0b 100644 --- a/DashSync/shared/Libraries/Logs/CompressingLogFileManager.m +++ b/DashSync/shared/Libraries/Logs/CompressingLogFileManager.m @@ -64,16 +64,35 @@ - (id)initWithLogsDirectory:(NSString *)aLogsDirectory if ((self = [super initWithLogsDirectory:aLogsDirectory])) { upToDate = NO; - + // Check for any files that need to be compressed. // But don't start right away. // Wait for the app startup process to finish. - + [self performSelector:@selector(compressNextLogFile) withObject:nil afterDelay:5.0]; } return self; } +- (NSString *)newLogFileName { + // Format: ios-YYYY-MM-DD--HH-mm-ss.log + NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init]; + [dateFormatter setDateFormat:@"yyyy-MM-dd'--'HH-mm-ss"]; + [dateFormatter setTimeZone:[NSTimeZone timeZoneWithAbbreviation:@"UTC"]]; + + NSString *timestamp = [dateFormatter stringFromDate:[NSDate date]]; + return [NSString stringWithFormat:@"ios-%@.log", timestamp]; +} + +- (BOOL)isLogFile:(NSString *)fileName { + // Match both old "log-" prefix and new "ios-" prefix + BOOL hasValidPrefix = [fileName hasPrefix:@"log-"] || [fileName hasPrefix:@"ios-"]; + BOOL hasLogExtension = [[fileName pathExtension] isEqualToString:@"log"]; + BOOL hasGzExtension = [[fileName pathExtension] isEqualToString:@"gz"]; + + return hasValidPrefix && (hasLogExtension || hasGzExtension); +} + - (void)dealloc { [NSObject cancelPreviousPerformRequestsWithTarget:self selector:@selector(compressNextLogFile) object:nil]; diff --git a/DashSync/shared/Models/CLAUDE.md b/DashSync/shared/Models/CLAUDE.md new file mode 100644 index 000000000..7aaefa6bf --- /dev/null +++ b/DashSync/shared/Models/CLAUDE.md @@ -0,0 +1,166 @@ +# DashSync Models + +This directory contains the core domain models for DashSync, organized by functional area. + +## Directory Structure + +| Directory | Purpose | +|-----------|---------| +| `Chain/` | Blockchain state - chains, blocks, merkle trees, chain locks | +| `Wallet/` | HD wallet - accounts, addresses, authentication | +| `Transactions/` | Transaction types - base, coinbase, provider, quorums | +| `Managers/` | Service coordinators - chain managers, service managers | +| `Derivation Paths/` | BIP32/44 key derivation paths | +| `Entities/` | Core Data entity definitions (83 entities) | +| `Identity/` | Blockchain identities, invitations, contacts | +| `Platform/` | Dash Platform - contracts, documents, transitions | +| `Masternode/` | Masternode lists, quorums, rotations | +| `DAPI/` | Decentralized API client and queries | +| `CoinJoin/` | Privacy mixing protocol | +| `Governance/` | Governance objects and voting | +| `Network/` | P2P networking - peers, bloom filters | +| `Messages/` | P2P protocol message handlers | +| `Keys/` | Cryptographic key management | +| `Crypto/` | Cryptography - sparse merkle trees | +| `Persistence/` | Data layer - Core Data controller, migrations | +| `Payment/` | Payment protocol support | +| `Spork/` | Network parameter updates | +| `System/` | Environment and error handling | +| `Notifications/` | Notification definitions | + +## Key Patterns + +### Model Hierarchy + +``` +DSChain (root object) +├── DSWallet[] +│ └── DSAccount[] +│ └── DSDerivationPath[] +├── DSBlock[] / DSMerkleBlock[] +├── DSMasternodeList[] +│ └── DSSimplifiedMasternodeEntry[] +├── DSQuorum[] +└── DSSpork[] +``` + +### Manager Hierarchy + +``` +DSChainsManager (singleton) +└── DSChainManager (per chain) + ├── DSPeerManager + ├── DSTransactionManager + ├── DSMasternodeManager + ├── DSIdentitiesManager + ├── DSGovernanceSyncManager + ├── DSSporkManager + └── DSKeyManager +``` + +## Transactions/ + +Transaction type inheritance: + +``` +DSTransaction (base) +├── DSCoinbaseTransaction +├── DSProviderRegistrationTransaction +├── DSProviderUpdateServiceTransaction +├── DSProviderUpdateRegistrarTransaction +├── DSProviderUpdateRevocationTransaction +├── DSQuorumCommitmentTransaction +├── DSAssetLockTransaction +├── DSAssetUnlockTransaction +└── DSCreditFundingTransaction +``` + +Use `DSTransactionFactory` to instantiate transactions from serialized data. + +## Managers/ + +### Chain Managers (`Managers/Chain Managers/`) +Coordinate blockchain operations: +- `DSChainManager` - Main chain coordinator +- `DSPeerManager` - P2P peer connections +- `DSTransactionManager` - Transaction pool +- `DSMasternodeManager` - Masternode operations +- `DSIdentitiesManager` - Identity management +- `DSGovernanceSyncManager` - Governance sync +- `DSSporkManager` - Spork handling +- `DSKeyManager` - Key operations + +### Service Managers (`Managers/Service Managers/`) +Handle external services: +- `DSAuthenticationManager` - User authentication +- `DSPriceManager` - Cryptocurrency pricing +- `DSInsightManager` - Blockchain explorer APIs + +## Entities/ + +Core Data entities for persistence. Each model typically has a corresponding entity: +- `DSChainEntity` ↔ `DSChain` +- `DSWalletEntity` ↔ `DSWallet` +- `DSTransactionEntity` ↔ `DSTransaction` + +Entity files: +- `*Entity+CoreDataClass.{h,m}` - Auto-generated Core Data class +- `*Entity+CoreDataProperties.{h,m}` - Auto-generated properties +- `*Entity.{h,m}` - Custom methods and logic + +## Identity/ + +Dash Platform identity management: +- `DSBlockchainIdentity` - Main identity class +- `DSBlockchainIdentityRegistrationTransition` - Identity creation +- `DSBlockchainIdentityUpdateTransition` - Identity updates +- `DSBlockchainInvitation` - Contact invitations +- `DSDashpayUserEntity` - Dashpay contacts + +## Platform/ + +Dash Platform Layer 2 objects: +- `DPContract` - Platform contracts +- `DPDocument` - Platform documents +- `DSPlatformDocumentsRequest` - Document queries +- State transitions for identity/document operations + +## Derivation Paths/ + +BIP32/44 key derivation: +- `DSDerivationPath` - Base derivation path +- `DSFundsDerivationPath` - Funds-related paths +- `DSAuthenticationKeysDerivationPath` - Auth keys +- `DSMasternodeHoldingsDerivationPath` - Masternode keys +- `DSCreditFundingDerivationPath` - Platform credit funding + +## Persistence/ + +- `DSDataController` - Core Data stack management +- `Migration/` - Database migration logic +- `Transformers/` - Custom value transformers (CBOR, JSON, etc.) + +## Common Conventions + +### Protected Interfaces +Files ending in `+Protected.h` expose internal methods for subclasses: +```objc +#import "DSTransaction+Protected.h" // For subclass access +``` + +### Entity Lookups +Entities provide class methods for Core Data queries: +```objc ++ (DSChainEntity *)chainEntityForType:(DSChainType)type + devnetIdentifier:(NSString *)devnetIdentifier + inContext:(NSManagedObjectContext *)context; +``` + +### Model-Entity Bridging +```objc +// Model to Entity +DSTransactionEntity *entity = [transaction transactionEntityInContext:context]; + +// Entity to Model +DSTransaction *tx = [entity transactionForChain:chain]; +``` diff --git a/DashSync/shared/Models/Chain/DSBlock.m b/DashSync/shared/Models/Chain/DSBlock.m index f0400d26e..b9fd6034f 100644 --- a/DashSync/shared/Models/Chain/DSBlock.m +++ b/DashSync/shared/Models/Chain/DSBlock.m @@ -133,7 +133,6 @@ - (BOOL)canCalculateDifficultyWithPreviousBlocks:(NSDictionary *)previousBlocks } currentBlock = previousBlocks[uint256_obj(currentBlock.prevBlock)]; if (!currentBlock) { - DSLog(@"[%@] Could not retrieve previous block", self.chain.name); return FALSE; } } @@ -149,9 +148,6 @@ - (BOOL)verifyDifficultyWithPreviousBlocks:(NSDictionary *)previousBlocks rDiffi *difficulty = darkGravityWaveTarget; } int32_t diff = self.target - darkGravityWaveTarget; - if (abs(diff) > 1) { - DSLog(@"[%@] weird difficulty for block at height %u with target %@ (off by %u)", self.chain.name, self.height, uint256_hex(setCompactBE(self.target)), diff); - } return (abs(diff) < 2); //the core client is less precise with a rounding error that can sometimes cause a problem. We are very rarely 1 off } @@ -173,7 +169,6 @@ - (int32_t)darkGravityWaveTargetWithPreviousBlocks:(NSDictionary *)previousBlock if (self.chain.allowMinDifficultyBlocks) { // recent block is more than 2 hours old if (self.timestamp > (previousBlock.timestamp + 2 * 60 * 60)) { - DSLog(@"[%@] Our block is way ahead of previous block %d > %d", self.chain.name, self.timestamp, previousBlock.timestamp); return self.chain.maxProofOfWorkTarget; } // recent block is more than 10 minutes old @@ -215,11 +210,7 @@ - (int32_t)darkGravityWaveTargetWithPreviousBlocks:(NSDictionary *)previousBlock assert(currentBlock); break; } - DSBlock *oldCurrentBlock = currentBlock; currentBlock = previousBlocks[uint256_obj(currentBlock.prevBlock)]; - if (!currentBlock) { - DSLog(@"[%@] Block %d missing for dark gravity wave calculation", self.chain.name, oldCurrentBlock.height - 1); - } } UInt256 blockCount256 = ((UInt256){.u64 = {blockCount, 0, 0, 0}}); // darkTarget is the difficulty diff --git a/DashSync/shared/Models/Chain/DSChain.m b/DashSync/shared/Models/Chain/DSChain.m index cefb7a469..e35372275 100644 --- a/DashSync/shared/Models/Chain/DSChain.m +++ b/DashSync/shared/Models/Chain/DSChain.m @@ -24,6 +24,7 @@ #import "BigIntTypes.h" #import "DSAccount.h" +#import "DSLogger.h" #import "DSAuthenticationKeysDerivationPath.h" #import "DSBIP39Mnemonic.h" #import "DSBlock+Protected.h" @@ -1505,9 +1506,6 @@ - (void)setLastTerminalBlockFromCheckpoints { } } - if (_lastTerminalBlock) { - DSLog(@"[%@] last terminal block at height %d chosen from checkpoints (hash is %@)", self.name, _lastTerminalBlock.height, [NSData dataWithUInt256:_lastTerminalBlock.blockHash].hexString); - } } - (void)setLastSyncBlockFromCheckpoints { @@ -1533,9 +1531,6 @@ - (void)setLastSyncBlockFromCheckpoints { } } - if (_lastSyncBlock) { - DSLog(@"[%@] last sync block at height %d chosen from checkpoints (hash is %@)", self.name, _lastSyncBlock.height, [NSData dataWithUInt256:_lastSyncBlock.blockHash].hexString); - } } - (DSBlock *)lastSyncBlockDontUseCheckpoints { @@ -1554,7 +1549,6 @@ - (DSBlock *)lastSyncBlockWithUseCheckpoints:(BOOL)useCheckpoints { } if (!_lastSyncBlock && useCheckpoints) { - DSLog(@"[%@] No last Sync Block, setting it from checkpoints", self.name); [self setLastSyncBlockFromCheckpoints]; } @@ -1781,10 +1775,10 @@ - (BOOL)addMinedFullBlock:(DSFullBlock *)block { - (BOOL)addBlock:(DSBlock *)block receivedAsHeader:(BOOL)isHeaderOnly fromPeer:(DSPeer *)peer { NSString *prefix = [NSString stringWithFormat:@"[%@: %@:%d]", self.name, peer.host ? peer.host : @"TEST", peer.port]; if (peer && !self.chainManager.syncPhase) { - DSLog(@"%@ Block was received from peer after reset, ignoring it", prefix); return FALSE; } - //DSLog(@"a block %@",uint256_hex(block.blockHash)); + DSLogDebug(@"DSChain", @"received block %@ at height %u from peer %@", + uint256_reverse_hex(block.blockHash), block.height, peer.host); //All blocks will be added from same delegateQueue NSArray *txHashes = block.transactionHashes; @@ -1823,15 +1817,6 @@ - (BOOL)addBlock:(DSBlock *)block receivedAsHeader:(BOOL)isHeaderOnly fromPeer:( if (!prev) { // header is an orphan -#if LOG_PREV_BLOCKS_ON_ORPHAN - NSSortDescriptor *sortDescriptor = [NSSortDescriptor sortDescriptorWithKey:@"height" ascending:TRUE]; - for (DSBlock *merkleBlock in [[self.blocks allValues] sortedArrayUsingDescriptors:@[sortDescriptor]]) { - DSLog(@"%@ printing previous block at height %d : %@", prefix, merkleBlock.height, merkleBlock.blockHashValue); - } -#endif - DSLog(@"%@ relayed orphan block %@, previous %@, height %d, last block is %@, lastBlockHeight %d, time %@", prefix, - uint256_reverse_hex(block.blockHash), uint256_reverse_hex(block.prevBlock), block.height, uint256_reverse_hex(self.lastTerminalBlock.blockHash), self.lastSyncBlockHeight, [NSDate dateWithTimeIntervalSince1970:block.timestamp]); - if (peer) { [self.chainManager chain:self receivedOrphanBlock:block fromPeer:peer]; [peer receivedOrphanBlock]; @@ -1894,20 +1879,14 @@ - (BOOL)addBlock:(DSBlock *)block receivedAsHeader:(BOOL)isHeaderOnly fromPeer:( uint32_t foundDifficulty = 0; if ((block.height > self.minimumDifficultyBlocks) && (block.height > (lastCheckpoint.height + DGW_PAST_BLOCKS_MAX)) && ![block verifyDifficultyWithPreviousBlocks:(blockPosition & DSBlockPosition_Terminal) ? self.mTerminalBlocks : self.mSyncBlocks rDifficulty:&foundDifficulty]) { - DSLog(@"%@ relayed block with invalid difficulty height %d target %x foundTarget %x, blockHash: %@", prefix, - block.height, block.target, foundDifficulty, blockHash); - if (peer) { [self.chainManager chain:self badBlockReceivedFromPeer:peer]; } return FALSE; } - + UInt256 difficulty = setCompactLE(block.target); if (uint256_sup(block.blockHash, difficulty)) { - DSLog(@"%@ relayed block with invalid block hash %d target %x, blockHash: %@ difficulty: %@", prefix, - block.height, block.target, uint256_bin(block.blockHash), uint256_bin(difficulty)); - if (peer) { [self.chainManager chain:self badBlockReceivedFromPeer:peer]; } @@ -1919,8 +1898,6 @@ - (BOOL)addBlock:(DSBlock *)block receivedAsHeader:(BOOL)isHeaderOnly fromPeer:( if ((!equivalentTerminalBlock) && (checkpoint && !uint256_eq(block.blockHash, checkpoint.blockHash))) { // verify block chain checkpoints - DSLog(@"%@ relayed a block that differs from the checkpoint at height %d, blockHash: %@, expected: %@", - prefix, block.height, blockHash, uint256_hex(checkpoint.blockHash)); if (peer) { [self.chainManager chain:self badBlockReceivedFromPeer:peer]; } @@ -1931,9 +1908,6 @@ - (BOOL)addBlock:(DSBlock *)block receivedAsHeader:(BOOL)isHeaderOnly fromPeer:( uint32_t h = block.height; if ((phase == DSChainSyncPhase_ChainSync || phase == DSChainSyncPhase_Synced) && uint256_eq(block.prevBlock, self.lastSyncBlockHash)) { // new block extends sync chain - if ((block.height % 1000) == 0 || txHashes.count > 0 || h > peer.lastBlockHeight) { - DSLog(@"%@ + sync block at: %d: %@", prefix, h, uint256_hex(block.blockHash)); - } self.mSyncBlocks[blockHash] = block; if (equivalentTerminalBlock && equivalentTerminalBlock.chainLocked && !block.chainLocked) { [block setChainLockedWithEquivalentBlock:equivalentTerminalBlock]; @@ -1941,9 +1915,6 @@ - (BOOL)addBlock:(DSBlock *)block receivedAsHeader:(BOOL)isHeaderOnly fromPeer:( self.lastSyncBlock = block; self.chainManager.syncState.lastSyncBlockHeight = block.height; if (!equivalentTerminalBlock && uint256_eq(block.prevBlock, self.lastTerminalBlock.blockHash)) { - if ((h % 1000) == 0 || txHashes.count > 0 || h > peer.lastBlockHeight) { - DSLog(@"%@ + terminal block (caught up) at: %d: %@", prefix, h, uint256_hex(block.blockHash)); - } self.mTerminalBlocks[blockHash] = block; self.lastTerminalBlock = block; self.chainManager.syncState.lastTerminalBlockHeight = block.height; @@ -1963,9 +1934,6 @@ - (BOOL)addBlock:(DSBlock *)block receivedAsHeader:(BOOL)isHeaderOnly fromPeer:( } } else if (uint256_eq(block.prevBlock, self.lastTerminalBlock.blockHash)) { // new block extends terminal chain - if ((h % 500) == 0 || txHashes.count > 0 || h > peer.lastBlockHeight) { - DSLog(@"%@ + terminal block at: %d: %@", prefix, h, uint256_hex(block.blockHash)); - } self.mTerminalBlocks[blockHash] = block; self.lastTerminalBlock = block; self.chainManager.syncState.estimatedBlockHeight = self.estimatedBlockHeight; @@ -1979,9 +1947,6 @@ - (BOOL)addBlock:(DSBlock *)block receivedAsHeader:(BOOL)isHeaderOnly fromPeer:( if (h == self.estimatedBlockHeight) syncDone = YES; onMainChain = TRUE; } else if ((phase == DSChainSyncPhase_ChainSync || phase == DSChainSyncPhase_Synced) && self.mSyncBlocks[blockHash] != nil) { // we already have the block (or at least the header) - if ((h % 1) == 0 || txHashes.count > 0 || h > peer.lastBlockHeight) { - DSLog(@"%@ relayed existing sync block at height %d", prefix, h); - } self.mSyncBlocks[blockHash] = block; if (equivalentTerminalBlock && equivalentTerminalBlock.chainLocked && !block.chainLocked) { [block setChainLockedWithEquivalentBlock:equivalentTerminalBlock]; @@ -2006,9 +1971,6 @@ - (BOOL)addBlock:(DSBlock *)block receivedAsHeader:(BOOL)isHeaderOnly fromPeer:( } } } else if (self.mTerminalBlocks[blockHash] != nil && (blockPosition & DSBlockPosition_Terminal)) { // we already have the block (or at least the header) - if ((h % 1) == 0 || txHashes.count > 0 || h > peer.lastBlockHeight) { - DSLog(@"%@ relayed existing terminal block at height %d (last sync height %d)", prefix, h, self.lastSyncBlockHeight); - } self.mTerminalBlocks[blockHash] = block; @synchronized(peer) { if (peer) { @@ -2029,22 +1991,18 @@ - (BOOL)addBlock:(DSBlock *)block receivedAsHeader:(BOOL)isHeaderOnly fromPeer:( } } else { // new block is on a fork if (h <= [self lastCheckpoint].height) { // fork is older than last checkpoint - DSLog(@"%@ ignoring block on fork older than most recent checkpoint, fork height: %d, blockHash: %@", prefix, h, blockHash); return TRUE; } - + if (h <= self.lastChainLock.height) { - DSLog(@"%@ ignoring block on fork when main chain is chainlocked: %d, blockHash: %@", prefix, h, blockHash); return TRUE; } - - DSLog(@"%@ potential chain fork to height %d blockPosition %d", prefix, block.height, blockPosition); + if (!(blockPosition & DSBlockPosition_Sync)) { //this is only a reorg of the terminal blocks self.mTerminalBlocks[blockHash] = block; if (uint256_supeq(self.lastTerminalBlock.chainWork, block.chainWork)) return TRUE; // if fork is shorter than main chain, ignore it for now - DSLog(@"%@ found potential chain fork on height %d", prefix, block.height); - + DSBlock *b = block, *b2 = self.lastTerminalBlock; while (b && b2 && !uint256_eq(b.blockHash, b2.blockHash) && !b2.chainLocked) { // walk back to where the fork joins the main chain @@ -2053,12 +2011,9 @@ - (BOOL)addBlock:(DSBlock *)block receivedAsHeader:(BOOL)isHeaderOnly fromPeer:( } if (!uint256_eq(b.blockHash, b2.blockHash) && b2.chainLocked) { //intermediate chain locked block - DSLog(@"%@ no reorganizing chain to height %d because of chainlock at height %d", prefix, h, b2.height); return TRUE; } - - DSLog(@"%@ reorganizing terminal chain from height %d, new height is %d", prefix, b.height, h); - + self.lastTerminalBlock = block; self.chainManager.syncState.lastTerminalBlockHeight = block.height; @synchronized(peer) { @@ -2078,7 +2033,6 @@ - (BOOL)addBlock:(DSBlock *)block receivedAsHeader:(BOOL)isHeaderOnly fromPeer:( } if (uint256_supeq(self.lastSyncBlock.chainWork, block.chainWork)) return TRUE; // if fork is shorter than main chain, ignore it for now - DSLog(@"%@ found sync chain fork on height %d", prefix, h); if ((phase == DSChainSyncPhase_ChainSync || phase == DSChainSyncPhase_Synced) && !uint256_supeq(self.lastTerminalBlock.chainWork, block.chainWork)) { DSBlock *b = block, *b2 = self.lastTerminalBlock; @@ -2088,9 +2042,8 @@ - (BOOL)addBlock:(DSBlock *)block receivedAsHeader:(BOOL)isHeaderOnly fromPeer:( } if (!uint256_eq(b.blockHash, b2.blockHash) && b2.chainLocked) { //intermediate chain locked block - DSLog(@"%@ no reorganizing chain to height %d because of chainlock at height %d", prefix, h, b2.height); + // no reorganizing chain because of chainlock } else { - DSLog(@"%@ reorganizing terminal chain from height %d, new height is %d", prefix, b.height, h); self.lastTerminalBlock = block; self.chainManager.syncState.lastTerminalBlockHeight = block.height; @synchronized(peer) { @@ -2109,12 +2062,9 @@ - (BOOL)addBlock:(DSBlock *)block receivedAsHeader:(BOOL)isHeaderOnly fromPeer:( } if (!uint256_eq(b.blockHash, b2.blockHash) && b2.chainLocked) { //intermediate chain locked block - DSLog(@"%@ no reorganizing sync chain to height %d because of chainlock at height %d", prefix, h, b2.height); return TRUE; } - - DSLog(@"%@ reorganizing sync chain from height %d, new height is %d", prefix, b.height, h); - + NSMutableArray *txHashes = [NSMutableArray array]; // mark transactions after the join point as unconfirmed for (DSWallet *wallet in self.wallets) { @@ -2235,9 +2185,6 @@ - (DSBlock *)lastTerminalBlock { DSMerkleBlock *lastTerminalBlock = [[lastTerminalBlocks firstObject] merkleBlock]; @synchronized (self) { self->_lastTerminalBlock = lastTerminalBlock; - if (lastTerminalBlock) { - DSLog(@"[%@] last terminal block at height %d recovered from db (hash is %@)", self.name, lastTerminalBlock.height, [NSData dataWithUInt256:lastTerminalBlock.blockHash].hexString); - } } }]; @@ -2305,7 +2252,6 @@ - (BOOL)addChainLock:(DSChainLock *)chainLock { [terminalBlock setChainLockedWithChainLock:chainLock]; if ((terminalBlock.chainLocked) && (![self recentTerminalBlockForBlockHash:terminalBlock.blockHash])) { //the newly chain locked block is not in the main chain, we will need to reorg to it - DSLog(@"[%@] Added a chain lock for block %@ that was not on the main terminal chain ending in %@, reorginizing", self.name, terminalBlock, self.lastSyncBlock); //clb chain locked block //tbmc terminal block DSBlock *clb = terminalBlock, *tbmc = self.lastTerminalBlock; @@ -2327,10 +2273,8 @@ - (BOOL)addChainLock:(DSChainLock *)chainLock { } if (cancelReorg) { - DSLog(@"[%@] Cancelling terminal reorg because block %@ is already chain locked", self.name, tbmc); + // Cancelling terminal reorg because block is already chain locked } else { - DSLog(@"[%@] Reorginizing to height %d", self.name, clb.height); - self.lastTerminalBlock = terminalBlock; self.chainManager.syncState.lastTerminalBlockHeight = terminalBlock.height; [self.chainManager notifySyncStateChanged]; @@ -2360,8 +2304,6 @@ - (BOOL)addChainLock:(DSChainLock *)chainLock { DSBlock *sbmc = self.lastSyncBlockDontUseCheckpoints; if (sbmc && (syncBlock.chainLocked) && ![self recentSyncBlockForBlockHash:syncBlock.blockHash]) { //!OCLINT //the newly chain locked block is not in the main chain, we will need to reorg to it - DSLog(@"[%@] Added a chain lock for block %@ that was not on the main sync chain ending in %@, reorginizing", self.name, syncBlock, self.lastSyncBlock); - //clb chain locked block //sbmc sync block main chain DSBlock *clb = syncBlock; @@ -2382,14 +2324,12 @@ - (BOOL)addChainLock:(DSChainLock *)chainLock { } if (cancelReorg) { - DSLog(@"[%@] Cancelling sync reorg because block %@ is already chain locked", self.name, sbmc); + // Cancelling sync reorg because block is already chain locked } else { self.lastSyncBlock = syncBlock; self.chainManager.syncState.lastSyncBlockHeight = syncBlock.height; [self.chainManager notifySyncStateChanged]; - DSLog(@"[%@] Reorginizing to height %d (last sync block %@)", self.name, clb.height, self.lastSyncBlock); - - + NSMutableArray *txHashes = [NSMutableArray array]; // mark transactions after the join point as unconfirmed for (DSWallet *wallet in self.wallets) { @@ -2869,7 +2809,6 @@ - (DSTransactionDirection)directionOfTransaction:(DSTransaction *)transaction { // MARK: - Wiping - (void)wipeBlockchainInfoInContext:(NSManagedObjectContext *)context { - DSLog(@"[%@] Wiping Blockchain Info", self.name); for (DSWallet *wallet in self.wallets) { [wallet wipeBlockchainInfoInContext:context]; } @@ -2897,7 +2836,6 @@ - (void)wipeBlockchainInfoInContext:(NSManagedObjectContext *)context { } - (void)wipeBlockchainNonTerminalInfoInContext:(NSManagedObjectContext *)context { - DSLog(@"[%@] Wiping Blockchain Non Terminal Info", self.name); for (DSWallet *wallet in self.wallets) { [wallet wipeBlockchainInfoInContext:context]; } @@ -2920,7 +2858,6 @@ - (void)wipeBlockchainNonTerminalInfoInContext:(NSManagedObjectContext *)context } - (void)wipeMasternodesInContext:(NSManagedObjectContext *)context { - DSLog(@"[%@] Wiping Masternode Info", self.name); DSChainEntity *chainEntity = [self chainEntityInContext:context]; [DSLocalMasternodeEntity deleteAllOnChainEntity:chainEntity]; [DSSimplifiedMasternodeEntryEntity deleteAllOnChainEntity:chainEntity]; @@ -2932,7 +2869,6 @@ - (void)wipeMasternodesInContext:(NSManagedObjectContext *)context { } - (void)wipeWalletsAndDerivatives { - DSLog(@"[%@] Wiping Wallets and Derivatives", self.name); [self unregisterAllWallets]; [self unregisterAllStandaloneDerivationPaths]; self.mWallets = [NSMutableArray array]; @@ -3471,12 +3407,8 @@ - (void)saveBlockLocators { for (DSTransactionHashEntity *e in [DSTransactionHashEntity objectsInContext:self.chainManagedObjectContext matching:@"txHash in %@", [self.transactionHashHeights allKeys]]) { e.blockHeight = [self.transactionHashHeights[e.txHash] intValue]; e.timestamp = [self.transactionHashTimestamps[e.txHash] intValue]; - ; [entities addObject:e]; } - for (DSTransactionHashEntity *e in entities) { - DSLogPrivate(@"[%@] blockHeight is %u for %@", self.name, e.blockHeight, e.txHash); - } self.transactionHashHeights = [NSMutableDictionary dictionary]; self.transactionHashTimestamps = [NSMutableDictionary dictionary]; @@ -3503,7 +3435,6 @@ - (void)saveTerminalBlocks { if ([[DSOptionsManager sharedInstance] keepHeaders]) { //only remove orphan chains NSArray *recentOrphans = [DSMerkleBlockEntity objectsInContext:self.chainManagedObjectContext matching:@"(chain == %@) && (height > %u) && !(blockHash in %@)", [self chainEntityInContext:self.chainManagedObjectContext], startHeight, blocks.allKeys]; - if ([recentOrphans count]) DSLog(@"%lu recent orphans will be removed from disk", (unsigned long)[recentOrphans count]); [DSMerkleBlockEntity deleteObjects:recentOrphans inContext:self.chainManagedObjectContext]; } else { //remember to not delete blocks needed for quorums diff --git a/DashSync/shared/Models/Chain/DSChainLock.m b/DashSync/shared/Models/Chain/DSChainLock.m index 3d9af3dea..99017b2d6 100644 --- a/DashSync/shared/Models/Chain/DSChainLock.m +++ b/DashSync/shared/Models/Chain/DSChainLock.m @@ -74,8 +74,6 @@ - (instancetype)initWithMessage:(NSData *)message onChain:(DSChain *)chain { off += sizeof(UInt768); self.chain = chain; - DSLog(@"[%@] the chain lock signature received for height %d (sig %@) (blockhash %@)", chain.name, self.height, uint768_hex(_signature), uint256_hex(_blockHash)); - return self; } @@ -102,7 +100,6 @@ - (UInt256)requestID { [data appendString:@"clsig"]; [data appendUInt32:self.height]; _requestID = [data SHA256_2]; - DSLog(@"[%@] the chain lock request ID is %@ for height %d", self.chain.name, uint256_hex(_requestID), self.height); return _requestID; } @@ -118,11 +115,6 @@ - (UInt256)signIDForQuorumEntry:(DSQuorumEntry *)quorumEntry { - (BOOL)verifySignatureAgainstQuorum:(DSQuorumEntry *)quorumEntry { UInt256 signId = [self signIDForQuorumEntry:quorumEntry]; BOOL verified = key_bls_verify(quorumEntry.quorumPublicKey.u8, quorumEntry.useLegacyBLSScheme, signId.u8, self.signature.u8); -#if DEBUG - DSLog(@"[%@] verifySignatureAgainstQuorum (%u): %u: %u: %@: %@: %@: %u", self.chain.name, verified, quorumEntry.llmqType, quorumEntry.verified, @"", uint384_hex(quorumEntry.quorumPublicKey), @"", quorumEntry.useLegacyBLSScheme); -#else - DSLogPrivate(@"[%@] verifySignatureAgainstQuorum (%u): %u: %u: %@: %@: %@: %u", self.chain.name, verified, quorumEntry.llmqType, quorumEntry.verified, uint256_hex(signId), uint384_hex(quorumEntry.quorumPublicKey), uint768_hex(self.signature), quorumEntry.useLegacyBLSScheme); -#endif return verified; } @@ -146,16 +138,6 @@ - (BOOL)verifySignatureWithQuorumOffset:(uint32_t)offset { DSQuorumEntry *quorumEntry = [self.chain.chainManager.masternodeManager quorumEntryForChainLockRequestID:[self requestID] forBlockHeight:self.height - offset]; if (quorumEntry && quorumEntry.verified) { self.signatureVerified = [self verifySignatureAgainstQuorum:quorumEntry]; - if (!self.signatureVerified) { - DSLog(@"[%@] unable to verify signature with offset %d", self.chain.name, offset); - } else { - DSLog(@"[%@] signature verified with offset %d", self.chain.name, offset); - } - - } else if (quorumEntry) { - DSLog(@"[%@] quorum entry %@ found but is not yet verified", self.chain.name, uint256_hex(quorumEntry.quorumHash)); - } else { - DSLog(@"[%@] no quorum entry found", self.chain.name); } if (self.signatureVerified) { self.intendedQuorum = quorumEntry; @@ -166,14 +148,11 @@ - (BOOL)verifySignatureWithQuorumOffset:(uint32_t)offset { } } else if (quorumEntry.verified && offset == 8) { //try again a few blocks more in the past - DSLog(@"[%@] trying with offset 0", self.chain.name); return [self verifySignatureWithQuorumOffset:0]; } else if (quorumEntry.verified && offset == 0) { //try again a few blocks more in the future - DSLog(@"[%@] trying with offset 16", self.chain.name); return [self verifySignatureWithQuorumOffset:16]; } - DSLog(@"[%@] returning chain lock signature verified %d with offset %d", self.chain.name, self.signatureVerified, offset); return self.signatureVerified; } diff --git a/DashSync/shared/Models/Chain/DSFullBlock.m b/DashSync/shared/Models/Chain/DSFullBlock.m index 585f6f9f4..cb8d6fccc 100644 --- a/DashSync/shared/Models/Chain/DSFullBlock.m +++ b/DashSync/shared/Models/Chain/DSFullBlock.m @@ -83,18 +83,9 @@ - (instancetype)initWithMessage:(NSData *)message onChain:(DSChain *)chain { self.totalTransactions = (uint32_t)transactions.count; if (![self isMerkleTreeValid]) { - DSLog(@"[%@] Merkle tree not valid for block", self.chain.name); return nil; } -#if LOG_BLOCKS || LOG_BLOCKS_FULL -#if LOG_BLOCKS_FULL - DSLog(@"[%@] %d - block %@ (%@) has %d transactions", self.chain.name, self.height, uint256_hex(self.blockHash), message.hexString, self.totalTransactions); -#else - DSLog(@"[%@] %d - block %@ has %d transactions", self.chain.name, self.height, uint256_hex(self.blockHash), self.totalTransactions); -#endif -#endif - return self; } @@ -171,10 +162,6 @@ - (BOOL)mineBlockAfterBlock:(DSBlock *)block withNonceOffset:(uint32_t)nonceOffs NSMutableData *preNonceMutableData = [self preNonceMutableData]; uint32_t i = 0; UInt256 fullTarget = setCompactLE(block.target); - DSLog(@"[%@] Trying to mine a block at height %d with target %@", self.chain.name, block.height, uint256_bin(fullTarget)); -#if LOG_MINING_BEST_TRIES - UInt256 bestTry = UINT256_MAX; -#endif do { NSMutableData *d = [preNonceMutableData mutableCopy]; [d appendUInt32:i]; @@ -182,17 +169,10 @@ - (BOOL)mineBlockAfterBlock:(DSBlock *)block withNonceOffset:(uint32_t)nonceOffs if (!uint256_sup(potentialBlockHash, fullTarget)) { //We found a block - DSLog(@"[%@] A Block was found %@ %@", self.chain.name, uint256_bin(fullTarget), uint256_bin(potentialBlockHash)); self.blockHash = potentialBlockHash; found = TRUE; break; } -#if LOG_MINING_BEST_TRIES - else if (uint256_sup(bestTry, potentialBlockHash)) { - DSLog(@"[%@] New best try (%d) found for target %@ %@", self.chain.name, i, uint256_bin(fullTarget), uint256_bin(potentialBlockHash)); - bestTry = potentialBlockHash; - } -#endif i++; } while (i != UINT32_MAX); if (!found) { diff --git a/DashSync/shared/Models/Chain/DSMerkleBlock.m b/DashSync/shared/Models/Chain/DSMerkleBlock.m index ebdf7a2da..bffcacff9 100644 --- a/DashSync/shared/Models/Chain/DSMerkleBlock.m +++ b/DashSync/shared/Models/Chain/DSMerkleBlock.m @@ -93,14 +93,6 @@ - (instancetype)initWithMessage:(NSData *)message onChain:(DSChain *)chain { self.blockHash = [DSKeyManager x11:d]; self.chain = chain; -#if LOG_MERKLE_BLOCKS || LOG_MERKLE_BLOCKS_FULL -#if LOG_MERKLE_BLOCKS_FULL - DSLog(@"[%@] %d - merkle block %@ (%@) has %d transactions", self.chain.name, self.height, uint256_hex(self.blockHash), message.hexString, self.totalTransactions); -#else - DSLog(@"[%@] %d - merkle block %@ has %d transactions", self.chain.name, self.height, uint256_hex(self.blockHash), self.totalTransactions); -#endif -#endif - return self; } diff --git a/DashSync/shared/Models/CoinJoin/DSCoinJoinManager.m b/DashSync/shared/Models/CoinJoin/DSCoinJoinManager.m index 69e5cb99f..b521e2a94 100644 --- a/DashSync/shared/Models/CoinJoin/DSCoinJoinManager.m +++ b/DashSync/shared/Models/CoinJoin/DSCoinJoinManager.m @@ -35,6 +35,7 @@ #import "DSBlock.h" #import "DSKeyManager.h" #import "DSDerivationPath+Protected.h" +#import "DSLogger.h" int32_t const DEFAULT_MIN_DEPTH = 0; int32_t const DEFAULT_MAX_DEPTH = 9999999; @@ -59,7 +60,7 @@ @implementation DSCoinJoinManager + (instancetype)sharedInstanceForChain:(DSChain *)chain { NSParameterAssert(chain); - + dispatch_once(&managerChainToken, ^{ _managerChainDictionary = [NSMutableDictionary dictionary]; }); @@ -106,14 +107,14 @@ - (CoinJoinClientOptions *)createOptions { options->coinjoin_multi_session = NO; options->denom_only = NO; options->chain_type = self.chain.chainType; - + return options; } - (void)updateOptionsWithAmount:(uint64_t)amount { if (self.options->coinjoin_amount != amount) { self.options->coinjoin_amount = amount; - + if (self.wrapper.isRegistered) { [self.wrapper updateOptions:self.options]; } @@ -123,7 +124,7 @@ - (void)updateOptionsWithAmount:(uint64_t)amount { - (void)updateOptionsWithEnabled:(BOOL)isEnabled { if (self.options->enable_coinjoin != isEnabled) { self.options->enable_coinjoin = isEnabled; - + if (self.wrapper.isRegistered) { [self.wrapper updateOptions:self.options]; } @@ -133,7 +134,7 @@ - (void)updateOptionsWithEnabled:(BOOL)isEnabled { - (void)updateOptionsWithSessions:(int32_t)sessions { if (self.options->coinjoin_sessions != sessions) { self.options->coinjoin_sessions = sessions; - + if (self.wrapper.isRegistered) { [self.wrapper updateOptions:self.options]; } @@ -141,7 +142,7 @@ - (void)updateOptionsWithSessions:(int32_t)sessions { } - (void)configureMixingWithAmount:(uint64_t)amount rounds:(int32_t)rounds sessions:(int32_t)sessions withMultisession:(BOOL)multisession denominationGoal:(int32_t)denomGoal denominationHardCap:(int32_t)denomHardCap { - DSLog(@"[%@] CoinJoin: mixing configuration: { rounds: %d, sessions: %d, amount: %llu, multisession: %s, denomGoal: %d, denomHardCap: %d }", self.chain.name, rounds, sessions, amount, multisession ? "YES" : "NO", denomGoal, denomHardCap); + DSLogInfo(@"DSCoinJoinManager", @"[%@] CoinJoin: mixing configuration: { rounds: %d, sessions: %d, amount: %llu, multisession: %s, denomGoal: %d, denomHardCap: %d }", self.chain.name, rounds, sessions, amount, multisession ? "YES" : "NO", denomGoal, denomHardCap); self.options->enable_coinjoin = true; self.options->coinjoin_amount = amount; self.options->coinjoin_rounds = rounds; @@ -149,7 +150,7 @@ - (void)configureMixingWithAmount:(uint64_t)amount rounds:(int32_t)rounds sessio self.options->coinjoin_multi_session = multisession; self.options->coinjoin_denoms_goal = denomGoal; self.options->coinjoin_denoms_hardcap = denomHardCap; - + if (self.wrapper.isRegistered) { [self.wrapper updateOptions:self.options]; } @@ -167,7 +168,7 @@ - (void)startAsync { } - (void)start { - DSLog(@"[%@] CoinJoinManager starting", self.chain.name); + DSLogInfo(@"DSCoinJoinManager", @"[%@] CoinJoinManager starting", self.chain.name); [self cancelCoinjoinTimer]; uint32_t interval = 1; uint32_t delay = 1; @@ -178,13 +179,13 @@ - (void)start { @synchronized (self) { self.cachedBlockHeight = self.chain.lastSyncBlock.height; self.options->enable_coinjoin = YES; - + if ([self.wrapper isRegistered]) { [self.wrapper updateOptions:self.options]; } else { [self.wrapper registerCoinJoin:self.options]; } - + self.coinjoinTimer = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0, self.processingQueue); if (self.coinjoinTimer) { dispatch_source_set_timer(self.coinjoinTimer, dispatch_time(DISPATCH_TIME_NOW, (int64_t)(delay * NSEC_PER_SEC)), interval * NSEC_PER_SEC, 1ull * NSEC_PER_SEC); @@ -200,7 +201,7 @@ - (void)doMaintenance { if ([self validMNCount] == 0) { return; } - + [self.wrapper doMaintenance]; } @@ -216,11 +217,11 @@ - (BOOL)startMixing { - (void)initiateShutdown { if (self.isMixing && !self.isShuttingDown) { - DSLog(@"[%@] CoinJoinManager initiated shutdown", self.chain.name); + DSLogInfo(@"DSCoinJoinManager", @"[%@] CoinJoinManager initiated shutdown", self.chain.name); self.isShuttingDown = true; [self updateOptionsWithSessions:0]; [self.wrapper initiateShutdown]; - + if (self.masternodeGroup != nil && self.masternodeGroup.isRunning) { [self.chain.chainManager.peerManager shouldSendDsq:false]; [self.masternodeGroup stopAsync]; @@ -230,7 +231,7 @@ - (void)initiateShutdown { - (void)stop { if (self.isMixing) { - DSLog(@"[%@] CoinJoinManager stopping", self.chain.name); + DSLogInfo(@"DSCoinJoinManager", @"[%@] CoinJoinManager stopping", self.chain.name); self.isMixing = false; [self cancelCoinjoinTimer]; self.cachedLastSuccessBlock = 0; @@ -247,7 +248,7 @@ - (void)stopAsync { [self.masternodeGroup stopAsync]; self.masternodeGroup = nil; } - + [[NSNotificationCenter defaultCenter] removeObserver:self]; } @@ -269,20 +270,12 @@ - (void)handleSyncStateDidChangeNotification:(NSNotification *)note { - (void)handleTransactionReceivedNotification { DSWallet *wallet = self.chain.wallets.firstObject; DSTransaction *lastTransaction = wallet.accounts.firstObject.recentTransactions.firstObject; - + if ([self.wrapper isMixingFeeTx:lastTransaction.txHash]) { -#if DEBUG - DSLogPrivate(@"[%@] CoinJoin tx: Mixing Fee: %@", self.chain.name, uint256_reverse_hex(lastTransaction.txHash)); -#else - DSLog(@"[%@] CoinJoin tx: Mixing Fee: %@", self.chain.name, @""); -#endif + DSLogInfo(@"DSCoinJoinManager", @"CoinJoin mixing fee transaction detected: %@", uint256_reverse_hex(lastTransaction.txHash)); [self onTransactionProcessed:lastTransaction.txHash type:CoinJoinTransactionType_MixingFee]; } else if ([self coinJoinTxTypeForTransaction:lastTransaction] == CoinJoinTransactionType_Mixing) { -#if DEBUG - DSLogPrivate(@"[%@] CoinJoin tx: Mixing Transaction: %@", self.chain.name, uint256_reverse_hex(lastTransaction.txHash)); -#else - DSLog(@"[%@] CoinJoin tx: Mixing Transaction: %@", self.chain.name, @""); -#endif + DSLogInfo(@"DSCoinJoinManager", @"CoinJoin mixing transaction detected: %@", uint256_reverse_hex(lastTransaction.txHash)); [self.wrapper unlockOutputs:lastTransaction]; [self onTransactionProcessed:lastTransaction.txHash type:CoinJoinTransactionType_Mixing]; } @@ -292,33 +285,33 @@ - (void)doAutomaticDenominatingWithDryRun:(BOOL)dryRun completion:(void (^)(BOOL if (![self.wrapper isRegistered]) { [self.wrapper registerCoinJoin:self.options]; } - + if (!dryRun && [self validMNCount] == 0) { completion(NO); return; } - - DSLog(@"[%@] CoinJoin: doAutomaticDenominatingWithDryRun: %@", self.chain.name, dryRun ? @"YES" : @"NO"); - + + DSLogInfo(@"DSCoinJoinManager", @"[%@] CoinJoin: doAutomaticDenominatingWithDryRun: %@", self.chain.name, dryRun ? @"YES" : @"NO"); + dispatch_async(self.processingQueue, ^{ BOOL result = [self.wrapper doAutomaticDenominatingWithDryRun:dryRun]; - + if (!dryRun) { if (result) { if (!self.hasReportedSuccess) { - DSLog(@"[%@] CoinJoin: Mixing started successfully", self.chain.name); + DSLogInfo(@"DSCoinJoinManager", @"[%@] CoinJoin: Mixing started successfully", self.chain.name); self.hasReportedSuccess = YES; self.hasReportedFailure = NO; } } else { if (!self.hasReportedFailure) { - DSLog(@"[%@] CoinJoin: Mixing start failed, will retry", self.chain.name); + DSLogInfo(@"DSCoinJoinManager", @"[%@] CoinJoin: Mixing start failed, will retry", self.chain.name); self.hasReportedFailure = YES; self.hasReportedSuccess = NO; } } } - + completion(result); }); } @@ -344,7 +337,7 @@ - (void)processMessageFrom:(DSPeer *)peer message:(NSData *)message type:(NSStri if (!self.isMixing) { return; } - + dispatch_async(self.processingQueue, ^{ if ([type isEqualToString:MSG_COINJOIN_QUEUE]) { if (!self.isShuttingDown) { @@ -359,131 +352,128 @@ - (void)processMessageFrom:(DSPeer *)peer message:(NSData *)message type:(NSStri - (BOOL)isMineInput:(UInt256)txHash index:(uint32_t)index { DSTransaction *tx = [self.chain transactionForHash:txHash]; DSAccount *account = [self.chain firstAccountThatCanContainTransaction:tx]; - + if (index < tx.outputs.count) { DSTransactionOutput *output = tx.outputs[index]; - + if ([account containsAddress:output.address]) { return YES; } } - + return NO; } - (NSArray *)selectCoinsGroupedByAddresses:(WalletEx *)walletEx skipDenominated:(BOOL)skipDenominated anonymizable:(BOOL)anonymizable skipUnconfirmed:(BOOL)skipUnconfirmed maxOupointsPerAddress:(int32_t)maxOupointsPerAddress { @synchronized(self) { // Note: cache is checked in dash-shared-core. - + uint64_t smallestDenom = coinjoin_get_smallest_denomination(); NSMutableDictionary *mapTally = [[NSMutableDictionary alloc] init]; NSMutableSet *setWalletTxesCounted = [[NSMutableSet alloc] init]; - + DSUTXO outpoint; NSArray *utxos = self.chain.wallets.firstObject.unspentOutputs; for (NSValue *value in utxos) { [value getValue:&outpoint]; - + if ([setWalletTxesCounted containsObject:uint256_data(outpoint.hash)]) { continue; } - + [setWalletTxesCounted addObject:uint256_data(outpoint.hash)]; DSTransaction *wtx = [self.chain transactionForHash:outpoint.hash]; - + if (wtx == nil) { continue; } - + if (wtx.isCoinbaseClassicTransaction && [wtx getBlocksToMaturity] > 0) { continue; } - + DSAccount *account = self.chain.wallets.firstObject.accounts.firstObject; - if (!account.coinJoinDerivationPath.addressesLoaded) { - DSLog(@"[%@] CoinJoin selectCoinsGroupedByAddresses: CJDerivationPath addresses NOT loaded", self.chain.name); - } - + BOOL isTrusted = wtx.instantSendReceived || [account transactionIsVerified:wtx]; - + if (skipUnconfirmed && !isTrusted) { continue; } - + for (int32_t i = 0; i < wtx.outputs.count; i++) { DSTransactionOutput *output = wtx.outputs[i]; NSData *txDest = output.outScript; NSString *address = [NSString bitcoinAddressWithScriptPubKey:txDest forChain:self.chain]; - + if (address == nil) { continue; } - + if (![account containsAddress:output.address]) { continue; } - + DSCompactTallyItem *tallyItem = mapTally[txDest]; - + if (maxOupointsPerAddress != -1 && tallyItem != nil && tallyItem.inputCoins.count >= maxOupointsPerAddress) { continue; } - + if ([account isSpent:dsutxo_obj(((DSUTXO){outpoint.hash, i}))]) { continue; } - + if (is_locked_coin(walletEx, (uint8_t (*)[32])(outpoint.hash.u8), (uint32_t)i)) { continue; } - + if (skipDenominated && is_denominated_amount(output.amount)) { continue; } - + if (anonymizable) { // ignore collaterals if (is_collateral_amount(output.amount)) { continue; } - + // ignore outputs that are 10 times smaller then the smallest denomination // otherwise they will just lead to higher fee / lower priority if (output.amount <= smallestDenom/10) { continue; } - + // ignore mixed if (is_fully_mixed(walletEx, (uint8_t (*)[32])(outpoint.hash.u8), (uint32_t)i)) { continue; } } - + if (tallyItem == nil) { tallyItem = [[DSCompactTallyItem alloc] init]; tallyItem.txDestination = txDest; mapTally[txDest] = tallyItem; } - + tallyItem.amount += output.amount; DSInputCoin *coin = [[DSInputCoin alloc] initWithTx:wtx index:i]; [tallyItem.inputCoins addObject:coin]; } } - + // construct resulting vector // NOTE: vecTallyRet is "sorted" by txdest (i.e. address), just like mapTally NSMutableArray *vecTallyRet = [NSMutableArray array]; - + for (DSCompactTallyItem *item in mapTally.allValues) { // TODO: (dashj) ignore this to get this dust back in if (anonymizable && item.amount < smallestDenom) { continue; } - + [vecTallyRet addObject:item]; } - + // Note: cache is assigned in dash-shared-core return vecTallyRet; @@ -492,96 +482,93 @@ - (BOOL)isMineInput:(UInt256)txHash index:(uint32_t)index { - (uint32_t)countInputsWithAmount:(uint64_t)inputAmount { uint32_t total = 0; - + @synchronized(self) { NSArray *unspent = self.chain.wallets.firstObject.unspentOutputs; - + DSUTXO outpoint; for (uint32_t i = 0; i < unspent.count; i++) { [unspent[i] getValue:&outpoint]; DSTransaction *tx = [self.chain transactionForHash:outpoint.hash]; - + if (tx == NULL) { continue; } - + if (tx.outputs[outpoint.n].amount != inputAmount) { continue; } - + if (tx.confirmations < 0) { continue; } - + total++; } } - + return total; } - (NSArray *)availableCoins:(WalletEx *)walletEx onlySafe:(BOOL)onlySafe coinControl:(DSCoinControl *_Nullable)coinControl minimumAmount:(uint64_t)minimumAmount maximumAmount:(uint64_t)maximumAmount minimumSumAmount:(uint64_t)minimumSumAmount maximumCount:(uint64_t)maximumCount { NSMutableArray *vCoins = [NSMutableArray array]; - + @synchronized(self) { CoinType coinType = coinControl != nil ? coinControl.coinType : CoinType_AllCoins; - + uint64_t total = 0; // Either the WALLET_FLAG_AVOID_REUSE flag is not set (in which case we always allow), or we default to avoiding, and only in the case where a coin control object is provided, and has the avoid address reuse flag set to false, do we allow already used addresses BOOL allowUsedAddresses = /* !IsWalletFlagSet(WALLET_FLAG_AVOID_REUSE) || */ (coinControl != nil && !coinControl.avoidAddressReuse); int32_t minDepth = coinControl != nil ? coinControl.minDepth : DEFAULT_MIN_DEPTH; int32_t maxDepth = coinControl != nil ? coinControl.maxDepth : DEFAULT_MAX_DEPTH; NSSet *spendables = [self getSpendableTXs]; - + for (DSTransaction *coin in spendables) { UInt256 wtxid = coin.txHash; DSAccount *account = self.chain.wallets.firstObject.accounts.firstObject; - if (!account.coinJoinDerivationPath.addressesLoaded) { - DSLog(@"[%@] CoinJoin availableCoins: CJDerivationPath addresses NOT loaded", self.chain.name); - } - + if ([account transactionIsPending:coin]) { continue; } - + if (coin.isImmatureCoinBase) { continue; } - + BOOL safeTx = coin.instantSendReceived || [account transactionIsVerified:coin]; - + if (onlySafe && !safeTx) { continue; } - + uint32_t depth = coin.confirmations; - + if (depth < minDepth || depth > maxDepth) { continue; } - + for (uint32_t i = 0; i < coin.outputs.count; i++) { DSTransactionOutput *output = coin.outputs[i]; uint64_t value = output.amount; BOOL found = NO; - + if (coinType == CoinType_OnlyFullyMixed) { if (!is_denominated_amount(value)) { continue; } - + found = is_fully_mixed(walletEx, (uint8_t (*)[32])(wtxid.u8), (uint32_t)i); } else if (coinType == CoinType_OnlyReadyToMix) { if (!is_denominated_amount(value)) { continue; } - + found = !is_fully_mixed(walletEx, (uint8_t (*)[32])(wtxid.u8), (uint32_t)i); } else if (coinType == CoinType_OnlyNonDenominated) { if (is_collateral_amount(value)) { continue; // do not use collateral amounts } - + found = !is_denominated_amount(value); } else if (coinType == CoinType_OnlyMasternodeCollateral) { found = value == 1000 * DUFFS; @@ -590,48 +577,48 @@ - (uint32_t)countInputsWithAmount:(uint64_t)inputAmount { } else { found = YES; } - + if (!found) { continue; } - + if (value < minimumAmount || value > maximumAmount) { continue; } - + DSUTXO utxo = ((DSUTXO){wtxid, i}); - + if (coinControl != nil && coinControl.hasSelected && !coinControl.allowOtherInputs && ![coinControl isSelected:utxo]) { continue; } - + if (is_locked_coin(walletEx, (uint8_t (*)[32])(wtxid.u8), (uint32_t)i) && coinType != CoinType_OnlyMasternodeCollateral) { continue; } - + if ([account isSpent:dsutxo_obj(utxo)]) { continue; } - + if (output.address == nil || ![account containsAddress:output.address]) { continue; } - + if (!allowUsedAddresses && [account transactionAddressAlreadySeenInOutputs:output.address]) { continue; } - + [vCoins addObject:[[DSInputCoin alloc] initWithTx:coin index:i]]; - + // Checks the sum amount of all UTXO's. if (minimumSumAmount != MAX_MONEY) { total += value; - + if (total >= minimumSumAmount) { return vCoins; } } - + // Checks the maximum number of UTXO's. if (maximumCount > 0 && vCoins.count >= maximumCount) { return vCoins; @@ -639,7 +626,7 @@ - (uint32_t)countInputsWithAmount:(uint64_t)inputAmount { } } } - + return vCoins; } @@ -647,23 +634,23 @@ - (double)getMixingProgress { if (![self.wrapper isRegistered]) { [self.wrapper registerCoinJoin:self.options]; } - + double requiredRounds = self.options->coinjoin_rounds + 0.875; // 1 x 50% + 1 x 50%^2 + 1 x 50%^3 __block int totalInputs = 0; __block int totalRounds = 0; - + NSDictionary *> *outputs = [self getOutputs]; uint64_t collateralAmount = [self.wrapper getCollateralAmount]; NSArray *denominations = [self.wrapper getStandardDenominations]; - + [outputs enumerateKeysAndObjectsUsingBlock:^(NSNumber *denom, NSArray *outputs, BOOL *stop) { [outputs enumerateObjectsUsingBlock:^(NSValue *output, NSUInteger idx, BOOL *stop) { DSUTXO outpoint; [output getValue:&outpoint]; - + if (denom.intValue >= 0) { int rounds = [self.wrapper getRealOutpointCoinJoinRounds:outpoint]; - + if (rounds >= 0) { totalInputs += 1; totalRounds += rounds; @@ -671,52 +658,52 @@ - (double)getMixingProgress { } else if (denom.intValue == -2) { DSTransaction *tx = [self.chain transactionForHash:outpoint.hash]; DSTransactionOutput *output = tx.outputs[outpoint.n]; - + __block int unmixedInputs = 0; __block int64_t outputValue = output.amount - collateralAmount; - + [denominations enumerateObjectsUsingBlock:^(NSNumber *coin, NSUInteger idx, BOOL *stop) { while (outputValue - coin.longLongValue > 0) { unmixedInputs++; outputValue -= coin.longLongValue; } }]; - + totalInputs += unmixedInputs; } }]; }]; - + double progress = totalInputs != 0 ? (double)totalRounds / (requiredRounds * totalInputs) : 0.0; - + if (self.lastReportedProgress != progress) { _lastReportedProgress = progress; - DSLog(@"[%@] CoinJoin: getMixingProgress: %f = %d / (%f * %d)", self.chain.name, progress, totalRounds, requiredRounds, totalInputs); + DSLogInfo(@"DSCoinJoinManager", @"[%@] CoinJoin: getMixingProgress: %f = %d / (%f * %d)", self.chain.name, progress, totalRounds, requiredRounds, totalInputs); } - + return fmax(0.0, fmin(progress, 1.0)); } - (NSDictionary *> *)getOutputs { NSMutableDictionary *> *outputs = [NSMutableDictionary dictionary]; - + for (NSNumber *amount in [self.wrapper getStandardDenominations]) { outputs[@([self.wrapper amountToDenomination:amount.unsignedLongLongValue])] = [NSMutableArray array]; } - + outputs[@(-2)] = [NSMutableArray array]; outputs[@(0)] = [NSMutableArray array]; DSAccount *account = self.chain.wallets.firstObject.accounts.firstObject; NSArray *utxos = account.unspentOutputs; DSUTXO outpoint; - + for (NSValue *value in utxos) { [value getValue:&outpoint]; - + DSTransaction *tx = [self.chain transactionForHash:outpoint.hash]; DSTransactionOutput *output = tx.outputs[outpoint.n]; NSString *address = [DSKeyManager addressWithScriptPubKey:output.outScript forChain:self.chain]; - + if ([account containsCoinJoinAddress:address]) { int denom = [self.wrapper amountToDenomination:output.amount]; NSMutableArray *listDenoms = outputs[@(denom)]; @@ -726,7 +713,7 @@ - (double)getMixingProgress { [outputs[@(-2)] addObject:value]; } } - + return outputs; } @@ -734,11 +721,11 @@ - (BOOL)isCoinJoinOutput:(DSTransactionOutput *)output utxo:(DSUTXO)utxo { if (![self.wrapper isDenominatedAmount:output.amount]) { return false; } - + if (![self.wrapper isFullyMixed:utxo]) { return false; } - + return [self.chain.wallets.firstObject.accounts.firstObject.coinJoinDerivationPath containsAddress:output.address]; } @@ -746,22 +733,22 @@ - (DSCoinJoinBalance *)getBalance { if (![self.wrapper isRegistered]) { [self.wrapper registerCoinJoin:self.options]; } - + DSAccount *account = self.chain.wallets.firstObject.accounts.firstObject; uint64_t anonymizedBalance = 0; uint64_t denominatedBalance = 0; DSUTXO outpoint; NSArray *utxos = account.unspentOutputs; - + for (NSValue *value in utxos) { [value getValue:&outpoint]; DSTransaction *tx = [account transactionForHash:outpoint.hash]; DSTransactionOutput *output = tx.outputs[outpoint.n]; - + if ([self isCoinJoinOutput:output utxo:outpoint]) { anonymizedBalance += output.amount; } - + if ([self.wrapper isDenominatedAmount:output.amount]) { denominatedBalance += output.amount; } @@ -778,27 +765,27 @@ - (DSCoinJoinBalance *)getBalance { watchOnlyTrusted:0 watchOnlyUntrustedPending:0 watchOnlyImmature:0]; - + return balance; } - (NSSet *)getSpendableTXs { NSMutableSet *ret = [[NSMutableSet alloc] init]; NSArray *unspent = self.chain.wallets.firstObject.unspentOutputs; - + DSUTXO outpoint; for (uint32_t i = 0; i < unspent.count; i++) { [unspent[i] getValue:&outpoint]; DSTransaction *tx = [self.chain transactionForHash:outpoint.hash]; - + if (tx) { [ret addObject:tx]; - + // Skip entries until we encounter a new TX DSUTXO nextOutpoint; while (i + 1 < unspent.count) { [unspent[i + 1] getValue:&nextOutpoint]; - + if (!uint256_eq(nextOutpoint.hash, outpoint.hash)) { break; } @@ -806,20 +793,20 @@ - (DSCoinJoinBalance *)getBalance { } } } - + return ret; } - (NSString *)freshAddress:(BOOL)internal { NSString *address; DSAccount *account = self.chain.wallets.firstObject.accounts.firstObject; - + if (internal) { address = account.coinJoinChangeAddress; } else { address = account.coinJoinReceiveAddress; } - + return address; } @@ -836,35 +823,29 @@ - (NSArray *)getUsedReceiveAddresses { - (BOOL)commitTransactionForAmounts:(NSArray *)amounts outputs:(NSArray *)outputs coinControl:(DSCoinControl *)coinControl onPublished:(void (^)(UInt256 txId, NSError * _Nullable error))onPublished { DSAccount *account = self.chain.wallets.firstObject.accounts.firstObject; DSTransaction *transaction = [account transactionForAmounts:amounts toOutputScripts:outputs withFee:YES coinControl:coinControl]; - + if (!transaction) { return NO; } - + BOOL signedTransaction = [account signTransaction:transaction]; - + if (!signedTransaction || !transaction.isSigned) { - DSLog(@"[%@] CoinJoin error: not signed", self.chain.name); + DSLogInfo(@"DSCoinJoinManager", @"[%@] CoinJoin error: not signed", self.chain.name); return NO; } else { [self.chain.chainManager.transactionManager publishTransaction:transaction completion:^(NSError *error) { - NSString *txDescription = @""; - #if DEBUG - txDescription = transaction.description; - #endif - if (error) { - DSLog(@"[%@] CoinJoin publish error: %@ for tx: %@", self.chain.name, error.description, txDescription); + DSLogInfo(@"DSCoinJoinManager", @"[%@] CoinJoin publish error: %@ for tx: %@", self.chain.name, error.description, uint256_reverse_hex(transaction.txHash)); } else { - DSLog(@"[%@] CoinJoin publish success: %@", self.chain.name, txDescription); + DSLogInfo(@"DSCoinJoinManager", @"[%@] CoinJoin publish success: %@", self.chain.name, uint256_reverse_hex(transaction.txHash)); } - dispatch_async(self.processingQueue, ^{ onPublished(transaction.txHash, error); }); }]; } - + return YES; } @@ -900,7 +881,7 @@ - (BOOL)sendMessageOfType:(NSString *)messageType message:(NSData *)message with DSCoinJoinSignedInputs *request = [DSCoinJoinSignedInputs requestWithData:message]; [peer sendRequest:request]; } else { - DSLog(@"[%@] CoinJoin: unknown message type: %@", self.chain.name, messageType); + DSLogInfo(@"DSCoinJoinManager", @"[%@] CoinJoin: unknown message type: %@", self.chain.name, messageType); return NO; } @@ -920,11 +901,11 @@ - (BOOL)isWaitingForNewBlock { if (!self.isChainSynced) { return true; } - + if (self.options->coinjoin_multi_session == true) { return false; } - + return self.cachedBlockHeight - self.cachedLastSuccessBlock < MIN_BLOCKS_TO_WAIT; } @@ -943,11 +924,11 @@ - (void)minimumAnonymizableBalanceWithCompletion:(void (^)(uint64_t balance))com dispatch_async(self.processingQueue, ^{ uint64_t valueMin = [self.wrapper getSmallestDenomination]; BOOL hasCollateralInputs = [self.wrapper hasCollateralInputs:YES]; - + if (hasCollateralInputs) { valueMin += [self.wrapper getMaxCollateralAmount]; } - + completion(valueMin); }); } @@ -960,22 +941,22 @@ - (DSCoinControl *)selectCoinJoinUTXOs { DSCoinControl *coinControl = [[DSCoinControl alloc] init]; [coinControl useCoinJoin:YES]; NSArray *utxos = self.chain.wallets.firstObject.unspentOutputs; - + for (NSValue *value in utxos) { DSUTXO utxo; [value getValue:&utxo]; - + DSTransaction *tx = [self.chain transactionForHash:utxo.hash]; if (!tx) continue; - + DSTransactionOutput *output = tx.outputs[utxo.n]; if (!output) continue; - + if ([self isCoinJoinOutput:output utxo:utxo] && ![self.wrapper isLockedCoin:utxo]) { [coinControl select:utxo]; } } - + return coinControl; } @@ -984,24 +965,24 @@ - (void)printUsedKeys { NSArray *issuedAddresses = [self getIssuedReceiveAddresses]; NSArray *usedAddresses = [self getUsedReceiveAddresses]; double percent = (double)usedAddresses.count * 100.0 / (double)issuedAddresses.count; - DSLog(@"[%@] CoinJoin init. Used addresses count %lu out of %lu (%.2f %%)", self.chain.name, (unsigned long)usedAddresses.count, (unsigned long)issuedAddresses.count, percent); + DSLogInfo(@"DSCoinJoinManager", @"[%@] CoinJoin init. Used addresses count %lu out of %lu (%.2f %%)", self.chain.name, (unsigned long)usedAddresses.count, (unsigned long)issuedAddresses.count, percent); }); } // Events - (void)onSessionStarted:(int32_t)baseId clientSessionId:(UInt256)clientId denomination:(uint32_t)denom poolState:(PoolState)state poolMessage:(PoolMessage)message poolStatus:(PoolStatus)status ipAddress:(UInt128)address isJoined:(BOOL)joined { - DSLog(@"[%@] CoinJoin: onSessionStarted: baseId: %d, clientId: %@, denom: %d, state: %d, message: %d, address: %@, isJoined: %s", self.chain.name, baseId, [uint256_hex(clientId) substringToIndex:7], denom, state, message, [self.masternodeGroup hostFor:address], joined ? "yes" : "no"); + DSLogInfo(@"DSCoinJoinManager", @"[%@] CoinJoin: onSessionStarted: baseId: %d, clientId: %@, denom: %d, state: %d, message: %d, address: %@, isJoined: %s", self.chain.name, baseId, [uint256_hex(clientId) substringToIndex:7], denom, state, message, [self.masternodeGroup hostFor:address], joined ? "yes" : "no"); [self.managerDelegate sessionStartedWithId:baseId clientSessionId:clientId denomination:denom poolState:state poolMessage:message poolStatus:status ipAddress:address isJoined:joined]; } - (void)onSessionComplete:(int32_t)baseId clientSessionId:(UInt256)clientId denomination:(uint32_t)denom poolState:(PoolState)state poolMessage:(PoolMessage)message poolStatus:(PoolStatus)status ipAddress:(UInt128)address isJoined:(BOOL)joined { - DSLog(@"[%@] CoinJoin: onSessionComplete: baseId: %d, clientId: %@, denom: %d, state: %d, status: %d, message: %d, address: %@, isJoined: %s", self.chain.name, baseId, [uint256_hex(clientId) substringToIndex:7], denom, state, status, message, [self.masternodeGroup hostFor:address], joined ? "yes" : "no"); + DSLogInfo(@"DSCoinJoinManager", @"[%@] CoinJoin: onSessionComplete: baseId: %d, clientId: %@, denom: %d, state: %d, status: %d, message: %d, address: %@, isJoined: %s", self.chain.name, baseId, [uint256_hex(clientId) substringToIndex:7], denom, state, status, message, [self.masternodeGroup hostFor:address], joined ? "yes" : "no"); [self.managerDelegate sessionCompleteWithId:baseId clientSessionId:clientId denomination:denom poolState:state poolMessage:message poolStatus:status ipAddress:address isJoined:joined]; } - (void)onMixingStarted:(nonnull NSArray *)statuses { - DSLog(@"[%@] CoinJoin: onMixingStarted, statuses: %@", self.chain.name, statuses.count > 0 ? [NSString stringWithFormat:@"%@", statuses] : @"empty"); + DSLogInfo(@"DSCoinJoinManager", @"[%@] CoinJoin: onMixingStarted, statuses: %@", self.chain.name, statuses.count > 0 ? [NSString stringWithFormat:@"%@", statuses] : @"empty"); [self.managerDelegate mixingStarted]; } @@ -1009,10 +990,10 @@ - (void)onMixingComplete:(nonnull NSArray *)statuses isInterrupted:(BOOL)isInter if (self.isShuttingDown) { [self stop]; } - + PoolStatus returnStatus = PoolStatus_ErrNotEnoughFunds; BOOL isError = YES; - + for (NSNumber *statusNumber in statuses) { PoolStatus status = [statusNumber intValue]; if (![self isError:status]) { @@ -1020,7 +1001,7 @@ - (void)onMixingComplete:(nonnull NSArray *)statuses isInterrupted:(BOOL)isInter isError = NO; break; } - + if (status != PoolStatus_ErrNotEnoughFunds) { returnStatus = status; } @@ -1031,9 +1012,9 @@ - (void)onMixingComplete:(nonnull NSArray *)statuses isInterrupted:(BOOL)isInter - (void)onTransactionProcessed:(UInt256)txId type:(CoinJoinTransactionType)type { #if DEBUG - DSLog(@"[%@] CoinJoin: onTransactionProcessed: %@, type: %d", self.chain.name, uint256_reverse_hex(txId), type); + DSLogInfo(@"DSCoinJoinManager", @"[%@] CoinJoin: onTransactionProcessed: %@, type: %d", self.chain.name, uint256_reverse_hex(txId), type); #else - DSLog(@"[%@] CoinJoin: onTransactionProcessed: %@, type: %d", self.chain.name, @"", type); + DSLogInfo(@"DSCoinJoinManager", @"[%@] CoinJoin: onTransactionProcessed: %@, type: %d", self.chain.name, @"", type); #endif [self.managerDelegate transactionProcessedWithId:txId type:type]; } diff --git a/DashSync/shared/Models/CoinJoin/DSCoinJoinWrapper.m b/DashSync/shared/Models/CoinJoin/DSCoinJoinWrapper.m index e3f29e99e..7f8994723 100644 --- a/DashSync/shared/Models/CoinJoin/DSCoinJoinWrapper.m +++ b/DashSync/shared/Models/CoinJoin/DSCoinJoinWrapper.m @@ -25,6 +25,7 @@ #import "DSChainManager.h" #import "DSCoinJoinWrapper.h" #import "DSBlock.h" +#import "DSLogger.h" #define AS_OBJC(context) ((__bridge DSCoinJoinWrapper *)(context)) #define AS_RUST(context) ((__bridge void *)(context)) @@ -83,7 +84,7 @@ - (BOOL)doAutomaticDenominatingWithDryRun:(BOOL)dryRun { Balance *balance = [[self.manager getBalance] ffi_malloc]; BOOL result = do_automatic_denominating(_clientManager, *balance, dryRun); [DSCoinJoinBalance ffi_free:balance]; - + return result; } } @@ -117,14 +118,14 @@ - (void)processDSQueueFrom:(DSPeer *)peer message:(NSData *)message { ByteArray *array = malloc(sizeof(ByteArray)); array->len = (uintptr_t)message.length; array->ptr = data_malloc(message); - + process_ds_queue(_clientManager, peer.address.u8, peer.port, array); - + if (array) { if (array->ptr) { free((void *)array->ptr); } - + free(array); } } @@ -135,13 +136,13 @@ - (void)processMessageFrom:(DSPeer *)peer message:(NSData *)message type:(NSStri ByteArray *array = malloc(sizeof(ByteArray)); array->len = (uintptr_t)message.length; array->ptr = data_malloc(message); - + process_coinjoin_message(_clientManager, peer.address.u8, peer.port, array, [type UTF8String]); - + if (array->ptr) { free((void *)array->ptr); } - + free(array); } } @@ -167,18 +168,18 @@ + (CoinJoinTransactionType)coinJoinTxTypeForTransaction:(DSTransaction *)transac + (CoinJoinTransactionType)coinJoinTxTypeForTransaction:(DSTransaction *)transaction account:(DSAccount *)account { NSArray *amountsSent = [account amountsSentByTransaction:transaction]; - + Transaction *tx = [transaction ffi_malloc:transaction.chain.chainType]; uint64_t *inputValues = malloc(amountsSent.count * sizeof(uint64_t)); for (uintptr_t i = 0; i < amountsSent.count; i++) { inputValues[i] = [amountsSent[i] unsignedLongLongValue]; } - + CoinJoinTransactionType type = get_coinjoin_tx_type(tx, inputValues, amountsSent.count); [DSTransaction ffi_free:tx]; free(inputValues); - + return type; } @@ -204,11 +205,11 @@ - (uint64_t)getSmallestDenomination { @synchronized (self) { CoinJoinDenominations *denominations = get_standard_denominations(); NSMutableArray *result = [NSMutableArray arrayWithCapacity:denominations->length]; - + for (size_t i = 0; i < denominations->length; i++) { [result addObject:@(denominations->denoms[i])]; } - + destroy_coinjoin_denomination(denominations); return result; } @@ -242,17 +243,17 @@ - (int32_t)getRealOutpointCoinJoinRounds:(DSUTXO)utxo { - (NSArray *)getSessionStatuses { @synchronized (self) { CoinJoinSessionStatuses* statuses = get_sessions_status(_clientManager); - + if (statuses) { NSMutableArray *statusArray = [NSMutableArray arrayWithCapacity:statuses->length]; - + for (size_t i = 0; i < statuses->length; i++) { PoolStatus status = statuses->statuses[i]; [statusArray addObject:@(status)]; } - + destroy_coinjoin_session_statuses(statuses); - + return statusArray; } else { return @[]; @@ -290,13 +291,13 @@ - (void)dealloc { InputValue *getInputValueByPrevoutHash(uint8_t (*prevout_hash)[32], uint32_t index, const void *context) { UInt256 txHash = *((UInt256 *)prevout_hash); InputValue *inputValue = NULL; - + @synchronized (context) { DSCoinJoinWrapper *wrapper = AS_OBJC(context); inputValue = malloc(sizeof(InputValue)); DSWallet *wallet = wrapper.chain.wallets.firstObject; int64_t value = [wallet inputValue:txHash inputIndex:index]; - + if (value != -1) { inputValue->is_valid = TRUE; inputValue->value = value; @@ -304,26 +305,26 @@ - (void)dealloc { inputValue->is_valid = FALSE; } } - + return inputValue; } bool hasChainLock(Block *block, const void *context) { BOOL hasChainLock = NO; - + @synchronized (context) { DSCoinJoinWrapper *wrapper = AS_OBJC(context); hasChainLock = [wrapper.chain blockHeightChainLocked:block->height]; } - + return hasChainLock; } Transaction *getTransaction(uint8_t (*tx_hash)[32], const void *context) { UInt256 txHash = *((UInt256 *)tx_hash); Transaction *tx = NULL; - + @synchronized (context) { DSCoinJoinWrapper *wrapper = AS_OBJC(context); DSTransaction *transaction = [wrapper.chain transactionForHash:txHash]; @@ -332,60 +333,60 @@ bool hasChainLock(Block *block, const void *context) { tx = [transaction ffi_malloc:wrapper.chain.chainType]; } } - + return tx; } bool isMineInput(uint8_t (*tx_hash)[32], uint32_t index, const void *context) { UInt256 txHash = *((UInt256 *)tx_hash); BOOL result = NO; - + @synchronized (context) { result = [AS_OBJC(context).manager isMineInput:txHash index:index]; } - + return result; } GatheredOutputs* availableCoins(bool onlySafe, CoinControl *coinControl, WalletEx *walletEx, const void *context) { GatheredOutputs *gatheredOutputs; - + @synchronized (context) { DSCoinJoinWrapper *wrapper = AS_OBJC(context); ChainType chainType = wrapper.chain.chainType; DSCoinControl *cc = [[DSCoinControl alloc] initWithFFICoinControl:coinControl chainType:wrapper.chain.chainType]; NSArray *coins = [wrapper.manager availableCoins:walletEx onlySafe:onlySafe coinControl:cc minimumAmount:1 maximumAmount:MAX_MONEY minimumSumAmount:MAX_MONEY maximumCount:0]; - + gatheredOutputs = malloc(sizeof(GatheredOutputs)); InputCoin **coinsArray = malloc(coins.count * sizeof(InputCoin *)); - + for (uintptr_t i = 0; i < coins.count; ++i) { coinsArray[i] = [coins[i] ffi_malloc:chainType]; } - + gatheredOutputs->items = coinsArray; gatheredOutputs->item_count = (uintptr_t)coins.count; } - + return gatheredOutputs; } SelectedCoins* selectCoinsGroupedByAddresses(bool skipDenominated, bool anonymizable, bool skipUnconfirmed, int maxOupointsPerAddress, WalletEx* walletEx, const void *context) { SelectedCoins *vecTallyRet; - + @synchronized (context) { DSCoinJoinWrapper *wrapper = AS_OBJC(context); NSArray *tempVecTallyRet = [wrapper.manager selectCoinsGroupedByAddresses:walletEx skipDenominated:skipDenominated anonymizable:anonymizable skipUnconfirmed:skipUnconfirmed maxOupointsPerAddress:maxOupointsPerAddress]; - + vecTallyRet = malloc(sizeof(SelectedCoins)); vecTallyRet->item_count = tempVecTallyRet.count; vecTallyRet->items = malloc(tempVecTallyRet.count * sizeof(CompactTallyItem *)); - + for (uint32_t i = 0; i < tempVecTallyRet.count; i++) { vecTallyRet->items[i] = [tempVecTallyRet[i] ffi_malloc:wrapper.chain.chainType]; } } - + return vecTallyRet; } @@ -405,15 +406,15 @@ void destroySelectedCoins(SelectedCoins *selectedCoins) { if (!selectedCoins) { return; } - + if (selectedCoins->items) { for (int i = 0; i < selectedCoins->item_count; i++) { [DSCompactTallyItem ffi_free:selectedCoins->items[i]]; } - + free(selectedCoins->items); } - + free(selectedCoins); } @@ -421,15 +422,15 @@ void destroyGatheredOutputs(GatheredOutputs *gatheredOutputs) { if (!gatheredOutputs) { return; } - + if (gatheredOutputs->items) { for (int i = 0; i < gatheredOutputs->item_count; i++) { [DSInputCoin ffi_free:gatheredOutputs->items[i]]; } - + free(gatheredOutputs->items); } - + free(gatheredOutputs); } @@ -438,12 +439,12 @@ void destroyGatheredOutputs(GatheredOutputs *gatheredOutputs) { DSCoinJoinWrapper *wrapper = AS_OBJC(context); DSTransaction *tx = [[DSTransaction alloc] initWithTransaction:transaction onChain:wrapper.chain]; BOOL isSigned = [wrapper.chain.wallets.firstObject.accounts.firstObject signTransaction:tx anyoneCanPay:anyoneCanPay]; - + if (isSigned) { return [tx ffi_malloc:wrapper.chain.chainType]; } } - + return nil; } @@ -457,7 +458,7 @@ ByteArray freshCoinJoinAddress(bool internal, const void *context) { @synchronized (context) { DSCoinJoinWrapper *wrapper = AS_OBJC(context); NSString *address = [wrapper.manager freshAddress:internal]; - + return script_pubkey_for_address([address UTF8String], wrapper.chain.chainType); } } @@ -465,60 +466,60 @@ ByteArray freshCoinJoinAddress(bool internal, const void *context) { bool commitTransaction(struct Recipient **items, uintptr_t item_count, CoinControl *coinControl, bool is_denominating, uint8_t (*client_session_id)[32], const void *context) { NSMutableArray *amounts = [NSMutableArray array]; NSMutableArray *scripts = [NSMutableArray array]; - + for (uintptr_t i = 0; i < item_count; i++) { Recipient *recipient = items[i]; [amounts addObject:@(recipient->amount)]; NSData *script = [NSData dataWithBytes:recipient->script_pub_key.ptr length:recipient->script_pub_key.len]; [scripts addObject:script]; } - + bool result = false; - + @synchronized (context) { DSCoinJoinWrapper *wrapper = AS_OBJC(context); DSCoinControl *cc = [[DSCoinControl alloc] initWithFFICoinControl:coinControl chainType:wrapper.chain.chainType]; result = [wrapper.manager commitTransactionForAmounts:amounts outputs:scripts coinControl:cc onPublished:^(UInt256 txId, NSError * _Nullable error) { @synchronized (context) { if (error) { - DSLog(@"[%@] CoinJoin: commit tx error: %@, tx type: %@", wrapper.chain.name, error, is_denominating ? @"denominations" : @"collateral"); + DSLogInfo(@"DSCoinJoinWrapper", @"[%@] CoinJoin: commit tx error: %@, tx type: %@", wrapper.chain.name, error, is_denominating ? @"denominations" : @"collateral"); } else if (is_denominating) { #if DEBUG - DSLog(@"[%@] CoinJoin tx: Denominations Created: %@", wrapper.chain.name, uint256_reverse_hex(txId)); + DSLogInfo(@"DSCoinJoinWrapper", @"[%@] CoinJoin tx: Denominations Created: %@", wrapper.chain.name, uint256_reverse_hex(txId)); #else - DSLog(@"[%@] CoinJoin tx: Denominations Created: %@", wrapper.chain.name, @""); + DSLogInfo(@"DSCoinJoinWrapper", @"[%@] CoinJoin tx: Denominations Created: %@", wrapper.chain.name, @""); #endif bool isFinished = finish_automatic_denominating(wrapper.clientManager, client_session_id); - + if (!isFinished) { - DSLog(@"[%@] CoinJoin: auto_denom not finished", wrapper.chain.name); + DSLogInfo(@"DSCoinJoinWrapper", @"[%@] CoinJoin: auto_denom not finished", wrapper.chain.name); } - + processor_destroy_block_hash(client_session_id); [wrapper.manager onTransactionProcessed:txId type:CoinJoinTransactionType_CreateDenomination]; } else { #if DEBUG - DSLog(@"[%@] CoinJoin tx: Collateral Created: %@", wrapper.chain.name, uint256_reverse_hex(txId)); + DSLogInfo(@"DSCoinJoinWrapper", @"[%@] CoinJoin tx: Collateral Created: %@", wrapper.chain.name, uint256_reverse_hex(txId)); #else - DSLog(@"[%@] CoinJoin tx: Collateral Created: %@", wrapper.chain.name, @""); + DSLogInfo(@"DSCoinJoinWrapper", @"[%@] CoinJoin tx: Collateral Created: %@", wrapper.chain.name, @""); #endif [wrapper.manager onTransactionProcessed:txId type:CoinJoinTransactionType_MakeCollateralInputs]; } } }]; } - + return result; } MasternodeEntry* masternodeByHash(uint8_t (*hash)[32], const void *context) { UInt256 mnHash = *((UInt256 *)hash); MasternodeEntry *masternode; - + @synchronized (context) { masternode = [[AS_OBJC(context).manager masternodeEntryByHash:mnHash] ffi_malloc]; } - + return masternode; } @@ -526,7 +527,7 @@ void destroyMasternodeEntry(MasternodeEntry *masternodeEntry) { if (!masternodeEntry) { return; } - + [DSSimplifiedMasternodeEntry ffi_free:masternodeEntry]; } @@ -548,7 +549,7 @@ void destroyMNList(MasternodeList *masternodeList) { // TODO: check destroyMaste if (!masternodeList) { return; } - + [DSMasternodeList ffi_free:masternodeList]; } @@ -560,7 +561,7 @@ bool isBlockchainSynced(const void *context) { bool isMasternodeOrDisconnectRequested(uint8_t (*ip_address)[16], uint16_t port, const void *context) { UInt128 ipAddress = *((UInt128 *)ip_address); - + @synchronized (context) { return [AS_OBJC(context).manager isMasternodeOrDisconnectRequested:ipAddress port:port]; } @@ -568,7 +569,7 @@ bool isMasternodeOrDisconnectRequested(uint8_t (*ip_address)[16], uint16_t port, bool disconnectMasternode(uint8_t (*ip_address)[16], uint16_t port, const void *context) { UInt128 ipAddress = *((UInt128 *)ip_address); - + @synchronized (context) { return [AS_OBJC(context).manager disconnectMasternode:ipAddress port:port]; } @@ -577,7 +578,7 @@ bool disconnectMasternode(uint8_t (*ip_address)[16], uint16_t port, const void * bool sendMessage(char *message_type, ByteArray *byteArray, uint8_t (*ip_address)[16], uint16_t port, bool warn, const void *context) { NSString *messageType = [NSString stringWithUTF8String:message_type]; UInt128 ipAddress = *((UInt128 *)ip_address); - + @synchronized (context) { NSData *message = [NSData dataWithBytes:byteArray->ptr length:byteArray->len]; return [AS_OBJC(context).manager sendMessageOfType:messageType message:message withPeerIP:ipAddress port:port warn:warn]; @@ -587,7 +588,7 @@ bool sendMessage(char *message_type, ByteArray *byteArray, uint8_t (*ip_address) bool addPendingMasternode(uint8_t (*pro_tx_hash)[32], uint8_t (*session_id)[32], const void *context) { UInt256 sessionId = *((UInt256 *)session_id); UInt256 proTxHash = *((UInt256 *)pro_tx_hash); - + @synchronized (context) { return [AS_OBJC(context).manager addPendingMasternode:proTxHash clientSessionId:sessionId]; } @@ -624,7 +625,7 @@ void sessionLifecycleListener(bool is_complete, @synchronized (context) { UInt256 clientSessionId = *((UInt256 *)client_session_id); UInt128 ipAddress = *((UInt128 *)ip_address); - + if (is_complete) { [AS_OBJC(context).manager onSessionComplete:base_session_id clientSessionId:clientSessionId denomination:denomination poolState:state poolMessage:message poolStatus:status ipAddress:ipAddress isJoined:joined]; } else { @@ -657,25 +658,26 @@ void mixingLifecycleListener(bool is_complete, @synchronized (context) { DSCoinJoinWrapper *wrapper = AS_OBJC(context); NSArray *addresses; - + if (used) { - addresses = [wrapper.manager getIssuedReceiveAddresses]; - } else { addresses = [wrapper.manager getUsedReceiveAddresses]; + } else { + addresses = [wrapper.manager getIssuedReceiveAddresses]; } - + CoinJoinKeys *keys = malloc(sizeof(CoinJoinKeys)); keys->item_count = addresses.count; keys->items = malloc(sizeof(ByteArray *) * keys->item_count); - + for (NSUInteger i = 0; i < addresses.count; i++) { NSString *address = addresses[i]; + ByteArray scriptPubKey = script_pubkey_for_address([address UTF8String], wrapper.chain.chainType); ByteArray *byteArray = malloc(sizeof(ByteArray)); - byteArray->ptr = script_pubkey_for_address([address UTF8String], wrapper.chain.chainType).ptr; - byteArray->len = script_pubkey_for_address([address UTF8String], wrapper.chain.chainType).len; + byteArray->ptr = scriptPubKey.ptr; + byteArray->len = scriptPubKey.len; keys->items[i] = byteArray; } - + return keys; } } @@ -684,14 +686,14 @@ void destroyCoinJoinKeys(struct CoinJoinKeys *coinjoin_keys) { if (coinjoin_keys == NULL) { return; } - + for (uintptr_t i = 0; i < coinjoin_keys->item_count; i++) { if (coinjoin_keys->items[i] != NULL) { free(coinjoin_keys->items[i]->ptr); free(coinjoin_keys->items[i]); } } - + free(coinjoin_keys->items); free(coinjoin_keys); } diff --git a/DashSync/shared/Models/CoinJoin/Utils/DSMasternodeGroup.m b/DashSync/shared/Models/CoinJoin/Utils/DSMasternodeGroup.m index b169c49f3..7c9d76755 100644 --- a/DashSync/shared/Models/CoinJoin/Utils/DSMasternodeGroup.m +++ b/DashSync/shared/Models/CoinJoin/Utils/DSMasternodeGroup.m @@ -19,6 +19,7 @@ #import "DSChainManager.h" #import "DSChain+Protected.h" #import "DSCoinJoinManager.h" +#import "DSLogger.h" #import "DSSimplifiedMasternodeEntry.h" #import "DSMasternodeManager.h" #import "DSPeerManager.h" @@ -116,15 +117,15 @@ - (BOOL)isMasternodeOrDisconnectRequested:(UInt128)ip port:(uint16_t)port { - (BOOL)disconnectMasternode:(UInt128)ip port:(uint16_t)port { return [self forPeer:ip port:port warn:YES withPredicate:^BOOL(DSPeer *peer) { - DSLog(@"[%@] CoinJoin: masternode[closing] %@", self.chain.name, [self hostFor:ip]); - + DSLogInfo(@"DSMasternodeGroup", @"[%@] CoinJoin: masternode[closing] %@", self.chain.name, [self hostFor:ip]); + @synchronized (self.mutablePendingClosingMasternodes) { [self.mutablePendingClosingMasternodes addObject:peer]; } - + [self updateMaxConnections]; [peer disconnect]; - + return true; }]; } @@ -143,13 +144,13 @@ - (BOOL)forPeer:(UInt128)ip port:(uint16_t)port warn:(BOOL)warn withPredicate:(B if (warn) { if (![self isNodePending:ip port:port]) { - DSLog(@"[%@] CoinJoin: Cannot find %@ in the list of connected peers: %@", self.chain.name, [self hostFor:ip], listOfPeers); + DSLogInfo(@"DSMasternodeGroup", @"[%@] CoinJoin: Cannot find %@ in the list of connected peers: %@", self.chain.name, [self hostFor:ip], listOfPeers); NSAssert(NO, @"Cannot find %@", [self hostFor:ip]); } else { - DSLog(@"[%@] CoinJoin: %@ in the list of pending peers", self.chain.name, [self hostFor:ip]); + DSLogInfo(@"DSMasternodeGroup", @"[%@] CoinJoin: %@ in the list of pending peers", self.chain.name, [self hostFor:ip]); } } - + return NO; } @@ -217,11 +218,11 @@ - (void)triggerConnectionsJobWithDelay:(NSTimeInterval)delay { NSTimeInterval delay = [retryTime timeIntervalSinceDate:now]; if (delay > 0.1) { - DSLog(@"[%@] CoinJoin: Waiting %fl s before next connect attempt to masternode to %@", self.chain.name, delay, peerToTry == NULL ? @"" : peerToTry.location); + DSLogInfo(@"DSMasternodeGroup", @"[%@] CoinJoin: Waiting %f s before next connect attempt to masternode to %@", self.chain.name, delay, peerToTry == NULL ? @"" : peerToTry.location); [self triggerConnectionsJobWithDelay:delay]; return; } - + [self connectTo:peerToTry]; } @@ -283,7 +284,7 @@ - (DSPeer *)getNextPendingMasternode { if (peerWithLeastBackoff) { @synchronized(self.addressMap) { [self.addressMap setObject:sessionValueWithLeastBackoff forKey:peerWithLeastBackoff.location]; - DSLog(@"[%@] CoinJoin: discovery: %@ -> %@", self.chain.name, peerWithLeastBackoff.location, uint256_hex(sessionId)); + DSLogInfo(@"DSMasternodeGroup", @"[%@] CoinJoin: discovery: %@ -> %@", self.chain.name, peerWithLeastBackoff.location, uint256_hex(sessionId)); } } @@ -306,26 +307,26 @@ - (DSSimplifiedMasternodeEntry *)mixingMasternodeAddressFor:(UInt256)sessionId { - (BOOL)addPendingMasternode:(UInt256)proTxHash clientSessionId:(UInt256)sessionId { @synchronized (self.mutablePendingSessions) { - DSLog(@"[%@] CoinJoin: adding masternode for mixing. maxConnections = %lu, protx: %@, sessionId: %@", self.chain.name, (unsigned long)_maxConnections, uint256_hex(proTxHash), uint256_hex(sessionId)); + DSLogInfo(@"DSMasternodeGroup", @"[%@] CoinJoin: adding masternode for mixing. maxConnections = %lu, protx: %@, sessionId: %@", self.chain.name, (unsigned long)_maxConnections, uint256_hex(proTxHash), uint256_hex(sessionId)); NSValue *sessionIdValue = [NSValue valueWithBytes:&sessionId objCType:@encode(UInt256)]; [self.mutablePendingSessions addObject:sessionIdValue]; - + NSValue *proTxHashKey = [NSValue value:&proTxHash withObjCType:@encode(UInt256)]; [self.masternodeMap setObject:sessionIdValue forKey:proTxHashKey]; [self.sessionMap setObject:proTxHashKey forKey:sessionIdValue]; } - + [self checkMasternodesWithoutSessions]; [self updateMaxConnections]; - + return true; } - (void)updateMaxConnections { _maxConnections = self.mutablePendingSessions.count; NSUInteger connections = MIN(self.maxConnections, self.coinJoinManager.options->coinjoin_sessions); - DSLog(@"[%@] CoinJoin: updating max connections to min(%lu, %lu)", self.chain.name, (unsigned long)_maxConnections, (unsigned long)self.coinJoinManager.options->coinjoin_sessions); - + DSLogInfo(@"DSMasternodeGroup", @"[%@] CoinJoin: updating max connections to min(%lu, %lu)", self.chain.name, (unsigned long)_maxConnections, (unsigned long)self.coinJoinManager.options->coinjoin_sessions); + [self updateMaxConnections:connections]; } @@ -344,9 +345,9 @@ - (void)updateMaxConnections:(NSUInteger)connections { NSUInteger connectedCount = self.mutableConnectedPeers.count; NSUInteger numPeers = pendingCount + connectedCount; adjustment = self.maxConnections - numPeers; - DSLogPrivate(@"CoinJoin: updateMaxConnections adjustment %lu, pendingCount: %lu, connectedCount: %lu", adjustment, pendingCount, connectedCount); + DSLogInfo(@"DSMasternodeGroup", @"[%@] CoinJoin: updateMaxConnections adjustment %ld, pendingCount: %lu, connectedCount: %lu", self.chain.name, (long)adjustment, (unsigned long)pendingCount, (unsigned long)connectedCount); } - + if (adjustment > 0) { [self triggerConnections]; } @@ -367,32 +368,32 @@ - (void)checkMasternodesWithoutSessions { if (mixingMasternodeAddress) { UInt128 ipAddress = mixingMasternodeAddress.address; uint16_t port = mixingMasternodeAddress.port; - + if (uint128_eq(ipAddress, peer.address) && port == peer.port) { found = YES; } } else { // TODO(DashJ): we may not need this anymore - DSLog(@"[%@] CoinJoin: session is not connected to a masternode: %@", self.chain.name, uint256_hex(sessionId)); + DSLogInfo(@"DSMasternodeGroup", @"[%@] CoinJoin: session is not connected to a masternode: %@", self.chain.name, uint256_hex(sessionId)); } } - + if (!found) { - DSLog(@"[%@] CoinJoin: masternode is not connected to a session: %@", self.chain.name, peer.location); + DSLogInfo(@"DSMasternodeGroup", @"[%@] CoinJoin: masternode is not connected to a session: %@", self.chain.name, peer.location); [masternodesToDrop addObject:peer]; } } - - DSLogPrivate(@"CoinJoin: need to drop %lu masternodes", (unsigned long)masternodesToDrop.count); - + + DSLogInfo(@"DSMasternodeGroup", @"[%@] CoinJoin: need to drop %lu masternodes", self.chain.name, (unsigned long)masternodesToDrop.count); + for (DSPeer *peer in masternodesToDrop) { DSSimplifiedMasternodeEntry *mn = [self.chain.chainManager.masternodeManager masternodeAtLocation:peer.address port:peer.port]; - DSLog(@"[%@] CoinJoin: masternode will be disconnected: %@: %@", self.chain.name, peer.location, uint256_hex(mn.providerRegistrationTransactionHash)); - + DSLogInfo(@"DSMasternodeGroup", @"[%@] CoinJoin: masternode will be disconnected: %@: %@", self.chain.name, peer.location, uint256_hex(mn.providerRegistrationTransactionHash)); + @synchronized (self.mutablePendingClosingMasternodes) { [self.mutablePendingClosingMasternodes addObject:peer]; } - + [peer disconnect]; } } @@ -407,45 +408,45 @@ - (NSString *)hostFor:(UInt128)address { } - (BOOL)connectTo:(DSPeer *)peer { - DSLogPrivate(@"[%@] CoinJoin: connectTo: %@", self.chain.name, peer.location); - + DSLogInfo(@"DSMasternodeGroup", @"[%@] CoinJoin: connectTo: %@", self.chain.name, peer.location); + if (![self isMasternodeSessionByPeer:peer]) { - DSLog(@"[%@] CoinJoin: %@ not a masternode session, exit", self.chain.name, peer.location); + DSLogInfo(@"DSMasternodeGroup", @"[%@] CoinJoin: %@ not a masternode session, exit", self.chain.name, peer.location); return NO; } - + if ([self isNodeConnected:peer] || [self isNodePending:peer]) { - DSLog(@"[%@] CoinJoin: attempting to connect to the same masternode again: %@", self.chain.name, peer.location); + DSLogInfo(@"DSMasternodeGroup", @"[%@] CoinJoin: attempting to connect to the same masternode again: %@", self.chain.name, peer.location); return NO; // do not connect to the same peer again } - + DSSimplifiedMasternodeEntry *mn = [_chain.chainManager.masternodeManager masternodeAtLocation:peer.address port:peer.port]; UInt256 sessionId = UINT256_ZERO; - + @synchronized (self.masternodeMap) { UInt256 proTxHash = mn.providerRegistrationTransactionHash; NSValue *proTxHashKey = [NSValue value:&proTxHash withObjCType:@encode(UInt256)]; NSValue *sessionObject = [self.masternodeMap objectForKey:proTxHashKey]; - + if (sessionObject) { [sessionObject getValue:&sessionId]; } } - + if (uint256_is_zero(sessionId)) { - DSLog(@"[%@] CoinJoin: session is not connected to a masternode, proTxHashKey not found in masternodeMap", self.chain.name); + DSLogInfo(@"DSMasternodeGroup", @"[%@] CoinJoin: session is not connected to a masternode, proTxHashKey not found in masternodeMap", self.chain.name); return NO; } - + DSSimplifiedMasternodeEntry *mixingMasternodeAddress = [self mixingMasternodeAddressFor:sessionId]; - + if (!mixingMasternodeAddress) { - DSLog(@"[%@] CoinJoin: session is not connected to a masternode, sessionId: %@", self.chain.name, uint256_hex(sessionId)); + DSLogInfo(@"DSMasternodeGroup", @"[%@] CoinJoin: session is not connected to a masternode, sessionId: %@", self.chain.name, uint256_hex(sessionId)); return NO; } - - DSLog(@"[%@] CoinJoin: masternode[connecting] %@: %@; %@", self.chain.name, peer.location, uint256_hex(mn.providerRegistrationTransactionHash), uint256_hex(sessionId)); - + + DSLogInfo(@"DSMasternodeGroup", @"[%@] CoinJoin: masternode[connecting] %@: %@; %@", self.chain.name, peer.location, uint256_hex(mn.providerRegistrationTransactionHash), 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 queue:self.networkingQueue]; peer.earliestKeyTime = self.chain.earliestWalletCreationTime;; @@ -484,13 +485,13 @@ - (void)peerConnected:(nonnull DSPeer *)peer { @synchronized (self.peersLock) { [self.groupBackoff trackSuccess]; [[self.backoffMap objectForKey:peer.location] trackSuccess]; - - DSLog(@"[%@] CoinJoin: New peer %@ ({%lu connected, %lu pending, %lu max)", self.chain.name, peer.location, self.mutableConnectedPeers.count, self.mutablePendingPeers.count, self.maxConnections); - + + DSLogInfo(@"DSMasternodeGroup", @"[%@] CoinJoin: New peer %@ (%lu connected, %lu pending, %lu max)", self.chain.name, peer.location, (unsigned long)self.mutableConnectedPeers.count, (unsigned long)self.mutablePendingPeers.count, (unsigned long)self.maxConnections); + [self.mutablePendingPeers removeObject:peer]; [self.mutableConnectedPeers addObject:peer]; } - + if (self.shouldSendDsq) { [peer sendRequest:[DSSendCoinJoinQueue requestWithShouldSend:true]]; } @@ -513,15 +514,15 @@ - (void)peer:(nonnull DSPeer *)peer disconnectedWithError:(nonnull NSError *)err DSPeer *masternode = NULL; NSArray *pendingClosingMasternodes = self.pendingClosingMasternodes; - + for (DSPeer *mn in pendingClosingMasternodes) { if ([peer.location isEqualToString:mn.location]) { masternode = mn; } } - - DSLog(@"[%@] CoinJoin: handling this mn peer death: %@ -> %@", self.chain.name, peer.location, masternode != NULL ? masternode.location : @"not found in closing list"); - + + DSLogInfo(@"DSMasternodeGroup", @"[%@] CoinJoin: handling this mn peer death: %@ -> %@", self.chain.name, peer.location, masternode != NULL ? masternode.location : @"not found in closing list"); + if (masternode) { NSString *address = peer.location; @@ -576,7 +577,7 @@ - (DSPeer *)peerForLocation:(UInt128)ipAddress port:(uint16_t)port { - (void)handleSyncStateDidChangeNotification:(NSNotification *)note { if ([note.userInfo[DSChainManagerNotificationChainKey] isEqual:[self chain]] && self.chain.lastSyncBlock.height > self.lastSeenBlock) { self.lastSeenBlock = self.chain.lastSyncBlock.height; - DSLogPrivate(@"[%@] CoinJoin: new block found, restarting masternode connections job", self.chain.name); + DSLogInfo(@"DSMasternodeGroup", @"[%@] CoinJoin: new block found, restarting masternode connections job", self.chain.name); [self triggerConnections]; } } diff --git a/DashSync/shared/Models/DAPI/DSPlatformDocumentsRequest.m b/DashSync/shared/Models/DAPI/DSPlatformDocumentsRequest.m index 1fde02804..5c893f038 100644 --- a/DashSync/shared/Models/DAPI/DSPlatformDocumentsRequest.m +++ b/DashSync/shared/Models/DAPI/DSPlatformDocumentsRequest.m @@ -230,7 +230,6 @@ - (GetDocumentsRequest *)getDocumentsRequest { } getDocumentsRequest.limit = self.limit; getDocumentsRequest.prove = self.prove; - DSLog(@"Sending request to Contract %@", getDocumentsRequest.dataContractId.base58String); return getDocumentsRequest; } diff --git a/DashSync/shared/Models/DAPI/NSPredicate+CBORData.m b/DashSync/shared/Models/DAPI/NSPredicate+CBORData.m index c39c8f25e..9fb7a1429 100644 --- a/DashSync/shared/Models/DAPI/NSPredicate+CBORData.m +++ b/DashSync/shared/Models/DAPI/NSPredicate+CBORData.m @@ -236,10 +236,6 @@ - (DSPlatformTreeQuery *)platformTreeQuery { } - (NSData *)dashPlatormWhereData { - NSArray *array = [self whereClauseArrayWithOptions:NSPredicateCBORDataOptions_DataToBase64]; - NSData *json = [NSJSONSerialization dataWithJSONObject:array options:0 error:nil]; - DSLogPrivate(@"json where %@", [[NSString alloc] initWithData:json encoding:NSUTF8StringEncoding]); - DSLogPrivate(@"cbor hex %@", [[self whereClauseArray] ds_cborEncodedObject].hexString); return [[self whereClauseArray] ds_cborEncodedObject]; } diff --git a/DashSync/shared/Models/DAPI/Networking/DSDAPIGRPCResponseHandler.m b/DashSync/shared/Models/DAPI/Networking/DSDAPIGRPCResponseHandler.m index 2bc9ef4d9..1f3e1d6be 100644 --- a/DashSync/shared/Models/DAPI/Networking/DSDAPIGRPCResponseHandler.m +++ b/DashSync/shared/Models/DAPI/Networking/DSDAPIGRPCResponseHandler.m @@ -189,10 +189,6 @@ - (void)parseDocumentsMessage:(GetDocumentsResponse *)documentsResponse { [mArray addObject:document]; } if (error) { - DSLog(@"Decoding error for parseDocumentsMessage cborData %@", cborData); - if (self.request) { - DSLog(@"request was %@", self.request.predicate); - } break; } } @@ -225,7 +221,6 @@ - (void)parseDataContractMessage:(GetDataContractResponse *)dataContractResponse } self.responseObject = [dataContractData ds_decodeCborError:&error]; if (error) { - DSLog(@"Decoding error for parseDataContractMessage cborData %@", dataContractData); self.decodingError = error; } } @@ -273,10 +268,6 @@ - (void)parseWaitForStateTransitionResultMessage:(WaitForStateTransitionResultRe [mArray addObject:document]; } if (error) { - DSLog(@"Decoding error for parseDocumentsMessage cborData %@", cborData); - if (self.request) { - DSLog(@"request was %@", self.request.predicate); - } break; } } @@ -388,7 +379,6 @@ - (void)parseGetIdentityIdsByPublicKeyHashesMessage:(GetIdentityIdsByPublicKeyHa } - (void)didReceiveInitialMetadata:(nullable NSDictionary *)initialMetadata { - DSLog(@"didReceiveInitialMetadata"); } - (void)didReceiveProtoMessage:(nullable GPBMessage *)message { @@ -414,7 +404,6 @@ - (void)didReceiveProtoMessage:(nullable GPBMessage *)message { self.decodingError = error; } } - DSLog(@"didReceiveProtoMessage"); } - (void)didCloseWithTrailingMetadata:(nullable NSDictionary *)trailingMetadata @@ -429,11 +418,6 @@ - (void)didCloseWithTrailingMetadata:(nullable NSDictionary *)trailingMetadata self.errorHandler(error); }); } - DSLog(@"error in didCloseWithTrailingMetadata from IP %@ %@", self.host ? self.host : @"Unknown", error); - if (self.request) { - DSLog(@"request contract ID was %@", self.request.contract.base58ContractId); - } - } else { if (self.successHandler) { dispatch_async(self.completionQueue, ^{ @@ -441,11 +425,9 @@ - (void)didCloseWithTrailingMetadata:(nullable NSDictionary *)trailingMetadata }); } } - DSLog(@"didCloseWithTrailingMetadata"); } - (void)didWriteMessage { - DSLog(@"didWriteMessage"); } - (NSDictionary *)verifyAndExtractFromProof:(Proof *)proof withMetadata:(ResponseMetadata *)metaData error:(NSError **)error { @@ -466,9 +448,6 @@ + (NSDictionary *)verifyAndExtractFromProof:(Proof *)proof withMetadata:(Respons return [self verifyAndExtractFromProof:proof withMetadata:metaData query:query forQuorumEntry:quorumEntry quorumType:quorum_type_for_platform(chain.chainType) error:error]; } else if (quorumEntry) { *error = [NSError errorWithCode:400 descriptionKey:DSLocalizedString(@"Quorum entry %@ found but is not yet verified", uint256_hex(quorumEntry.quorumHash))]; - DSLog(@"quorum entry %@ found but is not yet verified", uint256_hex(quorumEntry.quorumHash)); - } else { - DSLog(@"no quorum entry found for quorum hash %@", uint256_hex(quorumHash)); } return nil; } diff --git a/DashSync/shared/Models/DAPI/Networking/DSDAPIPlatformNetworkService.m b/DashSync/shared/Models/DAPI/Networking/DSDAPIPlatformNetworkService.m index eb061c47b..55850ae7d 100644 --- a/DashSync/shared/Models/DAPI/Networking/DSDAPIPlatformNetworkService.m +++ b/DashSync/shared/Models/DAPI/Networking/DSDAPIPlatformNetworkService.m @@ -669,7 +669,6 @@ - (void)loadBloomFilter:(NSString *)filter failure:(void (^)(NSError *error))failure { NSParameterAssert(stateTransition); NSParameterAssert(completionQueue); - DSLogPrivate(@"Broadcasting state transition to ip %@ with data %@ rawData %@", self.ipAddress, stateTransition.keyValueDictionary, stateTransition.data.hexString); WaitForStateTransitionResultRequest *waitForStateTransitionResultRequest = [[WaitForStateTransitionResultRequest alloc] init]; waitForStateTransitionResultRequest.prove = DSPROVE_PUSH_PLATFORM; diff --git a/DashSync/shared/Models/Derivation Paths/DSAuthenticationKeysDerivationPath.m b/DashSync/shared/Models/Derivation Paths/DSAuthenticationKeysDerivationPath.m index 55b753183..15440a538 100644 --- a/DashSync/shared/Models/Derivation Paths/DSAuthenticationKeysDerivationPath.m +++ b/DashSync/shared/Models/Derivation Paths/DSAuthenticationKeysDerivationPath.m @@ -125,11 +125,6 @@ - (void)loadAddresses { while (e.index >= self.mOrderedAddresses.count) [self.mOrderedAddresses addObject:[NSNull null]]; if (![DSKeyManager isValidDashAddress:e.address forChain:self.wallet.chain]) { -#if DEBUG - DSLogPrivate(@"[%@] address %@ loaded but was not valid on chain", self.wallet.chain.name, e.address); -#else - DSLog(@"[%@] address %@ loaded but was not valid on chain", self.wallet.chain.name, @""); -#endif continue; } self.mOrderedAddresses[e.index] = e.address; @@ -199,7 +194,6 @@ - (NSArray *)registerAddressesWithGapLimit:(NSUInteger)gapLimit forIdentityIndex NSString *addr = [DSKeyManager NSStringFrom:key_address_with_public_key_data(pubKey.bytes, pubKey.length, self.chain.chainType)]; if (!addr) { - DSLog(@"[%@] error generating keys", self.chain.name); if (error) { *error = [NSError errorWithCode:500 localizedDescriptionKey:@"Error generating public keys"]; } diff --git a/DashSync/shared/Models/Derivation Paths/DSDerivationPath.m b/DashSync/shared/Models/Derivation Paths/DSDerivationPath.m index d3a6caae8..5dd56fc0b 100644 --- a/DashSync/shared/Models/Derivation Paths/DSDerivationPath.m +++ b/DashSync/shared/Models/Derivation Paths/DSDerivationPath.m @@ -280,26 +280,6 @@ - (OpaqueKey *)extendedPublicKey { } } else { NSData *extendedPublicKeyData = getKeychainData([self standaloneExtendedPublicKeyLocationString], nil); -#ifdef DEBUG - if (!extendedPublicKeyData) { - if ([self isKindOfClass:[DSIncomingFundsDerivationPath class]]) { - DSFriendRequestEntity *friendRequest = [DSFriendRequestEntity anyObjectInContext:self.managedObjectContext matching:@"derivationPath.publicKeyIdentifier == %@", self.standaloneExtendedPublicKeyUniqueID]; - - NSAssert(friendRequest, @"friend request must exist"); - - DSBlockchainIdentityUsernameEntity *sourceUsernameEntity = [friendRequest.sourceContact.associatedBlockchainIdentity.usernames anyObject]; - DSBlockchainIdentityUsernameEntity *destinationUsernameEntity = [friendRequest.destinationContact.associatedBlockchainIdentity.usernames anyObject]; -#if DEBUG - DSLogPrivate(@"[%@] No extended public key set for the relationship between %@ and %@ (%@ receiving payments) ", self.chain.name, sourceUsernameEntity.stringValue, destinationUsernameEntity.stringValue, sourceUsernameEntity.stringValue); -#else - DSLog(@"[%@] No extended public key set for the relationship between %@ and %@ (%@ receiving payments) ", self.chain.name, - @"", - @"", - @""); -#endif /* DEBUG */ - } - } -#endif _extendedPublicKey = key_create_from_extended_public_key_data(extendedPublicKeyData.bytes, extendedPublicKeyData.length, (int16_t) self.signingAlgorithm); [self maybeRevertBLSMigration:extendedPublicKeyData]; } diff --git a/DashSync/shared/Models/Derivation Paths/DSFundsDerivationPath.m b/DashSync/shared/Models/Derivation Paths/DSFundsDerivationPath.m index c3960a44c..6dfb295d2 100644 --- a/DashSync/shared/Models/Derivation Paths/DSFundsDerivationPath.m +++ b/DashSync/shared/Models/Derivation Paths/DSFundsDerivationPath.m @@ -97,11 +97,6 @@ - (void)loadAddresses { while (e.index >= a.count) [a addObject:[NSNull null]]; if (![DSKeyManager isValidDashAddress:e.address forChain:self.account.wallet.chain]) { -#if DEBUG - DSLogPrivate(@"[%@] address %@ loaded but was not valid on chain", self.account.wallet.chain.name, e.address); -#else - DSLog(@"[%@] address %@ loaded but was not valid on chain %@", self.account.wallet.chain.name, @""); -#endif /* DEBUG */ continue; } a[e.index] = e.address; @@ -186,12 +181,20 @@ - (NSArray *)registerAddressesWithGapLimit:(NSUInteger)gapLimit internal:(BOOL)i NSMutableDictionary *addAddresses = [NSMutableDictionary dictionary]; + // keysNeeded is always > 0 here since we return early if a.count >= gapLimit + NSUInteger keysNeeded = gapLimit - a.count; + NSTimeInterval keyGenStart = [[NSDate date] timeIntervalSince1970]; + NSUInteger numChildren = [(internal) ? self.internalAddresses : self.externalAddresses count]; + DSLogInfo(@"DSFundsDerivationPath", @"%lu keys needed for %@ = %lu issued + %lu lookahead size + %lu lookahead threshold - %lu num children", + (unsigned long)keysNeeded, self.stringRepresentation, + (unsigned long)(n - keysNeeded), (unsigned long)gapLimit, (unsigned long)0, + (unsigned long)numChildren); + while (a.count < gapLimit) { // generate new addresses up to gapLimit NSData *pubKey = [self publicKeyDataAtIndex:n internal:internal]; NSString *addr = [DSKeyManager ecdsaKeyAddressFromPublicKeyData:pubKey forChainType:self.chain.chainType]; if (!addr) { - DSLog(@"[%@] error generating keys", self.account.wallet.chain.name); if (error) { *error = [NSError errorWithCode:500 localizedDescriptionKey:@"Error generating public keys"]; } @@ -205,6 +208,9 @@ - (NSArray *)registerAddressesWithGapLimit:(NSUInteger)gapLimit internal:(BOOL)i n++; } + NSTimeInterval keyGenTime = ([[NSDate date] timeIntervalSince1970] - keyGenStart) * 1000.0; + DSLogInfo(@"DSFundsDerivationPath", @"Took %.2f ms", keyGenTime); + if (!self.account.wallet.isTransient) { [self.managedObjectContext performBlock:^{ // store new address in core data DSDerivationPathEntity *derivationPathEntity = [DSDerivationPathEntity derivationPathEntityMatchingDerivationPath:self inContext:self.managedObjectContext]; diff --git a/DashSync/shared/Models/Derivation Paths/DSIncomingFundsDerivationPath.m b/DashSync/shared/Models/Derivation Paths/DSIncomingFundsDerivationPath.m index 7bbc16d2f..5b411079b 100644 --- a/DashSync/shared/Models/Derivation Paths/DSIncomingFundsDerivationPath.m +++ b/DashSync/shared/Models/Derivation Paths/DSIncomingFundsDerivationPath.m @@ -111,11 +111,6 @@ - (void)loadAddressesInContext:(NSManagedObjectContext *)context { while (e.index >= a.count) [a addObject:[NSNull null]]; if (![DSKeyManager isValidDashAddress:e.address forChain:self.account.wallet.chain]) { -#if DEBUG - DSLogPrivate(@"[%@] address %@ loaded but was not valid on chain", self.account.wallet.chain.name, e.address); -#else - DSLog(@"[%@] address %@ loaded but was not valid on chain", self.account.wallet.chain.name, @""); -#endif /* DEBUG */ continue; } a[e.index] = e.address; @@ -212,7 +207,6 @@ - (NSArray *)registerAddressesWithGapLimit:(NSUInteger)gapLimit inContext:(NSMan while (a.count < upperLimit) { // generate new addresses up to gapLimit NSString *address = [self addressAtIndex:n]; if (!address) { - DSLog(@"[%@] error generating keys", self.chain.name); if (error) { *error = [NSError errorWithCode:500 localizedDescriptionKey:@"Error generating public keys"]; } diff --git a/DashSync/shared/Models/Derivation Paths/DSSimpleIndexedDerivationPath.m b/DashSync/shared/Models/Derivation Paths/DSSimpleIndexedDerivationPath.m index 41254a03c..c25648519 100644 --- a/DashSync/shared/Models/Derivation Paths/DSSimpleIndexedDerivationPath.m +++ b/DashSync/shared/Models/Derivation Paths/DSSimpleIndexedDerivationPath.m @@ -31,11 +31,6 @@ - (void)loadAddresses { @autoreleasepool { while (e.index >= self.mOrderedAddresses.count) [self.mOrderedAddresses addObject:[NSNull null]]; if (![DSKeyManager isValidDashAddress:e.address forChain:self.wallet.chain]) { -#if DEBUG - DSLogPrivate(@"[%@] address %@ loaded but was not valid on chain", self.account.wallet.chain.name, e.address); -#else - DSLog(@"[%@] address %@ loaded but was not valid on chain", self.account.wallet.chain.name, @""); -#endif /* DEBUG */ continue; } self.mOrderedAddresses[e.index] = e.address; @@ -121,7 +116,6 @@ - (NSArray *)registerAddressesWithGapLimit:(NSUInteger)gapLimit error:(NSError * NSData *pubKey = [self publicKeyDataAtIndex:n]; NSString *addr = [DSKeyManager addressWithPublicKeyData:pubKey forChain:self.chain]; if (!addr) { - DSLog(@"[%@] error generating keys", self.chain.name); if (error) { *error = [NSError errorWithCode:500 localizedDescriptionKey:@"Error generating public keys"]; } diff --git a/DashSync/shared/Models/Entities/DSChainEntity+CoreDataClass.m b/DashSync/shared/Models/Entities/DSChainEntity+CoreDataClass.m index d99f69eca..baa1cf42a 100644 --- a/DashSync/shared/Models/Entities/DSChainEntity+CoreDataClass.m +++ b/DashSync/shared/Models/Entities/DSChainEntity+CoreDataClass.m @@ -135,7 +135,6 @@ + (DSChainEntity *)chainEntityForType:(ChainType)type checkpoints:(NSArray *)che DSChainEntity *chainEntityToRemove = objects[i]; [context deleteObject:chainEntityToRemove]; [context ds_save]; - DSLog(@"Removing extra chain entity of type %d", type.tag); } } DSChainEntity *chainEntity = [objects objectAtIndex:0]; diff --git a/DashSync/shared/Models/Entities/DSMasternodeListEntity+CoreDataClass.m b/DashSync/shared/Models/Entities/DSMasternodeListEntity+CoreDataClass.m index c9dcadd50..948898778 100644 --- a/DashSync/shared/Models/Entities/DSMasternodeListEntity+CoreDataClass.m +++ b/DashSync/shared/Models/Entities/DSMasternodeListEntity+CoreDataClass.m @@ -48,7 +48,6 @@ - (DSMasternodeList *)masternodeListWithSimplifiedMasternodeEntryPool:(NSDiction + (void)deleteAllOnChainEntity:(DSChainEntity *)chainEntity { NSArray *masternodeLists = [self objectsInContext:chainEntity.managedObjectContext matching:@"(block.chain == %@)", chainEntity]; for (DSMasternodeListEntity *masternodeList in masternodeLists) { - DSLog(@"MasternodeListEntity.deleteAllOnChainEntity: %@", masternodeList); [chainEntity.managedObjectContext deleteObject:masternodeList]; } } diff --git a/DashSync/shared/Models/Entities/DSSimplifiedMasternodeEntryEntity+CoreDataClass.m b/DashSync/shared/Models/Entities/DSSimplifiedMasternodeEntryEntity+CoreDataClass.m index 2ffc58237..47fe8e8eb 100644 --- a/DashSync/shared/Models/Entities/DSSimplifiedMasternodeEntryEntity+CoreDataClass.m +++ b/DashSync/shared/Models/Entities/DSSimplifiedMasternodeEntryEntity+CoreDataClass.m @@ -171,9 +171,6 @@ - (void)setAttributesFromSimplifiedMasternodeEntry:(DSSimplifiedMasternodeEntry self.simplifiedMasternodeEntryHash = [NSData dataWithUInt256:simplifiedMasternodeEntry.simplifiedMasternodeEntryHash]; self.updateHeight = blockHeight; - if (simplifiedMasternodeEntry.updateHeight != blockHeight) { - DSLog(@"• setAttributesFromSimplifiedMasternodeEntry: list.height %u != entry.height %u", blockHeight, simplifiedMasternodeEntry.updateHeight); - } // TODO: make sure we're doing // NSAssert(simplifiedMasternodeEntry.updateHeight == blockHeight, ([NSString stringWithFormat:@"the block height (%i) for %@ should be the same as the entry update height (%i)", blockHeight, uint256_hex(simplifiedMasternodeEntry.providerRegistrationTransactionHash), simplifiedMasternodeEntry.updateHeight])); if (!chainEntity) { @@ -205,7 +202,6 @@ - (void)setAttributesFromSimplifiedMasternodeEntry:(DSSimplifiedMasternodeEntry + (void)deleteHavingProviderTransactionHashes:(NSArray *)providerTransactionHashes onChainEntity:(DSChainEntity *)chainEntity { NSArray *hashesToDelete = [self objectsInContext:chainEntity.managedObjectContext matching:@"(chain == %@) && (providerRegistrationTransactionHash IN %@)", chainEntity, providerTransactionHashes]; for (DSSimplifiedMasternodeEntryEntity *simplifiedMasternodeEntryEntity in hashesToDelete) { - DSLog(@"deleteHavingProviderTransactionHashes: %@", simplifiedMasternodeEntryEntity.providerRegistrationTransactionHash.hexString); [chainEntity.managedObjectContext deleteObject:simplifiedMasternodeEntryEntity]; } } diff --git a/DashSync/shared/Models/Entities/DSTxOutputEntity+CoreDataClass.m b/DashSync/shared/Models/Entities/DSTxOutputEntity+CoreDataClass.m index 7c8c8b8c3..3f5b8ce25 100644 --- a/DashSync/shared/Models/Entities/DSTxOutputEntity+CoreDataClass.m +++ b/DashSync/shared/Models/Entities/DSTxOutputEntity+CoreDataClass.m @@ -55,8 +55,6 @@ - (instancetype)setAttributesFromTransaction:(DSTransaction *)transaction output self.localAddress = addressEntities[0]; self.account = self.localAddress.derivationPath.account; //this is to make the outputs easily accessible for an account } - } else { - DSLog(@"Output had no address"); } return self; } diff --git a/DashSync/shared/Models/Governance/DSGovernanceObject.m b/DashSync/shared/Models/Governance/DSGovernanceObject.m index 0d0968390..63a227c78 100644 --- a/DashSync/shared/Models/Governance/DSGovernanceObject.m +++ b/DashSync/shared/Models/Governance/DSGovernanceObject.m @@ -299,7 +299,6 @@ - (void)loadGovernanceVotes:(NSUInteger)count { if (!_knownGovernanceVoteHashesForExistingGovernanceVotes) _knownGovernanceVoteHashesForExistingGovernanceVotes = [NSMutableOrderedSet orderedSet]; for (DSGovernanceVoteEntity *governanceVoteEntity in governanceVoteEntities) { DSGovernanceVote *governanceVote = [governanceVoteEntity governanceVote]; - DSLog(@"%@ : %@ -> %d/%d", self.identifier, [NSData dataWithUInt256:governanceVote.masternode.simplifiedMasternodeEntryHash].shortHexString, governanceVote.outcome, governanceVote.signal); [_knownGovernanceVoteHashesForExistingGovernanceVotes addObject:[NSData dataWithUInt256:governanceVote.governanceVoteHash]]; [_governanceVotes addObject:governanceVote]; } @@ -386,7 +385,6 @@ - (void)peer:(DSPeer *)peer hasGovernanceVoteHashes:(NSSet *)governanceVoteHashe @synchronized(self) { if (!(([[DSOptionsManager sharedInstance] syncType] & DSSyncType_GovernanceVotes) == DSSyncType_GovernanceVotes)) return; - DSLog(@"peer relayed governance vote hashes"); if (!self.totalGovernanceVoteCount) { [self.delegate governanceObject:self didReceiveUnknownHashes:governanceVoteHashes fromPeer:peer]; } @@ -427,11 +425,9 @@ - (void)peer:(DSPeer *)peer hasGovernanceVoteHashes:(NSSet *)governanceVoteHashe } self.knownGovernanceVoteHashes = rHashes; self.needsRequestsGovernanceVoteHashEntities = nil; //just so it can lazy load again - DSLog(@"-> %lu - %lu", (unsigned long)[self.knownGovernanceVoteHashes count], (unsigned long)self.totalGovernanceVoteCount); if ([self.knownGovernanceVoteHashes count] >= self.totalGovernanceVoteCount) { //we have more than we should have //for a vote it doesn't matter and will happen often - DSLog(@"All governance vote hashes received for object %@", self.identifier); // [self.managedObjectContext performBlockAndWait:^{ // [DSGovernanceVoteHashEntity setContext:self.managedObjectContext]; // [DSGovernanceVoteHashEntity removeOldest:countAroundNow - self.totalGovernanceVoteCount hashesNotIn:governanceVoteHashes onChain:[self.chain chainEntityInContext:context]]; diff --git a/DashSync/shared/Models/Identity/DSBlockchainIdentity.m b/DashSync/shared/Models/Identity/DSBlockchainIdentity.m index f62ffd288..41ef62e50 100644 --- a/DashSync/shared/Models/Identity/DSBlockchainIdentity.m +++ b/DashSync/shared/Models/Identity/DSBlockchainIdentity.m @@ -1273,7 +1273,6 @@ - (void)addKey:(OpaqueKey *)key atIndex:(uint32_t)index ofType:(KeyKind)type wit } } else { NSAssert(FALSE, @"these should really match up"); - DSLog(@"these should really match up"); return; } } else { @@ -1310,7 +1309,6 @@ - (void)addKey:(OpaqueKey *)key atIndexPath:(NSIndexPath *)indexPath ofType:(Key } } else { NSAssert(FALSE, @"these should really match up"); - DSLog(@"these should really match up"); return; } } else { @@ -1321,8 +1319,6 @@ - (void)addKey:(OpaqueKey *)key atIndexPath:(NSIndexPath *)indexPath ofType:(Key } NSDictionary *keyDictionary = @{@(DSBlockchainIdentityKeyDictionary_Key): [NSValue valueWithPointer:key], @(DSBlockchainIdentityKeyDictionary_KeyType): @(type), @(DSBlockchainIdentityKeyDictionary_KeyStatus): @(status)}; [self.keyInfoDictionaries setObject:keyDictionary forKey:@(index)]; - } else { - DSLog(@"these should really match up"); } } @@ -1655,17 +1651,6 @@ - (void)fetchL3NetworkStateInformation:(DSBlockchainIdentityQueryStep)queryStep __weak typeof(self) weakSelf = self; if (completion) { dispatch_group_notify(dispatchGroup, self.identityQueue, ^{ -#if DEBUG - DSLogPrivate(@"Completed fetching of blockchain identity information for user %@ (query %lu - failures %lu)", - self.currentDashpayUsername ? self.currentDashpayUsername : self.uniqueIdString, - (unsigned long)queryStep, - failureStep); -#else - DSLog(@"Completed fetching of blockchain identity information for user %@ (query %lu - failures %lu)", - @"", - (unsigned long)queryStep, - failureStep); -#endif /* DEBUG */ if (!(failureStep & DSBlockchainIdentityQueryStep_ContactRequests)) { __strong typeof(weakSelf) strongSelf = weakSelf; if (!strongSelf) { @@ -1879,7 +1864,6 @@ - (void)signMessageDigest:(UInt256)digest forKeyIndex:(uint32_t)keyIndex ofType: NSAssert(privateKey, @"The private key should exist"); NSAssert([DSKeyManager keysPublicKeyDataIsEqual:privateKey key2:[self publicKeyAtIndex:keyIndex ofType:signingAlgorithm]], @"These should be equal"); NSParameterAssert(privateKey); - DSLogPrivate(@"Signing %@ with key %@", uint256_hex(digest), [DSKeyManager publicKeyData:privateKey].hexString); NSData *signature = [DSKeyManager signMesasageDigest:privateKey digest:digest]; completion(!signature.isZeroBytes, signature); } @@ -1985,7 +1969,6 @@ - (void)fetchAndUpdateContract:(DPContract *)contract inContext:(NSManagedObject }]; } else if (contract.contractState == DPContractState_Registered || contract.contractState == DPContractState_Registering) { - DSLog(@"Fetching contract for verification %@", contract.base58ContractId); [self.DAPINetworkService fetchContractForId:uint256_data(contract.contractId) completionQueue:self.identityQueue success:^(NSDictionary *_Nonnull contractDictionary) { @@ -2004,7 +1987,6 @@ - (void)fetchAndUpdateContract:(DPContract *)contract inContext:(NSManagedObject if (![set1 isEqualToSet:set2]) { [strongContract setContractState:DPContractState_NotRegistered inContext:context]; } - DSLog(@"Contract dictionary is %@", contractDictionary); } } failure:^(NSError *_Nonnull error) { @@ -2234,7 +2216,6 @@ - (void)registerUsernamesWithCompletion:(void (^_Nullable)(BOOL success, NSError } - (void)registerUsernamesAtStage:(DSBlockchainIdentityUsernameStatus)blockchainIdentityUsernameStatus inContext:(NSManagedObjectContext *)context completion:(void (^_Nullable)(BOOL success, NSError *error))completion onCompletionQueue:(dispatch_queue_t)completionQueue { - DSLog(@"registerUsernamesAtStage %lu", (unsigned long)blockchainIdentityUsernameStatus); switch (blockchainIdentityUsernameStatus) { case DSBlockchainIdentityUsernameStatus_Initial: { NSArray *usernameFullPaths = [self usernameFullPathsWithStatus:DSBlockchainIdentityUsernameStatus_Initial]; @@ -2387,7 +2368,6 @@ - (void)registerPreorderedSaltedDomainHashesForUsernameFullPaths:(NSArray *)user } } failure:^(NSError *_Nonnull error) { - DSLogPrivate(@"%@", error); if (completion) { dispatch_async(completionQueue, ^{ completion(NO, error); @@ -2430,8 +2410,6 @@ - (void)registerUsernameDomainsForUsernameFullPaths:(NSArray *)usernameFullPaths } } failure:^(NSError *_Nonnull error) { - DSLogPrivate(@"%@", error); - if (completion) { dispatch_async(completionQueue, ^{ completion(NO, error); @@ -2895,7 +2873,6 @@ - (void)monitorForContract:(DPContract *)contract withRetryCount:(uint32_t)retry } return; } - DSLog(@"Contract dictionary is %@", contractDictionary); if ([contractDictionary isKindOfClass:[NSDictionary class]] && [contractDictionary[@"$id"] isEqualToData:uint256_data(contract.contractId)]) { [contract setContractState:DPContractState_Registered inContext:context]; if (completion) { @@ -3185,8 +3162,6 @@ - (void)sendNewFriendRequestToPotentialContact:(DSPotentialContact *)potentialCo if (error.code == 12) { //UNIMPLEMENTED, this would mean that we are connecting to an old node [self.DAPIClient removeDAPINodeByAddress:dapiNetworkService.ipAddress]; } - DSLogPrivate(@"%@", error); - if (completion) { dispatch_async(dispatch_get_main_queue(), ^{ completion(NO, @[error]); @@ -4531,22 +4506,12 @@ - (BOOL)createNewKey:(OpaqueKey *)key forIdentityEntity:(DSBlockchainIdentityEnt NSData *privateKeyData = [DSKeyManager privateKeyData:key]; if (privateKeyData) { setKeychainData(privateKeyData, [self identifierForKeyAtPath:path fromDerivationPath:derivationPath], YES); -#if DEBUG - DSLogPrivate(@"Saving key at %@ for user %@", [self identifierForKeyAtPath:path fromDerivationPath:derivationPath], self.currentDashpayUsername); -#else - DSLog(@"Saving key at %@ for user %@", @"", @""); -#endif } else { OpaqueKey *privateKey = [self derivePrivateKeyAtIndexPath:path ofType:(int16_t) key->tag]; NSAssert([DSKeyManager keysPublicKeyDataIsEqual:privateKey key2:key], @"The keys don't seem to match up"); NSData *privateKeyData = [DSKeyManager privateKeyData:privateKey]; NSAssert(privateKeyData, @"Private key data should exist"); setKeychainData(privateKeyData, [self identifierForKeyAtPath:path fromDerivationPath:derivationPath], YES); -#if DEBUG - DSLogPrivate(@"Saving key after rederivation %@ for user %@", [self identifierForKeyAtPath:path fromDerivationPath:derivationPath], self.currentDashpayUsername ? self.currentDashpayUsername : self.uniqueIdString); -#else - DSLog(@"Saving key after rederivation %@ for user %@", @"", @""); -#endif } blockchainIdentityKeyPathEntity.path = path; @@ -4555,11 +4520,6 @@ - (BOOL)createNewKey:(OpaqueKey *)key forIdentityEntity:(DSBlockchainIdentityEnt [blockchainIdentityEntity addKeyPathsObject:blockchainIdentityKeyPathEntity]; return YES; } else { -#if DEBUG - DSLogPrivate(@"Already had saved this key %@", path); -#else - DSLog(@"Already had saved this key %@", @""); -#endif return NO; //no need to save the context } } diff --git a/DashSync/shared/Models/Managers/CLAUDE.md b/DashSync/shared/Models/Managers/CLAUDE.md new file mode 100644 index 000000000..e5c75feed --- /dev/null +++ b/DashSync/shared/Models/Managers/CLAUDE.md @@ -0,0 +1,220 @@ +# DashSync Managers + +Managers are service coordinators that handle specific functional areas of DashSync. They follow the Model-Manager pattern where models hold data and managers coordinate operations. + +## Directory Structure + +``` +Managers/ +├── Chain Managers/ # Blockchain operation coordinators +└── Service Managers/ # External service coordinators +``` + +## Chain Managers + +Located in `Chain Managers/`, these coordinate blockchain operations. + +### DSChainsManager (Singleton) +Entry point for multi-chain management. +```objc +[DSChainsManager sharedInstance] +``` +- Manages multiple chain instances (mainnet, testnet, devnets) +- Chain registration and retrieval +- Cross-chain coordination + +### DSChainManager +Per-chain coordinator with sub-managers. +```objc +chain.chainManager +``` +- Coordinates sync operations +- Manages chain state transitions +- Sub-manager lifecycle management + +**Categories:** +- `DSChainManager+Mining.h` - Mining operations +- `DSChainManager+Transactions.h` - Transaction operations +- `DSChainManager+Protected.h` - Internal interface + +### DSPeerManager (~50K lines) +P2P network management. +```objc +chain.chainManager.peerManager +``` +- Peer discovery and connection +- Message sending/receiving +- Network health monitoring +- Bloom filter management + +### DSTransactionManager (~108K lines) +Transaction pool management. +```objc +chain.chainManager.transactionManager +``` +- Transaction broadcasting +- Transaction verification +- Mempool management +- InstantSend handling + +### DSMasternodeManager (~49K lines) +Masternode operations. +```objc +chain.chainManager.masternodeManager +``` +- Masternode list sync +- Quorum management +- Rotation handling + +**Categories:** +- `DSMasternodeManager+LocalMasternode.h` - Local masternode ops +- `DSMasternodeManager+Mndiff.h` - Masternode diff processing + +### DSIdentitiesManager +Blockchain identity operations. +```objc +chain.chainManager.identitiesManager +``` +- Identity creation/retrieval +- Contact management +- Dashpay integration + +### DSGovernanceSyncManager +Governance synchronization. +```objc +chain.chainManager.governanceSyncManager +``` +- Proposal sync +- Vote tracking +- Superblock processing + +### DSSporkManager +Network parameters. +```objc +chain.chainManager.sporkManager +``` +- Spork state management +- Feature flag tracking + +### DSKeyManager +Cryptographic key operations. +```objc +chain.chainManager.keyManager +``` +- Key generation +- Signature operations +- Key derivation + +### DSBackgroundManager +Background task coordination. +- iOS background fetch +- Background processing tasks +- Sync scheduling + +## Service Managers + +Located in `Service Managers/`, these handle external services. + +### DSAuthenticationManager (`Auth/`) +User authentication. +```objc +[DSAuthenticationManager sharedInstance] +``` +- Biometric authentication (Touch ID, Face ID) +- PIN management +- Spend limits +- Device passcode verification + +### DSPriceManager (`Price/`) +Cryptocurrency pricing. +```objc +[DSPriceManager sharedInstance] +``` +- Price fetching from multiple sources +- Currency conversion +- Price caching +- Exchange rate updates + +### DSInsightManager +Blockchain explorer APIs. +- Transaction lookup +- Address balance queries +- External block explorer integration + +### DSVersionManager +App version management. +- Version checking +- Migration handling +- Compatibility verification + +### DSEventManager +Analytics and events. +- Event tracking +- User action logging +- Analytics integration + +### DSOptionsManager +User preferences. +- Configuration settings +- Feature toggles +- User preferences storage + +### DSShapeshiftManager +Exchange integration. +- Asset conversion +- Exchange rate queries +- Transaction tracking + +### DSErrorSimulationManager +Testing utilities. +- Error injection +- Failure simulation +- Debug scenarios + +## Common Patterns + +### Accessing Managers +```objc +// Chain managers (via chain) +DSChain *chain = [[DSChainsManager sharedInstance] mainnetChain]; +DSPeerManager *peers = chain.chainManager.peerManager; +DSTransactionManager *txManager = chain.chainManager.transactionManager; + +// Service managers (singletons) +DSPriceManager *prices = [DSPriceManager sharedInstance]; +DSAuthenticationManager *auth = [DSAuthenticationManager sharedInstance]; +``` + +### Protected Interfaces +Files ending in `+Protected.h` expose internal methods: +```objc +#import "DSPeerManager+Protected.h" // For testing or subclasses +``` + +### Manager Lifecycle +```objc +// Managers are typically created by their parent +// DSChainManager creates sub-managers on init +// Service managers are singletons with lazy initialization +``` + +### Notifications +Managers post notifications for state changes: +```objc +DSPeerManagerConnectedPeersDidChangeNotification +DSTransactionManagerTransactionStatusDidChangeNotification +DSChainManagerSyncPhaseDidChangeNotification +``` + +## File Size Reference + +| Manager | Lines | Complexity | +|---------|-------|------------| +| DSTransactionManager | ~108K | Very High | +| DSPeerManager | ~50K | High | +| DSMasternodeManager | ~49K | High | +| DSIdentitiesManager | ~35K | High | +| DSGovernanceSyncManager | ~31K | Medium | +| DSPriceManager | ~30K | Medium | +| DSShapeshiftManager | ~26K | Medium | +| DSChainManager | ~22K | Medium | diff --git a/DashSync/shared/Models/Managers/Chain Managers/DSChainManager.m b/DashSync/shared/Models/Managers/Chain Managers/DSChainManager.m index 2672588d6..b36953c14 100644 --- a/DashSync/shared/Models/Managers/Chain Managers/DSChainManager.m +++ b/DashSync/shared/Models/Managers/Chain Managers/DSChainManager.m @@ -25,6 +25,8 @@ #import "DSBloomFilter.h" #import "DSChain+Protected.h" +#import "DSChainSyncSpeedCalculator.h" +#import "DSLogger.h" #import "DSChainEntity+CoreDataClass.h" #import "DSChainManager+Mining.h" #import "DSChainManager+Protected.h" @@ -105,7 +107,6 @@ - (instancetype)initWithChain:(DSChain *)chain { //[self loadHeightTransactionZones]; self.miningQueue = dispatch_queue_create([[NSString stringWithFormat:@"org.dashcore.dashsync.mining.%@", self.chain.uniqueID] UTF8String], DISPATCH_QUEUE_SERIAL); - DSLog(@"[%@] DSChainManager.initWithChain %@", chain.name, chain); return self; } @@ -126,13 +127,16 @@ - (void)relayedNewItem { // MARK: - Blockchain Sync - (void)startSync { + DSLogInfo(@"DSChainManager", @"starting sync for chain %@", self.chain.name); + [[DSChainSyncSpeedCalculator sharedInstance] reset]; + [[DSChainSyncSpeedCalculator sharedInstance] startCalculating]; [self notify:DSChainManagerSyncWillStartNotification userInfo:@{DSChainManagerNotificationChainKey: self.chain}]; - DSLog(@"[%@] startSync -> peerManager::connect", self.chain.name); [self.peerManager connect]; } - (void)stopSync { - DSLog(@"[%@] stopSync (chain switch)", self.chain.name); + DSLogInfo(@"DSChainManager", @"stopping sync for chain %@", self.chain.name); + [[DSChainSyncSpeedCalculator sharedInstance] stopCalculating]; [self.masternodeManager stopSync]; [self.peerManager disconnect:DSDisconnectReason_ChainSwitch]; self.syncState.syncPhase = DSChainSyncPhase_Offline; @@ -153,7 +157,6 @@ - (void)disconnectedMasternodeListAndBlocksRescan { [self removeNonMainnetTrustedPeer]; [self notify:DSChainManagerSyncWillStartNotification userInfo:@{DSChainManagerNotificationChainKey: self.chain}]; - DSLog(@"[%@] disconnectedMasternodeListAndBlocksRescan -> peerManager::connect", self.chain.name); [self.peerManager connect]; } @@ -163,7 +166,6 @@ - (void)disconnectedMasternodeListRescan { [self removeNonMainnetTrustedPeer]; [self notify:DSChainManagerSyncWillStartNotification userInfo:@{DSChainManagerNotificationChainKey: self.chain}]; - DSLog(@"[%@] disconnectedMasternodeListRescan -> peerManager::connect", self.chain.name); [self.peerManager connect]; } @@ -173,7 +175,6 @@ - (void)disconnectedSyncBlocksRescan { [self removeNonMainnetTrustedPeer]; [self notify:DSChainManagerSyncWillStartNotification userInfo:@{DSChainManagerNotificationChainKey: self.chain}]; - DSLog(@"[%@] disconnectedSyncBlocksRescan -> peerManager::connect", self.chain.name); [self.peerManager connect]; } @@ -237,7 +238,7 @@ - (void)chainWillStartSyncingBlockchain:(DSChain *)chain { } - (void)chainWillStartConnectingToPeers:(DSChain *)chain { - + } - (void)chainShouldStartSyncingBlockchain:(DSChain *)chain onPeer:(DSPeer *)peer { @@ -268,7 +269,7 @@ - (void)chainShouldStartSyncingBlockchain:(DSChain *)chain onPeer:(DSPeer *)peer - (void)chainFinishedSyncingInitialHeaders:(DSChain *)chain fromPeer:(DSPeer *)peer onMainChain:(BOOL)onMainChain { if (onMainChain && peer && (peer == self.peerManager.downloadPeer)) [self relayedNewItem]; - + [self.peerManager chainSyncStopped]; if (([[DSOptionsManager sharedInstance] syncType] & DSSyncType_MasternodeList)) { // make sure we care about masternode lists @@ -278,10 +279,21 @@ - (void)chainFinishedSyncingInitialHeaders:(DSChain *)chain fromPeer:(DSPeer *)p - (void)chainFinishedSyncingTransactionsAndBlocks:(DSChain *)chain fromPeer:(DSPeer *)peer onMainChain:(BOOL)onMainChain { if (onMainChain && peer && (peer == self.peerManager.downloadPeer)) [self relayedNewItem]; - DSLog(@"[%@] finished syncing", self.chain.name); - + self.syncState.chainSyncStartHeight = 0; self.syncState.syncPhase = DSChainSyncPhase_Synced; + DSLogInfo(@"DSChainManager", @"chain sync completed at height %u", chain.lastSyncBlockHeight); + + // Log transaction list after sync completion + for (DSWallet *wallet in chain.wallets) { + NSArray *transactions = wallet.allTransactions; + DSLogInfo(@"DSChainManager", @"Wallet has %lu transactions after sync", (unsigned long)transactions.count); + for (DSTransaction *tx in transactions) { + NSString *status = tx.blockHeight == TX_UNCONFIRMED ? @"unconfirmed" : [NSString stringWithFormat:@"confirmed at %u", tx.blockHeight]; + DSLogDebug(@"DSChainManager", @" TX %@ - %@", uint256_reverse_hex(tx.txHash), status); + } + } + [self.transactionManager fetchMempoolFromNetwork]; [self.sporkManager getSporks]; [self.governanceSyncManager startGovernanceSync]; @@ -301,13 +313,11 @@ - (void)setSyncPhase:(DSChainSyncPhase)syncPhase { } - (void)syncBlockchain { - DSLog(@"[%@] syncBlockchain connected peers: %lu phase: %d", self.chain.name, self.peerManager.connectedPeerCount, self.syncPhase); if (self.peerManager.connectedPeerCount == 0) { if (self.syncPhase == DSChainSyncPhase_InitialTerminalBlocks) { self.syncState.syncPhase = DSChainSyncPhase_ChainSync; [self notifySyncStateChanged]; } - DSLog(@"[%@] syncBlockchain -> peerManager::connect", self.chain.name); [self.peerManager connect]; } else if (!self.peerManager.masternodeList && self.masternodeManager.currentMasternodeList) { [self.peerManager useMasternodeList:self.masternodeManager.currentMasternodeList withConnectivityNonce:self.sessionConnectivityNonce]; @@ -319,7 +329,6 @@ - (void)syncBlockchain { } - (void)chainFinishedSyncingMasternodeListsAndQuorums:(DSChain *)chain { - DSLog(@"[%@] finished syncing masternode list and quorums, it should start syncing chain", self.chain.name); if (chain.isEvolutionEnabled) { [self.identitiesManager syncBlockchainIdentitiesWithCompletion:^(NSArray *_Nullable blockchainIdentities) { [self syncBlockchain]; @@ -330,7 +339,6 @@ - (void)chainFinishedSyncingMasternodeListsAndQuorums:(DSChain *)chain { } - (void)chain:(DSChain *)chain badBlockReceivedFromPeer:(DSPeer *)peer { - DSLog(@"[%@: %@:%d] peer is misbehaving", self.chain.name, peer.host, peer.port); [self.peerManager peerMisbehaving:peer errorMessage:@"Bad block received from peer"]; } @@ -340,7 +348,6 @@ - (void)chain:(DSChain *)chain receivedOrphanBlock:(DSBlock *)block fromPeer:(DS // call getblocks, unless we already did with the previous block, or we're still downloading the chain if (self.chain.lastSyncBlockHeight >= peer.lastBlockHeight && !uint256_eq(self.chain.lastOrphan.blockHash, block.prevBlock)) { - DSLog(@"[%@: %@:%d] calling getblocks", self.chain.name, peer.host, peer.port); [peer sendGetblocksMessageWithLocators:[self.chain chainSyncBlockLocatorArray] andHashStop:UINT256_ZERO]; } } @@ -391,7 +398,6 @@ - (void)peer:(DSPeer *)peer relayedSyncInfo:(DSSyncCountInfo)syncCountInfo count if (peer.governanceRequestState == DSGovernanceRequestState_GovernanceObjectVoteHashesReceived) { if (count == 0) { //there were no votes - DSLog(@"[%@: %@:%d] no votes on object, going to next object", self.chain.name, peer.host, peer.port); peer.governanceRequestState = DSGovernanceRequestState_GovernanceObjectVotes; [self.governanceSyncManager finishedGovernanceVoteSyncWithPeer:peer]; } else { diff --git a/DashSync/shared/Models/Managers/Chain Managers/DSChainSyncSpeedCalculator.h b/DashSync/shared/Models/Managers/Chain Managers/DSChainSyncSpeedCalculator.h new file mode 100644 index 000000000..678845140 --- /dev/null +++ b/DashSync/shared/Models/Managers/Chain Managers/DSChainSyncSpeedCalculator.h @@ -0,0 +1,71 @@ +// +// DSChainSyncSpeedCalculator.h +// DashSync +// +// Created for improved logging to match Android/DashJ behavior. +// Copyright (c) 2024 Dash Core Group. All rights reserved. +// + +#import + +NS_ASSUME_NONNULL_BEGIN + +/** + * DSChainSyncSpeedCalculator tracks blockchain sync speed and statistics. + * + * This class provides periodic logging of sync progress similar to Android/DashJ: + * - Blocks/sec, tx/sec, pre-filtered tx/sec, headers/sec, mnlistdiff/sec + * - Average and last KB/sec throughput + * - Chain height vs target height + * - Stall detection status + */ +@interface DSChainSyncSpeedCalculator : NSObject + +/// Singleton instance for the main chain ++ (instancetype)sharedInstance; + +/// Start calculating sync speed (call when sync begins) +- (void)startCalculating; + +/// Stop calculating sync speed (call when sync ends) +- (void)stopCalculating; + +/// Record a block being received +- (void)recordBlockReceived; + +/// Record blocks being received (batch) +- (void)recordBlocksReceived:(NSUInteger)count; + +/// Record a transaction being received +- (void)recordTransactionReceived; + +/// Record transactions being received (batch) +- (void)recordTransactionsReceived:(NSUInteger)count; + +/// Record pre-filtered transactions (before bloom filter) +- (void)recordPreFilteredTransactionsReceived:(NSUInteger)count; + +/// Record a header being received +- (void)recordHeaderReceived; + +/// Record headers being received (batch) +- (void)recordHeadersReceived:(NSUInteger)count; + +/// Record a masternode list diff being received +- (void)recordMnListDiffReceived; + +/// Record bytes received +- (void)recordBytesReceived:(NSUInteger)bytes; + +/// Update chain heights for stall detection +- (void)updateChainHeight:(uint32_t)chainHeight commonHeight:(uint32_t)commonHeight targetHeight:(uint32_t)targetHeight; + +/// Force a log output immediately +- (void)logCurrentStats; + +/// Reset all counters +- (void)reset; + +@end + +NS_ASSUME_NONNULL_END diff --git a/DashSync/shared/Models/Managers/Chain Managers/DSChainSyncSpeedCalculator.m b/DashSync/shared/Models/Managers/Chain Managers/DSChainSyncSpeedCalculator.m new file mode 100644 index 000000000..da04c6e48 --- /dev/null +++ b/DashSync/shared/Models/Managers/Chain Managers/DSChainSyncSpeedCalculator.m @@ -0,0 +1,293 @@ +// +// DSChainSyncSpeedCalculator.m +// DashSync +// +// Created for improved logging to match Android/DashJ behavior. +// Copyright (c) 2024 Dash Core Group. All rights reserved. +// + +#import "DSChainSyncSpeedCalculator.h" +#import "DSLogger.h" + +// Log interval in seconds (matches Android) +static const NSTimeInterval kLogIntervalSeconds = 1.0; + +// Stall detection - if no progress for this many seconds, consider stalled +static const NSTimeInterval kStallDetectionSeconds = 30.0; + +@interface DSChainSyncSpeedCalculator () + +@property (nonatomic, strong) NSTimer *logTimer; +@property (nonatomic, strong) dispatch_queue_t statsQueue; + +// Current interval counters +@property (atomic, assign) NSUInteger blocksThisInterval; +@property (atomic, assign) NSUInteger transactionsThisInterval; +@property (atomic, assign) NSUInteger preFilteredTxThisInterval; +@property (atomic, assign) NSUInteger headersThisInterval; +@property (atomic, assign) NSUInteger mnListDiffsThisInterval; +@property (atomic, assign) NSUInteger bytesThisInterval; + +// Cumulative counters for averaging +@property (atomic, assign) NSUInteger totalBlocks; +@property (atomic, assign) NSUInteger totalTransactions; +@property (atomic, assign) NSUInteger totalBytes; +@property (atomic, assign) NSTimeInterval startTime; + +// Rolling averages +@property (atomic, assign) double avgKBPerSec; +@property (atomic, assign) double lastKBPerSec; + +// Chain heights for stall detection +@property (atomic, assign) uint32_t chainHeight; +@property (atomic, assign) uint32_t commonHeight; +@property (atomic, assign) uint32_t targetHeight; +@property (atomic, assign) NSTimeInterval lastProgressTime; +@property (atomic, assign) uint32_t lastChainHeight; + +// History for statistics logging (ring buffer of last 10 intervals) +@property (nonatomic, strong) NSMutableArray *historyBuffer; +@property (atomic, assign) NSUInteger historyIndex; + +@end + +@implementation DSChainSyncSpeedCalculator + ++ (instancetype)sharedInstance { + static DSChainSyncSpeedCalculator *instance = nil; + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + instance = [[self alloc] init]; + }); + return instance; +} + +- (instancetype)init { + self = [super init]; + if (self) { + _statsQueue = dispatch_queue_create("org.dashcore.dashsync.speedcalculator", DISPATCH_QUEUE_SERIAL); + _historyBuffer = [NSMutableArray arrayWithCapacity:10]; + [self reset]; + } + return self; +} + +- (void)startCalculating { + dispatch_async(dispatch_get_main_queue(), ^{ + [self.logTimer invalidate]; + self.startTime = [[NSDate date] timeIntervalSince1970]; + self.lastProgressTime = self.startTime; + self.logTimer = [NSTimer scheduledTimerWithTimeInterval:kLogIntervalSeconds + target:self + selector:@selector(timerFired) + userInfo:nil + repeats:YES]; + [[NSRunLoop currentRunLoop] addTimer:self.logTimer forMode:NSRunLoopCommonModes]; + }); +} + +- (void)stopCalculating { + dispatch_async(dispatch_get_main_queue(), ^{ + [self.logTimer invalidate]; + self.logTimer = nil; + }); +} + +- (void)timerFired { + [self logCurrentStats]; + [self resetIntervalCounters]; +} + +- (void)recordBlockReceived { + dispatch_async(self.statsQueue, ^{ + self.blocksThisInterval++; + self.totalBlocks++; + }); +} + +- (void)recordBlocksReceived:(NSUInteger)count { + dispatch_async(self.statsQueue, ^{ + self.blocksThisInterval += count; + self.totalBlocks += count; + }); +} + +- (void)recordTransactionReceived { + dispatch_async(self.statsQueue, ^{ + self.transactionsThisInterval++; + self.totalTransactions++; + }); +} + +- (void)recordTransactionsReceived:(NSUInteger)count { + dispatch_async(self.statsQueue, ^{ + self.transactionsThisInterval += count; + self.totalTransactions += count; + }); +} + +- (void)recordPreFilteredTransactionsReceived:(NSUInteger)count { + dispatch_async(self.statsQueue, ^{ + self.preFilteredTxThisInterval += count; + }); +} + +- (void)recordHeaderReceived { + dispatch_async(self.statsQueue, ^{ + self.headersThisInterval++; + }); +} + +- (void)recordHeadersReceived:(NSUInteger)count { + dispatch_async(self.statsQueue, ^{ + self.headersThisInterval += count; + }); +} + +- (void)recordMnListDiffReceived { + dispatch_async(self.statsQueue, ^{ + self.mnListDiffsThisInterval++; + }); +} + +- (void)recordBytesReceived:(NSUInteger)bytes { + dispatch_async(self.statsQueue, ^{ + self.bytesThisInterval += bytes; + self.totalBytes += bytes; + }); +} + +- (void)updateChainHeight:(uint32_t)chainHeight commonHeight:(uint32_t)commonHeight targetHeight:(uint32_t)targetHeight { + dispatch_async(self.statsQueue, ^{ + if (chainHeight > self.lastChainHeight) { + self.lastProgressTime = [[NSDate date] timeIntervalSince1970]; + self.lastChainHeight = chainHeight; + } + self.chainHeight = chainHeight; + self.commonHeight = commonHeight; + self.targetHeight = targetHeight; + }); +} + +- (void)logCurrentStats { + __block NSUInteger blocks, txs, preFilteredTxs, headers, mnListDiffs, bytes; + __block uint32_t chainH, commonH, targetH; + __block NSTimeInterval lastProgress; + __block double avgKB, totalB; + __block NSTimeInterval elapsed; + + dispatch_sync(self.statsQueue, ^{ + blocks = self.blocksThisInterval; + txs = self.transactionsThisInterval; + preFilteredTxs = self.preFilteredTxThisInterval; + headers = self.headersThisInterval; + mnListDiffs = self.mnListDiffsThisInterval; + bytes = self.bytesThisInterval; + chainH = self.chainHeight; + commonH = self.commonHeight; + targetH = self.targetHeight; + lastProgress = self.lastProgressTime; + totalB = (double)self.totalBytes; + elapsed = [[NSDate date] timeIntervalSince1970] - self.startTime; + }); + + // Calculate KB/sec + double lastKB = (double)bytes / 1024.0; + double avgKBPerSec = (elapsed > 0) ? (totalB / 1024.0 / elapsed) : 0; + + // Stall detection + NSTimeInterval now = [[NSDate date] timeIntervalSince1970]; + BOOL isStalled = (now - lastProgress) > kStallDetectionSeconds; + NSString *stallStatus = isStalled ? @"STALLED" : @"not stalled"; + + // Only log if there's activity or we haven't logged in a while + if (blocks > 0 || txs > 0 || headers > 0 || mnListDiffs > 0) { + // Store in history buffer for History Statistics logging + NSDictionary *historyEntry = @{ + @"tx": @(txs), + @"blocks": @(blocks), + @"headers": @(headers), + @"mnlistdiff": @(mnListDiffs) + }; + dispatch_async(self.statsQueue, ^{ + if (self.historyBuffer.count >= 10) { + [self.historyBuffer removeObjectAtIndex:0]; + } + [self.historyBuffer addObject:historyEntry]; + }); + + // Log Android-style output + DSLogInfo(@"DSChainSyncSpeedCalculator", + @"%lu blocks/sec, %lu tx/sec, %lu pre-filtered tx/sec, %lu headers/sec, %lu mnlistdiff/sec, avg/last %.2f/%.2f kilobytes per sec, chain/common height %u/%u, %@", + (unsigned long)blocks, + (unsigned long)txs, + (unsigned long)preFilteredTxs, + (unsigned long)headers, + (unsigned long)mnListDiffs, + avgKBPerSec, + lastKB, + chainH, + commonH, + stallStatus); + } + + // Store for averaging + dispatch_async(self.statsQueue, ^{ + self.avgKBPerSec = avgKBPerSec; + self.lastKBPerSec = lastKB; + }); +} + +- (void)logHistoryStats { + __block NSMutableString *historyString = [NSMutableString string]; + + dispatch_sync(self.statsQueue, ^{ + for (NSDictionary *entry in self.historyBuffer) { + if (historyString.length > 0) { + [historyString appendString:@", "]; + } + [historyString appendFormat:@"%@/%@/%@/%@", + entry[@"tx"], entry[@"blocks"], entry[@"headers"], entry[@"mnlistdiff"]]; + } + }); + + if (historyString.length > 0) { + DSLogInfo(@"DSChainSyncSpeedCalculator", @"History of transactions/blocks/headers/mnlistdiff: %@", historyString); + } +} + +- (void)resetIntervalCounters { + dispatch_async(self.statsQueue, ^{ + self.blocksThisInterval = 0; + self.transactionsThisInterval = 0; + self.preFilteredTxThisInterval = 0; + self.headersThisInterval = 0; + self.mnListDiffsThisInterval = 0; + self.bytesThisInterval = 0; + }); +} + +- (void)reset { + dispatch_sync(self.statsQueue, ^{ + self.blocksThisInterval = 0; + self.transactionsThisInterval = 0; + self.preFilteredTxThisInterval = 0; + self.headersThisInterval = 0; + self.mnListDiffsThisInterval = 0; + self.bytesThisInterval = 0; + self.totalBlocks = 0; + self.totalTransactions = 0; + self.totalBytes = 0; + self.startTime = [[NSDate date] timeIntervalSince1970]; + self.avgKBPerSec = 0; + self.lastKBPerSec = 0; + self.chainHeight = 0; + self.commonHeight = 0; + self.targetHeight = 0; + self.lastProgressTime = self.startTime; + self.lastChainHeight = 0; + [self.historyBuffer removeAllObjects]; + }); +} + +@end diff --git a/DashSync/shared/Models/Managers/Chain Managers/DSChainsManager.m b/DashSync/shared/Models/Managers/Chain Managers/DSChainsManager.m index 9dee6f6b6..fe84ba8c6 100644 --- a/DashSync/shared/Models/Managers/Chain Managers/DSChainsManager.m +++ b/DashSync/shared/Models/Managers/Chain Managers/DSChainsManager.m @@ -218,12 +218,9 @@ - (void)updateDevnetChain:(DSChain *)chain if (inet_aton([address UTF8String], &addrV4) != 0) { uint32_t ip = ntohl(addrV4.s_addr); ipAddress.u32[3] = CFSwapInt32HostToBig(ip); - DSLog(@"%08x", ip); } else if (inet_pton(AF_INET6, [address UTF8String], &addrV6)) { //todo support IPV6 - DSLog(@"we do not yet support IPV6"); } else { - DSLog(@"invalid address"); } [peerManager registerPeerAtLocation:ipAddress @@ -251,7 +248,7 @@ - (DSChain *_Nullable)registerDevnetChainWithIdentifier:(DevnetType)devnetType NSError *error = nil; DSChain *chain = [DSChain setUpDevnetWithIdentifier:devnetType protocolVersion:protocolVersion?protocolVersion:PROTOCOL_VERSION_DEVNET minProtocolVersion:minProtocolVersion?minProtocolVersion:DEFAULT_MIN_PROTOCOL_VERSION_DEVNET withCheckpoints:nil withMinimumDifficultyBlocks:minimumDifficultyBlocks withDefaultPort:standardPort withDefaultDapiJRPCPort:dapiJRPCPort withDefaultDapiGRPCPort:dapiGRPCPort dpnsContractID:dpnsContractID dashpayContractID:dashpayContractID isTransient:NO]; - + if (sporkAddress && [sporkAddress isValidDashDevnetAddress]) { chain.sporkAddress = sporkAddress; } @@ -270,12 +267,9 @@ - (DSChain *_Nullable)registerDevnetChainWithIdentifier:(DevnetType)devnetType if (inet_aton([address UTF8String], &addrV4) != 0) { uint32_t ip = ntohl(addrV4.s_addr); ipAddress.u32[3] = CFSwapInt32HostToBig(ip); - DSLog(@"%08x", ip); } else if (inet_pton(AF_INET6, [address UTF8String], &addrV6)) { //todo support IPV6 - DSLog(@"we do not yet support IPV6"); } else { - DSLog(@"invalid address"); } [peerManager registerPeerAtLocation:ipAddress @@ -332,7 +326,7 @@ - (void)removeDevnetChain:(DSChain *)chain { [self.knownChains removeObject:chain]; NSValue *genesisValue = uint256_obj(chain.genesisHash); [self.devnetGenesisDictionary removeObjectForKey:genesisValue]; - + dispatch_async(dispatch_get_main_queue(), ^{ [[NSNotificationCenter defaultCenter] postNotificationName:DSChainsDidChangeNotification object:nil]; }); diff --git a/DashSync/shared/Models/Managers/Chain Managers/DSGovernanceSyncManager.m b/DashSync/shared/Models/Managers/Chain Managers/DSGovernanceSyncManager.m index 6d004a78e..fb6729f00 100644 --- a/DashSync/shared/Models/Managers/Chain Managers/DSGovernanceSyncManager.m +++ b/DashSync/shared/Models/Managers/Chain Managers/DSGovernanceSyncManager.m @@ -89,7 +89,6 @@ - (DSPeerManager *)peerManager { // MARK: - Governance Sync - (void)continueGovernanceSync { - DSLog(@"[%@] --> Continuing Governance Sync", self.chain.name); NSUInteger last3HoursStandaloneBroadcastHashesCount = [self last3HoursStandaloneGovernanceObjectHashesCount]; if (last3HoursStandaloneBroadcastHashesCount) { DSPeer *downloadPeer = nil; @@ -144,13 +143,11 @@ - (void)startGovernanceSync { } //We need to sync - DSLog(@"[%@] --> Trying to start governance sync", self.chain.name); NSArray *sortedPeers = [self.peerManager.connectedPeers sortedArrayUsingDescriptors:@[[NSSortDescriptor sortDescriptorWithKey:@"lastRequestedGovernanceSync" ascending:YES]]]; BOOL startedGovernanceSync = FALSE; for (DSPeer *peer in sortedPeers) { if (peer.status != DSPeerStatus_Connected) continue; if ([[NSDate date] timeIntervalSince1970] - peer.lastRequestedGovernanceSync < 10800) { - DSLog(@"[%@] --> Peer recently used", self.chain.name); continue; //don't request less than every 3 hours from a peer } peer.lastRequestedGovernanceSync = [[NSDate date] timeIntervalSince1970]; //we are requesting the list from this peer @@ -186,7 +183,6 @@ - (void)publishVotes:(NSArray *)votes { - (void)startNextGoveranceVoteSyncWithPeer:(DSPeer *)peer { self.currentGovernanceSyncObject = [self.needVoteSyncGovernanceObjects firstObject]; self.currentGovernanceSyncObject.delegate = self; - DSLog(@"[%@] Getting votes for %@", self.chain.name, self.currentGovernanceSyncObject.identifier); [peer sendGovernanceSyncRequest:[DSGovernanceVotesSyncRequest requestWithParentHash:self.currentGovernanceSyncObject.governanceObjectHash]]; } @@ -354,7 +350,6 @@ - (void)peer:(DSPeer *)peer hasGovernanceObjectHashes:(NSSet *)governanceObjectH return; } } - DSLog(@"[%@: %@:%d] peer relayed governance objects", self.chain.name, peer.host, peer.port); NSMutableOrderedSet *hashesToInsert = [[NSOrderedSet orderedSetWithSet:governanceObjectHashes] mutableCopy]; NSMutableOrderedSet *hashesToUpdate = [[NSOrderedSet orderedSetWithSet:governanceObjectHashes] mutableCopy]; NSMutableOrderedSet *hashesToQuery = [[NSOrderedSet orderedSetWithSet:governanceObjectHashes] mutableCopy]; @@ -381,9 +376,6 @@ - (void)peer:(DSPeer *)peer hasGovernanceObjectHashes:(NSSet *)governanceObjectH } NSError *error = nil; [self.managedObjectContext save:&error]; - if (error) { - DSLog(@"[%@: %@:%d]: %@", self.chain.name, peer.host, peer.port, error); - } }]; if ([hashesToInsert count]) { [rHashes addObjectsFromArray:[hashesToInsert array]]; @@ -396,11 +388,9 @@ - (void)peer:(DSPeer *)peer hasGovernanceObjectHashes:(NSSet *)governanceObjectH } self.knownGovernanceObjectHashes = rHashes; - DSLog(@"[%@: %@:%d] -> %lu - %lu", self.chain.name, peer.host, peer.port, (unsigned long)[self.knownGovernanceObjectHashes count], (unsigned long)self.chain.totalGovernanceObjectsCount); NSUInteger countAroundNow = [self recentGovernanceObjectHashesCount]; if ([self.knownGovernanceObjectHashes count] > self.chain.totalGovernanceObjectsCount) { [self.managedObjectContext performBlockAndWait:^{ - DSLog(@"[%@: %@:%d] countAroundNow -> %lu - %lu", self.chain.name, peer.host, peer.port, (unsigned long)countAroundNow, (unsigned long)self.chain.totalGovernanceObjectsCount); if (countAroundNow > self.chain.totalGovernanceObjectsCount) { [DSGovernanceObjectHashEntity removeOldest:countAroundNow - self.chain.totalGovernanceObjectsCount onChainEntity:[self.chain chainEntityInContext:self.managedObjectContext]]; [self.managedObjectContext ds_save]; @@ -413,7 +403,6 @@ - (void)peer:(DSPeer *)peer hasGovernanceObjectHashes:(NSSet *)governanceObjectH } }]; } else if (countAroundNow == self.chain.totalGovernanceObjectsCount) { - DSLog(@"[%@: %@:%d] All governance object hashes received", self.chain.name, peer.host, peer.port); //we have all hashes, let's request objects. if (peer.governanceRequestState == DSGovernanceRequestState_GovernanceObjectHashesCountReceived) { peer.governanceRequestState = DSGovernanceRequestState_GovernanceObjects; @@ -462,9 +451,6 @@ - (void)peer:(DSPeer *)peer relayedGovernanceObject:(DSGovernanceObject *)govern - (DSGovernanceObject *)peer:(DSPeer *_Nullable)peer requestedGovernanceObject:(UInt256)governanceObjectHash { if (!([[DSOptionsManager sharedInstance] syncType] & DSSyncType_Governance)) return nil; // make sure we care about Governance objects DSGovernanceObject *proposal = [self.publishGovernanceObjects objectForKey:[NSData dataWithUInt256:governanceObjectHash]]; - if (!proposal) { - DSLog(@"[%@: %@:%d] Peer requested unknown proposal", self.chain.name, peer.host, peer.port); - } return proposal; } @@ -501,8 +487,6 @@ - (void)peer:(DSPeer *_Nullable)peer relayedGovernanceVote:(DSGovernanceVote *)g if (governanceVote.governanceObject.finishedSync) { [self finishedGovernanceVoteSyncWithPeer:peer]; } - } else { - DSLog(@"[%@: %@:%d] no parent hash", self.chain.name, peer.host, peer.port); } } @@ -515,8 +499,6 @@ - (DSGovernanceVote *)peer:(DSPeer *_Nullable)peer requestedVote:(UInt256)voteHa if (votes.count) { DSGovernanceVoteEntity *voteEntity = [votes firstObject]; vote = [voteEntity governanceVote]; - } else { - DSLog(@"[%@: %@:%d] Peer requested unknown vote", self.chain.name, peer.host, peer.port); } }]; } @@ -525,7 +507,6 @@ - (DSGovernanceVote *)peer:(DSPeer *_Nullable)peer requestedVote:(UInt256)voteHa - (void)peer:(DSPeer *)peer ignoredGovernanceSync:(DSGovernanceRequestState)governanceRequestState { [self.peerManager peerMisbehaving:peer errorMessage:@"Ignored Governance Sync"]; - DSLog(@"[%@: %@:%d] ignoredGovernanceSync -> peerManager::connect", self.chain.name, peer.host, peer.port); [self.peerManager connect]; } diff --git a/DashSync/shared/Models/Managers/Chain Managers/DSIdentitiesManager.m b/DashSync/shared/Models/Managers/Chain Managers/DSIdentitiesManager.m index 3a3171009..f74c49263 100644 --- a/DashSync/shared/Models/Managers/Chain Managers/DSIdentitiesManager.m +++ b/DashSync/shared/Models/Managers/Chain Managers/DSIdentitiesManager.m @@ -216,11 +216,6 @@ - (void)retrieveAllBlockchainIdentitiesChainStatesForWallet:(DSWallet *)wallet { completion(NO, nil, error); }); } -#if DEBUG - DSLogPrivate(@"Failure in searchIdentityByName %@", error); -#else - DSLog(@"Failure in searchIdentityByName %@", @""); -#endif }]; return call; } @@ -423,11 +418,6 @@ - (void)retrieveAllBlockchainIdentitiesChainStatesForWallet:(DSWallet *)wallet { completion(NO, nil, @[error]); }); } -#if DEBUG - DSLogPrivate(@"Failure in searchIdentitiesByNamePrefix %@", error); -#else - DSLog(@"Failure in searchIdentitiesByNamePrefix %@", @""); -#endif }]; return call; } @@ -461,11 +451,6 @@ - (void)searchIdentitiesByDPNSRegisteredBlockchainIdentityUniqueID:(NSData *)use completion(NO, nil, @[error]); }); } -#if DEBUG - DSLogPrivate(@"Failure in searchIdentitiesByDPNSRegisteredBlockchainIdentityUniqueID %@", error); -#else - DSLog(@"Failure in searchIdentitiesByDPNSRegisteredBlockchainIdentityUniqueID %@", @""); -#endif }]; } diff --git a/DashSync/shared/Models/Managers/Chain Managers/DSKeyManager.m b/DashSync/shared/Models/Managers/Chain Managers/DSKeyManager.m index 982cd11ce..dfd5d5456 100644 --- a/DashSync/shared/Models/Managers/Chain Managers/DSKeyManager.m +++ b/DashSync/shared/Models/Managers/Chain Managers/DSKeyManager.m @@ -37,7 +37,6 @@ - (instancetype)initWithChain:(DSChain *)chain { NSParameterAssert(chain); if (!(self = [super init])) return nil; _keysCache = [DSKeyManager createKeysCache]; - DSLog(@"[%@] DSKeyManager.initWithChain: %@: ", chain.name, chain); return self; } diff --git a/DashSync/shared/Models/Managers/Chain Managers/DSMasternodeManager+Mndiff.m b/DashSync/shared/Models/Managers/Chain Managers/DSMasternodeManager+Mndiff.m index 1d1955269..3648f0c5f 100644 --- a/DashSync/shared/Models/Managers/Chain Managers/DSMasternodeManager+Mndiff.m +++ b/DashSync/shared/Models/Managers/Chain Managers/DSMasternodeManager+Mndiff.m @@ -223,7 +223,6 @@ + (void)destroyProcessorCache:(MasternodeProcessorCache *)processorCache { /// - (void)processMasternodeDiffWith:(NSData *)message context:(DSMasternodeProcessorContext *)context completion:(void (^)(DSMnDiffProcessingResult *result))completion { NSAssert(self.processor, @"processMasternodeDiffMessage: No processor created"); - DSLog(@"[%@] processMasternodeDiffWith: %@", context.chain.name, context); MNListDiffResult *result = process_mnlistdiff_from_message(message.bytes, message.length, context.chain.chainType, @@ -241,7 +240,6 @@ - (void)processMasternodeDiffWith:(NSData *)message context:(DSMasternodeProcess - (void)processQRInfoWith:(NSData *)message context:(DSMasternodeProcessorContext *)context completion:(void (^)(DSQRInfoProcessingResult *result))completion { NSAssert(self.processor, @"processQRInfoMessage: No processor created"); NSAssert(self.processorCache, @"processQRInfoMessage: No processorCache created"); - DSLog(@"[%@] processQRInfoWith: %@", context.chain.name, context); QRInfoResult *result = process_qrinfo_from_message(message.bytes, message.length, context.chain.chainType, @@ -259,7 +257,6 @@ - (void)processQRInfoWith:(NSData *)message context:(DSMasternodeProcessorContex - (DSMnDiffProcessingResult *)processMasternodeDiffFromFile:(NSData *)message protocolVersion:(uint32_t)protocolVersion withContext:(DSMasternodeProcessorContext *)context { NSAssert(self.processor, @"processMasternodeDiffMessage: No processor created"); - DSLog(@"[%@] processMasternodeDiffMessage: %@", context.chain.name, context); MNListDiffResult *result = NULL; @synchronized (context) { result = process_mnlistdiff_from_message( diff --git a/DashSync/shared/Models/Managers/Chain Managers/DSMasternodeManager.m b/DashSync/shared/Models/Managers/Chain Managers/DSMasternodeManager.m index 388bbf627..08429b57d 100644 --- a/DashSync/shared/Models/Managers/Chain Managers/DSMasternodeManager.m +++ b/DashSync/shared/Models/Managers/Chain Managers/DSMasternodeManager.m @@ -253,7 +253,6 @@ - (DSMasternodeList *)loadMasternodeListAtBlockHash:(NSData *)blockHash withBloc } - (void)wipeMasternodeInfo { - DSLog(@"[%@] wipeMasternodeInfo", self.chain.name); [self clearProcessorCache]; [self.store removeAllMasternodeLists]; [self.masternodeListDiffService cleanAllLists]; @@ -268,7 +267,6 @@ - (void)wipeMasternodeInfo { - (DSQuorumSnapshot *_Nullable)quorumSnapshotForBlockHeight:(uint32_t)blockHeight { DSBlock *block = [self.chain blockAtHeight:blockHeight]; if (!block) { - DSLog(@"[%@] No block for snapshot at height: %ul: ", self.chain.name, blockHeight); return nil; } return [self.store.cachedQuorumSnapshots objectForKey:uint256_data(block.blockHash)]; @@ -287,7 +285,6 @@ - (BOOL)saveQuorumSnapshot:(DSQuorumSnapshot *)snapshot { - (NSData *_Nullable)CLSignatureForBlockHeight:(uint32_t)blockHeight { DSBlock *block = [self.chain blockAtHeight:blockHeight]; if (!block) { - DSLog(@"[%@] No block for snapshot at height: %ul: ", self.chain.name, blockHeight); return nil; } return [self.store.cachedCLSignatures objectForKey:uint256_data(block.blockHash)]; @@ -313,13 +310,11 @@ - (BOOL)saveCLSignature:(NSData *)blockHashData signatureData:(NSData *)signatur - (BOOL)saveMasternodeList:(DSMasternodeList *)masternodeList forBlockHash:(UInt256)blockHash { /// TODO: need to properly store in CoreData or wait for rust SQLite - //DSLog(@"[%@] ••• cache mnlist -> %@: %@", self.chain.name, uint256_hex(blockHash), masternodeList); [self.store.masternodeListsByBlockHash setObject:masternodeList forKey:uint256_data(blockHash)]; uint32_t lastHeight = self.lastMasternodeListBlockHeight; @synchronized (self.chain.chainManager.syncState) { self.chain.chainManager.syncState.masternodeListSyncInfo.lastBlockHeight = lastHeight; self.chain.chainManager.syncState.masternodeListSyncInfo.storedCount = self.store.masternodeListsByBlockHash.count; - DSLog(@"[%@] [DSMasternodeManager] New List Stored: %u/%lu", self.chain.name, lastHeight, self.store.masternodeListsByBlockHash.count); [self.chain.chainManager notifySyncStateChanged]; } return YES; @@ -340,13 +335,11 @@ - (DSMasternodeList *)masternodeListBeforeBlockHash:(UInt256)blockHash { // MARK: - Requesting Masternode List - (void)startSync { - DSLog(@"[%@] [DSMasternodeManager] startSync", self.chain.name); self.isSyncing = YES; [self getRecentMasternodeList]; } - (void)stopSync { - DSLog(@"[%@] [DSMasternodeManager] stopSync", self.chain.name); self.isSyncing = NO; [self cancelMasternodeListTimer]; if (self.chain.isRotatedQuorumsPresented) { @@ -356,7 +349,6 @@ - (void)stopSync { } - (void)getRecentMasternodeList { - DSLog(@"[%@] getRecentMasternodeList at tip", self.chain.name); [self.masternodeListDiffService getRecentMasternodeList]; if (self.chain.isRotatedQuorumsPresented) { [self.quorumRotationService getRecentMasternodeList]; @@ -434,7 +426,7 @@ - (DSMasternodeList *__nullable)processRequestFromFileForBlockHash:(UInt256)bloc if (!message) { return NULL; } - + MerkleBlockFinder blockFinder = ^DSMerkleBlock *(UInt256 blockHash) { return [self.chain blockForBlockHash:blockHash]; }; @@ -442,15 +434,13 @@ - (DSMasternodeList *__nullable)processRequestFromFileForBlockHash:(UInt256)bloc return blockFinder(blockHash).merkleRoot; }]; DSMnDiffProcessingResult *result = [self processMasternodeDiffFromFile:message protocolVersion:[checkpoint protocolVersion] withContext:context]; - + __block DSMerkleBlock *block = blockFinder(blockHash); if (![result isValid]) { - DSLog(@"[%@] Invalid File for block at height %u with merkleRoot %@ (foundCoinbase %@ | validQuorums %@ | rootMNListValid %@ | rootQuorumListValid %@)", self.chain.name, block.height, uint256_hex(block.merkleRoot), result.foundCoinbase?@"Yes":@"No", result.validQuorums?@"Yes":@"No", result.rootMNListValid?@"Yes":@"No", result.rootQuorumListValid?@"Yes":@"No"); return NULL; } // valid Coinbase might be false if no merkle block if (block && !result.validCoinbase) { - DSLog(@"[%@] Invalid Coinbase for block at height %u with merkleRoot %@", self.chain.name, block.height, uint256_hex(block.merkleRoot)); return NULL; } DSMasternodeList *masternodeList = result.masternodeList; @@ -458,7 +448,6 @@ - (DSMasternodeList *__nullable)processRequestFromFileForBlockHash:(UInt256)bloc addedMasternodes:result.addedMasternodes modifiedMasternodes:result.modifiedMasternodes completion:^(NSError *_Nonnull error) { - DSLog(@"[%@] MNL Saved from file", self.chain.name); }]; return masternodeList; } @@ -529,7 +518,6 @@ - (void)removeOutdatedMasternodeListsBeforeBlockHash:(UInt256)blockHash { return; } if (heightToDelete > 0 && heightToDelete != UINT32_MAX) { - DSLog(@"[%@] --> removeOldMasternodeLists (removeOutdatedMasternodeListsBeforeBlockHash): %u (%u, %u)", self.chain.name, heightToDelete, diffMasternodeList.height, qrinfoMasternodeList.height); uint32_t h = heightToDelete - 50; NSDictionary *lists = [[self.store masternodeListsByBlockHash] copy]; for (NSData *proRegTxHashData in lists) { @@ -544,10 +532,8 @@ - (void)removeOutdatedMasternodeListsBeforeBlockHash:(UInt256)blockHash { - (void)processMasternodeListDiffResult:(DSMnDiffProcessingResult *)result forPeer:(DSPeer *)peer skipPresenceInRetrieval:(BOOL)skipPresenceInRetrieval completion:(void (^)(void))completion { DSMasternodeList *masternodeList = result.masternodeList; - DSLog(@"[%@] •••• processMasternodeListDiffResult: isValid: %d validCoinbase: %d", self.chain.name, [result isValid], result.validCoinbase); if ([self.masternodeListDiffService shouldProcessDiffResult:result skipPresenceInRetrieval:skipPresenceInRetrieval]) { NSOrderedSet *neededMissingMasternodeLists = result.neededMissingMasternodeLists; - DSLog(@"[%@] •••• processMasternodeListDiffResult: missingMasternodeLists: %@", self.chain.name, [self logListSet:neededMissingMasternodeLists]); UInt256 masternodeListBlockHash = masternodeList.blockHash; NSData *masternodeListBlockHashData = uint256_data(masternodeListBlockHash); BOOL hasAwaitingQuorumValidation; @@ -566,11 +552,9 @@ - (void)processMasternodeListDiffResult:(DSMnDiffProcessingResult *)result forPe [self.store.masternodeListQueriesNeedingQuorumsValidated removeObject:masternodeListBlockHashData]; } } - DSLog(@"[%@] ••• updateStoreWithMasternodeList: %u: %@ (%@)", self.chain.name, masternodeList.height, uint256_hex(masternodeListBlockHash), uint256_reverse_hex(masternodeListBlockHash)); [self updateStoreWithProcessingResult:masternodeList result:result completion:^(NSError *error) { if ([result hasRotatedQuorumsForChain:self.chain] && !self.chain.isRotatedQuorumsPresented) { uint32_t masternodeListBlockHeight = [self heightForBlockHash:masternodeListBlockHash]; - DSLog(@"[%@] •••• processMasternodeListDiffResult: rotated quorums are presented at height %u: %@, so we'll switch into consuming qrinfo", self.chain.name, masternodeListBlockHeight, uint256_hex(masternodeListBlockHash)); self.chain.isRotatedQuorumsPresented = YES; self.rotatedQuorumsActivationHeight = masternodeListBlockHeight; if (self.isSyncing) { @@ -589,14 +573,13 @@ - (void)processMasternodeListDiffResult:(DSMnDiffProcessingResult *)result forPe } } - (void)processQRInfoResult:(DSQRInfoProcessingResult *)result forPeer:(DSPeer *)peer completion:(void (^)(void))completion { - + DSMnDiffProcessingResult *mnListDiffResultAtTip = result.mnListDiffResultAtTip; DSMnDiffProcessingResult *mnListDiffResultAtH = result.mnListDiffResultAtH; DSMnDiffProcessingResult *mnListDiffResultAtHC = result.mnListDiffResultAtHC; DSMnDiffProcessingResult *mnListDiffResultAtH2C = result.mnListDiffResultAtH2C; DSMnDiffProcessingResult *mnListDiffResultAtH3C = result.mnListDiffResultAtH3C; DSMnDiffProcessingResult *mnListDiffResultAtH4C = result.mnListDiffResultAtH4C; - DSLog(@"[%@] •••• processQRInfoResult tip: %d", self.chain.name, [mnListDiffResultAtTip isValid]); NSOrderedSet *missingMasternodeListsAtTip = mnListDiffResultAtTip.neededMissingMasternodeLists; NSOrderedSet *missingMasternodeListsAtH = mnListDiffResultAtH.neededMissingMasternodeLists; @@ -612,8 +595,7 @@ - (void)processQRInfoResult:(DSQRInfoProcessingResult *)result forPeer:(DSPeer * [missingMasternodeLists addObjectsFromArray:[missingMasternodeListsAtH2C array]]; [missingMasternodeLists addObjectsFromArray:[missingMasternodeListsAtH3C array]]; [missingMasternodeLists addObjectsFromArray:[missingMasternodeListsAtH4C array]]; - DSLog(@"[%@] •••• processQRInfoResult: missingMasternodeLists: %@", self.chain.name, [self logListSet:missingMasternodeLists]); - + DSMasternodeList *masternodeListAtTip = mnListDiffResultAtTip.masternodeList; DSMasternodeList *masternodeListAtH = mnListDiffResultAtH.masternodeList; DSMasternodeList *masternodeListAtHC = mnListDiffResultAtHC.masternodeList; @@ -689,9 +671,8 @@ - (void)processQRInfoResult:(DSQRInfoProcessingResult *)result forPeer:(DSPeer * [self.store saveQuorumSnapshot:result.snapshotAtH2C completion:^(NSError * _Nonnull error) {}]; [self.store saveQuorumSnapshot:result.snapshotAtH3C completion:^(NSError * _Nonnull error) {}]; [self.store saveQuorumSnapshot:result.snapshotAtH4C completion:^(NSError * _Nonnull error) {}]; - + for (DSMnDiffProcessingResult *diffResult in result.mnListDiffList) { - DSLog(@"[%@] •••• -> processed qrinfo +++ %u..%u %@ .. %@", self.chain.name, [self heightForBlockHash:diffResult.baseBlockHash], [self heightForBlockHash:diffResult.blockHash], uint256_hex(diffResult.baseBlockHash), uint256_hex(diffResult.blockHash)); DSMasternodeList *diffMasternodeList = diffResult.masternodeList; UInt256 diffBlockHash = diffMasternodeList.blockHash; NSData *diffBlockHashData = uint256_data(diffBlockHash); @@ -704,7 +685,7 @@ - (void)processQRInfoResult:(DSQRInfoProcessingResult *)result forPeer:(DSPeer * for (DSQuorumSnapshot *snapshot in result.snapshotList) { [self.store saveQuorumSnapshot:snapshot completion:^(NSError * _Nonnull error) {}]; } - + [self.store.activeQuorums unionOrderedSet:result.lastQuorumPerIndex]; } @@ -740,7 +721,6 @@ - (void)updateStoreWithProcessingResult:(DSMasternodeList *)masternodeList resul } - (void)peer:(DSPeer *)peer relayedMasternodeDiffMessage:(NSData *)message { - DSLog(@"[%@: %@:%d] •••• -> received mnlistdiff: %@", self.chain.name, peer.host, peer.port, uint256_hex(message.SHA256)); @synchronized (self.masternodeListDiffService) { self.masternodeListDiffService.timedOutAttempt = 0; } @@ -750,7 +730,6 @@ - (void)peer:(DSPeer *)peer relayedMasternodeDiffMessage:(NSData *)message { DSBlock *lastBlock = [self lastBlockForBlockHash:blockHash fromPeer:peer]; if (!lastBlock) { [self.masternodeListDiffService issueWithMasternodeListFromPeer:peer]; - DSLog(@"[%@] Last Block missing", self.chain.name); return UINT256_ZERO; } return lastBlock.merkleRoot; @@ -759,13 +738,10 @@ - (void)peer:(DSPeer *)peer relayedMasternodeDiffMessage:(NSData *)message { #if SAVE_MASTERNODE_DIFF_TO_FILE UInt256 baseBlockHash = result.baseBlockHash; UInt256 blockHash = result.blockHash; - DSLog(@"[%@] •••• -> processed mnlistdiff %u..%u %@ .. %@", self.chain.name, [self heightForBlockHash:baseBlockHash], [self heightForBlockHash:blockHash], uint256_hex(baseBlockHash), uint256_hex(blockHash)); NSString *fileName = [NSString stringWithFormat:@"MNL_%@_%@__%d.dat", @([self heightForBlockHash:baseBlockHash]), @([self heightForBlockHash:blockHash]), peer.version]; - DSLog(@"[%@] •-• File %@ saved", self.chain.name, fileName); [message saveToFile:fileName inDirectory:NSCachesDirectory]; #endif if (result.errorStatus) { - DSLog(@"[%@] Processing status: %ul", self.chain.name, result.errorStatus); dispatch_group_leave(self.processingGroup); return; } @@ -777,7 +753,6 @@ - (void)peer:(DSPeer *)peer relayedMasternodeDiffMessage:(NSData *)message { } - (void)peer:(DSPeer *)peer relayedQuorumRotationInfoMessage:(NSData *)message { - DSLog(@"[%@: %@:%d] •••• -> received qrinfo: %@", self.chain.name, peer.host, peer.port, uint256_hex(message.SHA256)); @synchronized (self.quorumRotationService) { self.quorumRotationService.timedOutAttempt = 0; } @@ -787,7 +762,6 @@ - (void)peer:(DSPeer *)peer relayedQuorumRotationInfoMessage:(NSData *)message { DSBlock *lastBlock = [self lastBlockForBlockHash:blockHash fromPeer:peer]; if (!lastBlock) { [self.quorumRotationService issueWithMasternodeListFromPeer:peer]; - DSLog(@"[%@] Last Block missing", self.chain.name); return UINT256_ZERO; } return lastBlock.merkleRoot; @@ -795,23 +769,13 @@ - (void)peer:(DSPeer *)peer relayedQuorumRotationInfoMessage:(NSData *)message { DSMasternodeProcessorContext *ctx = [self createDiffMessageContext:self.chain.isTestnet isFromSnapshot:NO isDIP0024:YES peer:peer merkleRootLookup:merkleRootLookup]; [self processQRInfoWith:message context:ctx completion:^(DSQRInfoProcessingResult * _Nonnull result) { if (result.errorStatus) { - DSLog(@"[%@] •••• Processing status: %u", self.chain.name, result.errorStatus); dispatch_group_leave(self.processingGroup); return; } #if SAVE_MASTERNODE_DIFF_TO_FILE UInt256 baseBlockHash = result.mnListDiffResultAtTip.baseBlockHash; UInt256 blockHash = result.mnListDiffResultAtTip.blockHash; - DSLog(@"[%@] •••• -> processed qrinfo tip %u..%u %@ .. %@", self.chain.name, [self heightForBlockHash:baseBlockHash], [self heightForBlockHash:blockHash], uint256_hex(baseBlockHash), uint256_hex(blockHash)); - DSLog(@"[%@] •••• -> processed qrinfo h %u..%u %@ .. %@", self.chain.name, [self heightForBlockHash:result.mnListDiffResultAtH.baseBlockHash], [self heightForBlockHash:result.mnListDiffResultAtH.blockHash], uint256_hex(result.mnListDiffResultAtH.baseBlockHash), uint256_hex(result.mnListDiffResultAtH.blockHash)); - DSLog(@"[%@] •••• -> processed qrinfo h-c %u..%u %@ .. %@", self.chain.name, [self heightForBlockHash:result.mnListDiffResultAtHC.baseBlockHash], [self heightForBlockHash:result.mnListDiffResultAtHC.blockHash], uint256_hex(result.mnListDiffResultAtHC.baseBlockHash), uint256_hex(result.mnListDiffResultAtHC.blockHash)); - DSLog(@"[%@] •••• -> processed qrinfo h-2c %u..%u %@ .. %@", self.chain.name, [self heightForBlockHash:result.mnListDiffResultAtH2C.baseBlockHash], [self heightForBlockHash:result.mnListDiffResultAtH2C.blockHash], uint256_hex(result.mnListDiffResultAtH2C.baseBlockHash), uint256_hex(result.mnListDiffResultAtH2C.blockHash)); - DSLog(@"[%@] •••• -> processed qrinfo h-3c %u..%u %@ .. %@", self.chain.name, [self heightForBlockHash:result.mnListDiffResultAtH3C.baseBlockHash], [self heightForBlockHash:result.mnListDiffResultAtH3C.blockHash], uint256_hex(result.mnListDiffResultAtH3C.baseBlockHash), uint256_hex(result.mnListDiffResultAtH3C.blockHash)); - if (result.extraShare) { - DSLog(@"[%@] •••• -> processed qrinfo h-4c %u..%u %@ .. %@", self.chain.name, [self heightForBlockHash:result.mnListDiffResultAtH4C.baseBlockHash], [self heightForBlockHash:result.mnListDiffResultAtH4C.blockHash], uint256_hex(result.mnListDiffResultAtH4C.baseBlockHash), uint256_hex(result.mnListDiffResultAtH4C.blockHash)); - } NSString *fileName = [NSString stringWithFormat:@"QRINFO_%@_%@__%d.dat", @([self heightForBlockHash:baseBlockHash]), @([self heightForBlockHash:blockHash]), peer.version]; - DSLog(@"[%@] •-• File %@ saved", self.chain.name, fileName); [message saveToFile:fileName inDirectory:NSCachesDirectory]; #endif [self processQRInfoResult:result forPeer:peer completion:^{ diff --git a/DashSync/shared/Models/Managers/Chain Managers/DSPeerManager.m b/DashSync/shared/Models/Managers/Chain Managers/DSPeerManager.m index 092fe6c85..9b6e59a93 100644 --- a/DashSync/shared/Models/Managers/Chain Managers/DSPeerManager.m +++ b/DashSync/shared/Models/Managers/Chain Managers/DSPeerManager.m @@ -61,12 +61,6 @@ #import #import -#define PEER_LOGGING 1 - -#if !PEER_LOGGING -#define DSLog(...) -#endif - #define TESTNET_DNS_SEEDS @[@"testnet-seed.dashdot.io"] //#define TESTNET_DNS_SEEDS @[@"35.92.167.154", @"52.12.116.10"] #define MAINNET_DNS_SEEDS @[@"dnsseed.dash.org"] @@ -223,12 +217,9 @@ + (UInt128)ipAddressFromString:(NSString *)address { if (inet_aton([address UTF8String], &addrV4) != 0) { uint32_t ip = ntohl(addrV4.s_addr); ipAddress.u32[3] = CFSwapInt32HostToBig(ip); - DSLog(@"ipAddressFromString: %@: %08x", address, ip); } else if (inet_pton(AF_INET6, [address UTF8String], &addrV6)) { //todo support IPV6 - DSLog(@"we do not yet support IPV6"); } else { - DSLog(@"invalid address"); } return ipAddress; } @@ -300,7 +291,6 @@ - (NSMutableOrderedSet *)peers { struct addrinfo hints = {0, AF_UNSPEC, SOCK_STREAM, 0, 0, 0, NULL, NULL}, *servinfo, *p; UInt128 addr = {.u32 = {0, 0, CFSwapInt32HostToBig(0xffff), 0}}; - DSLog(@"[%@] [DSPeerManager] DNS lookup %@", self.chain.name, [dnsSeeds objectAtIndex:i]); NSString *dnsSeed = [dnsSeeds objectAtIndex:i]; if (getaddrinfo([dnsSeed UTF8String], servname.UTF8String, &hints, &servinfo) == 0) { for (p = servinfo; p != NULL; p = p->ai_next) { @@ -325,8 +315,6 @@ - (NSMutableOrderedSet *)peers { } freeaddrinfo(servinfo); - } else { - DSLog(@"[%@] [DSPeerManager] failed getaddrinfo for %@", self.chain.name, dnsSeeds[i]); } }); } @@ -348,8 +336,6 @@ - (NSMutableOrderedSet *)peers { if (inet_aton([address UTF8String], &addrV4) != 0) { uint32_t ip = ntohl(addrV4.s_addr); ipAddress.u32[3] = CFSwapInt32HostToBig(ip); - } else { - DSLog(@"[%@] [DSPeerManager] invalid address", self.chain.name); } [_peers addObject:[[DSPeer alloc] initWithAddress:ipAddress port:port ? [port intValue] : self.chain.standardPort @@ -411,7 +397,6 @@ - (void)peerMisbehaving:(DSPeer *)peer errorMessage:(NSString *)errorMessage { } [peer disconnectWithError:[NSError errorWithCode:500 localizedDescriptionKey:errorMessage]]; - DSLog(@"[%@] [DSPeerManager] peerMisbehaving -> peerManager::connect", self.chain.name); [self connect]; } } @@ -442,11 +427,9 @@ - (void)sortPeers { // for (DSPeer * peer in _peers) { // DSLog(@"%@:%d lastRequestedMasternodeList(%f) lastRequestedGovernanceSync(%f)",peer.host,peer.port,peer.lastRequestedMasternodeList, peer.lastRequestedGovernanceSync); // } - DSLog(@"[%@] [DSPeerManager] peers sorted", self.chain.name); } - (void)savePeers { - DSLog(@"[%@] [DSPeerManager] save peers", self.chain.name); NSMutableSet *peers = [[self.peers.set setByAddingObjectsFromSet:self.misbehavingPeers] mutableCopy]; NSMutableSet *addrs = [NSMutableSet set]; @@ -546,7 +529,6 @@ - (void)resumeBlockchainSynchronizationOnPeers { if (self.downloadPeer) { [self updateFilterOnPeers]; } else { - DSLog(@"[%@] [DSPeerManager] resumeBlockchainSynchronizationOnPeers", self.chain.name); [self connect]; } } @@ -554,13 +536,15 @@ - (void)resumeBlockchainSynchronizationOnPeers { - (void)updateFilterOnPeers { if (self.downloadPeer.needsFilterUpdate) return; self.downloadPeer.needsFilterUpdate = YES; - DSLog(@"[%@] [DSPeerManager] filter update needed, waiting for pong", self.chain.name); + DSLogInfo(@"DSPeerManager", @"Updating Bloom filter on peers"); + NSTimeInterval filterUpdateStart = [[NSDate date] timeIntervalSince1970]; [self.downloadPeer sendPingMessageWithPongHandler:^(BOOL success) { // wait for pong so we include already sent tx if (!success) return; //we are on chainPeerManagerQueue - DSLog(@"[%@] [DSPeerManager] updating filter with newly created wallet addresses", self.chain.name); [self.transactionManager clearTransactionsBloomFilter]; + NSTimeInterval filterBuildTime = ([[NSDate date] timeIntervalSince1970] - filterUpdateStart) * 1000.0; + DSLogInfo(@"DSPeerManager", @"Bloom filter rebuild took %.2f ms", filterBuildTime); if (self.chain.lastSyncBlockHeight < self.chain.estimatedBlockHeight) { // if we're syncing, only update download peer [self.downloadPeer sendFilterloadMessage:[self.transactionManager transactionsBloomFilterForPeer:self.downloadPeer].data]; @@ -664,7 +648,6 @@ - (void)useMasternodeList:(DSMasternodeList *)masternodeList withConnectivityNon if (peers.count > 1 && peers.count < 1000) [self savePeers]; // peer relaying is complete when we receive <1000 if (connected) { - DSLog(@"[%@] [DSPeerManager] useMasternodeList -> connect", self.chain.name); [self connect]; } dispatch_async(dispatch_get_main_queue(), ^{ @@ -694,11 +677,9 @@ - (void)startBackgroundMode:(BOOL)performDisconnects { // MARK: - Connectivity - (void)connect { - DSLog(@"[%@] [DSPeerManager] connect", self.chain.name); self.desiredState = DSPeerManagerDesiredState_Connected; dispatch_async(self.networkingQueue, ^{ if ([self.chain syncsBlockchain] && ![self.chain canConstructAFilter]) { - DSLog(@"[%@] [DSPeerManager] failed to connect: check that wallet is created", self.chain.name); return; // check to make sure the wallet has been created if only are a basic wallet with no dash features } if (self.connectFailures >= MAX_CONNECT_FAILURES) self.connectFailures = 0; // this attempt is a manual retry @@ -750,9 +731,12 @@ - (void)connect { [peer setChainDelegate:self.chainManager peerDelegate:self transactionDelegate:self.transactionManager governanceDelegate:self.governanceSyncManager sporkDelegate:self.sporkManager masternodeDelegate:self.masternodeManager queue:self.networkingQueue]; peer.earliestKeyTime = earliestWalletCreationTime; - [self.mutableConnectedPeers addObject:peer]; + NSUInteger connectedCount = self.connectedPeerCount; + NSUInteger pendingCount = self.connectedPeers.count - connectedCount; + DSLogInfo(@"DSPeerManager", @"Attempting connection to %@:%u (%lu connected, %lu pending, %lu max)", + peer.host, peer.port, (unsigned long)connectedCount, (unsigned long)pendingCount + 1, (unsigned long)self.maxConnectCount); - DSLog(@"[%@: %@:%d] [DSPeerManager] Will attempt to connect to peer", self.chain.name, peer.host, peer.port); + [self.mutableConnectedPeers addObject:peer]; [peer connect]; } @@ -764,7 +748,6 @@ - (void)connect { if (peers.count == 0) { [self chainSyncStopped]; - DSLog(@"[%@] [DSPeerManager] No peers found -> SyncFailed", self.chain.name); dispatch_async(dispatch_get_main_queue(), ^{ NSError *error = [NSError errorWithCode:1 localizedDescriptionKey:@"No peers found"]; [[NSNotificationCenter defaultCenter] postNotificationName:DSChainManagerSyncFailedNotification @@ -831,7 +814,6 @@ - (void)peerConnected:(DSPeer *)peer { if (peer.timestamp > now + 2 * 60 * 60 || peer.timestamp < now - 2 * 60 * 60) peer.timestamp = now; //timestamp sanity check self.connectFailures = 0; - DSLog(@"[%@: %@:%d] [DSPeerManager] connected with lastblock %d (our last header %d - last block %d)", self.chain.name, peer.host, peer.port, peer.lastBlockHeight, self.chain.lastTerminalBlockHeight, self.chain.lastSyncBlockHeight); // drop peers that don't carry full blocks, or aren't synced yet // TODO: XXXX does this work with 0.11 pruned nodes? @@ -856,41 +838,30 @@ - (void)peerConnected:(DSPeer *)peer { } if (self.chain.estimatedBlockHeight >= peer.lastBlockHeight || self.chain.lastSyncBlockHeight >= peer.lastBlockHeight) { if (self.chain.lastSyncBlockHeight < self.chain.estimatedBlockHeight) { - DSLog(@"[%@: %@:%d] [DSPeerManager] lastSyncBlockHeight %u, estimatedBlockHeight %u", self.chain.name, peer.host, peer.port, self.chain.lastSyncBlockHeight, self.chain.estimatedBlockHeight); return; // don't get mempool yet if we're syncing } [peer sendPingMessageWithPongHandler:^(BOOL success) { if (!success) { - DSLog(@"[%@: %@:%d] [DSPeerManager] fetching mempool ping on connection failure peer", self.chain.name, peer.host, peer.port); return; } - DSLog(@"[%@: %@:%d] [DSPeerManager] fetching mempool ping on connection success peer", self.chain.name, peer.host, peer.port); [peer sendMempoolMessage:self.transactionManager.publishedTx.allKeys completion:^(BOOL success, BOOL needed, BOOL interruptedByDisconnect) { if (!success) { - if (!needed) { - DSLog(@"[%@: %@:%d] [DSPeerManager] fetching mempool message on connection not needed (already happening) peer", self.chain.name, peer.host, peer.port); - } else if (interruptedByDisconnect) { - DSLog(@"[%@: %@:%d] [DSPeerManager] fetching mempool message on connection failure peer", self.chain.name, peer.host, peer.port); - } else { - DSLog(@"[%@: %@:%d] [DSPeerManager] fetching mempool message on connection failure disconnect peer", self.chain.name, peer.host, peer.port); - } return; } - DSLog(@"[%@: %@:%d] [DSPeerManager] fetching mempool message on connection success peer", self.chain.name, peer.host, peer.port); peer.synced = YES; [self.transactionManager removeUnrelayedTransactionsFromPeer:peer]; if (!self.masternodeList) { [peer sendGetaddrMessage]; // request a list of other dash peers } - + if (self.shouldSendDsq) { [peer sendRequest:[DSSendCoinJoinQueue requestWithShouldSend:true]]; } - + dispatch_async(dispatch_get_main_queue(), ^{ - [[NSNotificationCenter defaultCenter] postNotificationName:DSTransactionManagerTransactionStatusDidChangeNotification + [[NSNotificationCenter defaultCenter] postNotificationName:DSTransactionManagerTransactionStatusDidChangeNotification object:nil userInfo:@{DSChainManagerNotificationChainKey: self.chain}]; }); @@ -951,7 +922,7 @@ - (void)peerConnected:(DSPeer *)peer { if ([self.chain syncsBlockchain] && ((lastSyncBlockHeight != lastTerminalBlockHeight) || (lastSyncBlockHeight < bestPeerLastBlockHeight))) { // start blockchain sync [self restartSyncTimeout:PROTOCOL_TIMEOUT]; - [[NSNotificationCenter defaultCenter] postNotificationName:DSTransactionManagerTransactionStatusDidChangeNotification + [[NSNotificationCenter defaultCenter] postNotificationName:DSTransactionManagerTransactionStatusDidChangeNotification object:nil userInfo:@{DSChainManagerNotificationChainKey: self.chain}]; [self.chainManager chainWillStartSyncingBlockchain:self.chain]; @@ -969,7 +940,7 @@ - (void)peerConnected:(DSPeer *)peer { } - (void)peer:(DSPeer *)peer disconnectedWithError:(NSError *)error { - DSLog(@"[%@: %@:%d] [DSPeerManager] disconnected %@%@", self.chain.name, peer.host, peer.port, (error ? @", " : @""), (error ? error : @"")); + DSLogInfo(@"DSPeerManager", @"[%@: %@:%d] disconnected%@%@", self.chain.name, peer.host, peer.port, (error ? @", " : @""), (error ? error : @"")); BOOL banned = NO; if ([error.domain isEqual:@"DashSync"]) { //} && error.code != DASH_PEER_TIMEOUT_CODE) { [self peerMisbehaving:peer errorMessage:error.localizedDescription]; // if it's protocol error other than timeout, the peer isn't following the rules @@ -985,10 +956,10 @@ - (void)peer:(DSPeer *)peer disconnectedWithError:(NSError *)error { _connected = NO; [self.chain removeEstimatedBlockHeightOfPeer:peer]; self.downloadPeer = nil; - + self.chainManager.syncState.hasDownloadPeer = NO; [self.chainManager notifySyncStateChanged]; - + if (self.connectFailures > MAX_CONNECT_FAILURES) self.connectFailures = MAX_CONNECT_FAILURES; } @@ -1008,18 +979,18 @@ - (void)peer:(DSPeer *)peer disconnectedWithError:(NSError *)error { @synchronized(self) { _peers = nil; } - if (_desiredState != DSPeerManagerDesiredState_Disconnected) - DSLog(@"[%@: %@:%d] [DSPeerManager] disconnectedWithError: max connect failures exceeded", self.chain.name, peer.host, peer.port); + if (_desiredState != DSPeerManagerDesiredState_Disconnected) { + DSLogInfo(@"DSPeerManager", @"[%@: %@:%d] max connect failures exceeded", self.chain.name, peer.host, peer.port); dispatch_async(dispatch_get_main_queue(), ^{ [[NSNotificationCenter defaultCenter] postNotificationName:DSChainManagerSyncFailedNotification object:nil userInfo:(error) ? @{@"error": error, DSChainManagerNotificationChainKey: self.chain} : @{DSChainManagerNotificationChainKey: self.chain}]; }); + } } else if (self.connectFailures < MAX_CONNECT_FAILURES) { dispatch_async(dispatch_get_main_queue(), ^{ #if TARGET_OS_IOS if ((self.desiredState == DSPeerManagerDesiredState_Connected) && [self.backgroundManager hasValidHeadersTask]) { - DSLog(@"[%@: %@:%d] [DSPeerManager] peer disconnectedWithError -> peerManager::connect", self.chain.name, peer.host, peer.port); if (!banned) [self connect]; // try connecting to another peer } #else @@ -1042,7 +1013,6 @@ - (void)peer:(DSPeer *)peer disconnectedWithError:(NSError *)error { - (void)peer:(DSPeer *)peer relayedPeers:(NSArray *)peers { if (self.masternodeList) return; - DSLog(@"[%@: %@:%d] [DSPeerManager] relayed %d peer(s)", self.chain.name, peer.host, peer.port, (int)peers.count); [self.peers addObjectsFromArray:peers]; [self.peers minusSet:self.misbehavingPeers]; [self sortPeers]; diff --git a/DashSync/shared/Models/Managers/Chain Managers/DSSporkManager.m b/DashSync/shared/Models/Managers/Chain Managers/DSSporkManager.m index bba224268..d17ee9151 100644 --- a/DashSync/shared/Models/Managers/Chain Managers/DSSporkManager.m +++ b/DashSync/shared/Models/Managers/Chain Managers/DSSporkManager.m @@ -175,7 +175,6 @@ - (void)peer:(DSPeer *_Nonnull)peer hasSporkHashes:(NSSet *_Nonnull)sporkHashes - (void)peer:(DSPeer *)peer relayedSpork:(NSData *)message { DSSpork *spork = [DSSpork sporkWithMessage:message onChain:self.chain]; - DSLog(@"[%@: %@:%d] received spork %u (%@) with message %@", self.chain.name, peer.host, peer.port, spork.identifier, spork.identifierString, message.hexString); if (!spork.isValid) { [self.peerManager peerMisbehaving:peer errorMessage:@"Spork is not valid"]; return; @@ -213,8 +212,6 @@ - (void)peer:(DSPeer *)peer relayedSpork:(NSData *)message { } [sporkEntity setAttributesFromSpork:spork withSporkHash:hashEntity]; // add new peers [self.managedObjectContext ds_save]; - } else { - DSLog(@"[%@: %@:%d] Spork was received that wasn't requested", self.chain.name, peer.host, peer.port); } } }]; diff --git a/DashSync/shared/Models/Managers/Chain Managers/DSTransactionManager.m b/DashSync/shared/Models/Managers/Chain Managers/DSTransactionManager.m index da0e5a76d..883c7f711 100644 --- a/DashSync/shared/Models/Managers/Chain Managers/DSTransactionManager.m +++ b/DashSync/shared/Models/Managers/Chain Managers/DSTransactionManager.m @@ -25,6 +25,8 @@ #import "DSTransactionManager.h" #import "DSAccount.h" +#import "DSChainSyncSpeedCalculator.h" +#import "DSLogger.h" #import "DSAuthenticationManager.h" #import "DSBlock.h" #import "DSBlockchainIdentity+Protected.h" @@ -159,12 +161,8 @@ - (UIViewController *)presentingViewController { // adds transaction to list of tx to be published, along with any unconfirmed inputs - (void)addUnconfirmedTransactionToPublishList:(DSTransaction *)transaction { if (transaction.blockHeight == TX_UNCONFIRMED) { -#if DEBUG - DSLogPrivate(@"[%@] [DSTransactionManager] add transaction to publish list %@ (%@)", self.chain.name, transaction, transaction.toData); -#else - DSLog(@"[%@] [DSTransactionManager] add transaction to publish list", self.chain.name); -#endif if (!self.publishedTx[uint256_obj(transaction.txHash)]) { + DSLogInfo(@"DSTransactionManager", @"add transaction to publish list %@", uint256_reverse_hex(transaction.txHash)); self.publishedTx[uint256_obj(transaction.txHash)] = transaction; for (DSTransactionInput *input in transaction.inputs) { UInt256 h = input.inputHash; @@ -178,11 +176,8 @@ - (void)addUnconfirmedTransactionToPublishList:(DSTransaction *)transaction { } - (void)publishTransaction:(DSTransaction *)transaction completion:(void (^)(NSError * _Nullable error))completion { -#if DEBUG - DSLogPrivate(@"[%@] [DSTransactionManager] publish transaction %@ %@", self.chain.name, transaction, transaction.toData); -#else - DSLog(@"[%@] [DSTransactionManager] publish transaction", self.chain.name); -#endif + DSLogInfo(@"DSTransactionManager", @"broadcastTransaction: We have %lu peers, adding %@ to the memory pool", + (unsigned long)self.peerManager.connectedPeerCount, uint256_reverse_hex(transaction.txHash)); if ([transaction transactionTypeRequiresInputs] && !transaction.isSigned) { if (completion) { [[DSEventManager sharedEventManager] saveEvent:@"transaction_manager:not_signed"]; @@ -213,14 +208,15 @@ - (void)publishTransaction:(DSTransaction *)transaction completion:(void (^)(NSE dispatch_async(self.chainManager.chain.networkingQueue, ^{ [self performSelector:@selector(txTimeout:) withObject:hash afterDelay:PROTOCOL_TIMEOUT]; - + dispatch_async(dispatch_get_main_queue(), ^{ [[NSNotificationCenter defaultCenter] postNotificationName:DSTransactionManagerTransactionStatusDidChangeNotification object:nil userInfo:@{DSChainManagerNotificationChainKey: self.chain, - DSTransactionManagerNotificationTransactionKey: transaction}]; + DSTransactionManagerNotificationTransactionKey: transaction}]; }); + DSLogInfo(@"DSTransactionManager", @"Sending to %lu peers", (unsigned long)peers.count); for (DSPeer *p in peers) { if (p.status != DSPeerStatus_Connected) continue; [p sendTransactionInvMessagesforTransactionHashes:txHashes txLockRequestHashes:nil]; @@ -259,15 +255,12 @@ - (void)removeUnrelayedTransactionsFromPeer:(DSPeer *)peer { [self.removeUnrelayedTransactionsLocalRequests addObject:peer.location]; // don't remove transactions until we're connected to maxConnectCount peers if (self.removeUnrelayedTransactionsLocalRequests.count < 2) { - DSLog(@"[%@] [DSTransactionManager] not removing unrelayed transactions until we have synced mempools from 2 peers %lu", self.chain.name, (unsigned long)self.peerManager.connectedPeerCount); return; } for (DSPeer *p in self.peerManager.connectedPeers) { // don't remove tx until sendMempoolMessage - DSLog(@"[%@: %@:%d] [DSTransactionManager] not removing unrelayed transactions because peer is not synced yet", self.chain.name, p.host, p.port); if (!p.synced) return; } - DSLog(@"[%@] [DSTransactionManager] removing unrelayed transactions", self.chain.name); NSMutableSet *transactionsSet = [NSMutableSet set]; NSMutableSet *specialTransactionsSet = [NSMutableSet set]; @@ -287,13 +280,7 @@ - (void)removeUnrelayedTransactionsFromPeer:(DSPeer *)peer { for (DSTransaction *transaction in transactionsSet) { if (transaction.blockHeight != TX_UNCONFIRMED) continue; hash = uint256_obj(transaction.txHash); -#if DEBUG - DSLogPrivate(@"[%@] checking published callback %@ -> %@", self.chain.name, uint256_reverse_hex(transaction.txHash), self.publishedCallback[hash] ? @"OK" : @"no callback"); -#else - DSLog(@"[%@] checking published callback -> %@", self.chain.name, self.publishedCallback[hash] ? @"OK" : @"no callback"); -#endif if (self.publishedCallback[hash] != NULL) continue; - DSLog(@"[%@] transaction relays count %lu, transaction requests count %lu", self.chain.name, (unsigned long)[self.txRelays[hash] count], (unsigned long)[self.txRequests[hash] count]); DSAccount *account = [self.chain firstAccountThatCanContainTransaction:transaction]; if (!account && ![specialTransactionsSet containsObject:transaction]) { //the following might be needed, it was in evopayments branch @@ -303,17 +290,12 @@ - (void)removeUnrelayedTransactionsFromPeer:(DSPeer *)peer { NSAssert(FALSE, @"This probably needs more implementation work, if you are here now is the time to do it."); continue; } - + BOOL updateTransaction = NO; - + if ([self.txRelays[hash] count] == 0 && [self.txRequests[hash] count] == 0) { // if this is for a transaction we sent, and it wasn't already known to be invalid, notify user of failure if (!rescan && account && [account amountSentByTransaction:transaction] > 0 && [account transactionIsValid:transaction]) { -#if DEBUG - DSLogPrivate(@"[%@] failed transaction %@", self.chain.name, transaction); -#else - DSLog(@"[%@] failed transaction ", self.chain.name); -#endif rescan = notify = YES; for (DSTransactionInput *input in transaction.inputs) { // only recommend a rescan if all inputs are confirmed @@ -321,46 +303,24 @@ - (void)removeUnrelayedTransactionsFromPeer:(DSPeer *)peer { rescan = NO; break; } - } else if (!account) { -#if DEBUG - DSLogPrivate(@"[%@] serious issue in masternode transaction %@", self.chain.name, transaction); -#else - DSLog(@"[%@] serious issue in masternode transaction ", self.chain.name); -#endif - } else { -#if DEBUG - DSLogPrivate(@"[%@] serious issue in transaction %@", self.chain.name, transaction); -#else - DSLog(@"[%@] serious issue in transaction ", self.chain.name); -#endif } -#if DEBUG - DSLogPrivate(@"[%@] removing transaction %@", self.chain.name, transaction); -#else - DSLog(@"[%@] removing transaction ", self.chain.name); -#endif [transactionsToBeRemoved addObject:transaction]; updateTransaction = YES; } else if ([self.txRelays[hash] count] < self.peerManager.maxConnectCount) { // set timestamp 0 to mark as unverified -#if DEBUG - DSLogPrivate(@"[%@] setting transaction as unverified %@", self.chain.name, transaction); -#else - DSLog(@"[%@] setting transaction as unverified ", self.chain.name); -#endif [self.chain setBlockHeight:TX_UNCONFIRMED andTimestamp:0 forTransactionHashes:@[hash]]; updateTransaction = YES; } - + if (updateTransaction) { dispatch_async(dispatch_get_main_queue(), ^{ [[NSNotificationCenter defaultCenter] postNotificationName:DSTransactionManagerTransactionStatusDidChangeNotification object:nil userInfo:@{DSChainManagerNotificationChainKey: self.chain, - DSTransactionManagerNotificationTransactionKey: transaction, - DSTransactionManagerNotificationTransactionChangesKey: @{DSTransactionManagerNotificationTransactionAcceptedStatusKey: @(NO)}}]; + DSTransactionManagerNotificationTransactionKey: transaction, + DSTransactionManagerNotificationTransactionChangesKey: @{DSTransactionManagerNotificationTransactionAcceptedStatusKey: @(NO)}}]; }); } } @@ -432,6 +392,7 @@ - (NSUInteger)relayCountForTransaction:(UInt256)txHash { } - (void)txTimeout:(NSValue *)txHash { + DSLogWarn(@"DSTransactionManager", @"tx broadcast timeout for %@", txHash); dispatch_async(dispatch_get_main_queue(), ^{ void (^callback)(NSError *error) = self.publishedCallback[txHash]; @@ -610,9 +571,9 @@ - (void)confirmProtocolRequest:(DSPaymentProtocolRequest *)protoReq forAmount:(u errorNotificationBlock(error, errorTitle, errorMessage, YES); return; } - + DSCoinControl *coinControl = nil; - + if (mixedOnly) { coinControl = [[DSCoinJoinManager sharedInstanceForChain:self.chain] selectCoinJoinUTXOs]; } @@ -662,7 +623,7 @@ - (void)confirmProtocolRequest:(DSPaymentProtocolRequest *)protoReq forAmount:(u isSecure:isSecure errorMessage:@"" localCurrency:localCurrency]; - + if (transactionCreationCompletion(tx, suggestedPrompt, amount, fee, address ? @[address] : @[], isSecure)) { CFRunLoopPerformBlock([[NSRunLoop mainRunLoop] getCFRunLoop], kCFRunLoopCommonModes, ^{ [self signAndPublishTransaction:tx createdFromProtocolRequest:protoReq fromAccount:account toAddress:address requiresSpendingAuthenticationPrompt:YES promptMessage:suggestedPrompt forAmount:amount keepAuthenticatedIfErrorAfterAuthentication:keepAuthenticatedIfErrorAfterAuthentication mixedOnly:mixedOnly requestingAdditionalInfo:additionalInfoRequest presentChallenge:challenge transactionCreationCompletion:transactionCreationCompletion signedCompletion:signedCompletion publishedCompletion:publishedCompletion requestRelayCompletion:requestRelayCompletion errorNotificationBlock:errorNotificationBlock]; @@ -774,12 +735,6 @@ - (void)publishSignedTransaction:(DSTransaction *)tx createdFromProtocolRequest: memo:nil onChain:account.wallet.chain]; -#if DEBUG - DSLogPrivate(@"[%@] posting payment to: %@", self.chain.name, protocolRequest.details.paymentURL); -#else - DSLog(@"[%@] posting payment to: ", self.chain.name); -#endif - [DSPaymentRequest postPayment:payment scheme:@"dash" to:protocolRequest.details.paymentURL @@ -917,22 +872,18 @@ - (void)confirmPaymentRequest:(DSPaymentRequest *)paymentRequest usingUserBlockc // MARK: - Mempools Sync - (void)fetchMempoolFromPeer:(DSPeer *)peer { - DSLog(@"[%@: %@:%d] [DSTransactionManager] fetching mempool from peer", self.chain.name, peer.host, peer.port); if (peer.status != DSPeerStatus_Connected) return; if ([self.chain canConstructAFilter] && (peer != self.peerManager.downloadPeer || self.transactionsBloomFilterFalsePositiveRate > BLOOM_REDUCED_FALSEPOSITIVE_RATE * 5.0)) { - DSLog(@"[%@: %@:%d] [DSTransactionManager] sending filterload message from peer", self.chain.name, peer.host, peer.port); [peer sendFilterloadMessage:[self transactionsBloomFilterForPeer:peer].data]; } [peer sendInvMessageForHashes:self.publishedTx.allKeys ofType:DSInvType_Tx]; // publish pending tx [peer sendPingMessageWithPongHandler:^(BOOL success) { if (success) { - DSLog(@"[%@: %@:%d] [DSTransactionManager] fetching mempool ping success peer", self.chain.name, peer.host, peer.port); [peer sendMempoolMessage:self.publishedTx.allKeys completion:^(BOOL success, BOOL needed, BOOL interruptedByDisconnect) { if (success) { - DSLog(@"[%@: %@:%d] [DSTransactionManager] fetching mempool message success peer", self.chain.name, peer.host, peer.port); peer.synced = YES; [self removeUnrelayedTransactionsFromPeer:peer]; if (!self.chainManager.peerManager.masternodeList) { @@ -941,14 +892,6 @@ - (void)fetchMempoolFromPeer:(DSPeer *)peer { dispatch_async(dispatch_get_main_queue(), ^{ [[NSNotificationCenter defaultCenter] postNotificationName:DSTransactionManagerTransactionStatusDidChangeNotification object:nil userInfo:@{DSChainManagerNotificationChainKey: self.chain}]; }); - } else { - if (!needed) { - DSLog(@"[%@: %@:%d] [DSTransactionManager] fetching mempool message not needed peer", self.chain.name, peer.host, peer.port); - } else if (interruptedByDisconnect) { - DSLog(@"[%@: %@:%d] [DSTransactionManager] fetching mempool message failure by disconnect peer", self.chain.name, peer.host, peer.port); - } else { - DSLog(@"[%@: %@:%d] [DSTransactionManager] fetching mempool message failure peer", self.chain.name, peer.host, peer.port); - } } if (peer == self.peerManager.downloadPeer) { [self.peerManager chainSyncStopped]; @@ -958,7 +901,6 @@ - (void)fetchMempoolFromPeer:(DSPeer *)peer { } }]; } else if (peer == self.peerManager.downloadPeer) { - DSLog(@"[%@: %@:%d] [DSTransactionManager] fetching mempool ping failure on download peer", self.chain.name, peer.host, peer.port); [self.peerManager chainSyncStopped]; dispatch_async(dispatch_get_main_queue(), ^{ @@ -967,8 +909,6 @@ - (void)fetchMempoolFromPeer:(DSPeer *)peer { object:nil userInfo:@{DSChainManagerNotificationChainKey: self.chain}]; }); - } else { - DSLog(@"[%@: %@:%d] [DSTransactionManager] fetching mempool ping failure on peer", self.chain.name, peer.host, peer.port); } }]; } @@ -1093,12 +1033,8 @@ - (void)chainWasWiped:(DSChain *)chain { //The peer is requesting a transaction that it does not know about that we are publishing - (DSTransaction *)peer:(DSPeer *)peer requestedTransaction:(UInt256)txHash { + DSLogInfo(@"DSTransactionManager", @"peer %@ requested tx %@", peer.host, uint256_reverse_hex(txHash)); NSValue *hash = uint256_obj(txHash); -#if DEBUG - DSLogPrivate(@"[%@: %@:%d] Peer requested transaction with hash %@", self.chain.name, peer.host, peer.port, hash); -#else - DSLog(@"[%@: %@:%d] Peer requested transaction with hash ", self.chain.name, peer.host, peer.port); -#endif DSTransaction *transaction = self.publishedTx[hash]; BOOL transactionIsPublished = !!transaction; NSArray *accounts = nil; @@ -1113,11 +1049,6 @@ - (DSTransaction *)peer:(DSPeer *)peer requestedTransaction:(UInt256)txHash { accounts = [self.chain accountsForTransactionHash:txHash transaction:&transaction]; } if (![accounts count]) { -#if DEBUG - DSLogPrivate(@"[%@: %@:%d] No transaction could be found on any account for hash %@", self.chain.name, peer.host, peer.port, hash); -#else - DSLog(@"[%@: %@:%d] No transaction could be found on any account for hash ", self.chain.name, peer.host, peer.port); -#endif return nil; } void (^callback)(NSError *error) = self.publishedCallback[hash]; @@ -1138,13 +1069,13 @@ - (DSTransaction *)peer:(DSPeer *)peer requestedTransaction:(UInt256)txHash { if (callback && !isTransactionValid) { [self.publishedTx removeObjectForKey:hash]; error = [NSError errorWithCode:401 localizedDescriptionKey:@"Double spend"]; - + dispatch_async(dispatch_get_main_queue(), ^{ [[NSNotificationCenter defaultCenter] postNotificationName:DSTransactionManagerTransactionStatusDidChangeNotification object:nil userInfo:@{DSChainManagerNotificationChainKey: self.chain, - DSTransactionManagerNotificationTransactionKey: transaction, - DSTransactionManagerNotificationTransactionChangesKey: @{DSTransactionManagerNotificationTransactionAcceptedStatusKey: @(NO)}}]; + DSTransactionManagerNotificationTransactionKey: transaction, + DSTransactionManagerNotificationTransactionChangesKey: @{DSTransactionManagerNotificationTransactionAcceptedStatusKey: @(NO)}}]; }); } else if (transaction) { for (DSAccount *account in accounts) { @@ -1189,21 +1120,15 @@ - (void)peer:(DSPeer *)peer hasTransactionWithHash:(UInt256)txHash { NSValue *hash = uint256_obj(txHash); BOOL syncing = (self.chain.lastSyncBlockHeight < self.chain.estimatedBlockHeight); DSTransaction *transaction = self.publishedTx[hash]; + DSLogInfo(@"DSTransactionManager", @"peer %@ has tx %@", peer.host, uint256_reverse_hex(txHash)); void (^callback)(NSError *error) = self.publishedCallback[hash]; -#if DEBUG - DSLogPrivate(@"[%@: %@:%d] has transaction %@", self.chain.name, peer.host, peer.port, hash); -#else - DSLog(@"[%@: %@:%d] has transaction %@", self.chain.name, peer.host, peer.port, @""); -#endif if (!transaction) transaction = [self.chain transactionForHash:txHash]; if (!transaction) { - DSLog(@"[%@: %@:%d] No transaction found on chain for this transaction", self.chain.name, peer.host, peer.port); return; } DSAccount *account = [self.chain firstAccountThatCanContainTransaction:transaction]; if (syncing && !account) { - DSLog(@"[%@: %@:%d] No account found for this transaction", self.chain.name, peer.host, peer.port); return; } if (![account registerTransaction:transaction saveImmediately:YES]) return; @@ -1212,11 +1137,14 @@ - (void)peer:(DSPeer *)peer hasTransactionWithHash:(UInt256)txHash { if (callback || (!syncing && ![self.txRelays[hash] containsObject:peer])) { if (!self.txRelays[hash]) self.txRelays[hash] = [NSMutableSet set]; [self.txRelays[hash] addObject:peer]; + NSUInteger relayCount = [self.txRelays[hash] count]; + DSLogInfo(@"DSTransactionManager", @"tx %@ relayed by %lu peers", uint256_reverse_hex(txHash), (unsigned long)relayCount); if (callback) [self.publishedCallback removeObjectForKey:hash]; - if ([self.txRelays[hash] count] >= self.peerManager.maxConnectCount && + if (relayCount >= self.peerManager.maxConnectCount && [self.chain transactionForHash:txHash].blockHeight == TX_UNCONFIRMED && [self.chain transactionForHash:txHash].timestamp == 0) { + DSLogInfo(@"DSTransactionManager", @"tx %@ confirmed by network (relayed by %lu peers)", uint256_reverse_hex(txHash), (unsigned long)relayCount); [self.chain setBlockHeight:TX_UNCONFIRMED andTimestamp:[NSDate timeIntervalSince1970] forTransactionHashes:@[hash]]; // set timestamp when tx is verified @@ -1241,55 +1169,35 @@ - (void)peer:(DSPeer *)peer relayedTransaction:(DSTransaction *)transaction inBl BOOL syncing = (self.chain.lastSyncBlockHeight < self.chain.estimatedBlockHeight); void (^callback)(NSError *error) = self.publishedCallback[hash]; - if (peer) { -#if DEBUG - DSLogPrivate(@"[%@: %@:%d] relayed transaction %@", self.chain.name, peer.host, peer.port, hash); -#else - DSLog(@"[%@: %@:%d] relayed transaction %@", self.chain.name, peer.host, peer.port, @""); -#endif + transaction.timestamp = block ? block.timestamp : [NSDate timeIntervalSince1970]; + NSArray *accounts = [self.chain accountsThatCanContainTransaction:transaction]; + + // Calculate transaction amount for logging (matching Android format) + int64_t txAmount = 0; + for (DSAccount *account in accounts) { + int64_t received = (int64_t)[account amountReceivedFromTransaction:transaction]; + int64_t sent = (int64_t)[account amountSentByTransaction:transaction]; + txAmount += (received - sent); + } + double txAmountDash = (double)txAmount / 100000000.0; + + if (block) { + DSLogInfo(@"DSTransactionManager", @"received tx for %.8f DASH: %@ [%lu] in block %@", + txAmountDash, uint256_reverse_hex(transaction.txHash), (unsigned long)transaction.outputs.count, uint256_reverse_hex(block.blockHash)); } else { -#if DEBUG - DSLogPrivate(@"[%@: %@:%d] accepting local transaction %@", self.chain.name, peer.host, peer.port, hash); -#else - DSLog(@"[%@: %@:%d] accepting local transaction %@", self.chain.name, peer.host, peer.port, @""); -#endif + DSLogInfo(@"DSTransactionManager", @"received tx for %.8f DASH: %@ [%lu] from peer %@", + txAmountDash, uint256_reverse_hex(transaction.txHash), (unsigned long)transaction.outputs.count, peer.host); } - transaction.timestamp = block ? block.timestamp : [NSDate timeIntervalSince1970]; - NSArray *accounts = [self.chain accountsThatCanContainTransaction:transaction]; + // Record transaction for speed calculator + [[DSChainSyncSpeedCalculator sharedInstance] recordTransactionReceived]; + NSMutableArray *accountsAcceptingTransaction = [NSMutableArray array]; NSMutableArray *accountsWithValidTransaction = [NSMutableArray array]; NSMutableArray *accountsSendingValueInTransaction = [NSMutableArray array]; if (!accounts.count) { if (![self.chain transactionHasLocalReferences:transaction]) { - if (peer) { -#if DEBUG - DSLogPrivate(@"[%@: %@:%d] no account or local references for transaction %@", self.chain.name, peer.host, peer.port, hash); -#else - DSLog(@"[%@: %@:%d] no account or local references for transaction %@", self.chain.name, peer.host, peer.port, @""); -#endif - } else { -#if DEBUG - DSLogPrivate(@"[%@: %@:%d] no account or local references for transaction %@", self.chain.name, peer.host, peer.port, hash); -#else - DSLog(@"[%@: %@:%d] no account or local references for transaction %@", self.chain.name, peer.host, peer.port, @""); -#endif - } return; - } else { - if (peer) { -#if DEBUG - DSLogPrivate(@"[%@: %@:%d] no account for transaction with local references %@", self.chain.name, peer.host, peer.port, hash); -#else - DSLog(@"[%@: %@:%d] no account for transaction with local references %@", self.chain.name, peer.host, peer.port, @""); -#endif - } else { -#if DEBUG - DSLogPrivate(@"[%@: %@:%d] no account for transaction with local references %@", self.chain.name, peer.host, peer.port, hash); -#else - DSLog(@"[%@: %@:%d] no account for transaction with local references %@", self.chain.name, peer.host, peer.port, @""); -#endif - } } } else { for (DSAccount *account in accounts) { @@ -1301,20 +1209,6 @@ - (void)peer:(DSPeer *)peer relayedTransaction:(DSTransaction *)transaction inBl if ([account amountSentByTransaction:transaction] > 0) { [accountsSendingValueInTransaction addObject:account]; } - } else { - if (peer) { -#if DEBUG - DSLogPrivate(@"[%@: %@:%d] could not register transaction %@", self.chain.name, peer.host, peer.port, hash); -#else - DSLog(@"[%@: %@:%d] could not register transaction %@", self.chain.name, peer.host, peer.port, @""); -#endif - } else { -#if DEBUG - DSLogPrivate(@"[%@: %@:%d] could not register transaction %@", self.chain.name, peer.host, peer.port, hash); -#else - DSLog(@"[%@: %@:%d] could not register transaction %@", self.chain.name, peer.host, peer.port, @""); -#endif - } } } if (accountsAcceptingTransaction.count == 0) { @@ -1480,6 +1374,7 @@ - (void)peer:(DSPeer *)peer relayedNotFoundMessagesWithTransactionHashes:(NSArra } - (void)peer:(DSPeer *)peer rejectedTransaction:(UInt256)txHash withCode:(uint8_t)code { + DSLogWarn(@"DSTransactionManager", @"peer %@ rejected tx %@ with code 0x%x", peer.host, uint256_reverse_hex(txHash), code); DSTransaction *transaction = nil; NSArray *accounts = [self.chain accountsForTransactionHash:txHash transaction:&transaction]; NSValue *hash = uint256_obj(txHash); @@ -1547,23 +1442,21 @@ - (void)peer:(DSPeer *)peer hasChainLockHashes:(NSOrderedSet *)chainLockHashes { } - (void)peer:(DSPeer *)peer relayedInstantSendTransactionLock:(DSInstantSendTransactionLock *)instantSendTransactionLock { - //NSValue *transactionHashValue = uint256_obj(instantSendTransactionLock.transactionHash); + DSLogInfo(@"DSTransactionManager", @"received InstantSend lock for tx %@ from peer %@", + uint256_reverse_hex(instantSendTransactionLock.transactionHash), peer.host); DSTransaction *transaction = nil; DSWallet *wallet = nil; DSAccount *account = [self.chain firstAccountForTransactionHash:instantSendTransactionLock.transactionHash transaction:&transaction wallet:&wallet]; if (account && transaction && transaction.instantSendReceived) { + DSLogDebug(@"DSTransactionManager", @"InstantSend lock for tx %@ already received, ignoring", + uint256_reverse_hex(instantSendTransactionLock.transactionHash)); return; //no point to retrieve the instant send lock if we already have it } BOOL verified = [instantSendTransactionLock verifySignature]; - -#if DEBUG - DSLogPrivate(@"[%@: %@:%d] relayed instant send transaction lock %@ %@", self.chain.name, peer.host, peer.port, verified ? @"Verified" : @"Not Verified", uint256_reverse_hex(instantSendTransactionLock.transactionHash)); -#else - DSLog(@"[%@: %@:%d] relayed instant send transaction lock %@ %@", self.chain.name, peer.host, peer.port, verified ? @"Verified" : @"Not Verified", @""); -#endif - + DSLogInfo(@"DSTransactionManager", @"InstantSend lock for tx %@ verified: %@", + uint256_reverse_hex(instantSendTransactionLock.transactionHash), verified ? @"YES" : @"NO"); if (account && transaction) { [transaction setInstantSendReceivedWithInstantSendLock:instantSendTransactionLock]; @@ -1586,13 +1479,11 @@ - (void)peer:(DSPeer *)peer relayedInstantSendTransactionLock:(DSInstantSendTran } - (void)checkInstantSendLocksWaitingForQuorums { - DSLog(@"[%@] Checking InstantSendLocks Waiting For Quorums", self.chain.name); for (NSData *transactionHashData in [self.instantSendLocksWaitingForQuorums copy]) { if (self.instantSendLocksWaitingForTransactions[transactionHashData]) continue; DSInstantSendTransactionLock *instantSendTransactionLock = self.instantSendLocksWaitingForQuorums[transactionHashData]; BOOL verified = [instantSendTransactionLock verifySignature]; if (verified) { - DSLogPrivate(@"[%@] Verified %@", self.chain.name, instantSendTransactionLock); [instantSendTransactionLock saveSignatureValid]; DSTransaction *transaction = nil; DSWallet *wallet = nil; @@ -1621,17 +1512,6 @@ - (void)checkInstantSendLocksWaitingForQuorums { if (!account || !transaction || transaction.confirmed) { [self.instantSendLocksWaitingForQuorums removeObjectForKey:uint256_data(instantSendTransactionLock.transactionHash)]; } -#if DEBUG - DSMasternodeList *masternodeList = nil; - DSQuorumEntry *quorum = [instantSendTransactionLock findSigningQuorumReturnMasternodeList:&masternodeList]; - if (quorum && masternodeList) { - NSArray *quorumEntries = [masternodeList quorumEntriesRankedForInstantSendRequestID:[instantSendTransactionLock requestID]]; - NSUInteger index = [quorumEntries indexOfObject:quorum]; - DSLog(@"[%@] Quorum %@ found at index %lu for masternodeList at height %lu", self.chain.name, quorum, (unsigned long)index, (unsigned long)masternodeList.height); - DSLog(@"[%@] Quorum entries are %@", self.chain.name, quorumEntries); - } - DSLog(@"[%@] Could not verify %@", self.chain.name, instantSendTransactionLock); -#endif } } } @@ -1645,7 +1525,6 @@ - (void)peer:(DSPeer *)peer relayedHeader:(DSMerkleBlock *)block { if (!self.chain.needsInitialTerminalHeadersSync && (self.chain.earliestWalletCreationTime < block.timestamp + DAY_TIME_INTERVAL * 2) && !self.chainManager.chainSynchronizationFingerprint) { - DSLog(@"[%@: %@:%d] ignoring header %@", self.chain.name, peer.host, peer.port, uint256_hex(block.blockHash)); return; } @@ -1656,14 +1535,18 @@ - (void)peer:(DSPeer *)peer relayedHeader:(DSMerkleBlock *)block { - (void)peer:(DSPeer *)peer relayedBlock:(DSMerkleBlock *)block { if (!self.chainManager.syncPhase) { - DSLog(@"[%@: %@:%d] Block was received after reset, ignoring it", self.chain.name, peer.host, peer.port); return; } + + // Record block for speed calculator + [[DSChainSyncSpeedCalculator sharedInstance] recordBlockReceived]; + [[DSChainSyncSpeedCalculator sharedInstance] updateChainHeight:self.chain.lastSyncBlockHeight + commonHeight:self.chain.lastSyncBlockHeight + targetHeight:self.chain.estimatedBlockHeight]; //DSLog(@"relayed block %@ total transactions %d %u",uint256_hex(block.blockHash), block.totalTransactions,block.timestamp); // ignore block headers that are newer than 2 days before earliestKeyTime (headers have 0 totalTransactions) if (block.totalTransactions == 0 && block.timestamp + DAY_TIME_INTERVAL * 2 > self.chain.earliestWalletCreationTime) { - DSLog(@"[%@: %@:%d] ignoring block %@", self.chain.name, peer.host, peer.port, uint256_hex(block.blockHash)); return; } @@ -1680,12 +1563,8 @@ - (void)peer:(DSPeer *)peer relayedBlock:(DSMerkleBlock *)block { // false positive rate sanity check if (self.peerManager.downloadPeer.status == DSPeerStatus_Connected && self.transactionsBloomFilterFalsePositiveRate > BLOOM_DEFAULT_FALSEPOSITIVE_RATE * 10.0) { - DSLog(@"[%@: %@:%d] bloom filter false positive rate %f too high after %d blocks, disconnecting...", self.chain.name, peer.host, - peer.port, self.transactionsBloomFilterFalsePositiveRate, self.chain.lastSyncBlockHeight + 1 - self.filterUpdateHeight); [self.peerManager.downloadPeer disconnect]; } else if (self.chain.lastSyncBlockHeight + 500 < peer.lastBlockHeight && self.transactionsBloomFilterFalsePositiveRate > BLOOM_REDUCED_FALSEPOSITIVE_RATE * 10.0) { - DSLog(@"[%@: %@:%d] bloom filter false positive rate %f too high after %d blocks, rebuilding", self.chain.name, peer.host, - peer.port, self.transactionsBloomFilterFalsePositiveRate, self.chain.lastSyncBlockHeight + 1 - self.filterUpdateHeight); [self updateTransactionsBloomFilter]; // rebuild bloom filter when it starts to degrade } } @@ -1693,7 +1572,6 @@ - (void)peer:(DSPeer *)peer relayedBlock:(DSMerkleBlock *)block { if (peer == self.peerManager.downloadPeer) [self.chainManager relayedNewItem]; if (!_bloomFilter) { // ignore potentially incomplete blocks when a filter update is pending - DSLog(@"[%@: %@:%d] ignoring block due to filter update %@", self.chain.name, peer.host, peer.port, uint256_hex(block.blockHash)); return; } @@ -1731,7 +1609,6 @@ - (void)peer:(DSPeer *)peer relayedBlock:(DSMerkleBlock *)block { [self.totalTransactionData appendUInt16:(block.height - 499) / 500]; [self.totalTransactionData appendUInt16:self.totalTransactionsSum / self.totalTransactionsQueue.count]; [self.totalTransactionData appendUInt16:self.totalTransactionsMax]; - DSLog(@"[%@: %@:%d] max total tx %d;%lu;%u", self.chain.name, peer.host, peer.port, block.height - 499, self.totalTransactionsSum / self.totalTransactionsQueue.count, self.totalTransactionsMax); } if (block.height == self.chain.lastTerminalBlockHeight) { NSString *fileName = [NSString stringWithFormat:@"MaxTransactionInfo_%@.dat", self.chain.name]; @@ -1747,9 +1624,11 @@ - (void)peer:(DSPeer *)peer relayedTooManyOrphanBlocks:(NSUInteger)orphanBlockCo } - (void)peer:(DSPeer *)peer relayedChainLock:(DSChainLock *)chainLock { + DSLogInfo(@"DSTransactionManager", @"received ChainLock for block %@ at height %u from peer %@", + uint256_reverse_hex(chainLock.blockHash), chainLock.height, peer.host); BOOL verified = [chainLock verifySignature]; - - DSLog(@"[%@: %@:%d] relayed chain lock %@", self.chain.name, peer.host, peer.port, uint256_reverse_hex(chainLock.blockHash)); + DSLogInfo(@"DSTransactionManager", @"ChainLock for block %@ verified: %@", + uint256_reverse_hex(chainLock.blockHash), verified ? @"YES" : @"NO"); DSMerkleBlock *block = [self.chain blockForBlockHash:chainLock.blockHash]; @@ -1771,13 +1650,11 @@ - (void)peer:(DSPeer *)peer relayedChainLock:(DSChainLock *)chainLock { } - (void)checkChainLocksWaitingForQuorums { - DSLog(@"[%@] Checking ChainLocks Waiting For Quorums", self.chain.name); for (NSData *chainLockHashData in [self.chainLocksWaitingForQuorums copy]) { if (self.chainLocksWaitingForMerkleBlocks[chainLockHashData]) continue; DSChainLock *chainLock = self.chainLocksWaitingForQuorums[chainLockHashData]; BOOL verified = [chainLock verifySignature]; if (verified) { - DSLog(@"[%@] Verified %@", self.chain.name, chainLock); [chainLock saveSignatureValid]; DSMerkleBlock *block = [self.chain blockForBlockHash:chainLock.blockHash]; [self.chainLocksWaitingForQuorums removeObjectForKey:chainLockHashData]; @@ -1790,22 +1667,8 @@ - (void)checkChainLocksWaitingForQuorums { dispatch_async(dispatch_get_main_queue(), ^{ [[NSNotificationCenter defaultCenter] postNotificationName:DSChainBlockWasLockedNotification object:nil userInfo:userInfo]; }); - } else { - DSLog(@"Warning: Unable to post notification due to nil chain or block (%s : %s)", self.chain == nil ? "nil" : "valid", block == nil ? "nil" : "valid"); } }); - } else { -#if DEBUG_CHAIN_LOCKS_WAITING_FOR_QUORUMS - DSMasternodeList *masternodeList = nil; - DSQuorumEntry *quorum = [chainLock findSigningQuorumReturnMasternodeList:&masternodeList]; - if (quorum && masternodeList) { - NSArray *quorumEntries = [masternodeList quorumEntriesRankedForInstantSendRequestID:[chainLock requestID]]; - NSUInteger index = [quorumEntries indexOfObject:quorum]; - DSLog(@"[%@] Quorum %@ found at index %lu for masternodeList at height %lu", self.chain.name, quorum, (unsigned long)index, (unsigned long)masternodeList.height); - DSLog(@"[%@] Quorum entries are %@", self.chain.name, quorumEntries); - } - DSLog(@"[%@] Could not verify %@", self.chain.name, chainLock); -#endif } } } @@ -1822,7 +1685,6 @@ - (void)peer:(DSPeer *)peer setFeePerByte:(uint64_t)feePerKb { if (secondFeePerByte * 2 > MIN_FEE_PER_B && secondFeePerByte * 2 <= MAX_FEE_PER_B && secondFeePerByte * 2 > self.chain.feePerByte) { - DSLog(@"[%@] increasing feePerKb to %llu based on feefilter messages from peers", self.chain.name, secondFeePerByte * 2); self.chain.feePerByte = secondFeePerByte * 2; } } diff --git a/DashSync/shared/Models/Managers/Service Managers/Auth/DSAuthenticationManager.m b/DashSync/shared/Models/Managers/Service Managers/Auth/DSAuthenticationManager.m index 4fd1e78a5..ee9bc643c 100644 --- a/DashSync/shared/Models/Managers/Service Managers/Auth/DSAuthenticationManager.m +++ b/DashSync/shared/Models/Managers/Service Managers/Auth/DSAuthenticationManager.m @@ -290,7 +290,6 @@ - (void)setPinWithCompletion:(void (^_Nullable)(BOOL success))completion { - (void)removePin { //You can only remove pin if there are no wallets if ([[DSChainsManager sharedInstance] hasAWallet]) { - DSLog(@"Tried to remove a pin, but wallets exist on device"); return; } setKeychainInt(0, BIOMETRIC_ALLOWED_AMOUNT_LEFT_KEY, NO); @@ -863,7 +862,6 @@ - (void)performAuthenticationPrecheck:(void (^)(BOOL shouldContinueAuthenticatio NSAssert(error == nil, @"Error is not handled"); const CGFloat lockoutTimeLeft = [self lockoutWaitTime]; - DSLog(@"locked out for %f more seconds", lockoutTimeLeft); if (lockoutTimeLeft > 0) { // locked out completion(NO, NO, YES, nil); diff --git a/DashSync/shared/Models/Managers/Service Managers/DSEventManager.m b/DashSync/shared/Models/Managers/Service Managers/DSEventManager.m index f9f087bb8..557d3c1b3 100644 --- a/DashSync/shared/Models/Managers/Service Managers/DSEventManager.m +++ b/DashSync/shared/Models/Managers/Service Managers/DSEventManager.m @@ -96,7 +96,6 @@ + (instancetype)sharedEventManager { NSUserDefaults *defs = [NSUserDefaults standardUserDefaults]; if (![defs boolForKey:HAS_DETERMINED_SAMPLE_GROUP]) { u_int32_t chosenNumber = arc4random_uniform(100); - DSLog(@"DSEventManager chosen number %d < %d", chosenNumber, SAMPLE_CHANCE); bool isInSample = chosenNumber < SAMPLE_CHANCE; [defs setBool:isInSample forKey:IS_IN_SAMPLE_GROUP]; [defs setBool:YES forKey:HAS_DETERMINED_SAMPLE_GROUP]; @@ -129,7 +128,6 @@ - (void)up { queue:self.myQueue usingBlock:^(NSNotification *note) { [self saveEvent:key]; - DSLog(@"DSEventManager received notification %@", note.name); #if TARGET_OS_IOS if ([note.name isEqualToString:UIApplicationDidEnterBackgroundNotification]) { [self _persistToDisk]; @@ -172,10 +170,6 @@ - (BOOL)hasAskedForPermission { } - (BOOL)shouldAskForPermission { - DSLog(@"---Sampling Metadata---"); - DSLog(@"User is in sample group: %d", [self isInSampleGroup]); - DSLog(@"User is been asked for permission: %d", [self hasAskedForPermission]); - DSLog(@"User has approved event collection: %d", [self hasAcquiredPermission]); return [self isInSampleGroup] && ![self hasAskedForPermission]; } @@ -238,14 +232,6 @@ - (void)sync { - (void)_pushEventNamed:(NSString *)evtName withAttributes:(NSDictionary *)attrs { [self.myQueue addOperationWithBlock:^{ -#if DEBUG // notify when in debug mode - [attrs enumerateKeysAndObjectsUsingBlock:^(id key, id obj, BOOL *stop) { - if (![key isKindOfClass:[NSString class]] || ![obj isKindOfClass:[NSString class]]) { - DSLog(@"warning: key or value in attributes dictionary is not of type string, " - @"will be implicitly converted"); - } - }]; -#endif NSMutableDictionary *safeDict = [NSMutableDictionary dictionary]; [attrs enumerateKeysAndObjectsUsingBlock:^(id key, id obj, BOOL *stop) { safeDict[[key description]] = [obj description]; @@ -293,7 +279,6 @@ - (void)_persistToDisk { withIntermediateDirectories:NO attributes:nil error:&error]) { - DSLog(@"Unable to create directory for storing event data: %@", error); return; } } @@ -308,9 +293,7 @@ - (void)_persistToDisk { // now write to disk NSOutputStream *os = [[NSOutputStream alloc] initToFileAtPath:fullPath append:NO]; [os open]; - if (![NSJSONSerialization writeJSONObject:self._buffer toStream:os options:0 error:&error]) { - DSLog(@"Unable to write JSON for events file: %@", error); - } + [NSJSONSerialization writeJSONObject:self._buffer toStream:os options:0 error:&error]; [os close]; // empty the buffer if we can't write JSON data, it's likely an unrecoverable error anyway @@ -397,7 +380,6 @@ - (void)_removeData { NSArray *files = [[NSFileManager defaultManager] contentsOfDirectoryAtPath:[self _unsentDataDirectory] error:&error]; if (error != nil) { - DSLog(@"Unable to read contents of event data directory: %@", error); return; // bail here as this is likely unrecoverable } @@ -405,9 +387,7 @@ - (void)_removeData { NSString *fileName = [[self _unsentDataDirectory] stringByAppendingPathComponent: [NSString stringWithFormat:@"/%@", baseName]]; NSError *removeErr = nil; - if (![[NSFileManager defaultManager] removeItemAtPath:fileName error:&removeErr]) { - DSLog(@"Unable to remove events file at path %@: %@", fileName, removeErr); - } + [[NSFileManager defaultManager] removeItemAtPath:fileName error:&removeErr]; }]; }]; } diff --git a/DashSync/shared/Models/Managers/Service Managers/DSInsightManager.m b/DashSync/shared/Models/Managers/Service Managers/DSInsightManager.m index 77ec21af0..361199b33 100644 --- a/DashSync/shared/Models/Managers/Service Managers/DSInsightManager.m +++ b/DashSync/shared/Models/Managers/Service Managers/DSInsightManager.m @@ -115,9 +115,6 @@ - (void)queryInsight:(NSString *)insightURL forBlockWithHash:(UInt256)blockHash cachePolicy:NSURLRequestReloadIgnoringCacheData timeoutInterval:20.0]; req.HTTPMethod = @"GET"; - DSLogPrivate(@"%@ GET: %@", req.URL.absoluteString, - [[NSString alloc] initWithData:req.HTTPBody - encoding:NSUTF8StringEncoding]); [[[NSURLSession sharedSession] dataTaskWithRequest:req completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) { @@ -129,7 +126,6 @@ - (void)queryInsight:(NSString *)insightURL forBlockWithHash:(UInt256)blockHash NSDictionary *json = [NSJSONSerialization JSONObjectWithData:data options:0 error:&error]; if (error) { - DSLogPrivate(@"Error decoding response %@", [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding]); completion(nil, [NSError errorWithCode:417 descriptionKey:[NSString stringWithFormat:DSLocalizedString(@"Unexpected response from %@", nil), req.URL.host]]); return; @@ -178,9 +174,6 @@ - (void)queryInsight:(NSString *)insightURL forTransactionWithHash:(UInt256)tran cachePolicy:NSURLRequestReloadIgnoringCacheData timeoutInterval:20.0]; req.HTTPMethod = @"GET"; - DSLogPrivate(@"%@ GET: %@", req.URL.absoluteString, - [[NSString alloc] initWithData:req.HTTPBody - encoding:NSUTF8StringEncoding]); [[[NSURLSession sharedSession] dataTaskWithRequest:req completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) { @@ -192,7 +185,6 @@ - (void)queryInsight:(NSString *)insightURL forTransactionWithHash:(UInt256)tran NSDictionary *json = [NSJSONSerialization JSONObjectWithData:data options:0 error:&error]; if (error) { - DSLogPrivate(@"Error decoding response %@", [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding]); completion(nil, [NSError errorWithCode:417 descriptionKey:[NSString stringWithFormat:DSLocalizedString(@"Unexpected response from %@", nil), req.URL.host]]); return; @@ -217,9 +209,6 @@ - (void)findExistingAddresses:(NSArray *)addresses forInsightURL:(NSString *)ins stringByAddingPercentEncodingWithAllowedCharacters:charset]]]; req.HTTPMethod = @"POST"; req.HTTPBody = [[args componentsJoinedByString:@"&"] dataUsingEncoding:NSUTF8StringEncoding]; - DSLogPrivate(@"%@ POST: %@", req.URL.absoluteString, - [[NSString alloc] initWithData:req.HTTPBody - encoding:NSUTF8StringEncoding]); [[[NSURLSession sharedSession] dataTaskWithRequest:req completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) { @@ -231,7 +220,6 @@ - (void)findExistingAddresses:(NSArray *)addresses forInsightURL:(NSString *)ins NSDictionary *json = [NSJSONSerialization JSONObjectWithData:data options:0 error:&error]; if (error || ![json isKindOfClass:[NSDictionary class]] || ![json objectForKey:@"items"]) { - DSLogPrivate(@"Error decoding response %@", [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding]); completion(nil, [NSError errorWithCode:417 descriptionKey:[NSString stringWithFormat:DSLocalizedString(@"Unexpected response from %@", nil), req.URL.host]]); return; @@ -271,9 +259,6 @@ - (void)utxos:(NSString *)insightURL forAddresses:(NSArray *)addresses stringByAddingPercentEncodingWithAllowedCharacters:charset]]]; req.HTTPMethod = @"POST"; req.HTTPBody = [[args componentsJoinedByString:@"&"] dataUsingEncoding:NSUTF8StringEncoding]; - DSLogPrivate(@"%@ POST: %@", req.URL.absoluteString, - [[NSString alloc] initWithData:req.HTTPBody - encoding:NSUTF8StringEncoding]); [[[NSURLSession sharedSession] dataTaskWithRequest:req completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) { @@ -288,7 +273,6 @@ - (void)utxos:(NSString *)insightURL forAddresses:(NSArray *)addresses DSUTXO o; if (error || ![json isKindOfClass:[NSArray class]]) { - DSLogPrivate(@"Error decoding response %@", [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding]); completion(nil, nil, nil, [NSError errorWithCode:417 descriptionKey:[NSString stringWithFormat:DSLocalizedString(@"Unexpected response from %@", nil), req.URL.host]]); return; diff --git a/DashSync/shared/Models/Managers/Service Managers/DSShapeshiftManager.m b/DashSync/shared/Models/Managers/Service Managers/DSShapeshiftManager.m index 5d503396d..685563ea0 100644 --- a/DashSync/shared/Models/Managers/Service Managers/DSShapeshiftManager.m +++ b/DashSync/shared/Models/Managers/Service Managers/DSShapeshiftManager.m @@ -100,7 +100,6 @@ - (NSFetchedResultsController *)fetchedResultsController { if (![aFetchedResultsController performFetch:&error]) { // Replace this implementation with code to handle the error appropriately. // abort() causes the application to generate a crash log and terminate. You should not use this function in a shipping application, although it may be useful during development. - DSLog(@"Unresolved error %@, %@", error, [error userInfo]); abort(); } @@ -130,7 +129,6 @@ - (void)controller:(NSFetchedResultsController *)controller didChangeObject:(id) newIndexPath:(NSIndexPath *)newIndexPath { if (changeType == NSFetchedResultsChangeInsert) { [(DSShapeshiftEntity *)anObject routinelyCheckStatusAtInterval:10]; - DSLogPrivate(@"BLOP %@", anObject); } } diff --git a/DashSync/shared/Models/Managers/Service Managers/DSVersionManager.m b/DashSync/shared/Models/Managers/Service Managers/DSVersionManager.m index 9c0810762..902a7b518 100644 --- a/DashSync/shared/Models/Managers/Service Managers/DSVersionManager.m +++ b/DashSync/shared/Models/Managers/Service Managers/DSVersionManager.m @@ -86,8 +86,6 @@ - (void)upgradeVersion1ExtendedKeysForWallet:(nullable DSWallet *)wallet chain:( } BOOL hasV0BIP44Data = (hasV2BIP44Data) ? NO : hasKeychainData(EXTENDED_0_PUBKEY_KEY_BIP44_V0, nil); if (!hasV2BIP44Data && (hasV1BIP44Data || hasV0BIP44Data)) { - DSLog(@"fixing public key"); - BOOL authTimeMigrated = getKeychainInt(AUTHENTICATION_TIME_VALUES_MIGRATED, nil); if (!authTimeMigrated) { //update pin unlock time diff --git a/DashSync/shared/Models/Masternode/DSMasternodeList.m b/DashSync/shared/Models/Masternode/DSMasternodeList.m index 1d388a407..33d3c7443 100644 --- a/DashSync/shared/Models/Masternode/DSMasternodeList.m +++ b/DashSync/shared/Models/Masternode/DSMasternodeList.m @@ -125,7 +125,6 @@ - (NSArray *)providerTxOrderedHashes { NSMutableArray *simplifiedMasternodeListByRegistrationTransactionHashHashes = [NSMutableArray array]; uint32_t height = blockHeightLookup(self.blockHash); if (height == UINT32_MAX) { - DSLog(@"Block height lookup queried an unknown block %@", uint256_hex(self.blockHash)); return nil; //this should never happen } for (NSData *proTxHash in proTxHashes) { @@ -142,7 +141,6 @@ - (NSArray *)providerTxOrderedHashes { NSMutableDictionary *simplifiedMasternodeListByRegistrationTransactionHashHashes = [NSMutableDictionary dictionary]; uint32_t height = blockHeightLookup(self.blockHash); if (height == UINT32_MAX) { - DSLog(@"Block height lookup queried an unknown block %@", uint256_hex(self.blockHash)); return nil; //this should never happen } for (NSData *proTxHash in proTxHashes) { @@ -241,7 +239,6 @@ - (NSArray *)scoresForQuorumModifier:(UInt256)quorumModifier atBlockHeight:(uint blockHeight:^uint32_t(UInt256 blockHash) { DSMerkleBlock *block = [self.chain blockForBlockHash:blockHash]; if (!block) { - DSLog(@"Unknown block %@", uint256_reverse_hex(blockHash)); NSAssert(block, @"block should be known"); } return block.height; @@ -416,7 +413,7 @@ - (void)saveToJsonFile:(NSString *)fileName { uint256_hex(entry.quorumVerificationVectorHash), uint768_hex(entry.quorumThresholdSignature), uint768_hex(entry.allCommitmentAggregatedSignature)]; - + [json_quorums addObject:json_quorum]; } } @@ -425,7 +422,6 @@ - (void)saveToJsonFile:(NSString *)fileName { NSString *list = [NSString stringWithFormat:@"{\n\"blockHash\":\"%@\", \n\"knownHeight\":%@, \n\"masternodeMerkleRoot\":\"%@\", \n\"quorumMerkleRoot\":\"%@\", \n%@, \n%@\n}", uint256_hex(self.blockHash), @(self.knownHeight), uint256_hex(self.masternodeMerkleRoot), uint256_hex(self.quorumMerkleRoot), nodes, quorums]; NSData* data = [list dataUsingEncoding:NSUTF8StringEncoding allowLossyConversion:NO]; [data saveToFile:fileName inDirectory:NSCachesDirectory]; - DSLog(@"•-• File %@ saved", fileName); } - (void)saveToJsonFileExtended:(NSString *)fileName { @@ -499,7 +495,6 @@ - (void)saveToJsonFileExtended:(NSString *)fileName { NSString *list = [NSString stringWithFormat:@"{\n\"blockHash\":\"%@\", \n\"knownHeight\":%@, \n\"masternodeMerkleRoot\":\"%@\", \n\"quorumMerkleRoot\":\"%@\", \n%@, \n%@\n}", uint256_hex(self.blockHash), @(self.knownHeight), uint256_hex(self.masternodeMerkleRoot), uint256_hex(self.quorumMerkleRoot), nodes, quorums]; NSData* data = [list dataUsingEncoding:NSUTF8StringEncoding allowLossyConversion:NO]; [data saveToFile:fileName inDirectory:NSCachesDirectory]; - DSLog(@"•-• File %@ saved", fileName); } - (NSString *)description { diff --git a/DashSync/shared/Models/Masternode/DSMasternodeListDiffService.m b/DashSync/shared/Models/Masternode/DSMasternodeListDiffService.m index 8bb336468..e9194a8e9 100644 --- a/DashSync/shared/Models/Masternode/DSMasternodeListDiffService.m +++ b/DashSync/shared/Models/Masternode/DSMasternodeListDiffService.m @@ -48,7 +48,6 @@ - (void)composeMasternodeListRequest:(NSOrderedSet *)list { [self requestMasternodeListDiff:previousBlockHash forBlockHash:blockHash]; } } else { - DSLog(@"[%@] Missing block (%@)", self.chain.name, blockHashData.hexString); [self removeFromRetrievalQueue:blockHashData]; } } @@ -58,10 +57,8 @@ - (void)requestMasternodeListDiff:(UInt256)previousBlockHash forBlockHash:(UInt2 DSGetMNListDiffRequest *request = [DSGetMNListDiffRequest requestWithBaseBlockHash:previousBlockHash blockHash:blockHash]; DSMasternodeListRequest *matchedRequest = [self requestInRetrievalFor:previousBlockHash blockHash:blockHash]; if (matchedRequest) { - DSLog(@"[%@] •••• mnlistdiff request with such a range already in retrieval: %u..%u %@ .. %@", self.chain.name, [self.store heightForBlockHash:previousBlockHash], [self.store heightForBlockHash:blockHash], uint256_hex(previousBlockHash), uint256_hex(blockHash)); return; } - DSLog(@"[%@] •••• requestMasternodeListDiff: %u..%u %@ .. %@", self.chain.name, [self.store heightForBlockHash:previousBlockHash], [self.store heightForBlockHash:blockHash], uint256_hex(previousBlockHash), uint256_hex(blockHash)); [self sendMasternodeListRequest:request]; } diff --git a/DashSync/shared/Models/Masternode/DSMasternodeListService.m b/DashSync/shared/Models/Masternode/DSMasternodeListService.m index 17c7dd746..bdba784a6 100644 --- a/DashSync/shared/Models/Masternode/DSMasternodeListService.m +++ b/DashSync/shared/Models/Masternode/DSMasternodeListService.m @@ -78,7 +78,6 @@ - (void)startTimeOutObserver { NSMutableSet *leftToGet = [requestsInRetrieval mutableCopy]; [leftToGet intersectSet:requestsInRetrieval2]; if ((masternodeListCount == [self.store knownMasternodeListsCount]) && [requestsInRetrieval isEqualToSet:leftToGet]) { - DSLog(@"[%@] %@ TimedOut", self.chain.name, self); self.timedOutAttempt++; [self disconnectFromDownloadPeer]; [self cleanRequestsInRetrieval]; @@ -138,7 +137,6 @@ - (void)getRecentMasternodeList { DSMerkleBlock *merkleBlock = [self.chain blockFromChainTip:0]; if (!merkleBlock) { // sometimes it happens while rescan - DSLog(@"[%@] getRecentMasternodeList: (no block exist) for tip", self.chain.name); return; } UInt256 merkleBlockHash = merkleBlock.blockHash; @@ -147,7 +145,6 @@ - (void)getRecentMasternodeList { return; } if ([self.store addBlockToValidationQueue:merkleBlock]) { - DSLog(@"[%@] MasternodeListService.Getting masternode list %u", self.chain.name, merkleBlock.height); NSData *merkleBlockHashData = uint256_data(merkleBlockHash); BOOL emptyRequestQueue = ![self retrievalQueueCount]; [self addToRetrievalQueue:merkleBlockHashData]; @@ -224,9 +221,6 @@ - (BOOL)shouldProcessDiffResult:(DSMnDiffProcessingResult *)diffResult skipPrese return NO; } BOOL isValid = [diffResult isTotallyValid]; - if (!isValid) { - DSLog(@"[%@] Invalid diff result: %@", self.chain.name, diffResult.debugDescription); - } return isValid; } @@ -262,7 +256,6 @@ - (void)removeFromRetrievalQueue:(NSData *)masternodeBlockHashData { @synchronized (self.chain.chainManager.syncState) { self.chain.chainManager.syncState.masternodeListSyncInfo.retrievalQueueCount = count; self.chain.chainManager.syncState.masternodeListSyncInfo.retrievalQueueMaxAmount = (uint32_t) self.retrievalQueueMaxAmount; - DSLog(@"[%@] Masternode list queue updated: %f/%lu", self.chain.name, count, self.retrievalQueueMaxAmount); [self.chain.chainManager notifySyncStateChanged]; } } @@ -276,7 +269,6 @@ - (void)cleanListsRetrievalQueue { @synchronized (self.chain.chainManager.syncState) { self.chain.chainManager.syncState.masternodeListSyncInfo.retrievalQueueCount = 0; self.chain.chainManager.syncState.masternodeListSyncInfo.retrievalQueueMaxAmount = (uint32_t) self.retrievalQueueMaxAmount; - DSLog(@"[%@] Masternode list queue cleaned up: 0/%lu", self.chain.name, self.retrievalQueueMaxAmount); [self.chain.chainManager notifySyncStateChanged]; } } @@ -304,19 +296,16 @@ - (void)updateMasternodeRetrievalQueue { @synchronized (self.chain.chainManager.syncState) { self.chain.chainManager.syncState.masternodeListSyncInfo.retrievalQueueCount = (uint32_t) currentCount; self.chain.chainManager.syncState.masternodeListSyncInfo.retrievalQueueMaxAmount = (uint32_t) self.retrievalQueueMaxAmount; - DSLog(@"[%@] Masternode list queue updated: %lu/%lu", self.chain.name, currentCount, self.retrievalQueueMaxAmount); [self.chain.chainManager notifySyncStateChanged]; } } - (void)fetchMasternodeListsToRetrieve:(void (^)(NSOrderedSet *listsToRetrieve))completion { if (![self retrievalQueueCount]) { - DSLog(@"[%@] No masternode lists in retrieval: %@", self.chain.name, self); [self.delegate masternodeListSerivceEmptiedRetrievalQueue:self]; return; } if ([self.requestsInRetrieval count]) { - DSLog(@"[%@] A masternode list is already in retrieval: %@", self.chain.name, self); return; } BOOL peerIsDisconnected; @@ -348,19 +337,6 @@ - (DSMasternodeListRequest*__nullable)requestInRetrievalFor:(UInt256)baseBlockHa - (BOOL)removeRequestInRetrievalForBaseBlockHash:(UInt256)baseBlockHash blockHash:(UInt256)blockHash { DSMasternodeListRequest *matchedRequest = [self requestInRetrievalFor:baseBlockHash blockHash:blockHash]; if (!matchedRequest) { - #if DEBUG - NSSet *requestsInRetrieval; - @synchronized (self.requestsInRetrieval) { - requestsInRetrieval = [self.requestsInRetrieval copy]; - } - NSMutableArray *requestsInRetrievalStrings = [NSMutableArray array]; - for (DSMasternodeListRequest *requestInRetrieval in requestsInRetrieval) { - [requestsInRetrievalStrings addObject:[requestInRetrieval logWithBlockHeightLookup:^uint32_t(UInt256 blockHash) { - return [self.store heightForBlockHash:blockHash]; - }]]; - } - DSLog(@"[%@] A masternode list (%@ .. %@) was received that is not set to be retrieved (%@)", self.chain.name, uint256_hex(baseBlockHash), uint256_hex(blockHash), [requestsInRetrievalStrings componentsJoinedByString:@", "]); - #endif /* DEBUG */ return NO; } @synchronized (self.requestsInRetrieval) { @@ -381,7 +357,6 @@ - (void)issueWithMasternodeListFromPeer:(DSPeer *)peer { [self.peerManager peerMisbehaving:peer errorMessage:@"Issue with Deterministic Masternode list"]; NSArray *faultyPeers = [[NSUserDefaults standardUserDefaults] arrayForKey:CHAIN_FAULTY_DML_MASTERNODE_PEERS]; if (faultyPeers.count >= MAX_FAULTY_DML_PEERS) { - DSLog(@"[%@] Exceeded max failures for masternode list, starting from scratch", self.chain.name); //no need to remove local masternodes [self cleanListsRetrievalQueue]; [self.store deleteAllOnChain]; diff --git a/DashSync/shared/Models/Masternode/DSMasternodeListStore.m b/DashSync/shared/Models/Masternode/DSMasternodeListStore.m index 3211e1729..b03fc3617 100644 --- a/DashSync/shared/Models/Masternode/DSMasternodeListStore.m +++ b/DashSync/shared/Models/Masternode/DSMasternodeListStore.m @@ -155,7 +155,6 @@ - (UInt256)closestKnownBlockHashForBlockHash:(UInt256)blockHash { } - (void)deleteAllOnChain { - DSLog(@"[%@] DSMasternodeListStore.deleteAllOnChain", self.chain.name); [self.managedObjectContext performBlockAndWait:^{ DSChainEntity *chainEntity = [self.chain chainEntityInContext:self.managedObjectContext]; [DSSimplifiedMasternodeEntryEntity deleteAllOnChainEntity:chainEntity]; @@ -172,7 +171,6 @@ - (void)deleteEmptyMasternodeLists { [fetchRequest setPredicate:[NSPredicate predicateWithFormat:@"block.chain == %@ && masternodes.@count == 0", [self.chain chainEntityInContext:self.managedObjectContext]]]; NSArray *masternodeListEntities = [DSMasternodeListEntity fetchObjects:fetchRequest inContext:self.managedObjectContext]; for (DSMasternodeListEntity *entity in [masternodeListEntities copy]) { - DSLog(@"[%@] DSMasternodeListStore.deleteEmptyMasternodeLists: %@", self.chain.name, entity); [self.managedObjectContext deleteObject:entity]; } [self.managedObjectContext ds_save]; @@ -237,7 +235,6 @@ - (DSMasternodeList *)loadMasternodeListAtBlockHash:(NSData *)blockHash withBloc NSMutableDictionary *quorumEntryPool = [NSMutableDictionary dictionary]; masternodeList = [masternodeListEntity masternodeListWithSimplifiedMasternodeEntryPool:[simplifiedMasternodeEntryPool copy] quorumEntryPool:quorumEntryPool withBlockHeightLookup:blockHeightLookup]; if (masternodeList) { - DSLog(@"[%@] ••• addMasternodeList (loadMasternodeListAtBlockHash) -> %@: %@", self.chain.name, blockHash.hexString, masternodeList); double count; @synchronized (self.masternodeListsByBlockHash) { [self.masternodeListsByBlockHash setObject:masternodeList forKey:blockHash]; @@ -252,7 +249,6 @@ - (DSMasternodeList *)loadMasternodeListAtBlockHash:(NSData *)blockHash withBloc [self.chain.chainManager notifySyncStateChanged]; [self.chain.chainManager notifySyncStateChanged]; } - DSLog(@"[%@] Loading Masternode List at height %u for blockHash %@ with %lu entries", self.chain.name, masternodeList.height, uint256_hex(masternodeList.blockHash), (unsigned long)masternodeList.simplifiedMasternodeEntries.count); } }]; dispatch_group_leave(self.savingGroup); @@ -285,7 +281,6 @@ - (DSMasternodeList *)loadMasternodeListsWithBlockHeightLookup:(BlockHeightFinde [self.cachedBlockHashHeights setObject:@(masternodeListEntity.block.height) forKey:uint256_data(masternodeList.blockHash)]; [simplifiedMasternodeEntryPool addEntriesFromDictionary:masternodeList.simplifiedMasternodeListDictionaryByReversedRegistrationTransactionHash]; [quorumEntryPool addEntriesFromDictionary:masternodeList.quorums]; - DSLog(@"[%@] Loading Masternode List at height %u for blockHash %@ with %lu entries", self.chain.name, masternodeList.height, uint256_hex(masternodeList.blockHash), (unsigned long)masternodeList.simplifiedMasternodeEntries.count); if (i == masternodeListEntities.count - 1) { currentList = masternodeList; } @@ -336,7 +331,6 @@ - (DSMasternodeList *)masternodeListForBlockHash:(UInt256)blockHash withBlockHei } - (void)removeAllMasternodeLists { - DSLog(@"[%@] ••• removeAllMasternodeLists -> ", self.chain.name); @synchronized (self.masternodeListsByBlockHash) { [self.masternodeListsByBlockHash removeAllObjects]; } @@ -347,7 +341,6 @@ - (void)removeAllMasternodeLists { @synchronized (self.chain.chainManager.syncState) { self.chain.chainManager.syncState.masternodeListSyncInfo.lastBlockHeight = UINT32_MAX; self.chain.chainManager.syncState.masternodeListSyncInfo.storedCount = 0; - DSLog(@"[%@] [DSMasternodeManager] All List Removed: %u/%u", self.chain.name, UINT32_MAX, 0); [self.chain.chainManager notifySyncStateChanged]; } } @@ -361,8 +354,6 @@ - (void)removeOldMasternodeLists:(uint32_t)lastBlockHeight { NSArray *masternodeListEntities = [DSMasternodeListEntity objectsInContext:self.managedObjectContext matching:@"block.height < %@ && block.blockHash IN %@ && (block.usedByQuorums.@count == 0)", @(lastBlockHeight - 50), masternodeListBlockHashes]; BOOL removedItems = !!masternodeListEntities.count; for (DSMasternodeListEntity *masternodeListEntity in [masternodeListEntities copy]) { - DSLog(@"[%@] Removing masternodeList at height %u", self.chain.name, masternodeListEntity.block.height); - DSLog(@"[%@] quorums are %@", self.chain.name, masternodeListEntity.block.usedByQuorums); //A quorum is on a block that can only have one masternode list. //A block can have one quorum of each type. //A quorum references the masternode list by it's block @@ -409,7 +400,6 @@ - (void)removeOldSimplifiedMasternodeEntries { BOOL deletedSomething = FALSE; NSUInteger deletionCount = 0; for (DSSimplifiedMasternodeEntryEntity *simplifiedMasternodeEntryEntity in [simplifiedMasternodeEntryEntities copy]) { - DSLog(@"[%@] removeOldSimplifiedMasternodeEntries: %@", self.chain.name, simplifiedMasternodeEntryEntity.providerRegistrationTransactionHash.hexString); [self.managedObjectContext deleteObject:simplifiedMasternodeEntryEntity]; deletedSomething = TRUE; deletionCount++; @@ -472,9 +462,6 @@ - (void)saveMasternodeList:(DSMasternodeList *)masternodeList addedMasternodes:( completion:^(NSError *error) { self.masternodeListCurrentlyBeingSavedCount--; dispatch_group_leave(self.savingGroup); - if (error) { - DSLog(@"[%@] Finished saving MNL at height %u with error: %@", self.chain.name, [self heightForBlockHash:masternodeList.blockHash], error.description); - } completion(error); }]; } @@ -490,7 +477,6 @@ - (void)saveQuorumSnapshot:(DSQuorumSnapshot *)quorumSnapshot if ([self.cachedQuorumSnapshots objectForKey:blockHashData]) { return; } - DSLog(@"[%@] Queued saving Quorum Snapshot for: %u: %@", self.chain.name, blockHeight, uint256_hex(blockHash)); [self.cachedQuorumSnapshots setObject:quorumSnapshot forKey:blockHashData]; dispatch_group_enter(self.savingGroup); NSManagedObjectContext *context = self.managedObjectContext; @@ -508,11 +494,9 @@ - (void)saveQuorumSnapshot:(DSQuorumSnapshot *)quorumSnapshot if (createUnknownBlocks) { merkleBlockEntity = [DSMerkleBlockEntity createMerkleBlockEntityForBlockHash:blockHash blockHeight:blockHeight chainEntity:chainEntity inContext:context]; } else { - DSLog(@"[%@] Merkle block should exist for block hash %@", self.chain.name, blockHashData.hexString); error = [NSError errorWithCode:600 localizedDescriptionKey:@"Merkle block should exist"]; } } else if (merkleBlockEntity.quorumSnapshot) { - DSLog(@"[%@] Merkle block already have quorum snapshot for %@", self.chain.name, blockHashData.hexString); error = [NSError errorWithCode:600 localizedDescriptionKey:@"Merkle block should not have a quorum snapshot already"]; // DGaF // skip we're just processing saved snapshot //[merkleBlockEntity.quorumSnapshot updateAttributesFromPotentialQuorumSnapshot:quorumSnapshot onBlock:merkleBlockEntity] @@ -522,7 +506,6 @@ - (void)saveQuorumSnapshot:(DSQuorumSnapshot *)quorumSnapshot } else { DSQuorumSnapshotEntity *quorumSnapshotEntity = [DSQuorumSnapshotEntity managedObjectInBlockedContext:context]; [quorumSnapshotEntity updateAttributesFromPotentialQuorumSnapshot:quorumSnapshot onBlock:merkleBlockEntity]; - DSLog(@"[%@] Finished saving Quorum Snapshot at height %u: %@", self.chain.name, blockHeight, uint256_hex(blockHash)); } error = [context ds_save]; if (completion) { @@ -539,7 +522,6 @@ + (void)saveMasternodeList:(DSMasternodeList *)masternodeList createUnknownBlocks:(BOOL)createUnknownBlocks inContext:(NSManagedObjectContext *)context completion:(void (^)(NSError *error))completion { - DSLog(@"[%@] Queued saving MNL at height %u: %@", chain.name, masternodeList.height, uint256_hex(masternodeList.blockHash)); [context performBlockAndWait:^{ //masternodes @autoreleasepool { @@ -558,7 +540,6 @@ + (void)saveMasternodeList:(DSMasternodeList *)masternodeList if (createUnknownBlocks) { merkleBlockEntity = [DSMerkleBlockEntity createMerkleBlockEntityForBlockHash:mnlBlockHash blockHeight:mnlHeight chainEntity:chainEntity inContext:context]; } else { - DSLog(@"[%@] Merkle block should exist for block hash %@", chain.name, mnlBlockHashData); error = [NSError errorWithCode:600 localizedDescriptionKey:@"Merkle block should exist"]; } } else if (merkleBlockEntity.masternodeList) { @@ -623,7 +604,6 @@ + (void)saveMasternodeList:(DSMasternodeList *)masternodeList } } chainEntity.baseBlockHash = mnlBlockHashData; - DSLog(@"[%@] Finished merging MNL at height %u: %@", chain.name, mnlHeight, mnlBlockHashData.hexString); } else if (!error) { DSMasternodeListEntity *masternodeListEntity = [DSMasternodeListEntity managedObjectInBlockedContext:context]; @@ -682,7 +662,6 @@ + (void)saveMasternodeList:(DSMasternodeList *)masternodeList } } chainEntity.baseBlockHash = mnlBlockHashData; - DSLog(@"[%@] Finished saving MNL at height %u", chain.name, mnlHeight); } else { chainEntity.baseBlockHash = uint256_data(chain.genesisHash); [DSLocalMasternodeEntity deleteAllOnChainEntity:chainEntity]; @@ -719,11 +698,9 @@ - (DSQuorumEntry *)quorumEntryForPlatformHavingQuorumHash:(UInt256)quorumHash fo masternodeList = [self masternodeListBeforeBlockHash:block.blockHash]; } if (!masternodeList) { - DSLog(@"[%@] No masternode list found yet", self.chain.name); return nil; } if (block.height - masternodeList.height > 32) { - DSLog(@"[%@] Masternode list is too old", self.chain.name); return nil; } DSQuorumEntry *quorumEntry = [masternodeList quorumEntryForPlatformWithQuorumHash:quorumHash]; @@ -747,12 +724,9 @@ - (DSQuorumEntry *)quorumEntryForLockRequestID:(UInt256)requestID } DSMasternodeList *masternodeList = [self masternodeListBeforeBlockHash:blockHash]; if (!masternodeList) { - DSLog(@"[%@] No masternode list found yet", self.chain.name); return nil; } if (merkleBlock.height - masternodeList.height > offset) { - DSLog(@"[%@] Masternode list for is too old (age: %d masternodeList height %d merkle block height %d)", self.chain.name, - merkleBlock.height - masternodeList.height, masternodeList.height, merkleBlock.height); return nil; } @@ -778,7 +752,6 @@ - (BOOL)addBlockToValidationQueue:(DSMerkleBlock *)merkleBlock { //DSLog(@"addBlockToValidationQueue: %u:%@", merkleBlock.height, uint256_hex(merkleBlockHash)); NSData *merkleBlockHashData = uint256_data(merkleBlockHash); if ([self hasMasternodeListAt:merkleBlockHashData]) { - DSLog(@"[%@] Already have that masternode list (or in stub) %u", self.chain.name, merkleBlock.height); return NO; } self.lastQueriedBlockHash = merkleBlockHash; diff --git a/DashSync/shared/Models/Masternode/DSMasternodeProcessorContext.m b/DashSync/shared/Models/Masternode/DSMasternodeProcessorContext.m index 1e53060b1..8c6bff738 100644 --- a/DashSync/shared/Models/Masternode/DSMasternodeProcessorContext.m +++ b/DashSync/shared/Models/Masternode/DSMasternodeProcessorContext.m @@ -71,7 +71,6 @@ - (ProcessingError)shouldProcessDiffWithRange:(UInt256)baseBlockHash blockHash:( uint32_t baseBlockHeight = [self blockHeightForBlockHash:baseBlockHash]; uint32_t blockHeight = [self blockHeightForBlockHash:blockHash]; if (blockHeight == UINT32_MAX) { - DSLog(@"•••• shouldProcessDiffWithRange: unknown blockHash: %u..%u %@ .. %@", baseBlockHeight, blockHeight, uint256_reverse_hex(baseBlockHash), uint256_reverse_hex(blockHash)); return ProcessingError_UnknownBlockHash; } DSChain *chain = self.chain; @@ -79,7 +78,6 @@ - (ProcessingError)shouldProcessDiffWithRange:(UInt256)baseBlockHash blockHash:( DSMasternodeListService *service = self.isDIP0024 ? manager.quorumRotationService : manager.masternodeListDiffService; BOOL hasRemovedFromRetrieval = [service removeRequestInRetrievalForBaseBlockHash:baseBlockHash blockHash:blockHash]; if (!hasRemovedFromRetrieval) { - DSLog(@"•••• shouldProcessDiffWithRange: persist in retrieval: %u..%u %@ .. %@", baseBlockHeight, blockHeight, uint256_reverse_hex(baseBlockHash), uint256_reverse_hex(blockHash)); return ProcessingError_PersistInRetrieval; } NSData *blockHashData = uint256_data(blockHash); @@ -89,7 +87,6 @@ - (ProcessingError)shouldProcessDiffWithRange:(UInt256)baseBlockHash blockHash:( BOOL noNeedToVerifyQuorums = !(needToVerifyRotatedQuorums || needToVerifyNonRotatedQuorums); BOOL hasLocallyStored = [manager.store hasMasternodeListAt:blockHashData]; if (hasLocallyStored && noNeedToVerifyQuorums) { - DSLog(@"•••• shouldProcessDiffWithRange: already persist: %u: %@ needToVerifyRotatedQuorums: %d needToVerifyNonRotatedQuorums: %d", blockHeight, uint256_reverse_hex(blockHash), needToVerifyRotatedQuorums, needToVerifyNonRotatedQuorums); [service removeFromRetrievalQueue:blockHashData]; return ProcessingError_LocallyStored; } @@ -97,7 +94,6 @@ - (ProcessingError)shouldProcessDiffWithRange:(UInt256)baseBlockHash blockHash:( if (!baseMasternodeList && !uint256_eq(chain.genesisHash, baseBlockHash) && uint256_is_not_zero(baseBlockHash)) { // this could have been deleted in the meantime, if so rerequest [service issueWithMasternodeListFromPeer:self.peer]; - DSLog(@"•••• No base masternode list at: %d: %@", baseBlockHeight, uint256_reverse_hex(baseBlockHash)); return ProcessingError_HasNoBaseBlockHash; } return ProcessingError_None; diff --git a/DashSync/shared/Models/Masternode/DSMnDiffProcessingResult.m b/DashSync/shared/Models/Masternode/DSMnDiffProcessingResult.m index 60b2d443e..0eb7edeee 100644 --- a/DashSync/shared/Models/Masternode/DSMnDiffProcessingResult.m +++ b/DashSync/shared/Models/Masternode/DSMnDiffProcessingResult.m @@ -31,7 +31,6 @@ + (instancetype)processingResultWith:(MNListDiffResult *)result onChain:(DSChain return processingResult; } if (result->masternode_list == NULL) { - DSLog(@"[%@] DSQRInfoProcessingResult.error.unknown", chain.name); processingResult.errorStatus = ProcessingError_ParseError; return processingResult; } diff --git a/DashSync/shared/Models/Masternode/DSQRInfoProcessingResult.m b/DashSync/shared/Models/Masternode/DSQRInfoProcessingResult.m index b96d5d120..50e837edf 100644 --- a/DashSync/shared/Models/Masternode/DSQRInfoProcessingResult.m +++ b/DashSync/shared/Models/Masternode/DSQRInfoProcessingResult.m @@ -24,11 +24,9 @@ + (instancetype)processingResultWith:(QRInfoResult *)result onChain:(DSChain *)c uint8_t errorStatus = result->error_status; processingResult.errorStatus = errorStatus; if (errorStatus > 0) { - DSLog(@"[%@] DSQRInfoProcessingResult.error %ul", chain.name, errorStatus); return processingResult; } if (result->result_at_tip == NULL) { - DSLog(@"[%@] DSQRInfoProcessingResult.error.unknown", chain.name); processingResult.errorStatus = ProcessingError_ParseError; return processingResult; } diff --git a/DashSync/shared/Models/Masternode/DSQuorumEntry.m b/DashSync/shared/Models/Masternode/DSQuorumEntry.m index 903df11e7..215dbf20f 100644 --- a/DashSync/shared/Models/Masternode/DSQuorumEntry.m +++ b/DashSync/shared/Models/Masternode/DSQuorumEntry.m @@ -192,7 +192,6 @@ - (BOOL)validateWithMasternodeList:(DSMasternodeList *)masternodeList { blockHeightLookup:^uint32_t(UInt256 blockHash) { DSMerkleBlock *block = [self.chain blockForBlockHash:blockHash]; if (!block) { - DSLog(@"[%@] Unknown block %@", self.chain.name, uint256_reverse_hex(blockHash)); NSAssert(block, @"block should be known"); } return block.height; @@ -201,7 +200,6 @@ - (BOOL)validateWithMasternodeList:(DSMasternodeList *)masternodeList { - (BOOL)validateWithMasternodeList:(DSMasternodeList *)masternodeList blockHeightLookup:(BlockHeightFinder)blockHeightLookup { if (!masternodeList) { - DSLog(@"[%@] Trying to validate a quorum without a masternode list", self.chain.name); return NO; } MasternodeList *list = [masternodeList ffi_malloc]; diff --git a/DashSync/shared/Models/Masternode/DSQuorumRotationService.m b/DashSync/shared/Models/Masternode/DSQuorumRotationService.m index dcfb6a254..a0d8e9cb6 100644 --- a/DashSync/shared/Models/Masternode/DSQuorumRotationService.m +++ b/DashSync/shared/Models/Masternode/DSQuorumRotationService.m @@ -37,7 +37,6 @@ - (void)composeMasternodeListRequest:(NSOrderedSet *)list { NSAssert(([self.store heightForBlockHash:previousBlockHash] != UINT32_MAX) || uint256_is_zero(previousBlockHash), @"This block height should be known"); [self requestQuorumRotationInfo:previousBlockHash forBlockHash:blockHash]; } else { - DSLog(@"[%@] Missing block (%@)", self.chain.name, blockHashData.hexString); [self removeFromRetrievalQueue:blockHashData]; } /* @@ -60,7 +59,6 @@ - (void)composeMasternodeListRequest:(NSOrderedSet *)list { NSAssert(([self.store heightForBlockHash:previousBlockHash] != UINT32_MAX) || uint256_is_zero(previousBlockHash), @"This block height should be known"); [self requestQuorumRotationInfo:previousBlockHash forBlockHash:blockHash]; } else { - DSLog(@"Missing block (%@)", blockHashData.hexString); [self removeFromRetrievalQueue:blockHashData]; } }*/ @@ -72,7 +70,6 @@ - (void)getRecentMasternodeList { DSMerkleBlock *merkleBlock = [self.chain blockFromChainTip:0]; if (!merkleBlock) { // sometimes it happens while rescan - DSLog(@"[%@] getRecentMasternodeList: (no block exist) for tip", self.chain.name); return; } UInt256 merkleBlockHash = merkleBlock.blockHash; @@ -87,7 +84,6 @@ - (void)getRecentMasternodeList { BOOL needUpdate = !self.masternodeListAtH || [self.masternodeListAtH hasUnverifiedRotatedQuorums] || (lastHeight % updateInterval == rotationOffset && lastHeight >= [self.store heightForBlockHash:self.masternodeListAtH.blockHash] + rotationOffset); if (needUpdate && [self.store addBlockToValidationQueue:merkleBlock]) { - DSLog(@"[%@] QuorumRotationService.Getting masternode list %u", self.chain.name, merkleBlock.height); NSData *merkleBlockHashData = uint256_data(merkleBlockHash); BOOL emptyRequestQueue = ![self retrievalQueueCount]; [self addToRetrievalQueue:merkleBlockHashData]; @@ -103,12 +99,10 @@ - (void)requestQuorumRotationInfo:(UInt256)previousBlockHash forBlockHash:(UInt2 // blockHeight % dkgInterval == activeSigningQuorumsCount + 11 + 8 DSMasternodeListRequest *matchedRequest = [self requestInRetrievalFor:previousBlockHash blockHash:blockHash]; if (matchedRequest) { - DSLog(@"[%@] •••• qrinfo request with such a range already in retrieval: %@ .. %@", self.chain.name, uint256_hex(previousBlockHash), uint256_hex(blockHash)); return; } NSArray *baseBlockHashes = @[[NSData dataWithUInt256:previousBlockHash]]; DSGetQRInfoRequest *request = [DSGetQRInfoRequest requestWithBaseBlockHashes:baseBlockHashes blockHash:blockHash extraShare:YES]; - DSLog(@"[%@] •••• requestQuorumRotationInfo: %@ .. %@", self.chain.name, uint256_hex(previousBlockHash), uint256_hex(blockHash)); [self sendMasternodeListRequest:request]; } diff --git a/DashSync/shared/Models/Masternode/DSSimplifiedMasternodeEntry.m b/DashSync/shared/Models/Masternode/DSSimplifiedMasternodeEntry.m index 201bc2bde..0f5f40002 100644 --- a/DashSync/shared/Models/Masternode/DSSimplifiedMasternodeEntry.m +++ b/DashSync/shared/Models/Masternode/DSSimplifiedMasternodeEntry.m @@ -18,14 +18,6 @@ #import "NSMutableData+Dash.h" #import -#define LOG_SMNE_CHANGES 1 - -#if LOG_SMNE_CHANGES -#define DSDSMNELog(s, ...) DSLog(s, ##__VA_ARGS__) -#else -#define DSDSMNELog(s, ...) -#endif - @interface DSSimplifiedMasternodeEntry () @property (nonatomic, assign) UInt256 providerRegistrationTransactionHash; @@ -151,7 +143,6 @@ - (BOOL)isValidAtBlockHeight:(uint32_t)blockHeight { uint32_t distance = prevHeight - blockHeight; if (distance < minDistance) { minDistance = distance; - DSDSMNELog(@"Validity for proTxHash %@ : Using %@ instead of %@ for list at block height %u (previousBlock.height %u)", uint256_hex(self.providerRegistrationTransactionHash), previousValidity[previousBlock].boolValue ? @"YES" : @"NO", isValid ? @"YES" : @"NO", blockHeight, prevHeight); isValid = [previousValidity[previousBlock] boolValue]; } } @@ -195,7 +186,6 @@ - (UInt256)simplifiedMasternodeEntryHashAtBlockHeight:(uint32_t)blockHeight { uint32_t distance = prevHeight - blockHeight; if (distance < minDistance) { minDistance = distance; - DSLog(@"[%@] SME Hash for proTxHash %@ : Using %@ instead of %@ for list at block height %u", self.chain.name, uint256_hex(self.providerRegistrationTransactionHash), uint256_hex(*(UInt256 *)(blockInfo.u8)), uint256_hex(usedSimplifiedMasternodeEntryHash), blockHeight); usedSimplifiedMasternodeEntryHash = previousSimplifiedMasternodeEntryHashes[previousBlock].UInt256; } } @@ -235,7 +225,6 @@ - (UInt384)operatorPublicKeyAtBlockHeight:(uint32_t)blockHeight { uint32_t distance = prevHeight - blockHeight; if (distance < minDistance) { minDistance = distance; - DSDSMNELog(@"OperatorKey : Using %@ instead of %@ for list at block height %u", uint384_hex(previousOperatorPublicKeyAtBlockHashes[previousBlock].UInt384), uint384_hex(usedPreviousOperatorPublicKeyAtBlockHash), blockHeight); usedPreviousOperatorPublicKeyAtBlockHash = previousOperatorPublicKeyAtBlockHashes[previousBlock].UInt384; } } diff --git a/DashSync/shared/Models/Network/DSPeer.m b/DashSync/shared/Models/Network/DSPeer.m index 7db959267..35e5b2097 100644 --- a/DashSync/shared/Models/Network/DSPeer.m +++ b/DashSync/shared/Models/Network/DSPeer.m @@ -28,6 +28,7 @@ #import "DSPeer.h" #import "DSAddrRequest.h" +#import "DSLogger.h" #import "DSBlockchainIdentityRegistrationTransition.h" #import "DSBloomFilter.h" #import "DSChain+Protected.h" @@ -73,19 +74,10 @@ #import "NSMutableData+Dash.h" #import -#define PEER_LOGGING 1 #define LOG_ALL_HEADERS_IN_ACCEPT_HEADERS 0 -#define LOG_TX_LOCK_VOTES 1 +#define LOG_TX_LOCK_VOTES 0 #define LOG_FULL_TX_MESSAGE 0 -#if !PEER_LOGGING -#define DSLog(...) -#endif - -#define MESSAGE_LOGGING (1 & DEBUG) -#define MESSAGE_CONTENT_LOGGING (0 & DEBUG) -#define MESSAGE_IN_DEPTH_TX_LOGGING (0 & DEBUG) - #define HEADER_LENGTH 24 #define MAX_MSG_LENGTH 0x02000000 #define CONNECT_TIMEOUT 3.0 @@ -94,9 +86,6 @@ #define LOCK(lock) dispatch_semaphore_wait(lock, DISPATCH_TIME_FOREVER); #define UNLOCK(lock) dispatch_semaphore_signal(lock); -#define DSLogWithLocation(obj, fmt, ...) DSLog(@"%@ " fmt, [obj debugLocation], ##__VA_ARGS__) -#define DSLogPrivateWithLocation(obj, fmt, ...) DSLogPrivate(@"%@ " fmt, [obj debugLocation], ##__VA_ARGS__) - @interface DSPeer () @property (nonatomic, weak) id peerDelegate; @@ -227,12 +216,12 @@ - (NSString *)host { - (void)connect { if (self.status != DSPeerStatus_Disconnected) return; + DSLogInfo(@"DSPeer", @"connecting to peer %@:%u", self.host, self.port); _status = DSPeerStatus_Connecting; _pingTime = DBL_MAX; if (!self.reachability) self.reachability = [DSReachabilityManager sharedManager]; if (self.reachability.networkReachabilityStatus == DSReachabilityStatusNotReachable) { // delay connect until network is reachable - DSLogWithLocation(self, @"not reachable, waiting..."); dispatch_async(dispatch_get_main_queue(), ^{ if (!self.reachabilityObserver) { self.reachabilityObserver = @@ -290,7 +279,6 @@ - (void)connect { dispatch_async(dispatch_queue_create(label.UTF8String, NULL), ^{ CFReadStreamRef readStream = NULL; CFWriteStreamRef writeStream = NULL; - DSLogWithLocation(self, @"connecting"); CFStreamCreatePairWithSocketToHost(NULL, (__bridge CFStringRef)self.host, self.port, &readStream, &writeStream); self.inputStream = CFBridgingRelease(readStream); self.outputStream = CFBridgingRelease(writeStream); @@ -317,7 +305,11 @@ - (void)disconnect { - (void)disconnectWithError:(NSError *)error { if (_status == DSPeerStatus_Disconnected) return; - DSLogWithLocation(self, @"Disconnected from peer (%@ protocol %d) with error: %@", self.useragent, self.version, error ? error : @"(None)"); + if (error) { + DSLogWarn(@"DSPeer", @"disconnecting from peer %@:%u with error: %@", self.host, self.port, error.localizedDescription); + } else { + DSLogInfo(@"DSPeer", @"disconnecting from peer %@:%u", self.host, self.port); + } [NSObject cancelPreviousPerformRequestsWithTarget:self]; // cancel connect timeout _status = DSPeerStatus_Disconnected; @@ -330,7 +322,7 @@ - (void)disconnectWithError:(NSError *)error { if (!self.runLoop) return; [self.inputStream close]; [self.outputStream close]; - + CFRunLoopStop([self.runLoop getCFRunLoop]); [NSObject cancelPreviousPerformRequestsWithTarget:self]; @@ -357,9 +349,10 @@ - (void)error:(NSString *)message, ... NS_FORMAT_FUNCTION(1, 2) { - (void)didConnect { if (self.status != DSPeerStatus_Connecting || !self.sentVerack || !self.gotVerack) return; - DSLogWithLocation(self, @"handshake completed %@", (self.peerDelegate.downloadPeer == self) ? @"(download peer)" : @""); [NSObject cancelPreviousPerformRequestsWithTarget:self]; // cancel pending handshake timeout _status = DSPeerStatus_Connected; + DSLogInfo(@"DSPeer", @"connected to peer %@:%u (version %u, services %llu, useragent: %@)", + self.host, self.port, self.version, self.services, self.useragent); [self dispatchAsyncInDelegateQueue:^{ if (self->_status == DSPeerStatus_Connected) [self.peerDelegate peerConnected:self]; @@ -378,13 +371,11 @@ - (void)receivedOrphanBlock { - (void)sendRequest:(DSMessageRequest *)request { NSString *type = [request type]; NSData *payload = [request toData]; -// DSLog(@"%@:%u sendRequest: [%@]: %@", self.host, self.port, type, [payload hexString]); [self sendMessage:payload type:type]; } - (void)sendMessage:(NSData *)message type:(NSString *)type { if (message.length > MAX_MSG_LENGTH) { - DSLogWithLocation(self, @"failed to send %@, length %u is too long", type, (int)message.length); #if DEBUG abort(); #endif @@ -392,34 +383,11 @@ - (void)sendMessage:(NSData *)message type:(NSString *)type { } if (!self.runLoop) return; CFRunLoopPerformBlock([self.runLoop getCFRunLoop], kCFRunLoopCommonModes, ^{ -#if MESSAGE_LOGGING - if (![type isEqualToString:MSG_GETDATA] && ![type isEqualToString:MSG_VERSION] && ![type isEqualToString:MSG_GETBLOCKS]) { //we log this somewhere else for better accuracy of what data is being got - DSLogWithLocation(self, @"%@sending %@", self.peerDelegate.downloadPeer == self ? @"(download peer) " : @"", type); -#if MESSAGE_IN_DEPTH_TX_LOGGING - if ([type isEqualToString:@"ix"] || [type isEqualToString:@"tx"]) { - DSTransaction *transactionBeingSent = [DSTransaction transactionWithMessage:message onChain:self.chain]; -#if DEBUG - DSLogPrivateWithLocation(self, @"transaction %@", transactionBeingSent.longDescription); -#else - DSLogWithLocation(self, @"transaction %@", @""); -#endif - } -#endif -#if MESSAGE_CONTENT_LOGGING -#if DEBUG - DSLogPrivateWithLocation(self, @"sending data (%lu bytes) %@", (unsigned long)message.length, message.hexString); -#else - DSLogWithLocation(self, @"sending data (%lu bytes) %@", (unsigned long)message.length, @""); -#endif -#endif - } -#endif LOCK(self.outputBufferSemaphore); [self.outputBuffer appendMessage:message type:type forChain:self.chain]; while (self.outputBuffer.length > 0 && self.outputStream.hasSpaceAvailable) { NSInteger l = [self.outputStream write:self.outputBuffer.bytes maxLength:self.outputBuffer.length]; if (l > 0) [self.outputBuffer replaceBytesInRange:NSMakeRange(0, l) withBytes:NULL length:0]; - //if (self.outputBuffer.length == 0) DSLog(@"%@:%u output buffer cleared", self.host, self.port); } UNLOCK(self.outputBufferSemaphore); @@ -434,8 +402,6 @@ - (void)sendVersionMessage { agent = [USER_AGENT stringByAppendingString:@"/"]; } else if (self.chain.isTestnet) { agent = [USER_AGENT stringByAppendingString:@"(testnet)/"]; -// } else if (self.chain.protocolVersion >= 70220) { -// agent = [USER_AGENT stringByAppendingString:[NSString stringWithFormat:@"(devnet.%u.%@)/", self.chain.devnetVersion, self.chain.devnetIdentifier]]; } else { agent = [USER_AGENT stringByAppendingString:[NSString stringWithFormat:@"(devnet.%@)/", [DSKeyManager devnetIdentifierFor:self.chain.chainType]]]; } @@ -448,9 +414,6 @@ - (void)sendVersionMessage { userAgent:agent]; self.pingStartTime = [NSDate timeIntervalSince1970]; -#if MESSAGE_LOGGING - DSLogWithLocation(self, @"%@sending version with protocol version %d user agent %@", self.peerDelegate.downloadPeer == self ? @"(download peer) " : @"", self.chain.protocolVersion, agent); -#endif [self sendRequest:request]; } @@ -464,11 +427,7 @@ - (void)sendFilterloadMessage:(NSData *)filter { @synchronized (self) { self.sentFilter = YES; } -#if DEBUG - DSLogPrivateWithLocation(self, @"Sending filter with fingerprint %@ to node %@", [NSData dataWithUInt256:filter.SHA256].shortHexString, self.peerDelegate.downloadPeer == self ? @"(download peer) " : @""); -#else - DSLogWithLocation(self, @"Sending filter with fingerprint %@ to node %@", @"", self.peerDelegate.downloadPeer == self ? @"(download peer) " : @""); -#endif + DSLogInfo(@"DSPeer", @"Sending Bloom filter to peer %@ (%lu bytes)", self.host, (unsigned long)filter.length); [self sendRequest:[DSFilterLoadRequest requestWithBloomFilterData:filter]]; } @@ -480,11 +439,6 @@ - (void)sendFilterloadMessage:(NSData *)filter { @param completion A completion block that is called when the mempool message processing is complete. This block is provided with three boolean arguments indicating various states of the transaction processing (e.g., if it was added, already known, or rejected). */ - (void)sendMempoolMessage:(NSArray *)publishedTxHashes completion:(MempoolCompletionBlock)completion { -#if DEBUG - DSLogPrivateWithLocation(self, @"sendMempoolMessage %@", publishedTxHashes); -#else - DSLogWithLocation(self, @"sendMempoolMessage %@", @""); -#endif @synchronized (self.knownTxHashes) { [self.knownTxHashes addObjectsFromArray:publishedTxHashes]; } @@ -525,7 +479,6 @@ - (void)cancelMempoolTimer { } } - (void)mempoolTimeout { - DSLogWithLocation(self, @"[DSPeer] mempool time out"); __block MempoolCompletionBlock completion = self.mempoolTransactionCompletion; [self sendPingMessageWithPongHandler:^(BOOL success) { if (completion) { @@ -574,33 +527,10 @@ - (void)sendGetblocksMessageWithLocators:(NSArray *)locators andHashStop:(UInt25 DSGetBlocksRequest *request = [DSGetBlocksRequest requestWithLocators:locators andHashStop:hashStop protocolVersion:self.chain.protocolVersion]; self.sentGetblocks = YES; -#if MESSAGE_LOGGING - NSMutableArray *locatorHexes = [NSMutableArray arrayWithCapacity:[locators count]]; - [locators enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) { - uint32_t knownHeight = [self.chain quickHeightForBlockHash:((NSData *)obj).UInt256]; - [locatorHexes addObject:[NSString stringWithFormat:@"%@ (block height %d)", - ((NSData *)obj).reverse.hexString, - knownHeight == UINT32_MAX ? 0 : knownHeight]]; - }]; -#if DEBUG - DSLogPrivateWithLocation(self, @"%@sending getblocks with locators %@", self.peerDelegate.downloadPeer == self ? @"(download peer) " : @"", locatorHexes); -#else - DSLogWithLocation(self, @"%@sending getblocks with locators %@", self.peerDelegate.downloadPeer == self ? @"(download peer) " : @"", @""); -#endif -//#if MESSAGE_CONTENT_LOGGING -//#if DEBUG -// DSLogPrivate(@"%@:%u sending data %@", self.host, self.port, msg.hexString); -//#else -// DSLog(@"%@:%u sending data %@", self.host, self.port, @""); -//#endif -//#endif -#endif - [self sendRequest:request]; } - (void)sendInvMessageForHashes:(NSArray *)invHashes ofType:(DSInvType)invType { - DSLogPrivateWithLocation(self, @"sending inv message of type %@ hashes count %lu", [self nameOfInvMessage:invType], invHashes.count); NSMutableOrderedSet *hashes = [NSMutableOrderedSet orderedSetWithArray:invHashes]; @synchronized (self.knownTxHashes) { [hashes minusOrderedSet:self.knownTxHashes]; @@ -608,7 +538,7 @@ - (void)sendInvMessageForHashes:(NSArray *)invHashes ofType:(DSInvType)invType { if (hashes.count == 0) return; DSInvRequest *request = [DSInvRequest requestWithHashes:hashes ofInvType:invType]; [self sendRequest:request]; - + switch (invType) { case DSInvType_Tx: @synchronized (self.knownTxHashes) { @@ -651,13 +581,6 @@ - (void)sendTransactionInvMessagesforTransactionHashes:(NSArray *)txInvHashes tx - (void)sendGetdataMessageForTxHash:(UInt256)txHash { if (!([[DSOptionsManager sharedInstance] syncType] & DSSyncType_GetsNewBlocks)) return; DSGetDataForTransactionHashRequest *request = [DSGetDataForTransactionHashRequest requestForTransactionHash:txHash]; -#if MESSAGE_LOGGING -#if DEBUG - DSLogPrivateWithLocation(self, @"sending getdata for transaction %@", uint256_hex(txHash)); -#else - DSLogWithLocation(self, @"sending getdata for transaction %@", @""); -#endif -#endif [self sendRequest:request]; } @@ -665,7 +588,6 @@ - (void)sendGetdataMessageWithTxHashes:(NSArray *)txHashes instantSendLockHashes if (!([[DSOptionsManager sharedInstance] syncType] & DSSyncType_GetsNewBlocks)) return; NSUInteger totalCount = txHashes.count + instantSendLockHashes.count + instantSendLockDHashes.count + blockHashes.count + chainLockHashes.count; if (totalCount > MAX_GETDATA_HASHES) { // limit total hash count to MAX_GETDATA_HASHES - DSLogWithLocation(self, @"couldn't send getdata, %lu is too many items, max is %u", totalCount, MAX_GETDATA_HASHES); return; } else if (totalCount == 0) return; @@ -676,25 +598,16 @@ - (void)sendGetdataMessageWithTxHashes:(NSArray *)txHashes instantSendLockHashes blockHashes:blockHashes chainLockHashes:chainLockHashes]; self.sentGetdataTxBlocks = YES; -#if MESSAGE_LOGGING - DSLogWithLocation(self, @"sending getdata (transactions and blocks)"); -#endif [self sendRequest:request]; } - (void)sendGovernanceRequest:(DSGovernanceHashesRequest *)request { if (request.hashes.count > MAX_GETDATA_HASHES) { // limit total hash count to MAX_GETDATA_HASHES - DSLogWithLocation(self, @"couldn't send governance votes getdata, %lu is too many items, max is %u", request.hashes.count, MAX_GETDATA_HASHES); return; } else if (request.hashes.count == 0) { - DSLogWithLocation(self, @"couldn't send governance getdata, there is no items"); return; } - - #if MESSAGE_LOGGING - DSLogWithLocation(self, @"sending getdata (%@)", request.description); - #endif - + // Not used [self sendRequest:request]; } @@ -710,9 +623,6 @@ - (void)sendPingMessageWithPongHandler:(void (^)(BOOL success))pongHandler { uint64_t localNonce = self.localNonce; self.pingStartTime = [NSDate timeIntervalSince1970]; -#if MESSAGE_LOGGING - DSLogWithLocation(self, @"sending ping"); -#endif [self dispatchAsyncInDelegateQueue:^{ [self sendRequest:[DSPingRequest requestWithLocalNonce:localNonce]]; }]; @@ -724,7 +634,6 @@ - (void)rerequestBlocksFrom:(UInt256)blockHash { if (i != NSNotFound) { [self.knownBlockHashes removeObjectsInRange:NSMakeRange(0, i)]; - DSLogWithLocation(self, @"re-requesting %lu blocks", self.knownBlockHashes.count); [self sendGetdataMessageWithTxHashes:nil instantSendLockHashes:nil instantSendLockDHashes:nil blockHashes:self.knownBlockHashes.array chainLockHashes:nil]; } } @@ -740,22 +649,18 @@ - (void)sendGetSporks { // Governance Synchronization for Votes and Objects - (void)sendGovernanceSyncRequest:(DSGovernanceSyncRequest *)request { // Make sure we aren't in a governance sync process - DSLogWithLocation(self, @"Requesting Governance Object Vote Hashes"); if (self.governanceRequestState != DSGovernanceRequestState_None) { - DSLog(@"[%@: %@:%d] Requesting Governance Object Hashes out of resting state", self.chain.name, self.host, self.port); return; } - DSLogWithLocation(self, @"Requesting %@", request.description); self.governanceRequestState = request.state; - + [self sendRequest:request]; - + if (request.state == DSGovernanceRequestState_GovernanceObjectHashes) { //we aren't afraid of coming back here within 5 seconds because a peer can only sendGovSync once every 3 hours dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(10 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ if (self.governanceRequestState == DSGovernanceRequestState_GovernanceObjectHashes) { - DSLogWithLocation(self, @"Peer ignored request for governance object hashes"); [self.governanceDelegate peer:self ignoredGovernanceSync:DSGovernanceRequestState_GovernanceObjectHashes]; } }); @@ -774,11 +679,6 @@ - (void)sendGovObject:(DSGovernanceObject *)governanceObject { // MARK: - accept - (void)acceptMessage:(NSData *)message type:(NSString *)type { -#if MESSAGE_LOGGING - if (![type isEqualToString:MSG_INV] && ![type isEqualToString:MSG_GOVOBJVOTE] && ![type isEqualToString:MSG_MERKLEBLOCK]) { - DSLogWithLocation(self, @"accept message %@", type); - } -#endif if (self.currentBlock && (!([MSG_TX isEqual:type] || [MSG_IX isEqual:type] || [MSG_ISLOCK isEqual:type]))) { // if we receive a non-tx message, merkleblock is done UInt256 hash = self.currentBlock.blockHash; @@ -842,7 +742,6 @@ - (void)acceptMessage:(NSData *)message type:(NSString *)type { [self acceptGovObjectVoteMessage:message]; else if ([MSG_GOVOBJ isEqual:type]) [self acceptGovObjectMessage:message]; - //else if ([MSG_GOVOBJSYNC isEqual:type]) [self acceptGovObjectSyncMessage:message]; // CoinJoin else if ([MSG_COINJOIN_COMPLETE isEqual:type]) @@ -855,11 +754,6 @@ - (void)acceptMessage:(NSData *)message type:(NSString *)type { [self acceptCoinJoinStatusUpdateMessage:message]; else if ([MSG_COINJOIN_BROADCAST_TX isEqual:type]) [self acceptCoinJoinBroadcastTxMessage:message]; -#if DROP_MESSAGE_LOGGING - else { - DSLogWithLocation(self, @"dropping %@, len:%u, not implemented", type, message.length); - } -#endif } - (void)acceptVersionMessage:(NSData *)message { @@ -877,32 +771,23 @@ - (void)acceptVersionMessage:(NSData *)message { return; } _lastBlockHeight = [message UInt32AtOffset:80 + l.unsignedIntegerValue]; + DSLogDebug(@"DSPeer", @"received version from %@:%u - version %u, height %u", + self.host, self.port, self.version, self.lastBlockHeight); - if (self.version < self.chain.minProtocolVersion /*|| self.version > self.chain.protocolVersion*/) { -#if MESSAGE_LOGGING - DSLogWithLocation(self, @"protocol version %u not supported, valid versions are: [%u, %u], useragent:\"%@\", ", self.version, self.chain.minProtocolVersion, self.chain.protocolVersion, self.useragent); -#endif + if (self.version < self.chain.minProtocolVersion) { [self error:@"protocol version %u not supported", self.version]; return; - } else { -#if MESSAGE_LOGGING - DSLogWithLocation(self, @"got version %u, useragent:\"%@\"", self.version, self.useragent); -#endif } [self sendVerackMessage]; } - (void)acceptVerackMessage:(NSData *)message { if (self.gotVerack) { - DSLogWithLocation(self, @"got unexpected verack"); return; } _pingTime = [NSDate timeIntervalSince1970] - self.pingStartTime; // use verack time as initial ping time self.pingStartTime = 0; -#if MESSAGE_LOGGING - DSLogWithLocation(self, @"got verack in %fs", self.pingTime); -#endif self.gotVerack = YES; [self didConnect]; } @@ -910,7 +795,6 @@ - (void)acceptVerackMessage:(NSData *)message { // TODO: relay addresses - (void)acceptAddrMessage:(NSData *)message { if (message.length > 0 && [message UInt8AtOffset:0] == 0) { - DSLogWithLocation(self, @"got addr with 0 addresses"); return; } else if (message.length < 5) { [self error:@"malformed addr message, length %u is too short", (int)message.length]; @@ -924,14 +808,12 @@ - (void)acceptAddrMessage:(NSData *)message { NSMutableArray *peers = [NSMutableArray array]; if (count > 1000) { - DSLogWithLocation(self, @"dropping addr message, %lu is too many addresses (max 1000)", count); return; } else if (message.length < l.unsignedIntegerValue + count * 30) { [self error:@"malformed addr message, length is %u, should be %u for %u addresses", (int)message.length, (int)(l.unsignedIntegerValue + count * 30), (int)count]; return; - } else - DSLogWithLocation(self, @"got addr with %lu addresses", count); + } for (NSUInteger off = l.unsignedIntegerValue; off < l.unsignedIntegerValue + 30 * count; off += 30) { NSTimeInterval timestamp = [message UInt32AtOffset:off]; @@ -960,7 +842,6 @@ - (void)acceptAddrMessage:(NSData *)message { } - (void)acceptAddrV2Message:(NSData *)message { - DSLogWithLocation(self, @"sendaddrv2, len:%lu, (not implemented)", message.length); } - (NSString *)nameOfInvMessage:(DSInvType)type { @@ -1033,17 +914,8 @@ - (void)acceptInvMessage:(NSData *)message { (int)(((l.unsignedIntegerValue == 0) ? 1 : l.unsignedIntegerValue) + count * 36), (int)count]; return; } else if (count > MAX_GETDATA_HASHES) { - DSLogWithLocation(self, @"dropping inv message, %lu is too many items, max is %u", count, MAX_GETDATA_HASHES); return; } -#if MESSAGE_LOGGING - if (count == 0) { - DSLogWithLocation(self, @"Got empty Inv message"); - } - if (count > 0 && ([message UInt32AtOffset:l.unsignedIntegerValue] != DSInvType_MasternodePing) && ([message UInt32AtOffset:l.unsignedIntegerValue] != DSInvType_MasternodePaymentVote) && ([message UInt32AtOffset:l.unsignedIntegerValue] != DSInvType_MasternodeVerify) && ([message UInt32AtOffset:l.unsignedIntegerValue] != DSInvType_GovernanceObjectVote)) { - DSLogWithLocation(self, @"got inv with %u item%@ (first item %@ with hash %@/%@)", (int)count, count == 1 ? @"" : @"s", [self nameOfInvMessage:[message UInt32AtOffset:l.unsignedIntegerValue]], [NSData dataWithUInt256:[message UInt256AtOffset:l.unsignedIntegerValue + sizeof(uint32_t)]].hexString, [NSData dataWithUInt256:[message UInt256AtOffset:l.unsignedIntegerValue + sizeof(uint32_t)]].reverse.hexString); - } -#endif BOOL onlyPrivateSendTransactions = NO; for (NSUInteger off = l.unsignedIntegerValue; off < l.unsignedIntegerValue + 36 * count; off += 36) { @@ -1071,8 +943,8 @@ - (void)acceptInvMessage:(NSData *)message { case DSInvType_Merkleblock: [blockHashes addObject:uint256_obj(hash)]; break; case DSInvType_Spork: [sporkHashes addObject:[NSData dataWithUInt256:hash]]; break; case DSInvType_GovernanceObject: [governanceObjectHashes addObject:[NSData dataWithUInt256:hash]]; break; - case DSInvType_GovernanceObjectVote: break; //[governanceObjectVoteHashes addObject:[NSData dataWithUInt256:hash]]; break; - case DSInvType_MasternodePing: break; //[masternodePingHashes addObject:uint256_obj(hash)]; break; + case DSInvType_GovernanceObjectVote: break; + case DSInvType_MasternodePing: break; case DSInvType_MasternodePaymentVote: break; case DSInvType_MasternodeVerify: break; case DSInvType_MasternodeBroadcast: break; @@ -1082,7 +954,6 @@ - (void)acceptInvMessage:(NSData *)message { case DSInvType_CompactBlock: break; case DSInvType_ChainLockSignature: [chainLockHashes addObject:uint256_obj(hash)]; break; case DSInvType_QuorumPrematureCommitment: - DSLog(@"[%@: %@:%d] Send premature commitment containing the quorum public key (intra-quorum communication)", self.chain.name, self.host, self.port); break; default: { NSString *desc = [NSString stringWithFormat:@"inventory type not dealt with: %u", type]; @@ -1097,12 +968,11 @@ - (void)acceptInvMessage:(NSData *)message { currentHeight = self.currentBlockHeight; isFilterNotLoaded = !self.sentFilter && !self.sentMempool && !self.sentGetblocks; } - + if ([self.chain syncsBlockchain] && isFilterNotLoaded && (txHashes.count > 0) && !onlyPrivateSendTransactions) { [self error:@"got tx inv message before loading a filter"]; return; } else if (txHashes.count + instantSendLockHashes.count + instantSendLockDHashes.count > 10000) { // this was happening on testnet, some sort of DOS/spam attack? - DSLogWithLocation(self, @"too many transactions, disconnecting"); [self disconnect]; // disconnecting seems to be the easiest way to mitigate it return; } else if (currentHeight > 0 && blockHashes.count > 2 && blockHashes.count < 500 && @@ -1158,7 +1028,7 @@ - (void)acceptInvMessage:(NSData *)message { [self.knownInstantSendLockHashes unionOrderedSet:instantSendLockHashes]; } - + if (instantSendLockDHashes.count > 0) { for (NSValue *hash in instantSendLockDHashes) { UInt256 h; @@ -1237,7 +1107,6 @@ - (void)acceptInvMessage:(NSData *)message { if (self.mempoolTransactionCompletion && (txHashes.count + governanceObjectHashes.count + sporkHashes.count > 0)) { self.mempoolRequestTime = [NSDate timeIntervalSince1970]; // this will cancel the mempool timeout - DSLogWithLocation(self, @"[DSPeer] got mempool tx inv messages"); __block MempoolCompletionBlock completion = self.mempoolTransactionCompletion; [self sendPingMessageWithPongHandler:^(BOOL success) { if (completion) { @@ -1274,19 +1143,6 @@ - (void)acceptTxMessage:(NSData *)message { [self dispatchAsyncInDelegateQueue:^{ [self.transactionDelegate peer:self relayedTransaction:tx inBlock:currentBlock]; }]; -#if LOG_FULL_TX_MESSAGE -#if DEBUG - DSLogPrivateWithLocation(self, @"got tx %@ %@", uint256_obj(tx.txHash), message.hexString); -#else - DSLogWithLocation(self, @"got tx %@ %@", @"", @""); -#endif -#else -#if DEBUG - DSLogPrivateWithLocation(self, @"got tx (%hu): %@", tx.type, uint256_obj(tx.txHash)); -#else - DSLogWithLocation(self, @"got tx (%lu): %@", tx.type, @""); -#endif -#endif } @@ -1294,19 +1150,11 @@ - (void)acceptTxMessage:(NSData *)message { UInt256 txHash = tx ? tx.txHash : message.SHA256_2; if ([self.currentBlockTxHashes containsObject:uint256_obj(txHash)]) { [self.currentBlockTxHashes removeObject:uint256_obj(txHash)]; - } else { -#if DEBUG - DSLogPrivateWithLocation(self, @"current block does not contain transaction %@ (contains %@)", uint256_hex(txHash), self.currentBlockTxHashes); -#else - DSLogWithLocation(self, @"current block does not contain transaction %@ (contains %@)", @"", @""); -#endif } if (self.currentBlockTxHashes.count == 0) { // we received the entire block including all matched tx DSMerkleBlock *block = self.currentBlock; - DSLogWithLocation(self, @"clearing current block"); - self.currentBlock = nil; self.currentBlockTxHashes = nil; @@ -1314,22 +1162,15 @@ - (void)acceptTxMessage:(NSData *)message { [self.transactionDelegate peer:self relayedBlock:block]; }); } - } else { - DSLogWithLocation(self, @"no current block"); } } - (void)acceptIslockMessage:(NSData *)message { -#if LOG_TX_LOCK_VOTES - DSLogWithLocation(self, @"peer relayed islock message: %@", message.hexString); -#endif if (![self.chain.chainManager.sporkManager deterministicMasternodeListEnabled]) { - DSLogWithLocation(self, @"returned instant send lock message when DML not enabled: %@", message); //no error here return; } if (![self.chain.chainManager.sporkManager llmqInstantSendEnabled]) { - DSLogWithLocation(self, @"returned instant send lock message when llmq instant send is not enabled: %@", message); //no error here return; } DSInstantSendTransactionLock *instantSendTransactionLock = [DSInstantSendTransactionLock instantSendTransactionLockWithNonDeterministicMessage:message onChain:self.chain]; @@ -1347,15 +1188,10 @@ - (void)acceptIslockMessage:(NSData *)message { } - (void)acceptIsdlockMessage:(NSData *)message { -#if LOG_TX_LOCK_VOTES - DSLogWithLocation(self, @"peer relayed isdlock message: %@", message.hexString); -#endif if (![self.chain.chainManager.sporkManager deterministicMasternodeListEnabled]) { - DSLogWithLocation(self, @"returned instant send lock message when DML not enabled: %@", message); //no error here return; } if (![self.chain.chainManager.sporkManager llmqInstantSendEnabled]) { - DSLogWithLocation(self, @"returned instant send lock message when llmq instant send is not enabled: %@", message); //no error here return; } DSInstantSendTransactionLock *instantSendTransactionLock = [DSInstantSendTransactionLock instantSendTransactionLockWithDeterministicMessage:message onChain:self.chain]; @@ -1398,31 +1234,6 @@ - (void)acceptHeadersMessage:(NSData *)message { (int)(((l == 0) ? 1 : l) + count * 81), (int)count]; return; } - if (count == 0) { -#if DEBUG - DSLogPrivateWithLocation(self, @"got 0 headers (%@)", message.hexString); -#else - DSLogWithLocation(self, @"got 0 headers (%@)", @""); -#endif - } else { - DSLogWithLocation(self, @"got %lu headers", count); - } - -#if LOG_ALL_HEADERS_IN_ACCEPT_HEADERS - for (int i = 0; i < count; i++) { - NSData *headerData = [message subdataWithRange:NSMakeRange(l + 81 * i, 80)]; - DSLogPrivate(@"BLOCK HEADER ----------"); - DSLogPrivate(@"block version %u", [headerData UInt8AtOffset:0]); - DSLogPrivate(@"previous blockheader hash %@ (%@)", [NSData dataWithUInt256:[headerData UInt256AtOffset:4]].hexString, [NSData dataWithUInt256:[headerData UInt256AtOffset:4]].reverse.hexString); - DSLogPrivate(@"merkle root %@", [NSData dataWithUInt256:[headerData UInt256AtOffset:36]].hexString); - uint32_t timestamp = [headerData UInt32AtOffset:68]; - DSLogPrivate(@"timestamp %x (%u) time is %@", timestamp, timestamp, [NSDate dateWithTimeIntervalSince1970:timestamp]); - DSLogPrivate(@"target is %x", [headerData UInt32AtOffset:72]); - DSLogPrivate(@"nonce is %x", [headerData UInt32AtOffset:76]); - DSLogPrivate(@"transaction count is %u", [headerData UInt8AtOffset:80]); - DSLogPrivate(@"-----------------------"); - } -#endif if (_relayStartTime != 0) { // keep track of relay peformance NSTimeInterval speed = count / ([NSDate timeIntervalSince1970] - self.relayStartTime); @@ -1431,10 +1242,6 @@ - (void)acceptHeadersMessage:(NSData *)message { _relaySpeed = _relaySpeed * 0.9 + speed * 0.1; _relayStartTime = 0; } - // for (int i = 0; i < count; i++) { - // UInt256 locator = [DSKeyManager x11:[message subdataWithRange:NSMakeRange(l + 81*i, 80)]]; - // DSLog(@"%@:%u header: %@", self.host, self.port, uint256_obj(locator)); - // } // To improve chain download performance, if this message contains 2000 headers then request the next 2000 headers // immediately, and switch to requesting blocks when we receive a header newer than earliestKeyTime // Devnets can run slower than usual @@ -1442,7 +1249,6 @@ - (void)acceptHeadersMessage:(NSData *)message { NSTimeInterval firstTimestamp = [message UInt32AtOffset:l + 81 + 68]; if (!self.chain.needsInitialTerminalHeadersSync && (firstTimestamp + DAY_TIME_INTERVAL * 2 >= self.earliestKeyTime) && [self.chain.chainManager shouldRequestMerkleBlocksForZoneAfterHeight:self.chain.lastSyncBlockHeight + 1]) { //this is a rare scenario where we called getheaders but the first header returned was actually past the cuttoff, but the previous header was before the cuttoff - DSLogWithLocation(self, @"calling getblocks with locators: %@", [self.chain chainSyncBlockLocatorArray]); [self sendGetblocksMessageWithLocators:self.chain.chainSyncBlockLocatorArray andHashStop:UINT256_ZERO]; return; } @@ -1462,11 +1268,8 @@ - (void)acceptHeadersMessage:(NSData *)message { } lastBlockHash = [DSKeyManager x11:[message subdataWithRange:NSMakeRange(off, 80)]]; lastHashData = uint256_data(lastBlockHash); - DSLogWithLocation(self, @"calling getblocks with locators: [%@, %@]", lastHashData.reverse.hexString, firstHashData.reverse.hexString); [self sendGetblocksMessageWithLocators:@[lastHashData, firstHashData] andHashStop:UINT256_ZERO]; } else { - - DSLogWithLocation(self, @"calling getheaders with locators: [%@, %@]", lastHashData.reverse.hexString, firstHashData.reverse.hexString); [self sendGetheadersMessageWithLocators:@[lastHashData, firstHashData] andHashStop:UINT256_ZERO]; } } @@ -1483,7 +1286,6 @@ - (void)acceptHeadersMessage:(NSData *)message { } - (void)acceptGetaddrMessage:(NSData *)message { - DSLogWithLocation(self, @"got getaddr"); [self sendRequest:[DSAddrRequest request]]; } @@ -1497,11 +1299,9 @@ - (void)acceptGetdataMessage:(NSData *)message { (int)(((l == 0) ? 1 : l) + count * 36), (int)count]; return; } else if (count > MAX_GETDATA_HASHES) { - DSLogWithLocation(self, @"dropping getdata message, %lu is too many items, max is %u", count, MAX_GETDATA_HASHES); return; } - DSLogWithLocation(self, @"%@got getdata for %lu item%@", self.peerDelegate.downloadPeer == self ? @"(download peer)" : @"", count, count == 1 ? @"" : @"s"); [self dispatchAsyncInDelegateQueue:^{ NSMutableData *notfound = [NSMutableData data]; @@ -1521,11 +1321,6 @@ - (void)acceptGetdataMessage:(NSData *)message { [self sendMessage:transaction.data type:MSG_TX]; break; } else { -#if DEBUG - DSLogPrivateWithLocation(self, @"peer requested transaction was not found with hash %@ reversed %@", [NSData dataWithUInt256:hash].hexString, [NSData dataWithUInt256:hash].reverse.hexString); -#else - DSLogWithLocation(self, @"peer requested transaction was not found with hash %@ reversed %@", @"", @""); -#endif [notfound appendUInt32:type]; [notfound appendBytes:&hash length:sizeof(hash)]; break; @@ -1579,8 +1374,6 @@ - (void)acceptNotfoundMessage:(NSData *)message { return; } - DSLogWithLocation(self, @"got notfound with %lu item%@ (first item %@)", count, count == 1 ? @"" : @"s", [self nameOfInvMessage:[message UInt32AtOffset:l]]); - for (NSUInteger off = l; off < l + 36 * count; off += 36) { if ([message UInt32AtOffset:off] == DSInvType_Tx) { [txHashes addObject:uint256_obj([message UInt256AtOffset:off + sizeof(uint32_t)])]; @@ -1600,9 +1393,6 @@ - (void)acceptPingMessage:(NSData *)message { [self error:@"malformed ping message, length is %u, should be 4", (int)message.length]; return; } -#if MESSAGE_LOGGING - DSLogWithLocation(self, @"got ping"); -#endif [self sendMessage:message type:MSG_PONG]; } @@ -1616,7 +1406,6 @@ - (void)acceptPongMessage:(NSData *)message { } else { __block BOOL hasNoHandlers = ![self.pongHandlers count]; if (hasNoHandlers) { - DSLogWithLocation(self, @"got unexpected pong"); return; } } @@ -1629,9 +1418,6 @@ - (void)acceptPongMessage:(NSData *)message { self.pingStartTime = 0; } -#if MESSAGE_LOGGING - DSLogWithLocation(self, @"got pong in %fs", self.pingTime); -#endif if (self->_status == DSPeerStatus_Connected && self.pongHandlers.count) { void (^handler)(BOOL) = nil; @synchronized(self.pongHandlers) { @@ -1661,8 +1447,7 @@ - (void)acceptMerkleblockMessage:(NSData *)message { [self error:@"got merkleblock message before loading a filter"]; return; } - //else DSLog(@"[%@: %@:%d] got merkleblock %@", self.chain.name, self.host, self.port, uint256_hex(block.blockHash)); - + NSMutableOrderedSet *txHashes = [NSMutableOrderedSet orderedSetWithArray:block.transactionHashes]; @synchronized (self.knownTxHashes) { [txHashes minusOrderedSet:self.knownTxHashes]; @@ -1685,11 +1470,6 @@ - (void)acceptMerkleblockMessage:(NSData *)message { // DIP08: https://github.com/dashpay/dips/blob/master/dip-0008.md - (void)acceptChainLockMessage:(NSData *)message { if (![self.chain.chainManager.sporkManager chainLocksEnabled]) { -#if DEBUG - DSLogPrivateWithLocation(self, @"returned chain lock message when chain locks are not enabled: %@", message); //no error here -#else - DSLogWithLocation(self, @"returned chain lock message when chain locks are not enabled: %@", @""); //no error here -#endif return; } DSChainLock *chainLock = [DSChainLock chainLockWithMessage:message onChain:self.chain]; @@ -1717,13 +1497,6 @@ - (void)acceptRejectMessage:(NSData *)message { l = lNumber.unsignedIntegerValue; UInt256 txHash = ([MSG_TX isEqual:type] || [MSG_IX isEqual:type]) ? [message UInt256AtOffset:off + l] : UINT256_ZERO; -#if DEBUG - DSLogPrivateWithLocation(self, @"rejected %@ code: 0x%x reason: \"%@\"%@%@", type, code, reason, - (uint256_is_zero(txHash) ? @"" : @" txid: "), (uint256_is_zero(txHash) ? @"" : uint256_obj(txHash))); -#else - DSLogWithLocation(self, @"rejected %@ code: 0x%x reason: \"%@\"%@%@", type, code, reason, - (uint256_is_zero(txHash) ? @"" : @" txid: "), (uint256_is_zero(txHash) ? @"" : @"")); -#endif reason = nil; // fixes an unused variable warning for non-debug builds if (uint256_is_not_zero(txHash)) { @@ -1741,7 +1514,6 @@ - (void)acceptFeeFilterMessage:(NSData *)message { } _feePerByte = ceilf((float)[message UInt64AtOffset:0] / 1000.0f); - DSLogWithLocation(self, @"got feefilter with rate %llu per Byte", self.feePerByte); [self dispatchAsyncInDelegateQueue:^{ [self.transactionDelegate peer:self setFeePerByte:self.feePerByte]; }]; @@ -1758,7 +1530,6 @@ - (void)acceptSporkMessage:(NSData *)message { - (void)acceptSSCMessage:(NSData *)message { DSSyncCountInfo syncCountInfo = [message UInt32AtOffset:0]; uint32_t count = [message UInt32AtOffset:4]; - DSLogWithLocation(self, @"received ssc message %d %d", syncCountInfo, count); switch (syncCountInfo) { case DSSyncCountInfo_GovernanceObject: if (self.governanceRequestState == DSGovernanceRequestState_GovernanceObjectHashes) { @@ -1816,7 +1587,6 @@ - (void)acceptGovObjectVoteMessage:(NSData *)message { } - (void)acceptGovObjectSyncMessage:(NSData *)message { - DSLogWithLocation(self, @"Gov Object Sync"); } // MARK: - Accept CoinJoin messages @@ -1912,10 +1682,6 @@ - (NSError *)connectionTimeoutError { - (void)stream:(NSStream *)aStream handleEvent:(NSStreamEvent)eventCode { switch (eventCode) { //!OCLINT case NSStreamEventOpenCompleted: - DSLogWithLocation(self, @"%@ stream connected in %fs", - (aStream == self.inputStream) ? @"input" : (aStream == self.outputStream ? @"output" : @"unknown"), - [NSDate timeIntervalSince1970] - self.pingStartTime); - if (aStream == self.outputStream) { self.pingStartTime = [NSDate timeIntervalSince1970]; // don't count connect time in ping time [NSObject cancelPreviousPerformRequestsWithTarget:self selector:@selector(disconnectWithError:) object:self.connectionTimeoutError]; // cancel pending socket connect timeout @@ -1956,7 +1722,6 @@ - (void)stream:(NSStream *)aStream handleEvent:(NSStreamEvent)eventCode { maxLength:self.msgHeader.length - headerLen]; if (l < 0) { - DSLogWithLocation(self, @"error reading message"); goto reset; //!OCLINT } @@ -1976,11 +1741,6 @@ - (void)stream:(NSStream *)aStream handleEvent:(NSStreamEvent)eventCode { if (self.msgHeader.length < HEADER_LENGTH) continue; // wait for more stream input } - // if ([self.msgHeader UInt8AtOffset:15] != 0) { // verify msg type field is null terminated - // [self error:@"malformed message header: %@", self.msgHeader]; - // goto reset; - // } - type = @((const char *)self.msgHeader.bytes + 4); length = [self.msgHeader UInt32AtOffset:16]; checksum = [self.msgHeader UInt32AtOffset:20]; @@ -1996,7 +1756,6 @@ - (void)stream:(NSStream *)aStream handleEvent:(NSStreamEvent)eventCode { maxLength:self.msgPayload.length - payloadLen]; if (l < 0) { - DSLogWithLocation(self, @"error reading %@", type); goto reset; //!OCLINT } @@ -2024,17 +1783,15 @@ - (void)stream:(NSStream *)aStream handleEvent:(NSStreamEvent)eventCode { break; case NSStreamEventErrorOccurred: - DSLogWithLocation(self, @"error connecting, %@", aStream.streamError); [self disconnectWithError:aStream.streamError]; break; case NSStreamEventEndEncountered: - DSLogWithLocation(self, @"connection closed"); [self disconnectWithError:nil]; break; default: - DSLogWithLocation(self, @"unknown network stream eventCode:%lu", eventCode); + break; } } diff --git a/DashSync/shared/Models/Payment/DSPaymentProtocol.m b/DashSync/shared/Models/Payment/DSPaymentProtocol.m index b0aa68bf7..1c034e98c 100644 --- a/DashSync/shared/Models/Payment/DSPaymentProtocol.m +++ b/DashSync/shared/Models/Payment/DSPaymentProtocol.m @@ -269,10 +269,7 @@ - (instancetype)initWithData:(NSData *)data onChain:(DSChain *)chain { case details_merchant_data: if (d) _merchantData = d; break; - default: { - DSLog(@"Unknown details type: %lu", (unsigned long)details); - break; - } + default: break; } if (script) [amounts addObject:@(amount)], [scripts addObject:script]; @@ -516,10 +513,8 @@ - (BOOL)isValid { if (status != errSecSuccess) { if (status == errSecUnimplemented) { _errorMessage = DSLocalizedString(@"Unsupported signature type", nil); - DSLog(@"%@", _errorMessage); } else { - _errorMessage = [NSError osStatusErrorWithCode:status].localizedDescription; - DSLog(@"SecKeyRawVerify error: %@", _errorMessage); + _errorMessage = [NSError osStatusErrorWithCode:status].localizedDescription; } r = NO; diff --git a/DashSync/shared/Models/Payment/DSPaymentRequest.m b/DashSync/shared/Models/Payment/DSPaymentRequest.m index 54d62d751..875a9a48e 100644 --- a/DashSync/shared/Models/Payment/DSPaymentRequest.m +++ b/DashSync/shared/Models/Payment/DSPaymentRequest.m @@ -238,17 +238,11 @@ - (NSURL *)url { - (BOOL)isValidAsNonDashpayPaymentRequest { if ([self.scheme isEqualToString:@"dash"]) { BOOL valid = [DSKeyManager isValidDashAddress:self.paymentAddress forChain:self.chain] || (self.r && [NSURL URLWithString:self.r]); - if (!valid) { - DSLog(@"Not a valid dash request"); - } return valid; } #if SHAPESHIFT_ENABLED else if ([self.scheme isEqualToString:@"bitcoin"]) { BOOL valid = [self.paymentAddress isValidBitcoinAddressOnChain:self.chain] || (self.r && [NSURL URLWithString:self.r]); - if (!valid) { - DSLog(@"Not a valid bitcoin request"); - } return valid; } #endif @@ -270,17 +264,11 @@ - (BOOL)isValidAsDashpayPaymentRequestForBlockchainIdentity:(DSBlockchainIdentit } }]; BOOL valid = [DSKeyManager isValidDashAddress:self.paymentAddress forChain:self.chain] || (self.r && [NSURL URLWithString:self.r]) || friendshipDerivationPath; - if (!valid) { - DSLog(@"Not a valid dash request"); - } return valid; } #if SHAPESHIFT_ENABLED else if ([self.scheme isEqualToString:@"bitcoin"]) { BOOL valid = ([self.paymentAddress isValidBitcoinAddressOnChain:self.chain] || (self.r && [NSURL URLWithString:self.r])) ? YES : NO; - if (!valid) { - DSLog(@"Not a valid bitcoin request"); - } return valid; } #endif @@ -469,9 +457,6 @@ + (void)fetch:(NSString *)url scheme:(NSString *)scheme callbackScheme:(NSString } if (!request) { - DSLog(@"unexpected response from %@:\n%@", req.URL.host, - [[NSString alloc] initWithData:data - encoding:NSUTF8StringEncoding]); completion(nil, [NSError errorWithCode:417 descriptionKey:[NSString stringWithFormat:DSLocalizedString(@"Unexpected response from %@", nil), req.URL.host]]); } else if (![request.details.chain isEqual:chain]) { @@ -518,9 +503,6 @@ + (void)postPayment:(DSPaymentProtocolPayment *)payment scheme:(NSString *)schem } if (!ack) { - DSLog(@"unexpected response from %@:\n%@", req.URL.host, - [[NSString alloc] initWithData:data - encoding:NSUTF8StringEncoding]); if (completion) { completion(nil, [NSError errorWithCode:417 descriptionKey:[NSString stringWithFormat:DSLocalizedString(@"Unexpected response from %@", nil), req.URL.host]]); } diff --git a/DashSync/shared/Models/Persistence/DSDataController.m b/DashSync/shared/Models/Persistence/DSDataController.m index 4433cd12c..4a290846c 100644 --- a/DashSync/shared/Models/Persistence/DSDataController.m +++ b/DashSync/shared/Models/Persistence/DSDataController.m @@ -96,19 +96,15 @@ - (void)loadPersistentContainer { [self.persistentContainer loadPersistentStoresWithCompletionHandler:^(NSPersistentStoreDescription *description, NSError *error) { if (error != nil) { - DSLog(@"Failed to load Core Data stack: %@", error); #if (DEBUG && 1) abort(); #else NSURL *storeURL = [self.class storeURL]; // if this is a not a debug build, attempt to delete and create a new persisent data store before crashing - if (![[NSFileManager defaultManager] removeItemAtURL:storeURL error:&error]) { - DSLog(@"%s: %@", __func__, error); - } + [[NSFileManager defaultManager] removeItemAtURL:storeURL error:&error]; [self.persistentContainer loadPersistentStoresWithCompletionHandler:^(NSPersistentStoreDescription *description, NSError *error) { if (error != nil) { - DSLog(@"Failed to load Core Data stack again: %@", error); abort(); } }]; diff --git a/DashSync/shared/Models/Persistence/Migration/DSCoreDataMigrator.m b/DashSync/shared/Models/Persistence/Migration/DSCoreDataMigrator.m index 02bf3d5ce..1cbd2a953 100644 --- a/DashSync/shared/Models/Persistence/Migration/DSCoreDataMigrator.m +++ b/DashSync/shared/Models/Persistence/Migration/DSCoreDataMigrator.m @@ -104,19 +104,15 @@ + (void)performMigrationWithCompletionQueue:(dispatch_queue_t)completionQueue co if (![[NSFileManager defaultManager] fileExistsAtPath:appSupportDir isDirectory:NULL]) { //Create one if (![[NSFileManager defaultManager] createDirectoryAtPath:appSupportDir withIntermediateDirectories:YES attributes:nil error:&error]) { - NSLog(@"%@", error.localizedDescription); + NSLog(@"Failed to create App Support directory: %@", error.localizedDescription); + NSAssert(NO, @"App Support directory creation failed: %@", error.localizedDescription); } else { NSURL *url = [NSURL fileURLWithPath:appSupportDir]; - if (![url setResourceValue:@YES - forKey:NSURLIsExcludedFromBackupKey - error:&error]) { - DSLog(@"Error excluding %@ from backup %@", url.lastPathComponent, error.localizedDescription); - } else { - DSLog(@"Excluding"); + if (![url setResourceValue:@YES forKey:NSURLIsExcludedFromBackupKey error:&error]) { + NSLog(@"Failed to exclude App Support from backup: %@", error.localizedDescription); } } } - NSAssert(error == nil, @"Creation should have succeeded"); if ([[NSFileManager defaultManager] fileExistsAtPath:[[self documentsWALURL] path]]) { [[NSFileManager defaultManager] copyItemAtURL:[self documentsWALURL] toURL:[DSDataController storeWALURL] error:&error]; NSAssert(error == nil, @"Copy should have succeeded"); @@ -214,7 +210,6 @@ + (void)migrateStoreAtURL:(NSURL *)storeURL toURL:(NSURL *)finalStoreURL toVersi } DSCoreDataMigrationVersionValue sourceVersion = [DSCoreDataMigrationVersion compatibleVersionForStoreMetadata:metadata]; if (sourceVersion == NSNotFound) { - DSLog(@"unknown source version at URL %@", storeURL); return @[]; } diff --git a/DashSync/shared/Models/Persistence/Migration/Policies/DSDeleteEntityMigrationPolicy.m b/DashSync/shared/Models/Persistence/Migration/Policies/DSDeleteEntityMigrationPolicy.m index 239d11a2a..ca92497c8 100644 --- a/DashSync/shared/Models/Persistence/Migration/Policies/DSDeleteEntityMigrationPolicy.m +++ b/DashSync/shared/Models/Persistence/Migration/Policies/DSDeleteEntityMigrationPolicy.m @@ -23,7 +23,6 @@ - (BOOL)createDestinationInstancesForSourceInstance:(NSManagedObject *)sInstance entityMapping:(NSEntityMapping *)mapping manager:(NSMigrationManager *)manager error:(NSError *__autoreleasing _Nullable *)error { - DSLog(@"Deleting Instance %@", sInstance); return YES; } @@ -31,7 +30,6 @@ - (BOOL)createRelationshipsForDestinationInstance:(NSManagedObject *)dInstance entityMapping:(NSEntityMapping *)mapping manager:(NSMigrationManager *)manager error:(NSError *__autoreleasing _Nullable *)error { - DSLog(@"Deleting relationships on %@", dInstance); return YES; } diff --git a/DashSync/shared/Models/Transactions/Base/DSInstantSendTransactionLock.m b/DashSync/shared/Models/Transactions/Base/DSInstantSendTransactionLock.m index 5a2fb3cfd..79ea2823f 100644 --- a/DashSync/shared/Models/Transactions/Base/DSInstantSendTransactionLock.m +++ b/DashSync/shared/Models/Transactions/Base/DSInstantSendTransactionLock.m @@ -166,7 +166,6 @@ - (UInt256)requestID { [data appendData:input]; } _requestID = [data SHA256_2]; - DSLogPrivate(@"[%@] the request ID is %@", self.chain.name, uint256_hex(_requestID)); return _requestID; } @@ -205,29 +204,16 @@ - (BOOL)verifySignatureWithQuorumOffset:(uint32_t)offset { DSQuorumEntry *quorumEntry = [self.chain.chainManager.masternodeManager quorumEntryForInstantSendRequestID:[self requestID] withBlockHeightOffset:offset]; if (quorumEntry && quorumEntry.verified) { self.signatureVerified = [self verifySignatureAgainstQuorum:quorumEntry]; - if (!self.signatureVerified) { - DSLog(@"[%@] unable to verify IS signature with offset %d", self.chain.name, offset); - } else { - DSLog(@"[%@] IS signature verified with offset %d", self.chain.name, offset); - } - - } else if (quorumEntry) { - DSLog(@"[%@] quorum entry %@ found but is not yet verified", self.chain.name, uint256_hex(quorumEntry.quorumHash)); - } else { - DSLog(@"[%@] no quorum entry found", self.chain.name); } if (self.signatureVerified) { self.intendedQuorum = quorumEntry; } else if (quorumEntry.verified && offset == 8) { //try again a few blocks more in the past - DSLog(@"[%@] trying with offset 0", self.chain.name); return [self verifySignatureWithQuorumOffset:0]; } else if (quorumEntry.verified && offset == 0) { //try again a few blocks more in the future - DSLog(@"[%@] trying with offset 16", self.chain.name); return [self verifySignatureWithQuorumOffset:16]; } - DSLog(@"[%@] returning signature verified %d with offset %d", self.chain.name, self.signatureVerified, offset); return self.signatureVerified; } diff --git a/DashSync/shared/Models/Transactions/Base/DSTransaction.m b/DashSync/shared/Models/Transactions/Base/DSTransaction.m index 7f3d8de0e..a71e9e051 100644 --- a/DashSync/shared/Models/Transactions/Base/DSTransaction.m +++ b/DashSync/shared/Models/Transactions/Base/DSTransaction.m @@ -953,7 +953,6 @@ - (BOOL)saveInitialInContext:(NSManagedObjectContext *)context { if (![context ds_save]) { self.persistenceStatus = DSTransactionPersistenceStatus_Saved; } else { - DSLog(@"[%@] There was an error saving the transaction", self.chain.name); self.persistenceStatus = DSTransactionPersistenceStatus_NotSaved; } } else { diff --git a/DashSync/shared/Models/Transactions/Provider/DSProviderRegistrationTransaction.m b/DashSync/shared/Models/Transactions/Provider/DSProviderRegistrationTransaction.m index 4a9c3526a..35460220e 100644 --- a/DashSync/shared/Models/Transactions/Provider/DSProviderRegistrationTransaction.m +++ b/DashSync/shared/Models/Transactions/Provider/DSProviderRegistrationTransaction.m @@ -133,7 +133,6 @@ - (instancetype)initWithProviderRegistrationTransactionVersion:(uint16_t)version self.platformNodeID = platformNodeID; self.operatorReward = operatorReward; self.scriptPayout = scriptPayout; - DSLogPrivate(@"[%@] Creating provider (masternode) with ownerKeyHash %@", chain.name, uint160_data(ownerKeyHash)); return self; } @@ -164,7 +163,6 @@ - (instancetype)initWithInputHashes:(NSArray *)hashes inputIndexes:(NSArray *)in self.scriptPayout = scriptPayout; [self hasSetInputsAndOutputs]; - DSLogPrivate(@"[%@] Creating provider (masternode) with ownerKeyHash %@", chain.name, uint160_data(ownerKeyHash)); return self; } diff --git a/DashSync/shared/Models/Transactions/Provider/DSProviderUpdateRegistrarTransaction.m b/DashSync/shared/Models/Transactions/Provider/DSProviderUpdateRegistrarTransaction.m index cd7210ae8..4b03757d1 100644 --- a/DashSync/shared/Models/Transactions/Provider/DSProviderUpdateRegistrarTransaction.m +++ b/DashSync/shared/Models/Transactions/Provider/DSProviderUpdateRegistrarTransaction.m @@ -148,7 +148,6 @@ - (BOOL)checkPayloadSignature { - (void)signPayloadWithKey:(OpaqueKey *)privateKey { //ATTENTION If this ever changes from ECDSA, change the max signature size defined above - //DSLogPrivate(@"Private Key is %@", [privateKey serializedPrivateKeyForChain:self.chain]); self.payloadSignature = [DSKeyManager NSDataFrom:key_ecdsa_compact_sign(privateKey->ecdsa, [self payloadHash].u8)];; } diff --git a/DashSync/shared/Models/Wallet/DSAccount.m b/DashSync/shared/Models/Wallet/DSAccount.m index d994a0554..70ede5a78 100644 --- a/DashSync/shared/Models/Wallet/DSAccount.m +++ b/DashSync/shared/Models/Wallet/DSAccount.m @@ -48,6 +48,7 @@ #import "DSAuthenticationManager.h" #import "DSBIP39Mnemonic.h" #import "DSChainEntity+CoreDataClass.h" +#import "DSLogger.h" #import "DSCoinbaseTransaction.h" #import "DSCreditFundingTransaction.h" #import "DSDerivationPathEntity+CoreDataClass.h" @@ -69,8 +70,6 @@ #import "NSMutableData+Dash.h" #import "NSString+Dash.h" -#define LOG_BALANCE_UPDATE 0 - #define AUTH_SWEEP_KEY @"AUTH_SWEEP_KEY" #define AUTH_SWEEP_FEE @"AUTH_SWEEP_FEE" @@ -169,7 +168,7 @@ - (void)verifyAndAssignAddedDerivationPaths:(NSArray *)deriv } self.coinJoinDerivationPath = (DSFundsDerivationPath *)derivationPath; } - + for (int j = i + 1; j < [derivationPaths count]; j++) { DSDerivationPath *derivationPath2 = [derivationPaths objectAtIndex:j]; NSAssert([derivationPath isDerivationPathEqual:derivationPath2] == NO, @"Derivation paths should all be different"); @@ -183,7 +182,7 @@ - (void)verifyAndAssignAddedDerivationPaths:(NSArray *)deriv - (instancetype)initWithAccountNumber:(uint32_t)accountNumber withDerivationPaths:(NSArray *)derivationPaths inContext:(NSManagedObjectContext *)context { NSParameterAssert(derivationPaths); - + if (!(self = [super init])) return nil; _accountNumber = accountNumber; [self verifyAndAssignAddedDerivationPaths:derivationPaths]; @@ -207,12 +206,12 @@ - (instancetype)initWithAccountNumber:(uint32_t)accountNumber withDerivationPath - (instancetype)initAsViewOnlyWithAccountNumber:(uint32_t)accountNumber withDerivationPaths:(NSArray *)derivationPaths inContext:(NSManagedObjectContext *)context { NSParameterAssert(derivationPaths); - + if (!(self = [self initWithAccountNumber:accountNumber withDerivationPaths:derivationPaths inContext:context])) return nil; self.isViewOnlyAccount = TRUE; self.transactionsToSave = [NSMutableArray array]; self.transactionsToSaveInBlockSave = [NSMutableDictionary dictionary]; - + return self; } @@ -224,34 +223,21 @@ - (void)setWallet:(DSWallet *)wallet { } } -#define TEST_LOG_ALL_TRANSACTIONS 0 - - (void)loadTransactions { if (_wallet.isTransient) return; - //NSDate *startTime = [NSDate date]; [self.managedObjectContext performBlockAndWait:^{ -#if TEST_LOG_ALL_TRANSACTIONS - NSArray *transactions = [DSTransactionEntity objectsInContext:self.managedObjectContext matching:@"transactionHash.chain == %@", [self.wallet.chain chainEntityInContext:self.managedObjectContext]]; - for (DSTransactionEntity *entity in transactions) { - DSTransaction *transaction = [entity transactionForChain:self.wallet.chain]; - DSLogPrivate(@"[%@] Transaction %@", _wallet.chain.name, [transaction longDescription]); - } -#endif - NSUInteger transactionCount = [DSTransactionEntity countObjectsInContext:self.managedObjectContext matching:@"transactionHash.chain == %@", [self.wallet.chain chainEntityInContext:self.managedObjectContext]]; if (transactionCount > self.allTx.count) { // pre-fetch transaction inputs and outputs @autoreleasepool { NSFetchRequest *fetchRequest = [DSTxOutputEntity fetchRequest]; - + //for some reason it is faster to search by the wallet unique id on the account, then it is by the account itself, this might change if there are more than 1 account; fetchRequest.predicate = [NSPredicate predicateWithFormat:@"account.walletUniqueID = %@ && account.index = %@", self.wallet.uniqueIDString, @(self.accountNumber)]; [fetchRequest setRelationshipKeyPathsForPrefetching:@[@"transaction.inputs", @"transaction.outputs", @"transaction.transactionHash", @"spentInInput.transaction.inputs", @"spentInInput.transaction.outputs", @"spentInInput.transaction.transactionHash"]]; - + NSError *fetchRequestError = nil; - //NSDate *transactionOutputsStartTime = [NSDate date]; NSArray *transactionOutputs = [self.managedObjectContext executeFetchRequest:fetchRequest error:&fetchRequestError]; - //DSLog(@"TransactionOutputsStartTime: %f", -[transactionOutputsStartTime timeIntervalSinceNow]); for (DSTxOutputEntity *e in transactionOutputs) { @autoreleasepool { if (e.transaction.transactionHash) { @@ -278,7 +264,6 @@ - (void)loadTransactions { } } }]; - //DSLog(@"Time: %f", -[startTime timeIntervalSinceNow]); [self sortTransactions]; _balance = UINT64_MAX; // trigger balance changed notification even if balance is zero [self updateBalance]; @@ -332,7 +317,7 @@ - (NSString *)uniqueID { - (uint32_t)blockHeight { static uint32_t height = 0; uint32_t h = self.wallet.chain.lastSyncBlockHeight; - + if (h > height) height = h; return height; } @@ -382,7 +367,7 @@ - (NSArray *)unspentOutputs { - (void)removeDerivationPath:(DSDerivationPath *)derivationPath { NSParameterAssert(derivationPath); - + if ([self.mFundDerivationPaths containsObject:derivationPath]) { [self.mFundDerivationPaths removeObject:derivationPath]; } @@ -406,7 +391,7 @@ - (DSIncomingFundsDerivationPath *)derivationPathForFriendshipWithIdentifier:(NS - (void)addDerivationPath:(DSDerivationPath *)derivationPath { NSParameterAssert(derivationPath); - + if (!_isViewOnlyAccount) { [self verifyAndAssignAddedDerivationPaths:@[derivationPath]]; } @@ -441,7 +426,7 @@ - (void)addOutgoingDerivationPath:(DSIncomingFundsDerivationPath *)derivationPat - (void)addDerivationPathsFromArray:(NSArray *)derivationPaths { NSParameterAssert(derivationPaths); - + if (!_isViewOnlyAccount) { [self verifyAndAssignAddedDerivationPaths:derivationPaths]; } @@ -487,7 +472,7 @@ - (NSArray *)registerAddressesWithGapLimit:(NSUInteger)gapLimit unusedAccountGap if ([derivationPath isKindOfClass:[DSFundsDerivationPath class]]) { DSFundsDerivationPath *fundsDerivationPath = (DSFundsDerivationPath *)derivationPath; NSUInteger registerGapLimit = 0; - + if ([fundsDerivationPath shouldUseReducedGapLimit]) { registerGapLimit = unusedAccountGapLimit; } else if (fundsDerivationPath.type == DSDerivationPathType_AnonymousFunds) { @@ -495,7 +480,7 @@ - (NSArray *)registerAddressesWithGapLimit:(NSUInteger)gapLimit unusedAccountGap } else { registerGapLimit = gapLimit; } - + [mArray addObjectsFromArray:[fundsDerivationPath registerAddressesWithGapLimit:registerGapLimit internal:internal error:error]]; } else if (!internal && [derivationPath isKindOfClass:[DSIncomingFundsDerivationPath class]]) { [mArray addObjectsFromArray:[(DSIncomingFundsDerivationPath *)derivationPath registerAddressesWithGapLimit:dashpayGapLimit error:error]]; @@ -553,7 +538,7 @@ - (BOOL)containsAddress:(NSString *)address { //in case address is of type [NSNull null] return FALSE; } - + for (DSFundsDerivationPath *derivationPath in self.fundDerivationPaths) { if ([derivationPath containsAddress:address]) return TRUE; } @@ -569,7 +554,7 @@ - (BOOL)containsCoinJoinAddress:(NSString *)coinJoinAddress { } if ([self.coinJoinDerivationPath containsAddress:coinJoinAddress]) return TRUE; - + return FALSE; } @@ -580,7 +565,7 @@ - (BOOL)containsInternalAddress:(NSString *)address { //in case address is of type [NSNull null] return FALSE; } - + for (DSFundsDerivationPath *derivationPath in self.fundDerivationPaths) { if ([derivationPath isKindOfClass:[DSFundsDerivationPath class]] && [derivationPath containsChangeAddress:address]) { return TRUE; @@ -595,7 +580,7 @@ - (BOOL)baseDerivationPathsContainAddress:(NSString *)address { //in case address is of type [NSNull null] return FALSE; } - + for (DSFundsDerivationPath *derivationPath in self.fundDerivationPaths) { if ([derivationPath isKindOfClass:[DSFundsDerivationPath class]] && [derivationPath containsAddress:address]) { return TRUE; @@ -611,7 +596,7 @@ - (BOOL)containsExternalAddress:(NSString *)address { //in case address is of type [NSNull null] return FALSE; } - + for (DSDerivationPath *derivationPath in self.fundDerivationPaths) { if ([derivationPath isKindOfClass:[DSFundsDerivationPath class]]) { if ([(DSFundsDerivationPath *)derivationPath containsReceiveAddress:address]) return TRUE; @@ -628,7 +613,7 @@ - (DSIncomingFundsDerivationPath *)externalDerivationPathContainingAddress:(NSSt //in case address is of type [NSNull null] return nil; } - + for (DSIncomingFundsDerivationPath *derivationPath in self.mContactOutgoingFundDerivationPathsDictionary.allValues) { if ([derivationPath containsAddress:address]) return derivationPath; } @@ -642,7 +627,7 @@ - (BOOL)addressIsUsed:(NSString *)address { //in case address is of type [NSNull null] return FALSE; } - + for (DSFundsDerivationPath *derivationPath in self.fundDerivationPaths) { if ([derivationPath addressIsUsed:address]) return TRUE; } @@ -655,7 +640,7 @@ - (BOOL)transactionAddressAlreadySeenInOutputs:(NSString *)address { //in case address is of type [NSNull null] return FALSE; } - + for (DSTransaction *transaction in self.allTransactions) { if ([transaction.outputs indexOfObjectPassingTest:^BOOL(DSTransactionOutput *_Nonnull obj, NSUInteger idx, BOOL *_Nonnull stop) { return [obj.address isEqual:address]; @@ -672,21 +657,18 @@ - (void)updateBalance { NSMutableSet *spentOutputs = [NSMutableSet set], *invalidTx = [NSMutableSet set], *pendingTransactionHashes = [NSMutableSet set]; NSMutableDictionary *pendingCoinbaseLockedTransactionHashes = [NSMutableDictionary dictionary]; uint32_t now = [NSDate timeIntervalSince1970]; - + for (DSFundsDerivationPath *derivationPath in self.fundDerivationPaths) { derivationPath.balance = 0; } - + for (DSTransaction *tx in [self.transactions reverseObjectEnumerator]) { -#if LOG_BALANCE_UPDATE - DSLogPrivate(@"updating balance after transaction %@", [NSData dataWithUInt256:tx.txHash].reverse.hexString); -#endif @autoreleasepool { NSMutableSet *spent = [NSMutableSet set]; NSSet *inputs; uint32_t n = 0; BOOL pending = NO; - + if (!tx.isCoinbaseClassicTransaction && ![tx isKindOfClass:[DSCoinbaseTransaction class]]) { NSMutableArray *rHashes = [NSMutableArray array]; @@ -705,58 +687,53 @@ - (void)updateBalance { } else { inputs = [NSSet set]; } - + + // Log UTXO state changes - inputs being marked as spent + for (NSValue *spentOutput in spent) { + DSUTXO o; + [spentOutput getValue:&o]; + DSLogInfo(@"DSAccount", @" marked %@:%u as spent by %@", + uint256_reverse_hex(o.hash), o.n, uint256_reverse_hex(tx.txHash)); + } [spentOutputs unionSet:spent]; // add inputs to spent output set n = 0; - + // check if any inputs are pending if (tx.blockHeight == TX_UNCONFIRMED) { if (tx.size > TX_MAX_SIZE) { pending = YES; // check transaction size is under TX_MAX_SIZE } - + for (DSTransactionInput *input in tx.inputs) { if (input.sequence == UINT32_MAX) continue; - + if (tx.lockTime < TX_MAX_LOCK_HEIGHT && tx.lockTime > self.wallet.chain.bestBlockHeight + 1) { pending = YES; // future lockTime -#if DEBUG - DSLogPrivate(@"received input lockTime %d for transaction %@", tx.lockTime, [NSData dataWithUInt256:tx.txHash].reverse.hexString); -#else - DSLog(@"received input lockTime %d for transaction %@", tx.lockTime, @""); -#endif + DSLogInfo(@"DSAccount", @"received input with future lockTime %d for transaction %@", tx.lockTime, uint256_reverse_hex(tx.txHash)); } if (tx.lockTime >= TX_MAX_LOCK_HEIGHT && tx.lockTime > now) { pending = YES; // future locktime -#if DEBUG - DSLogPrivate(@"received input lockTime %d for transaction %@", tx.lockTime, [NSData dataWithUInt256:tx.txHash].reverse.hexString); -#else - DSLog(@"received input lockTime %d for transaction %@", tx.lockTime, @""); -#endif + DSLogInfo(@"DSAccount", @"received input with future lockTime %d for transaction %@", tx.lockTime, uint256_reverse_hex(tx.txHash)); } } - + for (DSTransactionOutput *output in tx.outputs) { // check that no outputs are dust if (output.amount < TX_MIN_OUTPUT_AMOUNT) { pending = YES; -#if DEBUG - DSLogPrivate(@"received dust output %llu for transaction %@", output.amount, [NSData dataWithUInt256:tx.txHash].reverse.hexString); -#else - DSLog(@"received dust output %llu for transaction %@", output.amount, @""); -#endif + DSLogInfo(@"DSAccount", @"received dust output %llu for transaction %@", output.amount, uint256_reverse_hex(tx.txHash)); } } } - + if (pending || [inputs intersectsSet:pendingTransactionHashes]) { [pendingTransactionHashes addObject:uint256_obj(tx.txHash)]; continue; } - + uint32_t lockedBlockHeight = [self transactionOutputsAreLockedTill:tx]; - + if (lockedBlockHeight) { if (![pendingCoinbaseLockedTransactionHashes objectForKey:@(lockedBlockHeight)]) { pendingCoinbaseLockedTransactionHashes[@(lockedBlockHeight)] = [NSMutableSet set]; @@ -764,7 +741,7 @@ - (void)updateBalance { [((NSMutableSet *)pendingCoinbaseLockedTransactionHashes[@(lockedBlockHeight)]) addObject:uint256_obj(tx.txHash)]; continue; } - + //TODO: don't add outputs below TX_MIN_OUTPUT_AMOUNT //TODO: don't add coin generation outputs < 100 blocks deep //NOTE: balance/UTXOs will then need to be recalculated when last block changes @@ -782,49 +759,36 @@ - (void)updateBalance { } n++; } - + // transaction ordering is not guaranteed, so check the entire UTXO set against the entire spent output set [spent setSet:utxos.set]; [spent intersectSet:spentOutputs]; - + for (NSValue *output in spent) { // remove any spent outputs from UTXO set DSTransaction *transaction; DSUTXO o; - + [output getValue:&o]; transaction = self.allTx[uint256_obj(o.hash)]; [utxos removeObject:output]; - DSTransactionOutput *output = transaction.outputs[o.n]; - uint64_t amount = output.amount; + DSTransactionOutput *txOutput = transaction.outputs[o.n]; + uint64_t amount = txOutput.amount; + DSLogInfo(@"DSAccount", @" %@:%u prevtx <-unspent ->spent", uint256_reverse_hex(o.hash), o.n); balance -= amount; for (DSFundsDerivationPath *derivationPath in self.fundDerivationPaths) { - if ([derivationPath containsAddress:output.address]) { + if ([derivationPath containsAddress:txOutput.address]) { derivationPath.balance -= amount; break; } } } - + if (prevBalance < balance) totalReceived += balance - prevBalance; if (balance < prevBalance) totalSent += prevBalance - balance; prevBalance = balance; -#if LOG_BALANCE_UPDATE - DSLog(@"===UTXOS==="); - for (NSValue *utxo in utxos) { - DSUTXO o; - [utxo getValue:&o]; - DSLogPrivate(@"--%@ (%lu)", [NSData dataWithUInt256:o.hash].reverse.hexString, o.n); - } - DSLog(@"===Spent Outputs==="); - for (NSValue *utxo in spentOutputs) { - DSUTXO o; - [utxo getValue:&o]; - DSLogPrivate(@"--%@ (%lu)", [NSData dataWithUInt256:o.hash].reverse.hexString, o.n); - } -#endif } } - + self.invalidTransactionHashes = invalidTx; self.pendingTransactionHashes = pendingTransactionHashes; self.pendingCoinbaseLockedTransactionHashes = pendingCoinbaseLockedTransactionHashes; @@ -832,10 +796,17 @@ - (void)updateBalance { self.utxos = utxos; _totalSent = totalSent; _totalReceived = totalReceived; - + if (balance != _balance) { + // Only log if not the initial UINT64_MAX state (used to trigger notifications on first load) + if (_balance != UINT64_MAX) { + DSLogInfo(@"DSAccount", @"Balance updated: %.8f -> %.8f DASH, UTXOs: %lu, totalSent: %.8f, totalReceived: %.8f", + (double)_balance / 100000000.0, (double)balance / 100000000.0, + (unsigned long)utxos.count, + (double)totalSent / 100000000.0, (double)totalReceived / 100000000.0); + } _balance = balance; - + dispatch_async(dispatch_get_main_queue(), ^{ [NSObject cancelPreviousPerformRequestsWithTarget:self selector:@selector(postBalanceDidChangeNotification) object:nil]; [self performSelector:@selector(postBalanceDidChangeNotification) withObject:nil afterDelay:0.1]; @@ -857,7 +828,7 @@ static NSUInteger transactionAddressIndex(DSTransaction *transaction, NSArray *a NSUInteger i = [addressChain indexOfObject:output.address]; if (i != NSNotFound) return i; } - + return NSNotFound; } @@ -882,18 +853,18 @@ __block __weak BOOL (^_isAscending)(id, id) = isAscending = ^BOOL(DSTransaction return NO; }; - + NSArray *externalAddresses = self.externalAddresses; NSArray *internalAddresses = self.internalAddresses; - + [self.transactions sortWithOptions:NSSortStable usingComparator:^NSComparisonResult(id tx1, id tx2) { if (isAscending(tx1, tx2)) return NSOrderedAscending; if (isAscending(tx2, tx1)) return NSOrderedDescending; - + NSUInteger i = transactionAddressIndex(tx1, internalAddresses); NSUInteger j = transactionAddressIndex(tx2, (i == NSNotFound) ? externalAddresses : internalAddresses); - + if (i == NSNotFound && j != NSNotFound) i = transactionAddressIndex(tx1, externalAddresses); if (i == NSNotFound || j == NSNotFound || i == j) return NSOrderedSame; return (i > j) ? NSOrderedAscending : NSOrderedDescending; @@ -983,14 +954,14 @@ - (BOOL)canContainTransaction:(DSTransaction *)transaction { DSProviderUpdateRegistrarTransaction *providerUpdateRegistrarTransaction = (DSProviderUpdateRegistrarTransaction *)transaction; if ([self containsAddress:providerUpdateRegistrarTransaction.payoutAddress]) return YES; } - + return NO; } } - (BOOL)checkIsFirstTransaction:(DSTransaction *)transaction { NSParameterAssert(transaction); - + for (DSDerivationPath *derivationPath in self.fundDerivationPaths) { if ([derivationPath type] & DSDerivationPathType_IsForFunds) { NSString *firstAddress; @@ -1021,11 +992,11 @@ - (DSTransaction *)transactionFor:(uint64_t)amount to:(NSString *)address withFe // returns an unsigned transaction that sends the specified amount from the wallet to the given address - (DSCreditFundingTransaction *)creditFundingTransactionFor:(uint64_t)amount to:(NSString *)address withFee:(BOOL)fee { NSParameterAssert(address); - + NSMutableData *script = [NSMutableData data]; - + [script appendCreditBurnScriptPubKeyForAddress:address forChain:self.wallet.chain]; - + DSCreditFundingTransaction *transaction = [[DSCreditFundingTransaction alloc] initOnChain:self.wallet.chain]; return (DSCreditFundingTransaction *)[self updateTransaction:transaction forAmounts:@[@(amount)] toOutputScripts:@[script] withFee:fee sortType:DSTransactionSortType_BIP69]; } @@ -1101,7 +1072,7 @@ - (DSTransaction *)updateTransaction:(DSTransaction *)transaction // attacker double spending and requesting a refund for (NSValue *output in self.utxos) { [output getValue:&o]; - + if (coinControl && ![coinControl isSelected:o]) continue; tx = self.allTx[uint256_obj(o.hash)]; if ([self transactionOutputsAreLocked:tx]) continue; @@ -1127,7 +1098,7 @@ - (DSTransaction *)updateTransaction:(DSTransaction *)transaction // check for sufficient total funds before building a smaller transaction if (self.balance < amount + [self.wallet.chain feeForTxSize:txSize + cpfpSize]) { - DSLog(@"[%@] Insufficient funds. %llu is less than transaction amount:%llu", self.wallet.chain.name, self.balance, + DSLogInfo(@"DSAccount", @"[%@] Insufficient funds. %llu is less than transaction amount:%llu", self.wallet.chain.name, self.balance, amount + [self.wallet.chain feeForTxSize:txSize + cpfpSize]); return nil; } @@ -1166,7 +1137,7 @@ - (DSTransaction *)updateTransaction:(DSTransaction *)transaction } if (balance < amount + feeAmount) { // insufficient funds - DSLog(@"[%@] Insufficient funds. %llu is less than transaction amount:%llu", self.wallet.chain.name, balance, amount + feeAmount); + DSLogInfo(@"DSAccount", @"[%@] Insufficient funds. %llu is less than transaction amount:%llu", self.wallet.chain.name, balance, amount + feeAmount); return nil; } @@ -1177,18 +1148,18 @@ - (DSTransaction *)updateTransaction:(DSTransaction *)transaction if (followBIP69sorting) { [transaction sortInputsAccordingToBIP69]; } - + if (balance - (amount + feeAmount) >= self.wallet.chain.minOutputAmount) { NSString *changeAddress; - + if (coinControl.destChange) { changeAddress = coinControl.destChange; } else { changeAddress = self.changeAddress; } - + [transaction addOutputAddress:changeAddress amount:balance - (amount + feeAmount)]; - + if (followBIP69sorting) { [transaction sortOutputsAccordingToBIP69]; } else if (sortType == DSTransactionSortType_Shuffle) { @@ -1198,6 +1169,13 @@ - (DSTransaction *)updateTransaction:(DSTransaction *)transaction [transaction hasSetInputsAndOutputs]; + DSLogInfo(@"DSAccount", @"Completing send tx with %lu outputs, %lu inputs, spending %llu DASH, fee %llu DASH, txId: %@", + (unsigned long)transaction.outputs.count, + (unsigned long)transaction.inputs.count, + amount, + feeAmount, + uint256_reverse_hex(transaction.txHash)); + return transaction; } } @@ -1220,11 +1198,7 @@ - (NSArray *)setBlockHeight:(int32_t)height andTimestamp:(NSTimeInterval)timesta UInt256 h; if (!tx || (tx.blockHeight == height && tx.timestamp == timestamp)) continue; - #if DEBUG - DSLogPrivate(@"[%@] Setting account tx %@ height to %d", self.wallet.chain.name, tx, height); - #else - DSLogPrivate(@"[%@] Setting account tx %@ height to %d", self.wallet.chain.name, @"", height); - #endif + DSLogInfo(@"DSAccount", @"[%@] Setting account tx %@ height to %d", self.wallet.chain.name, uint256_reverse_hex(tx.txHash), height); tx.blockHeight = height; if (tx.timestamp == UINT32_MAX || tx.timestamp == 0) { //We should only update the timestamp one time @@ -1305,7 +1279,7 @@ - (NSArray *)usedDerivationPathsForTransaction:(DSTransaction *)transaction { for (DSFundsDerivationPath *derivationPath in self.fundDerivationPaths) { if (!(derivationPath.type == DSDerivationPathType_ClearFunds || derivationPath.type == DSDerivationPathType_AnonymousFunds)) continue; - + NSMutableOrderedSet *externalIndexes = [NSMutableOrderedSet orderedSet], *internalIndexes = [NSMutableOrderedSet orderedSet]; for (NSString *addr in transaction.inputAddresses) { @@ -1338,12 +1312,12 @@ - (BOOL)signTransaction:(DSTransaction *)transaction anyoneCanPay:(BOOL)anyoneCa NSParameterAssert(transaction); if (_isViewOnlyAccount) return NO; - + NSArray *usedDerivationPaths = [self usedDerivationPathsForTransaction:transaction]; - + @autoreleasepool { // @autoreleasepool ensures sensitive data will be dealocated immediately NSData *seed = [self.wallet requestSeedNoAuth]; - + if (!seed) { return NO; } else { @@ -1411,7 +1385,7 @@ - (void)signTransactions:(NSArray *)transactions withPrompt:(NS NSMutableArray *usedDerivationPaths = [NSMutableArray array]; for (DSFundsDerivationPath *derivationPath in self.fundDerivationPaths) { if (!(derivationPath.type == DSDerivationPathType_ClearFunds || derivationPath.type == DSDerivationPathType_AnonymousFunds)) continue; - + NSMutableOrderedSet *externalIndexes = [NSMutableOrderedSet orderedSet], *internalIndexes = [NSMutableOrderedSet orderedSet]; for (NSString *addr in transaction.inputAddresses) { @@ -1456,11 +1430,6 @@ - (void)signTransactions:(NSArray *)transactions withPrompt:(NS // records the transaction in the account, or returns false if it isn't associated with the wallet - (BOOL)registerTransaction:(DSTransaction *)transaction saveImmediately:(BOOL)saveImmediately { NSParameterAssert(transaction); -#if DEBUG - DSLogPrivate(@"[%@] [DSAccount] registering transaction %@", self.wallet.chain.name, transaction); -#else - DSLog(@"[%@] [DSAccount] registering transaction %@", self.wallet.chain.name, @""); -#endif @synchronized (self) { UInt256 txHash = transaction.txHash; NSValue *hash = uint256_obj(txHash); @@ -1474,20 +1443,12 @@ - (BOOL)registerTransaction:(DSTransaction *)transaction saveImmediately:(BOOL)s return NO; } if (self.allTx[hash] != nil) { - #if DEBUG - DSLogPrivate(@"[%@] [DSAccount] transaction already registered %@", self.wallet.chain.name, transaction); - #else - DSLog(@"[%@] [DSAccount] transaction already registered %@", self.wallet.chain.name, @""); - #endif return YES; } //TODO: handle tx replacement with input sequence numbers (now replacements appear invalid until confirmation) - #if DEBUG - DSLogPrivate(@"[%@] [DSAccount] received unseen transaction %@", self.wallet.chain.name, transaction); - #else - DSLog(@"[%@] [DSAccount] received unseen transaction %@", self.wallet.chain.name, @""); - #endif if ([self checkIsFirstTransaction:transaction]) _firstTransactionHash = txHash; //it's okay if this isn't really the first, as it will be close enough (500 blocks close) + DSLogInfo(@"DSAccount", @"Registering transaction %@, inputs: %lu, outputs: %lu, blockHeight: %u", + uint256_reverse_hex(txHash), (unsigned long)transaction.inputs.count, (unsigned long)transaction.outputs.count, transaction.blockHeight); self.allTx[hash] = transaction; [self.transactions insertObject:transaction atIndex:0]; for (NSString *address in transaction.inputAddresses) { @@ -1558,23 +1519,23 @@ - (BOOL)isSpent:(NSValue *)output { if (!output) { return false; } - + return [self.spentOutputs containsObject:output]; } - (int64_t)inputValue:(UInt256)txHash inputIndex:(uint32_t)index { NSValue *hash = uint256_obj(txHash); DSTransaction *tx = self.allTx[hash]; - + if (tx == NULL) { return -1; } - + if (![self transactionIsValid:tx] || [self.spentOutputs containsObject:dsutxo_obj(((DSUTXO){txHash, index}))]) { return -1; } - + return (int64_t)tx.outputs[index].amount; } @@ -1725,7 +1686,7 @@ - (NSArray *)amountsSentByTransaction:(DSTransaction *)transaction { [amounts addObject:@(0)]; } } - + return amounts; } @@ -1860,7 +1821,7 @@ - (void)sweepPrivateKey:(NSString *)privKey withFee:(BOOL)fee completion:^(void (^sweepCompletion)(DSTransaction *tx, uint64_t fee, NSError *error), NSDictionary *userInfo, NSString *password) { dispatch_async(dispatch_get_main_queue(), ^{ NSString *key = [DSKeyManager ecdsaKeyWithBIP38Key:userInfo[AUTH_SWEEP_KEY] passphrase:password forChainType:self.wallet.chain.chainType]; - + if (!key) { [[DSAuthenticationManager sharedInstance] badKeyPasswordForSweepCompletion:^{ @@ -1881,7 +1842,7 @@ - (void)sweepPrivateKey:(NSString *)privKey withFee:(BOOL)fee NSString *address = [DSKeyManager NSStringFrom:address_for_ecdsa_key(key, self.wallet.chain.chainType)]; NSData *publicKeyData = [DSKeyManager NSDataFrom:key_ecdsa_public_key_data(key)]; processor_destroy_ecdsa_key(key); - + if (!address) { completion(nil, 0, [NSError errorWithCode:187 localizedDescriptionKey:@"Not a valid private key"]); return; diff --git a/DashSync/shared/Models/Wallet/DSBIP39Mnemonic.m b/DashSync/shared/Models/Wallet/DSBIP39Mnemonic.m index 0b467b609..30ed28207 100644 --- a/DashSync/shared/Models/Wallet/DSBIP39Mnemonic.m +++ b/DashSync/shared/Models/Wallet/DSBIP39Mnemonic.m @@ -225,9 +225,6 @@ - (NSData *_Nullable)decodeWordArray:(NSArray *)wordArray inLanguage:(DSBIP39Lan uint32_t wordArrayCount = (uint32_t)wordArray.count; if ((wordArrayCount % 3) != 0 || wordArrayCount > 24) { -#if DEBUG - DSLogPrivate(@"phrase has wrong number of words"); -#endif return nil; } @@ -236,9 +233,6 @@ - (NSData *_Nullable)decodeWordArray:(NSArray *)wordArray inLanguage:(DSBIP39Lan y = (i * 8 / 11 + 1 < wordArrayCount) ? (uint32_t)[words indexOfObject:wordArray[i * 8 / 11 + 1]] : 0; if (x == (uint32_t)NSNotFound || y == (uint32_t)NSNotFound) { -#if DEBUG - DSLogPrivate(@"phrase contained unknown word: %@ in %lu", wordArray[i * 8 / 11 + (x == (uint32_t)NSNotFound ? 0 : 1)], (unsigned long)language); -#endif return nil; } diff --git a/DashSync/shared/Models/Wallet/DSSpecialTransactionsWalletHolder.m b/DashSync/shared/Models/Wallet/DSSpecialTransactionsWalletHolder.m index 31a6a65a1..b682d51ee 100644 --- a/DashSync/shared/Models/Wallet/DSSpecialTransactionsWalletHolder.m +++ b/DashSync/shared/Models/Wallet/DSSpecialTransactionsWalletHolder.m @@ -388,11 +388,6 @@ - (NSArray *)setBlockHeight:(int32_t)height andTimestamp:(NSTimeInterval)timesta UInt256 h; if (!tx || (tx.blockHeight == height && tx.timestamp == timestamp)) continue; -#if DEBUG - DSLogPrivate(@"[%@] Setting special tx %@ height to %d", self.wallet.chain.name, tx, height); -#else - DSLog(@"[%@] Setting special tx %@ height to %d", self.wallet.chain.name, @"", height); -#endif tx.blockHeight = height; if (tx.timestamp == UINT32_MAX || tx.timestamp == 0) { //We should only update the timestamp one time diff --git a/DashSync/shared/Models/Wallet/DSWallet.m b/DashSync/shared/Models/Wallet/DSWallet.m index 4a619cc4c..7833dee3d 100644 --- a/DashSync/shared/Models/Wallet/DSWallet.m +++ b/DashSync/shared/Models/Wallet/DSWallet.m @@ -562,11 +562,6 @@ - (void)migrateWalletCreationTime { NSTimeInterval realWalletCreationTime = [realWalletCreationDate timeIntervalSince1970]; if (realWalletCreationTime && (realWalletCreationTime != REFERENCE_DATE_2001)) { _walletCreationTime = MAX(realWalletCreationTime, BIP39_CREATION_TIME); //safeguard -#if DEBUG - DSLogPrivate(@"[%@] real wallet creation set to %@", self.chain.name, realWalletCreationDate); -#else - DSLog(@"[%@] real wallet creation set to %@", self.chain.name, @""); -#endif setKeychainData([NSData dataWithBytes:&realWalletCreationTime length:sizeof(realWalletCreationTime)], self.creationTimeUniqueID, NO); } else if (realWalletCreationTime == REFERENCE_DATE_2001) { realWalletCreationTime = 0; @@ -1334,7 +1329,6 @@ - (NSMutableDictionary *)blockchainIdentities { [context performBlockAndWait:^{ NSUInteger blockchainIdentityEntitiesCount = [DSBlockchainIdentityEntity countObjectsInContext:context matching:@"chain == %@ && isLocal == TRUE", [self.chain chainEntityInContext:context]]; if (blockchainIdentityEntitiesCount != keyChainDictionary.count) { - DSLog(@"[%@] Unmatching blockchain entities count", self.chain.name); } DSBlockchainIdentityEntity *blockchainIdentityEntity = [DSBlockchainIdentityEntity anyObjectInContext:context matching:@"uniqueID == %@", uniqueIdData]; DSBlockchainIdentity *blockchainIdentity = nil; @@ -1453,7 +1447,6 @@ - (NSMutableDictionary *)blockchainInvitations { [context performBlockAndWait:^{ NSUInteger blockchainInvitationEntitiesCount = [DSBlockchainInvitationEntity countObjectsInContext:context matching:@"chain == %@", [self.chain chainEntityInContext:context]]; if (blockchainInvitationEntitiesCount != keyChainDictionary.count) { - DSLog(@"[%@] Unmatching blockchain invitations count", self.chain.name); } DSBlockchainInvitationEntity *blockchainInvitationEntity = [DSBlockchainInvitationEntity anyObjectInContext:context matching:@"blockchainIdentity.uniqueID == %@", uint256_data([dsutxo_data(blockchainInvitationLockedOutpoint) SHA256_2])]; DSBlockchainInvitation *blockchainInvitation = nil; diff --git a/Example/CLAUDE.md b/Example/CLAUDE.md new file mode 100644 index 000000000..edb635d9d --- /dev/null +++ b/Example/CLAUDE.md @@ -0,0 +1,147 @@ +# DashSync Example App & Tests + +This directory contains the reference implementation and comprehensive test suite for DashSync. + +## Quick Start + +```bash +# Install dependencies +pod install + +# Open workspace +open DashSync.xcworkspace + +# Run tests from command line +xcodebuild test -workspace DashSync.xcworkspace \ + -scheme DashSync-Example \ + -destination 'platform=iOS Simulator,name=iPhone 15' +``` + +## Directory Structure + +``` +Example/ +├── DashSync/ # Example app source code +├── Tests/ # Unit and integration tests +├── NetworkInfo/ # Network configuration +├── DashSync.xcworkspace # Xcode workspace (use this!) +├── DashSync.xcodeproj/ # Xcode project +├── Podfile # CocoaPods configuration +└── Podfile.lock # Locked dependency versions +``` + +## Test Categories + +### Test Files + +| Test File | Coverage | +|-----------|----------| +| `DSChainTests.m` | Chain operations, sync, blocks | +| `DSTransactionTests.m` | Transaction types, serialization | +| `DSDeterministicMasternodeListTests.m` | Masternode lists, diffs | +| `DSWalletTests.m` | Wallet operations | +| `DSBIP32Tests.m` | BIP32 key derivation | +| `DSBIP39Tests.m` | BIP39 mnemonic handling | +| `DSHashTests.m` | Hash functions | +| `DSKeyTests.m` | Key operations | +| `DSBloomFilterTests.m` | Bloom filter logic | +| `DSGovernanceTests.m` | Governance objects | +| `DSProviderTransactionsTests.m` | Provider transactions | +| `DSSparseMerkleTreeTests.m` | Sparse merkle trees | +| `DSCoinJoinSessionTest.m` | CoinJoin mixing | +| `DSDIP14Tests.m` | DIP14 compliance | +| `DSAttackTests.m` | Chain attack scenarios | +| `DSMainnetSyncTests.m` | Mainnet sync | +| `DSTestnetSyncTests.m` | Testnet sync | +| `DSTestnetE2ETests.m` | End-to-end testnet | + +### Test Plans (`.xctestplan` files) + +| Plan | Purpose | +|------|---------| +| `FullUnitTestPlan` | All unit tests | +| `CryptoTests` | Cryptographic functions | +| `DerivationTests` | Key derivation | +| `MasternodeListTests` | Masternode operations | +| `TransactionTests` | Transaction handling | +| `WalletTests` | Wallet operations | +| `PaymentTests` | Payment protocol | +| `GovernanceTests` | Governance system | +| `LockTests` | Chain/instant locks | +| `CoinJoinTests` | Privacy mixing | +| `PlatformTransitionTests` | Platform transitions | +| `MainnetSyncTests` | Mainnet sync tests | +| `TestnetSyncTests` | Testnet sync tests | +| `TestnetE2ETests` | End-to-end tests | +| `Metrics` | Performance metrics | + +## Test Data Files + +The `Tests/` directory contains data files for deterministic testing: + +- `MasternodeList*.dat` - Masternode list snapshots +- `MNL_*.dat` - Masternode list diffs (from_to format) +- `DiffListTestnet*.dat` - Testnet diff data +- `BlocksForReorgTests/` - Block data for reorg tests + +## Running Specific Test Plans + +```bash +# Run crypto tests +xcodebuild test -workspace DashSync.xcworkspace \ + -scheme DashSync-Example \ + -testPlan CryptoTests \ + -destination 'platform=iOS Simulator,name=iPhone 15' + +# Run masternode tests +xcodebuild test -workspace DashSync.xcworkspace \ + -scheme DashSync-Example \ + -testPlan MasternodeListTests \ + -destination 'platform=iOS Simulator,name=iPhone 15' + +# Run network sync tests (requires network) +xcodebuild test -workspace DashSync.xcworkspace \ + -scheme DashSync-Example \ + -testPlan TestnetSyncTests \ + -destination 'platform=iOS Simulator,name=iPhone 15' +``` + +## Code Quality Tools + +### Linting +```bash +# Run OCLint +./run_oclint.sh + +# Check lint status +./check_lint.sh +``` + +### Configuration Files +- `.clang-format` - Clang formatting rules +- `.oclint` - OCLint rules +- `.bartycrouch.toml` - Localization tool config + +## Example App Features + +The example app in `DashSync/` demonstrates: +- Chain synchronization +- Wallet management +- Transaction creation +- Masternode operations +- Governance participation +- Identity management +- CoinJoin mixing + +## Dependencies + +See `Podfile` for current dependencies. Key pods: +- `DashSyncPod` (local development pod) +- Test dependencies as needed + +## CI/CD Integration + +Tests run automatically via GitHub Actions: +- Unit tests on every PR +- Sync tests on schedule +- Coverage reporting to Codecov