├── .gitignore ├── .gitmodules ├── .travis.yml ├── Breadcrumb Example ├── Breadcrumb Example.xcodeproj │ └── project.pbxproj ├── Breadcrumb Example │ ├── AppDelegate.h │ ├── AppDelegate.m │ ├── Base.lproj │ │ ├── LaunchScreen.xib │ │ └── Main.storyboard │ ├── Images.xcassets │ │ └── AppIcon.appiconset │ │ │ └── Contents.json │ ├── Info.plist │ ├── ViewController.h │ ├── ViewController.m │ └── main.m └── Breadcrumb ExampleTests │ ├── Breadcrumb_ExampleTests.m │ └── Info.plist ├── Breadcrumb.podspec ├── Breadcrumb ├── Breadcrumb.xcodeproj │ ├── project.pbxproj │ └── xcshareddata │ │ └── xcschemes │ │ ├── Breadcrumb-(Universial).xcscheme │ │ └── Breadcrumb.xcscheme ├── Breadcrumb │ ├── Abstracts │ │ ├── BCAProvider.h │ │ ├── BCAProvider.m │ │ ├── BCAddress.h │ │ └── BCAddress.m │ ├── Address Manager │ │ ├── BCAMMasterKey.h │ │ ├── BCAMMasterKey.m │ │ ├── BCAddressManager.h │ │ └── BCAddressManager.m │ ├── Amount │ │ ├── BCAmount.h │ │ └── BCAmount.m │ ├── BCScriptOpCodes.h │ ├── BIP39EnglishWords.plist │ ├── Breadcrumb-Prefix.pch │ ├── Breadcrumb.h │ ├── BreadcrumbCore.h │ ├── Categories │ │ ├── NSData+Encryption.h │ │ ├── NSData+Encryption.m │ │ ├── NSString+Base58.h │ │ └── NSString+Base58.m │ ├── Coins │ │ ├── BCCoin.h │ │ └── BCCoin.m │ ├── Crumbs │ │ ├── BRBIP32Sequence.h │ │ ├── BRBIP32Sequence.m │ │ ├── BRBIP39Mnemonic.h │ │ ├── BRBIP39Mnemonic.m │ │ ├── BRKey+BIP38.h │ │ ├── BRKey+BIP38.m │ │ ├── BRKey.h │ │ ├── BRKey.m │ │ ├── BRKeySequence.h │ │ ├── BRMnemonic.h │ │ ├── NSData+Bitcoin.h │ │ ├── NSData+Bitcoin.m │ │ ├── NSData+Hash.h │ │ ├── NSData+Hash.m │ │ ├── NSMutableData+Bitcoin.h │ │ ├── NSMutableData+Bitcoin.m │ │ ├── RIPEMD160.c │ │ ├── Reachability.h │ │ ├── Reachability.m │ │ └── ccMemory.h │ ├── FixedPeers.plist │ ├── Info.plist │ ├── Keys │ │ ├── BCKeyPair.h │ │ ├── BCKeyPair.m │ │ ├── BCKeySequence.h │ │ ├── BCKeySequence.m │ │ ├── BCPublicKey.h │ │ └── BCPublicKey.m │ ├── Mnemonic │ │ ├── BCMnemonic.h │ │ └── BCMnemonic.m │ ├── Providers │ │ ├── BCProviderChain.h │ │ └── BCProviderChain.m │ ├── Script │ │ ├── BCScript+DefaultScripts.h │ │ ├── BCScript+DefaultScripts.m │ │ ├── BCScript.h │ │ └── BCScript.m │ ├── Transaction │ │ ├── BCMutableTransaction.h │ │ ├── BCMutableTransaction.m │ │ ├── BCTransaction.h │ │ ├── BCTransaction.m │ │ ├── BCTransactionInput.h │ │ ├── BCTransactionInput.m │ │ ├── BCTransactionOutput.h │ │ └── BCTransactionOutput.m │ ├── Utilities │ │ ├── BCProtectedData.h │ │ └── BCProtectedData.m │ ├── Wallet │ │ ├── BCWallet+Restoration.h │ │ ├── BCWallet+Restoration.m │ │ ├── BCWallet+TransactionSigning.h │ │ ├── BCWallet+TransactionSigning.m │ │ ├── BCWallet+Transactions.h │ │ ├── BCWallet+Transactions.m │ │ ├── BCWallet.h │ │ └── BCWallet.m │ ├── _BCWallet.h │ └── secp256k1 │ │ ├── BCsecp256k1.h │ │ └── BCsecp256k1.m └── BreadcrumbTests │ ├── BCAddressTests.m │ ├── BCEncodingTests.m │ ├── BCHashTests.m │ ├── BCKeyPairTests.m │ ├── BCKeySequenceTests.m │ ├── BCMnemonicTests.m │ ├── BCScriptTests.m │ ├── BCWalletGenerationTests.m │ └── Info.plist ├── LICENSE ├── README.md ├── breadcrumb.xcworkspace └── contents.xcworkspacedata ├── libTomMath ├── libTomMath.xcodeproj │ ├── project.pbxproj │ └── xcshareddata │ │ └── xcschemes │ │ └── libTomMath.xcscheme ├── libTomMathTests │ └── Info.plist ├── tommath.h ├── tommath_class.h └── tommath_superclass.h ├── libs └── libsecp256k1 │ ├── include │ └── secp256k1.h │ └── libsecp256k1.a ├── makeLibs.sh ├── makeUniversalFramework.sh ├── makeiOS.sh └── test.sh /.gitignore: -------------------------------------------------------------------------------- 1 | # Xcode 2 | # 3 | build/ 4 | *.pbxuser 5 | !default.pbxuser 6 | *.mode1v3 7 | !default.mode1v3 8 | *.mode2v3 9 | !default.mode2v3 10 | *.perspectivev3 11 | !default.perspectivev3 12 | xcuserdata 13 | *.xccheckout 14 | *.moved-aside 15 | DerivedData 16 | *.hmap 17 | *.ipa 18 | *.xcuserstate 19 | 20 | ## DS_Store(s) 21 | .DS_Store 22 | **/.DS_Store 23 | 24 | # CocoaPods 25 | # 26 | # We recommend against adding the Pods directory to your .gitignore. However 27 | # you should judge for yourself, the pros and cons are mentioned at: 28 | # http://guides.cocoapods.org/using/using-cocoapods.html#should-i-ignore-the-pods-directory-in-source-control 29 | # 30 | # Pods/ 31 | -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "secp256k1"] 2 | path = secp256k1 3 | url = https://github.com/bitcoin/secp256k1.git 4 | [submodule "libTomMath/libtommath"] 5 | path = libTomMath/libtommath 6 | url = https://github.com/libtom/libtommath.git 7 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: objective-c 2 | before_install: 3 | - gem install xcpretty --no-rdoc --no-ri --no-document --quiet 4 | script: 5 | - set -o pipefail && xcodebuild -workspace Breadcrumb.xcworkspace -sdk iphonesimulator -scheme Breadcrumb -configuration Debug test | xcpretty -c 6 | 7 | -------------------------------------------------------------------------------- /Breadcrumb Example/Breadcrumb Example/AppDelegate.h: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.h 3 | // Breadcrumb Example 4 | // 5 | // Created by Andrew Hurst on 2/5/15. 6 | // Copyright (c) 2015 Breadcrumb. 7 | // 8 | // Distributed under the MIT software license, see the accompanying 9 | // file LICENSE or http://www.opensource.org/licenses/mit-license.php. 10 | // 11 | // 12 | 13 | #import 14 | 15 | @interface AppDelegate : UIResponder 16 | 17 | @property (strong, nonatomic) UIWindow *window; 18 | 19 | 20 | @end 21 | 22 | -------------------------------------------------------------------------------- /Breadcrumb Example/Breadcrumb Example/Base.lproj/LaunchScreen.xib: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 20 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | -------------------------------------------------------------------------------- /Breadcrumb Example/Breadcrumb Example/Base.lproj/Main.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | -------------------------------------------------------------------------------- /Breadcrumb Example/Breadcrumb Example/Images.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "iphone", 5 | "size" : "29x29", 6 | "scale" : "2x" 7 | }, 8 | { 9 | "idiom" : "iphone", 10 | "size" : "29x29", 11 | "scale" : "3x" 12 | }, 13 | { 14 | "idiom" : "iphone", 15 | "size" : "40x40", 16 | "scale" : "2x" 17 | }, 18 | { 19 | "idiom" : "iphone", 20 | "size" : "40x40", 21 | "scale" : "3x" 22 | }, 23 | { 24 | "idiom" : "iphone", 25 | "size" : "60x60", 26 | "scale" : "2x" 27 | }, 28 | { 29 | "idiom" : "iphone", 30 | "size" : "60x60", 31 | "scale" : "3x" 32 | }, 33 | { 34 | "idiom" : "ipad", 35 | "size" : "29x29", 36 | "scale" : "1x" 37 | }, 38 | { 39 | "idiom" : "ipad", 40 | "size" : "29x29", 41 | "scale" : "2x" 42 | }, 43 | { 44 | "idiom" : "ipad", 45 | "size" : "40x40", 46 | "scale" : "1x" 47 | }, 48 | { 49 | "idiom" : "ipad", 50 | "size" : "40x40", 51 | "scale" : "2x" 52 | }, 53 | { 54 | "idiom" : "ipad", 55 | "size" : "76x76", 56 | "scale" : "1x" 57 | }, 58 | { 59 | "idiom" : "ipad", 60 | "size" : "76x76", 61 | "scale" : "2x" 62 | } 63 | ], 64 | "info" : { 65 | "version" : 1, 66 | "author" : "xcode" 67 | } 68 | } -------------------------------------------------------------------------------- /Breadcrumb Example/Breadcrumb Example/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | BC.$(PRODUCT_NAME:rfc1034identifier) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | APPL 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | 1 23 | LSRequiresIPhoneOS 24 | 25 | UILaunchStoryboardName 26 | LaunchScreen 27 | UIMainStoryboardFile 28 | Main 29 | UIRequiredDeviceCapabilities 30 | 31 | armv7 32 | 33 | UISupportedInterfaceOrientations 34 | 35 | UIInterfaceOrientationPortrait 36 | UIInterfaceOrientationLandscapeLeft 37 | UIInterfaceOrientationLandscapeRight 38 | 39 | UISupportedInterfaceOrientations~ipad 40 | 41 | UIInterfaceOrientationPortrait 42 | UIInterfaceOrientationPortraitUpsideDown 43 | UIInterfaceOrientationLandscapeLeft 44 | UIInterfaceOrientationLandscapeRight 45 | 46 | 47 | 48 | -------------------------------------------------------------------------------- /Breadcrumb Example/Breadcrumb Example/ViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // ViewController.h 3 | // Breadcrumb Example 4 | // 5 | // Created by Andrew Hurst on 2/5/15. 6 | // Copyright (c) 2015 Breadcrumb. 7 | // 8 | // Distributed under the MIT software license, see the accompanying 9 | // file LICENSE or http://www.opensource.org/licenses/mit-license.php. 10 | // 11 | 12 | #import 13 | 14 | @interface ViewController : UIViewController 15 | 16 | 17 | @end 18 | 19 | -------------------------------------------------------------------------------- /Breadcrumb Example/Breadcrumb Example/ViewController.m: -------------------------------------------------------------------------------- 1 | // 2 | // ViewController.m 3 | // Breadcrumb Example 4 | // 5 | // Created by Andrew Hurst on 2/5/15. 6 | // Copyright (c) 2015 Breadcrumb. 7 | // 8 | // Distributed under the MIT software license, see the accompanying 9 | // file LICENSE or http://www.opensource.org/licenses/mit-license.php. 10 | // 11 | 12 | #import "ViewController.h" 13 | 14 | @interface ViewController () 15 | 16 | @end 17 | 18 | @implementation ViewController 19 | 20 | - (void)viewDidLoad { 21 | [super viewDidLoad]; 22 | // Do any additional setup after loading the view, typically from a nib. 23 | } 24 | 25 | - (void)didReceiveMemoryWarning { 26 | [super didReceiveMemoryWarning]; 27 | // Dispose of any resources that can be recreated. 28 | } 29 | 30 | @end 31 | -------------------------------------------------------------------------------- /Breadcrumb Example/Breadcrumb Example/main.m: -------------------------------------------------------------------------------- 1 | // 2 | // main.m 3 | // Breadcrumb Example 4 | // 5 | // Created by Andrew Hurst on 2/5/15. 6 | // Copyright (c) 2015 Breadcrumb. 7 | // 8 | // Distributed under the MIT software license, see the accompanying 9 | // file LICENSE or http://www.opensource.org/licenses/mit-license.php. 10 | 11 | 12 | #import 13 | #import "AppDelegate.h" 14 | 15 | int main(int argc, char * argv[]) { 16 | @autoreleasepool { 17 | return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class])); 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /Breadcrumb Example/Breadcrumb ExampleTests/Breadcrumb_ExampleTests.m: -------------------------------------------------------------------------------- 1 | // 2 | // Breadcrumb_ExampleTests.m 3 | // Breadcrumb ExampleTests 4 | // 5 | // Created by Andrew Hurst on 2/5/15. 6 | // Copyright (c) 2015 Breadcrumb. 7 | // 8 | // Distributed under the MIT software license, see the accompanying 9 | // file LICENSE or http://www.opensource.org/licenses/mit-license.php. 10 | // 11 | // 12 | 13 | #import 14 | #import 15 | 16 | @interface Breadcrumb_ExampleTests : XCTestCase 17 | 18 | @end 19 | 20 | @implementation Breadcrumb_ExampleTests 21 | 22 | - (void)setUp { 23 | [super setUp]; 24 | // Put setup code here. This method is called before the invocation of each test method in the class. 25 | } 26 | 27 | - (void)tearDown { 28 | // Put teardown code here. This method is called after the invocation of each test method in the class. 29 | [super tearDown]; 30 | } 31 | 32 | - (void)testExample { 33 | // This is an example of a functional test case. 34 | XCTAssert(YES, @"Pass"); 35 | } 36 | 37 | - (void)testPerformanceExample { 38 | // This is an example of a performance test case. 39 | [self measureBlock:^{ 40 | // Put the code you want to measure the time of here. 41 | }]; 42 | } 43 | 44 | @end 45 | -------------------------------------------------------------------------------- /Breadcrumb Example/Breadcrumb ExampleTests/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | BC.$(PRODUCT_NAME:rfc1034identifier) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | BNDL 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | 1 23 | 24 | 25 | -------------------------------------------------------------------------------- /Breadcrumb.podspec: -------------------------------------------------------------------------------- 1 | # 2 | # Be sure to run `pod spec lint Breadcrumb.podspec' to ensure this is a 3 | # valid spec and to remove all comments including this before submitting the spec. 4 | # 5 | # To learn more about Podspec attributes see http://docs.cocoapods.org/specification.html 6 | # To see working Podspecs in the CocoaPods repo see https://github.com/CocoaPods/Specs/ 7 | # 8 | 9 | Pod::Spec.new do |s| 10 | 11 | # ――― Spec Metadata ―――――――――――――――――――――――――――――――――――――――――――――――――――――――――― # 12 | # 13 | # These will help people to find your library, and whilst it 14 | # can feel like a chore to fill in it's definitely to your advantage. The 15 | # summary should be tweet-length, and the description more in depth. 16 | # 17 | 18 | s.name = "Breadcrumb" 19 | s.version = "0.0.1" 20 | s.summary = "A minimalistic bitcoin library." 21 | 22 | s.description = <<-DESC 23 | A longer description of Breadcrumb in Markdown format. 24 | 25 | * Think: Why did you write this? What is the focus? What does it do? 26 | * CocoaPods will be using this to generate tags, and improve search results. 27 | * Try to keep it short, snappy and to the point. 28 | * Finally, don't worry about the indent, CocoaPods strips it! 29 | DESC 30 | 31 | # s.homepage = "http://EXAMPLE/Breadcrumb" 32 | # s.screenshots = "www.example.com/screenshots_1.gif", "www.example.com/screenshots_2.gif" 33 | 34 | 35 | # ――― Spec License ――――――――――――――――――――――――――――――――――――――――――――――――――――――――――― # 36 | # 37 | # Licensing your code is important. See http://choosealicense.com for more info. 38 | # CocoaPods will detect a license file if there is a named LICENSE* 39 | # Popular ones are 'MIT', 'BSD' and 'Apache License, Version 2.0'. 40 | # 41 | 42 | # s.license = "MIT (example)" 43 | s.license = { :type => "MIT", :file => "LICENSE" } 44 | 45 | 46 | # ――― Author Metadata ――――――――――――――――――――――――――――――――――――――――――――――――――――――――― # 47 | # 48 | # Specify the authors of the library, with email addresses. Email addresses 49 | # of the authors are extracted from the SCM log. E.g. $ git log. CocoaPods also 50 | # accepts just a name if you'd rather not provide an email address. 51 | # 52 | # Specify a social_media_url where others can refer to, for example a twitter 53 | # profile URL. 54 | # 55 | 56 | s.author = { "Andr3wHur5t" => "Andr3wHur5t@live.com" } 57 | # Or just: s.author = "Andr3wHur5t" 58 | # s.authors = { "Andr3wHur5t" => "Andr3wHur5t@live.com" } 59 | # s.social_media_url = "http://twitter.com/Andr3wHur5t" 60 | 61 | # ――― Platform Specifics ――――――――――――――――――――――――――――――――――――――――――――――――――――――― # 62 | # 63 | # If this Pod runs only on iOS or OS X, then specify the platform and 64 | # the deployment target. You can optionally include the target after the platform. 65 | # 66 | 67 | s.platform = :ios 68 | s.platform = :ios, "8.0" 69 | 70 | # When using multiple platforms 71 | # s.ios.deployment_target = "5.0" 72 | # s.osx.deployment_target = "10.7" 73 | 74 | 75 | # ――― Source Location ―――――――――――――――――――――――――――――――――――――――――――――――――――――――――― # 76 | # 77 | # Specify the location from where the source should be retrieved. 78 | # Supports git, hg, bzr, svn and HTTP. 79 | # 80 | 81 | s.source = { :git => "http://github.com/Andr3wHur5t/Breadcrumb.git", :tag => "0.0.1" } 82 | 83 | 84 | # ――― Source Code ―――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――― # 85 | # 86 | # CocoaPods is smart about how it includes source code. For source files 87 | # giving a folder will include any h, m, mm, c & cpp files. For header 88 | # files it will include any header in the folder. 89 | # Not including the public_header_files will make all headers public. 90 | # 91 | 92 | s.source_files = "Breadcrumb/**/*.{h,m}","libs/libsecp256k1/**/*.h" 93 | s.exclude_files = "Breadcrumb Example/**/*" 94 | 95 | # s.public_header_files = "Classes/**/*.h" 96 | 97 | 98 | # ――― Resources ―――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――― # 99 | # 100 | # A list of resources included with the Pod. These are copied into the 101 | # target bundle with a build phase script. Anything else will be cleaned. 102 | # You can preserve files from being cleaned, please don't preserve 103 | # non-essential files like tests, examples and documentation. 104 | # 105 | 106 | # s.resource = "icon.png" 107 | # s.resources = "Resources/*.png" 108 | 109 | # s.preserve_paths = "FilesToSave", "MoreFilesToSave" 110 | 111 | 112 | # ――― Project Linking ―――――――――――――――――――――――――――――――――――――――――――――――――――――――――― # 113 | # 114 | # Link your library with frameworks, or libraries. Libraries do not include 115 | # the lib prefix of their name. 116 | # 117 | 118 | # s.framework = "SomeFramework" 119 | # s.frameworks = "SomeFramework", "AnotherFramework" 120 | 121 | # s.library = "iconv" 122 | # s.libraries = "iconv", "xml2" 123 | 124 | 125 | # ――― Project Settings ――――――――――――――――――――――――――――――――――――――――――――――――――――――――― # 126 | # 127 | # If your library depends on compiler flags you can set them in the xcconfig hash 128 | # where they will only apply to your library. If you depend on other Podspecs 129 | # you can include multiple dependencies to ensure it works. 130 | 131 | # s.requires_arc = true 132 | 133 | # s.xcconfig = { "HEADER_SEARCH_PATHS" => "$(SDKROOT)/usr/include/libxml2" } 134 | # s.dependency "JSONKit", "~> 1.4" 135 | 136 | end 137 | -------------------------------------------------------------------------------- /Breadcrumb/Breadcrumb.xcodeproj/xcshareddata/xcschemes/Breadcrumb-(Universial).xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 30 | 31 | 32 | 33 | 42 | 43 | 49 | 50 | 51 | 52 | 53 | 54 | 60 | 61 | 67 | 68 | 69 | 70 | 72 | 73 | 76 | 77 | 78 | -------------------------------------------------------------------------------- /Breadcrumb/Breadcrumb.xcodeproj/xcshareddata/xcschemes/Breadcrumb.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 29 | 35 | 36 | 37 | 43 | 49 | 50 | 51 | 52 | 53 | 58 | 59 | 61 | 67 | 68 | 69 | 71 | 72 | 74 | 75 | 76 | 77 | 78 | 79 | 85 | 86 | 87 | 88 | 97 | 98 | 104 | 105 | 106 | 107 | 108 | 109 | 115 | 116 | 122 | 123 | 124 | 125 | 127 | 128 | 131 | 132 | 133 | -------------------------------------------------------------------------------- /Breadcrumb/Breadcrumb/Abstracts/BCAProvider.h: -------------------------------------------------------------------------------- 1 | // 2 | // BCAProvider.h 3 | // Breadcrumb 4 | // 5 | // Created by Andrew Hurst on 2/6/15. 6 | // Copyright (c) 2015 Breadcrumb. 7 | // 8 | // Distributed under the MIT software license, see the accompanying 9 | // file LICENSE or http://www.opensource.org/licenses/mit-license.php. 10 | // 11 | 12 | #import 13 | #import "BCMutableTransaction.h" 14 | #import "BCTransaction.h" 15 | #import "BCAddressManager.h" 16 | #import "BCAmount.h" 17 | 18 | @interface BCAProvider : NSObject 19 | 20 | /*! 21 | @brief Gets the optimized UTXOs for the given addresses optimized for the given 22 | amount. 23 | 24 | @discussion This method is used to get inputs for transactions. 25 | 26 | @param amount The amount the UTXOs should be optimized for. 27 | @param addresses The addresses to get the UTXOs for. 28 | @param callback The callback to call once the operation completes 29 | */ 30 | - (void)UTXOforAmount:(uint64_t)amount 31 | andAddresses:(BCAddressManager *)addresses 32 | withCallback:(void (^)(NSArray *, NSError *))callback; 33 | 34 | /*! 35 | @brief Publishes the transaction through the providers network. 36 | 37 | @discussion This allows a provider to route the transaction through their 38 | service if desired. This is useful if you are issuing requests to multiple 39 | clients, and wish to reduplicate transactions on the server. Also if the 40 | transaction is not built, and signed on the client. 41 | 42 | @param transaction The transaction to publish. 43 | @param completion The completion to call once the transaction has been 44 | published, or the operation failed. 45 | */ 46 | - (void)publishTransaction:(BCMutableTransaction *)transaction 47 | forCoin:(BCCoin *)coin 48 | withCompletion:(void (^)(NSData *, NSError *))completion; 49 | 50 | - (void)syncAddressManager:(BCAddressManager *)addressManager 51 | withCallback:(void (^)(NSError *))callback; 52 | 53 | - (void)getBalanceForAddressManager:(BCAddressManager *)addressManager 54 | withCallback:(void (^)(uint64_t, NSError *))callback; 55 | 56 | @end 57 | -------------------------------------------------------------------------------- /Breadcrumb/Breadcrumb/Abstracts/BCAProvider.m: -------------------------------------------------------------------------------- 1 | // 2 | // BCAProvider.m 3 | // Breadcrumb 4 | // 5 | // Created by Andrew Hurst on 2/6/15. 6 | // Copyright (c) 2015 Breadcrumb. 7 | // 8 | // Distributed under the MIT software license, see the accompanying 9 | // file LICENSE or http://www.opensource.org/licenses/mit-license.php. 10 | // 11 | 12 | #import "BCAProvider.h" 13 | 14 | @implementation BCAProvider 15 | 16 | - (void)UTXOforAmount:(uint64_t)amount 17 | andAddresses:(BCAddressManager *)addresses 18 | withCallback:(void (^)(NSArray *, NSError *))callback { 19 | NSAssert(FALSE, @"Called method on abstract class."); 20 | } 21 | 22 | - (void)publishTransaction:(BCMutableTransaction *)transaction 23 | forCoin:(BCCoin *)coin 24 | withCompletion:(void (^)(NSData *,NSError *))completion { 25 | NSAssert(FALSE, @"Called method on abstract class."); 26 | } 27 | 28 | - (void)syncAddressManager:(BCAddressManager *)addressManager withCallback:(void(^)(NSError *))callback { 29 | NSAssert(FALSE, @"Called method on abstract class."); 30 | } 31 | 32 | - (void)getBalanceForAddressManager:(BCAddressManager *)addressManager 33 | withCallback:(void (^)(uint64_t, NSError *))callback { 34 | NSAssert(FALSE, @"Called method on abstract class."); 35 | } 36 | 37 | @end 38 | -------------------------------------------------------------------------------- /Breadcrumb/Breadcrumb/Abstracts/BCAddress.h: -------------------------------------------------------------------------------- 1 | // 2 | // BCAddress.h 3 | // Breadcrumb 4 | // 5 | // Created by Andrew Hurst on 2/5/15. 6 | // Copyright (c) 2015 Breadcrumb. 7 | // 8 | // Distributed under the MIT software license, see the accompanying 9 | // file LICENSE or http://www.opensource.org/licenses/mit-license.php. 10 | // 11 | 12 | #import 13 | 14 | @class BCCoin; 15 | @class BCScript; 16 | 17 | @interface BCAddress : NSObject 18 | 19 | #pragma mark Construction 20 | /*! 21 | @brief Constructs a address object with the bitcoin address string. 22 | 23 | @param addressString The address string to construct the object with. 24 | */ 25 | - (instancetype)initWithAddressString:(NSString *)addressString; 26 | 27 | /*! 28 | @brief Constructs a address object with the bitcoin address string. 29 | 30 | @param addressString The address string to construct the object with. 31 | */ 32 | + (instancetype)addressWithString:(NSString *)address; 33 | 34 | #pragma mark Info 35 | /*! 36 | @brief Converts the address to a string. 37 | */ 38 | - (NSString *)toString; 39 | 40 | /*! 41 | @brief Converts the address to data. 42 | */ 43 | - (NSData *)toData; 44 | 45 | /*! 46 | @brief Converts the address to data excluding its type byte. 47 | */ 48 | - (NSData *)toDataWithoutType; 49 | 50 | /*! 51 | @brief The code representing the type. 52 | */ 53 | @property(assign, nonatomic, readonly) uint8_t typeCode; 54 | 55 | #pragma mark Conversion 56 | /*! 57 | @brief Converts a public key into a base 58checked address using the old 58 | version byte. 59 | 60 | @discussion Converts a public key into an address by getting the has of the 61 | address (SHA256 + RIPMD160) then base 58 check encoding it. 62 | 63 | @param publicKey The public key to convert into a address. 64 | */ 65 | + (BCAddress *)addressFromPublicKey:(NSData *)publicKey 66 | usingCoin:(BCCoin *)coin; 67 | 68 | + (BCAddress *)addressFromScript:(BCScript *)script usingCoin:(BCCoin *)coin; 69 | 70 | #pragma mark Checks 71 | /*! 72 | @brief Checks if addresses are equivalent besides for their type. 73 | 74 | @param address The address to compare. 75 | 76 | @return True if addresses data excluding the version byte is the same, 77 | otherwise false. 78 | */ 79 | - (BOOL)isEqualExcludingVersion:(BCAddress *)address; 80 | 81 | @end 82 | 83 | @interface NSString (BCAddress) 84 | /*! 85 | @brief Attempts to convert a base58 encoded address into a native form. 86 | */ 87 | - (BCAddress *)toBitcoinAddress; 88 | 89 | @end 90 | -------------------------------------------------------------------------------- /Breadcrumb/Breadcrumb/Abstracts/BCAddress.m: -------------------------------------------------------------------------------- 1 | // 2 | // BCAddress.m 3 | // Breadcrumb 4 | // 5 | // Created by Andrew Hurst on 2/5/15. 6 | // Copyright (c) 2015 Breadcrumb. 7 | // 8 | // Distributed under the MIT software license, see the accompanying 9 | // file LICENSE or http://www.opensource.org/licenses/mit-license.php. 10 | // 11 | 12 | #import "BCAddress.h" 13 | #import "BCCoin.h" 14 | #import "BreadcrumbCore.h" 15 | #import "BCScript.h" 16 | 17 | @interface BCAddress () { 18 | NSString *_stringRepresentation; 19 | NSData *_dataRepresentation; 20 | } 21 | 22 | @end 23 | 24 | @implementation BCAddress 25 | 26 | @synthesize typeCode = _typeCode; 27 | 28 | #pragma mark Construction 29 | 30 | - (instancetype)initWithAddressString:(NSString *)addressString { 31 | if (addressString.length > 35 || addressString.length < 26) 32 | return NULL; // These are size constraints provided by here: 33 | // https://en.bitcoin.it/wiki/Address 34 | self = [super init]; 35 | if (self) { 36 | // The address should by base58check encoded 37 | _dataRepresentation = addressString.base58checkToData; 38 | 39 | // If the data representation is null we should assume that the checksum 40 | // validation failed, and the address is invalid. 41 | if (![_dataRepresentation isKindOfClass:[NSData class]]) return NULL; 42 | 43 | // Get the version byte from the data 44 | _typeCode = [_dataRepresentation UInt8AtOffset:0]; 45 | 46 | _stringRepresentation = addressString; 47 | } 48 | return self; 49 | } 50 | 51 | - (instancetype)initWithScript:(BCScript *)script usingCoin:(BCCoin *)coin { 52 | NSMutableData *buffer; 53 | NSParameterAssert([script isKindOfClass:[BCScript class]]); 54 | if (![script isKindOfClass:[BCScript class]]) return NULL; 55 | 56 | self = [super init]; 57 | if (!self) return NULL; 58 | 59 | // P2SH Type code 60 | _typeCode = coin.P2SHCode; 61 | buffer = [[NSMutableData alloc] init]; 62 | if (![buffer isKindOfClass:[NSMutableData class]]) return NULL; 63 | 64 | [buffer appendUInt8:_typeCode]; 65 | 66 | // Hash160 67 | [buffer appendData:[[[script toData] SHA256] RMD160]]; 68 | 69 | _dataRepresentation = [NSData dataWithData:buffer]; 70 | _stringRepresentation = [_dataRepresentation base58CheckEncoding]; 71 | 72 | return self; 73 | } 74 | 75 | + (instancetype)addressWithString:(NSString *)address { 76 | return [[[self class] alloc] initWithAddressString:address]; 77 | } 78 | 79 | #pragma mark Info 80 | 81 | - (NSString *)toString { 82 | return _stringRepresentation; 83 | } 84 | 85 | - (NSData *)toData { 86 | return _dataRepresentation; 87 | } 88 | 89 | - (NSData *)toDataWithoutType { 90 | return [_dataRepresentation 91 | subdataWithRange:NSMakeRange(1, _dataRepresentation.length - 1)]; 92 | } 93 | 94 | #pragma mark Debugging 95 | 96 | - (NSString *)debugDescription { 97 | return [self description]; 98 | } 99 | 100 | - (NSString *)description { 101 | return [self toString]; 102 | } 103 | 104 | #pragma mark Comparison 105 | 106 | - (BOOL)isEqual:(id)object { 107 | if (![object isKindOfClass:[self class]]) return FALSE; 108 | return [[self toString] isEqualToString:[((BCAddress *)object)toString]]; 109 | } 110 | 111 | - (BOOL)isEqualExcludingVersion:(BCAddress *)address { 112 | NSData *addr1, *addr2; 113 | addr1 = [self toData]; 114 | addr1 = [addr1 subdataWithRange:NSMakeRange(1, addr1.length - 1)]; 115 | 116 | addr2 = [address toData]; 117 | addr2 = [addr2 subdataWithRange:NSMakeRange(1, addr2.length - 1)]; 118 | 119 | return [addr1 isEqualToData:addr2]; 120 | } 121 | 122 | #pragma mark Conversion 123 | 124 | + (BCAddress *)addressFromPublicKey:(NSData *)publicKey 125 | usingCoin:(BCCoin *)coin { 126 | NSData *hash; 127 | NSMutableData *mHash; 128 | NSString *addressString; 129 | NSParameterAssert([publicKey isKindOfClass:[NSData class]]); 130 | if (![publicKey isKindOfClass:[NSData class]]) return NULL; 131 | 132 | // HASH160 133 | hash = [[publicKey SHA256] RMD160]; 134 | if (![hash isKindOfClass:[NSData class]]) return NULL; 135 | 136 | mHash = [[NSMutableData alloc] init]; 137 | 138 | // Because we don't currently support multi-sig use the old version byte 139 | [mHash appendUInt8:[coin addressTypeForFlags:0]]; 140 | [mHash appendData:hash]; 141 | 142 | addressString = [mHash base58CheckEncoding]; 143 | if (![addressString isKindOfClass:[NSString class]]) return NULL; 144 | 145 | return [addressString toBitcoinAddress]; 146 | } 147 | 148 | + (BCAddress *)addressFromScript:(BCScript *)script usingCoin:(BCCoin *)coin { 149 | return [[[self class] alloc] initWithScript:script usingCoin:(BCCoin *)coin]; 150 | } 151 | 152 | @end 153 | 154 | @implementation NSString (BCAddress) 155 | 156 | - (BCAddress *)toBitcoinAddress { 157 | return [[BCAddress alloc] initWithAddressString:self]; 158 | } 159 | 160 | @end 161 | -------------------------------------------------------------------------------- /Breadcrumb/Breadcrumb/Address Manager/BCAMMasterKey.h: -------------------------------------------------------------------------------- 1 | // 2 | // BCAMMasterKey.h 3 | // Breadcrumb 4 | // 5 | // Created by Andrew Hurst on 2/22/15. 6 | // Copyright (c) 2015 Breadcrumb. 7 | // 8 | // Distributed under the MIT software license, see the accompanying 9 | // file LICENSE or http://www.opensource.org/licenses/mit-license.php. 10 | // 11 | 12 | #import 13 | #import "BCKeyPair.h" 14 | 15 | @interface BCAMMasterKey : NSObject 16 | #pragma mark Construction 17 | /*! 18 | @brief Constructs the master key from the provided key. 19 | 20 | @param key The key to construct with. 21 | */ 22 | - (instancetype)initWithKeyPair:(BCKeyPair *)key andCoin:(BCCoin *)coin; 23 | 24 | #pragma mark Metadata 25 | /*! 26 | @brief This is the key representing the master key. 27 | */ 28 | @property(strong, nonatomic, readonly) BCKeyPair *key; 29 | 30 | /*! 31 | @brief The coin to use in generation 32 | */ 33 | @property(strong, nonatomic, readonly) BCCoin *coin; 34 | 35 | /*! 36 | @brief This stats the index which was last used, setting this value causes 37 | addresses to be generated. 38 | */ 39 | @property(assign, nonatomic, readwrite) uint16_t lastUsedIndex; 40 | 41 | /*! 42 | @brief These are the addresses related to the key. 43 | */ 44 | @property(strong, nonatomic, readonly) NSMutableArray *addresses; 45 | 46 | /*! 47 | @brief The first unused address. 48 | */ 49 | @property(weak, nonatomic, readonly) BCAddress *firstUnusedAddress; 50 | 51 | #pragma mark Retrieval 52 | /*! 53 | @brief Retrieves the key pair with the associated address if any. 54 | 55 | @param address The address to get the key for. 56 | @param memoryKey The memory key to use in protecting the key. 57 | */ 58 | - (BCKeyPair *)keyPairForAddress:(BCAddress *)address 59 | withMemoryKey:(NSData *)memoryKey; 60 | 61 | - (BCAddress *)addressAtIndex:(uint16_t)index; 62 | - (void)expandAddressToIndex:(uint16_t)index; 63 | 64 | /*! 65 | @brief Checks if the inputted address is in the cache. 66 | 67 | @param address The address to check for. 68 | */ 69 | - (BOOL)hasAddressInCache:(BCAddress *)address; 70 | 71 | @end 72 | -------------------------------------------------------------------------------- /Breadcrumb/Breadcrumb/Address Manager/BCAMMasterKey.m: -------------------------------------------------------------------------------- 1 | // 2 | // BCAMMasterKey.m 3 | // Breadcrumb 4 | // 5 | // Created by Andrew Hurst on 2/22/15. 6 | // Copyright (c) 2015 Breadcrumb. 7 | // 8 | // Distributed under the MIT software license, see the accompanying 9 | // file LICENSE or http://www.opensource.org/licenses/mit-license.php. 10 | // 11 | #import "BCAMMasterKey.h" 12 | #import "BCProtectedData.h" 13 | #import "BCsecp256k1.h" 14 | 15 | // Set this to change our edge address search distance 16 | #define GAP_DISTANCE 20 17 | 18 | @implementation BCAMMasterKey 19 | 20 | @synthesize key = _key; 21 | @synthesize coin = _coin; 22 | @synthesize addresses = _addresses; 23 | @synthesize lastUsedIndex = _lastUsedIndex; 24 | 25 | #pragma mark Construction 26 | 27 | - (instancetype)initWithKeyPair:(BCKeyPair *)key andCoin:(BCCoin *)coin { 28 | @autoreleasepool { 29 | NSParameterAssert([key isKindOfClass:[BCKeyPair class]]); 30 | if (![key isKindOfClass:[BCKeyPair class]]) return NULL; 31 | self = [super init]; 32 | if (!self) return NULL; 33 | 34 | _key = key; 35 | _coin = coin; 36 | 37 | return self; 38 | } 39 | } 40 | 41 | #pragma mark Index Management 42 | 43 | - (void)setLastUsedIndex:(uint16_t)lastUsedIndex { 44 | [self expandAddressToIndex:lastUsedIndex + GAP_DISTANCE]; 45 | _lastUsedIndex = lastUsedIndex; 46 | } 47 | 48 | - (void)expandAddressToIndex:(uint16_t)index { 49 | uint16_t count, initial; 50 | if (self.addresses.count > index) return; 51 | 52 | initial = (uint16_t)self.addresses.count; 53 | count = index - initial; 54 | for (uint16_t i = 0; i < count; ++i) [self addressAtIndex:initial + i]; 55 | } 56 | 57 | #pragma mark Address Management 58 | 59 | - (NSMutableArray *)addresses { 60 | if (!_addresses) _addresses = [[NSMutableArray alloc] init]; 61 | return _addresses; 62 | } 63 | 64 | - (void)cacheAddress:(BCAddress *)address atIndex:(uint16_t)index { 65 | if (![address isKindOfClass:[BCAddress class]]) return; 66 | 67 | // Fill Empty spaces with NULL. Will be caught by address at index. 68 | for (uint16_t i = (uint16_t)self.addresses.count; i < index; ++i) 69 | [self.addresses setObject:[NSNull null] atIndexedSubscript:i]; 70 | [self.addresses setObject:address atIndexedSubscript:index]; 71 | } 72 | 73 | - (BCAddress *)firstUnusedAddress { 74 | return [self addressAtIndex:self.lastUsedIndex + 1]; 75 | } 76 | 77 | - (BCAddress *)addressAtIndex:(uint16_t)index { 78 | BCPublicKey *child; 79 | BCAddress *address; 80 | // Check Cache 81 | if (self.addresses.count > index) { 82 | address = [self.addresses objectAtIndex:index]; 83 | 84 | // if we found return, else generate address. 85 | if ([address isKindOfClass:[BCAddress class]]) return address; 86 | } 87 | 88 | // Check if we can derive the child from pub key. 89 | if (![self.key.publicKey isKindOfClass:[BCDerivablePublicKey class]]) 90 | return NULL; 91 | 92 | // Get the child public key at the correct index. 93 | child = [(BCDerivablePublicKey *)self.key.publicKey childKeyAtIndex:index]; 94 | if (![child isKindOfClass:[BCPublicKey class]]) return NULL; 95 | 96 | // Get its address 97 | address = [child addressForCoin:_coin]; 98 | [self cacheAddress:address atIndex:index]; 99 | return [address isKindOfClass:[BCAddress class]] ? address : NULL; 100 | } 101 | 102 | - (uint16_t)indexOfAddress:(BCAddress *)address { 103 | NSParameterAssert([address isKindOfClass:[BCAddress class]]); 104 | if (![address isKindOfClass:[BCAddress class]]) return UINT16_MAX; 105 | 106 | // Note: Last used index is disconected from the count of cached addresses 107 | // Note: This searches known addresses in self.lastUsedIndex and will try some 108 | // edge addresses as well. 109 | for (uint16_t i = 0; i < self.lastUsedIndex + GAP_DISTANCE; ++i) 110 | if ([address isEqualExcludingVersion:[self addressAtIndex:i]]) return i; 111 | 112 | // We failed 113 | return UINT16_MAX; 114 | } 115 | 116 | - (BCKeyPair *)keyPairForAddress:(BCAddress *)address 117 | withMemoryKey:(NSData *)memoryKey { 118 | @autoreleasepool { 119 | uint16_t index; 120 | BCKeyPair *child; 121 | NSParameterAssert([address isKindOfClass:[BCAddress class]]); 122 | NSParameterAssert([memoryKey isKindOfClass:[NSData class]]); 123 | 124 | index = [self indexOfAddress:address]; 125 | if (index == UINT16_MAX) return NULL; // We Failed :( 126 | 127 | child = [self.key childKeyPairAt:index withMemoryKey:memoryKey]; 128 | 129 | return [child isKindOfClass:[BCKeyPair class]] ? child : NULL; 130 | } 131 | } 132 | 133 | #pragma mark Checks 134 | 135 | - (BOOL)hasAddressInCache:(BCAddress *)address { 136 | for (BCAddress *addr in self.addresses) { 137 | if (![addr isKindOfClass:[BCAddress class]]) continue; 138 | if ([addr isEqual:address]) return TRUE; 139 | } 140 | 141 | return FALSE; 142 | } 143 | 144 | @end 145 | -------------------------------------------------------------------------------- /Breadcrumb/Breadcrumb/Address Manager/BCAddressManager.h: -------------------------------------------------------------------------------- 1 | // 2 | // BCAddressManager.h 3 | // Breadcrumb 4 | // 5 | // Created by Andrew Hurst on 2/19/15. 6 | // Copyright (c) 2015 Breadcrumb. 7 | // 8 | // Distributed under the MIT software license, see the accompanying 9 | // file LICENSE or http://www.opensource.org/licenses/mit-license.php. 10 | // 11 | 12 | #import 13 | #import "BCKeySequence.h" 14 | #import "BCAMMasterKey.h" 15 | #import "BCCoin.h" 16 | 17 | /*! 18 | @brief This manages a wallets addresses. 19 | 20 | @discussion This Oversees what addresses should be used, and thus what keys in 21 | the key sequence should be used for signing transactions. 22 | 23 | According to the current configuration of the manager. 24 | */ 25 | @interface BCAddressManager : NSObject 26 | #pragma mark Construction 27 | 28 | /*! 29 | @brief Constructs a address manager with the given configuration. 30 | 31 | @param wallet The wallet to manage addresses for. 32 | @param coinType The coin type defining wallet info for. 33 | @param preferred The preferred key path. 34 | @param mode The mode of the wallet. 35 | */ 36 | - (instancetype)initWithKeySequence:(BCKeySequence *)keys 37 | coinType:(BCCoin *)coinType 38 | preferredPath:(BCKeySequenceType)preferred 39 | andMemoryKey:(NSData *)memoryKey; 40 | 41 | #pragma mark Configuration 42 | /*! 43 | @brief The keys the wallet manages 44 | */ 45 | @property(weak, nonatomic, readonly) BCKeySequence *keySequence; 46 | 47 | /*! 48 | @brief The coin the addresses are for. 49 | 50 | @discussion This is my method of supporting different 'environments' such as 51 | TestNet3, MainNet, and other alt-currencies which are close enough to bitcoin 52 | that they still work with this wallet. 53 | */ 54 | @property(strong, nonatomic, readonly) BCCoin *coin; 55 | 56 | /*! 57 | @brief The preferred sequence type of the address manager. 58 | */ 59 | @property(assign, nonatomic, readonly) BCKeySequenceType preferredSequenceType; 60 | 61 | #pragma mark Address Retrieval 62 | 63 | /*! 64 | @brief This is the last known unused external address retrieved. May need to be 65 | synchronized. 66 | 67 | @discussion This is the last retrieved unused external chain address. 68 | 69 | External addresses are used for receiving money from other parties, they 70 | shouldn't be used as change addresses. 71 | */ 72 | @property(strong, nonatomic, readonly) BCAddress *firstUnusedExternal; 73 | 74 | /*! 75 | @brief This is the last know unused internal(change) address retrieved. May 76 | need 77 | to be synchronized. 78 | 79 | @discussion This is the last retrieved unused internal chain address. 80 | 81 | Internal addresses are used for change addresses in transactions, they 82 | shouldn't be given to third parties. 83 | 84 | */ 85 | @property(strong, nonatomic, readonly) BCAddress *firstUnusedInternal; 86 | 87 | #pragma mark Master Keys 88 | 89 | // This system actually works with multiple sequences, and it will slowly 90 | // migrate your money into the preferred sequence. 91 | @property(strong, nonatomic, readonly) BCAMMasterKey *bip44Internal; 92 | @property(strong, nonatomic, readonly) BCAMMasterKey *bip44External; 93 | 94 | @property(strong, nonatomic, readonly) BCAMMasterKey *bip32Internal; 95 | @property(strong, nonatomic, readonly) BCAMMasterKey *bip32External; 96 | 97 | #pragma mark Key Pair retrieval. 98 | 99 | /*! 100 | @brief This gets the key pair for the specified address if any in the 101 | key sequence.. 102 | 103 | @param address The address to get the key pair for. 104 | */ 105 | - (BCKeyPair *)keyPairForAddress:(BCAddress *)address 106 | usingMemoryKey:(NSData *)memoryKey; 107 | 108 | - (NSArray *)keyPairsForScript:(BCScript *)script 109 | usingMemoryKey:(NSData *)memoryKey; 110 | 111 | 112 | #pragma mark Checks 113 | /*! 114 | @brief Checks if the inputted address is in the cache. 115 | 116 | @param address The address to check for. 117 | */ 118 | - (BOOL)hasAddressInCache:(BCAddress *)address; 119 | 120 | @end 121 | -------------------------------------------------------------------------------- /Breadcrumb/Breadcrumb/Address Manager/BCAddressManager.m: -------------------------------------------------------------------------------- 1 | // 2 | // BCAddressManager.m 3 | // Breadcrumb 4 | // 5 | // Created by Andrew Hurst on 2/19/15. 6 | // Copyright (c) 2015 Breadcrumb. 7 | // 8 | // Distributed under the MIT software license, see the accompanying 9 | // file LICENSE or http://www.opensource.org/licenses/mit-license.php. 10 | // 11 | 12 | #import "BCAddressManager.h" 13 | #import "_BCWallet.h" 14 | 15 | @implementation BCAddressManager 16 | 17 | @synthesize keySequence = _keySequence; 18 | @synthesize coin = _coin; 19 | @synthesize preferredSequenceType = _preferredSequenceType; 20 | 21 | #pragma mark Construction 22 | 23 | - (instancetype)initWithKeySequence:(BCKeySequence *)keys 24 | coinType:(BCCoin *)coinType 25 | preferredPath:(BCKeySequenceType)preferred 26 | andMemoryKey:(NSData *)memoryKey { 27 | @autoreleasepool { 28 | NSParameterAssert([keys isKindOfClass:[BCKeySequence class]]); 29 | self = [self init]; 30 | if (!self) return NULL; 31 | _keySequence = keys; 32 | _coin = coinType; 33 | _preferredSequenceType = preferred; 34 | 35 | // Configure Keys 36 | [self setMasters:memoryKey]; 37 | memoryKey = NULL; 38 | return self; 39 | } 40 | } 41 | 42 | #pragma mark Configuration 43 | 44 | - (void)setMasters:(NSData *)memoryKey { 45 | @autoreleasepool { 46 | BCKeyPair *currentKey; 47 | // Set Bip 44 masters FORCE ACCOUNT 0 48 | currentKey = [self.keySequence 49 | keyPairForComponents: 50 | @[ @(0x8000002C), @(self.coin.coinId), @(BIP32_PRIME | 0), @(1) ] 51 | andMemoryKey:memoryKey]; 52 | _bip44Internal = 53 | [[BCAMMasterKey alloc] initWithKeyPair:currentKey andCoin:self.coin]; 54 | 55 | currentKey = [self.keySequence 56 | keyPairForComponents: 57 | @[ @(0x8000002C), @(self.coin.coinId), @(BIP32_PRIME | 0), @(0) ] 58 | andMemoryKey:memoryKey]; 59 | _bip44External = 60 | [[BCAMMasterKey alloc] initWithKeyPair:currentKey andCoin:self.coin]; 61 | 62 | // Set bip 32 masters 63 | currentKey = 64 | [self.keySequence keyPairForComponents:@[ @(BIP32_PRIME | 0), @(1) ] 65 | andMemoryKey:memoryKey]; 66 | _bip32Internal = 67 | [[BCAMMasterKey alloc] initWithKeyPair:currentKey andCoin:self.coin]; 68 | 69 | currentKey = 70 | [self.keySequence keyPairForComponents:@[ @(BIP32_PRIME | 0), @(0) ] 71 | andMemoryKey:memoryKey]; 72 | _bip32External = 73 | [[BCAMMasterKey alloc] initWithKeyPair:currentKey andCoin:self.coin]; 74 | 75 | memoryKey = NULL; 76 | } 77 | } 78 | 79 | #pragma mark Address Data 80 | 81 | - (BCAddress *)firstUnusedExternal { 82 | switch (self.preferredSequenceType) { 83 | case BCKeySequenceType_BIP32: 84 | return self.bip32External.firstUnusedAddress; 85 | break; 86 | default: 87 | return self.bip44External.firstUnusedAddress; 88 | break; 89 | } 90 | } 91 | 92 | - (BCAddress *)firstUnusedInternal { 93 | switch (self.preferredSequenceType) { 94 | case BCKeySequenceType_BIP32: 95 | return self.bip32Internal.firstUnusedAddress; 96 | break; 97 | default: 98 | return self.bip44Internal.firstUnusedAddress; 99 | break; 100 | } 101 | } 102 | 103 | #pragma mark Lookup 104 | 105 | - (BCKeyPair *)keyPairForAddress:(BCAddress *)address 106 | usingMemoryKey:(NSData *)memoryKey { 107 | @autoreleasepool { 108 | BCKeyPair *key; 109 | // Check all masters for key. 110 | key = 111 | [self.bip32Internal keyPairForAddress:address withMemoryKey:memoryKey]; 112 | if ([key isKindOfClass:[BCKeyPair class]]) { 113 | memoryKey = NULL; 114 | return key; 115 | } 116 | 117 | key = 118 | [self.bip32External keyPairForAddress:address withMemoryKey:memoryKey]; 119 | if ([key isKindOfClass:[BCKeyPair class]]) { 120 | memoryKey = NULL; 121 | return key; 122 | } 123 | 124 | key = 125 | [self.bip44Internal keyPairForAddress:address withMemoryKey:memoryKey]; 126 | if ([key isKindOfClass:[BCKeyPair class]]) { 127 | memoryKey = NULL; 128 | return key; 129 | } 130 | 131 | key = 132 | [self.bip44External keyPairForAddress:address withMemoryKey:memoryKey]; 133 | memoryKey = NULL; 134 | if ([key isKindOfClass:[BCKeyPair class]]) return key; 135 | 136 | return NULL; 137 | } 138 | } 139 | 140 | - (NSArray *)keyPairsForScript:(BCScript *)script 141 | usingMemoryKey:(NSData *)memoryKey { 142 | NSMutableData *data = [[NSMutableData alloc] init]; 143 | BCAddress *address; 144 | NSMutableArray *addresses; 145 | 146 | addresses = [[NSMutableArray alloc] init]; 147 | switch (script.type) { 148 | case BCScriptType_P2PKH: 149 | // Fake an address 150 | [data appendUInt8:0x01]; 151 | [data appendData:[script.elements objectAtIndex:2]]; 152 | if (data.length < 20) return NULL; 153 | 154 | address = [data.base58CheckEncoding toBitcoinAddress]; 155 | return @[ [self keyPairForAddress:address usingMemoryKey:memoryKey] ]; 156 | break; 157 | case BCScriptType_P2SH: 158 | // Fake an address 159 | [data appendUInt8:0x01]; 160 | [data appendData:[script.elements objectAtIndex:1]]; 161 | if (data.length < 20) return NULL; 162 | 163 | address = [data.base58CheckEncoding toBitcoinAddress]; 164 | return @[ [self keyPairForAddress:address usingMemoryKey:memoryKey] ]; 165 | break; 166 | case BCScriptType_P2PK: 167 | // Check the pub key is valid 168 | [data appendData:[script.elements objectAtIndex:0]]; 169 | if (data.length < 35) return NULL; 170 | // Get its address 171 | address = 172 | [[[BCPublicKey alloc] initWithData:data] addressForCoin:self.coin]; 173 | return @[ [self keyPairForAddress:address usingMemoryKey:memoryKey] ]; 174 | break; 175 | case BCScriptType_MofN: 176 | // TODO: This 177 | return NULL; 178 | break; 179 | default: 180 | return NULL; 181 | break; 182 | } 183 | 184 | return @[]; 185 | } 186 | 187 | #pragma mark Address checks 188 | 189 | - (BOOL)hasAddressInCache:(BCAddress *)address { 190 | if ([self.bip32External hasAddressInCache:address]) return TRUE; 191 | if ([self.bip32Internal hasAddressInCache:address]) return TRUE; 192 | if ([self.bip44External hasAddressInCache:address]) return TRUE; 193 | if ([self.bip44Internal hasAddressInCache:address]) return TRUE; 194 | return FALSE; 195 | } 196 | 197 | @end 198 | -------------------------------------------------------------------------------- /Breadcrumb/Breadcrumb/Amount/BCAmount.h: -------------------------------------------------------------------------------- 1 | // 2 | // BCAmount.h 3 | // Breadcrumb 4 | // 5 | // Created by Andrew Hurst on 2/5/15. 6 | // Copyright (c) 2015 Breadcrumb. 7 | // 8 | // Distributed under the MIT software license, see the accompanying 9 | // file LICENSE or http://www.opensource.org/licenses/mit-license.php. 10 | // 11 | 12 | #import 13 | 14 | static const uint64_t kBCAmountBits = 1e2; 15 | static const uint64_t kBCAmountmBTC = 1e5; 16 | static const uint64_t kBCAmountBTC = 1e8; 17 | 18 | typedef enum : NSUInteger { 19 | BCUnitType_Satoshi, 20 | BCUnitType_Bits, 21 | BCUnitType_mBTC, 22 | BCUnitType_BTC, 23 | } BCUnitType; 24 | 25 | /*! 26 | @brief A set of class methods for easy to read conversions of amounts of BTC. 27 | */ 28 | @interface BCAmount : NSObject 29 | #pragma mark Satoshi 30 | /*! 31 | @brief Converts the amount of satoshi to bits. 32 | 33 | @param satoshi The amount of satoshi to convert. 34 | */ 35 | + (CGFloat)satoshiToBits:(uint64_t)satoshi; 36 | 37 | /*! 38 | @brief Converts the amount of satoshi to mBTC. 39 | 40 | @param satoshi The amount of satoshi to convert. 41 | */ 42 | + (CGFloat)satoshiTomBTC:(uint64_t)satoshi; 43 | 44 | /*! 45 | @brief Converts the inputted amount of satoshi to BTC. 46 | 47 | @param satoshi The amount of satoshi to convert. 48 | */ 49 | + (CGFloat)satoshiToBTC:(uint64_t)satoshi; 50 | 51 | /*! 52 | @brief Pretty prints the inputed amount of satoshi 53 | 54 | @param satoshi The satoshi amount to pretty print. 55 | */ 56 | + (NSString *)prettyPrint:(uint64_t)satoshi; 57 | 58 | /*! 59 | @brief Gets the best sutited uint 60 | 61 | @param satoshi The amount to get the unit for. 62 | 63 | @return The best suited unit for pretty printing. 64 | */ 65 | + (BCUnitType)perferedUnitFor:(uint64_t)satoshi; 66 | 67 | #pragma mark Common Conversions 68 | /*! 69 | @brief Converts the inputted number of bits into satoshi 70 | 71 | @param Bits The bits to convert. 72 | */ 73 | + (uint64_t)Bits:(CGFloat)Bits; 74 | 75 | /*! 76 | @brief Converts the inputted number of bits into satoshi 77 | 78 | @param Bits The bits to convert. 79 | */ 80 | + (uint64_t)mBTC:(CGFloat)mBTC; 81 | 82 | /*! 83 | @brief Converts the inputted number of BTC into satoshi 84 | 85 | @param btc The BTC to convert. 86 | */ 87 | + (uint64_t)BTC:(CGFloat)btc; 88 | 89 | @end -------------------------------------------------------------------------------- /Breadcrumb/Breadcrumb/Amount/BCAmount.m: -------------------------------------------------------------------------------- 1 | // 2 | // BCAmount.m 3 | // Breadcrumb 4 | // 5 | // Created by Andrew Hurst on 2/5/15. 6 | // Copyright (c) 2015 Breadcrumb. 7 | // 8 | // Distributed under the MIT software license, see the accompanying 9 | // file LICENSE or http://www.opensource.org/licenses/mit-license.php. 10 | // 11 | 12 | #import "BCAmount.h" 13 | 14 | @implementation BCAmount 15 | 16 | #pragma mark Satoshi 17 | 18 | + (CGFloat)satoshiToBits:(uint64_t)satoshi { 19 | return (CGFloat)satoshi / (CGFloat)kBCAmountBits; 20 | } 21 | 22 | + (CGFloat)satoshiTomBTC:(uint64_t)satoshi { 23 | return (CGFloat)satoshi / (CGFloat)kBCAmountmBTC; 24 | } 25 | 26 | + (CGFloat)satoshiToBTC:(uint64_t)satoshi { 27 | return (CGFloat)satoshi / (CGFloat)kBCAmountBTC; 28 | } 29 | 30 | + (NSString *)prettyPrint:(uint64_t)satoshi { 31 | CGFloat amount; 32 | BCUnitType unit = [self perferedUnitFor:satoshi]; 33 | 34 | switch (unit) { 35 | case BCUnitType_Bits: 36 | amount = [self satoshiToBits:satoshi]; 37 | break; 38 | case BCUnitType_mBTC: 39 | amount = [self satoshiTomBTC:satoshi]; 40 | break; 41 | case BCUnitType_BTC: 42 | amount = [self satoshiToBTC:satoshi]; 43 | break; 44 | default: 45 | amount = satoshi; 46 | break; 47 | } 48 | 49 | return 50 | [NSString stringWithFormat:@"%@%@", @(amount), [self symbolForUnit:unit]]; 51 | } 52 | 53 | + (BCUnitType)perferedUnitFor:(uint64_t)satoshi { 54 | if (satoshi < kBCAmountBits) 55 | return BCUnitType_Satoshi; 56 | else if (satoshi < kBCAmountmBTC) 57 | return BCUnitType_Bits; 58 | else if (satoshi < kBCAmountBTC) 59 | return BCUnitType_mBTC; 60 | else 61 | return BCUnitType_BTC; 62 | } 63 | 64 | + (NSString *)symbolForUnit:(BCUnitType)unit { 65 | switch (unit) { 66 | case BCUnitType_Satoshi: 67 | return @"s"; 68 | break; 69 | case BCUnitType_Bits: 70 | return @"ƀ"; 71 | break; 72 | case BCUnitType_mBTC: 73 | return @"mBTC"; 74 | break; 75 | case BCUnitType_BTC: 76 | return @"Ƀ"; 77 | break; 78 | default: 79 | return @"???"; 80 | break; 81 | } 82 | } 83 | 84 | #pragma mark Common Conversions 85 | 86 | + (uint64_t)Bits:(CGFloat)Bits { 87 | return Bits * kBCAmountBits; 88 | } 89 | 90 | + (uint64_t)mBTC:(CGFloat)mBTC { 91 | return mBTC * kBCAmountmBTC; 92 | } 93 | 94 | + (uint64_t)BTC:(CGFloat)btc { 95 | return btc * kBCAmountBTC; 96 | } 97 | 98 | @end -------------------------------------------------------------------------------- /Breadcrumb/Breadcrumb/Breadcrumb-Prefix.pch: -------------------------------------------------------------------------------- 1 | // 2 | // Prefix header 3 | // 4 | // The contents of this file are implicitly included at the beginning of every source file. 5 | // 6 | 7 | #import 8 | 9 | #ifndef __IPHONE_7_0 10 | #warning "This project uses features only available in iOS SDK 7.0 and later." 11 | #endif 12 | 13 | #ifdef __OBJC__ 14 | #import 15 | #import 16 | #endif 17 | 18 | #define BITCOIN_TESTNET 1 19 | #define SATOSHIS 100000000 20 | #define MAX_MONEY (21000000LL*SATOSHIS) 21 | #define PARALAX_RATIO 0.25 22 | //#define TX_FEE_0_8_RULES 1 23 | 24 | #define LDQUOTE @"\xE2\x80\x9C" // left double quote (utf-8) 25 | #define RDQUOTE @"\xE2\x80\x9D" // right double quote (utf-8) 26 | #define DISPLAY_NAME [NSString stringWithFormat:LDQUOTE @"%@" RDQUOTE,\ 27 | NSBundle.mainBundle.infoDictionary[@"CFBundleDisplayName"]] 28 | 29 | #if ! DEBUG 30 | #define NSLog(...) 31 | #endif 32 | -------------------------------------------------------------------------------- /Breadcrumb/Breadcrumb/Breadcrumb.h: -------------------------------------------------------------------------------- 1 | // 2 | // Breadcrumb.h 3 | // Breadcrumb 4 | // 5 | // Created by Andrew Hurst on 2/4/15. 6 | // Copyright (c) 2015 Breadcrumb. 7 | // 8 | // Distributed under the MIT software license, see the accompanying 9 | // file LICENSE or http://www.opensource.org/licenses/mit-license.php. 10 | // 11 | // 12 | 13 | #import 14 | 15 | //! Project version number for Breadcrumb. 16 | FOUNDATION_EXPORT double BreadcrumbVersionNumber; 17 | 18 | //! Project version string for Breadcrumb. 19 | FOUNDATION_EXPORT const unsigned char BreadcrumbVersionString[]; 20 | 21 | // In this header, you should import all the public headers of your framework 22 | // using statements like #import 23 | 24 | #pragma mark Utilities 25 | #import 26 | #import 27 | #import 28 | #import 29 | 30 | #pragma mark Scripts 31 | #import 32 | #import 33 | 34 | #pragma mark Concrete Interfaces 35 | #import 36 | #import 37 | 38 | #pragma mark Transaction Interfaces 39 | #import 40 | 41 | #pragma mark Wallets 42 | #import 43 | #import 44 | 45 | 46 | #pragma mark Providers 47 | #import 48 | #import 49 | 50 | #import -------------------------------------------------------------------------------- /Breadcrumb/Breadcrumb/BreadcrumbCore.h: -------------------------------------------------------------------------------- 1 | // 2 | // BreadcrumbCore.h 3 | // Breadcrumb 4 | // 5 | // Created by Andrew Hurst on 2/5/15. 6 | // Copyright (c) 2015 Breadcrumb. 7 | // 8 | // Distributed under the MIT software license, see the accompanying 9 | // file LICENSE or http://www.opensource.org/licenses/mit-license.php. 10 | // 11 | // 12 | 13 | #import 14 | #import 15 | #import 16 | 17 | 18 | #import 19 | #import 20 | #import 21 | #import 22 | 23 | #import 24 | #import 25 | #import 26 | #import 27 | -------------------------------------------------------------------------------- /Breadcrumb/Breadcrumb/Categories/NSData+Encryption.h: -------------------------------------------------------------------------------- 1 | // 2 | // NSData+Encryption.h 3 | // Breadcrumb 4 | // 5 | // Created by Andrew Hurst on 2/6/15. 6 | // Copyright (c) 2015 Breadcrumb. 7 | // 8 | // Distributed under the MIT software license, see the accompanying 9 | // file LICENSE or http://www.opensource.org/licenses/mit-license.php. 10 | // 11 | // 12 | 13 | #import 14 | 15 | @interface NSData (Encryption) 16 | 17 | #pragma mark AES 18 | /*! 19 | @brief Encrypts the data with AES 256 using the inputted key. 20 | 21 | @param key The key to encrypt the data with. 22 | */ 23 | - (NSData *)AES256Encrypt:(NSData *)key; 24 | 25 | /*! 26 | @brief Decrypts the data with AES 256 using the inputted key. 27 | 28 | @param key The key to decrypt the data with. 29 | */ 30 | - (NSData *)AES256Decrypt:(NSData *)key; 31 | 32 | - (NSData *)AES256ETMEncrypt:(NSData *)key; 33 | - (NSData *)AES256ETMDecrypt:(NSData *)key; 34 | 35 | #pragma mark Scrypt 36 | /*! 37 | @brief Scrypts the inputed password with the salt, and the output length. 38 | 39 | @param password The password to to derive from. 40 | @param salt The salt to use. 41 | @param length The output length. 42 | */ 43 | + (NSData *)scryptPassword:(NSData *)password 44 | usingSalt:(NSData *)salt 45 | withOutputLength:(NSUInteger)length; 46 | 47 | /*! 48 | @brief Scrypts the inputed password with the inputted algorithm parameters. 49 | 50 | @param password The password to to derive from. 51 | @param salt The salt to use. 52 | @param n The work factor of the algorithm. 53 | @param r The block size of the algorithm. 54 | @param p The paralyzation factor of the algorithm. 55 | @param length The byte length of the output. 56 | */ 57 | + (NSData *)scryptPassword:(NSData *)password 58 | usingSalt:(NSData *)salt 59 | workFactor:(uint64_t)n 60 | blockSize:(uint32_t)r 61 | parallelizationFactor:(uint32_t)p 62 | withOutputLength:(NSUInteger)length; 63 | 64 | #pragma mark Sec Random 65 | 66 | + (NSData *)pseudoRandomDataWithLength:(NSUInteger)length; 67 | 68 | @end 69 | -------------------------------------------------------------------------------- /Breadcrumb/Breadcrumb/Categories/NSString+Base58.h: -------------------------------------------------------------------------------- 1 | // 2 | // NSString+Base58.h 3 | // Breadcrumb 4 | // 5 | // Adapted by Andrew Hurst on 2/13/15. 6 | // 7 | // Created by Aaron Voisine on 5/13/13. 8 | // Copyright (c) 2013 Aaron Voisine 9 | // 10 | // Permission is hereby granted, free of charge, to any person obtaining a copy 11 | // of this software and associated documentation files (the "Software"), to 12 | // deal 13 | // in the Software without restriction, including without limitation the rights 14 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 15 | // copies of the Software, and to permit persons to whom the Software is 16 | // furnished to do so, subject to the following conditions: 17 | // 18 | // The above copyright notice and this permission notice shall be included in 19 | // all copies or substantial portions of the Software. 20 | // 21 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 22 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 23 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 24 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 25 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 26 | // FROM, 27 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 28 | // THE SOFTWARE. 29 | 30 | #import 31 | 32 | #define BITCOIN_PUBKEY_ADDRESS 0 33 | #define BITCOIN_SCRIPT_ADDRESS 5 34 | #define BITCOIN_PUBKEY_ADDRESS_TEST 111 35 | #define BITCOIN_SCRIPT_ADDRESS_TEST 196 36 | #define BITCOIN_PRIVKEY 128 37 | #define BITCOIN_PRIVKEY_TEST 239 38 | 39 | @interface NSString (BCBase58) 40 | #pragma mark Encoding 41 | /*! 42 | @brief Encodes the inputted data into raw base 58 format 43 | 44 | @param data The data to encode into raw base 58 45 | */ 46 | + (NSString *)base58WithData:(NSData *)data; 47 | 48 | /*! 49 | @brief Encodes the inputted data into base58 check format. 50 | 51 | @param data The data to encode into base58 check format. 52 | */ 53 | + (NSString *)base58checkWithData:(NSData *)data; 54 | 55 | /*! 56 | @brief Encodes a hex string into a bas358 check string. 57 | */ 58 | - (NSString *)hexToBase58check; 59 | 60 | /*! 61 | @brief Encodes the inputted data into a hex string. 62 | 63 | @param data The data to encode into a hex string 64 | */ 65 | + (NSString *)hexWithData:(NSData *)data; 66 | 67 | /*! 68 | @brief Encodes hex into a raw base58 string. 69 | */ 70 | - (NSString *)hexToBase58; 71 | 72 | #pragma mark Decoding 73 | /*! 74 | @brief Decodes a raw base58 encoded string into data. 75 | */ 76 | - (NSData *)base58ToData; 77 | 78 | /*! 79 | @brief Decodes a base58 check encoded string into data. 80 | */ 81 | - (NSData *)base58checkToData; 82 | 83 | /*! 84 | @brief Decodes a base 58 check string into a hex string. 85 | */ 86 | - (NSString *)base58checkToHex; 87 | 88 | /*! 89 | @brief Decodes base58 to hex. 90 | */ 91 | - (NSString *)base58ToHex; 92 | 93 | /*! 94 | @brief Decodes a hex string into data. 95 | */ 96 | - (NSData *)hexToData; 97 | 98 | - (NSData *)addressToHash160; 99 | 100 | #pragma mark Validity Checks 101 | 102 | /*! 103 | @brief Checks if the string is a valid bitcoin address 104 | */ 105 | //- (BOOL)isValidBitcoinAddress; 106 | 107 | /*! 108 | @brief Checks if the string is a valid private key. 109 | */ 110 | //- (BOOL)isValidBitcoinPrivateKey; 111 | 112 | /*! 113 | @brief Checks if the key is a valid BIP38 key. 114 | 115 | @discussion BIP38 encrypted keys: 116 | https://github.com/bitcoin/bips/blob/master/bip-0038.mediawiki 117 | */ 118 | //- (BOOL)isValidBitcoinBIP38Key; 119 | 120 | @end 121 | 122 | @interface NSData (BCBase58) 123 | 124 | - (NSString *)base58Encoding; 125 | + (NSData *)fromBase58:(NSString *)base58Encoding; 126 | - (NSString *)base58CheckEncoding; 127 | + (NSData *)fromBase58Check:(NSString *)base58CheckEncoding; 128 | - (NSString *)toHex; 129 | + (NSData *)fromHex:(NSString *)hex; 130 | @end 131 | -------------------------------------------------------------------------------- /Breadcrumb/Breadcrumb/Coins/BCCoin.h: -------------------------------------------------------------------------------- 1 | // 2 | // BCCoin.h 3 | // Breadcrumb 4 | // 5 | // Created by Andrew Hurst on 2/20/15. 6 | // Copyright (c) 2015 Breadcrumb. 7 | // 8 | // Distributed under the MIT software license, see the accompanying 9 | // file LICENSE or http://www.opensource.org/licenses/mit-license.php. 10 | // 11 | 12 | #import 13 | @class BCAddress; 14 | 15 | // @brief This defines a set of known address types. OLD MIGRATE. 16 | // typedef enum : uint8_t { 17 | // BCAddressType_Old = 0x00, 18 | // BCAddressType_New = 0x05 19 | // } BCAddressType; 20 | 21 | /*! 22 | @brief This is my method of supporting different 'environments' such as 23 | TestNet3, MainNet, and other alt-currencies which are close enough to bitcoin 24 | that they still work with this wallet. 25 | 26 | @discussion This method allows us to have multiple wallets for different 27 | currencies in the same application simultaneously. ;) 28 | */ 29 | @interface BCCoin : NSObject 30 | 31 | #pragma mark Coin Metadata 32 | /*! 33 | @brief The id of the coin used in BIP 44. 34 | */ 35 | @property(assign, nonatomic, readonly) uint32_t coinId; 36 | 37 | #pragma mark Address Info 38 | /*! 39 | @brief Gets the correct address type code for the specified string. 40 | 41 | @param flags The flags indicating the address type information 42 | 43 | @return The type code that should be used for the address with the specified 44 | flag. 45 | */ 46 | - (uint8_t)addressTypeForFlags:(NSUInteger)flags; 47 | 48 | /*! 49 | @brief Checks if the inputted address is valid for the coin. 50 | 51 | @param address The address to check. 52 | */ 53 | - (BOOL)typeIsValidForCoin:(BCAddress *)address; 54 | 55 | #pragma mark Default Coins 56 | 57 | @property(assign, nonatomic, readonly) uint8_t P2SHCode; 58 | 59 | /*! 60 | @brief This coin is configured for main net. 61 | */ 62 | + (instancetype)MainNetBitcoin; 63 | 64 | /*! 65 | @brief This coin is configured for testnet3. 66 | */ 67 | + (instancetype)TestNet3Bitcoin; 68 | 69 | @end 70 | 71 | @interface BCMainNetBitcoin : BCCoin 72 | @end 73 | 74 | @interface BCTestNet3Bitcoin : BCCoin 75 | @end 76 | -------------------------------------------------------------------------------- /Breadcrumb/Breadcrumb/Coins/BCCoin.m: -------------------------------------------------------------------------------- 1 | // 2 | // BCCoin.m 3 | // Breadcrumb 4 | // 5 | // Created by Andrew Hurst on 2/20/15. 6 | // Copyright (c) 2015 Breadcrumb. 7 | // 8 | // Distributed under the MIT software license, see the accompanying 9 | // file LICENSE or http://www.opensource.org/licenses/mit-license.php. 10 | // 11 | 12 | #import "BCCoin.h" 13 | #import "BCAddress.h" 14 | 15 | @implementation BCCoin 16 | 17 | #pragma mark Address Info 18 | /*! 19 | @brief Gets the correct address type code for the specified string. 20 | 21 | @param flags The flags indicating the address type information 22 | 23 | @return The type code that should be used for the address with the specified 24 | flag. 25 | */ 26 | - (uint8_t)addressTypeForFlags:(NSUInteger)flags { 27 | NSAssert(false, @"Abstract Method!"); 28 | return UINT8_MAX; 29 | } 30 | 31 | - (BOOL)typeIsValidForCoin:(BCAddress *)address { 32 | NSAssert(false, @"Abstract Method!"); 33 | return FALSE; 34 | } 35 | 36 | - (uint32_t)coinId { 37 | return 0x80000000; 38 | } 39 | 40 | - (uint8_t)P2SHCode { 41 | return 0x05; 42 | } 43 | 44 | #pragma mark Default Coins 45 | 46 | + (instancetype)MainNetBitcoin { 47 | static dispatch_once_t onceToken; 48 | static BCCoin *coin; 49 | dispatch_once(&onceToken, ^{ coin = [[BCMainNetBitcoin alloc] init]; }); 50 | return coin; 51 | } 52 | 53 | + (instancetype)TestNet3Bitcoin { 54 | static dispatch_once_t onceToken; 55 | static BCCoin *coin; 56 | dispatch_once(&onceToken, ^{ coin = [[BCTestNet3Bitcoin alloc] init]; }); 57 | return coin; 58 | } 59 | 60 | @end 61 | 62 | @implementation BCMainNetBitcoin 63 | 64 | - (uint8_t)addressTypeForFlags:(NSUInteger)flags { 65 | switch (flags) { 66 | default: 67 | return 0x00; 68 | break; 69 | } 70 | } 71 | 72 | - (BOOL)typeIsValidForCoin:(BCAddress *)address { 73 | if (![address isKindOfClass:[BCAddress class]]) return FALSE; 74 | // Dialaowing test net addresses, and private keys. https://en.bitcoin.it/wiki/List_of_address_prefixes 75 | return (address.typeCode == 0x00 || address.typeCode == 0x05) && 76 | (address.typeCode != 111 || address.typeCode != 196 || 77 | address.typeCode != 239 || address.typeCode != 128); 78 | } 79 | 80 | - (uint32_t)coinId { 81 | return 0x80000000; 82 | } 83 | 84 | - (uint8_t)P2SHCode { 85 | return 0x05; 86 | } 87 | 88 | @end 89 | 90 | @implementation BCTestNet3Bitcoin 91 | 92 | - (uint8_t)addressTypeForFlags:(NSUInteger)flags { 93 | switch (flags) { 94 | default: 95 | return 111; 96 | break; 97 | } 98 | } 99 | 100 | - (BOOL)typeIsValidForCoin:(BCAddress *)address { 101 | if (![address isKindOfClass:[BCAddress class]]) return FALSE; 102 | // Must be one of the regestered values https://en.bitcoin.it/wiki/List_of_address_prefixes 103 | return address.typeCode == 111 || address.typeCode == 196; 104 | } 105 | 106 | - (uint32_t)coinId { 107 | return 0x80000001; 108 | } 109 | 110 | 111 | - (uint8_t)P2SHCode { 112 | return 196; 113 | } 114 | 115 | @end 116 | -------------------------------------------------------------------------------- /Breadcrumb/Breadcrumb/Crumbs/BRBIP32Sequence.h: -------------------------------------------------------------------------------- 1 | // 2 | // BRBIP32Sequence.h 3 | // BreadWallet 4 | // 5 | // Created by Aaron Voisine on 7/19/13. 6 | // Copyright (c) 2013 Aaron Voisine 7 | // 8 | // Permission is hereby granted, free of charge, to any person obtaining a copy 9 | // of this software and associated documentation files (the "Software"), to deal 10 | // in the Software without restriction, including without limitation the rights 11 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 12 | // copies of the Software, and to permit persons to whom the Software is 13 | // furnished to do so, subject to the following conditions: 14 | // 15 | // The above copyright notice and this permission notice shall be included in 16 | // all copies or substantial portions of the Software. 17 | // 18 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 23 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 24 | // THE SOFTWARE. 25 | 26 | #import 27 | #import "BRKeySequence.h" 28 | 29 | @interface BRBIP32Sequence : NSObject 30 | 31 | - (NSData *)masterPublicKeyFromSeed:(NSData *)seed; 32 | - (NSData *)publicKey:(unsigned)n internal:(BOOL)internal masterPublicKey:(NSData *)masterPublicKey; 33 | - (NSString *)privateKey:(unsigned)n internal:(BOOL)internal fromSeed:(NSData *)seed; 34 | - (NSArray *)privateKeys:(NSArray *)n internal:(BOOL)internal fromSeed:(NSData *)seed; 35 | 36 | - (NSString *)serializedPrivateMasterFromSeed:(NSData *)seed; 37 | - (NSString *)serializedMasterPublicKey:(NSData *)masterPublicKey; 38 | 39 | @end 40 | -------------------------------------------------------------------------------- /Breadcrumb/Breadcrumb/Crumbs/BRBIP39Mnemonic.h: -------------------------------------------------------------------------------- 1 | // 2 | // BRBIP39Mnemonic.h 3 | // BreadWallet 4 | // 5 | // Created by Aaron Voisine on 3/21/14. 6 | // Copyright (c) 2014 Aaron Voisine 7 | // 8 | // Permission is hereby granted, free of charge, to any person obtaining a copy 9 | // of this software and associated documentation files (the "Software"), to 10 | // deal 11 | // in the Software without restriction, including without limitation the rights 12 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 13 | // copies of the Software, and to permit persons to whom the Software is 14 | // furnished to do so, subject to the following conditions: 15 | // 16 | // The above copyright notice and this permission notice shall be included in 17 | // all copies or substantial portions of the Software. 18 | // 19 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 20 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 21 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 22 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 23 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 24 | // FROM, 25 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 26 | // THE SOFTWARE. 27 | 28 | #import 29 | #import "BRMnemonic.h" 30 | 31 | // BIP39 is method for generating a deterministic wallet seed from a mnemonic 32 | // phrase 33 | // https://github.com/bitcoin/bips/blob/master/bip-0039.mediawiki 34 | 35 | #define BIP39_CREATION_TIME (1388534400.0 - NSTimeIntervalSince1970) 36 | #define WORDS @"BIP39EnglishWords" 37 | 38 | @interface BRBIP39Mnemonic : NSObject 39 | 40 | + (instancetype)sharedInstance; 41 | 42 | - (NSString *)encodePhrase:(NSData *)data; 43 | - (NSData *)decodePhrase:(NSString *)phrase; 44 | - (BOOL)phraseIsValid:(NSString *)phrase; 45 | 46 | - (NSString *)normalizePhrase:(NSString *)phrase; 47 | - (NSData *)deriveKeyFromPhrase:(NSString *)phrase 48 | withPassphrase:(NSString *)passphrase; 49 | 50 | + (NSBundle *)bundle; 51 | @end 52 | -------------------------------------------------------------------------------- /Breadcrumb/Breadcrumb/Crumbs/BRKey+BIP38.h: -------------------------------------------------------------------------------- 1 | // 2 | // BRKey+BIP38.h 3 | // BreadWallet 4 | // 5 | // Created by Aaron Voisine on 4/9/14. 6 | // Copyright (c) 2014 Aaron Voisine 7 | // 8 | // Permission is hereby granted, free of charge, to any person obtaining a copy 9 | // of this software and associated documentation files (the "Software"), to deal 10 | // in the Software without restriction, including without limitation the rights 11 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 12 | // copies of the Software, and to permit persons to whom the Software is 13 | // furnished to do so, subject to the following conditions: 14 | // 15 | // The above copyright notice and this permission notice shall be included in 16 | // all copies or substantial portions of the Software. 17 | // 18 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 23 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 24 | // THE SOFTWARE. 25 | 26 | #import "BRKey.h" 27 | 28 | // BIP38 is a method for encrypting private keys with a passphrase 29 | // https://github.com/bitcoin/bips/blob/master/bip-0038.mediawiki 30 | 31 | @interface BRKey (BIP38) 32 | 33 | // decrypts a BIP38 key using the given passphrase or retuns nil if passphrase is incorrect 34 | + (instancetype)keyWithBIP38Key:(NSString *)key andPassphrase:(NSString *)passphrase; 35 | 36 | // generates an "intermediate code" for an EC multiply mode key, salt should be 64bits of random data 37 | + (NSString *)BIP38IntermediateCodeWithSalt:(uint64_t)salt andPassphrase:(NSString *)passphrase; 38 | 39 | // generates an "intermediate code" for an EC multiply mode key with a lot and sequence number, lot must be less than 40 | // 1048576, sequence must be less than 4096, and salt should be 32bits of random data 41 | + (NSString *)BIP38IntermediateCodeWithLot:(uint32_t)lot sequence:(uint16_t)sequence salt:(uint32_t)salt 42 | passphrase:(NSString *)passphrase; 43 | 44 | // generates a BIP38 key from an "intermediate code" and 24 bytes of cryptographically random data (seedb), 45 | // compressed indicates if compressed pubKey format should be used for the bitcoin address, confcode (optional) will 46 | // be set to the "confirmation code" 47 | + (NSString *)BIP38KeyWithIntermediateCode:(NSString *)code seedb:(NSData *)seedb compressed:(BOOL)compressed 48 | confirmationCode:(NSString **)confcode; 49 | 50 | // returns true if the "confirmation code" confirms that the given bitcoin address depends on the specified passphrase 51 | + (BOOL)confirmWithBIP38ConfirmationCode:(NSString *)code address:(NSString *)address passphrase:(NSString *)passphrase; 52 | 53 | - (instancetype)initWithBIP38Key:(NSString *)key andPassphrase:(NSString *)passphrase; 54 | 55 | // encrypts receiver with passphrase and returns BIP38 key 56 | - (NSString *)BIP38KeyWithPassphrase:(NSString *)passphrase; 57 | 58 | @end 59 | -------------------------------------------------------------------------------- /Breadcrumb/Breadcrumb/Crumbs/BRKey.h: -------------------------------------------------------------------------------- 1 | // 2 | // BRKey.h 3 | // BreadWallet 4 | // 5 | // Created by Aaron Voisine on 5/22/13. 6 | // Copyright (c) 2013 Aaron Voisine 7 | // 8 | // Permission is hereby granted, free of charge, to any person obtaining a copy 9 | // of this software and associated documentation files (the "Software"), to deal 10 | // in the Software without restriction, including without limitation the rights 11 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 12 | // copies of the Software, and to permit persons to whom the Software is 13 | // furnished to do so, subject to the following conditions: 14 | // 15 | // The above copyright notice and this permission notice shall be included in 16 | // all copies or substantial portions of the Software. 17 | // 18 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 23 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 24 | // THE SOFTWARE. 25 | 26 | #import 27 | 28 | @interface BRKey : NSObject 29 | 30 | @property (nonatomic, strong) NSString *privateKey; 31 | @property (nonatomic, strong) NSData *publicKey; 32 | @property (nonatomic, readonly) NSString *address; 33 | @property (nonatomic, readonly) NSData *hash160; 34 | 35 | + (instancetype)keyWithPrivateKey:(NSString *)privateKey; 36 | + (instancetype)keyWithSecret:(NSData *)secret compressed:(BOOL)compressed; 37 | + (instancetype)keyWithPublicKey:(NSData *)publicKey; 38 | 39 | - (instancetype)initWithPrivateKey:(NSString *)privateKey; 40 | - (instancetype)initWithSecret:(NSData *)secret compressed:(BOOL)compressed; 41 | - (instancetype)initWithPublicKey:(NSData *)publicKey; 42 | 43 | - (NSData *)sign:(NSData *)d; 44 | - (BOOL)verify:(NSData *)d signature:(NSData *)sig; 45 | 46 | @end 47 | -------------------------------------------------------------------------------- /Breadcrumb/Breadcrumb/Crumbs/BRKeySequence.h: -------------------------------------------------------------------------------- 1 | // 2 | // BRKeySequence.h 3 | // BreadWallet 4 | // 5 | // Created by Aaron Voisine on 5/27/13. 6 | // Copyright (c) 2013 Aaron Voisine 7 | // 8 | // Permission is hereby granted, free of charge, to any person obtaining a copy 9 | // of this software and associated documentation files (the "Software"), to deal 10 | // in the Software without restriction, including without limitation the rights 11 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 12 | // copies of the Software, and to permit persons to whom the Software is 13 | // furnished to do so, subject to the following conditions: 14 | // 15 | // The above copyright notice and this permission notice shall be included in 16 | // all copies or substantial portions of the Software. 17 | // 18 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 23 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 24 | // THE SOFTWARE. 25 | 26 | #import 27 | 28 | #define SEQUENCE_GAP_LIMIT_EXTERNAL 10 29 | #define SEQUENCE_GAP_LIMIT_INTERNAL 5 30 | 31 | @protocol BRKeySequence 32 | @required 33 | 34 | - (NSData *)masterPublicKeyFromSeed:(NSData *)seed; 35 | - (NSData *)publicKey:(unsigned)n internal:(BOOL)internal masterPublicKey:(NSData *)masterPublicKey; 36 | - (NSString *)privateKey:(unsigned)n internal:(BOOL)internal fromSeed:(NSData *)seed; 37 | - (NSArray *)privateKeys:(NSArray *)n internal:(BOOL)internal fromSeed:(NSData *)seed; 38 | 39 | @end 40 | -------------------------------------------------------------------------------- /Breadcrumb/Breadcrumb/Crumbs/BRMnemonic.h: -------------------------------------------------------------------------------- 1 | // 2 | // BRMnemonic.h 3 | // BreadWallet 4 | // 5 | // Created by Aaron Voisine on 8/15/13. 6 | // Copyright (c) 2013 Aaron Voisine 7 | // 8 | // Permission is hereby granted, free of charge, to any person obtaining a copy 9 | // of this software and associated documentation files (the "Software"), to deal 10 | // in the Software without restriction, including without limitation the rights 11 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 12 | // copies of the Software, and to permit persons to whom the Software is 13 | // furnished to do so, subject to the following conditions: 14 | // 15 | // The above copyright notice and this permission notice shall be included in 16 | // all copies or substantial portions of the Software. 17 | // 18 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 23 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 24 | // THE SOFTWARE. 25 | 26 | #import 27 | 28 | @protocol BRMnemonic 29 | @required 30 | 31 | - (NSString *)encodePhrase:(NSData *)data; 32 | - (NSData *)decodePhrase:(NSString *)phrase; 33 | - (BOOL)phraseIsValid:(NSString *)phrase; 34 | 35 | @end 36 | -------------------------------------------------------------------------------- /Breadcrumb/Breadcrumb/Crumbs/NSData+Bitcoin.h: -------------------------------------------------------------------------------- 1 | // 2 | // NSData+Bitcoin.h 3 | // BreadWallet 4 | // 5 | // Created by Aaron Voisine on 10/9/13. 6 | // Copyright (c) 2013 Aaron Voisine 7 | // 8 | // Permission is hereby granted, free of charge, to any person obtaining a copy 9 | // of this software and associated documentation files (the "Software"), to 10 | // deal 11 | // in the Software without restriction, including without limitation the rights 12 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 13 | // copies of the Software, and to permit persons to whom the Software is 14 | // furnished to do so, subject to the following conditions: 15 | // 16 | // The above copyright notice and this permission notice shall be included in 17 | // all copies or substantial portions of the Software. 18 | // 19 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 20 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 21 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 22 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 23 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 24 | // FROM, 25 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 26 | // THE SOFTWARE. 27 | 28 | #import 29 | #import "BCScriptOpCodes.h" 30 | 31 | #define VAR_INT16_HEADER 0xfd 32 | #define VAR_INT32_HEADER 0xfe 33 | #define VAR_INT64_HEADER 0xff 34 | 35 | // bitcoin script opcodes: https://en.bitcoin.it/wiki/Script#Constants 36 | //#define OP_PUSHDATA1 0x4c 37 | //#define OP_PUSHDATA2 0x4d 38 | //#define OP_PUSHDATA4 0x4e 39 | //#define OP_DUP 0x76 40 | //#define OP_EQUAL 0x87 41 | //#define OP_EQUALVERIFY 0x88 42 | //#define OP_HASH160 0xa9 43 | //#define OP_CHECKSIG 0xac 44 | 45 | @interface NSData (Bitcoin) 46 | 47 | - (uint8_t)UInt8AtOffset:(NSUInteger)offset; 48 | - (uint16_t)UInt16AtOffset:(NSUInteger)offset; 49 | - (uint32_t)UInt32AtOffset:(NSUInteger)offset; 50 | - (uint64_t)UInt64AtOffset:(NSUInteger)offset; 51 | - (uint64_t)varIntAtOffset:(NSUInteger)offset length:(NSUInteger *)length; 52 | - (NSData *)hashAtOffset:(NSUInteger)offset; 53 | - (NSString *)stringAtOffset:(NSUInteger)offset length:(NSUInteger *)length; 54 | - (NSData *)dataAtOffset:(NSUInteger)offset length:(NSUInteger *)length; 55 | - (NSArray *)scriptElements; // an array of NSNumber and NSData objects 56 | // representing each script element 57 | - (int)intValue; // returns the opcode used to store the receiver in a script 58 | // (i.e. OP_PUSHDATA1) 59 | 60 | @end 61 | -------------------------------------------------------------------------------- /Breadcrumb/Breadcrumb/Crumbs/NSData+Bitcoin.m: -------------------------------------------------------------------------------- 1 | // 2 | // NSData+Bitcoin.m 3 | // BreadWallet 4 | // 5 | // Created by Aaron Voisine on 10/9/13. 6 | // Copyright (c) 2013 Aaron Voisine 7 | // 8 | // Permission is hereby granted, free of charge, to any person obtaining a copy 9 | // of this software and associated documentation files (the "Software"), to 10 | // deal 11 | // in the Software without restriction, including without limitation the rights 12 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 13 | // copies of the Software, and to permit persons to whom the Software is 14 | // furnished to do so, subject to the following conditions: 15 | // 16 | // The above copyright notice and this permission notice shall be included in 17 | // all copies or substantial portions of the Software. 18 | // 19 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 20 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 21 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 22 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 23 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 24 | // FROM, 25 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 26 | // THE SOFTWARE. 27 | 28 | #import "NSData+Bitcoin.h" 29 | #import 30 | 31 | @implementation NSData (Bitcoin) 32 | 33 | - (uint8_t)UInt8AtOffset:(NSUInteger)offset { 34 | if (self.length < offset + sizeof(uint8_t)) return 0; 35 | return *((const uint8_t *)self.bytes + offset); 36 | } 37 | 38 | - (uint16_t)UInt16AtOffset:(NSUInteger)offset { 39 | if (self.length < offset + sizeof(uint16_t)) return 0; 40 | return CFSwapInt16LittleToHost( 41 | *(const uint16_t *)((const uint8_t *)self.bytes + offset)); 42 | } 43 | 44 | - (uint32_t)UInt32AtOffset:(NSUInteger)offset { 45 | if (self.length < offset + sizeof(uint32_t)) return 0; 46 | return CFSwapInt32LittleToHost( 47 | *(const uint32_t *)((const uint8_t *)self.bytes + offset)); 48 | } 49 | 50 | - (uint64_t)UInt64AtOffset:(NSUInteger)offset { 51 | if (self.length < offset + sizeof(uint64_t)) return 0; 52 | return CFSwapInt64LittleToHost( 53 | *(const uint64_t *)((const uint8_t *)self.bytes + offset)); 54 | } 55 | 56 | - (uint64_t)varIntAtOffset:(NSUInteger)offset length:(NSUInteger *)length { 57 | uint8_t h = [self UInt8AtOffset:offset]; 58 | 59 | switch (h) { 60 | case VAR_INT16_HEADER: 61 | if (length) *length = sizeof(h) + sizeof(uint16_t); 62 | return [self UInt16AtOffset:offset + 1]; 63 | 64 | case VAR_INT32_HEADER: 65 | if (length) *length = sizeof(h) + sizeof(uint32_t); 66 | return [self UInt32AtOffset:offset + 1]; 67 | 68 | case VAR_INT64_HEADER: 69 | if (length) *length = sizeof(h) + sizeof(uint64_t); 70 | return [self UInt64AtOffset:offset + 1]; 71 | 72 | default: 73 | if (length) *length = sizeof(h); 74 | return h; 75 | } 76 | } 77 | 78 | - (NSData *)hashAtOffset:(NSUInteger)offset { 79 | if (self.length < offset + CC_SHA256_DIGEST_LENGTH) return nil; 80 | return [self subdataWithRange:NSMakeRange(offset, CC_SHA256_DIGEST_LENGTH)]; 81 | } 82 | 83 | - (NSString *)stringAtOffset:(NSUInteger)offset length:(NSUInteger *)length { 84 | NSUInteger ll, l = (NSUInteger)[self varIntAtOffset : offset length : &ll]; 85 | 86 | if (length) *length = ll + l; 87 | if (ll == 0 || self.length < offset + ll + l) return nil; 88 | return [[NSString alloc] initWithBytes:(const char *)self.bytes + offset + ll 89 | length:l 90 | encoding:NSUTF8StringEncoding]; 91 | } 92 | 93 | - (NSData *)dataAtOffset:(NSUInteger)offset length:(NSUInteger *)length { 94 | NSUInteger ll, l = (NSUInteger)[self varIntAtOffset : offset length : &ll]; 95 | 96 | if (length) *length = ll + l; 97 | if (ll == 0 || self.length < offset + ll + l) return nil; 98 | return [self subdataWithRange:NSMakeRange(offset + ll, l)]; 99 | } 100 | 101 | // an array of NSNumber and NSData objects representing each script element 102 | - (NSArray *)scriptElements { 103 | NSMutableArray *a = [NSMutableArray array]; 104 | const uint8_t *b = (const uint8_t *)self.bytes; 105 | NSUInteger l, length = self.length; 106 | 107 | for (NSUInteger i = 0; i < length; i++) { 108 | if (b[i] > OP_PUSHDATA4) { 109 | [a addObject:@(b[i])]; 110 | continue; 111 | } 112 | 113 | switch (b[i]) { 114 | case 0: 115 | [a addObject:@(0)]; 116 | continue; 117 | 118 | case OP_PUSHDATA1: 119 | i++; 120 | if (i + sizeof(uint8_t) > length) return a; 121 | l = b[i]; 122 | i += sizeof(uint8_t); 123 | break; 124 | 125 | case OP_PUSHDATA2: 126 | i++; 127 | if (i + sizeof(uint16_t) > length) return a; 128 | l = CFSwapInt16LittleToHost(*(uint16_t *)&b[i]); 129 | i += sizeof(uint16_t); 130 | break; 131 | 132 | case OP_PUSHDATA4: 133 | i++; 134 | if (i + sizeof(uint32_t) > length) return a; 135 | l = CFSwapInt32LittleToHost(*(uint32_t *)&b[i]); 136 | i += sizeof(uint32_t); 137 | break; 138 | 139 | default: 140 | l = b[i]; 141 | i++; 142 | break; 143 | } 144 | 145 | if (i + l > length) return a; 146 | [a addObject:[NSData dataWithBytes:&b[i] length:l]]; 147 | i += l - 1; 148 | } 149 | 150 | return a; 151 | } 152 | 153 | // returns the opcode used to store the receiver in a script (i.e. OP_PUSHDATA1) 154 | - (int)intValue { 155 | if (self.length < OP_PUSHDATA1) 156 | return (int)self.length; 157 | else if (self.length <= UINT8_MAX) 158 | return OP_PUSHDATA1; 159 | else if (self.length <= UINT16_MAX) 160 | return OP_PUSHDATA2; 161 | else 162 | return OP_PUSHDATA4; 163 | } 164 | 165 | @end 166 | -------------------------------------------------------------------------------- /Breadcrumb/Breadcrumb/Crumbs/NSData+Hash.h: -------------------------------------------------------------------------------- 1 | // 2 | // NSData+Hash.h 3 | // BreadWallet 4 | // 5 | // Created by Aaron Voisine on 5/13/13. 6 | // Copyright (c) 2013 Aaron Voisine 7 | // 8 | // Permission is hereby granted, free of charge, to any person obtaining a copy 9 | // of this software and associated documentation files (the "Software"), to 10 | // deal 11 | // in the Software without restriction, including without limitation the rights 12 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 13 | // copies of the Software, and to permit persons to whom the Software is 14 | // furnished to do so, subject to the following conditions: 15 | // 16 | // The above copyright notice and this permission notice shall be included in 17 | // all copies or substantial portions of the Software. 18 | // 19 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 20 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 21 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 22 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 23 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 24 | // FROM, 25 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 26 | // THE SOFTWARE. 27 | 28 | #import 29 | 30 | @interface NSData (Hash) 31 | 32 | - (NSData *)SHA1; 33 | - (NSData *)SHA256; 34 | - (NSData *)SHA256_2; 35 | - (NSData *)SHA512; 36 | - (NSData *)SHA512HmacWithKey:(NSData *)key; 37 | - (NSData *)RMD160; 38 | - (NSData *)hash160; 39 | - (NSData *)reverse; 40 | 41 | @end 42 | -------------------------------------------------------------------------------- /Breadcrumb/Breadcrumb/Crumbs/NSData+Hash.m: -------------------------------------------------------------------------------- 1 | // 2 | // NSData+Hash.m 3 | // BreadWallet 4 | // 5 | // Created by Aaron Voisine on 5/13/13. 6 | // Copyright (c) 2013 Aaron Voisine 7 | // 8 | // Permission is hereby granted, free of charge, to any person obtaining a copy 9 | // of this software and associated documentation files (the "Software"), to 10 | // deal 11 | // in the Software without restriction, including without limitation the rights 12 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 13 | // copies of the Software, and to permit persons to whom the Software is 14 | // furnished to do so, subject to the following conditions: 15 | // 16 | // The above copyright notice and this permission notice shall be included in 17 | // all copies or substantial portions of the Software. 18 | // 19 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 20 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 21 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 22 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 23 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 24 | // FROM, 25 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 26 | // THE SOFTWARE. 27 | 28 | #import "NSData+Hash.h" 29 | #import 30 | #import 31 | #import "RIPEMD160.c" 32 | 33 | @implementation NSData (Hash) 34 | 35 | - (NSData *)SHA1 { 36 | NSMutableData *d = [NSMutableData dataWithLength:CC_SHA1_DIGEST_LENGTH]; 37 | 38 | CC_SHA1(self.bytes, (CC_LONG)self.length, d.mutableBytes); 39 | 40 | return d; 41 | } 42 | 43 | - (NSData *)SHA256 { 44 | NSMutableData *d = [NSMutableData dataWithLength:CC_SHA256_DIGEST_LENGTH]; 45 | 46 | CC_SHA256(self.bytes, (CC_LONG)self.length, d.mutableBytes); 47 | 48 | return d; 49 | } 50 | 51 | - (NSData *)SHA256_2 { 52 | NSMutableData *d = [NSMutableData dataWithLength:CC_SHA256_DIGEST_LENGTH]; 53 | 54 | CC_SHA256(self.bytes, (CC_LONG)self.length, d.mutableBytes); 55 | CC_SHA256(d.bytes, (CC_LONG)d.length, d.mutableBytes); 56 | 57 | return d; 58 | } 59 | 60 | - (NSData *)SHA512 { 61 | NSMutableData *d = [NSMutableData dataWithLength:CC_SHA512_DIGEST_LENGTH]; 62 | 63 | CC_SHA512(self.bytes, (CC_LONG)self.length, d.mutableBytes); 64 | 65 | return d; 66 | } 67 | 68 | - (NSData *)SHA512HmacWithKey:(NSData *)key { 69 | NSMutableData *d; 70 | NSParameterAssert([key isKindOfClass:[NSData class]]); 71 | if (![key isKindOfClass:[NSData class]]) return NULL; 72 | 73 | d = [NSMutableData dataWithLength:CC_SHA512_DIGEST_LENGTH]; 74 | CCHmac(kCCHmacAlgSHA512, key.bytes, key.length, self.bytes, 75 | (CC_LONG)self.length, d.mutableBytes); 76 | 77 | return [d isKindOfClass:[NSData class]] ? d : NULL; 78 | } 79 | 80 | - (NSData *)RMD160 { 81 | NSMutableData *d = [NSMutableData dataWithLength:RIPEMD160_DIGEST_SIZE]; 82 | ripemd160(self.bytes, self.length, d.mutableBytes); 83 | return d; 84 | } 85 | 86 | - (NSData *)hash160 { 87 | return self.SHA256.RMD160; 88 | } 89 | 90 | - (NSData *)reverse { 91 | NSUInteger l = self.length; 92 | NSMutableData *d = [NSMutableData dataWithLength:l]; 93 | uint8_t *b1 = d.mutableBytes; 94 | const uint8_t *b2 = self.bytes; 95 | 96 | for (NSUInteger i = 0; i < l; i++) { 97 | b1[i] = b2[l - i - 1]; 98 | } 99 | 100 | return d; 101 | } 102 | 103 | @end 104 | -------------------------------------------------------------------------------- /Breadcrumb/Breadcrumb/Crumbs/NSMutableData+Bitcoin.h: -------------------------------------------------------------------------------- 1 | // 2 | // NSMutableData+Bitcoin.h 3 | // BreadWallet 4 | // 5 | // Created by Aaron Voisine on 5/20/13. 6 | // Copyright (c) 2013 Aaron Voisine 7 | // 8 | // Permission is hereby granted, free of charge, to any person obtaining a copy 9 | // of this software and associated documentation files (the "Software"), to deal 10 | // in the Software without restriction, including without limitation the rights 11 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 12 | // copies of the Software, and to permit persons to whom the Software is 13 | // furnished to do so, subject to the following conditions: 14 | // 15 | // The above copyright notice and this permission notice shall be included in 16 | // all copies or substantial portions of the Software. 17 | // 18 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 23 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 24 | // THE SOFTWARE. 25 | 26 | #import 27 | 28 | #if BITCOIN_TESTNET 29 | #define BITCOIN_MAGIC_NUMBER 0x0709110b 30 | #else 31 | #define BITCOIN_MAGIC_NUMBER 0xd9b4bef9 32 | #endif 33 | 34 | CFAllocatorRef SecureAllocator(); 35 | 36 | @interface NSMutableData (Bitcoin) 37 | 38 | + (NSMutableData *)secureData; 39 | + (NSMutableData *)secureDataWithLength:(NSUInteger)length; 40 | + (NSMutableData *)secureDataWithCapacity:(NSUInteger)capacity; 41 | + (NSMutableData *)secureDataWithData:(NSData *)data; 42 | 43 | + (size_t)sizeOfVarInt:(uint64_t)i; 44 | 45 | - (void)appendUInt8:(uint8_t)i; 46 | - (void)appendUInt16:(uint16_t)i; 47 | - (void)appendUInt32:(uint32_t)i; 48 | - (void)appendUInt64:(uint64_t)i; 49 | - (void)appendVarInt:(uint64_t)i; 50 | - (void)appendString:(NSString *)s; 51 | 52 | - (void)appendScriptPubKeyForAddress:(NSString *)address; 53 | - (void)appendScriptPushData:(NSData *)d; 54 | 55 | - (void)appendMessage:(NSData *)message type:(NSString *)type; 56 | - (void)appendNullPaddedString:(NSString *)s length:(NSUInteger)length; 57 | - (void)appendNetAddress:(uint32_t)address port:(uint16_t)port services:(uint64_t)services; 58 | 59 | @end 60 | -------------------------------------------------------------------------------- /Breadcrumb/Breadcrumb/Crumbs/Reachability.h: -------------------------------------------------------------------------------- 1 | /* 2 | File: Reachability.h 3 | Abstract: Basic demonstration of how to use the SystemConfiguration Reachablity APIs. 4 | Version: 3.5 5 | 6 | Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple 7 | Inc. ("Apple") in consideration of your agreement to the following 8 | terms, and your use, installation, modification or redistribution of 9 | this Apple software constitutes acceptance of these terms. If you do 10 | not agree with these terms, please do not use, install, modify or 11 | redistribute this Apple software. 12 | 13 | In consideration of your agreement to abide by the following terms, and 14 | subject to these terms, Apple grants you a personal, non-exclusive 15 | license, under Apple's copyrights in this original Apple software (the 16 | "Apple Software"), to use, reproduce, modify and redistribute the Apple 17 | Software, with or without modifications, in source and/or binary forms; 18 | provided that if you redistribute the Apple Software in its entirety and 19 | without modifications, you must retain this notice and the following 20 | text and disclaimers in all such redistributions of the Apple Software. 21 | Neither the name, trademarks, service marks or logos of Apple Inc. may 22 | be used to endorse or promote products derived from the Apple Software 23 | without specific prior written permission from Apple. Except as 24 | expressly stated in this notice, no other rights or licenses, express or 25 | implied, are granted by Apple herein, including but not limited to any 26 | patent rights that may be infringed by your derivative works or by other 27 | works in which the Apple Software may be incorporated. 28 | 29 | The Apple Software is provided by Apple on an "AS IS" basis. APPLE 30 | MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION 31 | THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS 32 | FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND 33 | OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS. 34 | 35 | IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL 36 | OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 37 | SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 38 | INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION, 39 | MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED 40 | AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE), 41 | STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE 42 | POSSIBILITY OF SUCH DAMAGE. 43 | 44 | Copyright (C) 2014 Apple Inc. All Rights Reserved. 45 | 46 | */ 47 | 48 | #import 49 | #import 50 | #import 51 | 52 | 53 | typedef enum : NSInteger { 54 | NotReachable = 0, 55 | ReachableViaWiFi, 56 | ReachableViaWWAN 57 | } NetworkStatus; 58 | 59 | 60 | extern NSString *kReachabilityChangedNotification; 61 | 62 | 63 | @interface Reachability : NSObject 64 | 65 | /*! 66 | * Use to check the reachability of a given host name. 67 | */ 68 | + (instancetype)reachabilityWithHostName:(NSString *)hostName; 69 | 70 | /*! 71 | * Use to check the reachability of a given IP address. 72 | */ 73 | + (instancetype)reachabilityWithAddress:(const struct sockaddr_in *)hostAddress; 74 | 75 | /*! 76 | * Checks whether the default route is available. Should be used by applications that do not connect to a particular host. 77 | */ 78 | + (instancetype)reachabilityForInternetConnection; 79 | 80 | /*! 81 | * Checks whether a local WiFi connection is available. 82 | */ 83 | + (instancetype)reachabilityForLocalWiFi; 84 | 85 | /*! 86 | * Start listening for reachability notifications on the current run loop. 87 | */ 88 | - (BOOL)startNotifier; 89 | - (void)stopNotifier; 90 | 91 | - (NetworkStatus)currentReachabilityStatus; 92 | 93 | /*! 94 | * WWAN may be available, but not active until a connection has been established. WiFi may require a connection for VPN on Demand. 95 | */ 96 | - (BOOL)connectionRequired; 97 | 98 | @end 99 | 100 | 101 | -------------------------------------------------------------------------------- /Breadcrumb/Breadcrumb/Crumbs/ccMemory.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2010 Apple Inc. All Rights Reserved. 3 | * 4 | * @APPLE_LICENSE_HEADER_START@ 5 | * 6 | * This file contains Original Code and/or Modifications of Original Code 7 | * as defined in and that are subject to the Apple Public Source License 8 | * Version 2.0 (the 'License'). You may not use this file except in 9 | * compliance with the License. Please obtain a copy of the License at 10 | * http://www.opensource.apple.com/apsl/ and read it before using this 11 | * file. 12 | * 13 | * The Original Code and all software distributed under the License are 14 | * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER 15 | * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, 16 | * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, 17 | * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. 18 | * Please see the License for the specific language governing rights and 19 | * limitations under the License. 20 | * 21 | * @APPLE_LICENSE_HEADER_END@ 22 | */ 23 | 24 | /* 25 | * ccMemory.h 26 | * CommonCrypto 27 | */ 28 | 29 | #ifndef CCMEMORY_H 30 | #define CCMEMORY_H 31 | 32 | #ifdef KERNEL 33 | #define CC_XMALLOC(s) OSMalloc((s), CC_OSMallocTag) 34 | #define CC_XFREE(p, s) OSFree((p), (s), CC_OSMallocTag) 35 | #else /* KERNEL */ 36 | #include 37 | #include 38 | 39 | #define CC_XMALLOC(s) malloc(s) 40 | #define CC_XCALLOC(c, s) calloc((c), (s)) 41 | #define CC_XREALLOC(p, s) realloc((p), (s)) 42 | #define CC_XFREE(p, s) free(p) 43 | #define CC_XMEMCPY(s1, s2, n) memcpy((s1), (s2), (n)) 44 | #define CC_XMEMCMP(s1, s2, n) memcmp((s1), (s2), (n)) 45 | #define CC_XMEMSET(s1, s2, n) memset((s1), (s2), (n)) 46 | #define CC_XZEROMEM(p, n) memset((p), 0, (n)) 47 | #define CC_XSTRCMP(s1, s2) strcmp((s1), (s2)) 48 | #define CC_XSTORE32H(x, y) do { \ 49 | (y)[0] = (unsigned char)(((x)>>24)&255); \ 50 | (y)[1] = (unsigned char)(((x)>>16)&255); \ 51 | (y)[2] = (unsigned char)(((x)>>8)&255); \ 52 | (y)[3] = (unsigned char)((x)&255); \ 53 | } while(0) 54 | #define CC_XSTORE64H(x, y) \ 55 | { (y)[0] = (unsigned char)(((x)>>56)&255); (y)[1] = (unsigned char)(((x)>>48)&255); \ 56 | (y)[2] = (unsigned char)(((x)>>40)&255); (y)[3] = (unsigned char)(((x)>>32)&255); \ 57 | (y)[4] = (unsigned char)(((x)>>24)&255); (y)[5] = (unsigned char)(((x)>>16)&255); \ 58 | (y)[6] = (unsigned char)(((x)>>8)&255); (y)[7] = (unsigned char)((x)&255); } 59 | 60 | 61 | 62 | #define CC_XQSORT(base, nelement, width, comparfunc) qsort((base), (nelement), (width), (comparfunc)) 63 | 64 | #define CC_XALIGNED(PTR,NBYTE) (!(((size_t)(PTR))%(NBYTE))) 65 | 66 | #define CC_XMIN(X,Y) (((X) < (Y)) ? (X): (Y)) 67 | #endif 68 | 69 | 70 | 71 | 72 | #endif /* CCMEMORY_H */ 73 | -------------------------------------------------------------------------------- /Breadcrumb/Breadcrumb/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | BC.$(PRODUCT_NAME:rfc1034identifier) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | FMWK 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | $(CURRENT_PROJECT_VERSION) 23 | NSPrincipalClass 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /Breadcrumb/Breadcrumb/Keys/BCKeyPair.h: -------------------------------------------------------------------------------- 1 | // 2 | // BCKeyPair.h 3 | // Breadcrumb 4 | // 5 | // Created by Andrew Hurst on 2/10/15. 6 | // Copyright (c) 2015 Breadcrumb. 7 | // 8 | // Distributed under the MIT software license, see the accompanying 9 | // file LICENSE or http://www.opensource.org/licenses/mit-license.php. 10 | // 11 | 12 | #import 13 | #import "BCPublicKey.h" 14 | 15 | @interface BCKeyPair : NSObject 16 | #pragma mark Construction 17 | /*! 18 | @brief Constructs a key pair with the inputted keys. 19 | 20 | @param privateKey The private key for the key pair. 21 | @param memoryKey The key to encrypt the private key with while it is in 22 | memory. 23 | */ 24 | - (instancetype)initWithPrivateKey:(NSData *)privateKey 25 | chainCode:(NSData *)chainCode 26 | andMemoryKey:(NSData *)memoryKey; 27 | 28 | - (instancetype)initWithWIF:(NSString *)wifString 29 | andMemoryKey:(NSData *)memoryKey; 30 | #pragma mark Public Info 31 | /*! 32 | @brief The public key of the key pair. 33 | */ 34 | @property(strong, nonatomic, readonly) BCPublicKey *publicKey; 35 | 36 | /*! 37 | @brief This is an initialization vector for child keys. 38 | 39 | @discussion This can be used for hardened public key generation, you should 40 | limit outside exposure to this data as much as possible. 41 | */ 42 | @property(strong, nonatomic, readonly) NSData *chainCode; 43 | 44 | @property(assign, nonatomic, readonly) BOOL isCompressed; 45 | 46 | #pragma mark Private Info 47 | /*! 48 | @brief Decrypts, and retrieves the private key from memory. 49 | 50 | @param memoryKey The key used to encrypt the private key in memory. 51 | 52 | @return The clear text private key, or NULL if the operation failed. 53 | */ 54 | - (NSData *)privateKeyUsingMemoryKey:(NSData *)memoryKey; 55 | 56 | #pragma mark Child Retrieval 57 | /*! 58 | @brief Gets the internal key pair for the specified index of the key sequence. 59 | 60 | @discussion The internal address is used for change addresses. 61 | 62 | @param index The index of the internal key pair to retrieve. 63 | 64 | @return The internal key pair for the specified index, or NULL if invalid. 65 | */ 66 | - (instancetype)childKeyPairAt:(uint32_t)index withMemoryKey:(NSData *)memoryKe; 67 | 68 | #pragma mark Singing Operations 69 | /*! 70 | @brief Signs the inputed data with the key pairs private key. 71 | 72 | @param data The data to sign. 73 | @param memoryKey The key used to encrypt the private key in memory. 74 | 75 | @return The signed data or NULL if invalid. 76 | */ 77 | - (NSData *)signHash:(NSData *)hash withMemoryKey:(NSData *)memoryKey; 78 | 79 | /*! 80 | @brief Verifies that the signed data was signed by the key pairs public key. 81 | 82 | @param signedData The signed data to check. 83 | @param hash The data before it was signed. 84 | 85 | @return True if the data has been signed by the key pairs public key. 86 | */ 87 | - (BOOL)didSign:(NSData *)signedData withOriginalHash:(NSData *)hash; 88 | 89 | #pragma mark Utilities 90 | 91 | /*! 92 | @brief Serialized the inputted array as a key sequence with the assumed master 93 | prepended. 94 | 95 | @param sequence The sequence to serialized into a string. 96 | */ 97 | + (NSString *)serializeSequence:(NSArray *)sequence; 98 | 99 | @end -------------------------------------------------------------------------------- /Breadcrumb/Breadcrumb/Keys/BCKeySequence.h: -------------------------------------------------------------------------------- 1 | // 2 | // BCKeySequence.h 3 | // Breadcrumb 4 | // 5 | // Created by Andrew Hurst on 2/10/15. 6 | // Copyright (c) 2015 Breadcrumb. 7 | // 8 | // Distributed under the MIT software license, see the accompanying 9 | // file LICENSE or http://www.opensource.org/licenses/mit-license.php. 10 | // 11 | // 12 | // Explanation: 13 | // m = Master key that is derived from the root/seed 14 | // # = is the index of the key 15 | // #' = the index of the hardened key aka 0x80000000 | # 16 | // The / is equivalent to derived from 17 | // 18 | // Example 1) 19 | // Sequence: m/0'/0/0/0' 20 | // Meaning: [[[master childAt: 0x80000000 | 0] 21 | // childAt: 0] 22 | // childAt: 0] 23 | // childAt: 0x80000000 | 0]; 24 | // 25 | // 0x80000000 is the hardened index. 26 | 27 | #import "BCKeyPair.h" 28 | #import "BCProtectedData.h" 29 | 30 | // All Keys derived past this index are considered to be hardened. 31 | #define BIP32_PRIME 0x80000000 32 | 33 | // Valid Chars for path 34 | static NSString *const kBCKeySequenceValidChars = @"m/'h1234567890"; 35 | static NSString *const kBCKeySequenceMasterChar = @"m"; 36 | static NSString *const kBCKeySequenceDelimiterChar = @"/"; 37 | static NSString *const kBCKeySequenceNumericalChars = @"1234567890"; 38 | static NSString *const kBCKeySequenceHardenedFlagChars = @"'h"; 39 | 40 | /*! 41 | @brief Defines how a key hierarchy is structured. 42 | */ 43 | typedef enum 44 | : NSUInteger { 45 | /*! 46 | @brief The BIP32 standard. Example: m/0'/0/0 47 | 48 | @discussion you should try to migrate away from this, and use a newer 49 | standard. 50 | 51 | Description: m/account'/isExternal/index 52 | */ 53 | BCKeySequenceType_BIP32 = 0, 54 | /*! 55 | @brief The BIP44 path standard. Example: m/44'/0'/0'/0/0 56 | 57 | @discussion This is an extension of BIP32 with better definition on how 58 | paths should work, you should use this instead of BIP32. 59 | 60 | Description: m/44'/coin'/account'/isExternal/index 61 | */ 62 | BCKeySequenceType_BIP44 = 1, 63 | } BCKeySequenceType; 64 | 65 | /*! 66 | @brief This keeps track of the wallets seed, and master public, and private 67 | key pairs. 68 | */ 69 | @interface BCKeySequence : NSObject 70 | #pragma mark Construction 71 | /*! 72 | @brief Constructs the key sequence using the provided seed, and memory key. 73 | 74 | @param rootSeed The root seed to derive child keys from. 75 | @param memoryKey The memory key used to secure root seed, and its children. 76 | */ 77 | - (instancetype)initWithRootSeed:(NSData *)rootSeed 78 | andMemoryKey:(NSData *)memoryKey; 79 | 80 | #pragma mark Keys 81 | /*! 82 | @brief The root seed of the wallet. 83 | */ 84 | @property(strong, nonatomic, readonly) BCProtectedData *rootSeed; 85 | 86 | /*! 87 | @brief The master key pair derived from the seed. 88 | 89 | @discussion This is the key sequence used to derive child keys. 90 | */ 91 | @property(strong, nonatomic, readonly) BCKeyPair *masterKeyPair; 92 | 93 | #pragma mark Child Retrieval 94 | 95 | /*! 96 | @brief Gets the key pair with the array of indexes. 97 | 98 | @param components The array of indexes to get the key pair for. 99 | @param memoryKey The memory key to use in protecting the key pairs private 100 | key. 101 | */ 102 | - (BCKeyPair *)keyPairForComponents:(NSArray *)components 103 | andMemoryKey:(NSData *)memoryKey; 104 | 105 | /*! 106 | @brief Gets the key pair at the specified bip32 path 107 | 108 | @param path The bip32 path to get the key pair for. 109 | @param memoryKey The memory key to protect the key pairs private key. 110 | */ 111 | - (BCKeyPair *)keyPairForPath:(NSString *)path andMemoryKey:(NSData *)memoryKey; 112 | 113 | #pragma mark Utilities 114 | /*! 115 | @brief Extracts the components from inputted key path, as defined in BIP 32. 116 | 117 | @param The array of components needed to derive the specified key from a master 118 | key pair. 119 | */ 120 | + (NSArray *)componentsFromPath:(NSString *)path; 121 | 122 | @end 123 | -------------------------------------------------------------------------------- /Breadcrumb/Breadcrumb/Keys/BCPublicKey.h: -------------------------------------------------------------------------------- 1 | // 2 | // BCPublicKey.h 3 | // Breadcrumb 4 | // 5 | // Created by Andrew Hurst on 2/20/15. 6 | // Copyright (c) 2015 Breadcrumb. 7 | // 8 | // Distributed under the MIT software license, see the accompanying 9 | // file LICENSE or http://www.opensource.org/licenses/mit-license.php. 10 | // 11 | // 12 | 13 | #import 14 | #import "BCAddress.h" 15 | #import "BCCoin.h" 16 | 17 | @interface BCPublicKey : NSObject 18 | #pragma mark Construction 19 | /*! 20 | @brief Constructs the public key with the inputted key. 21 | 22 | @param data The data of the key to use as the public key. 23 | */ 24 | - (instancetype)initWithData:(NSData *)data; 25 | 26 | #pragma mark Configuration 27 | /*! 28 | @brief The public keys data. 29 | */ 30 | @property(strong, nonatomic, readonly) NSData *data; 31 | 32 | /*! 33 | @brief The public keys address. 34 | */ 35 | - (BCAddress *)addressForCoin:(BCCoin *)coin; 36 | 37 | #pragma mark Comparison 38 | 39 | - (BOOL)isEqualToData:(NSData *)data; 40 | @end 41 | 42 | /*! 43 | @brief This a public key which can derive non-hardened child public keys. 44 | */ 45 | @interface BCDerivablePublicKey : BCPublicKey 46 | #pragma mark Construction 47 | /*! 48 | @brief Constructs the public key with the inputted key. 49 | 50 | @param data The data of the key to use as the public key. 51 | */ 52 | - (instancetype)initWithData:(NSData *)data andChainCode:(NSData *)chainCode; 53 | 54 | #pragma mark Configuration 55 | /*! 56 | @brief The chain code to use when deriving child keys. 57 | */ 58 | @property(strong, nonatomic, readonly) NSData *chainCode; 59 | 60 | #pragma mark Derivation 61 | /*! 62 | @brief Gets the child public key at the specified index. 63 | 64 | @param index The index of the child key to get. 65 | 66 | @return The resulting public key. 67 | */ 68 | - (BCPublicKey *)childKeyAtIndex:(uint32_t)index; 69 | 70 | @end 71 | -------------------------------------------------------------------------------- /Breadcrumb/Breadcrumb/Keys/BCPublicKey.m: -------------------------------------------------------------------------------- 1 | // 2 | // BCPublicKey.m 3 | // Breadcrumb 4 | // 5 | // Created by Andrew Hurst on 2/20/15. 6 | // Copyright (c) 2015 Breadcrumb. 7 | // 8 | // Distributed under the MIT software license, see the accompanying 9 | // file LICENSE or http://www.opensource.org/licenses/mit-license.php. 10 | // 11 | // 12 | 13 | #import "BCPublicKey.h" 14 | #import "BCKeySequence.h" 15 | #import "BCsecp256k1.h" 16 | #import "BreadcrumbCore.h" 17 | 18 | @implementation BCPublicKey 19 | 20 | @synthesize data = _data; 21 | 22 | #pragma mark Construction 23 | 24 | - (instancetype)initWithData:(NSData *)data { 25 | NSParameterAssert([data isKindOfClass:[NSData class]]); 26 | if (![data isKindOfClass:[NSData class]]) return NULL; 27 | 28 | self = [super init]; 29 | if (!self) return NULL; 30 | _data = data; 31 | 32 | return self; 33 | } 34 | 35 | #pragma mark Info 36 | 37 | - (BCAddress *)addressForCoin:(BCCoin *)coin { 38 | return [BCAddress addressFromPublicKey:_data usingCoin:coin]; 39 | } 40 | 41 | #pragma mark Comparison 42 | - (BOOL)isEqualToData:(NSData *)data { 43 | return [self.data isEqualToData:data]; 44 | } 45 | 46 | @end 47 | 48 | @implementation BCDerivablePublicKey 49 | 50 | @synthesize chainCode = _chainCode; 51 | 52 | #pragma mark Construction 53 | 54 | - (instancetype)initWithData:(NSData *)data { 55 | NSAssert(false, @"Not implemented, use - " 56 | @"(instancetype)initWithData:andChainCode: instead."); 57 | return NULL; 58 | } 59 | 60 | - (instancetype)initWithData:(NSData *)data andChainCode:(NSData *)chainCode { 61 | NSParameterAssert([chainCode isKindOfClass:[NSData class]]); 62 | self = [super initWithData:data]; 63 | if (!self) return NULL; 64 | _chainCode = chainCode; 65 | return self; 66 | } 67 | 68 | #pragma mark Derivation 69 | 70 | // The function CKDpub((Kpar, cpar), i) → (Ki, ci) computes a child extended 71 | // public key from the parent extended public key. It is only defined for 72 | // non-hardened child keys. 73 | - (BCPublicKey *)childKeyAtIndex:(uint32_t)index { 74 | // TODO: EC get the child code from the current public key. 75 | // TODO: add tests in HD. 76 | NSMutableData *dataToDerive; 77 | NSData *childChain, *opData; 78 | 79 | // Check For Hardened key 80 | if (index >= BIP32_PRIME) return NULL; 81 | 82 | // Setup the data to derive 83 | dataToDerive = [[NSMutableData alloc] init]; 84 | if (![dataToDerive isKindOfClass:[NSMutableData class]]) return NULL; 85 | 86 | // dataToDerive = serP(Kpar) || ser32(i); 87 | [dataToDerive appendData:self.data]; 88 | [dataToDerive appendUInt32:CFSwapInt32(index)]; 89 | 90 | // HMAC-SHA512(key = chainCode, data = dataToDerive); 91 | opData = [dataToDerive SHA512HmacWithKey:self.chainCode]; 92 | if (![opData isKindOfClass:[NSData class]] || opData.length != 64) 93 | return NULL; 94 | 95 | // parse256() 96 | childChain = [opData subdataWithRange:NSMakeRange(32, 32)]; 97 | opData = [opData subdataWithRange:NSMakeRange(0, 32)]; 98 | 99 | // childPublic = point(opData) + self.data. 100 | opData = [[BCsecp256k1 sharedInstance] publicKey:self.data add:opData]; 101 | 102 | // In case parse256(IL) ≥ n or Ki is the point at infinity 103 | if (false) 104 | // key invalid, and one should proceed with the next value for i. 105 | return [self childKeyAtIndex:index + 1]; 106 | 107 | // return opData; 108 | return [[BCPublicKey alloc] initWithData:opData]; 109 | } 110 | 111 | @end 112 | -------------------------------------------------------------------------------- /Breadcrumb/Breadcrumb/Mnemonic/BCMnemonic.h: -------------------------------------------------------------------------------- 1 | // 2 | // BCMnemonic.h 3 | // Breadcrumb 4 | // 5 | // Created by Andrew Hurst on 2/5/15. 6 | // Copyright (c) 2015 Breadcrumb. 7 | // 8 | // Distributed under the MIT software license, see the accompanying 9 | // file LICENSE or http://www.opensource.org/licenses/mit-license.php. 10 | // 11 | // 12 | // This really should be an object, I will change this later. 13 | 14 | #import 15 | 16 | typedef enum : NSUInteger { 17 | BCMnemonicLang_English, 18 | BCMnemonicLang_Japanese, 19 | } BCMnemonicLang; 20 | 21 | /*! 22 | @brief Utility class for mnemonic BIP39 generation, processing, and conversion. 23 | 24 | @discussion https://github.com/bitcoin/bips/blob/master/bip-0039.mediawiki 25 | */ 26 | @interface BCMnemonic : NSObject 27 | #pragma mark Generation 28 | /*! 29 | @brief Generates a BIP39 compliant mnemonic using data from a 30 | cryptographic random number generator. 31 | 32 | @return The resulting random mnemonic. 33 | */ 34 | + (NSString *)newMnemonic; 35 | 36 | /*! 37 | @brief Generates a BIP39 compliant mnemonic from the inputted data. 38 | 39 | @param data The data to construct the mnemonic from. 40 | 41 | @discussion The seed data should be random, using a cryptographic random number 42 | generator. 43 | 44 | @return The resulting mnemonic. 45 | */ 46 | + (NSString *)mnemonicFromEntropy:(NSData *)data; 47 | 48 | #pragma mark Processing 49 | /*! 50 | @brief Sanitizes the inputed mnemonic phrase. 51 | 52 | @param phrase The phrase to sanitize 53 | 54 | @return The sanitized phrase, or NULL if the inputted phrase was invalid. 55 | */ 56 | + (NSString *)sanitizePhrase:(NSString *)phrase; 57 | 58 | /*! 59 | @brief Decodes the inputted mnemonic phrase into data. 60 | 61 | @param phrase The mnemonic phrase to decode into data. 62 | 63 | @return the decoded value, or NULL if the inputted value is invalid. 64 | */ 65 | + (NSData *)decodePhrase:(NSString *)phrase; 66 | 67 | /*! 68 | @brief Encodes the inputed data into a mnemonic phrase. 69 | 70 | @param phraseData The data to encode into a phrase, MUST be a multiple of 32 71 | bits. 72 | 73 | @return The resulting mnemonic phrase, or NULL if the process failed. 74 | */ 75 | + (NSString *)encodeData:(NSData *)phraseData; 76 | 77 | #pragma mark Conversion 78 | 79 | /*! 80 | @brief Derives a seed key from the inputted phrase, and passphrase. 81 | 82 | @param phrase The BIP39 compliant phrase. 83 | @param passphrase The passphrase for the sequence (SALT). 84 | 85 | @return The seed key to use. 86 | */ 87 | + (NSData *)keyFromPhrase:(NSString *)phrase 88 | withPassphrase:(NSString *)passphrase; 89 | 90 | + (BOOL)wordIsValid:(NSString *)word; 91 | 92 | + (NSArray *)wordListForLanguage:(BCMnemonicLang)lang; 93 | 94 | @end 95 | -------------------------------------------------------------------------------- /Breadcrumb/Breadcrumb/Mnemonic/BCMnemonic.m: -------------------------------------------------------------------------------- 1 | // 2 | // BCMnemonic.m 3 | // Breadcrumb 4 | // 5 | // Created by Andrew Hurst on 2/5/15. 6 | // Copyright (c) 2015 Breadcrumb. 7 | // 8 | // Distributed under the MIT software license, see the accompanying 9 | // file LICENSE or http://www.opensource.org/licenses/mit-license.php. 10 | // 11 | // 12 | 13 | #import "BCMnemonic.h" 14 | #import "BreadcrumbCore.h" 15 | 16 | #define SEED_ENTROPY_LENGTH (128 / 8) 17 | 18 | @implementation BCMnemonic 19 | #pragma mark Generation 20 | 21 | // TODO: Allow For configuration of entropy length 22 | + (NSString *)newMnemonic { 23 | // Auto release pool ensures data is deallocated immediately 24 | @autoreleasepool { 25 | NSString *phrase; 26 | NSMutableData *entropy; 27 | 28 | entropy = [NSMutableData secureDataWithLength:SEED_ENTROPY_LENGTH]; 29 | SecRandomCopyBytes(kSecRandomDefault, entropy.length, entropy.mutableBytes); 30 | if (![entropy isKindOfClass:[NSData class]]) { 31 | NSAssert(FALSE, @"Failed to generate entropy."); 32 | return NULL; 33 | } 34 | 35 | phrase = [self mnemonicFromEntropy:entropy]; 36 | return [phrase isKindOfClass:[NSString class]] ? phrase : NULL; 37 | } 38 | } 39 | 40 | + (NSString *)mnemonicFromEntropy:(NSData *)data { 41 | // Auto release pool ensures data is deallocated immediately 42 | @autoreleasepool { 43 | NSParameterAssert([data isKindOfClass:[NSData class]]); 44 | if (![data isKindOfClass:[NSData class]]) return NULL; 45 | return [[BRBIP39Mnemonic sharedInstance] encodePhrase:data]; 46 | } 47 | } 48 | 49 | #pragma mark Processing 50 | 51 | + (NSString *)sanitizePhrase:(NSString *)phrase { 52 | // Auto release pool ensures data is deallocated immediately 53 | @autoreleasepool { 54 | NSString *sanitizedPhrase; 55 | NSParameterAssert([phrase isKindOfClass:[NSString class]]); 56 | if (![phrase isKindOfClass:[NSString class]]) return NULL; 57 | 58 | BRBIP39Mnemonic *m = [BRBIP39Mnemonic sharedInstance]; 59 | if (![m isKindOfClass:[BRBIP39Mnemonic class]]) return NULL; 60 | 61 | sanitizedPhrase = [m encodePhrase:[m decodePhrase:phrase]]; 62 | return [sanitizedPhrase isKindOfClass:[NSString class]] ? sanitizedPhrase 63 | : NULL; 64 | } 65 | } 66 | 67 | + (NSData *)decodePhrase:(NSString *)phrase { 68 | // Auto release pool ensures data is deallocated immediately 69 | @autoreleasepool { 70 | NSData *decodedValue; 71 | NSParameterAssert([phrase isKindOfClass:[NSString class]]); 72 | if ([phrase isKindOfClass:[NSString class]]) return NULL; 73 | 74 | decodedValue = [[BRBIP39Mnemonic sharedInstance] decodePhrase:phrase]; 75 | return [decodedValue isKindOfClass:[NSData class]] ? decodedValue : NULL; 76 | } 77 | } 78 | 79 | + (NSString *)encodeData:(NSData *)phraseData { 80 | // Auto release pool ensures data is deallocated immediately 81 | @autoreleasepool { 82 | NSString *encodedValue; 83 | NSParameterAssert([phraseData isKindOfClass:[NSData class]]); 84 | if ([phraseData isKindOfClass:[NSString class]]) return NULL; 85 | 86 | encodedValue = [[BRBIP39Mnemonic sharedInstance] encodePhrase:phraseData]; 87 | return [encodedValue isKindOfClass:[NSString class]] ? encodedValue : NULL; 88 | } 89 | } 90 | 91 | #pragma mark Conversion 92 | 93 | + (NSData *)keyFromPhrase:(NSString *)phrase 94 | withPassphrase:(NSString *)passphrase { 95 | @autoreleasepool { 96 | return [[BRBIP39Mnemonic sharedInstance] deriveKeyFromPhrase:phrase 97 | withPassphrase:passphrase]; 98 | } 99 | } 100 | 101 | + (BOOL)wordIsValid:(NSString *)word { 102 | NSString *currentWord; 103 | NSArray *words = [self wordListForLanguage:BCMnemonicLang_English]; 104 | if (![words isKindOfClass:[NSArray class]]) { 105 | NSLog(@"Missing BIP 39 words file."); 106 | return FALSE; 107 | } 108 | 109 | for (NSUInteger i = 0; i < words.count; ++i) { 110 | currentWord = [words objectAtIndex:i]; 111 | if ([currentWord isKindOfClass:[NSString class]]) 112 | if ([currentWord isEqualToString:word]) return TRUE; 113 | } 114 | 115 | return FALSE; 116 | } 117 | 118 | + (NSArray *)wordListForLanguage:(BCMnemonicLang)lang { 119 | return [NSArray arrayWithContentsOfFile:[[BRBIP39Mnemonic bundle] 120 | pathForResource:WORDS 121 | ofType:@"plist"]]; 122 | } 123 | 124 | @end 125 | -------------------------------------------------------------------------------- /Breadcrumb/Breadcrumb/Providers/BCProviderChain.h: -------------------------------------------------------------------------------- 1 | // 2 | // BCProviderChain.h 3 | // Breadcrumb 4 | // 5 | // Created by Andrew Hurst on 2/6/15. 6 | // Copyright (c) 2015 Breadcrumb. 7 | // 8 | // Distributed under the MIT software license, see the accompanying 9 | // file LICENSE or http://www.opensource.org/licenses/mit-license.php. 10 | // 11 | // 12 | 13 | #import "BCAProvider.h" 14 | 15 | /*! 16 | @brief A sample provider using the Chain API with a local cache, that publishes 17 | transactions to the bitcoin network. 18 | */ 19 | @interface BCProviderChain : BCAProvider 20 | 21 | @end 22 | 23 | @interface BCTransaction (BCProviderChain) 24 | /*! 25 | @brief Instantiates the transaction from transaction data formatted in a Chain 26 | response. 27 | 28 | @param chainTransaction The chain response to build the transaction with. 29 | */ 30 | + (instancetype)transactionFromChainTransaction: 31 | (NSDictionary *)chainTransaction; 32 | @end 33 | -------------------------------------------------------------------------------- /Breadcrumb/Breadcrumb/Script/BCScript+DefaultScripts.h: -------------------------------------------------------------------------------- 1 | // 2 | // BCScript+DefaultScripts.h 3 | // Breadcrumb 4 | // 5 | // Created by Andrew Hurst on 2/8/15. 6 | // Copyright (c) 2015 Breadcrumb. 7 | // 8 | // Distributed under the MIT software license, see the accompanying 9 | // file LICENSE or http://www.opensource.org/licenses/mit-license.php. 10 | // 11 | // 12 | 13 | #import "BCScript.h" 14 | #import "BCAddress.h" 15 | 16 | @interface BCScript (DefaultScripts) 17 | 18 | #pragma mark Transactions 19 | /*! 20 | @brief Creates a standard transaction script using the inputted address. 21 | 22 | @param address The output address for the transaction. 23 | */ 24 | //+ (instancetype)standardTransactionScript:(BCAddress *)address; 25 | 26 | /*! 27 | @brief Creates a standard transaction script using the inputted address. 28 | 29 | @param address The output address for the transaction. 30 | @param coin The coin which the transaction should be generated for. 31 | */ 32 | + (instancetype)standardTransactionScript:(BCAddress *)address 33 | andCoin:(BCCoin *)coin; 34 | 35 | /*! 36 | @brief Creates a multi-signiture reedem script for the provided inputs 37 | 38 | @param pubkeys The public keys in order of signing. 39 | @param minSignitures The mimumum number of signitures. 40 | 41 | @return The mulit-signiture reedeem script. 42 | */ 43 | + (instancetype)multisigScriptWithPubkeys:(NSArray *)pubkeys 44 | andMinumumSignitures:(uint8_t)minSignitures; 45 | 46 | #pragma mark Messages 47 | /*! 48 | @brief Creates an op return script with the specified data. 49 | 50 | @param data The data to put in the op return script. 51 | */ 52 | + (instancetype)opReturnScriptWithData:(NSData *)data; 53 | 54 | @end 55 | -------------------------------------------------------------------------------- /Breadcrumb/Breadcrumb/Script/BCScript+DefaultScripts.m: -------------------------------------------------------------------------------- 1 | // 2 | // BCScript+DefaultScripts.m 3 | // Breadcrumb 4 | // 5 | // Created by Andrew Hurst on 2/8/15. 6 | // Copyright (c) 2015 Breadcrumb. 7 | // 8 | // Distributed under the MIT software license, see the accompanying 9 | // file LICENSE or http://www.opensource.org/licenses/mit-license.php. 10 | // 11 | // 12 | 13 | #import "BCScript+DefaultScripts.h" 14 | #import "BCPublicKey.h" 15 | 16 | @implementation BCScript (DefaultScripts) 17 | 18 | + (instancetype)standardTransactionScript:(BCAddress *)address { 19 | return [self standardTransactionScript:address andCoin:[BCCoin MainNetBitcoin]]; 20 | } 21 | 22 | + (instancetype)standardTransactionScript:(BCAddress *)address andCoin:(BCCoin *)coin { 23 | BCMutableScript *script; 24 | NSParameterAssert([address isKindOfClass:[BCAddress class]]); 25 | if (![address isKindOfClass:[BCAddress class]]) return NULL; 26 | 27 | script = [BCMutableScript script]; 28 | if (![script isKindOfClass:[BCMutableScript class]]) return NULL; 29 | 30 | // Check if it is a P2SH address 31 | if (address.typeCode == coin.P2SHCode) { 32 | [script writeOpCode:OP_HASH160]; 33 | [script writeBytes:[address toDataWithoutType]]; 34 | [script writeOpCode:OP_EQUAL]; 35 | 36 | } else { 37 | // Write the script 38 | [script writeOpCode:OP_DUP]; 39 | [script writeOpCode:OP_HASH160]; 40 | 41 | // The type is redundant 42 | [script writeBytes:[address toDataWithoutType]]; 43 | 44 | [script writeOpCode:OP_EQUALVERIFY]; 45 | [script writeOpCode:OP_CHECKSIG]; 46 | } 47 | // Return the script, Note we don't need to convert to an immutable instance 48 | // because mutable methods are technically available on BCScript but 49 | // inaccessible unless you manually call it via -()performSelector:(SEL); 50 | return [script isKindOfClass:[BCScript class]] 51 | ? [BCScript scriptWithData:[script toData]] 52 | : NULL; 53 | } 54 | 55 | + (instancetype)multisigScriptWithPubkeys:(NSArray *)pubkeys 56 | andMinumumSignitures:(uint8_t)minSignitures { 57 | BCMutableScript *script; 58 | BCScriptOpCode minSigs, totalSigs; 59 | NSParameterAssert([pubkeys isKindOfClass:[NSArray class]]); 60 | if (![pubkeys isKindOfClass:[NSArray class]]) return NULL; 61 | 62 | // Get Min sigs count 63 | minSigs = OP_(minSignitures); 64 | if (minSigs == OP_NOP1) return NULL; // Out of range 65 | 66 | // Get Total Sigs Count 67 | totalSigs = OP_((uint16_t)pubkeys.count); 68 | if (totalSigs == OP_NOP1 || totalSigs == OP_0) return NULL; // Out of range 69 | 70 | // Write Script 71 | script = [[BCMutableScript alloc] init]; 72 | 73 | [script writeOpCode:minSigs]; 74 | for (BCPublicKey *pubKey in pubkeys) [script writeBytes:pubKey.data]; 75 | [script writeOpCode:totalSigs]; 76 | [script writeOpCode:OP_CHECKMULTISIG]; 77 | 78 | return [script isKindOfClass:[BCScript class]] ? script : NULL; 79 | } 80 | 81 | + (instancetype)opReturnScriptWithData:(NSData *)data { 82 | BCMutableScript *script; 83 | NSParameterAssert([data isKindOfClass:[NSData class]] && data.length < 40); 84 | if (![data isKindOfClass:[NSData class]] || data.length > 40) return NULL; 85 | script = [[BCMutableScript alloc] init]; 86 | 87 | [script writeOpCode:OP_RETURN]; 88 | [script writeBytes:data]; 89 | 90 | return [script isKindOfClass:[BCScript class]] ? script : NULL; 91 | } 92 | 93 | @end 94 | -------------------------------------------------------------------------------- /Breadcrumb/Breadcrumb/Script/BCScript.h: -------------------------------------------------------------------------------- 1 | // 2 | // BCScript.h 3 | // Breadcrumb 4 | // 5 | // Created by Andrew Hurst on 2/8/15. 6 | // Copyright (c) 2015 Breadcrumb. 7 | // 8 | // Distributed under the MIT software license, see the accompanying 9 | // file LICENSE or http://www.opensource.org/licenses/mit-license.php. 10 | // 11 | 12 | #import 13 | #import "BCScriptOpCodes.h" 14 | #import "BCAddress.h" 15 | 16 | /*! 17 | @brief Script types 18 | */ 19 | typedef enum : NSUInteger { 20 | /*! 21 | @brief Pay to public key hash (bitcoin address). 22 | 23 | @discussion OP_DUP OP_HASH160 <20 bytes of public key hash> 24 | OP_EQUALVERIFY OP_CHECKSIG 25 | */ 26 | BCScriptType_P2PKH = 0, 27 | 28 | /*! 29 | @brief Pay to script hash. 30 | 31 | @discussion OP_HASH160 <20 bytes of script hash> OP_EQUAL 32 | */ 33 | BCScriptType_P2SH, 34 | 35 | /*! 36 | @brief Pay to public key. 37 | 38 | @discussion <33 or 65 bytes of public key> OP_CHECKSIG 39 | */ 40 | BCScriptType_P2PK, 41 | 42 | /*! 43 | @brief Multi signiture. 44 | 45 | @discussion OP_ [n s] OP_ OP_CHECKMULTISIG 46 | */ 47 | BCScriptType_MofN, 48 | 49 | /*! 50 | @brief Op return script to push arbitrary data to the block 51 | chain. (Unspendable) 52 | 53 | @discussion OP_RETURN 54 | */ 55 | BCScriptType_OPReturn, 56 | 57 | /*! 58 | @brief A non standard transaction. (Unspendable) 59 | */ 60 | BCScriptType_NonStandard 61 | } BCScriptType; 62 | 63 | /*! 64 | @brief A immutable bitcoin script. 65 | 66 | @discussion This is best used to store bitcoin scripts. 67 | */ 68 | @interface BCScript : NSObject 69 | #pragma mark Construction 70 | /*! 71 | @brief Makes a script with the inputted data. 72 | 73 | @param data The script data to construct with 74 | */ 75 | - (instancetype)initWithData:(NSData *)data; 76 | 77 | /*! 78 | @brief Makes a script with the inputted data. 79 | 80 | @param data The script data to construct with 81 | */ 82 | + (instancetype)scriptWithData:(NSData *)data; 83 | 84 | /*! 85 | @brief Makes a script. 86 | */ 87 | + (instancetype)script; 88 | 89 | #pragma mark Representations 90 | /*! 91 | @brief Gets the bytes representing the script. 92 | 93 | @return The NSData managed bytes. 94 | */ 95 | - (NSData *)toData; 96 | 97 | /*! 98 | @brief Gets the string representation of the script. 99 | 100 | @return The string representation. 101 | */ 102 | - (NSString *)toString; 103 | 104 | @property(assign, nonatomic, readonly) BCScriptType type; 105 | 106 | @property(strong, nonatomic, readonly) NSArray *elements; 107 | 108 | 109 | - (BCAddress *)P2SHAddressForCoin:(BCCoin *)coin; 110 | 111 | @end 112 | 113 | /*! 114 | @brief A mutable bitcoin script. 115 | 116 | @discussion This is best used for writing bitcoin scripts. 117 | */ 118 | @interface BCMutableScript : BCScript 119 | #pragma mark Mutation 120 | /*! 121 | @brief Writes the inputted op code to the buffer. 122 | 123 | @param opCode The opcode to write to the buffer. 124 | */ 125 | - (void)writeOpCode:(BCScriptOpCode)opCode; 126 | 127 | /*! 128 | @brief Writes the bytes the data represents. 129 | 130 | @param bytes The bytes to write. 131 | */ 132 | - (void)writeBytes:(NSData *)bytes; 133 | 134 | @end 135 | -------------------------------------------------------------------------------- /Breadcrumb/Breadcrumb/Transaction/BCTransaction.h: -------------------------------------------------------------------------------- 1 | // 2 | // BCTransaction.h 3 | // Breadcrumb 4 | // 5 | // Created by Andrew Hurst on 2/7/15. 6 | // Copyright (c) 2015 Breadcrumb. 7 | // 8 | // Distributed under the MIT software license, see the accompanying 9 | // file LICENSE or http://www.opensource.org/licenses/mit-license.php. 10 | // 11 | // 12 | 13 | #import 14 | #import "BCAddress.h" 15 | #import "BCScript.h" 16 | 17 | /*! 18 | @brief Immutable Transaction object. 19 | */ 20 | @interface BCTransaction : NSObject 21 | #pragma mark Construction 22 | /*! 23 | @brief Constructs the transaction object with the inputted metadata. 24 | 25 | @param addresses The addresses for the transaction. 26 | @param script The transactions script. 27 | @param hash The hash of the transaction object. 28 | @param value The value of the transaction. 29 | @param confirmations The number of confirmations of the transaction. 30 | @param isSigned States if the transaction has been signed. 31 | */ 32 | - (instancetype)initWithAddresses:(NSArray *)addresses 33 | script:(BCScript *)script 34 | hash:(NSData *)hash 35 | outputIndex:(uint32_t)outputIndex 36 | value:(uint64_t)value 37 | confirmations:(NSNumber *)confirmations 38 | andSigned:(BOOL)isSigned; 39 | 40 | #pragma mark Metadata 41 | /*! 42 | @brief The addresses for the transaction. 43 | */ 44 | @property(strong, nonatomic, readonly) NSArray *addresses; 45 | 46 | /*! 47 | @brief The transactions script data. 48 | */ 49 | @property(strong, nonatomic, readonly) BCScript *script; 50 | 51 | /*! 52 | @brief The transactions hash. 53 | */ 54 | @property(strong, nonatomic, readonly) NSData *hash; 55 | 56 | @property(assign, nonatomic, readonly) uint32_t outputIndex; 57 | 58 | /*! 59 | @brief The value of the transaction. 60 | */ 61 | @property(assign, nonatomic, readonly) uint64_t value; 62 | 63 | /*! 64 | @brief The number of confirmations the transaction has. 65 | 66 | @discussion This is an optional value, it may return NULL. 67 | */ 68 | @property(strong, nonatomic, readonly) NSNumber *confirmations; 69 | 70 | /*! 71 | @brief States if the transaction has been signed. 72 | */ 73 | @property(assign, nonatomic, readonly) BOOL isSigned; 74 | 75 | @end 76 | -------------------------------------------------------------------------------- /Breadcrumb/Breadcrumb/Transaction/BCTransaction.m: -------------------------------------------------------------------------------- 1 | // 2 | // BCTransaction.m 3 | // Breadcrumb 4 | // 5 | // Created by Andrew Hurst on 2/7/15. 6 | // Copyright (c) 2015 Breadcrumb. 7 | // 8 | // Distributed under the MIT software license, see the accompanying 9 | // file LICENSE or http://www.opensource.org/licenses/mit-license.php. 10 | // 11 | // 12 | 13 | #import "BCTransaction.h" 14 | #import "BCScript+DefaultScripts.h" 15 | #import "BreadcrumbCore.h" 16 | 17 | @implementation BCTransaction 18 | 19 | @synthesize addresses = _addresses; 20 | @synthesize script = _script; 21 | @synthesize hash = _hash; 22 | @synthesize outputIndex = _outputIndex; 23 | 24 | @synthesize value = _value; 25 | @synthesize confirmations = _confirmations; 26 | 27 | @synthesize isSigned = _isSigned; 28 | 29 | #pragma mark Construction 30 | 31 | - (instancetype)initWithAddresses:(NSArray *)addresses 32 | script:(BCScript *)script 33 | hash:(NSData *)hash 34 | outputIndex:(uint32_t)outputIndex 35 | value:(uint64_t)value 36 | confirmations:(NSNumber *)confirmations 37 | andSigned:(BOOL)isSigned { 38 | self = [super init]; 39 | if (self) { 40 | // Validate addresses 41 | if (![addresses isKindOfClass:[NSArray class]]) return NULL; 42 | for (NSUInteger i = 0; i < addresses.count; ++i) 43 | if (![[addresses objectAtIndex:i] isKindOfClass:[BCAddress class]]) 44 | return NULL; 45 | _addresses = addresses; 46 | 47 | if (![script isKindOfClass:[BCScript class]]) return NULL; 48 | _script = script; 49 | if (![hash isKindOfClass:[NSData class]]) return NULL; 50 | _hash = hash; 51 | 52 | _outputIndex = outputIndex; 53 | 54 | _value = value; 55 | 56 | // Optional value, can be NULL 57 | _confirmations = 58 | [confirmations isKindOfClass:[NSNumber class]] ? confirmations : NULL; 59 | _isSigned = isSigned; 60 | } 61 | return self; 62 | } 63 | 64 | #pragma mark Debug 65 | 66 | - (NSString *)description { 67 | NSString *addresses; 68 | for (BCAddress *address in self.addresses) 69 | if ([addresses isKindOfClass:[NSString class]]) { 70 | addresses = 71 | [NSString stringWithFormat:@"%@, %@", addresses, [address toString]]; 72 | } else { 73 | addresses = [address toString]; 74 | } 75 | 76 | return [NSString 77 | stringWithFormat:@"Address(es): %@\nValue: %@\n" 78 | @"Confirmations: %@\nHash: %@\nOutput " 79 | @"Index:%@\nScript: '%@'\nisSigned: %@\n", 80 | addresses, [BCAmount prettyPrint:self.value], 81 | self.confirmations, self.hash.toHex, @(self.outputIndex), 82 | self.script, self.isSigned ? @"true" : @"false"]; 83 | } 84 | 85 | @end 86 | -------------------------------------------------------------------------------- /Breadcrumb/Breadcrumb/Transaction/BCTransactionInput.h: -------------------------------------------------------------------------------- 1 | // 2 | // BCTransactionInput.h 3 | // Breadcrumb 4 | // 5 | // Created by Andrew Hurst on 2/8/15. 6 | // Copyright (c) 2015 Breadcrumb. 7 | // 8 | // Distributed under the MIT software license, see the accompanying 9 | // file LICENSE or http://www.opensource.org/licenses/mit-license.php. 10 | // 11 | // 12 | 13 | #import 14 | #import "BCTransaction.h" 15 | 16 | @interface BCTransactionInput : NSObject 17 | #pragma mark Construction 18 | /*! 19 | @brief Constructs the transaction input with its binary representation, as 20 | defined by the bitcoin protocol. 21 | 22 | @param data The binary representation to construct with. 23 | */ 24 | - (instancetype)initWithData:(NSData *)data; 25 | 26 | - (instancetype)initWithData:(NSData *)data 27 | atOffset:(NSUInteger)offset 28 | withLength:(NSUInteger *)length; 29 | 30 | - (instancetype)initWithTransaction:(BCTransaction *)transaction; 31 | 32 | - (instancetype)initWithHash:(NSData *)hash 33 | previousIndex:(uint32_t)index 34 | script:(BCScript *)script 35 | address:(BCAddress *)address 36 | value:(uint64_t)value 37 | andSequence:(uint32_t)sequence; 38 | 39 | #pragma mark Meta Data 40 | 41 | /*! 42 | @brief This is the address which must sign the transaction. 43 | 44 | @discussion This is the address which has ownership for the transaction. In the 45 | future when we support multi signature this will need to be an array of 46 | addresses. 47 | 48 | NOTE: this can be null, because it can not be directly retrieved from parsing a 49 | raw transaction input. 50 | */ 51 | @property(strong, nonatomic, readonly) BCAddress *controllingAddress; 52 | 53 | /*! 54 | @brief The previous outputs hash. 55 | */ 56 | @property(strong, nonatomic, readonly) NSData *previousOutputHash; 57 | 58 | /*! 59 | @brief The previous outputs index. 60 | */ 61 | @property(assign, nonatomic, readonly) uint32_t previousOutputIndex; 62 | 63 | /*! 64 | @brief The script containing the signature. 65 | */ 66 | @property(strong, nonatomic, readonly) BCScript *scriptSig; 67 | 68 | /*! 69 | @brief The sequence value for the input, this is used to update unlocked 70 | transactions though the network currently doesn't support it. 71 | */ 72 | @property(assign, nonatomic, readonly) uint32_t sequence; 73 | 74 | @property(assign, nonatomic, readonly) uint64_t value; 75 | 76 | #pragma mark Fee Calculation 77 | 78 | - (NSUInteger)size; 79 | 80 | #pragma mark Representations 81 | 82 | - (NSString *)toString; 83 | 84 | /*! 85 | @brief This gets the input in its binary representation as defined by the 86 | bitcoin protocol. 87 | */ 88 | - (NSData *)toData; 89 | 90 | @end 91 | -------------------------------------------------------------------------------- /Breadcrumb/Breadcrumb/Transaction/BCTransactionInput.m: -------------------------------------------------------------------------------- 1 | // 2 | // BCTransactionInput.m 3 | // Breadcrumb 4 | // 5 | // Created by Andrew Hurst on 2/8/15. 6 | // Copyright (c) 2015 Breadcrumb. 7 | // 8 | // Distributed under the MIT software license, see the accompanying 9 | // file LICENSE or http://www.opensource.org/licenses/mit-license.php. 10 | // 11 | // 12 | 13 | #import "BCTransactionInput.h" 14 | #import "BreadcrumbCore.h" 15 | 16 | @implementation BCTransactionInput 17 | 18 | @synthesize previousOutputHash = _previousOutputHash; 19 | @synthesize previousOutputIndex = _previousOutputIndex; 20 | @synthesize sequence = _sequence; 21 | @synthesize controllingAddress = _controllingAddress; 22 | 23 | @synthesize scriptSig = _scriptSig; 24 | 25 | #pragma mark Construction 26 | 27 | - (instancetype)initWithData:(NSData *)data { 28 | return [self initWithData:data atOffset:0 withLength:NULL]; 29 | } 30 | 31 | - (instancetype)initWithData:(NSData *)data 32 | atOffset:(NSUInteger)offset 33 | withLength:(NSUInteger *)length { 34 | NSUInteger position, _length, scriptLength; 35 | uint32_t transactionIndex, sequence; 36 | NSData *scriptData, *transactionHash, *_data; 37 | BCScript *script; 38 | NSParameterAssert([data isKindOfClass:[NSData class]]); 39 | if (![data isKindOfClass:[NSData class]]) return NULL; 40 | 41 | // Get the data in the correct range 42 | _data = [data subdataWithRange:NSMakeRange(offset, data.length - offset)]; 43 | if (![_data isKindOfClass:[NSData class]]) return NULL; 44 | 45 | // Parse Data 46 | position = 0; // Get the transaction Hash 47 | transactionHash = [_data subdataWithRange:NSMakeRange(position, 32)]; 48 | position += 32; 49 | 50 | // Get the transaction output index 51 | transactionIndex = [_data UInt32AtOffset:position]; 52 | position += sizeof(uint32_t); 53 | 54 | // Get the scripts length 55 | scriptLength = (NSUInteger)[_data varIntAtOffset:position length:&_length]; 56 | position += _length; 57 | 58 | // Get the scripts data 59 | if (_data.length <= position + scriptLength) return NULL; 60 | scriptData = [_data subdataWithRange:NSMakeRange(position, scriptLength)]; 61 | position += scriptLength; 62 | 63 | // Get the sequence value 64 | sequence = [_data UInt32AtOffset:position]; 65 | position += sizeof(uint32_t); 66 | 67 | // Check the script data 68 | if (![scriptData isKindOfClass:[NSData class]]) return NULL; 69 | 70 | script = [BCScript scriptWithData:scriptData]; 71 | if (![script isKindOfClass:[BCScript class]]) return NULL; 72 | 73 | // Update Length if available 74 | if (length) *length = position; 75 | 76 | return [self initWithHash:transactionHash 77 | previousIndex:transactionIndex 78 | script:script 79 | address:NULL 80 | value:INFINITY 81 | andSequence:sequence]; 82 | } 83 | 84 | - (instancetype)initWithTransaction:(BCTransaction *)transaction { 85 | NSParameterAssert([transaction isKindOfClass:[BCTransaction class]]); 86 | if (![transaction isKindOfClass:[BCTransaction class]]) return NULL; 87 | 88 | return [self initWithHash:transaction.hash 89 | previousIndex:transaction.outputIndex 90 | script:transaction.script 91 | address:[transaction.addresses objectAtIndex:0] 92 | value:transaction.value 93 | andSequence:UINT32_MAX]; 94 | } 95 | 96 | - (instancetype)initWithHash:(NSData *)hash 97 | previousIndex:(uint32_t)index 98 | script:(BCScript *)script 99 | address:(BCAddress *)address 100 | value:(uint64_t)value 101 | andSequence:(uint32_t)sequence { 102 | NSParameterAssert([hash isKindOfClass:[NSData class]]); 103 | if (![hash isKindOfClass:[NSData class]]) return NULL; 104 | self = [self init]; 105 | if (self) { 106 | _previousOutputHash = hash; 107 | _previousOutputIndex = index; 108 | _scriptSig = script; 109 | _sequence = sequence; 110 | _value = value; 111 | _controllingAddress = address; 112 | } 113 | return self; 114 | } 115 | 116 | #pragma mark Fee Calculation 117 | 118 | - (NSUInteger)size { 119 | return [self toData].length; 120 | } 121 | 122 | #pragma mark Representations 123 | 124 | - (NSString *)toString { 125 | return [NSString stringWithFormat:@"Output Hash: '%@'\nOutput Index: %@\nSig " 126 | @"Script: '%@'\nSequence: %x", 127 | self.previousOutputHash.toHex, 128 | @(self.previousOutputIndex), self.scriptSig, 129 | self.sequence]; 130 | } 131 | 132 | - (NSData *)toData { 133 | NSData *scriptData; 134 | NSMutableData *buffer; 135 | 136 | buffer = [[NSMutableData alloc] init]; 137 | 138 | scriptData = [self.scriptSig toData]; 139 | if (![scriptData isKindOfClass:[NSData class]]) return NULL; 140 | 141 | [buffer appendData:[self.previousOutputHash reverse]]; 142 | [buffer appendUInt32:self.previousOutputIndex]; 143 | [buffer appendVarInt:scriptData.length]; 144 | [buffer appendData:scriptData]; 145 | [buffer appendUInt32:self.sequence]; 146 | 147 | return [NSData dataWithData:buffer]; 148 | } 149 | 150 | #pragma mark Debug 151 | 152 | - (NSString *)description { 153 | return [self toString]; 154 | } 155 | 156 | @end 157 | -------------------------------------------------------------------------------- /Breadcrumb/Breadcrumb/Transaction/BCTransactionOutput.h: -------------------------------------------------------------------------------- 1 | // 2 | // BCTransactionOutput.h 3 | // Breadcrumb 4 | // 5 | // Created by Andrew Hurst on 2/8/15. 6 | // Copyright (c) 2015 Breadcrumb. 7 | // 8 | // Distributed under the MIT software license, see the accompanying 9 | // file LICENSE or http://www.opensource.org/licenses/mit-license.php. 10 | // 11 | // 12 | 13 | #import 14 | #import "BCAddress.h" 15 | #import "BCScript.h" 16 | 17 | @interface BCTransactionOutput : NSObject 18 | 19 | #pragma mark Construction 20 | 21 | - (instancetype)initWithData:(NSData *)data; 22 | 23 | - (instancetype)initWithData:(NSData *)data 24 | atOffset:(NSUInteger)offset 25 | withLength:(NSUInteger *)length; 26 | 27 | - (instancetype)initWithScript:(BCScript *)script andValue:(uint64_t)value; 28 | 29 | + (instancetype)outputWithData:(NSData *)data; 30 | 31 | + (instancetype)outputWithScript:(BCScript *)script andValue:(uint64_t)value; 32 | 33 | + (instancetype)standardOutputForAmount:(uint64_t)amount 34 | toAddress:(BCAddress *)address 35 | forCoin:(BCCoin *)coin; 36 | 37 | #pragma mark Metadata 38 | /*! 39 | @brief The amount the output is for. 40 | */ 41 | @property(assign, nonatomic, readonly) uint64_t value; 42 | 43 | /*! 44 | @brief The transactions script. 45 | */ 46 | @property(strong, nonatomic, readonly) BCScript *script; 47 | 48 | #pragma mark Fee Calculation 49 | 50 | - (NSUInteger)size; 51 | 52 | #pragma mark Representations 53 | 54 | /*! 55 | @brief Gets a human readable string representation the transaction output. 56 | */ 57 | - (NSString *)toString; 58 | 59 | /*! 60 | @brief Converts the transaction output to its data representation. 61 | */ 62 | - (NSData *)toData; 63 | 64 | @end 65 | -------------------------------------------------------------------------------- /Breadcrumb/Breadcrumb/Transaction/BCTransactionOutput.m: -------------------------------------------------------------------------------- 1 | // 2 | // BCTransactionOutput.m 3 | // Breadcrumb 4 | // 5 | // Created by Andrew Hurst on 2/8/15. 6 | // Copyright (c) 2015 Breadcrumb. 7 | // 8 | // Distributed under the MIT software license, see the accompanying 9 | // file LICENSE or http://www.opensource.org/licenses/mit-license.php. 10 | // 11 | // 12 | 13 | #import "BCTransactionOutput.h" 14 | #import "BCScript+DefaultScripts.h" 15 | #import "BreadcrumbCore.h" 16 | 17 | @implementation BCTransactionOutput 18 | 19 | @synthesize script = _script; 20 | @synthesize value = _value; 21 | #pragma mark Construction 22 | 23 | - (instancetype)initWithData:(NSData *)data { 24 | return [self initWithData:data atOffset:0 withLength:NULL]; 25 | } 26 | 27 | - (instancetype)initWithData:(NSData *)data 28 | atOffset:(NSUInteger)offset 29 | withLength:(NSUInteger *)length { 30 | uint64_t value; 31 | NSUInteger scriptLength, valueLength, position = 0; 32 | NSData *scriptData, *_data; 33 | BCScript *script; 34 | NSParameterAssert([data isKindOfClass:[NSData class]]); 35 | if (![data isKindOfClass:[NSData class]]) return NULL; 36 | 37 | // Get data from offset 38 | _data = [data subdataWithRange:NSMakeRange(offset, data.length - offset)]; 39 | if (![_data isKindOfClass:[NSData class]]) return NULL; 40 | 41 | // Get the value of the output 42 | value = [_data UInt64AtOffset:0]; 43 | position += sizeof(uint64_t); 44 | 45 | // Get the scripts length 46 | scriptLength = [_data varIntAtOffset:position length:&valueLength]; 47 | position += valueLength; 48 | 49 | // Get the scripts data 50 | scriptData = [_data subdataWithRange:NSMakeRange(position, scriptLength)]; 51 | position += scriptLength; 52 | if (![scriptData isKindOfClass:[NSData class]]) return NULL; 53 | 54 | script = [BCScript scriptWithData:scriptData]; 55 | if (![script isKindOfClass:[BCScript class]]) return NULL; 56 | 57 | if (length) *length = position; 58 | 59 | return [self initWithScript:script andValue:value]; 60 | } 61 | 62 | - (instancetype)initWithScript:(BCScript *)script andValue:(uint64_t)value { 63 | NSParameterAssert([script isKindOfClass:[BCScript class]]); 64 | if (![script isKindOfClass:[BCScript class]]) return NULL; 65 | 66 | self = [self init]; 67 | if (self) { 68 | _script = script; 69 | _value = value; 70 | } 71 | return self; 72 | } 73 | 74 | + (instancetype)outputWithData:(NSData *)data { 75 | return [[[self class] alloc] initWithData:data]; 76 | } 77 | 78 | + (instancetype)outputWithScript:(BCScript *)script andValue:(uint64_t)value { 79 | return [[[self class] alloc] initWithScript:script andValue:value]; 80 | } 81 | 82 | + (instancetype)standardOutputForAmount:(uint64_t)amount 83 | toAddress:(BCAddress *)address 84 | forCoin:(BCCoin *)coin { 85 | BCScript *transactionScript; 86 | NSParameterAssert([address isKindOfClass:[BCAddress class]]); 87 | if (![address isKindOfClass:[BCAddress class]]) return NULL; 88 | 89 | transactionScript = [BCScript standardTransactionScript:address andCoin:coin]; 90 | if (![transactionScript isKindOfClass:[BCScript class]]) return NULL; 91 | 92 | return [self outputWithScript:transactionScript andValue:amount]; 93 | } 94 | 95 | #pragma mark Fee Calculation 96 | 97 | - (NSUInteger)size { 98 | return [self toData].length; 99 | } 100 | 101 | #pragma mark Representations 102 | 103 | - (NSString *)toString { 104 | return [NSString 105 | stringWithFormat:@"Value: %@\nScript: '%@'", [BCAmount prettyPrint:self.value], self.script]; 106 | } 107 | 108 | - (NSData *)toData { 109 | uint64_t scriptSize; 110 | NSData *scriptData; 111 | NSMutableData *buffer = [[NSMutableData alloc] init]; 112 | 113 | // Get the script data 114 | scriptData = [self.script toData]; 115 | if (![scriptData isKindOfClass:[NSData class]]) return NULL; 116 | 117 | // Get the scripts length 118 | scriptSize = scriptData.length; 119 | 120 | // Append the buffer 121 | [buffer appendUInt64:self.value]; 122 | [buffer appendVarInt:scriptSize]; 123 | [buffer appendData:scriptData]; 124 | 125 | // Make an immutable copy 126 | return [NSData dataWithData:buffer]; 127 | } 128 | 129 | #pragma mark Debug 130 | 131 | - (NSString *)description { 132 | return [self toString]; 133 | } 134 | 135 | @end 136 | -------------------------------------------------------------------------------- /Breadcrumb/Breadcrumb/Utilities/BCProtectedData.h: -------------------------------------------------------------------------------- 1 | // 2 | // BCProtectedData.h 3 | // Breadcrumb 4 | // 5 | // Created by Andrew Hurst on 2/10/15. 6 | // Copyright (c) 2015 Breadcrumb. 7 | // 8 | // Distributed under the MIT software license, see the accompanying 9 | // file LICENSE or http://www.opensource.org/licenses/mit-license.php. 10 | // 11 | // 12 | // This is my attempt to reduce surface area of attack, This should be used for 13 | // all protected data stored in memory. Assuming this goes under review we 14 | // should just need to worry about key management, and Input validation. 15 | 16 | #import 17 | 18 | /*! 19 | @brief Standard interface for protecting arbitrary data in memory using a key. 20 | 21 | @discussion This will protect NSData in memory by AES256 encrypting it using 22 | the inputted memory key, for this to have any effect you MUST generate a strong 23 | memory key, and keep that key protected. 24 | 25 | You SHOULD never directly use a user inputted password as a key unless passed 26 | through a key derivation algorithm first. You should consider using Scrypt 27 | (Preferred), or PBKDF2 as you key derivation methods. 28 | */ 29 | @interface BCProtectedData : NSObject 30 | #pragma mark Construction 31 | /*! 32 | @brief Constructs a protected memory object with 33 | 34 | @discussion This will protect NSData in memory by AES256 encrypting it using 35 | the inputted memory key, for this to have any effect you MUST generate a strong 36 | memory key, and keep that key protected. 37 | 38 | You SHOULD never directly use a user inputted password as a key unless passed 39 | through a key derivation algorithm first. You should consider using Scrypt 40 | (Preferred), or PBKDF2 as you key derivation methods. 41 | 42 | @param data The data which should be protected. 43 | @param memoryKey The key used to protect the data. 44 | */ 45 | - (instancetype)initData:(NSData *)data withMemoryKey:(NSData *)memoryKey; 46 | 47 | /*! 48 | @brief Constructs a protected memory object with 49 | 50 | @discussion This will protect NSData in memory by AES256 encrypting it using 51 | the inputted memory key, for this to have any effect you MUST generate a strong 52 | memory key, and keep that key protected. 53 | 54 | You SHOULD never directly use a user inputted password as a key unless passed 55 | through a key derivation algorithm first. You should consider using Scrypt 56 | (Preferred), or PBKDF2 as you key derivation methods. 57 | 58 | @param data The data which should be protected. 59 | @param memoryKey The key used to protect the data. 60 | */ 61 | + (instancetype)protectedData:(NSData *)data withMemoryKey:(NSData *)memoryKey; 62 | 63 | #pragma mark Retrieval 64 | 65 | /*! 66 | @brief The protected datas' cypher text. 67 | */ 68 | @property(strong, nonatomic, readonly) NSData *cypherText; 69 | 70 | /*! 71 | @brief Retrieves the protected data in the clear, using the inputted memory key 72 | to decrypt the data. 73 | 74 | @param memoryKey The key used to decrypt the protected memory. 75 | 76 | @return A copy of the protected data in the clear, or NULL if the memory key 77 | was incorrect. 78 | */ 79 | - (NSData *)dataUsingMemoryKey:(NSData *)memoryKey; 80 | 81 | #pragma mark Algorithm 82 | /*! 83 | @brief Verifies that the key is valid for the used algorithm. 84 | 85 | @param key The key to verify. 86 | */ 87 | + (BOOL)keyIsValidForAlgorithm:(NSData *)key; 88 | 89 | @end 90 | 91 | @interface NSData (BCProtectedData) 92 | 93 | /*! 94 | @brief Gets the current data protected with the inputted key. 95 | 96 | @discussion This will protect NSData in memory by AES256 encrypting it using 97 | the inputted memory key, for this to have any effect you MUST generate a strong 98 | memory key, and keep that key protected. 99 | 100 | You SHOULD never directly use a user inputted password as a key unless passed 101 | through a key derivation algorithm first. You should consider using Scrypt 102 | (Preferred), or PBKDF2 as you key derivation methods. 103 | 104 | @param key The key used to protect the data. 105 | */ 106 | - (BCProtectedData *)protectedWithKey:(NSData *)key; 107 | 108 | @end 109 | -------------------------------------------------------------------------------- /Breadcrumb/Breadcrumb/Utilities/BCProtectedData.m: -------------------------------------------------------------------------------- 1 | // 2 | // BCProtectedData.m 3 | // Breadcrumb 4 | // 5 | // Created by Andrew Hurst on 2/10/15. 6 | // Copyright (c) 2015 Breadcrumb. 7 | // 8 | // Distributed under the MIT software license, see the accompanying 9 | // file LICENSE or http://www.opensource.org/licenses/mit-license.php. 10 | // 11 | // 12 | 13 | #import "BCProtectedData.h" 14 | #import "NSData+Encryption.h" 15 | #import "NSMutableData+Bitcoin.h" 16 | 17 | @implementation BCProtectedData 18 | 19 | @synthesize cypherText = _cypherText; 20 | 21 | #pragma mark Construction 22 | 23 | - (instancetype)initData:(NSData *)data withMemoryKey:(NSData *)memoryKey { 24 | @autoreleasepool { 25 | NSParameterAssert([data isKindOfClass:[NSData class]]); 26 | NSParameterAssert([[self class] keyIsValidForAlgorithm:memoryKey]); 27 | if (![data isKindOfClass:[NSData class]] || 28 | ![[self class] keyIsValidForAlgorithm:memoryKey]) 29 | return NULL; 30 | 31 | // We want to use secure mutable data because it will zero it self out. 32 | _cypherText = [[self class] encrypt:data withKey:memoryKey]; 33 | memoryKey = NULL; 34 | data = NULL; 35 | } 36 | return self; 37 | } 38 | 39 | + (instancetype)protectedData:(NSData *)data withMemoryKey:(NSData *)memoryKey { 40 | return [[[self class] alloc] initData:data withMemoryKey:memoryKey]; 41 | } 42 | 43 | #pragma mark Retrieval 44 | 45 | - (NSData *)dataUsingMemoryKey:(NSData *)memoryKey { 46 | @autoreleasepool { 47 | NSParameterAssert([[self class] keyIsValidForAlgorithm:memoryKey]); 48 | if (![[self class] keyIsValidForAlgorithm:memoryKey]) return NULL; 49 | 50 | // Attempt to decrypt the entered data, return secure data so it will zero 51 | // it self out. 52 | return [[self class] decrypt:_cypherText withKey:memoryKey]; 53 | } 54 | } 55 | 56 | #pragma mark Algorithm Implementation 57 | 58 | + (NSData *)encrypt:(NSData *)data withKey:(NSData *)key { 59 | @autoreleasepool { 60 | // Note: Returns [NSMutableData secureData] zeros self out apon dealloc 61 | NSData *cypherText = [data AES256ETMEncrypt:key]; 62 | data = NULL; 63 | key = NULL; 64 | return [cypherText isKindOfClass:[NSData class]] ? cypherText : NULL; 65 | } 66 | } 67 | 68 | + (NSData *)decrypt:(NSData *)data withKey:(NSData *)key { 69 | @autoreleasepool { 70 | // Note: Returns [NSMutableData secureData] zeros self out apon dealloc 71 | NSData *clearText = [data AES256ETMDecrypt:key]; 72 | data = NULL; 73 | key = NULL; 74 | return [clearText isKindOfClass:[NSData class]] ? clearText : NULL; 75 | } 76 | } 77 | 78 | + (BOOL)keyIsValidForAlgorithm:(NSData *)key { 79 | @autoreleasepool { 80 | // AES Requires key to be in quantities of 32 bytes 81 | return [key isKindOfClass:[NSData class]] && key.length % 32 == 0; 82 | } 83 | } 84 | 85 | @end 86 | 87 | @implementation NSData (BCProtectedData) 88 | 89 | - (BCProtectedData *)protectedWithKey:(NSData *)key { 90 | @autoreleasepool { 91 | return [BCProtectedData protectedData:self withMemoryKey:key]; 92 | } 93 | } 94 | 95 | @end 96 | -------------------------------------------------------------------------------- /Breadcrumb/Breadcrumb/Wallet/BCWallet+Restoration.h: -------------------------------------------------------------------------------- 1 | // 2 | // BCWallet+Restoration.h 3 | // Breadcrumb 4 | // 5 | // Created by Andrew Hurst on 2/10/15. 6 | // Copyright (c) 2015 Breadcrumb. 7 | // 8 | // Distributed under the MIT software license, see the accompanying 9 | // file LICENSE or http://www.opensource.org/licenses/mit-license.php. 10 | // 11 | // 12 | 13 | #import "BCWallet.h" 14 | 15 | @interface BCWallet (Restoration) 16 | #pragma mark Construction 17 | /*! 18 | @brief Constructs the wallet using the inputted restoration data. 19 | 20 | @param privInfo The wallets private info. 21 | @param pubInfo The wallets public info. 22 | @param password The password data used in the creation of the wallet. 23 | */ 24 | + (instancetype)initUsingPrivateInfo:(NSDictionary *)privInfo 25 | publicInfo:(NSDictionary *)pubInfo 26 | password:(NSData *)password 27 | withCompletion:(void (^)(id))completion; 28 | 29 | #pragma mark Info 30 | /*! 31 | @brief Gets the wallets private information in its password protected format to 32 | be used in restoration. 33 | 34 | @return Dictionary with the wallets private info password protected. 35 | */ 36 | - (NSDictionary *)privateInfo; 37 | 38 | /*! 39 | @brief Public wallet info to be used for restoration. 40 | 41 | @return Public information about the wallet in clear text. 42 | */ 43 | - (NSDictionary *)publicInfo; 44 | 45 | @end 46 | -------------------------------------------------------------------------------- /Breadcrumb/Breadcrumb/Wallet/BCWallet+Restoration.m: -------------------------------------------------------------------------------- 1 | // 2 | // BCWallet+Restoration.m 3 | // Breadcrumb 4 | // 5 | // Created by Andrew Hurst on 2/10/15. 6 | // Copyright (c) 2015 Breadcrumb. 7 | // 8 | // Distributed under the MIT software license, see the accompanying 9 | // file LICENSE or http://www.opensource.org/licenses/mit-license.php. 10 | // 11 | // 12 | 13 | #import "BCWallet+Restoration.h" 14 | #import "_BCWallet.h" 15 | 16 | @implementation BCWallet (Restoration) 17 | #pragma mark Construction 18 | 19 | + (instancetype)initUsingPrivateInfo:(NSDictionary *)privInfo 20 | publicInfo:(NSDictionary *)pubInfo 21 | password:(NSData *)password 22 | withCompletion:(void (^)(id))completion { 23 | @autoreleasepool { 24 | // TODO: Process info and restore 25 | return NULL; 26 | } 27 | } 28 | 29 | #pragma mark Restoration Data Retrieval 30 | 31 | - (NSDictionary *)privateInfo { 32 | return NULL; 33 | } 34 | 35 | - (NSDictionary *)publicInfo { 36 | return NULL; 37 | } 38 | 39 | #pragma mark Utilities 40 | 41 | + (NSDictionary *)privateInfoWithEncryptedSeed:(NSData *)seed 42 | encryptedMnemonic:(NSData *)mnemonic { 43 | @autoreleasepool { 44 | NSParameterAssert([seed isKindOfClass:[NSData class]]); 45 | NSParameterAssert([mnemonic isKindOfClass:[NSData class]]); 46 | if (![seed isKindOfClass:[NSData class]] || 47 | ![mnemonic isKindOfClass:[NSData class]]) 48 | return NULL; 49 | return @{kBCRestoration_Seed : seed, kBCRestoration_Mnemonic : mnemonic}; 50 | } 51 | } 52 | @end 53 | -------------------------------------------------------------------------------- /Breadcrumb/Breadcrumb/Wallet/BCWallet+TransactionSigning.h: -------------------------------------------------------------------------------- 1 | // 2 | // BCWallet+TransactionSigning.h 3 | // Breadcrumb 4 | // 5 | // Created by Andrew Hurst on 2/9/15. 6 | // Copyright (c) 2015 Breadcrumb. 7 | // 8 | // Distributed under the MIT software license, see the accompanying 9 | // file LICENSE or http://www.opensource.org/licenses/mit-license.php. 10 | // 11 | // 12 | 13 | #import "BCWallet.h" 14 | #import "BCMutableTransaction.h" 15 | 16 | @interface BCWallet (_TransactionSigning) 17 | 18 | /*! 19 | @brief Signs the inputted transaction with this wallets keys. 20 | 21 | @param transaction The transaction to sign. 22 | @param key The key to decrypt the wallets keys with. 23 | @param error The location to put the signing error info if any. 24 | 25 | @return The signed transaction. 26 | */ 27 | - (BCMutableTransaction *)_signTransaction:(BCMutableTransaction *)transaction 28 | withKey:(NSData *)key 29 | andError:(NSError **)error; 30 | @end 31 | 32 | @interface BCWallet (_SecurityUtilities) 33 | 34 | /*! 35 | @brief This generates a key using the wallet salt, and the given password. 36 | 37 | @discussion This method scrypt the inputted password with the salt from the 38 | wallets salt class method. 39 | 40 | This is a long running operation, and should not be executed on the main 41 | thread. 42 | 43 | @param password The password data to generate the key with. 44 | 45 | @return The 32 byte key, or NULL if the operation failed.. 46 | */ 47 | + (NSData *)_keyFromPassword:(NSData *)password; 48 | 49 | /*! 50 | @brief The data that should be used as a salt on the current system. 51 | 52 | @discussion This is a per application/device salt based off of the applications 53 | container. 54 | 55 | This means that if the application is uninstalled, or the same application is 56 | installed on another device, and the keychain is shared across devices the 57 | other device won't be able to generate the key. This could be seen as a bug, or 58 | purposefully. 59 | 60 | If you want different behavior you should override this method in your 61 | subclass. 62 | */ 63 | + (NSData *)_saltData; 64 | 65 | @end 66 | -------------------------------------------------------------------------------- /Breadcrumb/Breadcrumb/Wallet/BCWallet+Transactions.h: -------------------------------------------------------------------------------- 1 | // 2 | // BCWallet+Transactions.h 3 | // Breadcrumb 4 | // 5 | // Created by Andrew Hurst on 2/6/15. 6 | // Copyright (c) 2015 Breadcrumb. 7 | // 8 | // Distributed under the MIT software license, see the accompanying 9 | // file LICENSE or http://www.opensource.org/licenses/mit-license.php. 10 | // 11 | // 12 | 13 | #import "BCWallet.h" 14 | #import "BCTransaction.h" 15 | #import "BCMutableTransaction.h" 16 | 17 | static const uint64_t kBCStandardFeePerKB = 20000; 18 | 19 | @interface BCWallet (Transactions) 20 | 21 | /*! 22 | @brief Sends the inputted amount to the address, and invokes the callback with 23 | any errors. 24 | 25 | @param amount The amount to send in satoshi. 26 | @param address The address to send the amount to. 27 | @param callback The callback to call when the operation completes or fails 28 | */ 29 | - (void)send:(uint64_t)amount 30 | to:(BCAddress *)address 31 | feePerKB:(uint64_t)feePerKB 32 | usingPassword:(NSData *)password 33 | withCallback:(void (^)(NSData *, NSError *))callback; 34 | 35 | /*! 36 | @brief Sends the inputted amount to the address, and invokes the callback with 37 | any errors. 38 | 39 | @param amount The amount to send in satoshi. 40 | @param address The address to send the amount to. 41 | @param callback The callback to call when the operation completes or fails 42 | @param extra Extra info to pass to the provider. 43 | */ 44 | - (void)send:(uint64_t)amount 45 | to:(BCAddress *)address 46 | feePerKB:(uint64_t)feePerKB 47 | usingPassword:(NSData *)password 48 | withCallback:(void (^)(NSData *, NSError *))callback 49 | andExtra:(id)extra; 50 | 51 | /*! 52 | @brief Sends the inputted amount to the address, and invokes the callback with 53 | any errors. 54 | 55 | @param amount The amount to send in satoshi. 56 | @param address The address to send the amount to. 57 | @param callback The callback to call when the operation completes or fails 58 | */ 59 | - (void)send:(uint64_t)amount 60 | to:(BCAddress *)address 61 | usingPassword:(NSData *)password 62 | withCallback:(void (^)(NSData *, NSError *))callback; 63 | 64 | /*! 65 | @brief Sends the inputted amount to the address, and invokes the callback with 66 | any errors. 67 | 68 | @param amount The amount to send in satoshi. 69 | @param address The address to send the amount to. 70 | */ 71 | - (void)send:(uint64_t)amount 72 | to:(BCAddress *)address 73 | usingPassword:(NSData *)password; 74 | 75 | /*! 76 | @brief Creates a transaction for the current wallet at the specified amount to 77 | the specified address. 78 | 79 | @param amount The amount to make transaction is for. 80 | @param feePerKB The fee to give to the miner per kb of the transaction. 81 | @param address The address of the person to send the transaction to. 82 | @param callback The callback to call with the unsigned transaction, or an 83 | operational error. 84 | */ 85 | - (void)_unsignedTransactionForAmount:(uint64_t)amount 86 | feePerKB:(uint64_t)feePerKB 87 | to:(BCAddress *)address 88 | withCallback:(void (^)(BCMutableTransaction *, 89 | NSError *))callback; 90 | @end 91 | -------------------------------------------------------------------------------- /Breadcrumb/Breadcrumb/_BCWallet.h: -------------------------------------------------------------------------------- 1 | // 2 | // _BCWallet.h 3 | // Breadcrumb 4 | // 5 | // Created by Andrew Hurst on 2/9/15. 6 | // Copyright (c) 2015 Breadcrumb. 7 | // 8 | // Distributed under the MIT software license, see the accompanying 9 | // file LICENSE or http://www.opensource.org/licenses/mit-license.php. 10 | // 11 | // 12 | 13 | #import "BCWallet.h" 14 | #import "BCProviderChain.h" 15 | #import "BCProtectedData.h" 16 | #import "BCKeySequence.h" 17 | 18 | #import "BCWallet+Transactions.h" 19 | #import "BCWallet+TransactionSigning.h" 20 | #import "BCWallet+Restoration.h" 21 | 22 | #import "BCAddressManager.h" 23 | 24 | #import "BreadcrumbCore.h" 25 | 26 | // Queue Label 27 | static const char *kBCWalletQueueLabel = "com.Breadcrumb.wallet"; 28 | 29 | // Restoration Keys 30 | static NSString *const kBCRestoration_Seed = @"seed"; 31 | static NSString *const kBCRestoration_Mnemonic = @"mnemonic"; 32 | 33 | @interface BCWallet () { 34 | // Because the information in the wallet is protected using a scrypt derived 35 | // key we need to have a background queue so we don't block the main queue. We 36 | // also want user operations execute in order 37 | dispatch_queue_t __queue; 38 | } 39 | 40 | #pragma mark Protected Data 41 | /*! 42 | @brief The protected data of the mnemonic phrase. 43 | 44 | @discussion This is protected with AES256 using a scrypt key derived from the 45 | entered passphrase, its' cypher text is managed by the protected data object. 46 | The data retrieved from the protected data manager has a secure allocator, 47 | reallocator, and deallocator. 48 | */ 49 | @property(strong, nonatomic, readonly) BCProtectedData *protectedMnemonic; 50 | 51 | #pragma mark Keys & Addresses 52 | /*! 53 | @brief This manages HD key pairs, and their children. 54 | 55 | @discussion This maintains the lifecycle of the master key pair, and its 56 | children. 57 | */ 58 | @property(strong, nonatomic, readonly) BCKeySequence *keys; 59 | 60 | /*! 61 | @brief This manages addresses, and key paths. 62 | 63 | @discussion This currently supports hybrid imports, and calls the provider 64 | object. 65 | */ 66 | @property(strong, nonatomic, readonly) BCAddressManager *addressManager; 67 | 68 | #pragma mark Queue 69 | /*! 70 | @brief The queue which wallet operations are performed. 71 | */ 72 | @property(nonatomic, readonly) dispatch_queue_t queue; 73 | 74 | @end 75 | -------------------------------------------------------------------------------- /Breadcrumb/Breadcrumb/secp256k1/BCsecp256k1.h: -------------------------------------------------------------------------------- 1 | // 2 | // BCsecp256k1.h 3 | // Breadcrumb 4 | // 5 | // Created by Andrew Hurst on 2/11/15. 6 | // Copyright (c) 2015 Breadcrumb. 7 | // 8 | // Distributed under the MIT software license, see the accompanying 9 | // file LICENSE or http://www.opensource.org/licenses/mit-license.php. 10 | // 11 | // 12 | 13 | #import 14 | #import "tommath.h" 15 | 16 | /*! 17 | @brief This is a helper class for secp256k1 functions. 18 | 19 | @discussion you should always use the shared instance of this class, there is 20 | no reason to have more than one instance of this. 21 | 22 | This is an abstraction of https://github.com/bitcoin/secp256k1 23 | */ 24 | @interface BCsecp256k1 : NSObject 25 | #pragma mark Operations 26 | /*! 27 | @brief Derives a public key for the given private key. 28 | 29 | @param privateKey The private key to generate the public key from. 30 | */ 31 | - (NSData *)publicKeyFromKey:(NSData *)privateKey compressed:(BOOL)compressed; 32 | 33 | /*! 34 | @brief Signs the inputted hash with the inputed private key. 35 | 36 | @param hash The 32 byte hash to sign, 37 | @param key The 32 byte key to sign the hash with. 38 | */ 39 | - (NSData *)signatureForHash:(NSData *)hash withPrivateKey:(NSData *)key; 40 | 41 | /*! 42 | @brief Checks if the signature is valid given the signed data, the origin data, 43 | and the public key. 44 | 45 | @param signature The signed data. 46 | @param hash The origin data before it was signed. 47 | @param publicKey The public key of the key pair that signed the data. 48 | */ 49 | - (BOOL)signature:(NSData *)signature 50 | originHash:(NSData *)hash 51 | isValidForPublicKey:(NSData *)publicKey; 52 | 53 | #pragma mark Public Key Tweeks 54 | 55 | - (NSData *)publicKey:(NSData *)publicKey add:(NSData *)tweek; 56 | 57 | - (NSData *)privateKey:(NSData *)privateKey add:(NSData *)tweek; 58 | 59 | #pragma mark Shared access 60 | 61 | /*! 62 | @brief This is the instance you should use for secp256k1 operations. First call 63 | can take (10-100ms) 64 | 65 | @discussion First access of this instance allocates memory for secp256k1 66 | operations, upon deallocation of this instance memory for the c library will 67 | be also deallocated. 68 | */ 69 | + (instancetype)sharedInstance; 70 | 71 | #pragma mark Utilities 72 | + (NSData *)pseudoRandomDataWithLength:(NSUInteger)length; 73 | + (mp_int)curveOrder; 74 | @end 75 | -------------------------------------------------------------------------------- /Breadcrumb/Breadcrumb/secp256k1/BCsecp256k1.m: -------------------------------------------------------------------------------- 1 | // 2 | // BCsecp256k1.m 3 | // Breadcrumb 4 | // 5 | // Created by Andrew Hurst on 2/11/15. 6 | // Copyright (c) 2015 Breadcrumb. 7 | // 8 | // Distributed under the MIT software license, see the accompanying 9 | // file LICENSE or http://www.opensource.org/licenses/mit-license.php. 10 | // 11 | // 12 | 13 | #import "BCsecp256k1.h" 14 | #import "secp256k1.h" 15 | #import "BreadcrumbCore.h" 16 | 17 | @implementation BCsecp256k1 18 | #pragma mark Construction 19 | 20 | - (instancetype)init { 21 | NSAssert(false, @"MUST use shared instance of BCsecp256k1."); 22 | return NULL; 23 | } 24 | 25 | - (instancetype)_init { 26 | self = [super init]; 27 | if (self) { 28 | // Need to alloc for secp256k1 29 | secp256k1_start(SECP256K1_START_SIGN); 30 | secp256k1_start(SECP256K1_START_VERIFY); 31 | } 32 | return self; 33 | } 34 | 35 | - (void)dealloc { 36 | secp256k1_stop(); 37 | } 38 | 39 | #pragma mark Operations 40 | 41 | - (NSData *)publicKeyFromKey:(NSData *)privateKey compressed:(BOOL)compressed { 42 | @autoreleasepool { 43 | unsigned char pubKey[65]; 44 | int pubKeyLength; 45 | if (![privateKey isKindOfClass:[NSData class]]) return NULL; 46 | if (![privateKey bytes] || privateKey.length != 32) return NULL; 47 | 48 | if (secp256k1_ec_pubkey_create(pubKey, &pubKeyLength, [privateKey bytes], 49 | compressed) == 0) { 50 | NSLog(@"Failed to create public key!"); // TODO: Report as errors 51 | return NULL; 52 | } else { 53 | return [[NSData alloc] initWithBytes:pubKey length:(NSUInteger)pubKeyLength]; 54 | } 55 | } 56 | } 57 | 58 | - (NSData *)signatureForHash:(NSData *)hash withPrivateKey:(NSData *)key { 59 | @autoreleasepool { 60 | unsigned char signature[72]; 61 | int sigLength = 72; 62 | NSData *signiture; 63 | if (![key isKindOfClass:[NSData class]]) { 64 | key = NULL; 65 | return NULL; 66 | } 67 | 68 | if (secp256k1_ec_seckey_verify([key bytes]) == 0) { 69 | NSLog(@"Key Not Valid"); // TODO: Report as errors 70 | key = NULL; 71 | return NULL; 72 | } 73 | 74 | if (secp256k1_ecdsa_sign( 75 | [hash bytes], signature, &sigLength, [key bytes], secp256k1_nonce_function_rfc6979, 76 | NULL) == 0) { 77 | NSLog(@"Failed to sign!"); // TODO: Report as errors 78 | key = NULL; 79 | return NULL; 80 | } else { 81 | key = NULL; 82 | signiture = [[NSData alloc] initWithBytes:signature length:(NSUInteger)sigLength]; 83 | 84 | return [signiture isKindOfClass:[NSData class]] ? signiture : NULL; 85 | } 86 | } 87 | } 88 | 89 | - (BOOL)signature:(NSData *)signature 90 | originHash:(NSData *)hash 91 | isValidForPublicKey:(NSData *)publicKey { 92 | @autoreleasepool { 93 | int status; 94 | // TODO: Validate Inputs 95 | 96 | status = secp256k1_ecdsa_verify([hash bytes], [signature bytes], 97 | (int)signature.length, [publicKey bytes], 98 | (int)publicKey.length); 99 | switch (status) { 100 | case 1: 101 | return TRUE; 102 | break; 103 | case 0: 104 | // NSLog(@"Incorrect Sig"); // TODO: Report as errors 105 | return FALSE; 106 | break; 107 | case -1: 108 | // NSLog(@"Invalid Sig"); // TODO: Report as errors 109 | return FALSE; 110 | break; 111 | case -2: 112 | // NSLog(@"Invalid pub key"); // TODO: Report as errors 113 | return FALSE; 114 | break; 115 | default: 116 | return FALSE; 117 | break; 118 | } 119 | } 120 | } 121 | 122 | - (NSData *)publicKey:(NSData *)publicKey add:(NSData *)tweek { 123 | NSMutableData *mPubKey = [NSMutableData dataWithData:publicKey]; 124 | if ( !secp256k1_ec_pubkey_tweak_add([mPubKey mutableBytes], (int)mPubKey.length, tweek.bytes) ) { 125 | return NULL; 126 | } 127 | return [NSData dataWithData:mPubKey]; 128 | } 129 | 130 | - (NSData *)privateKey:(NSData *)privateKey add:(NSData *)tweek { 131 | @autoreleasepool { 132 | NSMutableData *mPrivKey = [NSMutableData dataWithData:privateKey]; 133 | if (!secp256k1_ec_privkey_tweak_add((unsigned char *)tweek.bytes, [mPrivKey mutableBytes])) { 134 | return NULL; 135 | } 136 | return [NSData dataWithData:mPrivKey]; 137 | } 138 | } 139 | 140 | #pragma mark Shared access 141 | 142 | + (instancetype)sharedInstance { 143 | static dispatch_once_t onceToken; 144 | static BCsecp256k1 *instance; 145 | dispatch_once(&onceToken, ^{ instance = [[[self class] alloc] _init]; }); 146 | return instance; 147 | } 148 | 149 | #pragma mark Utilties 150 | + (NSData *)pseudoRandomDataWithLength:(NSUInteger)length { 151 | @autoreleasepool { 152 | NSMutableData *entropy; 153 | 154 | entropy = [NSMutableData secureDataWithLength:length]; 155 | SecRandomCopyBytes(kSecRandomDefault, entropy.length, entropy.mutableBytes); 156 | 157 | return entropy; 158 | } 159 | } 160 | 161 | + (mp_int)curveOrder { 162 | // TODO: Move to ECDSA helper 163 | static dispatch_once_t onceToken; 164 | static mp_int curveOrder; 165 | dispatch_once(&onceToken, ^{ 166 | mp_init(&curveOrder); 167 | // sepc256k1 curve order as defined https://en.bitcoin.it/wiki/Secp256k1 168 | mp_read_radix( 169 | &curveOrder, 170 | "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141", 171 | 16); 172 | }); 173 | return curveOrder; 174 | } 175 | 176 | @end 177 | -------------------------------------------------------------------------------- /Breadcrumb/BreadcrumbTests/BCAddressTests.m: -------------------------------------------------------------------------------- 1 | // 2 | // BCAddressTests.m 3 | // Breadcrumb 4 | // 5 | // Created by Andrew Hurst on 2/17/15. 6 | // Copyright (c) 2015 Breadcrumb. 7 | // 8 | // Distributed under the MIT software license, see the accompanying 9 | // file LICENSE or http://www.opensource.org/licenses/mit-license.php. 10 | // 11 | 12 | #import "Breadcrumb.h" 13 | #import 14 | 15 | @interface BCAddressTests : XCTestCase 16 | 17 | @end 18 | 19 | @implementation BCAddressTests 20 | #pragma mark Test Address Parsing 21 | 22 | - (void)testAddresses { 23 | // Valid 24 | XCTAssert([[BCAddress addressWithString:@"1AGNa15ZQXAZUgFiqJ2i7Z2DPU2J6hW62i"] 25 | isKindOfClass:[BCAddress class]], 26 | @"Failed"); 27 | 28 | // Valid 29 | XCTAssert([[BCAddress addressWithString:@"1Q1pE5vPGEEMqRcVRMbtBK842Y6Pzo6nK9"] 30 | isKindOfClass:[BCAddress class]], 31 | @"Failed"); 32 | 33 | // Invalid 34 | XCTAssert( 35 | ![[BCAddress addressWithString:@"1AGNa15ZQXAZUgFiqJ2i7Z2DPU2J6hW62X"] 36 | isKindOfClass:[BCAddress class]], 37 | @"Failed"); 38 | 39 | // Invalid 40 | XCTAssert( 41 | ![[BCAddress addressWithString:@"1ANNa15ZQXAZUgFiqJ2i7Z2DPU2J6hW62i"] 42 | isKindOfClass:[BCAddress class]], 43 | @"Failed"); 44 | 45 | // Invalid 46 | XCTAssert( 47 | ![[BCAddress addressWithString:@"1A Na15ZQXAZUgFiqJ2i7Z2DPU2J6hW62i"] 48 | isKindOfClass:[BCAddress class]], 49 | @"Failed"); 50 | } 51 | 52 | #pragma mark Address From Public Key 53 | 54 | - (void)testAddressFromPublicKeyVector0 { 55 | // Test Address Generation From Pub Key 56 | XCTAssert( 57 | [[BCAddress addressFromPublicKey:@"03f5dfdb9768d46bff4c93952ed7cd9e7" 58 | @"2c944afb00de14335be0e73baf20516b" 59 | @"a".hexToData usingCoin:[BCCoin TestNet3Bitcoin]] 60 | isEqualExcludingVersion: 61 | [@"mw2LAcLNSWETLQXEQ7xs237RtkPUDrQTXR" toBitcoinAddress]], 62 | @"Failed"); 63 | } 64 | 65 | #pragma mark Address Equality 66 | 67 | - (void)testAddressEqualitySameNetwork { 68 | // Same Value 69 | XCTAssert( 70 | [[@"mw2LAcLNSWETLQXEQ7xs237RtkPUDrQTXR" toBitcoinAddress] 71 | isEqual:[@"mw2LAcLNSWETLQXEQ7xs237RtkPUDrQTXR" toBitcoinAddress]], 72 | @"Failed"); 73 | 74 | // From Diff Network 75 | XCTAssert( 76 | ![[@"mw2LAcLNSWETLQXEQ7xs237RtkPUDrQTXR" toBitcoinAddress] 77 | isEqual:[@"1GWNsZFPdUoCZJ3cgYzVC7u72knmJBhHiQ" toBitcoinAddress]], 78 | @"Failed"); 79 | } 80 | 81 | - (void)testAddressEqualityDifNetwork { 82 | // Same but from diff network 83 | XCTAssert([[@"mw2LAcLNSWETLQXEQ7xs237RtkPUDrQTXR" toBitcoinAddress] 84 | isEqualExcludingVersion: 85 | [@"1GWNsZFPdUoCZJ3cgYzVC7u72knmJBhHiQ" toBitcoinAddress]], 86 | @"Failed"); 87 | } 88 | @end 89 | -------------------------------------------------------------------------------- /Breadcrumb/BreadcrumbTests/BCEncodingTests.m: -------------------------------------------------------------------------------- 1 | // 2 | // BCEncodingTests.m 3 | // Breadcrumb 4 | // 5 | // Created by Andrew Hurst on 2/18/15. 6 | // Copyright (c) 2015 Breadcrumb. 7 | // 8 | // Distributed under the MIT software license, see the accompanying 9 | // file LICENSE or http://www.opensource.org/licenses/mit-license.php. 10 | // 11 | 12 | #import "Breadcrumb.h" 13 | #import 14 | 15 | @interface BCEncodingTests : XCTestCase 16 | 17 | @end 18 | 19 | @implementation BCEncodingTests 20 | 21 | #pragma mark Base58 22 | 23 | - (void)testBase58 { 24 | // Base58 encoding (Note Failure to encode...) 25 | XCTAssert([[@"deadBeeF".hexToData base58Encoding] isEqualToString:@"6h8cQN"], 26 | @"Encodes base58"); 27 | XCTAssert([[[@"6h8cQN" base58ToData] toHex] isEqual:@"deadbeef"], 28 | @"Decodes base58"); 29 | XCTAssert([[[[[self class] transactionOneHex] 30 | .hexToData base58Encoding] base58ToData] 31 | isEqualToData:[[self class] transactionOneHex].hexToData], 32 | @"Full Encoding Check"); 33 | XCTAssert(![@"invalid" base58ToData], @"failed"); 34 | XCTAssert(![@" \t\n\v\f\r skip \r\f\v\n\t a" base58ToData], @"failed"); 35 | 36 | // TODO: Ensure this matches bitcoind 37 | XCTAssert(![@" \t\n\v\f\r skip \r\f\v\n\t " base58ToData], @"failed"); 38 | } 39 | 40 | - (void)testBase58Check { 41 | // Base58 Check Encoding 42 | XCTAssert([[@"00c4c5d791fcb4654a1ef5e03fe0ad3d9c598f9827" 43 | .hexToData base58CheckEncoding] 44 | isEqualToString:@"1JwSSubhmg6iPtRjtyqhUYYH7bZg3Lfy1T"], 45 | @"Encodes base58 with checksum"); 46 | XCTAssert([[[@"1JwSSubhmg6iPtRjtyqhUYYH7bZg3Lfy1T" base58checkToData] toHex] 47 | isEqual:@"00c4c5d791fcb4654a1ef5e03fe0ad3d9c598f9827"], 48 | @"Decodes base58 with checksum"); 49 | XCTAssert([[[[[self class] transactionOneHex] 50 | .hexToData base58CheckEncoding] base58checkToData] 51 | isEqualToData:[[self class] transactionOneHex].hexToData], 52 | @"Full Encoding Check"); 53 | 54 | XCTAssert(![@"invalid" base58checkToData], @"failed"); 55 | } 56 | 57 | #pragma mark Data 58 | 59 | + (NSString *)transactionOneHex { 60 | return 61 | @"0100000002be6ee63b7c778f1c31c4710dbffa599b9ec8a9c0fd0e65f7f08d1077ef2f0" 62 | @"7e4000000006a473044022028758879bba44439ab8ad5be025ff9d8acc38206f626d1c" 63 | @"a4a1dbf0af343265302205bb7db56d5426bd11810ed06bf50ae2a018bc7cc8639d6dfc" 64 | @"5e7fdc9f052c13f01210387212e3733d75ddcce9121c2af5df1f06e71f63fb736df4dc" 65 | @"02dc56e9f3c4f02ffffffff97515bb7f32f28446bfe7b34b232b1e9ad1221f1d4ab462" 66 | @"4726412764b126611000000006a47304402200c3dd4af3a7e273aab864d797d18b1b05" 67 | @"a5f1980a19fd27e8a5de8d3c3ec8cdf02203718499f163104d162d67d1a095bbc9c443" 68 | @"db9d8ca03207a461aefe4e16f394301210387212e3733d75ddcce9121c2af5df1f06e7" 69 | @"1f63fb736df4dc02dc56e9f3c4f02ffffffff0228230000000000001976a914dc8ae9c" 70 | @"bf82a840cb562793cc1928bd485cc531888ac50c30000000000001976a9143696e32f2" 71 | @"e5ee974ce59b16a11387dcf05435d6a88ac00000000"; 72 | ; 73 | } 74 | 75 | @end 76 | -------------------------------------------------------------------------------- /Breadcrumb/BreadcrumbTests/BCScriptTests.m: -------------------------------------------------------------------------------- 1 | // 2 | // BCScriptTests.m 3 | // Breadcrumb 4 | // 5 | // Created by Andrew Hurst on 2/20/15. 6 | // Copyright (c) 2015 Breadcrumb. 7 | // 8 | // Distributed under the MIT software license, see the accompanying 9 | // file LICENSE or http://www.opensource.org/licenses/mit-license.php. 10 | // 11 | // 12 | 13 | #import "Breadcrumb.h" 14 | #import 15 | 16 | @interface BCScriptTests : XCTestCase 17 | 18 | @end 19 | 20 | @implementation BCScriptTests 21 | 22 | #pragma mark Default Scripts 23 | - (void)testStandardTransactionScriptGeneration { 24 | XCTAssert( 25 | [[[BCScript standardTransactionScript: 26 | [@"mufBQc5iD1T5dGdfahS7u9vhmg5kpWWXPn" toBitcoinAddress] 27 | andCoin:[BCCoin TestNet3Bitcoin]] toData] 28 | isEqualToData:@"76a9149b2008e9998794e0ef27a878f57852d2311d091c88ac" 29 | .hexToData], 30 | @"Pass"); 31 | } 32 | 33 | @end 34 | -------------------------------------------------------------------------------- /Breadcrumb/BreadcrumbTests/BCWalletGenerationTests.m: -------------------------------------------------------------------------------- 1 | // 2 | // BCWalletGenerationTests.m 3 | // Breadcrumb 4 | // 5 | // Created by Andrew Hurst on 2/18/15. 6 | // Copyright (c) 2015 Breadcrumb. 7 | // 8 | // Distributed under the MIT software license, see the accompanying 9 | // file LICENSE or http://www.opensource.org/licenses/mit-license.php. 10 | // 11 | // 12 | 13 | #import "Breadcrumb.h" 14 | #import "_BCWallet.h" 15 | #import 16 | 17 | @interface BCWalletGenerationTests : XCTestCase 18 | 19 | @end 20 | 21 | @implementation BCWalletGenerationTests 22 | 23 | #pragma mark Internal Tests 24 | 25 | - (void)testWalletCreationVector0 { 26 | BCWallet *wallet; 27 | NSData *password; 28 | password = [NSMutableData dataWithLength:32]; 29 | 30 | // Random Construction Test 31 | wallet = [[BCWallet alloc] initNewWithPassword:password 32 | andCoin:[BCCoin MainNetBitcoin]]; 33 | XCTAssert([wallet isKindOfClass:[BCWallet class]], @"Failed to construct"); 34 | } 35 | 36 | #pragma mark BIP Defined Vectors 37 | 38 | // This is a memonic test Not a wallet Generation Test 39 | 40 | // correct horse battery staple 41 | // Private Key: C4BBCB1FBEC99D65BF59D85C8CB62EE2DB963F0FE106F483D9AFA73BD4E39A8A 42 | // Address: 1JwSSubhmg6iPtRjtyqhUYYH7bZg3Lfy1T 43 | 44 | #pragma mark BitcoinJ BIP 32 Vectors (TESTNET) 45 | 46 | // Seed as words: mouse palace human birth waste brother pair fragile million 47 | // west aspect express 48 | // Seed as hex: 49 | // 4b51919e2f2be7909d5d5260e0f9a929799d93b4ab687657d1d5bcfde97be80fa2e36d6fa3fc594943e82aa5a238723be6c931fba5dd4d7395d0a8c9a46b4272 50 | // M/0H 51 | // DeterministicKey{pub=039bc63c02a83c5347e5e0a45aa1ece696bb66b3408e4048f1379fa6514169f65e, 52 | // chainCode=a9b92f438ba117eb470c423ba6965fadaf6d97607b481e4128660b6ba403ebc4, 53 | // path=M/0H} 54 | // M/0H/0 55 | // DeterministicKey{pub=03bfe172fa9be00ae96c19ca7345316fc1a2b1768bc009370a507b154550ba7040, 56 | // chainCode=90690e08539f021d9a6e196cd25d404e3b5423f48435881d0e45823317648faa, 57 | // path=M/0H/0} 58 | // M/0H/0/0 59 | // DeterministicKey{pub=02fb9b3bf3374d0e1b9573156b3c0a778b2f0979482e0fd7fa07e8af42dd55eb7c, 60 | // chainCode=156940426ae5cfc90eea3dd6c94a0b3255d99fbb7ad69435f1581011db8020b0, 61 | // path=M/0H/0/0} mvihzZu32GdpYrhVHi8CYXF2yUDaKG2ivu 62 | 63 | // NT this is not a proper test yet 64 | - (void)NTtestWalletKeyGenVector0 { 65 | // Test compatibility with BitcoinJ 66 | NSData *password; 67 | BCWallet *wallet; 68 | 69 | password = [[NSMutableData alloc] initWithLength:32]; 70 | wallet = [[BCWallet alloc] 71 | initUsingMnemonicPhrase:@"slab ski horn medal document cat minute " 72 | @"uniform worth coyote sight dragon" 73 | password:password 74 | coin:[BCCoin TestNet3Bitcoin] 75 | andCallback:NULL]; 76 | 77 | NSAssert(wallet, @"Failed"); 78 | [wallet 79 | keySequenceWithPassword:password 80 | usingCallback:^(BCKeySequence *sequence, NSData *memoryKey) { 81 | BCKeyPair *m_0h, *m_0h_0, *m_0h_0_0; 82 | // Verify the root seed matches 83 | NSAssert([[sequence.rootSeed dataUsingMemoryKey:memoryKey] 84 | isEqualToData:@"77e572c9238590d687ca29cd3c6a6b" 85 | @"f9f973a26eafadf49e24880d1c62f" 86 | @"3ec03ac7867aa2b1a0102c5bc11cc" 87 | @"dc40eea2580ab41a818fea2166b60" 88 | @"816a96c98b1".hexToData], 89 | @"Failed"); 90 | 91 | // Verify HD 92 | // M/0' 93 | m_0h = [sequence.masterKeyPair childKeyPairAt:0x80000000 94 | withMemoryKey:memoryKey]; 95 | 96 | // Chain Code 97 | NSAssert([m_0h.chainCode 98 | isEqualToData:@"e92d1221934bfe476a6311a1c4efca" 99 | @"755fcf27170dbdde60e2efb52a82a" 100 | @"1bf91".hexToData], 101 | @"Failed"); 102 | 103 | // Pub Key 104 | NSAssert([m_0h.publicKey 105 | isEqualToData:@"031c243bb8b8c1a3f31f4a68ed550e" 106 | @"80862bb314387b0c06872a95142f2" 107 | @"55e65d6".hexToData], 108 | @"Failed"); 109 | 110 | // M/0'/0 111 | m_0h_0 = [m_0h childKeyPairAt:0 withMemoryKey:memoryKey]; 112 | 113 | // Chain Code 114 | NSAssert([m_0h_0.chainCode 115 | isEqualToData:@"0ff81906965fa4957fd97958839a70" 116 | @"33dc6ddcb46ef100e0ceb3f6841d8" 117 | @"86e0a".hexToData], 118 | @"Failed"); 119 | 120 | // Pub Key 121 | NSAssert([m_0h_0.publicKey 122 | isEqualToData:@"02cefa13934831168b8d6e12e1c1e3" 123 | @"41240d3e0c9be18a8557758c98a17" 124 | @"f7d9f97".hexToData], 125 | @"Failed"); 126 | 127 | // M/0'/0/0 128 | m_0h_0_0 = 129 | [m_0h_0 childKeyPairAt:0 withMemoryKey:memoryKey]; 130 | 131 | // Chain Code 132 | NSAssert([m_0h_0_0.chainCode 133 | isEqualToData:@"f0219686103125a3993ec60d73238a" 134 | @"03fbd36ec89fe539514fedbda0766" 135 | @"c0bd5".hexToData], 136 | @"Failed"); 137 | 138 | // Pub Key 139 | NSAssert([m_0h_0_0.publicKey 140 | isEqualToData:@"033319568f40dca5ee98bfada06bd1" 141 | @"c239d62946646b854f49b055c973f" 142 | @"9e5c265".hexToData], 143 | @"Failed"); 144 | }]; 145 | } 146 | @end 147 | -------------------------------------------------------------------------------- /Breadcrumb/BreadcrumbTests/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | BC.$(PRODUCT_NAME:rfc1034identifier) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | BNDL 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | 1 23 | 24 | 25 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2015 Andrew Hurst 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | 23 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Breadcrumb 2 | 3 | [![Build Status](https://travis-ci.org/Andr3wHur5t/Breadcrumb.svg)](https://travis-ci.org/Andr3wHur5t/Breadcrumb) 4 | [![CocoaPods](https://img.shields.io/cocoapods/l/AFNetworking.svg)](https://github.com/Andr3wHur5t/Breadcrumb/blob/master/LICENSE) 5 | 6 | **Breadcrumb** takes away the complexity that you normally encounter when working with other **Bitcoin**, or **Blockchain** libraries. 7 | 8 | With minimalistic interfaces you can quickly get started working with Bitcoin, and the Blockchain. 9 | 10 | Explore the capabilities of the block chain by publishing, and building custom transactions, and scripts. 11 | 12 | Making a wallet is so easy you can start sending, and receiving Bitcoin in less than 15 lines of code. 13 | 14 | ## How to get started 15 | 16 | Include `Breadcrumb.framework`, and `CommonCrypto.framework` into your Xcode project. 17 | 18 | Add `#import ` to one of your applications' source files. 19 | 20 | Make a wallet, and start sending Bitcoin. 21 | 22 | ```Objective-C 23 | NSData *password = [@"password" dataUsingEncoding:NSUTF8StringEncoding]; 24 | BCWallet *wallet = [[BCWallet alloc] initNewWithPassword:password]; 25 | 26 | [wallet mnemonicPhraseWithPassword:password 27 | usingCallback:^(NSString *mnemonic) { 28 | NSLog(@"Brainwallet Phrase: %@",mnemonic); 29 | }]; 30 | 31 | BCAddress *address = [@"3J98t1WpEZ73CNmQviecrnyiWrnqRhWNLy" toBitcoinAddress]; 32 | NSNumber *amount = @20000; // Satoshi 33 | [wallet send:amount to:address usingPassword:password withCallback: 34 | ^(NSError *error) { 35 | if ( [error isKindOfClass:[NSError class]] ) 36 | NSLog(@"Transaction Failed: '%@'",error.localizedDescription); 37 | }]; 38 | 39 | ``` 40 | 41 | 42 | 43 | ## License 44 | Breadcrumb is under **MIT license**, and uses source from **Breadwallet** (also under MIT) 45 | 46 | 47 | The MIT License (MIT) 48 | 49 | Copyright (c) 2015 Andrew Hurst 50 | 51 | Permission is hereby granted, free of charge, to any person obtaining a copy 52 | of this software and associated documentation files (the "Software"), to deal 53 | in the Software without restriction, including without limitation the rights 54 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 55 | copies of the Software, and to permit persons to whom the Software is 56 | furnished to do so, subject to the following conditions: 57 | The above copyright notice and this permission notice shall be included in all 58 | copies or substantial portions of the Software. 59 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 60 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 61 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 62 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 63 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 64 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 65 | SOFTWARE. 66 | -------------------------------------------------------------------------------- /breadcrumb.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 9 | 10 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /libTomMath/libTomMath.xcodeproj/xcshareddata/xcschemes/libTomMath.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 29 | 35 | 36 | 37 | 38 | 39 | 44 | 45 | 47 | 53 | 54 | 55 | 56 | 57 | 63 | 64 | 65 | 66 | 75 | 76 | 82 | 83 | 84 | 85 | 86 | 87 | 93 | 94 | 100 | 101 | 102 | 103 | 105 | 106 | 109 | 110 | 111 | -------------------------------------------------------------------------------- /libTomMath/libTomMathTests/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | AH.$(PRODUCT_NAME:rfc1034identifier) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | BNDL 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | 1 23 | 24 | 25 | -------------------------------------------------------------------------------- /libTomMath/tommath_superclass.h: -------------------------------------------------------------------------------- 1 | /* super class file for PK algos */ 2 | 3 | /* default ... include all MPI */ 4 | #define LTM_ALL 5 | 6 | /* RSA only (does not support DH/DSA/ECC) */ 7 | /* #define SC_RSA_1 */ 8 | 9 | /* For reference.... On an Athlon64 optimizing for speed... 10 | 11 | LTM's mpi.o with all functions [striped] is 142KiB in size. 12 | 13 | */ 14 | 15 | /* Works for RSA only, mpi.o is 68KiB */ 16 | #ifdef SC_RSA_1 17 | #define BN_MP_SHRINK_C 18 | #define BN_MP_LCM_C 19 | #define BN_MP_PRIME_RANDOM_EX_C 20 | #define BN_MP_INVMOD_C 21 | #define BN_MP_GCD_C 22 | #define BN_MP_MOD_C 23 | #define BN_MP_MULMOD_C 24 | #define BN_MP_ADDMOD_C 25 | #define BN_MP_EXPTMOD_C 26 | #define BN_MP_SET_INT_C 27 | #define BN_MP_INIT_MULTI_C 28 | #define BN_MP_CLEAR_MULTI_C 29 | #define BN_MP_UNSIGNED_BIN_SIZE_C 30 | #define BN_MP_TO_UNSIGNED_BIN_C 31 | #define BN_MP_MOD_D_C 32 | #define BN_MP_PRIME_RABIN_MILLER_TRIALS_C 33 | #define BN_REVERSE_C 34 | #define BN_PRIME_TAB_C 35 | 36 | /* other modifiers */ 37 | #define BN_MP_DIV_SMALL /* Slower division, not critical */ 38 | 39 | /* here we are on the last pass so we turn things off. The functions classes are still there 40 | * but we remove them specifically from the build. This also invokes tweaks in functions 41 | * like removing support for even moduli, etc... 42 | */ 43 | #ifdef LTM_LAST 44 | #undef BN_MP_TOOM_MUL_C 45 | #undef BN_MP_TOOM_SQR_C 46 | #undef BN_MP_KARATSUBA_MUL_C 47 | #undef BN_MP_KARATSUBA_SQR_C 48 | #undef BN_MP_REDUCE_C 49 | #undef BN_MP_REDUCE_SETUP_C 50 | #undef BN_MP_DR_IS_MODULUS_C 51 | #undef BN_MP_DR_SETUP_C 52 | #undef BN_MP_DR_REDUCE_C 53 | #undef BN_MP_REDUCE_IS_2K_C 54 | #undef BN_MP_REDUCE_2K_SETUP_C 55 | #undef BN_MP_REDUCE_2K_C 56 | #undef BN_S_MP_EXPTMOD_C 57 | #undef BN_MP_DIV_3_C 58 | #undef BN_S_MP_MUL_HIGH_DIGS_C 59 | #undef BN_FAST_S_MP_MUL_HIGH_DIGS_C 60 | #undef BN_FAST_MP_INVMOD_C 61 | 62 | /* To safely undefine these you have to make sure your RSA key won't exceed the Comba threshold 63 | * which is roughly 255 digits [7140 bits for 32-bit machines, 15300 bits for 64-bit machines] 64 | * which means roughly speaking you can handle upto 2536-bit RSA keys with these defined without 65 | * trouble. 66 | */ 67 | #undef BN_S_MP_MUL_DIGS_C 68 | #undef BN_S_MP_SQR_C 69 | #undef BN_MP_MONTGOMERY_REDUCE_C 70 | #endif 71 | 72 | #endif 73 | 74 | /* $Source$ */ 75 | /* $Revision$ */ 76 | /* $Date$ */ 77 | -------------------------------------------------------------------------------- /libs/libsecp256k1/libsecp256k1.a: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Andr3wHur5t/Breadcrumb/dbd124f3aff887a56e4342db8ed0b4bc36cb910f/libs/libsecp256k1/libsecp256k1.a -------------------------------------------------------------------------------- /makeLibs.sh: -------------------------------------------------------------------------------- 1 | ./makeiOS.sh -n libsecp256k1.a -o "${PWD}/libs/libsecp256k1/" -i "${PWD}/secp256k1" 2 | -------------------------------------------------------------------------------- /makeUniversalFramework.sh: -------------------------------------------------------------------------------- 1 | et -e 2 | set -o pipefail 3 | 4 | #################[ Tests: helps workaround any future bugs in Xcode ]######## 5 | # 6 | DEBUG_THIS_SCRIPT="false" 7 | 8 | if [ $DEBUG_THIS_SCRIPT = "true" ] 9 | then 10 | echo "########### TESTS #############" 11 | echo "Use the following variables when debugging this script; note that they may change on recursions" 12 | echo "BUILD_DIR = $BUILD_DIR" 13 | echo "BUILD_ROOT = $BUILD_ROOT" 14 | echo "CONFIGURATION_BUILD_DIR = $CONFIGURATION_BUILD_DIR" 15 | echo "BUILT_PRODUCTS_DIR = $BUILT_PRODUCTS_DIR" 16 | echo "CONFIGURATION_TEMP_DIR = $CONFIGURATION_TEMP_DIR" 17 | echo "TARGET_BUILD_DIR = $TARGET_BUILD_DIR" 18 | fi 19 | 20 | 21 | # only do this for release 22 | if [ ${CONFIGURATION} = "Release" ] 23 | then 24 | 25 | #####################[ part 1 ]################## 26 | # First, work out the BASESDK version number (NB: Apple ought to report this, but they hide it) 27 | # (incidental: searching for substrings in sh is a nightmare! Sob) 28 | 29 | SDK_VERSION=$(echo ${SDK_NAME} | grep -o '.\{3\}$') 30 | 31 | # Next, work out if we're in SIM or DEVICE 32 | 33 | if [ ${PLATFORM_NAME} = "iphonesimulator" ] 34 | then 35 | OTHER_SDK_TO_BUILD=iphoneos${SDK_VERSION} 36 | else 37 | OTHER_SDK_TO_BUILD=iphonesimulator${SDK_VERSION} 38 | fi 39 | 40 | echo "XCode has selected SDK: ${PLATFORM_NAME} with version: ${SDK_VERSION} (although back-targetting: ${IPHONEOS_DEPLOYMENT_TARGET})" 41 | echo "...therefore, OTHER_SDK_TO_BUILD = ${OTHER_SDK_TO_BUILD}" 42 | # 43 | #####################[ end of part 1 ]################## 44 | 45 | #####################[ part 2 ]################## 46 | # 47 | # IF this is the original invocation, invoke WHATEVER other builds are required 48 | # 49 | # Xcode is already building ONE target... 50 | # 51 | # ...but this is a LIBRARY, so Apple is wrong to set it to build just one. 52 | # ...we need to build ALL targets 53 | # ...we MUST NOT re-build the target that is ALREADY being built: Xcode WILL CRASH YOUR COMPUTER if you try this (infinite recursion!) 54 | # 55 | # 56 | # So: build ONLY the missing platforms/configurations. 57 | 58 | if [ "true" == ${ALREADYINVOKED:-false} ] 59 | then 60 | 61 | echo "RECURSION: I am NOT the root invocation, so I'm NOT going to recurse" 62 | else 63 | # CRITICAL: 64 | # Prevent infinite recursion (Xcode sucks) 65 | export ALREADYINVOKED="true" 66 | 67 | echo "RECURSION: I am the root ... recursing all missing build targets NOW..." 68 | echo "RECURSION: ...about to invoke: xcodebuild -configuration \"${CONFIGURATION}\" -project \"${PROJECT_NAME}.xcodeproj\" -target \"${TARGET_NAME}\" -sdk \"${OTHER_SDK_TO_BUILD}\" ${ACTION} RUN_CLANG_STATIC_ANALYZER=NO" BUILD_DIR=\"${BUILD_DIR}\" BUILD_ROOT=\"${BUILD_ROOT}\" SYMROOT=\"${SYMROOT}\" 69 | 70 | xcodebuild -configuration "${CONFIGURATION}" -project "${PROJECT_NAME}.xcodeproj" -target "${TARGET_NAME}" -sdk "${OTHER_SDK_TO_BUILD}" ${ACTION} RUN_CLANG_STATIC_ANALYZER=NO BUILD_DIR="${BUILD_DIR}" BUILD_ROOT="${BUILD_ROOT}" SYMROOT="${SYMROOT}" 71 | 72 | ACTION="build" 73 | 74 | #Merge all platform binaries as a fat binary for each configurations. 75 | 76 | # Calculate where the (multiple) built files are coming from: 77 | CURRENTCONFIG_DEVICE_DIR=${SYMROOT}/${CONFIGURATION}-iphoneos 78 | CURRENTCONFIG_SIMULATOR_DIR=${SYMROOT}/${CONFIGURATION}-iphonesimulator 79 | 80 | echo "Taking device build from: ${CURRENTCONFIG_DEVICE_DIR}" 81 | echo "Taking simulator build from: ${CURRENTCONFIG_SIMULATOR_DIR}" 82 | 83 | CREATING_UNIVERSAL_DIR=${SYMROOT}/${CONFIGURATION}-universal 84 | echo "...I will output a universal build to: ${CREATING_UNIVERSAL_DIR}" 85 | 86 | # ... remove the products of previous runs of this script 87 | # NB: this directory is ONLY created by this script - it should be safe to delete! 88 | 89 | # Create the directory if needed 90 | if [ ! -d "${CREATING_UNIVERSAL_DIR}" ]; then 91 | mkdir "${CREATING_UNIVERSAL_DIR}" 92 | fi 93 | 94 | # Create the directory for the framework 95 | if [ -d "${CREATING_UNIVERSAL_DIR}/${EXECUTABLE_NAME}.framework" ]; then 96 | rm -rf"${CREATING_UNIVERSAL_DIR}/${EXECUTABLE_NAME}.framework" 97 | fi 98 | if [ ! -d "${CREATING_UNIVERSAL_DIR}/${EXECUTABLE_NAME}.framework" ]; then 99 | mkdir "${CREATING_UNIVERSAL_DIR}/${EXECUTABLE_NAME}.framework" 100 | fi 101 | 102 | # Copy All framewrok Files 103 | cp -R "${CURRENTCONFIG_DEVICE_DIR}/${EXECUTABLE_NAME}.framework/." "${CREATING_UNIVERSAL_DIR}/${EXECUTABLE_NAME}.framework" 104 | 105 | # Remove copied lib if any 106 | rm "${CREATING_UNIVERSAL_DIR}/${EXECUTABLE_NAME}.framework/${EXECUTABLE_NAME}" 107 | 108 | # 109 | echo "lipo: for current configuration (${CONFIGURATION}) creating output file: ${CREATING_UNIVERSAL_DIR}/${EXECUTABLE_NAME}.framework/${EXECUTABLE_NAME}" 110 | xcrun -sdk iphoneos lipo -create -output "${CREATING_UNIVERSAL_DIR}/${EXECUTABLE_NAME}.framework/${EXECUTABLE_NAME}" "${CURRENTCONFIG_DEVICE_DIR}/${EXECUTABLE_NAME}.framework/${EXECUTABLE_NAME}" "${CURRENTCONFIG_SIMULATOR_DIR}/${EXECUTABLE_NAME}.framework/${EXECUTABLE_NAME}" 111 | 112 | # Clean up our Build 113 | rm -rf "${CREATING_UNIVERSAL_DIR}/../${PROJECT}.build" 114 | 115 | fi 116 | fi 117 | -------------------------------------------------------------------------------- /test.sh: -------------------------------------------------------------------------------- 1 | gem install xcpretty --no-rdoc --no-ri --no-document --quiet 2 | set -o pipefail && xcodebuild -workspace Breadcrumb.xcworkspace -sdk iphonesimulator -scheme Breadcrumb -configuration Debug test | xcpretty -c 3 | 4 | # xctool is broken ref: https://github.com/facebook/xctool/issues/415 5 | # xctool -workspace Breadcrumb.xcworkspace -scheme Breadcrumb -sdk iphonesimulator test 6 | --------------------------------------------------------------------------------